Jump To …

jquerypp.js

(function (window, $, undefined) {

jquery/dom/styles/styles.js

  var getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,

The following variables are used to convert camelcased attribute names into dashed names, e.g. borderWidth to border-width

    rupper = /([A-Z])/g,
    rdashAlpha = /-([a-z])/ig,
    fcamelCase = function (all, letter) {
      return letter.toUpperCase();
    },

Returns the computed style for an elementn

    getStyle = function (elem) {
      if (getComputedStyle) {
        return getComputedStyle(elem, null);
      }
      else if (elem.currentStyle) {
        return elem.currentStyle;
      }
    },

Checks for float px and numeric values

    rfloat = /float/i,
    rnumpx = /^-?\d+(?:px)?$/i,
    rnum = /^-?\d/;

Returns a list of styles for a given element

  $.styles = function (el, styles) {
    if (!el) {
      return null;
    }
    var currentS = getStyle(el),
      oldName, val, style = el.style,
      results = {},
      i = 0,
      left, rsLeft, camelCase, name;

Go through each style

    for (; i < styles.length; i++) {
      name = styles[i];
      oldName = name.replace(rdashAlpha, fcamelCase);

      if (rfloat.test(name)) {
        name = $.support.cssFloat ? "float" : "styleFloat";
        oldName = "cssFloat";
      }

If we have getComputedStyle available

      if (getComputedStyle) {

convert camelcased property names to dashed name

        name = name.replace(rupper, "-$1").toLowerCase();

use getPropertyValue of the current style object

        val = currentS.getPropertyValue(name);

default opacity is 1

        if (name === "opacity" && val === "") {
          val = "1";
        }
        results[oldName] = val;
      } else {

Without getComputedStyles

        camelCase = name.replace(rdashAlpha, fcamelCase);
        results[oldName] = currentS[name] || currentS[camelCase];

convert to px

        if (!rnumpx.test(results[oldName]) && rnum.test(results[oldName])) {

Remember the original values

          left = style.left;
          rsLeft = el.runtimeStyle.left;

Put in the new values to get a computed value out

          el.runtimeStyle.left = el.currentStyle.left;
          style.left = camelCase === "fontSize" ? "1em" : (results[oldName] || 0);
          results[oldName] = style.pixelLeft + "px";

Revert the changed values

          style.left = left;
          el.runtimeStyle.left = rsLeft;
        }

      }
    }

    return results;
  };


  $.fn.styles = function () {

Pass the arguments as an array to $.styles

    return $.styles(this[0], $.makeArray(arguments));
  };

jquery/dom/animate/animate.js

Overwrites jQuery.fn.animate to use CSS 3 animations if possible

  var

The global animation counter

  animationNum = 0,

The stylesheet for our animations

    styleSheet = null,

The animation cache

    cache = [],

Stores the browser properties like transition end event name and prefix

    browser = null,

Store the original $.fn.animate

    oldanimate = $.fn.animate,

Return the stylesheet, create it if it doesn't exists

    getStyleSheet = function () {
      if (!styleSheet) {
        var style = document.createElement('style');
        style.setAttribute("type", "text/css");
        style.setAttribute("media", "screen");

        document.getElementsByTagName('head')[0].appendChild(style);
        if (!window.createPopup) {
          style.appendChild(document.createTextNode(''));
        }

        styleSheet = style.sheet;
      }

      return styleSheet;
    },

removes an animation rule from a sheet

    removeAnimation = function (sheet, name) {
      for (var j = sheet.cssRules.length - 1; j >= 0; j--) {
        var rule = sheet.cssRules[j];

7 means the keyframe rule

        if (rule.type === 7 && rule.name == name) {
          sheet.deleteRule(j)
          return;
        }
      }
    },

Returns whether the animation should be passed to the original $.fn.animate.

    passThrough = function (props, ops) {
      var nonElement = !(this[0] && this[0].nodeType),
        isInline = !nonElement && $(this).css("display") === "inline" && $(this).css("float") === "none";

      for (var name in props) {

jQuery does something with these values

        if (props[name] == 'show' || props[name] == 'hide' || props[name] == 'toggle'

Arrays for individual easing

        || $.isArray(props[name])

Negative values not handled the same

        || props[name] < 0

unit-less value

        || name == 'zIndex' || name == 'z-index' || name == 'scrollTop' || name == 'scrollLeft') {
          return true;
        }
      }

      return props.jquery === true || getBrowser() === null ||

Animating empty properties

      $.isEmptyObject(props) ||

We can't do custom easing

      (ops && ops.length == 4) || (ops && typeof ops[2] == 'string') ||

Second parameter is an object - we can only handle primitives

      $.isPlainObject(ops) ||

Inline and non elements

      isInline || nonElement;
    },

Gets a CSS number (with px added as the default unit if the value is a number)

    cssValue = function (origName, value) {
      if (typeof value === "number" && !$.cssNumber[origName]) {
        return value += "px";
      }
      return value;
    },

Feature detection borrowed by http://modernizr.com/

    getBrowser = function () {
      if (!browser) {
        var t, el = document.createElement('fakeelement'),
          transitions = {
            'transition': {
              transitionEnd: 'transitionEnd',
              prefix: ''
            },
                'OTransition': {
                    transitionEnd : 'oTransitionEnd',
                    prefix : '-o-'
                },
                'MSTransition': {
                    transitionEnd : 'msTransitionEnd',
                    prefix : '-ms-'
                },
            'MozTransition': {
              transitionEnd: 'animationend',
              prefix: '-moz-'
            },
            'WebkitTransition': {
              transitionEnd: 'webkitAnimationEnd',
              prefix: '-webkit-'
            }
          }

          for (t in transitions) {
            if (el.style[t] !== undefined) {
              browser = transitions[t];
            }
          }
      }
      return browser;
    },

Properties that Firefox can't animate if set to 'auto': https://bugzilla.mozilla.org/show_bug.cgi?id=571344 Provides a converter that returns the actual value

    ffProps = {
      top: function (el) {
        return el.position().top;
      },
      left: function (el) {
        return el.position().left;
      },
      width: function (el) {
        return el.width();
      },
      height: function (el) {
        return el.height();
      },
      fontSize: function (el) {
        return '1em';
      }
    },

Add browser specific prefix

    addPrefix = function (properties) {
      var result = {};
      $.each(properties, function (name, value) {
        result[getBrowser().prefix + name] = value;
      });
      return result;
    },

Returns the animation name for a given style. It either uses a cached version or adds it to the stylesheet, removing the oldest style if the cache has reached a certain size.

    getAnimation = function (style) {
      var sheet, name, last;

Look up the cached style, set it to that name and reset age if found increment the age for any other animation

      $.each(cache, function (i, animation) {
        if (style === animation.style) {
          name = animation.name;
          animation.age = 0;
        } else {
          animation.age += 1;
        }
      });

      if (!name) { // Add a new style
        sheet = getStyleSheet();
        name = "jquerypp_animation_" + (animationNum++);

get the last sheet and insert this rule into it

        sheet.insertRule("@" + getBrowser().prefix + "keyframes " + name + ' ' + style, (sheet.cssRules && sheet.cssRules.length) || 0);
        cache.push({
          name: name,
          style: style,
          age: 0
        });

Sort the cache by age

        cache.sort(function (first, second) {
          return first.age - second.age;
        });

Remove the last (oldest) item from the cache if it has more than 20 items

        if (cache.length > 20) {
          last = cache.pop();
          removeAnimation(sheet, last.name);
        }
      }

      return name;
    };


  $.fn.animate = function (props, speed, easing, callback) {

default to normal animations if browser doesn't support them

    if (passThrough.apply(this, arguments)) {
      return oldanimate.apply(this, arguments);
    }

    var optall = $.speed(speed, easing, callback);

Add everything to the animation queue

    this.queue(optall.queue, function (done) {
      var

current CSS values

      current,

The list of properties passed

      properties = [],
        to = "",
        prop, self = $(this),
        duration = optall.duration,

the animation keyframe name

        animationName,

The key used to store the animation hook

        dataKey,

the text for the keyframe

        style = "{ from {",

The animation end event handler. Will be called both on animation end and after calling .stop()

        animationEnd = function (currentCSS, exec) {
          self.css(currentCSS);

          self.css(addPrefix({
            "animation-duration": "",
            "animation-name": "",
            "animation-fill-mode": "",
            "animation-play-state": ""
          }));

Call the original callback

          if ($.isFunction(optall.old) && exec) {

Call success, pass the DOM element as the this reference

            optall.old.call(self[0], true)
          }

          $.removeData(self, dataKey, true);
        },
        finishAnimation = function () {

Call animationEnd using the passed properties

          animationEnd(props, true);
          done();
        };

      for (prop in props) {
        properties.push(prop);
      }

      if (getBrowser().prefix === '-moz-') {

Normalize 'auto' properties in FF

        $.each(properties, function (i, prop) {
          var converter = ffProps[$.camelCase(prop)];
          if (converter && self.css(prop) == 'auto') {
            self.css(prop, converter(self));
          }
        });
      }

Use $.styles

      current = self.styles.apply(self, properties);
      $.each(properties, function (i, cur) {

Convert a camelcased property name

        var name = cur.replace(/([A-Z]|^ms)/g, "-$1").toLowerCase();
        style += name + " : " + cssValue(cur, current[cur]) + "; ";
        to += name + " : " + cssValue(cur, props[cur]) + "; ";
      });

      style += "} to {" + to + " }}";

      animationName = getAnimation(style);
      dataKey = animationName + '.run';

Add a hook which will be called when the animation stops

      $._data(this, dataKey, {
        stop: function (gotoEnd) {

Pause the animation

          self.css(addPrefix({
            'animation-play-state': 'paused'
          }));

Unbind the animation end handler

          self.off(getBrowser().transitionEnd, finishAnimation);
          if (!gotoEnd) {

We were told not to finish the animation Call animationEnd but set the CSS to the current computed style

            animationEnd(self.styles.apply(self, properties), false);
          } else {

Finish animaion

            animationEnd(props, true);
          }
        }
      });

set this element to point to that animation

      self.css(addPrefix({
        "animation-duration": duration + "ms",
        "animation-name": animationName,
        "animation-fill-mode": "forwards"
      }));

Attach the transition end event handler to run only once

      self.one(getBrowser().transitionEnd, finishAnimation);

    });

    return this;
  };

jquery/dom/compare/compare.js

See http://ejohn.org/blog/comparing-document-position/

  $.fn.compare = function (element) { //usually
    try {

Firefox 3 throws an error with XUL - we can't use compare then

      element = element.jquery ? element[0] : element;
    } catch (e) {
      return null;
    }

make sure we aren't coming from XUL element

    if (window.HTMLElement) {
      var s = HTMLElement.prototype.toString.call(element)
      if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]' || s === '[object Window]') {
        return null;
      }
    }

    if (this[0].compareDocumentPosition) {

For browsers that support it, use compareDocumentPosition https://developer.mozilla.org/en/DOM/Node.compareDocumentPosition

      return this[0].compareDocumentPosition(element);
    }

this[0] contains element

    if (this[0] == document && element != document) return 8;

    var number =

this[0] contains element

    (this[0] !== element && this[0].contains(element) && 16) +

element contains this[0]

    (this[0] != element && element.contains(this[0]) && 8),
      docEl = document.documentElement;

Use the sourceIndex

    if (this[0].sourceIndex) {

this[0] precedes element

      number += (this[0].sourceIndex < element.sourceIndex && 4)

element precedes foo[0]

      number += (this[0].sourceIndex > element.sourceIndex && 2)

The nodes are in different documents

      number += (this[0].ownerDocument !== element.ownerDocument || (this[0] != docEl && this[0].sourceIndex <= 0) || (element != docEl && element.sourceIndex <= 0)) && 1
    }

    return number;
  }

