diff --git a/dom/animate/animate.js b/dom/animate/animate.js index 148e4216..34f0b447 100644 --- a/dom/animate/animate.js +++ b/dom/animate/animate.js @@ -1,324 +1,324 @@ -steal('jquery', 'jquery/dom/styles', function ($) { - - // 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) { /* For Safari */ - 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; - }; - - /** - * @function $.fn.animate - * @parent $.animate - * - * Animate CSS properties using native CSS animations, if possible. - * Uses the original [$.fn.animate()](http://api.$.com/animate/) otherwise. - * - * @param {Object} props The CSS properties to animate - * @param {Integer|String|Object} [speed=400] The animation duration in ms. - * Will use $.fn.animate if a string or object is passed - * @param {Function} [callback] A callback to execute once the animation is complete - * @return {jQuery} The jQuery element - */ - $.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 = jQuery.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; - }; - - return $; -}); +steal('jquery', 'jquery/dom/styles', function ($) { + + // 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) { /* For Safari */ + 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; + }; + + /** + * @function $.fn.animate + * @parent $.animate + * + * Animate CSS properties using native CSS animations, if possible. + * Uses the original [$.fn.animate()](http://api.$.com/animate/) otherwise. + * + * @param {Object} props The CSS properties to animate + * @param {Integer|String|Object} [speed=400] The animation duration in ms. + * Will use $.fn.animate if a string or object is passed + * @param {Function} [callback] A callback to execute once the animation is complete + * @return {jQuery} The jQuery element + */ + $.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; + }; + + return $; +}); diff --git a/dom/closest/closest.js b/dom/closest/closest.js index 4460647b..9adc3003 100644 --- a/dom/closest/closest.js +++ b/dom/closest/closest.js @@ -1,50 +1,50 @@ -/** - * @add jQuery.fn - */ -steal('jquery', function($) { - /** - * @function closest - * @parent dom - * @plugin jquery/dom/closest - * Overwrites closest to allow open > selectors. This allows controller - * actions such as: - * - * ">li click" : function( el, ev ) { ... } - */ - var oldClosest = jQuery.fn.closest; - jQuery.fn.closest = function(selectors, context){ - var rooted = {}, res, result, thing, i, j, selector, rootedIsEmpty = true, selector, selectorsArr = selectors; - if(typeof selectors == "string") selectorsArr = [selectors]; - - $.each(selectorsArr, function(i, selector){ - if(selector.indexOf(">") == 0 ){ - if(selector.indexOf(" ") != -1){ - throw " closest does not work with > followed by spaces!" - } - rooted[( selectorsArr[i] = selector.substr(1) )] = selector; - if(typeof selectors == "string") selectors = selector.substr(1); - rootedIsEmpty = false; - } - }) - - res = oldClosest.call(this, selectors, context); - - if(rootedIsEmpty) return res; - i =0; - while(i < res.length){ - result = res[i], selector = result.selector; - if (rooted[selector] !== undefined) { - result.selector = rooted[selector]; - rooted[selector] = false; - if(typeof result.selector !== "string" || result.elem.parentNode !== context ){ - res.splice(i,1); - continue; - } - } - i++; - } - return res; - } - - return $; +/** + * @add jQuery.fn + */ +steal('jquery', function($) { + /** + * @function closest + * @parent dom + * @plugin jquery/dom/closest + * Overwrites closest to allow open > selectors. This allows controller + * actions such as: + * + * ">li click" : function( el, ev ) { ... } + */ + var oldClosest = $.fn.closest; + $.fn.closest = function(selectors, context){ + var rooted = {}, res, result, thing, i, j, selector, rootedIsEmpty = true, selector, selectorsArr = selectors; + if(typeof selectors == "string") selectorsArr = [selectors]; + + $.each(selectorsArr, function(i, selector){ + if(selector.indexOf(">") == 0 ){ + if(selector.indexOf(" ") != -1){ + throw " closest does not work with > followed by spaces!" + } + rooted[( selectorsArr[i] = selector.substr(1) )] = selector; + if(typeof selectors == "string") selectors = selector.substr(1); + rootedIsEmpty = false; + } + }) + + res = oldClosest.call(this, selectors, context); + + if(rootedIsEmpty) return res; + i =0; + while(i < res.length){ + result = res[i], selector = result.selector; + if (rooted[selector] !== undefined) { + result.selector = rooted[selector]; + rooted[selector] = false; + if(typeof result.selector !== "string" || result.elem.parentNode !== context ){ + res.splice(i,1); + continue; + } + } + i++; + } + return res; + } + + return $; }) \ No newline at end of file diff --git a/dom/compare/compare.js b/dom/compare/compare.js index ee81f442..0a8bfb6f 100644 --- a/dom/compare/compare.js +++ b/dom/compare/compare.js @@ -1,75 +1,75 @@ -steal('jquery', function($) { - -/** - * @function jQuery.fn.compare - * @parent jQuery.compare - * - * Compare two elements and return a bitmask as a number representing the following conditions: - * - * - `000000` -> __0__: Elements are identical - * - `000001` -> __1__: The nodes are in different documents (or one is outside of a document) - * - `000010` -> __2__: #bar precedes #foo - * - `000100` -> __4__: #foo precedes #bar - * - `001000` -> __8__: #bar contains #foo - * - `010000` -> __16__: #foo contains #bar - * - * You can check for any of these conditions using a bitwise AND: - * - * if( $('#foo').compare($('#bar')) & 2 ) { - * console.log("#bar precedes #foo") - * } - * - * @param {HTMLElement|jQuery} element an element or jQuery collection to compare against. - * @return {Number} A number representing a bitmask deatiling how the elements are positioned from each other. - */ - -// See http://ejohn.org/blog/comparing-document-position/ -jQuery.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; -} - -return $; +steal('jquery', function($) { + +/** + * @function jQuery.fn.compare + * @parent jQuery.compare + * + * Compare two elements and return a bitmask as a number representing the following conditions: + * + * - `000000` -> __0__: Elements are identical + * - `000001` -> __1__: The nodes are in different documents (or one is outside of a document) + * - `000010` -> __2__: #bar precedes #foo + * - `000100` -> __4__: #foo precedes #bar + * - `001000` -> __8__: #bar contains #foo + * - `010000` -> __16__: #foo contains #bar + * + * You can check for any of these conditions using a bitwise AND: + * + * if( $('#foo').compare($('#bar')) & 2 ) { + * console.log("#bar precedes #foo") + * } + * + * @param {HTMLElement|jQuery} element an element or jQuery collection to compare against. + * @return {Number} A number representing a bitmask deatiling how the elements are positioned from each other. + */ + +// 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; +} + +return $; }); \ No newline at end of file diff --git a/dom/cookie/cookie.js b/dom/cookie/cookie.js index c4b0035b..a11f9fb1 100644 --- a/dom/cookie/cookie.js +++ b/dom/cookie/cookie.js @@ -1,114 +1,114 @@ -steal('jquery', 'jquery/lang/json', function($) { - /** - * @function jQuery.cookie - * @parent jquerypp - * @plugin jquery/dom/cookie - * @author Klaus Hartl/klaus.hartl@stilbuero.de - * - * `jQuery.cookie(name, [value], [options])` lets you create, read and remove cookies. It is the - * [jQuery cookie plugin](https://github.com/carhartl/jquery-cookie) written by [Klaus Hartl](stilbuero.de) - * and dual licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) - * and [GPL](http://www.gnu.org/licenses/gpl.html) licenses. - * - * ## Examples - * - * Set the value of a cookie. - * - * $.cookie('the_cookie', 'the_value'); - * - * Create a cookie with all available options. - * - * $.cookie('the_cookie', 'the_value', { - * expires: 7, - * path: '/', - * domain: 'jquery.com', - * secure: true - * }); - * - * Create a session cookie. - * - * $.cookie('the_cookie', 'the_value'); - * - * Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain - * used when the cookie was set. - * - * $.cookie('the_cookie', null); - * - * Get the value of a cookie. - * - * $.cookie('the_cookie'); - * - * @param {String} [name] The name of the cookie. - * @param {String} [value] The value of the cookie. - * @param {Object} [options] An object literal containing key/value pairs to provide optional cookie attributes. Values can be: - * - * - `expires` - Either an integer specifying the expiration date from now on in days or a Date object. If a negative value is specified (e.g. a date in the past), the cookie will be deleted. If set to null or omitted, the cookie will be a session cookie and will not be retained when the the browser exits. - * - `domain` - The domain name - * - `path` - The value of the path atribute of the cookie (default: path of page that created the cookie). - * - `secure` - If true, the secure attribute of the cookie will be set and the cookie transmission will require a secure protocol (like HTTPS). - * - * @return {String} the value of the cookie or {undefined} when setting the cookie. - */ - jQuery.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' && jQuery.toJSON) { - value = jQuery.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 = jQuery.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 (jQuery.evalJSON && cookieValue && cookieValue.match(/^\s*\{/)) { - try { - cookieValue = jQuery.evalJSON(cookieValue); - } - catch (e) { - } - } - return cookieValue; - } - }; - - return $; -}); +steal('jquery', 'jquery/lang/json', function($) { + /** + * @function jQuery.cookie + * @parent jquerypp + * @plugin jquery/dom/cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + * + * `jQuery.cookie(name, [value], [options])` lets you create, read and remove cookies. It is the + * [jQuery cookie plugin](https://github.com/carhartl/jquery-cookie) written by [Klaus Hartl](stilbuero.de) + * and dual licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) + * and [GPL](http://www.gnu.org/licenses/gpl.html) licenses. + * + * ## Examples + * + * Set the value of a cookie. + * + * $.cookie('the_cookie', 'the_value'); + * + * Create a cookie with all available options. + * + * $.cookie('the_cookie', 'the_value', { + * expires: 7, + * path: '/', + * domain: 'jquery.com', + * secure: true + * }); + * + * Create a session cookie. + * + * $.cookie('the_cookie', 'the_value'); + * + * Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * $.cookie('the_cookie', null); + * + * Get the value of a cookie. + * + * $.cookie('the_cookie'); + * + * @param {String} [name] The name of the cookie. + * @param {String} [value] The value of the cookie. + * @param {Object} [options] An object literal containing key/value pairs to provide optional cookie attributes. Values can be: + * + * - `expires` - Either an integer specifying the expiration date from now on in days or a Date object. If a negative value is specified (e.g. a date in the past), the cookie will be deleted. If set to null or omitted, the cookie will be a session cookie and will not be retained when the the browser exits. + * - `domain` - The domain name + * - `path` - The value of the path atribute of the cookie (default: path of page that created the cookie). + * - `secure` - If true, the secure attribute of the cookie will be set and the cookie transmission will require a secure protocol (like HTTPS). + * + * @return {String} the value of the cookie or {undefined} when setting the cookie. + */ + $.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; + } + }; + + return $; +}); diff --git a/dom/styles/styles.js b/dom/styles/styles.js index babfe151..d000e19e 100644 --- a/dom/styles/styles.js +++ b/dom/styles/styles.js @@ -1,103 +1,103 @@ -steal('jquery', function( $ ) { - 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 = jQuery.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; - }; - - /** - * @function jQuery.fn.styles - * @parent jQuery.styles - * @plugin jQuery.styles - * - * Returns a set of computed styles. Pass the names of the styles you want to - * retrieve as arguments: - * - * $("div").styles('float','display') - * // -> { cssFloat: "left", display: "block" } - * - * @param {String} style pass the names of the styles to retrieve as the argument list - * @return {Object} an object of `style` : `value` pairs - */ - $.fn.styles = function() { - // Pass the arguments as an array to $.styles - return $.styles(this[0], $.makeArray(arguments)); - }; - - return $; +steal('jquery', function( $ ) { + 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; + }; + + /** + * @function jQuery.fn.styles + * @parent jQuery.styles + * @plugin jQuery.styles + * + * Returns a set of computed styles. Pass the names of the styles you want to + * retrieve as arguments: + * + * $("div").styles('float','display') + * // -> { cssFloat: "left", display: "block" } + * + * @param {String} style pass the names of the styles to retrieve as the argument list + * @return {Object} an object of `style` : `value` pairs + */ + $.fn.styles = function() { + // Pass the arguments as an array to $.styles + return $.styles(this[0], $.makeArray(arguments)); + }; + + return $; }); \ No newline at end of file diff --git a/dom/within/within.js b/dom/within/within.js index 22e39a11..184455c9 100644 --- a/dom/within/within.js +++ b/dom/within/within.js @@ -1,94 +1,94 @@ -steal('jquery', function($) { - // 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); - } -/** - * @function jQuery.fn.within - * @parent jQuery.within - * @plugin jquery/dom/within - * - * Returns all elements matching the selector that touch a given point: - * - * // get all elements that touch 200x200. - * $('*').within(200, 200); - * - * @param {Number} left the position from the left of the page - * @param {Number} top the position from the top of the page - * @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. - * @return {jQuery} a jQuery collection of elements whos area - * overlaps the element position. - */ -$.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 ? - jQuery.data(this,"offsetCache") || jQuery.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( jQuery.unique( ret ), "within", left+","+top ); -} - - -/** - * @function jQuery.fn.withinBox - * @parent jQuery.within - * - * Returns all elements matching the selector that have a given area in common: - * - * $('*').withinBox(200, 200, 100, 100) - * - * @param {Number} left the position from the left of the page - * @param {Number} top the position from the top of the page - * @param {Number} width the width of the area - * @param {Number} height the height of the area - * @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. - * @return {jQuery} a jQuery collection of elements whos area - * overlaps the element position. - */ -$.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 ? - jQuery.data(this,"offset") || - jQuery.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( jQuery.unique( ret ), "withinBox", jQuery.makeArray(arguments).join(",") ); -} - -return $; -}) +steal('jquery', function($) { + // 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); + } +/** + * @function jQuery.fn.within + * @parent jQuery.within + * @plugin jquery/dom/within + * + * Returns all elements matching the selector that touch a given point: + * + * // get all elements that touch 200x200. + * $('*').within(200, 200); + * + * @param {Number} left the position from the left of the page + * @param {Number} top the position from the top of the page + * @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. + * @return {jQuery} a jQuery collection of elements whos area + * overlaps the element position. + */ +$.fn.within= function(left, top, useOffsetCache) { + var ret = [] + this.each(function(){ + var q = $(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 ); +} + + +/** + * @function jQuery.fn.withinBox + * @parent jQuery.within + * + * Returns all elements matching the selector that have a given area in common: + * + * $('*').withinBox(200, 200, 100, 100) + * + * @param {Number} left the position from the left of the page + * @param {Number} top the position from the top of the page + * @param {Number} width the width of the area + * @param {Number} height the height of the area + * @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. + * @return {jQuery} a jQuery collection of elements whos area + * overlaps the element position. + */ +$.fn.withinBox = function(left, top, width, height, useOffsetCache){ + var ret = [] + this.each(function(){ + var q = $(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(",") ); +} + +return $; +}) diff --git a/event/default/default.js b/event/default/default.js index f3d26ae2..9e6b8c2d 100644 --- a/event/default/default.js +++ b/event/default/default.js @@ -1,119 +1,119 @@ -steal('jquery', function($){ -/** - * @function jQuery.fn.triggerAsync - * @parent jQuery.event.pause - * @plugin jquery/event/default - * - * `jQuery.fn.triggerAsync(type, [data], [success], [prevented]` triggers an event and calls success - * when the event has finished propagating through the DOM and no other handler - * called `event.preventDefault()` or returned `false`. - * - * $('#panel').triggerAsync('show', function() { - * $('#panel').show(); - * }); - * - * You can also provide a callback that gets called if `event.preventDefault()` was called on the event: - * - * $('panel').triggerAsync('show', function(){ - * $('#panel').show(); - * },function(){ - * $('#other').addClass('error'); - * }); - * - * @param {String} type The type of event - * @param {Object} data The data for the event - * @param {Function} success a callback function which occurs upon success - * @param {Function} prevented a callback function which occurs if preventDefault was called - */ -$.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; -} - - - -/** - * @add jQuery.event.special - */ -//cache default types for performance -var types = {}, rnamespaces= /\.(.*)$/, $event = $.event; -/** - * @attribute default - * @parent specialevents - * @plugin jquery/event/default - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/default/default.js - * @test jquery/event/default/qunit.html - * - */ -$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[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.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; -}; - -return $; +steal('jquery', function($){ +/** + * @function jQuery.fn.triggerAsync + * @parent jQuery.event.pause + * @plugin jquery/event/default + * + * `jQuery.fn.triggerAsync(type, [data], [success], [prevented]` triggers an event and calls success + * when the event has finished propagating through the DOM and no other handler + * called `event.preventDefault()` or returned `false`. + * + * $('#panel').triggerAsync('show', function() { + * $('#panel').show(); + * }); + * + * You can also provide a callback that gets called if `event.preventDefault()` was called on the event: + * + * $('panel').triggerAsync('show', function(){ + * $('#panel').show(); + * },function(){ + * $('#other').addClass('error'); + * }); + * + * @param {String} type The type of event + * @param {Object} data The data for the event + * @param {Function} success a callback function which occurs upon success + * @param {Function} prevented a callback function which occurs if preventDefault was called + */ +$.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; +} + + + +/** + * @add jQuery.event.special + */ +//cache default types for performance +var types = {}, rnamespaces= /\.(.*)$/, $event = $.event; +/** + * @attribute default + * @parent specialevents + * @plugin jquery/event/default + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/default/default.js + * @test jquery/event/default/qunit.html + * + */ +$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; +}; + +return $; }); \ No newline at end of file diff --git a/event/destroyed/destroyed.js b/event/destroyed/destroyed.js index cb00616d..e25d90b8 100644 --- a/event/destroyed/destroyed.js +++ b/event/destroyed/destroyed.js @@ -1,22 +1,22 @@ -steal('jquery', function( $ ) { - /** - * @attribute destroyed - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/dom/destroyed/destroyed.js - * @test jquery/event/destroyed/qunit.html - */ - - // Store the old jQuery.cleanData - var oldClean = jQuery.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); - }; -return $; +steal('jquery', function( $ ) { + /** + * @attribute destroyed + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/dom/destroyed/destroyed.js + * @test jquery/event/destroyed/qunit.html + */ + + // 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); + }; +return $; }); \ No newline at end of file diff --git a/event/drag/scroll/scroll.js b/event/drag/scroll/scroll.js index a49cb4c1..f5ea55fe 100644 --- a/event/drag/scroll/scroll.js +++ b/event/drag/scroll/scroll.js @@ -1,152 +1,152 @@ -steal("jquery", "jquery/event/drop", function($) { //needs drop to determine if respondable - -/** - * @add jQuery.Drag.prototype - */ -$.Drag.prototype. - /** - * @plugin jquery/event/drag/scroll - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drag/scroll/scroll.js - * - * `drag.scrolls(elements, [options])` scroll elements with - * a scroll bar as the drag moves to borders. - * - * The following sets up the drag motions to scroll `#todos` and the window. Scrolling will - * start 50px away from a boundary and the speed will increase to 50px of scroll every 15ms. - * - * $('#todos').on(".todo","draginit", function(ev, drag){ - * drag.scrolls($('#todos').add(window), { - * distance : 50, - * delta : function(diff) { return (50 - diff) / 2}, - * direction : "y" - * }) - * }) - * - * @param {jQuery} elements an array of elements to scroll. The window can be in this array. - * @param {Object} [options] changes the default settings. - * - * - `distance` {number} 30 - how many pixels away from a boundry where we start scrolling - * - `delta(diff)` {Function} - returns how far we should scroll. It is passed how many pixels the cursor is - * from the boundry. - * - `direction` {String} - direction scrolling should happen. "xy" is the default. - */ - 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) - } - }, - /** - * Scrolls an element then calls mouse a mousemove in the same location. - * @hide - */ - move: function( scroll_element, drag_element, dx, dy, ev/*, x,y,sx, sy*/ ) { - 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}) - } -}) - -return $; +steal("jquery", "jquery/event/drop", function($) { //needs drop to determine if respondable + +/** + * @add jQuery.Drag.prototype + */ +$.Drag.prototype. + /** + * @plugin jquery/event/drag/scroll + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drag/scroll/scroll.js + * + * `drag.scrolls(elements, [options])` scroll elements with + * a scroll bar as the drag moves to borders. + * + * The following sets up the drag motions to scroll `#todos` and the window. Scrolling will + * start 50px away from a boundary and the speed will increase to 50px of scroll every 15ms. + * + * $('#todos').on(".todo","draginit", function(ev, drag){ + * drag.scrolls($('#todos').add(window), { + * distance : 50, + * delta : function(diff) { return (50 - diff) / 2}, + * direction : "y" + * }) + * }) + * + * @param {jQuery} elements an array of elements to scroll. The window can be in this array. + * @param {Object} [options] changes the default settings. + * + * - `distance` {number} 30 - how many pixels away from a boundry where we start scrolling + * - `delta(diff)` {Function} - returns how far we should scroll. It is passed how many pixels the cursor is + * from the boundry. + * - `direction` {String} - direction scrolling should happen. "xy" is the default. + */ + 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 = $(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 = $(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) + } + }, + /** + * Scrolls an element then calls mouse a mousemove in the same location. + * @hide + */ + move: function( scroll_element, drag_element, dx, dy, ev/*, x,y,sx, sy*/ ) { + 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}) + } +}) + +return $; }) \ No newline at end of file diff --git a/event/drop/drop.js b/event/drop/drop.js index eaa0d9b7..175d1dcc 100644 --- a/event/drop/drop.js +++ b/event/drop/drop.js @@ -1,455 +1,455 @@ -steal('jquery', 'jquery/event/drag', 'jquery/dom/within', 'jquery/dom/compare', function($){ - var event = $.event; - /** - * @add jQuery.event.special - */ - var eventNames = [ - /** - * @attribute dropover - * @parent jQuery.event.drop - * - * `dropover` is triggered when a [jQuery.event.drag drag] is first moved onto this - * drop element. - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * This event can be used to highlight the element when a drag is moved over it: - * - * $('.droparea').on('dropover', function(ev, drop, drag) { - * $(this).addClass('highlight'); - * }); - */ - "dropover", - /** - * @attribute dropon - * @parent jQuery.event.drop - * - * `dropon` is triggered when a drag is dropped on a drop element. - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * - * $('.droparea').on('dropon', function(ev, drop, drag) { - * $(this).html('Dropped: ' + drag.element.text()); - * }); - */ - "dropon", - /** - * @attribute dropout - * @parent jQuery.event.drop - * - * `dropout` is called when a drag is moved out of this drop element. - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * - * $('.droparea').on('dropover', function(ev, drop, drag) { - * // Remove the drop element highlight - * $(this).removeClass('highlight'); - * }); - */ - "dropout", - /** - * @attribute dropinit - * @parent jQuery.event.drop - * - * `dropinit` is called when a drag motion starts and the drop elements are initialized. - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * Calling [jQuery.Drop.prototype.cancel drop.cancel()] prevents the element from - * being dropped on: - * - * $('.droparea').on('dropover', function(ev, drop, drag) { - * if(drag.element.hasClass('not-me')) { - * drop.cancel(); - * } - * }); - */ - "dropinit", - /** - * @attribute dropmove - * @parent jQuery.event.drop - * - * `dropmove` is triggered repeatedly when a drag is moved over a drop - * (similar to a mousemove). - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * - * $('.droparea').on('dropmove', function(ev, drop, drag) { - * $(this).html(drag.location.x() + '/' + drag.location.y()); - * }); - */ - "dropmove", - /** - * @attribute dropend - * @parent jQuery.event.drop - * - * `dropend` is called when the drag motion is done for this drop element. - * The event handler gets an instance of [jQuery.Drag] passed as the second and a - * [jQuery.Drop] as the third parameter. - * - * - * $('.droparea').on('dropend', function(ev, drop, drag) { - * // Remove the drop element highlight - * $(this).removeClass('highlight'); - * }); - */ - "dropend"]; - - /** - * @class jQuery.Drop - * @parent jQuery.event.drop - * @plugin jquery/event/drop - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drop/drop.js - * @test jquery/event/drag/qunit.html - * - * The `jQuery.Drop` constructor is never called directly but an instance is passed to the - * to the `dropinit`, `dropover`, `dropmove`, `dropon`, and `dropend` event handlers as the - * third argument (the second will be the [jQuery.Drag]): - * - * $('#dropper').on('dropover', function(el, drop, drag) { - * // drop -> $.Drop - * // drag -> $.Drag - * }); - */ - $.Drop = function(callbacks, element){ - jQuery.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,{ - /** - * @static - */ - 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; - } - } - }, - /** - * @hide - * For a list of affected drops, sorts them by which is deepest in the DOM first. - */ - 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; - }, - /** - * @hide - * Tests if a drop is within the point. - */ - isAffected: function( point, moveable, responder ) { - return ((responder.element != moveable.element) && (responder.element.within(point[0], point[1], responder._cache).length == 1)); - }, - /** - * @hide - * Calls dropout and sets last active to null - * @param {Object} drop - * @param {Object} drag - * @param {Object} event - */ - deactivate: function( responder, mover, event ) { - mover.out(event, responder) - responder.callHandlers(this.lowerName+'out',responder.element[0], event, mover) - }, - /** - * @hide - * Calls dropover - * @param {Object} drop - * @param {Object} drag - * @param {Object} event - */ - 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) - }, - /** - * `$.Drop.compile()` gets all elements that are droppable and adds them to a list. - * - * This should be called if and when new drops are added to the page - * during the motion of a single drag. - * - * This is called by default when a drag motion starts. - * - * ## Use - * - * After adding an element or drop, call compile. - * - * $("#midpoint").bind("dropover",function(){ - * // when a drop hovers over midpoint, - * // make drop a drop. - * $("#drop").bind("dropover", function(){ - * - * }); - * $.Drop.compile(); - * }); - */ - 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< length; i++){ - this[method][i].call(el || this.element[0], ev, this, drag) - } - }, - /** - * `drop.cache(value)` sets the drop to cache positions of draggable elements. - * This should be called on `dropinit`. For example: - * - * $('#dropable').on('dropinit', function( el, ev, drop ) { - * drop.cache(); - * }); - * - * @param {Boolean} [value=true] Whether to cache drop elements or not. - */ - cache: function( value ) { - this._cache = value != null ? value : true; - }, - /** - * `drop.cancel()` prevents this drop from being dropped on. - * - * $('.droparea').on('dropover', function(ev, drop, drag) { - * if(drag.element.hasClass('not-me')) { - * drop.cancel(); - * } - * }); - */ - cancel: function() { - this._canceled = true; - } - }); - - return $; +steal('jquery', 'jquery/event/drag', 'jquery/dom/within', 'jquery/dom/compare', function($){ + var event = $.event; + /** + * @add jQuery.event.special + */ + var eventNames = [ + /** + * @attribute dropover + * @parent jQuery.event.drop + * + * `dropover` is triggered when a [jQuery.event.drag drag] is first moved onto this + * drop element. + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * This event can be used to highlight the element when a drag is moved over it: + * + * $('.droparea').on('dropover', function(ev, drop, drag) { + * $(this).addClass('highlight'); + * }); + */ + "dropover", + /** + * @attribute dropon + * @parent jQuery.event.drop + * + * `dropon` is triggered when a drag is dropped on a drop element. + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * + * $('.droparea').on('dropon', function(ev, drop, drag) { + * $(this).html('Dropped: ' + drag.element.text()); + * }); + */ + "dropon", + /** + * @attribute dropout + * @parent jQuery.event.drop + * + * `dropout` is called when a drag is moved out of this drop element. + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * + * $('.droparea').on('dropover', function(ev, drop, drag) { + * // Remove the drop element highlight + * $(this).removeClass('highlight'); + * }); + */ + "dropout", + /** + * @attribute dropinit + * @parent jQuery.event.drop + * + * `dropinit` is called when a drag motion starts and the drop elements are initialized. + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * Calling [jQuery.Drop.prototype.cancel drop.cancel()] prevents the element from + * being dropped on: + * + * $('.droparea').on('dropover', function(ev, drop, drag) { + * if(drag.element.hasClass('not-me')) { + * drop.cancel(); + * } + * }); + */ + "dropinit", + /** + * @attribute dropmove + * @parent jQuery.event.drop + * + * `dropmove` is triggered repeatedly when a drag is moved over a drop + * (similar to a mousemove). + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * + * $('.droparea').on('dropmove', function(ev, drop, drag) { + * $(this).html(drag.location.x() + '/' + drag.location.y()); + * }); + */ + "dropmove", + /** + * @attribute dropend + * @parent jQuery.event.drop + * + * `dropend` is called when the drag motion is done for this drop element. + * The event handler gets an instance of [jQuery.Drag] passed as the second and a + * [jQuery.Drop] as the third parameter. + * + * + * $('.droparea').on('dropend', function(ev, drop, drag) { + * // Remove the drop element highlight + * $(this).removeClass('highlight'); + * }); + */ + "dropend"]; + + /** + * @class jQuery.Drop + * @parent jQuery.event.drop + * @plugin jquery/event/drop + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drop/drop.js + * @test jquery/event/drag/qunit.html + * + * The `jQuery.Drop` constructor is never called directly but an instance is passed to the + * to the `dropinit`, `dropover`, `dropmove`, `dropon`, and `dropend` event handlers as the + * third argument (the second will be the [jQuery.Drag]): + * + * $('#dropper').on('dropover', function(el, drop, drag) { + * // drop -> $.Drop + * // drag -> $.Drag + * }); + */ + $.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,{ + /** + * @static + */ + 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; + } + } + }, + /** + * @hide + * For a list of affected drops, sorts them by which is deepest in the DOM first. + */ + 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; + }, + /** + * @hide + * Tests if a drop is within the point. + */ + isAffected: function( point, moveable, responder ) { + return ((responder.element != moveable.element) && (responder.element.within(point[0], point[1], responder._cache).length == 1)); + }, + /** + * @hide + * Calls dropout and sets last active to null + * @param {Object} drop + * @param {Object} drag + * @param {Object} event + */ + deactivate: function( responder, mover, event ) { + mover.out(event, responder) + responder.callHandlers(this.lowerName+'out',responder.element[0], event, mover) + }, + /** + * @hide + * Calls dropover + * @param {Object} drop + * @param {Object} drag + * @param {Object} event + */ + 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) + }, + /** + * `$.Drop.compile()` gets all elements that are droppable and adds them to a list. + * + * This should be called if and when new drops are added to the page + * during the motion of a single drag. + * + * This is called by default when a drag motion starts. + * + * ## Use + * + * After adding an element or drop, call compile. + * + * $("#midpoint").bind("dropover",function(){ + * // when a drop hovers over midpoint, + * // make drop a drop. + * $("#drop").bind("dropover", function(){ + * + * }); + * $.Drop.compile(); + * }); + */ + 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 ? $(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< length; i++){ + this[method][i].call(el || this.element[0], ev, this, drag) + } + }, + /** + * `drop.cache(value)` sets the drop to cache positions of draggable elements. + * This should be called on `dropinit`. For example: + * + * $('#dropable').on('dropinit', function( el, ev, drop ) { + * drop.cache(); + * }); + * + * @param {Boolean} [value=true] Whether to cache drop elements or not. + */ + cache: function( value ) { + this._cache = value != null ? value : true; + }, + /** + * `drop.cancel()` prevents this drop from being dropped on. + * + * $('.droparea').on('dropover', function(ev, drop, drag) { + * if(drag.element.hasClass('not-me')) { + * drop.cancel(); + * } + * }); + */ + cancel: function() { + this._canceled = true; + } + }); + + return $; }); \ No newline at end of file diff --git a/event/fastfix/fastfix.js b/event/fastfix/fastfix.js index 3707b497..b7fd457a 100644 --- a/event/fastfix/fastfix.js +++ b/event/fastfix/fastfix.js @@ -1,112 +1,112 @@ -steal('jquery', function ($) { - // 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 - jQuery.each(jQuery.event.keyHooks.props.concat(jQuery.event.mouseHooks.props).concat(jQuery.event.props), function (i, prop) { - if (prop !== "target") { - (function () { - Object.defineProperty(jQuery.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; - } - }); - })(); - } - }); - - jQuery.event.fix = function (event) { - if (event[ jQuery.expando ]) { - return event; - } - // Create a jQuery event with at minimum a target and type set - var originalEvent = event, - event = jQuery.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; - } - } - - return $; -}); +steal('jquery', function ($) { + // 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; + } + } + + return $; +}); diff --git a/event/handle/handle.js b/event/handle/handle.js index 42961301..be20580f 100644 --- a/event/handle/handle.js +++ b/event/handle/handle.js @@ -1,209 +1,209 @@ -steal("jquery", function($) { - -var $event = $.event, - oldTrigger = $event.trigger, - isElement = function(o){ - return ( - typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 - typeof o === "object" && o.nodeType === 1 && typeof o.nodeName==="string" - ) || (o === window) || (o === document); - }; -$.event.trigger = function(event, data, elem, onlyHandlers){ - // Event object or event type - var type = event.type || event, - namespaces = [], - exclusive; - - if ( type.indexOf("!") >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.exclusive = exclusive; - event.namespace = namespaces.join("."); - event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - - // triggerHandler() and global events don't bubble or run the default action - if ( onlyHandlers || !elem ) { - event.preventDefault(); - event.stopPropagation(); - } - - // Handle a global trigger - if ( !elem ) { - // TODO: Stop taunting the data cache; remove global events and always attach to document - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - return; - } - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - event.target = elem; - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - var cur = elem, - // IE doesn't like method names with a colon (#3533, #8272) - ontype = type.indexOf(":") < 0 ? "on" + type : ""; - - // Fire event on the current element, then bubble up the DOM tree - do { - var handle = jQuery._data( cur, "handle" ); - - event.currentTarget = cur; - if ( handle ) { - handle.apply( cur, data ); - } - - // Trigger an inline bound script - if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { - event.result = false; - event.preventDefault(); - } - - // Bubble up to document, then to window - cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; - } while ( cur && !event.isPropagationStopped() ); - - // If nobody prevented the default action, do it now - if ( !event.isDefaultPrevented() ) { - var old, - special = jQuery.event.special[ type ] || {}; - - if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction)() check here because IE6/7 fails that test. - // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. - try { - if ( ontype && elem[ type ] ) { - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - jQuery.event.triggered = type; - elem[ type ](); - } - } catch ( ieError ) {} - - if ( old ) { - elem[ ontype ] = old; - } - - jQuery.event.triggered = undefined; - } - } - - return event.result; -} -// a copy of $'s handle function that goes until it finds -$.event.handle = function( event ) { - - event = jQuery.event.fix( event || window.event ); - // Snapshot the handlers list since a called handler may add/remove events. - var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), - run_all = !event.exclusive && !event.namespace, - args = Array.prototype.slice.call( arguments, 0 ); - - // Use the fix-ed Event rather than the (read-only) native event - args[0] = event; - event.currentTarget = this; - - // JMVC CHANGED - var oldType = event.type, - // run if default is included - runDefault = event.type !== "default" && $event.special['default'] && - // and its not an original event - !event.originalEvent && - // and its an element - isElement(event.target); - if (runDefault) { - $event.special['default'].triggerDefault(event, this, args[1]); - } - event.type = oldType; - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - if( event.firstPass ){ - event.firstPass = false; - continue; - } - - // Triggered event must 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event. - if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - // JMVC CHANGED - if (runDefault) { - $event.special['default'].checkAndRunDefaults(event, this); - } - return event.result; -} - - return $; -}) +steal("jquery", function($) { + +var $event = $.event, + oldTrigger = $event.trigger, + isElement = function(o){ + return ( + typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 + typeof o === "object" && o.nodeType === 1 && typeof o.nodeName==="string" + ) || (o === window) || (o === document); + }; +$.event.trigger = function(event, data, elem, onlyHandlers){ + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || $.event.customEvent[ type ]) && !$.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // 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 ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + $.each( $.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = $.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + $.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data ? $.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = $._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && $.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = $.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && $.nodeName( elem, "a" )) && $.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + $.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + $.event.triggered = undefined; + } + } + + return event.result; +} +// a copy of $'s handle function that goes until it finds +$.event.handle = function( event ) { + + event = $.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = (($._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + // JMVC CHANGED + var oldType = event.type, + // run if default is included + runDefault = event.type !== "default" && $event.special['default'] && + // and its not an original event + !event.originalEvent && + // and its an element + isElement(event.target); + if (runDefault) { + $event.special['default'].triggerDefault(event, this, args[1]); + } + event.type = oldType; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + if( event.firstPass ){ + event.firstPass = false; + continue; + } + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + // JMVC CHANGED + if (runDefault) { + $event.special['default'].checkAndRunDefaults(event, this); + } + return event.result; +} + + return $; +}) diff --git a/event/hashchange/hashchange.js b/event/hashchange/hashchange.js index 25bf7a86..b692fa65 100644 --- a/event/hashchange/hashchange.js +++ b/event/hashchange/hashchange.js @@ -1,270 +1,416 @@ -/*! - * jQuery hashchange event - v1.2 - 2/11/2010 - * http://benalman.com/projects/jquery-hashchange-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ - -// Script: jQuery hashchange event -// -// *Version: 1.2, Last updated: 2/11/2010* -// -// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ -// GitHub - http://github.com/cowboy/jquery-hashchange/ -// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js -// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (1.1kb) -// -// About: License -// -// Copyright (c) 2010 "Cowboy" Ben Alman, -// Dual licensed under the MIT and GPL licenses. -// http://benalman.com/about/license/ -// -// About: Examples -// -// This working example, complete with fully commented code, illustrate one way -// in which this plugin can be used. -// -// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ -// -// About: Support and Testing -// -// Information about what version or versions of jQuery this plugin has been -// tested with, what browsers it has been tested in, and where the unit tests -// reside (so you can test it yourself). -// -// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 -// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.1. -// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ -// -// About: Known issues -// -// While this jQuery hashchange event implementation is quite stable and robust, -// there are a few unfortunate browser bugs surrounding expected hashchange -// event-based behaviors, independent of any JavaScript window.onhashchange -// abstraction. See the following examples for more information: -// -// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ -// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ -// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ -// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ -// -// About: Release History -// -// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin -// from a page on another domain would cause an error in Safari 4. Also, -// IE6/7 Iframe is now inserted after the body (this actually works), -// which prevents the page from scrolling when the event is first bound. -// Event can also now be bound before DOM ready, but it won't be usable -// before then in IE6/7. -// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug -// where browser version is incorrectly reported as 8.0, despite -// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. -// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special -// window.onhashchange functionality into a separate plugin for users -// who want just the basic event & back button support, without all the -// extra awesomeness that BBQ provides. This plugin will be included as -// part of jQuery BBQ, but also be available separately. -/** - * @add jQuery.event.special - */ -// -/** - * @attribute hashchange - * - * Documentation on JMVC's hashchange event can - * be found at [http://benalman.com/projects/jquery-hashchange-plugin/]. - * - * ### Examples - * - * // with jQuery - * $(window).bind('hashchange', function(){ - * // do something - * }) - * - * // with $.Controller - * $.Controller('Nav',{ - * "{window} hashchange" : function(){ - * // do something - * } - * }) - * - */ -steal('jquery', function($){ - '$:nomunge'; // Used by YUI compressor. - - // Method / object references. - var fake_onhashchange, - jq_event_special = $.event.special, - - // Reused strings. - str_location = 'location', - str_hashchange = 'hashchange', - str_href = 'href', - - // IE6/7 specifically need some special love when it comes to back-button - // support, so let's do a little browser sniffing.. - browser = $.browser, - mode = document.documentMode, - is_old_ie = browser.msie && ( mode === undefined || mode < 8 ), - - // Does the browser support window.onhashchange? Test for IE version, since - // IE8 incorrectly reports this when in "IE7" or "IE8 Compatibility View"! - supports_onhashchange = 'on' + str_hashchange in window && !is_old_ie; - - // Get location.hash (or what you'd expect location.hash to be) sans any - // leading #. Thanks for making this necessary, Firefox! - function get_fragment( url ) { - url = url || window[ str_location ][ str_href ]; - return url.replace( /^[^#]*#?(.*)$/, '$1' ); - }; - - // Property: jQuery.hashchangeDelay - // - // The numeric interval (in milliseconds) at which the - // polling loop executes. Defaults to 100. - - $[ str_hashchange + 'Delay' ] = 100; - - // Event: hashchange event - // - // Fired when location.hash changes. In browsers that support it, the native - // window.onhashchange event is used (IE8, FF3.6), otherwise a polling loop is - // initialized, running every milliseconds to see if - // the hash has changed. In IE 6 and 7, a hidden Iframe is created to allow - // the back button and hash-based history to work. - // - // Usage: - // - // > $(window).bind( 'hashchange', function(e) { - // > var hash = location.hash; - // > ... - // > }); - // - // Additional Notes: - // - // * The polling loop and Iframe are not created until at least one callback - // is actually bound to 'hashchange'. - // * If you need the bound callback(s) to execute immediately, in cases where - // the page 'state' exists on page load (via bookmark or page refresh, for - // example) use $(window).trigger( 'hashchange' ); - // * The event can be bound before DOM ready, but since it won't be usable - // before then in IE6/7 (due to the necessary Iframe), recommended usage is - // to bind it inside a $(document).ready() callback. - - jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { - - // Called only when the first 'hashchange' event is bound to window. - setup: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to create our own. And we don't want to call this - // until the user binds to the event, just in case they never do, since it - // will create a polling loop and possibly even a hidden Iframe. - $( fake_onhashchange.start ); - }, - - // Called only when the last 'hashchange' event is unbound from window. - teardown: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to stop ours (if possible). - $( fake_onhashchange.stop ); - } - - }); - - // fake_onhashchange does all the work of triggering the window.onhashchange - // event for browsers that don't natively support it, including creating a - // polling loop to watch for hash changes and in IE 6/7 creating a hidden - // Iframe to enable back and forward. - fake_onhashchange = (function(){ - var self = {}, - timeout_id, - iframe, - set_history, - get_history; - - // Initialize. In IE 6/7, creates a hidden Iframe for history handling. - function init(){ - // Most browsers don't need special methods here.. - set_history = get_history = function(val){ return val; }; - - // But IE6/7 do! - if ( is_old_ie ) { - - // Create hidden Iframe after the end of the body to prevent initial - // page load from scrolling unnecessarily. - iframe = $('