text: (function(f, define){
      define([ "./kendo.core" ], f);
  })(function(){
  
  var __meta__ = {
      id: "fx",
      name: "Effects",
      category: "framework",
      description: "Required for animation effects in all Kendo UI widgets.",
      depends: [ "core" ]
  };
  
  (function($, undefined) {
      var kendo = window.kendo,
          fx = kendo.effects,
          each = $.each,
          extend = $.extend,
          proxy = $.proxy,
          support = kendo.support,
          browser = support.browser,
          transforms = support.transforms,
          transitions = support.transitions,
          scaleProperties = { scale: 0, scalex: 0, scaley: 0, scale3d: 0 },
          translateProperties = { translate: 0, translatex: 0, translatey: 0, translate3d: 0 },
          hasZoom = (typeof document.documentElement.style.zoom !== "undefined") && !transforms,
          matrix3dRegExp = /matrix3?d?\s*\(.*,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?/i,
          cssParamsRegExp = /^(-?[\d\.\-]+)?[\w\s]*,?\s*(-?[\d\.\-]+)?[\w\s]*/i,
          translateXRegExp = /translatex?$/i,
          oldEffectsRegExp = /(zoom|fade|expand)(\w+)/,
          singleEffectRegExp = /(zoom|fade|expand)/,
          unitRegExp = /[xy]$/i,
          transformProps = ["perspective", "rotate", "rotatex", "rotatey", "rotatez", "rotate3d", "scale", "scalex", "scaley", "scalez", "scale3d", "skew", "skewx", "skewy", "translate", "translatex", "translatey", "translatez", "translate3d", "matrix", "matrix3d"],
          transform2d = ["rotate", "scale", "scalex", "scaley", "skew", "skewx", "skewy", "translate", "translatex", "translatey", "matrix"],
          transform2units = { "rotate": "deg", scale: "", skew: "px", translate: "px" },
          cssPrefix = transforms.css,
          round = Math.round,
          BLANK = "",
          PX = "px",
          NONE = "none",
          AUTO = "auto",
          WIDTH = "width",
          HEIGHT = "height",
          HIDDEN = "hidden",
          ORIGIN = "origin",
          ABORT_ID = "abortId",
          OVERFLOW = "overflow",
          TRANSLATE = "translate",
          POSITION = "position",
          COMPLETE_CALLBACK = "completeCallback",
          TRANSITION = cssPrefix + "transition",
          TRANSFORM = cssPrefix + "transform",
          BACKFACE = cssPrefix + "backface-visibility",
          PERSPECTIVE = cssPrefix + "perspective",
          DEFAULT_PERSPECTIVE = "1500px",
          TRANSFORM_PERSPECTIVE = "perspective(" + DEFAULT_PERSPECTIVE + ")",
          ios7 = support.mobileOS && support.mobileOS.majorVersion == 7,
          directions = {
              left: {
                  reverse: "right",
                  property: "left",
                  transition: "translatex",
                  vertical: false,
                  modifier: -1
              },
              right: {
                  reverse: "left",
                  property: "left",
                  transition: "translatex",
                  vertical: false,
                  modifier: 1
              },
              down: {
                  reverse: "up",
                  property: "top",
                  transition: "translatey",
                  vertical: true,
                  modifier: 1
              },
              up: {
                  reverse: "down",
                  property: "top",
                  transition: "translatey",
                  vertical: true,
                  modifier: -1
              },
              top: {
                  reverse: "bottom"
              },
              bottom: {
                  reverse: "top"
              },
              "in": {
                  reverse: "out",
                  modifier: -1
              },
              out: {
                  reverse: "in",
                  modifier: 1
              },
  
              vertical: {
                  reverse: "vertical"
              },
  
              horizontal: {
                  reverse: "horizontal"
              }
          };
  
      kendo.directions = directions;
  
      extend($.fn, {
          kendoStop: function(clearQueue, gotoEnd) {
              if (transitions) {
                  return fx.stopQueue(this, clearQueue || false, gotoEnd || false);
              } else {
                  return this.stop(clearQueue, gotoEnd);
              }
          }
      });
  
      /* jQuery support for all transform animations (FF 3.5/3.6, Opera 10.x, IE9 */
  
      if (transforms && !transitions) {
          each(transform2d, function(idx, value) {
              $.fn[value] = function(val) {
                  if (typeof val == "undefined") {
                      return animationProperty(this, value);
                  } else {
                      var that = $(this)[0],
                          transformValue = value + "(" + val + transform2units[value.replace(unitRegExp, "")] + ")";
  
                      if (that.style.cssText.indexOf(TRANSFORM) == -1) {
                          $(this).css(TRANSFORM, transformValue);
                      } else {
                          that.style.cssText = that.style.cssText.replace(new RegExp(value + "\\(.*?\\)", "i"), transformValue);
                      }
                  }
                  return this;
              };
  
              $.fx.step[value] = function (fx) {
                  $(fx.elem)[value](fx.now);
              };
          });
  
          var curProxy = $.fx.prototype.cur;
          $.fx.prototype.cur = function () {
              if (transform2d.indexOf(this.prop) != -1) {
                  return parseFloat($(this.elem)[this.prop]());
              }
  
              return curProxy.apply(this, arguments);
          };
      }
  
      kendo.toggleClass = function(element, classes, options, add) {
          if (classes) {
              classes = classes.split(" ");
  
              if (transitions) {
                  options = extend({
                      exclusive: "all",
                      duration: 400,
                      ease: "ease-out"
                  }, options);
  
                  element.css(TRANSITION, options.exclusive + " " + options.duration + "ms " + options.ease);
                  setTimeout(function() {
                      element.css(TRANSITION, "").css(HEIGHT);
                  }, options.duration); // TODO: this should fire a kendoAnimate session instead.
              }
  
              each(classes, function(idx, value) {
                  element.toggleClass(value, add);
              });
          }
  
          return element;
      };
  
      kendo.parseEffects = function(input, mirror) {
          var effects = {};
  
          if (typeof input === "string") {
              each(input.split(" "), function(idx, value) {
                  var redirectedEffect = !singleEffectRegExp.test(value),
                      resolved = value.replace(oldEffectsRegExp, function(match, $1, $2) {
                          return $1 + ":" + $2.toLowerCase();
                      }), // Support for old zoomIn/fadeOut style, now deprecated.
                      effect = resolved.split(":"),
                      direction = effect[1],
                      effectBody = {};
  
                  if (effect.length > 1) {
                      effectBody.direction = (mirror && redirectedEffect ? directions[direction].reverse : direction);
                  }
  
                  effects[effect[0]] = effectBody;
              });
          } else {
              each(input, function(idx) {
                  var direction = this.direction;
  
                  if (direction && mirror && !singleEffectRegExp.test(idx)) {
                      this.direction = directions[direction].reverse;
                  }
  
                  effects[idx] = this;
              });
          }
  
          return effects;
      };
  
      function parseInteger(value) {
          return parseInt(value, 10);
      }
  
      function parseCSS(element, property) {
          return parseInteger(element.css(property));
      }
  
      function keys(obj) {
          var acc = [];
          for (var propertyName in obj) {
              acc.push(propertyName);
          }
          return acc;
      }
  
      function strip3DTransforms(properties) {
          for (var key in properties) {
              if (transformProps.indexOf(key) != -1 && transform2d.indexOf(key) == -1) {
                  delete properties[key];
              }
          }
  
          return properties;
      }
  
      function normalizeCSS(element, properties) {
          var transformation = [], cssValues = {}, lowerKey, key, value, isTransformed;
  
          for (key in properties) {
              lowerKey = key.toLowerCase();
              isTransformed = transforms && transformProps.indexOf(lowerKey) != -1;
  
              if (!support.hasHW3D && isTransformed && transform2d.indexOf(lowerKey) == -1) {
                  delete properties[key];
              } else {
                  value = properties[key];
  
                  if (isTransformed) {
                      transformation.push(key + "(" + value + ")");
                  } else {
                      cssValues[key] = value;
                  }
              }
          }
  
          if (transformation.length) {
              cssValues[TRANSFORM] = transformation.join(" ");
          }
  
          return cssValues;
      }
  
      if (transitions) {
          extend(fx, {
              transition: function(element, properties, options) {
                  var css,
                      delay = 0,
                      oldKeys = element.data("keys") || [],
                      timeoutID;
  
                  options = extend({
                          duration: 200,
                          ease: "ease-out",
                          complete: null,
                          exclusive: "all"
                      },
                      options
                  );
  
                  var stopTransitionCalled = false;
  
                  var stopTransition = function() {
                      if (!stopTransitionCalled) {
                          stopTransitionCalled = true;
  
                          if (timeoutID) {
                              clearTimeout(timeoutID);
                              timeoutID = null;
                          }
  
                          element
                          .removeData(ABORT_ID)
                          .dequeue()
                          .css(TRANSITION, "")
                          .css(TRANSITION);
  
                          options.complete.call(element);
                      }
                  };
  
                  options.duration = $.fx ? $.fx.speeds[options.duration] || options.duration : options.duration;
  
                  css = normalizeCSS(element, properties);
  
                  $.merge(oldKeys, keys(css));
                  element
                      .data("keys", $.unique(oldKeys))
                      .height();
  
                  element.css(TRANSITION, options.exclusive + " " + options.duration + "ms " + options.ease).css(TRANSITION);
                  element.css(css).css(TRANSFORM);
  
                  /**
                   * Use transitionEnd event for browsers who support it - but duplicate it with setTimeout, as the transitionEnd event will not be triggered if no CSS properties change.
                   * This should be cleaned up at some point (widget by widget), and refactored to widgets not relying on the complete callback if no transition occurs.
                   *
                   * For IE9 and below, resort to setTimeout.
                   */
                  if (transitions.event) {
                      element.one(transitions.event, stopTransition);
                      if (options.duration !== 0) {
                          delay = 500;
                      }
                  }
  
                  timeoutID = setTimeout(stopTransition, options.duration + delay);
                  element.data(ABORT_ID, timeoutID);
                  element.data(COMPLETE_CALLBACK, stopTransition);
              },
  
              stopQueue: function(element, clearQueue, gotoEnd) {
                  var cssValues,
                      taskKeys = element.data("keys"),
                      retainPosition = (!gotoEnd && taskKeys),
                      completeCallback = element.data(COMPLETE_CALLBACK);
  
                  if (retainPosition) {
                      cssValues = kendo.getComputedStyles(element[0], taskKeys);
                  }
  
                  if (completeCallback) {
                      completeCallback();
                  }
  
                  if (retainPosition) {
                      element.css(cssValues);
                  }
  
                  return element
                          .removeData("keys")
                          .stop(clearQueue);
              }
          });
      }
  
      function animationProperty(element, property) {
          if (transforms) {
              var transform = element.css(TRANSFORM);
              if (transform == NONE) {
                  return property == "scale" ? 1 : 0;
              }
  
              var match = transform.match(new RegExp(property + "\\s*\\(([\\d\\w\\.]+)")),
                  computed = 0;
  
              if (match) {
                  computed = parseInteger(match[1]);
              } else {
                  match = transform.match(matrix3dRegExp) || [0, 0, 0, 0, 0];
                  property = property.toLowerCase();
  
                  if (translateXRegExp.test(property)) {
                      computed = parseFloat(match[3] / match[2]);
                  } else if (property == "translatey") {
                      computed = parseFloat(match[4] / match[2]);
                  } else if (property == "scale") {
                      computed = parseFloat(match[2]);
                  } else if (property == "rotate") {
                      computed = parseFloat(Math.atan2(match[2], match[1]));
                  }
              }
  
              return computed;
          } else {
              return parseFloat(element.css(property));
          }
      }
  
      var EffectSet = kendo.Class.extend({
          init: function(element, options) {
              var that = this;
  
              that.element = element;
              that.effects = [];
              that.options = options;
              that.restore = [];
          },
  
          run: function(effects) {
              var that = this,
                  effect,
                  idx, jdx,
                  length = effects.length,
                  element = that.element,
                  options = that.options,
                  deferred = $.Deferred(),
                  start = {},
                  end = {},
                  target,
                  children,
                  childrenLength;
  
              that.effects = effects;
  
              deferred.then($.proxy(that, "complete"));
  
              element.data("animating", true);
  
              for (idx = 0; idx < length; idx ++) {
                  effect = effects[idx];
  
                  effect.setReverse(options.reverse);
                  effect.setOptions(options);
  
                  that.addRestoreProperties(effect.restore);
  
                  effect.prepare(start, end);
  
                  children = effect.children();
  
                  for (jdx = 0, childrenLength = children.length; jdx < childrenLength; jdx ++) {
                      children[jdx].duration(options.duration).run();
                  }
              }
  
              // legacy support for options.properties
              for (var effectName in options.effects) {
                  extend(end, options.effects[effectName].properties);
              }
  
              // Show the element initially
              if (!element.is(":visible")) {
                  extend(start, { display: element.data("olddisplay") || "block" });
              }
  
              if (transforms && !options.reset) {
                  target = element.data("targetTransform");
  
                  if (target) {
                      start = extend(target, start);
                  }
              }
  
              start = normalizeCSS(element, start);
  
              if (transforms && !transitions) {
                  start = strip3DTransforms(start);
              }
  
              element.css(start)
                     .css(TRANSFORM); // Nudge
  
              for (idx = 0; idx < length; idx ++) {
                  effects[idx].setup();
              }
  
              if (options.init) {
                  options.init();
              }
  
              element.data("targetTransform", end);
              fx.animate(element, end, extend({}, options, { complete: deferred.resolve }));
  
              return deferred.promise();
          },
  
          stop: function() {
              $(this.element).kendoStop(true, true);
          },
  
          addRestoreProperties: function(restore) {
              var element = this.element,
                  value,
                  i = 0,
                  length = restore.length;
  
              for (; i < length; i ++) {
                  value = restore[i];
  
                  this.restore.push(value);
  
                  if (!element.data(value)) {
                      element.data(value, element.css(value));
                  }
              }
          },
  
          restoreCallback: function() {
              var element = this.element;
  
              for (var i = 0, length = this.restore.length; i < length; i ++) {
                  var value = this.restore[i];
                  element.css(value, element.data(value));
              }
          },
  
          complete: function() {
              var that = this,
                  idx = 0,
                  element = that.element,
                  options = that.options,
                  effects = that.effects,
                  length = effects.length;
  
              element
                  .removeData("animating")
                  .dequeue(); // call next animation from the queue
  
              if (options.hide) {
                  element.data("olddisplay", element.css("display")).hide();
              }
  
              this.restoreCallback();
  
              if (hasZoom && !transforms) {
                  setTimeout($.proxy(this, "restoreCallback"), 0); // Again jQuery callback in IE8-
              }
  
              for (; idx < length; idx ++) {
                  effects[idx].teardown();
              }
  
              if (options.completeCallback) {
                  options.completeCallback(element);
              }
          }
      });
  
      fx.promise = function(element, options) {
          var effects = [],
              effectClass,
              effectSet = new EffectSet(element, options),
              parsedEffects = kendo.parseEffects(options.effects),
              effect;
  
          options.effects = parsedEffects;
  
          for (var effectName in parsedEffects) {
              effectClass = fx[capitalize(effectName)];
  
              if (effectClass) {
                  effect = new effectClass(element, parsedEffects[effectName].direction);
                  effects.push(effect);
             }
          }
  
          if (effects[0]) {
              effectSet.run(effects);
          } else { // Not sure how would an fx promise reach this state - means that you call kendoAnimate with no valid effects? Why?
              if (!element.is(":visible")) {
                  element.css({ display: element.data("olddisplay") || "block" }).css("display");
              }
  
              if (options.init) {
                  options.init();
              }
  
              element.dequeue();
              effectSet.complete();
          }
      };
  
      extend(fx, {
          animate: function(elements, properties, options) {
              var useTransition = options.transition !== false;
              delete options.transition;
  
              if (transitions && "transition" in fx && useTransition) {
                  fx.transition(elements, properties, options);
              } else {
                  if (transforms) {
                      elements.animate(strip3DTransforms(properties), { queue: false, show: false, hide: false, duration: options.duration, complete: options.complete }); // Stop animate from showing/hiding the element to be able to hide it later on.
                  } else {
                      elements.each(function() {
                          var element = $(this),
                              multiple = {};
  
                          each(transformProps, function(idx, value) { // remove transforms to avoid IE and older browsers confusion
                              var params,
                                  currentValue = properties ? properties[value]+ " " : null; // We need to match
  
                              if (currentValue) {
                                  var single = properties;
  
                                  if (value in scaleProperties && properties[value] !== undefined) {
                                      params = currentValue.match(cssParamsRegExp);
                                      if (transforms) {
                                          extend(single, { scale: +params[0] });
                                      }
                                  } else {
                                      if (value in translateProperties && properties[value] !== undefined) {
                                          var position = element.css(POSITION),
                                              isFixed = (position == "absolute" || position == "fixed");
  
                                          if (!element.data(TRANSLATE)) {
                                              if (isFixed) {
                                                  element.data(TRANSLATE, {
                                                      top: parseCSS(element, "top") || 0,
                                                      left: parseCSS(element, "left") || 0,
                                                      bottom: parseCSS(element, "bottom"),
                                                      right: parseCSS(element, "right")
                                                  });
                                              } else {
                                                  element.data(TRANSLATE, {
                                                      top: parseCSS(element, "marginTop") || 0,
                                                      left: parseCSS(element, "marginLeft") || 0
                                                  });
                                              }
                                          }
  
                                          var originalPosition = element.data(TRANSLATE);
  
                                          params = currentValue.match(cssParamsRegExp);
                                          if (params) {
  
                                              var dX = value == TRANSLATE + "y" ? +null : +params[1],
                                                  dY = value == TRANSLATE + "y" ? +params[1] : +params[2];
  
                                              if (isFixed) {
                                                  if (!isNaN(originalPosition.right)) {
                                                      if (!isNaN(dX)) { extend(single, { right: originalPosition.right - dX }); }
                                                  } else {
                                                      if (!isNaN(dX)) { extend(single, { left: originalPosition.left + dX }); }
                                                  }
  
                                                  if (!isNaN(originalPosition.bottom)) {
                                                      if (!isNaN(dY)) { extend(single, { bottom: originalPosition.bottom - dY }); }
                                                  } else {
                                                      if (!isNaN(dY)) { extend(single, { top: originalPosition.top + dY }); }
                                                  }
                                              } else {
                                                  if (!isNaN(dX)) { extend(single, { marginLeft: originalPosition.left + dX }); }
                                                  if (!isNaN(dY)) { extend(single, { marginTop: originalPosition.top + dY }); }
                                              }
                                          }
                                      }
                                  }
  
                                  if (!transforms && value != "scale" && value in single) {
                                      delete single[value];
                                  }
  
                                  if (single) {
                                      extend(multiple, single);
                                  }
                              }
                          });
  
                          if (browser.msie) {
                              delete multiple.scale;
                          }
  
                          element.animate(multiple, { queue: false, show: false, hide: false, duration: options.duration, complete: options.complete }); // Stop animate from showing/hiding the element to be able to hide it later on.
                      });
                  }
              }
          }
      });
  
      fx.animatedPromise = fx.promise;
  
      var Effect = kendo.Class.extend({
          init: function(element, direction) {
              var that = this;
              that.element = element;
              that._direction = direction;
              that.options = {};
              that._additionalEffects = [];
  
              if (!that.restore) {
                  that.restore = [];
              }
          },
  
  // Public API
          reverse: function() {
              this._reverse = true;
              return this.run();
          },
  
          play: function() {
              this._reverse = false;
              return this.run();
          },
  
          add: function(additional) {
              this._additionalEffects.push(additional);
              return this;
          },
  
          direction: function(value) {
              this._direction = value;
              return this;
          },
  
          duration: function(duration) {
              this._duration = duration;
              return this;
          },
  
          compositeRun: function() {
              var that = this,
                  effectSet = new EffectSet(that.element, { reverse: that._reverse, duration: that._duration }),
                  effects = that._additionalEffects.concat([ that ]);
  
              return effectSet.run(effects);
          },
  
          run: function() {
              if (this._additionalEffects && this._additionalEffects[0]) {
                  return this.compositeRun();
              }
  
              var that = this,
                  element = that.element,
                  idx = 0,
                  restore = that.restore,
                  length = restore.length,
                  value,
                  deferred = $.Deferred(),
                  start = {},
                  end = {},
                  target,
                  children = that.children(),
                  childrenLength = children.length;
  
              deferred.then($.proxy(that, "_complete"));
  
              element.data("animating", true);
  
              for (idx = 0; idx < length; idx ++) {
                  value = restore[idx];
  
                  if (!element.data(value)) {
                      element.data(value, element.css(value));
                  }
              }
  
              for (idx = 0; idx < childrenLength; idx ++) {
                  children[idx].duration(that._duration).run();
              }
  
              that.prepare(start, end);
  
              if (!element.is(":visible")) {
                  extend(start, { display: element.data("olddisplay") || "block" });
              }
  
              if (transforms) {
                  target = element.data("targetTransform");
  
                  if (target) {
                      start = extend(target, start);
                  }
              }
  
              start = normalizeCSS(element, start);
  
              if (transforms && !transitions) {
                  start = strip3DTransforms(start);
              }
  
              element.css(start).css(TRANSFORM); // Trick webkit into re-rendering
  
              that.setup();
  
              element.data("targetTransform", end);
              fx.animate(element, end, { duration: that._duration, complete: deferred.resolve });
  
              return deferred.promise();
          },
  
          stop: function() {
              var idx = 0,
                  children = this.children(),
                  childrenLength = children.length;
  
              for (idx = 0; idx < childrenLength; idx ++) {
                  children[idx].stop();
              }
  
              $(this.element).kendoStop(true, true);
              return this;
          },
  
          restoreCallback: function() {
              var element = this.element;
  
              for (var i = 0, length = this.restore.length; i < length; i ++) {
                  var value = this.restore[i];
                  element.css(value, element.data(value));
              }
          },
  
          _complete: function() {
              var that = this,
                  element = that.element;
  
              element
                  .removeData("animating")
                  .dequeue(); // call next animation from the queue
  
              that.restoreCallback();
  
              if (that.shouldHide()) {
                  element.data("olddisplay", element.css("display")).hide();
              }
  
              if (hasZoom && !transforms) {
                  setTimeout($.proxy(that, "restoreCallback"), 0); // Again jQuery callback in IE8-
              }
  
              that.teardown();
          },
  
          /////////////////////////// Support for kendo.animate;
          setOptions: function(options) {
              extend(true, this.options, options);
          },
  
          children: function() {
              return [];
          },
  
          shouldHide: $.noop,
  
          setup: $.noop,
          prepare: $.noop,
          teardown: $.noop,
          directions: [],
  
          setReverse: function(reverse) {
              this._reverse = reverse;
              return this;
          }
      });
  
      function capitalize(word) {
          return word.charAt(0).toUpperCase() + word.substring(1);
      }
  
      function createEffect(name, definition) {
          var effectClass = Effect.extend(definition),
              directions = effectClass.prototype.directions;
  
          fx[capitalize(name)] = effectClass;
  
          fx.Element.prototype[name] = function(direction, opt1, opt2, opt3) {
              return new effectClass(this.element, direction, opt1, opt2, opt3);
          };
  
          each(directions, function(idx, theDirection) {
              fx.Element.prototype[name + capitalize(theDirection)] = function(opt1, opt2, opt3) {
                  return new effectClass(this.element, theDirection, opt1, opt2, opt3);
              };
          });
      }
  
      var FOUR_DIRECTIONS = ["left", "right", "up", "down"],
          IN_OUT = ["in", "out"];
  
      createEffect("slideIn", {
          directions: FOUR_DIRECTIONS,
  
          divisor: function(value) {
              this.options.divisor = value;
              return this;
          },
  
          prepare: function(start, end) {
              var that = this,
                  tmp,
                  element = that.element,
                  direction = directions[that._direction],
                  offset = -direction.modifier * (direction.vertical ? element.outerHeight() : element.outerWidth()),
                  startValue = offset / (that.options && that.options.divisor || 1) + PX,
                  endValue = "0px";
  
              if (that._reverse) {
                  tmp = start;
                  start = end;
                  end = tmp;
              }
  
              if (transforms) {
                  start[direction.transition] = startValue;
                  end[direction.transition] = endValue;
              } else {
                  start[direction.property] = startValue;
                  end[direction.property] = endValue;
              }
          }
      });
  
      createEffect("tile", {
          directions: FOUR_DIRECTIONS,
  
          init: function(element, direction, previous) {
              Effect.prototype.init.call(this, element, direction);
              this.options = { previous: previous };
          },
  
          previousDivisor: function(value) {
              this.options.previousDivisor = value;
              return this;
          },
  
          children: function() {
              var that = this,
                  reverse = that._reverse,
                  previous = that.options.previous,
                  divisor = that.options.previousDivisor || 1,
                  dir = that._direction;
  
              var children = [ kendo.fx(that.element).slideIn(dir).setReverse(reverse) ];
  
              if (previous) {
                  children.push( kendo.fx(previous).slideIn(directions[dir].reverse).divisor(divisor).setReverse(!reverse) );
              }
  
              return children;
          }
      });
  
      function createToggleEffect(name, property, defaultStart, defaultEnd) {
          createEffect(name, {
              directions: IN_OUT,
  
              startValue: function(value) {
                  this._startValue = value;
                  return this;
              },
  
              endValue: function(value) {
                  this._endValue = value;
                  return this;
              },
  
              shouldHide: function() {
                 return this._shouldHide;
              },
  
              prepare: function(start, end) {
                  var that = this,
                      startValue,
                      endValue,
                      out = this._direction === "out",
                      startDataValue = that.element.data(property),
                      startDataValueIsSet = !(isNaN(startDataValue) || startDataValue == defaultStart);
  
                  if (startDataValueIsSet) {
                      startValue = startDataValue;
                  } else if (typeof this._startValue !== "undefined") {
                      startValue = this._startValue;
                  } else {
                      startValue = out ? defaultStart : defaultEnd;
                  }
  
                  if (typeof this._endValue !== "undefined") {
                      endValue = this._endValue;
                  } else {
                      endValue = out ? defaultEnd : defaultStart;
                  }
  
                  if (this._reverse) {
                      start[property] = endValue;
                      end[property] = startValue;
                  } else {
                      start[property] = startValue;
                      end[property] = endValue;
                  }
  
                  that._shouldHide = end[property] === defaultEnd;
              }
          });
      }
  
      createToggleEffect("fade", "opacity", 1, 0);
      createToggleEffect("zoom", "scale", 1, 0.01);
  
      createEffect("slideMargin", {
          prepare: function(start, end) {
              var that = this,
                  element = that.element,
                  options = that.options,
                  origin = element.data(ORIGIN),
                  offset = options.offset,
                  margin,
                  reverse = that._reverse;
  
              if (!reverse && origin === null) {
                  element.data(ORIGIN, parseFloat(element.css("margin-" + options.axis)));
              }
  
              margin = (element.data(ORIGIN) || 0);
              end["margin-" + options.axis] = !reverse ? margin + offset : margin;
          }
      });
  
      createEffect("slideTo", {
          prepare: function(start, end) {
              var that = this,
                  element = that.element,
                  options = that.options,
                  offset = options.offset.split(","),
                  reverse = that._reverse;
  
              if (transforms) {
                  end.translatex = !reverse ? offset[0] : 0;
                  end.translatey = !reverse ? offset[1] : 0;
              } else {
                  end.left = !reverse ? offset[0] : 0;
                  end.top = !reverse ? offset[1] : 0;
              }
              element.css("left");
          }
      });
  
      createEffect("expand", {
          directions: ["horizontal", "vertical"],
  
          restore: [ OVERFLOW ],
  
          prepare: function(start, end) {
              var that = this,
                  element = that.element,
                  options = that.options,
                  reverse = that._reverse,
                  property = that._direction === "vertical" ? HEIGHT : WIDTH,
                  setLength = element[0].style[property],
                  oldLength = element.data(property),
                  length = parseFloat(oldLength || setLength),
                  realLength = round(element.css(property, AUTO)[property]());
  
              start.overflow = HIDDEN;
  
              length = (options && options.reset) ? realLength || length : length || realLength;
  
              end[property] = (reverse ? 0 : length) + PX;
              start[property] = (reverse ? length : 0) + PX;
  
              if (oldLength === undefined) {
                  element.data(property, setLength);
              }
          },
  
          shouldHide: function() {
             return this._reverse;
          },
  
          teardown: function() {
              var that = this,
                  element = that.element,
                  property = that._direction === "vertical" ? HEIGHT : WIDTH,
                  length = element.data(property);
  
              if (length == AUTO || length === BLANK) {
                  setTimeout(function() { element.css(property, AUTO).css(property); }, 0); // jQuery animate complete callback in IE is called before the last animation step!
              }
          }
      });
  
      var TRANSFER_START_STATE = { position: "absolute", marginLeft: 0, marginTop: 0, scale: 1 };
      /**
       * Intersection point formulas are taken from here - http://zonalandeducation.com/mmts/intersections/intersectionOfTwoLines1/intersectionOfTwoLines1.html
       * Formula for a linear function from two points from here - http://demo.activemath.org/ActiveMath2/search/show.cmd?id=mbase://AC_UK_calculus/functions/ex_linear_equation_two_points
       * The transform origin point is the intersection point of the two lines from the top left corners/top right corners of the element and target.
       * The math and variables below MAY BE SIMPLIFIED (zeroes removed), but this would make the formula too cryptic.
       */
      createEffect("transfer", {
          init: function(element, target) {
              this.element = element;
              this.options = { target: target };
              this.restore = [];
          },
  
          setup: function() {
              this.element.appendTo(document.body);
          },
  
          prepare: function(start, end) {
              var that = this,
                  element = that.element,
                  outerBox = fx.box(element),
                  innerBox = fx.box(that.options.target),
                  currentScale = animationProperty(element, "scale"),
                  scale = fx.fillScale(innerBox, outerBox),
                  transformOrigin = fx.transformOrigin(innerBox, outerBox);
  
              extend(start, TRANSFER_START_STATE);
              end.scale = 1;
  
              element.css(TRANSFORM, "scale(1)").css(TRANSFORM);
              element.css(TRANSFORM, "scale(" + currentScale + ")");
  
              start.top = outerBox.top;
              start.left = outerBox.left;
              start.transformOrigin = transformOrigin.x + PX + " " + transformOrigin.y + PX;
  
              if (that._reverse) {
                  start.scale = scale;
              } else {
                  end.scale = scale;
              }
          }
      });
  
  
      var CLIPS = {
          top: "rect(auto auto $size auto)",
          bottom: "rect($size auto auto auto)",
          left: "rect(auto $size auto auto)",
          right: "rect(auto auto auto $size)"
      };
  
      var ROTATIONS = {
          top:    { start: "rotatex(0deg)", end: "rotatex(180deg)" },
          bottom: { start: "rotatex(-180deg)", end: "rotatex(0deg)" },
          left:   { start: "rotatey(0deg)", end: "rotatey(-180deg)" },
          right:  { start: "rotatey(180deg)", end: "rotatey(0deg)" }
      };
  
      function clipInHalf(container, direction) {
          var vertical = kendo.directions[direction].vertical,
              size = (container[vertical ? HEIGHT : WIDTH]() / 2) + "px";
  
          return CLIPS[direction].replace("$size", size);
      }
  
      createEffect("turningPage", {
          directions: FOUR_DIRECTIONS,
  
          init: function(element, direction, container) {
              Effect.prototype.init.call(this, element, direction);
              this._container = container;
          },
  
          prepare: function(start, end) {
              var that = this,
                  reverse = that._reverse,
                  direction = reverse ? directions[that._direction].reverse : that._direction,
                  rotation = ROTATIONS[direction];
  
              start.zIndex = 1;
  
              if (that._clipInHalf) {
                 start.clip = clipInHalf(that._container, kendo.directions[direction].reverse);
              }
  
              start[BACKFACE] = HIDDEN;
  
              end[TRANSFORM] = TRANSFORM_PERSPECTIVE + (reverse ? rotation.start : rotation.end);
              start[TRANSFORM] = TRANSFORM_PERSPECTIVE + (reverse ? rotation.end : rotation.start);
          },
  
          setup: function() {
              this._container.append(this.element);
          },
  
          face: function(value) {
              this._face = value;
              return this;
          },
  
          shouldHide: function() {
              var that = this,
                  reverse = that._reverse,
                  face = that._face;
  
              return (reverse && !face) || (!reverse && face);
          },
  
          clipInHalf: function(value) {
              this._clipInHalf = value;
              return this;
          },
  
          temporary: function() {
              this.element.addClass('temp-page');
              return this;
          }
      });
  
      createEffect("staticPage", {
          directions: FOUR_DIRECTIONS,
  
          init: function(element, direction, container) {
              Effect.prototype.init.call(this, element, direction);
              this._container = container;
          },
  
          restore: ["clip"],
  
          prepare: function(start, end) {
              var that = this,
                  direction = that._reverse ? directions[that._direction].reverse : that._direction;
  
              start.clip = clipInHalf(that._container, direction);
              start.opacity = 0.999;
              end.opacity = 1;
          },
  
          shouldHide: function() {
              var that = this,
                  reverse = that._reverse,
                  face = that._face;
  
              return (reverse && !face) || (!reverse && face);
          },
  
          face: function(value) {
              this._face = value;
              return this;
          }
      });
  
      createEffect("pageturn", {
          directions: ["horizontal", "vertical"],
  
          init: function(element, direction, face, back) {
              Effect.prototype.init.call(this, element, direction);
              this.options = {};
              this.options.face = face;
              this.options.back = back;
          },
  
          children: function() {
              var that = this,
                  options = that.options,
                  direction = that._direction === "horizontal" ? "left" : "top",
                  reverseDirection = kendo.directions[direction].reverse,
                  reverse = that._reverse,
                  temp,
                  faceClone = options.face.clone(true).removeAttr("id"),
                  backClone = options.back.clone(true).removeAttr("id"),
                  element = that.element;
  
              if (reverse) {
                  temp = direction;
                  direction = reverseDirection;
                  reverseDirection = temp;
              }
  
              return [
                  kendo.fx(options.face).staticPage(direction, element).face(true).setReverse(reverse),
                  kendo.fx(options.back).staticPage(reverseDirection, element).setReverse(reverse),
                  kendo.fx(faceClone).turningPage(direction, element).face(true).clipInHalf(true).temporary().setReverse(reverse),
                  kendo.fx(backClone).turningPage(reverseDirection, element).clipInHalf(true).temporary().setReverse(reverse)
              ];
          },
  
          prepare: function(start, end) {
              start[PERSPECTIVE] = DEFAULT_PERSPECTIVE;
              start.transformStyle = "preserve-3d";
              // hack to trigger transition end.
              start.opacity = 0.999;
              end.opacity = 1;
          },
  
          teardown: function() {
              this.element.find(".temp-page").remove();
          }
      });
  
      createEffect("flip", {
          directions: ["horizontal", "vertical"],
  
          init: function(element, direction, face, back) {
              Effect.prototype.init.call(this, element, direction);
              this.options = {};
              this.options.face = face;
              this.options.back = back;
          },
  
          children: function() {
              var that = this,
                  options = that.options,
                  direction = that._direction === "horizontal" ? "left" : "top",
                  reverseDirection = kendo.directions[direction].reverse,
                  reverse = that._reverse,
                  temp,
                  element = that.element;
  
              if (reverse) {
                  temp = direction;
                  direction = reverseDirection;
                  reverseDirection = temp;
              }
  
              return [
                  kendo.fx(options.face).turningPage(direction, element).face(true).setReverse(reverse),
                  kendo.fx(options.back).turningPage(reverseDirection, element).setReverse(reverse)
              ];
          },
  
          prepare: function(start) {
              start[PERSPECTIVE] = DEFAULT_PERSPECTIVE;
              start.transformStyle = "preserve-3d";
          }
      });
  
      var RESTORE_OVERFLOW = !support.mobileOS.android;
      var IGNORE_TRANSITION_EVENT_SELECTOR = ".km-touch-scrollbar";
  
      createEffect("replace", {
          _before: $.noop,
          _after: $.noop,
          init: function(element, previous, transitionClass) {
              Effect.prototype.init.call(this, element);
              this._previous = $(previous);
              this._transitionClass = transitionClass;
          },
  
          duration: function() {
              throw new Error("The replace effect does not support duration setting; the effect duration may be customized through the transition class rule");
          },
  
          beforeTransition: function(callback) {
              this._before = callback;
              return this;
          },
  
          afterTransition: function(callback) {
              this._after = callback;
              return this;
          },
  
          _both: function() {
              return $().add(this._element).add(this._previous);
          },
  
          _containerClass: function() {
              var direction = this._direction,
                  containerClass = "k-fx k-fx-start k-fx-" + this._transitionClass;
  
              if (direction) {
                  containerClass += " k-fx-" + direction;
              }
  
              if (this._reverse) {
                  containerClass += " k-fx-reverse";
              }
  
              return containerClass;
          },
  
          complete: function(e) {
              if (!this.deferred || (e && $(e.target).is(IGNORE_TRANSITION_EVENT_SELECTOR))) {
                  return;
              }
  
              var container = this.container;
  
              container
                  .removeClass("k-fx-end")
                  .removeClass(this._containerClass())
                  .off(transitions.event, this.completeProxy);
  
              this._previous.hide().removeClass("k-fx-current");
              this.element.removeClass("k-fx-next");
  
              if (RESTORE_OVERFLOW) {
                  container.css(OVERFLOW, "");
              }
  
              if (!this.isAbsolute) {
                  this._both().css(POSITION, "");
              }
  
              this.deferred.resolve();
              delete this.deferred;
          },
  
          run: function() {
              if (this._additionalEffects && this._additionalEffects[0]) {
                  return this.compositeRun();
              }
  
              var that = this,
                  element = that.element,
                  previous = that._previous,
                  container = element.parents().filter(previous.parents()).first(),
                  both = that._both(),
                  deferred = $.Deferred(),
                  originalPosition = element.css(POSITION),
                  originalOverflow;
  
              // edge case for grid/scheduler, where the previous is already destroyed.
              if (!container.length) {
                  container = element.parent();
              }
  
              this.container = container;
              this.deferred = deferred;
              this.isAbsolute = originalPosition  == "absolute";
  
              if (!this.isAbsolute) {
                  both.css(POSITION, "absolute");
              }
  
              if (RESTORE_OVERFLOW) {
                  originalOverflow = container.css(OVERFLOW);
                  container.css(OVERFLOW, "hidden");
              }
  
              if (!transitions) {
                  this.complete();
              } else {
                  element.addClass("k-fx-hidden");
  
                  container.addClass(this._containerClass());
  
                  this.completeProxy = $.proxy(this, "complete");
                  container.on(transitions.event, this.completeProxy);
  
                  kendo.animationFrame(function() {
                      element.removeClass("k-fx-hidden").addClass("k-fx-next");
                      previous.css("display", "").addClass("k-fx-current");
                      that._before(previous, element);
                      kendo.animationFrame(function() {
                          container.removeClass("k-fx-start").addClass("k-fx-end");
                          that._after(previous, element);
                      });
                  });
              }
  
              return deferred.promise();
          },
  
          stop: function() {
              this.complete();
          }
      });
  
      var Animation = kendo.Class.extend({
          init: function() {
              var that = this;
              that._tickProxy = proxy(that._tick, that);
              that._started = false;
          },
  
          tick: $.noop,
          done: $.noop,
          onEnd: $.noop,
          onCancel: $.noop,
  
          start: function() {
              if (!this.enabled()) {
                  return;
              }
  
              if (!this.done()) {
                  this._started = true;
                  kendo.animationFrame(this._tickProxy);
              } else {
                  this.onEnd();
              }
          },
  
          enabled: function() {
              return true;
          },
  
          cancel: function() {
              this._started = false;
              this.onCancel();
          },
  
          _tick: function() {
              var that = this;
              if (!that._started) { return; }
  
              that.tick();
  
              if (!that.done()) {
                  kendo.animationFrame(that._tickProxy);
              } else {
                  that._started = false;
                  that.onEnd();
              }
          }
      });
  
      var Transition = Animation.extend({
          init: function(options) {
              var that = this;
              extend(that, options);
              Animation.fn.init.call(that);
          },
  
          done: function() {
              return this.timePassed() >= this.duration;
          },
  
          timePassed: function() {
              return Math.min(this.duration, (new Date()) - this.startDate);
          },
  
          moveTo: function(options) {
              var that = this,
                  movable = that.movable;
  
              that.initial = movable[that.axis];
              that.delta = options.location - that.initial;
  
              that.duration = typeof options.duration == "number" ? options.duration : 300;
  
              that.tick = that._easeProxy(options.ease);
  
              that.startDate = new Date();
              that.start();
          },
  
          _easeProxy: function(ease) {
              var that = this;
  
              return function() {
                  that.movable.moveAxis(that.axis, ease(that.timePassed(), that.initial, that.delta, that.duration));
              };
          }
      });
  
      extend(Transition, {
          easeOutExpo: function (t, b, c, d) {
              return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
          },
  
          easeOutBack: function (t, b, c, d, s) {
              s = 1.70158;
              return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
          }
      });
  
      fx.Animation = Animation;
      fx.Transition = Transition;
      fx.createEffect = createEffect;
  
      fx.box = function(element) {
          element = $(element);
          var result = element.offset();
          result.width = element.outerWidth();
          result.height = element.outerHeight();
          return result;
      };
  
      fx.transformOrigin = function(inner, outer) {
          var x = (inner.left - outer.left) * outer.width / (outer.width - inner.width),
              y = (inner.top - outer.top) * outer.height / (outer.height - inner.height);
  
          return {
              x: isNaN(x) ? 0 : x,
              y: isNaN(y) ? 0 : y
          };
      };
  
      fx.fillScale = function(inner, outer) {
          return Math.min(inner.width / outer.width, inner.height / outer.height);
      };
  
      fx.fitScale = function(inner, outer) {
          return Math.max(inner.width / outer.width, inner.height / outer.height);
      };
  })(window.kendo.jQuery);
  
  return window.kendo;
  
  }, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });
  