jquery/lang/json/json.js

  $.toJSON = function (o, replacer, space, recurse) {
    if (typeof(JSON) == 'object' && JSON.stringify) return JSON.stringify(o, replacer, space);

    if (!recurse && $.isFunction(replacer)) o = replacer("", o);

    if (typeof space == "number") space = "          ".substring(0, space);
    space = (typeof space == "string") ? space.substring(0, 10) : "";

    var type = typeof(o);

    if (o === null) return "null";

    if (type == "undefined" || type == "function") return undefined;

    if (type == "number" || type == "boolean") return o + "";

    if (type == "string") return $.quoteString(o);

    if (type == 'object') {
      if (typeof o.toJSON == "function") return $.toJSON(o.toJSON(), replacer, space, true);

      if (o.constructor === Date) {
        var month = o.getUTCMonth() + 1;
        if (month < 10) month = '0' + month;

        var day = o.getUTCDate();
        if (day < 10) day = '0' + day;

        var year = o.getUTCFullYear();

        var hours = o.getUTCHours();
        if (hours < 10) hours = '0' + hours;

        var minutes = o.getUTCMinutes();
        if (minutes < 10) minutes = '0' + minutes;

        var seconds = o.getUTCSeconds();
        if (seconds < 10) seconds = '0' + seconds;

        var milli = o.getUTCMilliseconds();
        if (milli < 100) milli = '0' + milli;
        if (milli < 10) milli = '0' + milli;

        return '"' + year + '-' + month + '-' + day + 'T' + hours + ':' + minutes + ':' + seconds + '.' + milli + 'Z"';
      }

      var process = ($.isFunction(replacer)) ?
      function (k, v) {
        return replacer(k, v);
      } : function (k, v) {
        return v;
      },
        nl = (space) ? "\n" : "",
        sp = (space) ? " " : "";

      if (o.constructor === Array) {
        var ret = [];
        for (var i = 0; i < o.length; i++)
        ret.push(($.toJSON(process(i, o[i]), replacer, space, true) || "null").replace(/^/gm, space));

        return "[" + nl + ret.join("," + nl) + nl + "]";
      }

      var pairs = [],
        proplist;
      if ($.isArray(replacer)) {
        proplist = $.map(replacer, function (v) {
          return (typeof v == "string" || typeof v == "number") ? v + "" : null;
        });
      }
      for (var k in o) {
        var name, val, type = typeof k;

        if (proplist && $.inArray(k + "", proplist) == -1) continue;

        if (type == "number") name = '"' + k + '"';
        else if (type == "string") name = $.quoteString(k);
        else continue; //skip non-string or number keys
        val = $.toJSON(process(k, o[k]), replacer, space, true);

        if (typeof val == "undefined") continue; //skip pairs where the value is a function.
        pairs.push((name + ":" + sp + val).replace(/^/gm, space));
      }

      return "{" + nl + pairs.join("," + nl) + nl + "}";
    }
  };


  $.evalJSON = function (src) {
    if (typeof(JSON) == 'object' && JSON.parse) return JSON.parse(src);
    return eval("(" + src + ")");
  };


  $.secureEvalJSON = function (src) {
    if (typeof(JSON) == 'object' && JSON.parse) return JSON.parse(src);

    var filtered = src;
    filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
    filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');

    if (/^[\],:{}\s]*$/.test(filtered)) return eval("(" + src + ")");
    else throw new SyntaxError("Error parsing JSON, source is not valid.");
  };


  $.quoteString = function (string) {
    if (string.match(_escapeable)) {
      return '"' + string.replace(_escapeable, function (a) {
        var c = _meta[a];
        if (typeof c === 'string') return c;
        c = a.charCodeAt();
        return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
      }) + '"';
    }
    return '"' + string + '"';
  };

  var _escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;

  var _meta = {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '"': '\\"',
    '\\': '\\\\'
  };

jquery/dom/cookie/cookie.js

  $.cookie = function (name, value, options) {
    if (typeof value != 'undefined') {

name and value given, set cookie

      options = options || {};
      if (value === null) {
        value = '';
        options.expires = -1;
      }

convert value to JSON string

      if (typeof value == 'object' && $.toJSON) {
        value = $.toJSON(value);
      }
      var expires = '';

Set expiry

      if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
        var date;
        if (typeof options.expires == 'number') {
          date = new Date();
          date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
        }
        else {
          date = options.expires;
        }
        expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
      }

CAUTION: Needed to parenthesize options.path and options.domain in the following expressions, otherwise they evaluate to undefined in the packed version for some reason...

      var path = options.path ? '; path=' + (options.path) : '';
      var domain = options.domain ? '; domain=' + (options.domain) : '';
      var secure = options.secure ? '; secure' : '';

Set the cookie name=value;expires=;path=;domain=;secure-

      document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    }
    else { // only name given, get cookie
      var cookieValue = null;
      if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
          var cookie = $.trim(cookies[i]);

Does this cookie string begin with the name we want?

          if (cookie.substring(0, name.length + 1) == (name + '=')) {

Get the cookie value

            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
          }
        }
      }

Parse JSON from the cookie into an object

      if ($.evalJSON && cookieValue && cookieValue.match(/^\s*\{/)) {
        try {
          cookieValue = $.evalJSON(cookieValue);
        }
        catch (e) {}
      }
      return cookieValue;
    }
  };

jquery/dom/dimensions/dimensions.js

  var

margin is inside border

  weird = /button|select/i,
    getBoxes = {},
    checks = {
      width: ["Left", "Right"],
      height: ['Top', 'Bottom'],
      oldOuterHeight: $.fn.outerHeight,
      oldOuterWidth: $.fn.outerWidth,
      oldInnerWidth: $.fn.innerWidth,
      oldInnerHeight: $.fn.innerHeight
    },
    supportsSetter = $.fn.jquery >= '1.8.0';

  $.each({

    width:

    "Width",

    height:

for each 'height' and 'width'

    "Height"
  }, function (lower, Upper) {

used to get the padding and border for an element in a given direction

    getBoxes[lower] = function (el, boxes) {
      var val = 0;
      if (!weird.test(el.nodeName)) {

make what to check for ....

        var myChecks = [];
        $.each(checks[lower], function () {
          var direction = this;
          $.each(boxes, function (name, val) {
            if (val) myChecks.push(name + direction + (name == 'border' ? "Width" : ""));
          })
        })
        $.each($.styles(el, myChecks), function (name, value) {
          val += (parseFloat(value) || 0);
        })
      }
      return val;
    }

getter / setter

    if (!supportsSetter) {
      $.fn["outer" + Upper] = function (v, margin) {
        var first = this[0];
        if (typeof v == 'number') {

Setting the value

          first && this[lower](v - getBoxes[lower](first, {
            padding: true,
            border: true,
            margin: margin
          }))
          return this;
        } else {

Return the old value

          return first ? checks["oldOuter" + Upper].apply(this, arguments) : null;
        }
      }
      $.fn["inner" + Upper] = function (v) {
        var first = this[0];
        if (typeof v == 'number') {

Setting the value

          first && this[lower](v - getBoxes[lower](first, {
            padding: true
          }))
          return this;
        } else {

Return the old value

          return first ? checks["oldInner" + Upper].apply(this, arguments) : null;
        }
      }
    }

provides animations

    var animate = function (boxes) {

Return the animation function

      return function (fx) {
        if (fx[supportsSetter ? 'pos' : 'state'] == 0) {
          fx.start = $(fx.elem)[lower]();
          fx.end = fx.end - getBoxes[lower](fx.elem, boxes);
        }
        fx.elem.style[lower] = (fx.pos * (fx.end - fx.start) + fx.start) + "px"
      }
    }
    $.fx.step["outer" + Upper] = animate({
      padding: true,
      border: true
    })
    $.fx.step["outer" + Upper + "Margin"] = animate({
      padding: true,
      border: true,
      margin: true
    })
    $.fx.step["inner" + Upper] = animate({
      padding: true
    })

  })

jquery/dom/formparams/formparams.js

  var

use to parse bracket notation like my[name][attribute]

  keyBreaker = /[^\[\]]+/g,

converts values that look like numbers and booleans and removes empty strings

    convertValue = function (value) {
      if ($.isNumeric(value)) {
        return parseFloat(value);
      } else if (value === 'true') {
        return true;
      } else if (value === 'false') {
        return false;
      } else if (value === '' || value === null) {
        return undefined;
      }
      return value;
    },

Access nested data

    nestData = function (elem, type, data, parts, value, seen, fullName) {
      var name = parts.shift();

Keep track of the dot separated fullname. Used to uniquely track seen values and if they should be converted to an array or not

      fullName = fullName ? fullName + '.' + name : name;

      if (parts.length) {
        if (!data[name]) {
          data[name] = {};
        }

Recursive call

        nestData(elem, type, data[name], parts, value, seen, fullName);
      } else {

Handle same name case, as well as "last checkbox checked" case

        if (fullName in seen && type != "radio" && !$.isArray(data[name])) {
          if (name in data) {
            data[name] = [data[name]];
          } else {
            data[name] = [];
          }
        } else {
          seen[fullName] = true;
        }

Finally, assign data

        if ((type == "radio" || type == "checkbox") && !elem.is(":checked")) {
          return
        }

        if (!data[name]) {
          data[name] = value;
        } else {
          data[name].push(value);
        }


      }

    };


  $.fn.extend({
    formParams: function (params) {

      var convert;

Quick way to determine if something is a boolean

      if ( !! params === params) {
        convert = params;
        params = null;
      }

      if (params) {
        return this.setParams(params);
      } else {
        return this.getParams(convert);
      }
    },
    setParams: function (params) {

Find all the inputs

      this.find("[name]").each(function () {
        var $this = $(this),
          value = params[$this.attr("name")];

Don't do all this work if there's no value

        if (value !== undefined) {

Nested these if statements for performance

          if ($this.is(":radio")) {
            if ($this.val() == value) {
              $this.attr("checked", true);
            }
          } else if ($this.is(":checkbox")) {

Convert single value to an array to reduce complexity

            value = $.isArray(value) ? value : [value];
            if ($.inArray($this.val(), value) > -1) {
              $this.attr("checked", true);
            }
          } else {
            $this.val(value);
          }
        }
      });
    },
    getParams: function (convert) {
      var data = {},

This is used to keep track of the checkbox names that we've already seen, so we know that we should return an array if we see it multiple times. Fixes last checkbox checked bug.

        seen = {},
        current;

      this.find("[name]:not(:disabled)").each(function () {
        var $this = $(this),
          type = $this.attr("type"),
          name = $this.attr("name"),
          value = $this.val(),
          parts;

Don't accumulate submit buttons and nameless elements

        if (type == "submit" || !name) {
          return;
        }

Figure out name parts

        parts = name.match(keyBreaker);
        if (!parts.length) {
          parts = [name];
        }

Convert the value

        if (convert) {
          value = convertValue(value);
        }

Assign data recursively

        nestData($this, type, data, parts, value, seen);

      });

      return data;
    }
  });

jquery/dom/range/range.js

  $.fn.range =

  function () {
    return $.Range(this[0])
  }

  var convertType = function (type) {
    return type.replace(/([a-z])([a-z]+)/gi, function (all, first, next) {
      return first + next.toLowerCase()
    }).replace(/_/g, "");
  },

