define("jquery/pp/animate", ["jquery"], function ($) { // ## jquery/dom/styles/styles.js var getComputedStyle = document.defaultView && document.defaultView.getComputedStyle, // The following variables are used to convert camelcased attribute names // into dashed names, e.g. borderWidth to border-width rupper = /([A-Z])/g, rdashAlpha = /-([a-z])/ig, fcamelCase = function( all, letter ) { return letter.toUpperCase(); }, // Returns the computed style for an elementn getStyle = function( elem ) { if ( getComputedStyle ) { return getComputedStyle(elem, null); } else if ( elem.currentStyle ) { return elem.currentStyle; } }, // Checks for float px and numeric values rfloat = /float/i, rnumpx = /^-?\d+(?:px)?$/i, rnum = /^-?\d/; // Returns a list of styles for a given element $.styles = function( el, styles ) { if (!el ) { return null; } var currentS = getStyle(el), oldName, val, style = el.style, results = {}, i = 0, left, rsLeft, camelCase, name; // Go through each style for (; i < styles.length; i++ ) { name = styles[i]; oldName = name.replace(rdashAlpha, fcamelCase); if ( rfloat.test(name) ) { name = $.support.cssFloat ? "float" : "styleFloat"; oldName = "cssFloat"; } // If we have getComputedStyle available if ( getComputedStyle ) { // convert camelcased property names to dashed name name = name.replace(rupper, "-$1").toLowerCase(); // use getPropertyValue of the current style object val = currentS.getPropertyValue(name); // default opacity is 1 if ( name === "opacity" && val === "" ) { val = "1"; } results[oldName] = val; } else { // Without getComputedStyles camelCase = name.replace(rdashAlpha, fcamelCase); results[oldName] = currentS[name] || currentS[camelCase]; // convert to px if (!rnumpx.test(results[oldName]) && rnum.test(results[oldName]) ) { // Remember the original values left = style.left; rsLeft = el.runtimeStyle.left; // Put in the new values to get a computed value out el.runtimeStyle.left = el.currentStyle.left; style.left = camelCase === "fontSize" ? "1em" : (results[oldName] || 0); results[oldName] = style.pixelLeft + "px"; // Revert the changed values style.left = left; el.runtimeStyle.left = rsLeft; } } } return results; }; /** * @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)); }; // ## jquery/dom/animate/animate.js // Overwrites `jQuery.fn.animate` to use CSS 3 animations if possible var // The global animation counter animationNum = 0, // The stylesheet for our animations styleSheet = null, // The animation cache cache = [], // Stores the browser properties like transition end event name and prefix browser = null, // Store the original $.fn.animate oldanimate = $.fn.animate, // Return the stylesheet, create it if it doesn't exists getStyleSheet = function () { if(!styleSheet) { var style = document.createElement('style'); style.setAttribute("type", "text/css"); style.setAttribute("media", "screen"); document.getElementsByTagName('head')[0].appendChild(style); if (!window.createPopup) { /* 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 $; });