reverses things like STARTTOEND into ENDTOSTART

    reverse = function (type) {
      return type.replace(/^([a-z]+)_TO_([a-z]+)/i, function (all, first, last) {
        return last + "_TO_" + first;
      });
    },
    getWindow = function (element) {
      return element ? element.ownerDocument.defaultView || element.ownerDocument.parentWindow : window
    },
    bisect = function (el, start, end) {

split the start and end ... figure out who is touching ...

      if (end - start == 1) {
        return
      }
    },
    support = {};

  $.Range = function (range) {

If it's called w/o new, call it with new!

    if (this.constructor !== $.Range) {
      return new $.Range(range);
    }

If we are passed a jQuery-wrapped element, get the raw element

    if (range && range.jquery) {
      range = range[0];
    }

If we have an element, or nothing

    if (!range || range.nodeType) {

create a range

      this.win = getWindow(range)
      if (this.win.document.createRange) {
        this.range = this.win.document.createRange()
      } else if (this.win && this.win.document.body && this.win.document.body.createTextRange) {
        this.range = this.win.document.body.createTextRange()
      }

if we have an element, make the range select it

      if (range) {
        this.select(range)
      }
    }

if we are given a point

    else if (range.clientX != null || range.pageX != null || range.left != null) {
      this.moveToPoint(range);
    }

if we are given a touch event

    else if (range.originalEvent && range.originalEvent.touches && range.originalEvent.touches.length) {
      this.moveToPoint(range.originalEvent.touches[0])

    }

if we are a normal event

    else if (range.originalEvent && range.originalEvent.changedTouches && range.originalEvent.changedTouches.length) {
      this.moveToPoint(range.originalEvent.changedTouches[0])
    }

given a TextRange or something else?

    else {
      this.range = range;
    }
  };

  $.Range.

  current = function (el) {
    var win = getWindow(el),
      selection;
    if (win.getSelection) {

If we can get the selection

      selection = win.getSelection()
      return new $.Range(selection.rangeCount ? selection.getRangeAt(0) : win.document.createRange())
    } else {

Otherwise use document.selection

      return new $.Range(win.document.selection.createRange());
    }
  };

  $.extend($.Range.prototype,

  {

    moveToPoint: function (point) {
      var clientX = point.clientX,
        clientY = point.clientY
        if (!clientX) {
          var off = scrollOffset();
          clientX = (point.pageX || point.left || 0) - off.left;
          clientY = (point.pageY || point.top || 0) - off.top;
        }
        if (support.moveToPoint) {
          this.range = $.Range().range
          this.range.moveToPoint(clientX, clientY);
          return this;
        }

it's some text node in this range ...

        var parent = document.elementFromPoint(clientX, clientY);

typically it will be 'on' text

      for (var n = 0; n < parent.childNodes.length; n++) {
        var node = parent.childNodes[n];
        if (node.nodeType === 3 || node.nodeType === 4) {
          var range = $.Range(node),
            length = range.toString().length;

now lets start moving the end until the boundingRect is within our range

          for (var i = 1; i < length + 1; i++) {
            var rect = range.end(i).rect();
            if (rect.left <= clientX && rect.left + rect.width >= clientX && rect.top <= clientY && rect.top + rect.height >= clientY) {
              range.start(i - 1);
              this.range = range.range;
              return this;
            }
          }
        }
      }

if not 'on' text, recursively go through and find out when we shift to next 'line'

      var previous;
      iterate(parent.childNodes, function (textNode) {
        var range = $.Range(textNode);
        if (range.rect().top > point.clientY) {
          return false;
        } else {
          previous = range;
        }
      });

      if (previous) {
        previous.start(previous.toString().length);
        this.range = previous.range;
      } else {
        this.range = $.Range(parent).range
      }
    },

    window: function () {
      return this.win || window;
    },

    overlaps: function (elRange) {
      if (elRange.nodeType) {
        elRange = $.Range(elRange).select(elRange);
      }

if the start is within the element ...

      var startToStart = this.compare("START_TO_START", elRange),
        endToEnd = this.compare("END_TO_END", elRange)

if we wrap elRange

        if (startToStart <= 0 && endToEnd >= 0) {
          return true;
        }

if our start is inside of it

        if (startToStart >= 0 && this.compare("START_TO_END", elRange) <= 0) {
          return true;
        }

if our end is inside of elRange

        if (this.compare("END_TO_START", elRange) >= 0 && endToEnd <= 0) {
          return true;
        }
        return false;
    },

    collapse: function (toStart) {
      this.range.collapse(toStart === undefined ? true : toStart);
      return this;
    },

    toString: function () {
      return typeof this.range.text == "string" ? this.range.text : this.range.toString();
    },

    start: function (set) {

return start

      if (set === undefined) {
        if (this.range.startContainer) {
          return {
            container: this.range.startContainer,
            offset: this.range.startOffset
          }
        } else {

Get the start parent element

          var start = this.clone().collapse().parent();

used to get the start element offset

          var startRange = $.Range(start).select(start).collapse();
          startRange.move("END_TO_START", this);
          return {
            container: start,
            offset: startRange.toString().length
          }
        }
      } else {
        if (this.range.setStart) {

supports setStart

          if (typeof set == 'number') {
            this.range.setStart(this.range.startContainer, set)
          } else if (typeof set == 'string') {
            var res = callMove(this.range.startContainer, this.range.startOffset, parseInt(set, 10))
            this.range.setStart(res.node, res.offset);
          } else {
            this.range.setStart(set.container, set.offset)
          }
        } else {
          if (typeof set == "string") {
            this.range.moveStart('character', parseInt(set, 10))
          } else {

get the current end container

            var container = this.start().container,
              offset
              if (typeof set == "number") {
                offset = set
              } else {
                container = set.container
                offset = set.offset
              }
              var newPoint = $.Range(container).collapse();

move it over offset characters

            newPoint.range.move(offset);
            this.move("START_TO_START", newPoint);
          }
        }
        return this;
      }

    },

    end: function (set) {

read end

      if (set === undefined) {
        if (this.range.startContainer) {
          return {
            container: this.range.endContainer,
            offset: this.range.endOffset
          }
        }
        else {
          var

Get the end parent element

          end = this.clone().collapse(false).parent(),

used to get the end elements offset

            endRange = $.Range(end).select(end).collapse();
          endRange.move("END_TO_END", this);
          return {
            container: end,
            offset: endRange.toString().length
          }
        }
      } else {
        if (this.range.setEnd) {
          if (typeof set == 'number') {
            this.range.setEnd(this.range.endContainer, set)
          } else if (typeof set == 'string') {
            var res = callMove(this.range.endContainer, this.range.endOffset, parseInt(set, 10))
            this.range.setEnd(res.node, res.offset);
          } else {
            this.range.setEnd(set.container, set.offset)
          }
        } else {
          if (typeof set == "string") {
            this.range.moveEnd('character', parseInt(set, 10));
          } else {

get the current end container

            var container = this.end().container,
              offset
              if (typeof set == "number") {
                offset = set
              } else {
                container = set.container
                offset = set.offset
              }
              var newPoint = $.Range(container).collapse();

move it over offset characters

            newPoint.range.move(offset);
            this.move("END_TO_START", newPoint);
          }
        }
        return this;
      }
    },

    parent: function () {
      if (this.range.commonAncestorContainer) {
        return this.range.commonAncestorContainer;
      } else {

        var parentElement = this.range.parentElement(),
          range = this.range;

IE's parentElement will always give an element, we want text ranges

        iterate(parentElement.childNodes, function (txtNode) {
          if ($.Range(txtNode).range.inRange(range)) {

swap out the parentElement

            parentElement = txtNode;
            return false;
          }
        });

        return parentElement;
      }
    },

    rect: function (from) {
      var rect = this.range.getBoundingClientRect();

for some reason in webkit this gets a better value

      if (!rect.height && !rect.width) {
        rect = this.range.getClientRects()[0]
      }
      if (from === 'page') {

Add the scroll offset

        var off = scrollOffset();
        rect = $.extend({}, rect);
        rect.top += off.top;
        rect.left += off.left;
      }
      return rect;
    },

    rects: function (from) {

order rects by size

      var rects = $.map($.makeArray(this.range.getClientRects()).sort(function (rect1, rect2) {
        return rect2.width * rect2.height - rect1.width * rect1.height;
      }), function (rect) {
        return $.extend({}, rect)
      }),
        i = 0,
        j, len = rects.length;

safari returns overlapping client rects - big rects can contain 2 smaller rects - some rects can contain 0 - width rects - we don't want these 0 width rects

      while (i < rects.length) {
        var cur = rects[i],
          found = false;

        j = i + 1;
        while (j < rects.length) {
          if (withinRect(cur, rects[j])) {
            if (!rects[j].width) {
              rects.splice(j, 1)
            } else {
              found = rects[j];
              break;
            }
          } else {
            j++;
          }
        }

        if (found) {
          rects.splice(i, 1)
        } else {
          i++;
        }

      }

safari will be return overlapping ranges ...

      if (from == 'page') {
        var off = scrollOffset();
        return $.each(rects, function (ith, item) {
          item.top += off.top;
          item.left += off.left;
        })
      }

      return rects;
    }

  });
  (function () {

method branching ....

    var fn = $.Range.prototype,
      range = $.Range().range;


    fn.compare = range.compareBoundaryPoints ?
    function (type, range) {
      return this.range.compareBoundaryPoints(this.window().Range[reverse(type)], range.range)
    } : function (type, range) {
      return this.range.compareEndPoints(convertType(type), range.range)
    }


    fn.move = range.setStart ?
    function (type, range) {

      var rangesRange = range.range;
      switch (type) {
      case "START_TO_END":
        this.range.setStart(rangesRange.endContainer, rangesRange.endOffset)
        break;
      case "START_TO_START":
        this.range.setStart(rangesRange.startContainer, rangesRange.startOffset)
        break;
      case "END_TO_END":
        this.range.setEnd(rangesRange.endContainer, rangesRange.endOffset)
        break;
      case "END_TO_START":
        this.range.setEnd(rangesRange.startContainer, rangesRange.startOffset)
        break;
      }

      return this;
    } : function (type, range) {
      this.range.setEndPoint(convertType(type), range.range)
      return this;
    };
    var cloneFunc = range.cloneRange ? "cloneRange" : "duplicate",
      selectFunc = range.selectNodeContents ? "selectNodeContents" : "moveToElementText";

    fn.

    clone = function () {
      return $.Range(this.range[cloneFunc]());
    };

    fn.

    select = range.selectNodeContents ?
    function (el) {
      if (!el) {
        var selection = this.window().getSelection();
        selection.removeAllRanges();
        selection.addRange(this.range);
      } else {
        this.range.selectNodeContents(el);
      }
      return this;
    } : function (el) {
      if (!el) {
        this.range.select()
      } else if (el.nodeType === 3) {

select this node in the element ...

        var parent = el.parentNode,
          start = 0,
          end;
        iterate(parent.childNodes, function (txtNode) {
          if (txtNode === el) {
            end = start + txtNode.nodeValue.length;
            return false;
          } else {
            start = start + txtNode.nodeValue.length
          }
        })
        this.range.moveToElementText(parent);

        this.range.moveEnd('character', end - this.range.text.length)
        this.range.moveStart('character', start);
      } else {
        this.range.moveToElementText(el);
      }
      return this;
    };

  })();

helpers ----------------- iterates through a list of elements, calls cb on every text node if cb returns false, exits the iteration

  var iterate = function (elems, cb) {
    var elem, start;
    for (var i = 0; elems[i]; i++) {
      elem = elems[i];

Get the text from text nodes and CDATA nodes

      if (elem.nodeType === 3 || elem.nodeType === 4) {
        if (cb(elem) === false) {
          return false;
        }

Traverse everything else, except comment nodes

      }
      else if (elem.nodeType !== 8) {
        if (iterate(elem.childNodes, cb) === false) {
          return false;
        }
      }
    }

  },
    isText = function (node) {
      return node.nodeType === 3 || node.nodeType === 4
    },
    iteratorMaker = function (toChildren, toNext) {
      return function (node, mustMoveRight) {

first try down

        if (node[toChildren] && !mustMoveRight) {
          return isText(node[toChildren]) ? node[toChildren] : arguments.callee(node[toChildren])
        } else if (node[toNext]) {
          return isText(node[toNext]) ? node[toNext] : arguments.callee(node[toNext])
        } else if (node.parentNode) {
          return arguments.callee(node.parentNode, true)
        }
      }
    },
    getNextTextNode = iteratorMaker("firstChild", "nextSibling"),
    getPrevTextNode = iteratorMaker("lastChild", "previousSibling"),
    callMove = function (container, offset, howMany) {
      var mover = howMany < 0 ? getPrevTextNode : getNextTextNode;

find the text element

      if (!isText(container)) {

sometimes offset isn't actually an element

        container = container.childNodes[offset] ? container.childNodes[offset] :

if this happens, use the last child

        container.lastChild;

        if (!isText(container)) {
          container = mover(container)
        }
        return move(container, howMany)
      } else {
        if (offset + howMany < 0) {
          return move(mover(container), offset + howMany)
        } else {
          return move(container, offset + howMany)
        }

      }
    },

Moves howMany characters from the start of from

    move = function (from, howMany) {
      var mover = howMany < 0 ? getPrevTextNode : getNextTextNode;

      howMany = Math.abs(howMany);

      while (from && howMany >= from.nodeValue.length) {
        howMany = howMany - from.nodeValue.length;
        from = mover(from)
      }
      return {
        node: from,
        offset: mover === getNextTextNode ? howMany : from.nodeValue.length - howMany
      }
    },
    supportWhitespace, isWhitespace = function (el) {
      if (supportWhitespace == null) {
        supportWhitespace = 'isElementContentWhitespace' in el;
      }
      return (supportWhitespace ? el.isElementContentWhitespace : (el.nodeType === 3 && '' == el.data.trim()));

    },

if a point is within a rectangle

    within = function (rect, point) {

      return rect.left <= point.clientX && rect.left + rect.width >= point.clientX && rect.top <= point.clientY && rect.top + rect.height >= point.clientY
    },

if a rectangle is within another rectangle

    withinRect = function (outer, inner) {
      return within(outer, {
        clientX: inner.left,
        clientY: inner.top
      }) && //top left
      within(outer, {
        clientX: inner.left + inner.width,
        clientY: inner.top
      }) && //top right
      within(outer, {
        clientX: inner.left,
        clientY: inner.top + inner.height
      }) && //bottom left
      within(outer, {
        clientX: inner.left + inner.width,
        clientY: inner.top + inner.height
      }) //bottom right
    },

gets the scroll offset from a window

    scrollOffset = function (win) {
      var win = win || window;
      doc = win.document.documentElement, body = win.document.body;

      return {
        left: (doc && doc.scrollLeft || body && body.scrollLeft || 0) + (doc.clientLeft || 0),
        top: (doc && doc.scrollTop || body && body.scrollTop || 0) + (doc.clientTop || 0)
      };
    };

  support.moveToPoint = !! $.Range().range.moveToPoint

jquery/dom/selection/selection.js

  var getWindow = function (element) {
    return element ? element.ownerDocument.defaultView || element.ownerDocument.parentWindow : window
  },

A helper that uses range to abstract out getting the current start and endPos.

    getElementsSelection = function (el, win) {

get a copy of the current range and a range that spans the element

      var current = $.Range.current(el).clone(),
        entireElement = $.Range(el).select(el);

if there is no overlap, there is nothing selected

      if (!current.overlaps(entireElement)) {
        return null;
      }

if the current range starts before our element

      if (current.compare("START_TO_START", entireElement) < 1) {

the selection within the element begins at 0

        startPos = 0;

move the current range to start at our element

        current.move("START_TO_START", entireElement);
      } else {

Make a copy of the element's range. Move it's end to the start of the selected range The length of the copy is the start of the selected range.

        fromElementToCurrent = entireElement.clone();
        fromElementToCurrent.move("END_TO_START", current);
        startPos = fromElementToCurrent.toString().length
      }

If the current range ends after our element

      if (current.compare("END_TO_END", entireElement) >= 0) {

the end position is the last character

        endPos = entireElement.toString().length
      } else {

otherwise, it's the start position plus the current range TODO: this doesn't seem like it works if current extends to the left of the element.

        endPos = startPos + current.toString().length
      }
      return {
        start: startPos,
        end: endPos,
        width: endPos - startPos
      };
    },

Text selection works differently for selection in an input vs normal html elements like divs, spans, and ps. This function branches between the various methods of getting the selection.

    getSelection = function (el) {
      var win = getWindow(el);

selectionStart means this is an input element in a standards browser.

      if (el.selectionStart !== undefined) {

        if (document.activeElement && document.activeElement != el && el.selectionStart == el.selectionEnd && el.selectionStart == 0) {
          return {
            start: el.value.length,
            end: el.value.length,
            width: 0
          };
        }
        return {
          start: el.selectionStart,
          end: el.selectionEnd,
          width: el.selectionEnd - el.selectionStart
        };
      }

getSelection means a 'normal' element in a standards browser.

      else if (win.getSelection) {
        return getElementsSelection(el, win)
      } else {

IE will freak out, where there is no way to detect it, so we provide a callback if it does.

        try {

The following typically works for input elements in IE:

          if (el.nodeName.toLowerCase() == 'input') {
            var real = getWindow(el).document.selection.createRange(),
              r = el.createTextRange();
            r.setEndPoint("EndToStart", real);

            var start = r.text.length
            return {
              start: start,
              end: start + real.text.length,
              width: real.text.length
            }
          }

This works on textareas and other elements

          else {
            var res = getElementsSelection(el, win)
            if (!res) {
              return res;
            }

we have to clean up for ie's textareas which don't count for newlines correctly

            var current = $.Range.current().clone(),
              r2 = current.clone().collapse().range,
              r3 = current.clone().collapse(false).range;

            r2.moveStart('character', -1)
            r3.moveStart('character', -1)

if we aren't at the start, but previous is empty, we are at start of newline

            if (res.startPos != 0 && r2.text == "") {
              res.startPos += 2;
            }

do a similar thing for the end of the textarea

            if (res.endPos != 0 && r3.text == "") {
              res.endPos += 2;
            }

            return res
          }
        } catch (e) {
          return {
            start: el.value.length,
            end: el.value.length,
            width: 0
          };
        }
      }
    },

Selects text within an element. Depending if it's a form element or not, or a standards based browser or not, we do different things.

    select = function (el, start, end) {
      var win = getWindow(el);

IE behaves bad even if it sorta supports getSelection so we have to try the IE methods first. barf.

      if (el.setSelectionRange) {
        if (end === undefined) {
          el.focus();
          el.setSelectionRange(start, start);
        } else {
          el.select();
          el.selectionStart = start;
          el.selectionEnd = end;
        }
      } else if (el.createTextRange) {
        var r = el.createTextRange();
        r.moveStart('character', start);
        end = end || start;
        r.moveEnd('character', end - el.value.length);

        r.select();
      } else if (win.getSelection) {
        var doc = win.document,
          sel = win.getSelection(),
          range = doc.createRange(),
          ranges = [start, end !== undefined ? end : start];
        getCharElement([el], ranges);
        range.setStart(ranges[0].el, ranges[0].count);
        range.setEnd(ranges[1].el, ranges[1].count);

removeAllRanges is necessary for webkit

        sel.removeAllRanges();
        sel.addRange(range);

      } else if (win.document.body.createTextRange) { //IE's weirdness
        var range = document.body.createTextRange();
        range.moveToElementText(el);
        range.collapse()
        range.moveStart('character', start)
        range.moveEnd('character', end !== undefined ? end : start)
        range.select();
      }

    },

If one of the range values is within start and len, replace the range value with the element and its offset.

    replaceWithLess = function (start, len, range, el) {
      if (typeof range[0] === 'number' && range[0] < len) {
        range[0] = {
          el: el,
          count: range[0] - start
        };
      }
      if (typeof range[1] === 'number' && range[1] <= len) {
        range[1] = {
          el: el,
          count: range[1] - start
        };
      }
    },
    getCharElement = function (elems, range, len) {
      var elem, start;

      len = len || 0;
      for (var i = 0; elems[i]; i++) {
        elem = elems[i];

Get the text from text nodes and CDATA nodes

        if (elem.nodeType === 3 || elem.nodeType === 4) {
          start = len
          len += elem.nodeValue.length;

check if len is now greater than what's in counts

          replaceWithLess(start, len, range, elem)

Traverse everything else, except comment nodes

        } else if (elem.nodeType !== 8) {
          len = getCharElement(elem.childNodes, range, len);
        }
      }
      return len;
    };

  $.fn.selection = function (start, end) {
    if (start !== undefined) {
      return this.each(function () {
        select(this, start, end)
      })
    } else {
      return getSelection(this[0])
    }
  };

for testing

  $.fn.selection.getCharElement = getCharElement;

jquery/dom/within/within.js

Checks if x and y coordinates are within a box with left, top, width and height

  var withinBox = function (x, y, left, top, width, height) {
    return (y >= top && y < top + height && x >= left && x < left + width);
  }

  $.fn.within = function (left, top, useOffsetCache) {
    var ret = []
    this.each(function () {
      var q = jQuery(this);

      if (this == document.documentElement) {
        return ret.push(this);
      }

uses either the cached offset or .offset()

      var offset = useOffsetCache ? $.data(this, "offsetCache") || $.data(this, "offsetCache", q.offset()) : q.offset();

Check if the given coordinates are within the area of the current element

      var res = withinBox(left, top, offset.left, offset.top, this.offsetWidth, this.offsetHeight);

      if (res) {

Add it to the results

        ret.push(this);
      }
    });

    return this.pushStack($.unique(ret), "within", left + "," + top);
  }

  $.fn.withinBox = function (left, top, width, height, useOffsetCache) {
    var ret = []
    this.each(function () {
      var q = jQuery(this);

      if (this == document.documentElement) return ret.push(this);

use cached offset or .offset()

      var offset = useOffsetCache ? $.data(this, "offset") || $.data(this, "offset", q.offset()) : q.offset();

      var ew = q.width(),
        eh = q.height(),

Checks if the element offset is within the given box

        res = !((offset.top > top + height) || (offset.top + eh < top) || (offset.left > left + width) || (offset.left + ew < left));

      if (res) ret.push(this);
    });
    return this.pushStack($.unique(ret), "withinBox", $.makeArray(arguments).join(","));
  }

jquery/event/default/default.js

  $.fn.triggerAsync = function (type, data, success, prevented) {
    if (typeof data == 'function') {
      prevented = success;
      success = data;
      data = undefined;
    }

    if (this.length) {
      var el = this;

Trigger the event with the success callback as the success handler when triggerAsync called within another triggerAsync,it's the same tick time so we should use timeout http://javascriptweblog.wordpress.com/2010/06/28/understanding-javascript-timers/

      setTimeout(function () {
        el.trigger({
          type: type,
          _success: success,
          _prevented: prevented
        }, data);
      }, 0);

    } else {

If we have no elements call the success callback right away

      if (success) success.call(this);
    }
    return this;
  }

cache default types for performance

  var types = {},
    rnamespaces = /\.(.*)$/,
    $event = $.event;

  $event.special["default"] = {
    add: function (handleObj) {

save the type

      types[handleObj.namespace.replace(rnamespaces, "")] = true;
    },
    setup: function () {
      return true
    }
  }

overwrite trigger to allow default types

  var oldTrigger = $event.trigger;

  $event.trigger = function defaultTriggerer(event, data, elem, onlyHandlers) {

Event object or event type

    var type = event.type || event,

Caller can pass in an Event, Object, or just an event type string

      event = typeof event === "object" ?

jQuery.Event object

      event[$.expando] ? event :

Object literal

      new $.Event(type, event) :

Just the event type (string)

      new $.Event(type),
      res = oldTrigger.call($.event, event, data, elem, onlyHandlers),
      paused = event.isPaused && event.isPaused();

    if (!onlyHandlers && !event.isDefaultPrevented() && event.type.indexOf("default") !== 0) {

Trigger the default. event

      oldTrigger("default." + event.type, data, elem)
      if (event._success) {
        event._success(event)
      }
    }

    if (!onlyHandlers && event.isDefaultPrevented() && event.type.indexOf("default") !== 0 && !paused) {
      if (event._prevented) {
        event._prevented(event);
      }
    }

code for paused

    if (paused) {

set back original stuff

      event.isDefaultPrevented =
      event.pausedState.isDefaultPrevented;
      event.isPropagationStopped =
      event.pausedState.isPropagationStopped;
    }
    return res;
  };

jquery/event/destroyed/destroyed.js

Store the old jQuery.cleanData

  var oldClean = $.cleanData;

Overwrites cleanData which is called by jQuery on manipulation methods

  $.cleanData = function (elems) {
    for (var i = 0, elem;
    (elem = elems[i]) !== undefined; i++) {

Trigger the destroyed event

      $(elem).triggerHandler("destroyed");
    }

Call the old jQuery.cleanData

    oldClean(elems);
  };

jquery/lang/vector/vector.js

  var getSetZero = function (v) {
    return v !== undefined ? (this.array[0] = v) : this.array[0]
  },
    getSetOne = function (v) {
      return v !== undefined ? (this.array[1] = v) : this.array[1]
    };

  $.Vector = function (arr) {
    var array = $.isArray(arr) ? arr : $.makeArray(arguments);
    this.update(array);
  };
  $.Vector.prototype =

  {

    app: function (f) {
      var i, newArr = [];

      for (i = 0; i < this.array.length; i++) {
        newArr.push(f(this.array[i], i));
      }
      return new $.Vector(newArr);
    },

    plus: function () {
      var i, args = arguments[0] instanceof $.Vector ? arguments[0].array : $.makeArray(arguments),
        arr = this.array.slice(0),
        vec = new $.Vector();
      for (i = 0; i < args.length; i++) {
        arr[i] = (arr[i] ? arr[i] : 0) + args[i];
      }
      return vec.update(arr);
    },

    minus: function () {
      var i, args = arguments[0] instanceof $.Vector ? arguments[0].array : $.makeArray(arguments),
        arr = this.array.slice(0),
        vec = new $.Vector();
      for (i = 0; i < args.length; i++) {
        arr[i] = (arr[i] ? arr[i] : 0) - args[i];
      }
      return vec.update(arr);
    },

    equals: function () {
      var i, args = arguments[0] instanceof $.Vector ? arguments[0].array : $.makeArray(arguments),
        arr = this.array.slice(0),
        vec = new $.Vector();
      for (i = 0; i < args.length; i++) {
        if (arr[i] != args[i]) {
          return null;
        }
      }
      return vec.update(arr);
    },

    x: getSetZero,

    left: getSetZero,

    width: getSetZero,

    y: getSetOne,

    top: getSetOne,

    height: getSetOne,

    toString: function () {
      return "(" + this.array.join(', ') + ")";
    },

    update: function (array) {
      var i;
      if (this.array) {
        for (i = 0; i < this.array.length; i++) {
          delete this.array[i];
        }
      }
      this.array = array;
      for (i = 0; i < array.length; i++) {
        this[i] = this.array[i];
      }
      return this;
    }
  };

  $.Event.prototype.vector = function () {

Get the first touch element for touch events

    var touches = "ontouchend" in document && this.originalEvent.touches && this.originalEvent.touches.length ? this.originalEvent.changedTouches[0] : this;
    if (this.originalEvent.synthetic) {
      var doc = document.documentElement,
        body = document.body;
      return new $.Vector(touches.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0), touches.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0));
    } else {
      return new $.Vector(touches.pageX, touches.pageY);
    }
  };

  $.fn.offsetv = function () {
    if (this[0] == window) {
      return new $.Vector(window.pageXOffset ? window.pageXOffset : document.documentElement.scrollLeft, window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop);
    } else {
      var offset = this.offset();
      return new $.Vector(offset.left, offset.top);
    }
  };

  $.fn.dimensionsv = function (which) {
    if (this[0] == window || !which) {
      return new $.Vector(this.width(), this.height());
    }
    else {
      return new $.Vector(this[which + "Width"](), this[which + "Height"]());
    }
  };

jquery/event/livehack/livehack.js

  var event = $.event,

helper that finds handlers by type and calls back a function, this is basically handle events - the events object types - an array of event types to look for callback(type, handlerFunc, selector) - a callback selector - an optional selector to filter with, if there, matches by selector if null, matches anything, otherwise, matches with no selector

    findHelper = function (events, types, callback, selector) {
      var t, type, typeHandlers, all, h, handle, namespaces, namespace, match;
      for (t = 0; t < types.length; t++) {
        type = types[t];
        all = type.indexOf(".") < 0;
        if (!all) {
          namespaces = type.split(".");
          type = namespaces.shift();
          namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
        }
        typeHandlers = (events[type] || []).slice(0);

        for (h = 0; h < typeHandlers.length; h++) {
          handle = typeHandlers[h];

          match = (all || namespace.test(handle.namespace));

          if (match) {
            if (selector) {
              if (handle.selector === selector) {
                callback(type, handle.origHandler || handle.handler);
              }
            } else if (selector === null) {
              callback(type, handle.origHandler || handle.handler, handle.selector);
            }
            else if (!handle.selector) {
              callback(type, handle.origHandler || handle.handler);

            }
          }


        }
      }
    };


  event.find = function (el, types, selector) {
    var events = ($._data(el) || {}).events,
      handlers = [],
      t, liver, live;

    if (!events) {
      return handlers;
    }
    findHelper(events, types, function (type, handler) {
      handlers.push(handler);
    }, selector);
    return handlers;
  };

  event.findBySelector = function (el, types) {
    var events = $._data(el).events,
      selectors = {},

adds a handler for a given selector and event

      add = function (selector, event, handler) {
        var select = selectors[selector] || (selectors[selector] = {}),
          events = select[event] || (select[event] = []);
        events.push(handler);
      };

    if (!events) {
      return selectors;
    }

first check live: then check straight binds

    findHelper(events, types, function (type, handler, selector) {
      add(selector || "", type, handler);
    }, null);

    return selectors;
  };
  event.supportTouch = "ontouchend" in document;

  $.fn.respondsTo = function (events) {
    if (!this.length) {
      return false;
    } else {

add default ?

      return event.find(this[0], $.isArray(events) ? events : [events]).length > 0;
    }
  };
  $.fn.triggerHandled = function (event, data) {
    event = (typeof event == "string" ? $.Event(event) : event);
    this.trigger(event, data);
    return event.handled;
  };

  event.setupHelper = function (types, startingEvent, onFirst) {
    if (!onFirst) {
      onFirst = startingEvent;
      startingEvent = null;
    }
    var add = function (handleObj) {
      var bySelector, selector = handleObj.selector || "",
        namespace = handleObj.namespace ? '.' + handleObj.namespace : '';

      if (selector) {
        bySelector = event.find(this, types, selector);
        if (!bySelector.length) {
          $(this).delegate(selector, startingEvent + namespace, onFirst);
        }
      }
      else {

var bySelector = event.find(this, types, selector);

        if (!event.find(this, types, selector).length) {
          event.add(this, startingEvent + namespace, onFirst, {
            selector: selector,
            delegate: this
          });
        }

      }

    },
      remove = function (handleObj) {
        var bySelector, selector = handleObj.selector || "";
        if (selector) {
          bySelector = event.find(this, types, selector);
          if (!bySelector.length) {
            $(this).undelegate(selector, startingEvent, onFirst);
          }
        }
        else {
          if (!event.find(this, types, selector).length) {
            event.remove(this, startingEvent, onFirst, {
              selector: selector,
              delegate: this
            });
          }
        }
      };
    $.each(types, function () {
      event.special[this] = {
        add: add,
        remove: remove,
        setup: function () {},
        teardown: function () {}
      };
    });
  };

jquery/event/reverse/reverse.js

  $.event.reverse = function (name, attributes) {
    var bound = $(),
      count = 0,
      dispatch = $.event.handle || $.event.dispatch;

    $.event.special[name] = {
      setup: function () {

add and sort the resizers array don't add window because it can't be compared easily

        if (this !== window) {
          bound.push(this);
          $.unique(bound);
        }

returns false if the window

        return this !== window;
      },
      teardown: function () {

we shouldn't have to sort

        bound = bound.not(this);

returns false if the window

        return this !== window;
      },
      add: function (handleObj) {
        var origHandler = handleObj.handler;
        handleObj.origHandler = origHandler;

        handleObj.handler = function (ev, data) {
          var isWindow = this === window;
          if (attributes && attributes.handler) {
            var result = attributes.handler.apply(this, arguments);
            if (result === true) {
              return;
            }
          }

if this is the first handler for this event ...

          if (count === 0) {

prevent others from doing what we are about to do

            count++;
            var where = data === false ? ev.target : this

trigger all this element's handlers

            dispatch.call(where, ev, data);
            if (ev.isPropagationStopped()) {
              count--;
              return;
            }

get all other elements within this element that listen to move and trigger their resize events

            var index = bound.index(this),
              length = bound.length,
              child, sub;

if index == -1 it's the window

            while (++index < length && (child = bound[index]) && (isWindow || $.contains(where, child))) {

call the event

              dispatch.call(child, ev, data);

              if (ev.isPropagationStopped()) {

move index until the item is not in the current child

                while (++index < length && (sub = bound[index])) {
                  if (!$.contains(child, sub)) {

set index back one

                    index--;
                    break
                  }
                }
              }
            }

prevent others from responding

            ev.stopImmediatePropagation();
            count--;
          } else {
            handleObj.origHandler.call(this, ev, data);
          }
        }
      }
    };

automatically bind on these

    $([document, window]).bind(name, function () {});

    return $.event.special[name];
  }

jquery/event/drag/core/core.js

  if (!$.event.special.move) {
    $.event.reverse('move');
  }

modify live steal the live handler ....

  var bind = function (object, method) {
    var args = Array.prototype.slice.call(arguments, 2);
    return function () {
      var args2 = [this].concat(args, $.makeArray(arguments));
      return method.apply(object, args2);
    };
  },
    event = $.event,

function to clear the window selection if there is one

    clearSelection = window.getSelection ?
    function () {
      window.getSelection().removeAllRanges()
    } : function () {},

    supportTouch = "ontouchend" in document,

Use touch events or map it to mouse events

    startEvent = supportTouch ? "touchstart" : "mousedown",
    stopEvent = supportTouch ? "touchend" : "mouseup",
    moveEvent = supportTouch ? "touchmove" : "mousemove",

On touchmove events the default (scrolling) event has to be prevented

    preventTouchScroll = function (ev) {
      ev.preventDefault();
    };


  $.Drag = function () {};


  $.extend($.Drag, {
    lowerName: "drag",
    current: null,
    distance: 0,

    mousedown: function (ev, element) {
      var isLeftButton = ev.button === 0 || ev.button == 1,
        doEvent = isLeftButton || supportTouch;

      if (!doEvent || this.current) {
        return;
      }

create Drag

      var drag = new $.Drag(),
        delegate = ev.delegateTarget || element,
        selector = ev.handleObj.selector,
        self = this;
      this.current = drag;

      drag.setup({
        element: element,
        delegate: ev.delegateTarget || element,
        selector: ev.handleObj.selector,
        moved: false,
        _distance: this.distance,
        callbacks: {
          dragdown: event.find(delegate, ["dragdown"], selector),
          draginit: event.find(delegate, ["draginit"], selector),
          dragover: event.find(delegate, ["dragover"], selector),
          dragmove: event.find(delegate, ["dragmove"], selector),
          dragout: event.find(delegate, ["dragout"], selector),
          dragend: event.find(delegate, ["dragend"], selector),
          dragcleanup: event.find(delegate, ["dragcleanup"], selector)
        },
        destroyed: function () {
          self.current = null;
        }
      }, ev);
    }
  });


  $.extend($.Drag.prototype, {
    setup: function (options, ev) {
      $.extend(this, options);

      this.element = $(this.element);
      this.event = ev;
      this.moved = false;
      this.allowOtherDrags = false;
      var mousemove = bind(this, this.mousemove),
        mouseup = bind(this, this.mouseup);
      this._mousemove = mousemove;
      this._mouseup = mouseup;
      this._distance = options.distance ? options.distance : 0;

where the mouse is located

      this.mouseStartPosition = ev.vector();

      $(document).bind(moveEvent, mousemove);
      $(document).bind(stopEvent, mouseup);
      if (supportTouch) {

On touch devices we want to disable scrolling

        $(document).bind(moveEvent, preventTouchScroll);
      }

      if (!this.callEvents('down', this.element, ev)) {
        this.noSelection(this.delegate);

this is for firefox

        clearSelection();
      }
    },



    destroy: function () {

Unbind the mouse handlers attached for dragging

      $(document).unbind(moveEvent, this._mousemove);
      $(document).unbind(stopEvent, this._mouseup);
      if (supportTouch) {

Enable scrolling again for touch devices when the drag is done

        $(document).unbind(moveEvent, preventTouchScroll);
      }

      if (!this.moved) {
        this.event = this.element = null;
      }

      if (!supportTouch) {
        this.selection(this.delegate);
      }
      this.destroyed();
    },
    mousemove: function (docEl, ev) {
      if (!this.moved) {
        var dist = Math.sqrt(Math.pow(ev.pageX - this.event.pageX, 2) + Math.pow(ev.pageY - this.event.pageY, 2));

Don't initialize the drag if it hasn't been moved the minimum distance

        if (dist < this._distance) {
          return false;
        }

Otherwise call init and indicate that the drag has moved

        this.init(this.element, ev);
        this.moved = true;
      }

      this.element.trigger('move', this);
      var pointer = ev.vector();
      if (this._start_position && this._start_position.equals(pointer)) {
        return;
      }
      this.draw(pointer, ev);
    },

    mouseup: function (docEl, event) {

if there is a current, we should call its dragstop

      if (this.moved) {
        this.end(event);
      }
      this.destroy();
    },


    noSelection: function (elm) {
      elm = elm || this.delegate
      document.documentElement.onselectstart = function () {

Disables selection

        return false;
      };
      document.documentElement.unselectable = "on";
      this.selectionDisabled = (this.selectionDisabled ? this.selectionDisabled.add(elm) : $(elm));
      this.selectionDisabled.css('-moz-user-select', '-moz-none');
    },


    selection: function () {
      if (this.selectionDisabled) {
        document.documentElement.onselectstart = function () {};
        document.documentElement.unselectable = "off";
        this.selectionDisabled.css('-moz-user-select', '');
      }
    },

    init: function (element, event) {
      element = $(element);

the element that has been clicked on

      var startElement = (this.movingElement = (this.element = $(element)));

if a mousemove has come after the click if the drag has been cancelled

      this._cancelled = false;
      this.event = event;


      this.mouseElementPosition = this.mouseStartPosition.minus(this.element.offsetv()); //where the mouse is on the Element
      this.callEvents('init', element, event);

Check what they have set and respond accordingly if they canceled

      if (this._cancelled === true) {
        return;
      }

if they set something else as the element

      this.startPosition = startElement != this.movingElement ? this.movingElement.offsetv() : this.currentDelta();

      this.makePositioned(this.movingElement);

Adjust the drag elements z-index to a high value

      this.oldZIndex = this.movingElement.css('zIndex');
      this.movingElement.css('zIndex', 1000);
      if (!this._only && this.constructor.responder) {

calls $.Drop.prototype.compile if there is a drop element

        this.constructor.responder.compile(event, this);
      }
    },
    makePositioned: function (that) {
      var style, pos = that.css('position');

Position properly, set top and left to 0px for Opera

      if (!pos || pos == 'static') {
        style = {
          position: 'relative'
        };

        if (window.opera) {
          style.top = '0px';
          style.left = '0px';
        }
        that.css(style);
      }
    },
    callEvents: function (type, element, event, drop) {
      var i, cbs = this.callbacks[this.constructor.lowerName + type];
      for (i = 0; i < cbs.length; i++) {
        cbs[i].call(element, event, this, drop);
      }
      return cbs.length;
    },

    currentDelta: function () {
      return new $.Vector(parseInt(this.movingElement.css('left'), 10) || 0, parseInt(this.movingElement.css('top'), 10) || 0);
    },

draws the position of the dragmove object

    draw: function (pointer, event) {

only drag if we haven't been cancelled;

      if (this._cancelled) {
        return;
      }
      clearSelection();

the offset between the mouse pointer and the representative that the user asked for

      this.location = pointer.minus(this.mouseElementPosition);

call move events

      this.move(event);
      if (this._cancelled) {
        return;
      }
      if (!event.isDefaultPrevented()) {
        this.position(this.location);
      }

fill in

      if (!this._only && this.constructor.responder) {
        this.constructor.responder.show(pointer, this, event);
      }
    },

    position: function (newOffsetv) { //should draw it on the page
      var style, dragged_element_css_offset = this.currentDelta(),

the drag element's current left + top css attributes the vector between the movingElement's page and css positions this can be thought of as the original offset

        dragged_element_position_vector = this.movingElement.offsetv().minus(dragged_element_css_offset);
      this.required_css_position = newOffsetv.minus(dragged_element_position_vector);

      this.offsetv = newOffsetv;
      style = this.movingElement[0].style;
      if (!this._cancelled && !this._horizontal) {
        style.top = this.required_css_position.top() + "px";
      }
      if (!this._cancelled && !this._vertical) {
        style.left = this.required_css_position.left() + "px";
      }
    },
    move: function (event) {
      this.callEvents('move', this.element, event);
    },
    over: function (event, drop) {
      this.callEvents('over', this.element, event, drop);
    },
    out: function (event, drop) {
      this.callEvents('out', this.element, event, drop);
    },

    end: function (event) {

If canceled do nothing

      if (this._cancelled) {
        return;
      }

notify the responder - usually a $.Drop instance

      if (!this._only && this.constructor.responder) {
        this.constructor.responder.end(event, this);
      }

      this.callEvents('end', this.element, event);

      if (this._revert) {
        var self = this;

animate moving back to original position

        this.movingElement.animate({
          top: this.startPosition.top() + "px",
          left: this.startPosition.left() + "px"
        }, function () {
          self.cleanup.apply(self, arguments);
        });
      }
      else {
        this.cleanup(event);
      }
      this.event = null;
    },

    cleanup: function (event) {
      this.movingElement.css({
        zIndex: this.oldZIndex
      });
      if (this.movingElement[0] !== this.element[0] && !this.movingElement.has(this.element[0]).length && !this.element.has(this.movingElement[0]).length) {
        this.movingElement.css({
          display: 'none'
        });
      }
      if (this._removeMovingElement) {

Remove the element when using drag.ghost()

        this.movingElement.remove();
      }

      if (event) {
        this.callEvents('cleanup', this.element, event);
      }

      this.movingElement = this.element = this.event = null;
    },

    cancel: function () {
      this._cancelled = true;
      if (!this._only && this.constructor.responder) {

clear the drops

        this.constructor.responder.clear(this.event.vector(), this, this.event);
      }
      this.destroy();

    },

    ghost: function (parent) {

create a ghost by cloning the source element and attach the clone to the dom after the source element

      var ghost = this.movingElement.clone().css('position', 'absolute');
      if (parent) {
        $(parent).append(ghost);
      } else {
        $(this.movingElement).after(ghost)
      }
      ghost.width(this.movingElement.width()).height(this.movingElement.height());

put the ghost in the right location ...

      ghost.offset(this.movingElement.offset())

store the original element and make the ghost the dragged element

      this.movingElement = ghost;
      this.noSelection(ghost)
      this._removeMovingElement = true;
      return ghost;
    },

    representative: function (element, offsetX, offsetY) {
      this._offsetX = offsetX || 0;
      this._offsetY = offsetY || 0;

      var p = this.mouseStartPosition;

Just set the representative as the drag element

      this.movingElement = $(element);
      this.movingElement.css({
        top: (p.y() - this._offsetY) + "px",
        left: (p.x() - this._offsetX) + "px",
        display: 'block',
        position: 'absolute'
      }).show();
      this.noSelection(this.movingElement)
      this.mouseElementPosition = new $.Vector(this._offsetX, this._offsetY);
      return this;
    },

    revert: function (val) {
      this._revert = val === undefined ? true : val;
      return this;
    },

    vertical: function () {
      this._vertical = true;
      return this;
    },

    horizontal: function () {
      this._horizontal = true;
      return this;
    },

    only: function (only) {
      return (this._only = (only === undefined ? true : only));
    },


    distance: function (val) {
      if (val !== undefined) {
        this._distance = val;
        return this;
      } else {
        return this._distance
      }
    }
  });

  event.setupHelper([

  'dragdown',

  'draginit',

  'dragover',

  'dragmove',

  'dragout',

  'dragend',

  'dragcleanup'], startEvent, function (e) {
    $.Drag.mousedown.call($.Drag, e, this);
  });

jquery/event/drag/step/step.js

  var round = function (x, m) {
    return Math.round(x / m) * m;
  }

  $.Drag.prototype.

  step = function (amount, container, center) {

on draws ... make sure this happens

    if (typeof amount == 'number') {
      amount = {
        x: amount,
        y: amount
      }
    }
    container = container || $(document.body);
    this._step = amount;

    var styles = container.styles("borderTopWidth", "paddingTop", "borderLeftWidth", "paddingLeft");
    var top = parseInt(styles.borderTopWidth) + parseInt(styles.paddingTop),
      left = parseInt(styles.borderLeftWidth) + parseInt(styles.paddingLeft);

    this._step.offset = container.offsetv().plus(left, top);
    this._step.center = center;
    return this;
  };

  (function () {
    var oldPosition = $.Drag.prototype.position;
    $.Drag.prototype.position = function (offsetPositionv) {

adjust requiredcssposition accordingly

      if (this._step) {
        var step = this._step,
          center = step.center && step.center.toLowerCase(),
          movingSize = this.movingElement.dimensionsv('outer'),
          lot = step.offset.top() - (center && center != 'x' ? movingSize.height() / 2 : 0),
          lof = step.offset.left() - (center && center != 'y' ? movingSize.width() / 2 : 0);

        if (this._step.x) {
          offsetPositionv.left(Math.round(lof + round(offsetPositionv.left() - lof, this._step.x)))
        }
        if (this._step.y) {
          offsetPositionv.top(Math.round(lot + round(offsetPositionv.top() - lot, this._step.y)))
        }
      }

      oldPosition.call(this, offsetPositionv)
    }
  })();

jquery/event/drag/limit/limit.js

  $.Drag.prototype

  .limit = function (container, center) {

on draws ... make sure this happens

    var styles = container.styles('borderTopWidth', 'paddingTop', 'borderLeftWidth', 'paddingLeft'),
      paddingBorder = new $.Vector(
      parseInt(styles.borderLeftWidth, 10) + parseInt(styles.paddingLeft, 10) || 0, parseInt(styles.borderTopWidth, 10) + parseInt(styles.paddingTop, 10) || 0);

    this._limit = {
      offset: container.offsetv().plus(paddingBorder),
      size: container.dimensionsv(),
      center: center === true ? 'both' : center
    };
    return this;
  };

  var oldPosition = $.Drag.prototype.position;
  $.Drag.prototype.position = function (offsetPositionv) {

adjust requiredcssposition accordingly

    if (this._limit) {
      var limit = this._limit,
        center = limit.center && limit.center.toLowerCase(),
        movingSize = this.movingElement.dimensionsv('outer'),
        halfHeight = center && center != 'x' ? movingSize.height() / 2 : 0,
        halfWidth = center && center != 'y' ? movingSize.width() / 2 : 0,
        lot = limit.offset.top(),
        lof = limit.offset.left(),
        height = limit.size.height(),
        width = limit.size.width();

check if we are out of bounds ... above

      if (offsetPositionv.top() + halfHeight < lot) {
        offsetPositionv.top(lot - halfHeight);
      }

below

      if (offsetPositionv.top() + movingSize.height() - halfHeight > lot + height) {
        offsetPositionv.top(lot + height - movingSize.height() + halfHeight);
      }

left

      if (offsetPositionv.left() + halfWidth < lof) {
        offsetPositionv.left(lof - halfWidth);
      }

right

      if (offsetPositionv.left() + movingSize.width() - halfWidth > lof + width) {
        offsetPositionv.left(lof + width - movingSize.left() + halfWidth);
      }
    }

    oldPosition.call(this, offsetPositionv);
  };

jquery/event/drop/drop.js

  var event = $.event;

  var eventNames = [

  "dropover",

  "dropon",

  "dropout",

  "dropinit",

  "dropmove",

  "dropend"];


  $.Drop = function (callbacks, element) {
    $.extend(this, callbacks);
    this.element = $(element);
  }

add the elements ...

  $.each(eventNames, function () {
    event.special[this] = {
      add: function (handleObj) {

add this element to the compiles list

        var el = $(this),
          current = (el.data("dropEventCount") || 0);
        el.data("dropEventCount", current + 1)
        if (current == 0) {
          $.Drop.addElement(this);
        }
      },
      remove: function () {
        var el = $(this),
          current = (el.data("dropEventCount") || 0);
        el.data("dropEventCount", current - 1)
        if (current <= 1) {
          $.Drop.removeElement(this);
        }
      }
    }
  });

  $.extend($.Drop, {

    lowerName: "drop",
    _rootElements: [],

elements that are listening for drops

    _elements: $(),

elements that can be dropped on

    last_active: [],
    endName: "dropon",

adds an element as a 'root' element this element might have events that we need to respond to

    addElement: function (el) {

check other elements

      for (var i = 0; i < this._rootElements.length; i++) {
        if (el == this._rootElements[i]) return;
      }
      this._rootElements.push(el);
    },
    removeElement: function (el) {
      for (var i = 0; i < this._rootElements.length; i++) {
        if (el == this._rootElements[i]) {
          this._rootElements.splice(i, 1)
          return;
        }
      }
    },

    sortByDeepestChild: function (a, b) {

Use jQuery.compare to compare two elements

      var compare = a.element.compare(b.element);
      if (compare & 16 || compare & 4) return 1;
      if (compare & 8 || compare & 2) return -1;
      return 0;
    },

    isAffected: function (point, moveable, responder) {
      return ((responder.element != moveable.element) && (responder.element.within(point[0], point[1], responder._cache).length == 1));
    },

    deactivate: function (responder, mover, event) {
      mover.out(event, responder)
      responder.callHandlers(this.lowerName + 'out', responder.element[0], event, mover)
    },

    activate: function (responder, mover, event) { //this is where we should call over
      mover.over(event, responder)
      responder.callHandlers(this.lowerName + 'over', responder.element[0], event, mover);
    },
    move: function (responder, mover, event) {
      responder.callHandlers(this.lowerName + 'move', responder.element[0], event, mover)
    },

    compile: function (event, drag) {

if we called compile w/o a current drag

      if (!this.dragging && !drag) {
        return;
      } else if (!this.dragging) {
        this.dragging = drag;
        this.last_active = [];
      }
      var el, drops, selector, dropResponders, newEls = [],
        dragging = this.dragging;

go to each root element and look for drop elements

      for (var i = 0; i < this._rootElements.length; i++) { //for each element
        el = this._rootElements[i]

gets something like {"": ["dropinit"], ".foo" : ["dropover","dropmove"] }

        var drops = $.event.findBySelector(el, eventNames)

get drop elements by selector

        for (selector in drops) {
          dropResponders = selector ? jQuery(selector, el) : [el];

for each drop element

          for (var e = 0; e < dropResponders.length; e++) {

add the callbacks to the element's Data there already might be data, so we merge it

            if (this.addCallbacks(dropResponders[e], drops[selector], dragging)) {
              newEls.push(dropResponders[e])
            };
          }
        }
      }

once all callbacks are added, call init on everything ...

      this.add(newEls, event, dragging)
    },

adds the drag callbacks object to the element or merges other callbacks ... returns true or false if the element is new ... onlyNew lets only new elements add themselves

    addCallbacks: function (el, callbacks, onlyNew) {
      var origData = $.data(el, "_dropData");
      if (!origData) {
        $.data(el, "_dropData", new $.Drop(callbacks, el));
        return true;
      } else if (!onlyNew) {
        var origCbs = origData;

merge data

        for (var eventName in callbacks) {
          origCbs[eventName] = origCbs[eventName] ? origCbs[eventName].concat(callbacks[eventName]) : callbacks[eventName];
        }
        return false;
      }
    },

calls init on each element's drags. if its cancelled it's removed adds to the current elements ...

    add: function (newEls, event, drag, dragging) {
      var i = 0,
        drop;

      while (i < newEls.length) {
        drop = $.data(newEls[i], "_dropData");
        drop.callHandlers(this.lowerName + 'init', newEls[i], event, drag)
        if (drop._canceled) {
          newEls.splice(i, 1)
        } else {
          i++;
        }
      }
      this._elements.push.apply(this._elements, newEls)
    },
    show: function (point, moveable, event) {
      var element = moveable.element;
      if (!this._elements.length) return;

      var respondable, affected = [],
        propagate = true,
        i = 0,
        j, la, toBeActivated, aff, oldLastActive = this.last_active,
        responders = [],
        self = this,
        drag;

what's still affected ... we can also move element out here

      while (i < this._elements.length) {
        drag = $.data(this._elements[i], "_dropData");

        if (!drag) {
          this._elements.splice(i, 1)
        }
        else {
          i++;
          if (self.isAffected(point, moveable, drag)) {
            affected.push(drag);
          }
        }
      }

we should only trigger on lowest children

      affected.sort(this.sortByDeepestChild);
      event.stopRespondPropagate = function () {
        propagate = false;
      }

      toBeActivated = affected.slice();

all these will be active

      this.last_active = affected;

deactivate everything in last_active that isn't active

      for (j = 0; j < oldLastActive.length; j++) {
        la = oldLastActive[j];
        i = 0;
        while ((aff = toBeActivated[i])) {
          if (la == aff) {
            toBeActivated.splice(i, 1);
            break;
          } else {
            i++;
          }
        }
        if (!aff) {
          this.deactivate(la, moveable, event);
        }
        if (!propagate) return;
      }
      for (var i = 0; i < toBeActivated.length; i++) {
        this.activate(toBeActivated[i], moveable, event);
        if (!propagate) return;
      }

activate everything in affected that isn't in last_active

      for (i = 0; i < affected.length; i++) {
        this.move(affected[i], moveable, event);

        if (!propagate) return;
      }
    },
    end: function (event, moveable) {
      var la, endName = this.lowerName + 'end',
        onEvent = $.Event(this.endName, event),
        dropData;

call dropon go through the actives ... if you are over one, call dropped on it

      for (var i = 0; i < this.last_active.length; i++) {
        la = this.last_active[i]
        if (this.isAffected(event.vector(), moveable, la) && la[this.endName]) {
          la.callHandlers(this.endName, null, onEvent, moveable);
        }

        if (onEvent.isPropagationStopped()) {
          break;
        }
      }

call dropend

      for (var r = 0; r < this._elements.length; r++) {
        dropData = $.data(this._elements[r], "_dropData");
        dropData && dropData.callHandlers(endName, null, event, moveable);
      }

      this.clear();
    },

    clear: function () {
      this._elements.each(function () {

remove temporary drop data

        $.removeData(this, "_dropData")
      })
      this._elements = $();
      delete this.dragging;
    }
  })
  $.Drag.responder = $.Drop;

  $.extend($.Drop.prototype, {

    callHandlers: function (method, el, ev, drag) {
      var length = this[method] ? this[method].length : 0
      for (var i = 0; i < length; i++) {
        this[method][i].call(el || this.element[0], ev, this, drag)
      }
    },

    cache: function (value) {
      this._cache = value != null ? value : true;
    },

    cancel: function () {
      this._canceled = true;
    }
  });

jquery/event/drag/scroll/scroll.js

needs drop to determine if respondable

  $.Drag.prototype.

  scrolls = function (elements, options) {
    var elements = $(elements);

    for (var i = 0; i < elements.length; i++) {
      this.constructor.responder._elements.push(elements.eq(i).data("_dropData", new $.Scrollable(elements[i], options))[0])
    }
  },

  $.Scrollable = function (element, options) {
    this.element = jQuery(element);
    this.options = $.extend({

when we should start scrolling

      distance: 30,

how far we should move

      delta: function (diff, distance) {
        return (distance - diff) / 2;
      },
      direction: "xy"
    }, options);
    this.x = this.options.direction.indexOf("x") != -1;
    this.y = this.options.direction.indexOf("y") != -1;
  }
  $.extend($.Scrollable.prototype, {
    init: function (element) {
      this.element = jQuery(element);
    },
    callHandlers: function (method, el, ev, drag) {
      this[method](el || this.element[0], ev, this, drag)
    },
    dropover: function () {

    },
    dropon: function () {
      this.clear_timeout();
    },
    dropout: function () {
      this.clear_timeout();
    },
    dropinit: function () {

    },
    dropend: function () {},
    clear_timeout: function () {
      if (this.interval) {
        clearTimeout(this.interval)
        this.interval = null;
      }
    },
    distance: function (diff) {
      return (30 - diff) / 2;
    },
    dropmove: function (el, ev, drop, drag) {

if we were about to call a move, clear it.

      this.clear_timeout();

position of the mouse

      var mouse = ev.vector(),

get the object we are going to get the boundries of

        location_object = $(el == document.documentElement ? window : el),

get the dimension and location of that object

        dimensions = location_object.dimensionsv('outer'),
        position = location_object.offsetv(),

how close our mouse is to the boundries

        bottom = position.y() + dimensions.y() - mouse.y(),
        top = mouse.y() - position.y(),
        right = position.x() + dimensions.x() - mouse.x(),
        left = mouse.x() - position.x(),

how far we should scroll

        dx = 0,
        dy = 0,
        distance = this.options.distance;

check if we should scroll

      if (bottom < distance && this.y) {
        dy = this.options.delta(bottom, distance);
      } else if (top < distance && this.y) {
        dy = -this.options.delta(top, distance);
      }

      if (right < distance && this.options && this.x) {
        dx = this.options.delta(right, distance);
      } else if (left < distance && this.x) {
        dx = -this.options.delta(left, distance);
      }

if we should scroll

      if (dx || dy) {

set a timeout that will create a mousemove on that object

        var self = this;
        this.interval = setTimeout(function () {
          self.move($(el), drag.movingElement, dx, dy, ev, ev.clientX, ev.clientY, ev.screenX, ev.screenY)
        }, 15)
      }
    },

    move: function (scroll_element, drag_element, dx, dy, ev) {
      scroll_element.scrollTop(scroll_element.scrollTop() + dy);
      scroll_element.scrollLeft(scroll_element.scrollLeft() + dx);

      drag_element.trigger(
      $.event.fix({
        type: "mousemove",
        clientX: ev.clientX,
        clientY: ev.clientY,
        screenX: ev.screenX,
        screenY: ev.screenY,
        pageX: ev.pageX,
        pageY: ev.pageY
      }))

drag_element.synthetic('mousemove',{clientX: x, clientY: y, screenX: sx, screenY: sy})

    }
  })

jquery/event/drag/drag.js

jquery/event/fastfix/fastfix.js

http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html https://gist.github.com/2377196 IE 8 has Object.defineProperty but it only defines DOM Nodes. According to http://kangax.github.com/es5-compat-table/#define-property-ie-note All browser that have Object.defineProperties also support Object.defineProperty properly

  if (Object.defineProperties) {
    var

Use defineProperty on an object to set the value and return it

    set = function (obj, prop, val) {
      if (val !== undefined) {
        Object.defineProperty(obj, prop, {
          value: val
        });
      }
      return val;
    },

special converters

      special = {
        pageX: function (original) {
          if (!original) {
            return;
          }

          var eventDoc = this.target.ownerDocument || document;
          doc = eventDoc.documentElement;
          body = eventDoc.body;
          return original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
        },
        pageY: function (original) {
          if (!original) {
            return;
          }

          var eventDoc = this.target.ownerDocument || document;
          doc = eventDoc.documentElement;
          body = eventDoc.body;
          return original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
        },
        relatedTarget: function (original) {
          if (!original) {
            return;
          }

          return original.fromElement === this.target ? original.toElement : original.fromElement;
        },
        metaKey: function (originalEvent) {
          if (!originalEvent) {
            return;
          }
          return originalEvent.ctrlKey;
        },
        which: function (original) {
          if (!original) {
            return;
          }

          return original.charCode != null ? original.charCode : original.keyCode;
        }
      };

Get all properties that should be mapped

    $.each($.event.keyHooks.props.concat($.event.mouseHooks.props).concat($.event.props), function (i, prop) {
      if (prop !== "target") {
        (function () {
          Object.defineProperty($.Event.prototype, prop, {
            get: function () {

get the original value, undefined when there is no original event

              var originalValue = this.originalEvent && this.originalEvent[prop];

overwrite getter lookup

              return this['_' + prop] !== undefined ? this['_' + prop] : set(this, prop,

if we have a special function and no value

              special[prop] && originalValue === undefined ?

call the special function

              special[prop].call(this, this.originalEvent) :

use the original value

              originalValue)
            },
            set: function (newValue) {

Set the property with underscore prefix

              this['_' + prop] = newValue;
            }
          });
        })();
      }
    });

    $.event.fix = function (event) {
      if (event[$.expando]) {
        return event;
      }

Create a jQuery event with at minimum a target and type set

      var originalEvent = event,
        event = $.Event(originalEvent);
      event.target = originalEvent.target;

Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)

      if (!event.target) {
        event.target = originalEvent.srcElement || document;
      }

Target should not be a text node (#504, Safari)

      if (event.target.nodeType === 3) {
        event.target = event.target.parentNode;
      }

      return event;
    }
  }

jquery/event/hover/hover.js

  $.Hover = function () {
    this._delay = $.Hover.delay;
    this._distance = $.Hover.distance;
    this._leave = $.Hover.leave
  };

  $.extend($.Hover, {

    delay: 100,

    distance: 10,
    leave: 0
  })


  $.extend($.Hover.prototype, {

    delay: function (delay) {
      this._delay = delay;
      return this;
    },

    distance: function (distance) {
      this._distance = distance;
      return this;
    },

    leave: function (leave) {
      this._leave = leave;
      return this;
    }
  })
  var event = $.event,
    handle = event.handle,
    onmouseenter = function (ev) {

now start checking mousemoves to update location

      var delegate = ev.delegateTarget || ev.currentTarget;
      var selector = ev.handleObj.selector;
      var pending = $.data(delegate, "_hover" + selector);

prevents another mouseenter until current has run its course

      if (pending) {

Under some circumstances, mouseleave may never fire (e.g., the element is removed while hovered) so if we've entered another element, wait the leave time, then force it to release.

        if (!pending.forcing) {
          pending.forcing = true;
          clearTimeout(pending.leaveTimer);
          var leaveTime = pending.leaving ? Math.max(0, pending.hover.leave - (new Date() - pending.leaving)) : pending.hover.leave;
          var self = this;

          setTimeout(function () {
            pending.callHoverLeave();
            onmouseenter.call(self, ev);
          }, leaveTime);
        }
        return;
      }
      var loc = {
        pageX: ev.pageX,
        pageY: ev.pageY
      },

The current distance

        dist = 0,

Timer that checks for the distance travelled

        timer, enteredEl = this,

If we are hovered

        hovered = false,

The previous event

        lastEv = ev,

The $.Hover instance passed to events

        hover = new $.Hover(),

timer if hover.leave has been called

        leaveTimer,

Callback for triggering hoverleave

        callHoverLeave = function () {
          $.each(event.find(delegate, ["hoverleave"], selector), function () {
            this.call(enteredEl, ev, hover)
          })
          cleanUp();
        },
        mousemove = function (ev) {
          clearTimeout(leaveTimer);

Update the distance and location

          dist += Math.pow(ev.pageX - loc.pageX, 2) + Math.pow(ev.pageY - loc.pageY, 2);
          loc = {
            pageX: ev.pageX,
            pageY: ev.pageY
          }
          lastEv = ev
        },
        mouseleave = function (ev) {
          clearTimeout(timer);
          if (hovered) {

go right away

            if (hover._leave === 0) {
              callHoverLeave();
            } else {
              clearTimeout(leaveTimer);

leave the hover after the time set in hover.leave(time)

              pending.leaving = new Date();
              leaveTimer = pending.leaveTimer = setTimeout(function () {
                callHoverLeave();
              }, hover._leave)
            }
          } else {
            cleanUp();
          }
        },
        cleanUp = function () {

Unbind all events and data

          $(enteredEl).unbind("mouseleave", mouseleave)
          $(enteredEl).unbind("mousemove", mousemove);
          $.removeData(delegate, "_hover" + selector)
        },
        hoverenter = function () {
          $.each(event.find(delegate, ["hoverenter"], selector), function () {
            this.call(enteredEl, lastEv, hover)
          })
          hovered = true;
        };
      pending = {
        callHoverLeave: callHoverLeave,
        hover: hover
      };
      $.data(delegate, "_hover" + selector, pending);

Bind the mousemove event

      $(enteredEl).bind("mousemove", mousemove).bind("mouseleave", mouseleave);

call hoverinit for each element with the hover instance

      $.each(event.find(delegate, ["hoverinit"], selector), function () {
        this.call(enteredEl, ev, hover)
      })

      if (hover._delay === 0) {
        hoverenter();
      } else {
        timer = setTimeout(function () {

check that we aren't moving around

          if (dist < hover._distance && $(enteredEl).queue().length == 0) {
            hoverenter();
            return;
          } else {

Reset distance and timer

            dist = 0;
            timer = setTimeout(arguments.callee, hover._delay)
          }
        }, hover._delay);
      }
    };

Attach events

  event.setupHelper([

  "hoverinit",

  "hoverenter",

  "hoverleave",

  "hovermove"], "mouseenter", onmouseenter)

jquery/event/key/key.js

copied from jQuery 1.8.3

  var uaMatch = function (ua) {
    ua = ua.toLowerCase();

    var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];

    return {
      browser: match[1] || "",
      version: match[2] || "0"
    };
  }

  var keymap = {},
    reverseKeyMap = {},
    currentBrowser = uaMatch(navigator.userAgent).browser;


  $.event.key = function (browser, map) {
    if (browser === undefined) {
      return keymap;
    }

    if (map === undefined) {
      map = browser;
      browser = currentBrowser;
    }

extend the keymap

    if (!keymap[browser]) {
      keymap[browser] = {};
    }
    $.extend(keymap[browser], map);

and also update the reverse keymap

    if (!reverseKeyMap[browser]) {
      reverseKeyMap[browser] = {};
    }
    for (var name in map) {
      reverseKeyMap[browser][map[name]] = name;
    }
  };

  $.event.key({

backspace

    '\b': '8',

tab

    '\t': '9',

enter

    '\r': '13',

special

    'shift': '16',
    'ctrl': '17',
    'alt': '18',

others

    'pause-break': '19',
    'caps': '20',
    'escape': '27',
    'num-lock': '144',
    'scroll-lock': '145',
    'print': '44',

navigation

    'page-up': '33',
    'page-down': '34',
    'end': '35',
    'home': '36',
    'left': '37',
    'up': '38',
    'right': '39',
    'down': '40',
    'insert': '45',
    'delete': '46',

normal characters

    ' ': '32',
    '0': '48',
    '1': '49',
    '2': '50',
    '3': '51',
    '4': '52',
    '5': '53',
    '6': '54',
    '7': '55',
    '8': '56',
    '9': '57',
    'a': '65',
    'b': '66',
    'c': '67',
    'd': '68',
    'e': '69',
    'f': '70',
    'g': '71',
    'h': '72',
    'i': '73',
    'j': '74',
    'k': '75',
    'l': '76',
    'm': '77',
    'n': '78',
    'o': '79',
    'p': '80',
    'q': '81',
    'r': '82',
    's': '83',
    't': '84',
    'u': '85',
    'v': '86',
    'w': '87',
    'x': '88',
    'y': '89',
    'z': '90',

normal-characters, numpad

    'num0': '96',
    'num1': '97',
    'num2': '98',
    'num3': '99',
    'num4': '100',
    'num5': '101',
    'num6': '102',
    'num7': '103',
    'num8': '104',
    'num9': '105',
    '*': '106',
    '+': '107',
    '-': '109',
    '.': '110',

normal-characters, others

    '/': '111',
    ';': '186',
    '=': '187',
    ',': '188',
    '-': '189',
    '.': '190',
    '/': '191',
    '`': '192',
    '[': '219',
    '\\': '220',
    ']': '221',
    "'": '222',

ignore these, you shouldn't use them

    'left window key': '91',
    'right window key': '92',
    'select key': '93',


    'f1': '112',
    'f2': '113',
    'f3': '114',
    'f4': '115',
    'f5': '116',
    'f6': '117',
    'f7': '118',
    'f8': '119',
    'f9': '120',
    'f10': '121',
    'f11': '122',
    'f12': '123'
  });


  $.Event.prototype.keyName = function () {
    var event = this,
      test = /\w/,

It can be either keyCode or charCode. Look both cases up in the reverse key map and converted to a string

      key_Key = reverseKeyMap[currentBrowser][(event.keyCode || event.which) + ""],
      char_Key = String.fromCharCode(event.keyCode || event.which),
      key_Char = event.charCode && reverseKeyMap[currentBrowser][event.charCode + ""],
      char_Char = event.charCode && String.fromCharCode(event.charCode);

    if (char_Char && test.test(char_Char)) {

string representation of event.charCode

      return char_Char.toLowerCase()
    }
    if (key_Char && test.test(key_Char)) {

reverseKeyMap representation of event.charCode

      return char_Char.toLowerCase()
    }
    if (char_Key && test.test(char_Key)) {

string representation of event.keyCode

      return char_Key.toLowerCase()
    }
    if (key_Key && test.test(key_Key)) {

reverseKeyMap representation of event.keyCode

      return key_Key.toLowerCase()
    }

    if (event.type == 'keypress') {

keypress doesn't capture everything

      return event.keyCode ? String.fromCharCode(event.keyCode) : String.fromCharCode(event.which)
    }

    if (!event.keyCode && event.which) {

event.which

      return String.fromCharCode(event.which)
    }

default

    return reverseKeyMap[currentBrowser][event.keyCode + ""]
  }

jquery/event/pause/pause.js

  var current, rnamespaces = /\.(.*)$/,
    returnFalse = function () {
      return false
    },
    returnTrue = function () {
      return true
    };

  $.Event.prototype.isPaused = returnFalse

  $.Event.prototype.pause = function () {

stop the event from continuing temporarily keep the current state of the event ...

    this.pausedState = {
      isDefaultPrevented: this.isDefaultPrevented() ? returnTrue : returnFalse,
      isPropagationStopped: this.isPropagationStopped() ? returnTrue : returnFalse
    };

    this.stopImmediatePropagation();
    this.preventDefault();
    this.isPaused = returnTrue;
  };

  $.Event.prototype.resume = function () {

temporarily remove all event handlers of this type

    var handleObj = this.handleObj,
      currentTarget = this.currentTarget;

temporarily overwrite special handle

    var origType = $.event.special[handleObj.origType],
      origHandle = origType && origType.handle;

    if (!origType) {
      $.event.special[handleObj.origType] = {};
    }
    $.event.special[handleObj.origType].handle = function (ev) {

remove this once we have passed the handleObj

      if (ev.handleObj === handleObj && ev.currentTarget === currentTarget) {
        if (!origType) {
          delete $.event.special[handleObj.origType];
        } else {
          $.event.special[handleObj.origType].handle = origHandle;
        }
      }
    }
    delete this.pausedState;

reset stuff

    this.isPaused = this.isImmediatePropagationStopped = returnFalse;

    if (!this.isPropagationStopped()) {

fire the event again, no events will get fired until same currentTarget / handler

      $.event.trigger(this, [], this.target);
    }

  };

jquery/event/resize/resize.js

  var

bind on the window window resizes to happen

  win = $(window),
    windowWidth = 0,
    windowHeight = 0,
    timer;

  $(function () {
    windowWidth = win.width();
    windowHeight = win.height();
  });

  $.event.reverse('resize', {
    handler: function (ev, data) {
      var isWindow = this === window;

if we are the window and a real resize has happened then we check if the dimensions actually changed if they did, we will wait a brief timeout and trigger resize on the window this is for IE, to prevent window resize 'infinate' loop issues

      if (isWindow && ev.originalEvent) {
        var width = win.width(),
          height = win.height();

        if ((width != windowWidth || height != windowHeight)) {

update the new dimensions

          windowWidth = width;
          windowHeight = height;
          clearTimeout(timer)
          timer = setTimeout(function () {
            win.trigger("resize");
          }, 1);

        }
        return true;
      }
    }
  });

jquery/event/swipe/swipe.js

  var isPhantom = /Phantom/.test(navigator.userAgent),
    supportTouch = !isPhantom && "ontouchend" in document,
    scrollEvent = "touchmove scroll",

Use touch events or map it to mouse events

    touchStartEvent = supportTouch ? "touchstart" : "mousedown",
    touchStopEvent = supportTouch ? "touchend" : "mouseup",
    touchMoveEvent = supportTouch ? "touchmove" : "mousemove",
    data = function (event) {
      var d = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
      return {
        time: (new Date).getTime(),
        coords: [d.pageX, d.pageY],
        origin: $(event.target)
      };
    };

  var swipe = $.event.swipe = {

    delay: 500,

    max: 320,

    min: 30
  };

  $.event.setupHelper([

  "swipe",

  'swipeleft',

  'swiperight',

  'swipeup',

  'swipedown'], touchStartEvent, function (ev) {
    var

update with data when the event was started

    start = data(ev),
      stop, delegate = ev.delegateTarget || ev.currentTarget,
      selector = ev.handleObj.selector,
      entered = this;

    function moveHandler(event) {
      if (!start) {
        return;
      }

update stop with the data from the current event

      stop = data(event);

prevent scrolling

      if (Math.abs(start.coords[0] - stop.coords[0]) > 10) {
        event.preventDefault();
      }
    };

Attach to the touch move events

    $(document.documentElement).bind(touchMoveEvent, moveHandler).one(touchStopEvent, function (event) {
      $(this).unbind(touchMoveEvent, moveHandler);

if start and stop contain data figure out if we have a swipe event

      if (start && stop) {

calculate the distance between start and stop data

        var deltaX = Math.abs(start.coords[0] - stop.coords[0]),
          deltaY = Math.abs(start.coords[1] - stop.coords[1]),
          distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

check if the delay and distance are matched

        if (stop.time - start.time < swipe.delay && distance >= swipe.min && distance <= swipe.max) {
          var events = ['swipe'];

check if we moved horizontally

          if (deltaX >= swipe.min && deltaY < swipe.min) {

based on the x coordinate check if we moved left or right

            events.push(start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight");
          } else

check if we moved vertically

          if (deltaY >= swipe.min && deltaX < swipe.min) {

based on the y coordinate check if we moved up or down

            events.push(start.coords[1] < stop.coords[1] ? "swipedown" : "swipeup");
          }

trigger swipe events on this guy

          $.each($.event.find(delegate, events, selector), function () {
            this.call(entered, ev, {
              start: start,
              end: stop
            })
          })

        }
      }

reset start and stop

      start = stop = undefined;
    })
  });

})(this, jQuery);