diff --git a/dist/jquery.transform-0.9.3.js b/dist/jquery.transform-0.9.3.js index 8f35447..8679d40 100644 --- a/dist/jquery.transform-0.9.3.js +++ b/dist/jquery.transform-0.9.3.js @@ -1,562 +1,562 @@ -/*! - * jQuery 2d Transform v0.9.3 - * http://wiki.github.com/heygrady/transform/ - * - * Copyright 2010, Grady Kuhnline - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Date: Sat Dec 4 15:46:09 2010 -0800 - */ -/////////////////////////////////////////////////////// -// Transform -/////////////////////////////////////////////////////// -(function($, window, document, undefined) { - /** - * @var Regex identify the matrix filter in IE - */ - var rmatrix = /progid:DXImageTransform\.Microsoft\.Matrix\(.*?\)/, - rfxnum = /^([\+\-]=)?([\d+.\-]+)(.*)$/, - rperc = /%/; - - // Steal some code from Modernizr - var m = document.createElement( 'modernizr' ), - m_style = m.style; - - function stripUnits(arg) { - return parseFloat(arg); - } - - /** - * Find the prefix that this browser uses - */ - function getVendorPrefix() { - var property = { - transformProperty : '', - MozTransform : '-moz-', - WebkitTransform : '-webkit-', - OTransform : '-o-', - msTransform : '-ms-' - }; - for (var p in property) { - if (typeof m_style[p] != 'undefined') { - return property[p]; - } - } - return null; - } - - function supportCssTransforms() { - if (typeof(window.Modernizr) !== 'undefined') { - return Modernizr.csstransforms; - } - - var props = [ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]; - for ( var i in props ) { - if ( m_style[ props[i] ] !== undefined ) { - return true; - } - } - } - - // Capture some basic properties - var vendorPrefix = getVendorPrefix(), - transformProperty = vendorPrefix !== null ? vendorPrefix + 'transform' : false, - transformOriginProperty = vendorPrefix !== null ? vendorPrefix + 'transform-origin' : false; - - // store support in the jQuery Support object - $.support.csstransforms = supportCssTransforms(); - - // IE9 public preview 6 requires the DOM names - if (vendorPrefix == '-ms-') { - transformProperty = 'msTransform'; - transformOriginProperty = 'msTransformOrigin'; - } - - /** - * Class for creating cross-browser transformations - * @constructor - */ - $.extend({ - transform: function(elem) { - // Cache the transform object on the element itself - elem.transform = this; - - /** - * The element we're working with - * @var jQueryCollection - */ - this.$elem = $(elem); - - /** - * Remember the matrix we're applying to help the safeOuterLength func - */ - this.applyingMatrix = false; - this.matrix = null; - - /** - * Remember the css height and width to save time - * This is only really used in IE - * @var Number - */ - this.height = null; - this.width = null; - this.outerHeight = null; - this.outerWidth = null; - - /** - * We need to know the box-sizing in IE for building the outerHeight and outerWidth - * @var string - */ - this.boxSizingValue = null; - this.boxSizingProperty = null; - - this.attr = null; - this.transformProperty = transformProperty; - this.transformOriginProperty = transformOriginProperty; - } - }); - - $.extend($.transform, { - /** - * @var Array list of all valid transform functions - */ - funcs: ['matrix', 'origin', 'reflect', 'reflectX', 'reflectXY', 'reflectY', 'rotate', 'scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY', 'translate', 'translateX', 'translateY'] - }); - - /** - * Create Transform as a jQuery plugin - * @param Object funcs - * @param Object options - */ - $.fn.transform = function(funcs, options) { - return this.each(function() { - var t = this.transform || new $.transform(this); - if (funcs) { - t.exec(funcs, options); - } - }); - }; - - $.transform.prototype = { - /** - * Applies all of the transformations - * @param Object funcs - * @param Object options - * forceMatrix - uses the matrix in all browsers - * preserve - tries to preserve the values from previous runs - */ - exec: function(funcs, options) { - // extend options - options = $.extend(true, { - forceMatrix: false, - preserve: false - }, options); - - // preserve the funcs from the previous run - this.attr = null; - if (options.preserve) { - funcs = $.extend(true, this.getAttrs(true, true), funcs); - } else { - funcs = $.extend(true, {}, funcs); // copy the object to prevent weirdness - } - - // Record the custom attributes on the element itself - this.setAttrs(funcs); - - // apply the funcs - if ($.support.csstransforms && !options.forceMatrix) { - // CSS3 is supported - return this.execFuncs(funcs); - } else if ($.browser.msie || ($.support.csstransforms && options.forceMatrix)) { - // Internet Explorer or Forced matrix - return this.execMatrix(funcs); - } - return false; - }, - - /** - * Applies all of the transformations as functions - * @param Object funcs - */ - execFuncs: function(funcs) { - var values = []; - - // construct a CSS string - for (var func in funcs) { - // handle origin separately - if (func == 'origin') { - this[func].apply(this, $.isArray(funcs[func]) ? funcs[func] : [funcs[func]]); - } else if ($.inArray(func, $.transform.funcs) !== -1) { - values.push(this.createTransformFunc(func, funcs[func])); - } - } - this.$elem.css(transformProperty, values.join(' ')); - return true; - }, - - /** - * Applies all of the transformations as a matrix - * @param Object funcs - */ - execMatrix: function(funcs) { - var matrix, - tempMatrix, - args; - - var elem = this.$elem[0], - _this = this; - function normalPixels(val, i) { - if (rperc.test(val)) { - // this really only applies to translation - return parseFloat(val) / 100 * _this['safeOuter' + (i ? 'Height' : 'Width')](); - } - return toPx(elem, val); - } - - var rtranslate = /translate[X|Y]?/, - trans = []; - - for (var func in funcs) { - switch ($.type(funcs[func])) { - case 'array': args = funcs[func]; break; - case 'string': args = $.map(funcs[func].split(','), $.trim); break; - default: args = [funcs[func]]; - } - - if ($.matrix[func]) { - - if ($.cssAngle[func]) { - // normalize on degrees - args = $.map(args, $.angle.toDegree); - } else if (!$.cssNumber[func]) { - // normalize to pixels - args = $.map(args, normalPixels); - } else { - // strip units - args = $.map(args, stripUnits); - } - - tempMatrix = $.matrix[func].apply(this, args); - if (rtranslate.test(func)) { - //defer translation - trans.push(tempMatrix); - } else { - matrix = matrix ? matrix.x(tempMatrix) : tempMatrix; - } - } else if (func == 'origin') { - this[func].apply(this, args); - } - } - - // check that we have a matrix - matrix = matrix || $.matrix.identity(); - - // Apply translation - $.each(trans, function(i, val) { matrix = matrix.x(val); }); - - // pull out the relevant values - var a = parseFloat(matrix.e(1,1).toFixed(6)), - b = parseFloat(matrix.e(2,1).toFixed(6)), - c = parseFloat(matrix.e(1,2).toFixed(6)), - d = parseFloat(matrix.e(2,2).toFixed(6)), - tx = matrix.rows === 3 ? parseFloat(matrix.e(1,3).toFixed(6)) : 0, - ty = matrix.rows === 3 ? parseFloat(matrix.e(2,3).toFixed(6)) : 0; - - //apply the transform to the element - if ($.support.csstransforms && vendorPrefix === '-moz-') { - // -moz- - this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + 'px, ' + ty + 'px)'); - } else if ($.support.csstransforms) { - // -webkit, -o-, w3c - // NOTE: WebKit and Opera don't allow units on the translate variables - this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + ', ' + ty + ')'); - } else if ($.browser.msie) { - // IE requires the special transform Filter - - //TODO: Use Nearest Neighbor during animation FilterType=\'nearest neighbor\' - var filterType = ', FilterType=\'nearest neighbor\''; //bilinear - var style = this.$elem[0].style; - var matrixFilter = 'progid:DXImageTransform.Microsoft.Matrix(' + - 'M11=' + a + ', M12=' + c + ', M21=' + b + ', M22=' + d + - ', sizingMethod=\'auto expand\'' + filterType + ')'; - var filter = style.filter || $.curCSS( this.$elem[0], "filter" ) || ""; - style.filter = rmatrix.test(filter) ? filter.replace(rmatrix, matrixFilter) : filter ? filter + ' ' + matrixFilter : matrixFilter; - - // Let's know that we're applying post matrix fixes and the height/width will be static for a bit - this.applyingMatrix = true; - this.matrix = matrix; - - // IE can't set the origin or translate directly - this.fixPosition(matrix, tx, ty); - - this.applyingMatrix = false; - this.matrix = null; - } - return true; - }, - - /** - * Sets the transform-origin - * This really needs to be percentages - * @param Number x length - * @param Number y length - */ - origin: function(x, y) { - // use CSS in supported browsers - if ($.support.csstransforms) { - if (typeof y === 'undefined') { - this.$elem.css(transformOriginProperty, x); - } else { - this.$elem.css(transformOriginProperty, x + ' ' + y); - } - return true; - } - - // correct for keyword lengths - switch (x) { - case 'left': x = '0'; break; - case 'right': x = '100%'; break; - case 'center': // no break - case undefined: x = '50%'; - } - switch (y) { - case 'top': y = '0'; break; - case 'bottom': y = '100%'; break; - case 'center': // no break - case undefined: y = '50%'; //TODO: does this work? - } - - // store mixed values with units, assumed pixels - this.setAttr('origin', [ - rperc.test(x) ? x : toPx(this.$elem[0], x) + 'px', - rperc.test(y) ? y : toPx(this.$elem[0], y) + 'px' - ]); - //console.log(this.getAttr('origin')); - return true; - }, - - /** - * Create a function suitable for a CSS value - * @param string func - * @param Mixed value - */ - createTransformFunc: function(func, value) { - if (func.substr(0, 7) === 'reflect') { - // let's fake reflection, false value - // falsey sets an identity matrix - var m = value ? $.matrix[func]() : $.matrix.identity(); - return 'matrix(' + m.e(1,1) + ', ' + m.e(2,1) + ', ' + m.e(1,2) + ', ' + m.e(2,2) + ', 0, 0)'; - } - - //value = _correctUnits(func, value); - - if (func == 'matrix') { - if (vendorPrefix === '-moz-') { - value[4] = value[4] ? value[4] + 'px' : 0; - value[5] = value[5] ? value[5] + 'px' : 0; - } - } - return func + '(' + ($.isArray(value) ? value.join(', ') : value) + ')'; - }, - - /** - * @param Matrix matrix - * @param Number tx - * @param Number ty - * @param Number height - * @param Number width - */ - fixPosition: function(matrix, tx, ty, height, width) { - // now we need to fix it! - var calc = new $.matrix.calc(matrix, this.safeOuterHeight(), this.safeOuterWidth()), - origin = this.getAttr('origin'); // mixed percentages and px - - // translate a 0, 0 origin to the current origin - var offset = calc.originOffset(new $.matrix.V2( - rperc.test(origin[0]) ? parseFloat(origin[0])/100*calc.outerWidth : parseFloat(origin[0]), - rperc.test(origin[1]) ? parseFloat(origin[1])/100*calc.outerHeight : parseFloat(origin[1]) - )); - - // IE glues the top-most and left-most pixels of the transformed object to top/left of the original object - //TODO: This seems wrong in the calculations - var sides = calc.sides(); - - // Protect against an item that is already positioned - var cssPosition = this.$elem.css('position'); - if (cssPosition == 'static') { - cssPosition = 'relative'; - } - - //TODO: if the element is already positioned, we should attempt to respect it (somehow) - //NOTE: we could preserve our offset top and left in an attr on the elem - var pos = {top: 0, left: 0}; - - // Approximates transform-origin, tx, and ty - var css = { - 'position': cssPosition, - 'top': (offset.top + ty + sides.top + pos.top) + 'px', - 'left': (offset.left + tx + sides.left + pos.left) + 'px', - 'zoom': 1 - }; - - this.$elem.css(css); - } - }; - - /** - * Ensure that values have the appropriate units on them - * @param string func - * @param Mixed value - */ - function toPx(elem, val) { - var parts = rfxnum.exec($.trim(val)); - - if (parts[3] && parts[3] !== 'px') { - var prop = 'paddingBottom', - orig = $.style( elem, prop ); - - $.style( elem, prop, val ); - val = cur( elem, prop ); - $.style( elem, prop, orig ); - return val; - } - return parseFloat( val ); - } - - function cur(elem, prop) { - if ( elem[prop] != null && (!elem.style || elem.style[prop] == null) ) { - return elem[ prop ]; - } - - var r = parseFloat( $.css( elem, prop ) ); - return r && r > -10000 ? r : 0; - } -})(jQuery, this, this.document); - - -/////////////////////////////////////////////////////// -// Safe Outer Length -/////////////////////////////////////////////////////// -(function($, window, document, undefined) { - $.extend($.transform.prototype, { - /** - * @param void - * @return Number - */ - safeOuterHeight: function() { - return this.safeOuterLength('height'); - }, - - /** - * @param void - * @return Number - */ - safeOuterWidth: function() { - return this.safeOuterLength('width'); - }, - - /** - * Returns reliable outer dimensions for an object that may have been transformed. - * Only use this if the matrix isn't handy - * @param String dim height or width - * @return Number - */ - safeOuterLength: function(dim) { - var funcName = 'outer' + (dim == 'width' ? 'Width' : 'Height'); - - if (!$.support.csstransforms && $.browser.msie) { - // make the variables more generic - dim = dim == 'width' ? 'width' : 'height'; - - // if we're transforming and have a matrix; we can shortcut. - // the true outerHeight is the transformed outerHeight divided by the ratio. - // the ratio is equal to the height of a 1px by 1px box that has been transformed by the same matrix. - if (this.applyingMatrix && !this[funcName] && this.matrix) { - // calculate and return the correct size - var calc = new $.matrix.calc(this.matrix, 1, 1), - ratio = calc.offset(), - length = this.$elem[funcName]() / ratio[dim]; - this[funcName] = length; - - return length; - } else if (this.applyingMatrix && this[funcName]) { - // return the cached calculation - return this[funcName]; - } - - // map dimensions to box sides - var side = { - height: ['top', 'bottom'], - width: ['left', 'right'] - }; - - // setup some variables - var elem = this.$elem[0], - outerLen = parseFloat($.curCSS(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width - boxSizingProp = this.boxSizingProperty, - boxSizingValue = this.boxSizingValue; - - // IE6 && IE7 will never have a box-sizing property, so fake it - if (!this.boxSizingProperty) { - boxSizingProp = this.boxSizingProperty = _findBoxSizingProperty() || 'box-sizing'; - boxSizingValue = this.boxSizingValue = this.$elem.css(boxSizingProp) || 'content-box'; - } - - // return it immediately if we already know it - if (this[funcName] && this[dim] == outerLen) { - return this[funcName]; - } else { - this[dim] = outerLen; - } - - // add in the padding and border - if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { - outerLen += parseFloat($.curCSS(elem, 'padding-' + side[dim][0], true)) || 0 + - parseFloat($.curCSS(elem, 'padding-' + side[dim][1], true)) || 0; - } - if (boxSizingProp && boxSizingValue == 'content-box') { - outerLen += parseFloat($.curCSS(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + - parseFloat($.curCSS(elem, 'border-' + side[dim][1] + '-width', true)) || 0; - } - - // remember and return the outerHeight - this[funcName] = outerLen; - return outerLen; - } - return this.$elem[funcName](); - } - }); - - /** - * Determine the correct property for checking the box-sizing property - * @param void - * @return string - */ - var _boxSizingProperty = null; - function _findBoxSizingProperty () { - if (_boxSizingProperty) { - return _boxSizingProperty; - } - - var property = { - boxSizing : 'box-sizing', - MozBoxSizing : '-moz-box-sizing', - WebkitBoxSizing : '-webkit-box-sizing', - OBoxSizing : '-o-box-sizing' - }, - elem = document.body; - - for (var p in property) { - if (typeof elem.style[p] != 'undefined') { - _boxSizingProperty = property[p]; - return _boxSizingProperty; - } - } - return null; - } -})(jQuery, this, this.document); - +/*! + * jQuery 2d Transform v0.9.3 + * http://wiki.github.com/heygrady/transform/ + * + * Copyright 2010, Grady Kuhnline + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Date: Sat Dec 4 16:40:39 2010 -0800 + */ +/////////////////////////////////////////////////////// +// Transform +/////////////////////////////////////////////////////// +(function($, window, document, undefined) { + /** + * @var Regex identify the matrix filter in IE + */ + var rmatrix = /progid:DXImageTransform\.Microsoft\.Matrix\(.*?\)/, + rfxnum = /^([\+\-]=)?([\d+.\-]+)(.*)$/, + rperc = /%/; + + // Steal some code from Modernizr + var m = document.createElement( 'modernizr' ), + m_style = m.style; + + function stripUnits(arg) { + return parseFloat(arg); + } + + /** + * Find the prefix that this browser uses + */ + function getVendorPrefix() { + var property = { + transformProperty : '', + MozTransform : '-moz-', + WebkitTransform : '-webkit-', + OTransform : '-o-', + msTransform : '-ms-' + }; + for (var p in property) { + if (typeof m_style[p] != 'undefined') { + return property[p]; + } + } + return null; + } + + function supportCssTransforms() { + if (typeof(window.Modernizr) !== 'undefined') { + return Modernizr.csstransforms; + } + + var props = [ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]; + for ( var i in props ) { + if ( m_style[ props[i] ] !== undefined ) { + return true; + } + } + } + + // Capture some basic properties + var vendorPrefix = getVendorPrefix(), + transformProperty = vendorPrefix !== null ? vendorPrefix + 'transform' : false, + transformOriginProperty = vendorPrefix !== null ? vendorPrefix + 'transform-origin' : false; + + // store support in the jQuery Support object + $.support.csstransforms = supportCssTransforms(); + + // IE9 public preview 6 requires the DOM names + if (vendorPrefix == '-ms-') { + transformProperty = 'msTransform'; + transformOriginProperty = 'msTransformOrigin'; + } + + /** + * Class for creating cross-browser transformations + * @constructor + */ + $.extend({ + transform: function(elem) { + // Cache the transform object on the element itself + elem.transform = this; + + /** + * The element we're working with + * @var jQueryCollection + */ + this.$elem = $(elem); + + /** + * Remember the matrix we're applying to help the safeOuterLength func + */ + this.applyingMatrix = false; + this.matrix = null; + + /** + * Remember the css height and width to save time + * This is only really used in IE + * @var Number + */ + this.height = null; + this.width = null; + this.outerHeight = null; + this.outerWidth = null; + + /** + * We need to know the box-sizing in IE for building the outerHeight and outerWidth + * @var string + */ + this.boxSizingValue = null; + this.boxSizingProperty = null; + + this.attr = null; + this.transformProperty = transformProperty; + this.transformOriginProperty = transformOriginProperty; + } + }); + + $.extend($.transform, { + /** + * @var Array list of all valid transform functions + */ + funcs: ['matrix', 'origin', 'reflect', 'reflectX', 'reflectXY', 'reflectY', 'rotate', 'scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY', 'translate', 'translateX', 'translateY'] + }); + + /** + * Create Transform as a jQuery plugin + * @param Object funcs + * @param Object options + */ + $.fn.transform = function(funcs, options) { + return this.each(function() { + var t = this.transform || new $.transform(this); + if (funcs) { + t.exec(funcs, options); + } + }); + }; + + $.transform.prototype = { + /** + * Applies all of the transformations + * @param Object funcs + * @param Object options + * forceMatrix - uses the matrix in all browsers + * preserve - tries to preserve the values from previous runs + */ + exec: function(funcs, options) { + // extend options + options = $.extend(true, { + forceMatrix: false, + preserve: false + }, options); + + // preserve the funcs from the previous run + this.attr = null; + if (options.preserve) { + funcs = $.extend(true, this.getAttrs(true, true), funcs); + } else { + funcs = $.extend(true, {}, funcs); // copy the object to prevent weirdness + } + + // Record the custom attributes on the element itself + this.setAttrs(funcs); + + // apply the funcs + if ($.support.csstransforms && !options.forceMatrix) { + // CSS3 is supported + return this.execFuncs(funcs); + } else if ($.browser.msie || ($.support.csstransforms && options.forceMatrix)) { + // Internet Explorer or Forced matrix + return this.execMatrix(funcs); + } + return false; + }, + + /** + * Applies all of the transformations as functions + * @param Object funcs + */ + execFuncs: function(funcs) { + var values = []; + + // construct a CSS string + for (var func in funcs) { + // handle origin separately + if (func == 'origin') { + this[func].apply(this, $.isArray(funcs[func]) ? funcs[func] : [funcs[func]]); + } else if ($.inArray(func, $.transform.funcs) !== -1) { + values.push(this.createTransformFunc(func, funcs[func])); + } + } + this.$elem.css(transformProperty, values.join(' ')); + return true; + }, + + /** + * Applies all of the transformations as a matrix + * @param Object funcs + */ + execMatrix: function(funcs) { + var matrix, + tempMatrix, + args; + + var elem = this.$elem[0], + _this = this; + function normalPixels(val, i) { + if (rperc.test(val)) { + // this really only applies to translation + return parseFloat(val) / 100 * _this['safeOuter' + (i ? 'Height' : 'Width')](); + } + return toPx(elem, val); + } + + var rtranslate = /translate[X|Y]?/, + trans = []; + + for (var func in funcs) { + switch ($.type(funcs[func])) { + case 'array': args = funcs[func]; break; + case 'string': args = $.map(funcs[func].split(','), $.trim); break; + default: args = [funcs[func]]; + } + + if ($.matrix[func]) { + + if ($.cssAngle[func]) { + // normalize on degrees + args = $.map(args, $.angle.toDegree); + } else if (!$.cssNumber[func]) { + // normalize to pixels + args = $.map(args, normalPixels); + } else { + // strip units + args = $.map(args, stripUnits); + } + + tempMatrix = $.matrix[func].apply(this, args); + if (rtranslate.test(func)) { + //defer translation + trans.push(tempMatrix); + } else { + matrix = matrix ? matrix.x(tempMatrix) : tempMatrix; + } + } else if (func == 'origin') { + this[func].apply(this, args); + } + } + + // check that we have a matrix + matrix = matrix || $.matrix.identity(); + + // Apply translation + $.each(trans, function(i, val) { matrix = matrix.x(val); }); + + // pull out the relevant values + var a = parseFloat(matrix.e(1,1).toFixed(6)), + b = parseFloat(matrix.e(2,1).toFixed(6)), + c = parseFloat(matrix.e(1,2).toFixed(6)), + d = parseFloat(matrix.e(2,2).toFixed(6)), + tx = matrix.rows === 3 ? parseFloat(matrix.e(1,3).toFixed(6)) : 0, + ty = matrix.rows === 3 ? parseFloat(matrix.e(2,3).toFixed(6)) : 0; + + //apply the transform to the element + if ($.support.csstransforms && vendorPrefix === '-moz-') { + // -moz- + this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + 'px, ' + ty + 'px)'); + } else if ($.support.csstransforms) { + // -webkit, -o-, w3c + // NOTE: WebKit and Opera don't allow units on the translate variables + this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + ', ' + ty + ')'); + } else if ($.browser.msie) { + // IE requires the special transform Filter + + //TODO: Use Nearest Neighbor during animation FilterType=\'nearest neighbor\' + var filterType = ', FilterType=\'nearest neighbor\''; //bilinear + var style = this.$elem[0].style; + var matrixFilter = 'progid:DXImageTransform.Microsoft.Matrix(' + + 'M11=' + a + ', M12=' + c + ', M21=' + b + ', M22=' + d + + ', sizingMethod=\'auto expand\'' + filterType + ')'; + var filter = style.filter || $.css( this.$elem[0], "filter" ) || ""; + style.filter = rmatrix.test(filter) ? filter.replace(rmatrix, matrixFilter) : filter ? filter + ' ' + matrixFilter : matrixFilter; + + // Let's know that we're applying post matrix fixes and the height/width will be static for a bit + this.applyingMatrix = true; + this.matrix = matrix; + + // IE can't set the origin or translate directly + this.fixPosition(matrix, tx, ty); + + this.applyingMatrix = false; + this.matrix = null; + } + return true; + }, + + /** + * Sets the transform-origin + * This really needs to be percentages + * @param Number x length + * @param Number y length + */ + origin: function(x, y) { + // use CSS in supported browsers + if ($.support.csstransforms) { + if (typeof y === 'undefined') { + this.$elem.css(transformOriginProperty, x); + } else { + this.$elem.css(transformOriginProperty, x + ' ' + y); + } + return true; + } + + // correct for keyword lengths + switch (x) { + case 'left': x = '0'; break; + case 'right': x = '100%'; break; + case 'center': // no break + case undefined: x = '50%'; + } + switch (y) { + case 'top': y = '0'; break; + case 'bottom': y = '100%'; break; + case 'center': // no break + case undefined: y = '50%'; //TODO: does this work? + } + + // store mixed values with units, assumed pixels + this.setAttr('origin', [ + rperc.test(x) ? x : toPx(this.$elem[0], x) + 'px', + rperc.test(y) ? y : toPx(this.$elem[0], y) + 'px' + ]); + //console.log(this.getAttr('origin')); + return true; + }, + + /** + * Create a function suitable for a CSS value + * @param string func + * @param Mixed value + */ + createTransformFunc: function(func, value) { + if (func.substr(0, 7) === 'reflect') { + // let's fake reflection, false value + // falsey sets an identity matrix + var m = value ? $.matrix[func]() : $.matrix.identity(); + return 'matrix(' + m.e(1,1) + ', ' + m.e(2,1) + ', ' + m.e(1,2) + ', ' + m.e(2,2) + ', 0, 0)'; + } + + //value = _correctUnits(func, value); + + if (func == 'matrix') { + if (vendorPrefix === '-moz-') { + value[4] = value[4] ? value[4] + 'px' : 0; + value[5] = value[5] ? value[5] + 'px' : 0; + } + } + return func + '(' + ($.isArray(value) ? value.join(', ') : value) + ')'; + }, + + /** + * @param Matrix matrix + * @param Number tx + * @param Number ty + * @param Number height + * @param Number width + */ + fixPosition: function(matrix, tx, ty, height, width) { + // now we need to fix it! + var calc = new $.matrix.calc(matrix, this.safeOuterHeight(), this.safeOuterWidth()), + origin = this.getAttr('origin'); // mixed percentages and px + + // translate a 0, 0 origin to the current origin + var offset = calc.originOffset(new $.matrix.V2( + rperc.test(origin[0]) ? parseFloat(origin[0])/100*calc.outerWidth : parseFloat(origin[0]), + rperc.test(origin[1]) ? parseFloat(origin[1])/100*calc.outerHeight : parseFloat(origin[1]) + )); + + // IE glues the top-most and left-most pixels of the transformed object to top/left of the original object + //TODO: This seems wrong in the calculations + var sides = calc.sides(); + + // Protect against an item that is already positioned + var cssPosition = this.$elem.css('position'); + if (cssPosition == 'static') { + cssPosition = 'relative'; + } + + //TODO: if the element is already positioned, we should attempt to respect it (somehow) + //NOTE: we could preserve our offset top and left in an attr on the elem + var pos = {top: 0, left: 0}; + + // Approximates transform-origin, tx, and ty + var css = { + 'position': cssPosition, + 'top': (offset.top + ty + sides.top + pos.top) + 'px', + 'left': (offset.left + tx + sides.left + pos.left) + 'px', + 'zoom': 1 + }; + + this.$elem.css(css); + } + }; + + /** + * Ensure that values have the appropriate units on them + * @param string func + * @param Mixed value + */ + function toPx(elem, val) { + var parts = rfxnum.exec($.trim(val)); + + if (parts[3] && parts[3] !== 'px') { + var prop = 'paddingBottom', + orig = $.style( elem, prop ); + + $.style( elem, prop, val ); + val = cur( elem, prop ); + $.style( elem, prop, orig ); + return val; + } + return parseFloat( val ); + } + + function cur(elem, prop) { + if ( elem[prop] != null && (!elem.style || elem.style[prop] == null) ) { + return elem[ prop ]; + } + + var r = parseFloat( $.css( elem, prop ) ); + return r && r > -10000 ? r : 0; + } +})(jQuery, this, this.document); + + +/////////////////////////////////////////////////////// +// Safe Outer Length +/////////////////////////////////////////////////////// +(function($, window, document, undefined) { + $.extend($.transform.prototype, { + /** + * @param void + * @return Number + */ + safeOuterHeight: function() { + return this.safeOuterLength('height'); + }, + + /** + * @param void + * @return Number + */ + safeOuterWidth: function() { + return this.safeOuterLength('width'); + }, + + /** + * Returns reliable outer dimensions for an object that may have been transformed. + * Only use this if the matrix isn't handy + * @param String dim height or width + * @return Number + */ + safeOuterLength: function(dim) { + var funcName = 'outer' + (dim == 'width' ? 'Width' : 'Height'); + + if (!$.support.csstransforms && $.browser.msie) { + // make the variables more generic + dim = dim == 'width' ? 'width' : 'height'; + + // if we're transforming and have a matrix; we can shortcut. + // the true outerHeight is the transformed outerHeight divided by the ratio. + // the ratio is equal to the height of a 1px by 1px box that has been transformed by the same matrix. + if (this.applyingMatrix && !this[funcName] && this.matrix) { + // calculate and return the correct size + var calc = new $.matrix.calc(this.matrix, 1, 1), + ratio = calc.offset(), + length = this.$elem[funcName]() / ratio[dim]; + this[funcName] = length; + + return length; + } else if (this.applyingMatrix && this[funcName]) { + // return the cached calculation + return this[funcName]; + } + + // map dimensions to box sides + var side = { + height: ['top', 'bottom'], + width: ['left', 'right'] + }; + + // setup some variables + var elem = this.$elem[0], + outerLen = parseFloat($.css(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width + boxSizingProp = this.boxSizingProperty, + boxSizingValue = this.boxSizingValue; + + // IE6 && IE7 will never have a box-sizing property, so fake it + if (!this.boxSizingProperty) { + boxSizingProp = this.boxSizingProperty = _findBoxSizingProperty() || 'box-sizing'; + boxSizingValue = this.boxSizingValue = this.$elem.css(boxSizingProp) || 'content-box'; + } + + // return it immediately if we already know it + if (this[funcName] && this[dim] == outerLen) { + return this[funcName]; + } else { + this[dim] = outerLen; + } + + // add in the padding and border + if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { + outerLen += parseFloat($.css(elem, 'padding-' + side[dim][0], true)) || 0 + + parseFloat($.css(elem, 'padding-' + side[dim][1], true)) || 0; + } + if (boxSizingProp && boxSizingValue == 'content-box') { + outerLen += parseFloat($.css(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + + parseFloat($.css(elem, 'border-' + side[dim][1] + '-width', true)) || 0; + } + + // remember and return the outerHeight + this[funcName] = outerLen; + return outerLen; + } + return this.$elem[funcName](); + } + }); + + /** + * Determine the correct property for checking the box-sizing property + * @param void + * @return string + */ + var _boxSizingProperty = null; + function _findBoxSizingProperty () { + if (_boxSizingProperty) { + return _boxSizingProperty; + } + + var property = { + boxSizing : 'box-sizing', + MozBoxSizing : '-moz-box-sizing', + WebkitBoxSizing : '-webkit-box-sizing', + OBoxSizing : '-o-box-sizing' + }, + elem = document.body; + + for (var p in property) { + if (typeof elem.style[p] != 'undefined') { + _boxSizingProperty = property[p]; + return _boxSizingProperty; + } + } + return null; + } +})(jQuery, this, this.document); + /////////////////////////////////////////////////////// // Attr diff --git a/dist/jquery.transform-0.9.3.min.js b/dist/jquery.transform-0.9.3.min.js index 9006041..d564189 100644 --- a/dist/jquery.transform-0.9.3.min.js +++ b/dist/jquery.transform-0.9.3.min.js @@ -6,6 +6,6 @@ * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * - * Date: Sat Dec 4 15:46:09 2010 -0800 + * Date: Sat Dec 4 16:40:39 2010 -0800 */ -(function(f,g,j,b){var h=/progid:DXImageTransform\.Microsoft\.Matrix\(.*?\)/,c=/^([\+\-]=)?([\d+.\-]+)(.*)$/,q=/%/;var d=j.createElement("modernizr"),e=d.style;function n(s){return parseFloat(s)}function l(){var s={transformProperty:"",MozTransform:"-moz-",WebkitTransform:"-webkit-",OTransform:"-o-",msTransform:"-ms-"};for(var t in s){if(typeof e[t]!="undefined"){return s[t]}}return null}function r(){if(typeof(g.Modernizr)!=="undefined"){return Modernizr.csstransforms}var t=["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"];for(var s in t){if(e[t[s]]!==b){return true}}}var a=l(),i=a!==null?a+"transform":false,k=a!==null?a+"transform-origin":false;f.support.csstransforms=r();if(a=="-ms-"){i="msTransform";k="msTransformOrigin"}f.extend({transform:function(s){s.transform=this;this.$elem=f(s);this.applyingMatrix=false;this.matrix=null;this.height=null;this.width=null;this.outerHeight=null;this.outerWidth=null;this.boxSizingValue=null;this.boxSizingProperty=null;this.attr=null;this.transformProperty=i;this.transformOriginProperty=k}});f.extend(f.transform,{funcs:["matrix","origin","reflect","reflectX","reflectXY","reflectY","rotate","scale","scaleX","scaleY","skew","skewX","skewY","translate","translateX","translateY"]});f.fn.transform=function(s,t){return this.each(function(){var u=this.transform||new f.transform(this);if(s){u.exec(s,t)}})};f.transform.prototype={exec:function(s,t){t=f.extend(true,{forceMatrix:false,preserve:false},t);this.attr=null;if(t.preserve){s=f.extend(true,this.getAttrs(true,true),s)}else{s=f.extend(true,{},s)}this.setAttrs(s);if(f.support.csstransforms&&!t.forceMatrix){return this.execFuncs(s)}else{if(f.browser.msie||(f.support.csstransforms&&t.forceMatrix)){return this.execMatrix(s)}}return false},execFuncs:function(t){var s=[];for(var u in t){if(u=="origin"){this[u].apply(this,f.isArray(t[u])?t[u]:[t[u]])}else{if(f.inArray(u,f.transform.funcs)!==-1){s.push(this.createTransformFunc(u,t[u]))}}}this.$elem.css(i,s.join(" "));return true},execMatrix:function(z){var C,x,t;var F=this.$elem[0],B=this;function A(N,M){if(q.test(N)){return parseFloat(N)/100*B["safeOuter"+(M?"Height":"Width")]()}return o(F,N)}var s=/translate[X|Y]?/,u=[];for(var v in z){switch(f.type(z[v])){case"array":t=z[v];break;case"string":t=f.map(z[v].split(","),f.trim);break;default:t=[z[v]]}if(f.matrix[v]){if(f.cssAngle[v]){t=f.map(t,f.angle.toDegree)}else{if(!f.cssNumber[v]){t=f.map(t,A)}else{t=f.map(t,n)}}x=f.matrix[v].apply(this,t);if(s.test(v)){u.push(x)}else{C=C?C.x(x):x}}else{if(v=="origin"){this[v].apply(this,t)}}}C=C||f.matrix.identity();f.each(u,function(M,N){C=C.x(N)});var K=parseFloat(C.e(1,1).toFixed(6)),I=parseFloat(C.e(2,1).toFixed(6)),H=parseFloat(C.e(1,2).toFixed(6)),G=parseFloat(C.e(2,2).toFixed(6)),L=C.rows===3?parseFloat(C.e(1,3).toFixed(6)):0,J=C.rows===3?parseFloat(C.e(2,3).toFixed(6)):0;if(f.support.csstransforms&&a==="-moz-"){this.$elem.css(i,"matrix("+K+", "+I+", "+H+", "+G+", "+L+"px, "+J+"px)")}else{if(f.support.csstransforms){this.$elem.css(i,"matrix("+K+", "+I+", "+H+", "+G+", "+L+", "+J+")")}else{if(f.browser.msie){var w=", FilterType='nearest neighbor'";var D=this.$elem[0].style;var E="progid:DXImageTransform.Microsoft.Matrix(M11="+K+", M12="+H+", M21="+I+", M22="+G+", sizingMethod='auto expand'"+w+")";var y=D.filter||f.curCSS(this.$elem[0],"filter")||"";D.filter=h.test(y)?y.replace(h,E):y?y+" "+E:E;this.applyingMatrix=true;this.matrix=C;this.fixPosition(C,L,J);this.applyingMatrix=false;this.matrix=null}}}return true},origin:function(s,t){if(f.support.csstransforms){if(typeof t==="undefined"){this.$elem.css(k,s)}else{this.$elem.css(k,s+" "+t)}return true}switch(s){case"left":s="0";break;case"right":s="100%";break;case"center":case b:s="50%"}switch(t){case"top":t="0";break;case"bottom":t="100%";break;case"center":case b:t="50%"}this.setAttr("origin",[q.test(s)?s:o(this.$elem[0],s)+"px",q.test(t)?t:o(this.$elem[0],t)+"px"]);return true},createTransformFunc:function(t,u){if(t.substr(0,7)==="reflect"){var s=u?f.matrix[t]():f.matrix.identity();return"matrix("+s.e(1,1)+", "+s.e(2,1)+", "+s.e(1,2)+", "+s.e(2,2)+", 0, 0)"}if(t=="matrix"){if(a==="-moz-"){u[4]=u[4]?u[4]+"px":0;u[5]=u[5]?u[5]+"px":0}}return t+"("+(f.isArray(u)?u.join(", "):u)+")"},fixPosition:function(B,y,x,D,s){var w=new f.matrix.calc(B,this.safeOuterHeight(),this.safeOuterWidth()),C=this.getAttr("origin");var v=w.originOffset(new f.matrix.V2(q.test(C[0])?parseFloat(C[0])/100*w.outerWidth:parseFloat(C[0]),q.test(C[1])?parseFloat(C[1])/100*w.outerHeight:parseFloat(C[1])));var t=w.sides();var u=this.$elem.css("position");if(u=="static"){u="relative"}var A={top:0,left:0};var z={position:u,top:(v.top+x+t.top+A.top)+"px",left:(v.left+y+t.left+A.left)+"px",zoom:1};this.$elem.css(z)}};function o(s,u){var t=c.exec(f.trim(u));if(t[3]&&t[3]!=="px"){var w="paddingBottom",v=f.style(s,w);f.style(s,w,u);u=p(s,w);f.style(s,w,v);return u}return parseFloat(u)}function p(t,u){if(t[u]!=null&&(!t.style||t.style[u]==null)){return t[u]}var s=parseFloat(f.css(t,u));return s&&s>-10000?s:0}})(jQuery,this,this.document);(function(d,c,a,f){d.extend(d.transform.prototype,{safeOuterHeight:function(){return this.safeOuterLength("height")},safeOuterWidth:function(){return this.safeOuterLength("width")},safeOuterLength:function(l){var p="outer"+(l=="width"?"Width":"Height");if(!d.support.csstransforms&&d.browser.msie){l=l=="width"?"width":"height";if(this.applyingMatrix&&!this[p]&&this.matrix){var k=new d.matrix.calc(this.matrix,1,1),n=k.offset(),g=this.$elem[p]()/n[l];this[p]=g;return g}else{if(this.applyingMatrix&&this[p]){return this[p]}}var o={height:["top","bottom"],width:["left","right"]};var h=this.$elem[0],j=parseFloat(d.curCSS(h,l,true)),q=this.boxSizingProperty,i=this.boxSizingValue;if(!this.boxSizingProperty){q=this.boxSizingProperty=e()||"box-sizing";i=this.boxSizingValue=this.$elem.css(q)||"content-box"}if(this[p]&&this[l]==j){return this[p]}else{this[l]=j}if(q&&(i=="padding-box"||i=="content-box")){j+=parseFloat(d.curCSS(h,"padding-"+o[l][0],true))||0+parseFloat(d.curCSS(h,"padding-"+o[l][1],true))||0}if(q&&i=="content-box"){j+=parseFloat(d.curCSS(h,"border-"+o[l][0]+"-width",true))||0+parseFloat(d.curCSS(h,"border-"+o[l][1]+"-width",true))||0}this[p]=j;return j}return this.$elem[p]()}});var b=null;function e(){if(b){return b}var h={boxSizing:"box-sizing",MozBoxSizing:"-moz-box-sizing",WebkitBoxSizing:"-webkit-box-sizing",OBoxSizing:"-o-box-sizing"},g=a.body;for(var i in h){if(typeof g.style[i]!="undefined"){b=h[i];return b}}return null}})(jQuery,this,this.document);(function(g,f,b,h){var d=/([\w\-]*?)\((.*?)\)/g,a="data-transform",e=/\s/,c=/,\s?/;g.extend(g.transform.prototype,{setAttrs:function(i){var j="",l;for(var k in i){l=i[k];if(g.isArray(l)){l=l.join(", ")}j+=" "+k+"("+l+")"}this.attr=g.trim(j);this.$elem.attr(a,this.attr)},setAttr:function(k,l){if(g.isArray(l)){l=l.join(", ")}var j=this.attr||this.$elem.attr(a);if(!j||j.indexOf(k)==-1){this.attr=g.trim(j+" "+k+"("+l+")");this.$elem.attr(a,this.attr)}else{var i=[],n;d.lastIndex=0;while(n=d.exec(j)){if(k==n[1]){i.push(k+"("+l+")")}else{i.push(n[0])}}this.attr=i.join(" ");this.$elem.attr(a,this.attr)}},getAttrs:function(){var j=this.attr||this.$elem.attr(a);if(!j){return{}}var i={},l,k;d.lastIndex=0;while((l=d.exec(j))!==null){if(l){k=l[2].split(c);i[l[1]]=k.length==1?k[0]:k}}return i},getAttr:function(j){var i=this.getAttrs();if(typeof i[j]!=="undefined"){return i[j]}if(j==="origin"&&g.support.csstransforms){return this.$elem.css(this.transformOriginProperty).split(e)}else{if(j==="origin"){return["50%","50%"]}}return g.cssDefault[j]||0}});if(typeof(g.cssAngle)=="undefined"){g.cssAngle={}}g.extend(g.cssAngle,{rotate:true,skew:true,skewX:true,skewY:true});if(typeof(g.cssDefault)=="undefined"){g.cssDefault={}}g.extend(g.cssDefault,{scale:[1,1],scaleX:1,scaleY:1,matrix:[1,0,0,1,0,0],origin:["50%","50%"],reflect:[1,0,0,1,0,0],reflectX:[1,0,0,1,0,0],reflectXY:[1,0,0,1,0,0],reflectY:[1,0,0,1,0,0]});if(typeof(g.cssMultipleValues)=="undefined"){g.cssMultipleValues={}}g.extend(g.cssMultipleValues,{matrix:6,origin:{length:2,duplicate:true},reflect:6,reflectX:6,reflectXY:6,reflectY:6,scale:{length:2,duplicate:true},skew:2,translate:2});g.extend(g.cssNumber,{matrix:true,reflect:true,reflectX:true,reflectXY:true,reflectY:true,scale:true,scaleX:true,scaleY:true});g.each(g.transform.funcs,function(j,k){g.cssHooks[k]={set:function(n,o){var l=n.transform||new g.transform(n),i={};i[k]=o;l.exec(i,{preserve:true})},get:function(n,l){var i=n.transform||new g.transform(n);return i.getAttr(k)}}});g.each(["reflect","reflectX","reflectXY","reflectY"],function(j,k){g.cssHooks[k].get=function(n,l){var i=n.transform||new g.transform(n);return i.getAttr("matrix")||g.cssDefault[k]}})})(jQuery,this,this.document);(function(e,g,h,c){var d=/^([+\-]=)?([\d+.\-]+)(.*)$/;var a=e.fn.animate;e.fn.animate=function(p,l,o,n){var k=e.speed(l,o,n),j=e.cssMultipleValues;k.complete=k.old;if(!e.isEmptyObject(p)){if(typeof k.original==="undefined"){k.original={}}e.each(p,function(s,u){if(j[s]||e.cssAngle[s]||(!e.cssNumber[s]&&e.inArray(s,e.transform.funcs)!==-1)){var t=null;if(jQuery.isArray(p[s])){var r=1,q=u.length;if(j[s]){r=(typeof j[s].length==="undefined"?j[s]:j[s].length)}if(q>r||(q-10000?j:0}var f=e.fx.prototype.custom;e.fx.prototype.custom=function(u,v,w){var y=e.cssMultipleValues[this.prop],p=e.cssAngle[this.prop];if(y||(!e.cssNumber[this.prop]&&e.inArray(this.prop,e.transform.funcs)!==-1)){this.values=[];if(!y){y=1}var x=this.options.original[this.prop],t=e(this.elem).css(this.prop),j=e.cssDefault[this.prop]||0;if(!e.isArray(t)){t=[t]}if(!e.isArray(x)){if(e.type(x)==="string"){x=x.split(",")}else{x=[x]}}var l=y.length||y,s=0;while(x.lengthi||h>i||k<1||h<1){return 0}return this.elements[(k-1)*j+h-1]},decompose:function(){var v=this.e(1,1),t=this.e(2,1),q=this.e(1,2),p=this.e(2,2),o=this.e(1,3),n=this.e(2,3);if(Math.abs(v*p-t*q)<0.01){return{rotate:0+"deg",skewX:0+"deg",scaleX:1,scaleY:1,translateX:0+"px",translateY:0+"px"}}var l=o,j=n;var u=Math.sqrt(v*v+t*t);v=v/u;t=t/u;var i=v*q+t*p;q-=v*i;p-=t*i;var s=Math.sqrt(q*q+p*p);q=q/s;p=p/s;i=i/s;if((v*p-t*q)<0){v=-v;t=-t;u=-u}var w=f.angle.radianToDegree;var h=w(Math.atan2(t,v));i=w(Math.atan(i));return{rotate:h+"deg",skewX:i+"deg",scaleX:u,scaleY:s,translateX:l+"px",translateY:j+"px"}}};f.extend(d.M2x2.prototype,c,{toM3x3:function(){var h=this.elements;return new d.M3x3(h[0],h[1],0,h[2],h[3],0,0,0,1)},x:function(j){var k=typeof(j.rows)==="undefined";if(!k&&j.rows==3){return this.toM3x3().x(j)}var i=this.elements,h=j.elements;if(k&&h.length==2){return new d.V2(i[0]*h[0]+i[1]*h[1],i[2]*h[0]+i[3]*h[1])}else{if(h.length==i.length){return new d.M2x2(i[0]*h[0]+i[1]*h[2],i[0]*h[1]+i[1]*h[3],i[2]*h[0]+i[3]*h[2],i[2]*h[1]+i[3]*h[3])}}return false},inverse:function(){var i=1/this.determinant(),h=this.elements;return new d.M2x2(i*h[3],i*-h[1],i*-h[2],i*h[0])},determinant:function(){var h=this.elements;return h[0]*h[3]-h[1]*h[2]}});f.extend(d.M3x3.prototype,c,{x:function(j){var k=typeof(j.rows)==="undefined";if(!k&&j.rows<3){j=j.toM3x3()}var i=this.elements,h=j.elements;if(k&&h.length==3){return new d.V3(i[0]*h[0]+i[1]*h[1]+i[2]*h[2],i[3]*h[0]+i[4]*h[1]+i[5]*h[2],i[6]*h[0]+i[7]*h[1]+i[8]*h[2])}else{if(h.length==i.length){return new d.M3x3(i[0]*h[0]+i[1]*h[3]+i[2]*h[6],i[0]*h[1]+i[1]*h[4]+i[2]*h[7],i[0]*h[2]+i[1]*h[5]+i[2]*h[8],i[3]*h[0]+i[4]*h[3]+i[5]*h[6],i[3]*h[1]+i[4]*h[4]+i[5]*h[7],i[3]*h[2]+i[4]*h[5]+i[5]*h[8],i[6]*h[0]+i[7]*h[3]+i[8]*h[6],i[6]*h[1]+i[7]*h[4]+i[8]*h[7],i[6]*h[2]+i[7]*h[5]+i[8]*h[8])}}return false},inverse:function(){var i=1/this.determinant(),h=this.elements;return new d.M3x3(i*(h[8]*h[4]-h[7]*h[5]),i*(-(h[8]*h[1]-h[7]*h[2])),i*(h[5]*h[1]-h[4]*h[2]),i*(-(h[8]*h[3]-h[6]*h[5])),i*(h[8]*h[0]-h[6]*h[2]),i*(-(h[5]*h[0]-h[3]*h[2])),i*(h[7]*h[3]-h[6]*h[4]),i*(-(h[7]*h[0]-h[6]*h[1])),i*(h[4]*h[0]-h[3]*h[1]))},determinant:function(){var h=this.elements;return h[0]*(h[8]*h[4]-h[7]*h[5])-h[3]*(h[8]*h[1]-h[7]*h[2])+h[6]*(h[5]*h[1]-h[4]*h[2])}});var a={e:function(h){return this.elements[h-1]}};f.extend(d.V2.prototype,a);f.extend(d.V3.prototype,a)})(jQuery,this,this.document);(function(c,b,a,d){if(typeof(c.matrix)=="undefined"){c.extend({matrix:{}})}c.extend(c.matrix,{calc:function(e,f,g){this.matrix=e;this.outerHeight=f;this.outerWidth=g}});c.matrix.calc.prototype={coord:function(e,i,h){h=typeof(h)!=="undefined"?h:0;var g=this.matrix,f;switch(g.rows){case 2:f=g.x(new c.matrix.V2(e,i));break;case 3:f=g.x(new c.matrix.V3(e,i,h));break}return f},corners:function(e,h){var f=!(typeof(e)!=="undefined"||typeof(h)!=="undefined"),g;if(!this.c||!f){h=h||this.outerHeight;e=e||this.outerWidth;g={tl:this.coord(0,0),bl:this.coord(0,h),tr:this.coord(e,0),br:this.coord(e,h)}}else{g=this.c}if(f){this.c=g}return g},sides:function(e){var f=e||this.corners();return{top:Math.min(f.tl.e(2),f.tr.e(2),f.br.e(2),f.bl.e(2)),bottom:Math.max(f.tl.e(2),f.tr.e(2),f.br.e(2),f.bl.e(2)),left:Math.min(f.tl.e(1),f.tr.e(1),f.br.e(1),f.bl.e(1)),right:Math.max(f.tl.e(1),f.tr.e(1),f.br.e(1),f.bl.e(1))}},offset:function(e){var f=this.sides(e);return{height:Math.abs(f.bottom-f.top),width:Math.abs(f.right-f.left)}},area:function(e){var h=e||this.corners();var g={x:h.tr.e(1)-h.tl.e(1)+h.br.e(1)-h.bl.e(1),y:h.tr.e(2)-h.tl.e(2)+h.br.e(2)-h.bl.e(2)},f={x:h.bl.e(1)-h.tl.e(1)+h.br.e(1)-h.tr.e(1),y:h.bl.e(2)-h.tl.e(2)+h.br.e(2)-h.tr.e(2)};return 0.25*Math.abs(g.e(1)*f.e(2)-g.e(2)*f.e(1))},nonAffinity:function(){var f=this.sides(),g=f.top-f.bottom,e=f.left-f.right;return parseFloat(parseFloat(Math.abs((Math.pow(g,2)+Math.pow(e,2))/(f.top*f.bottom+f.left*f.right))).toFixed(8))},originOffset:function(h,g){h=h?h:new c.matrix.V2(this.outerWidth*0.5,this.outerHeight*0.5);g=g?g:new c.matrix.V2(0,0);var e=this.coord(h.e(1),h.e(2));var f=this.coord(g.e(1),g.e(2));return{top:(f.e(2)-g.e(2))-(e.e(2)-h.e(2)),left:(f.e(1)-g.e(1))-(e.e(1)-h.e(1))}}}})(jQuery,this,this.document);(function(e,d,a,f){if(typeof(e.matrix)=="undefined"){e.extend({matrix:{}})}var c=e.matrix,g=c.M2x2,b=c.M3x3;e.extend(c,{identity:function(k){k=k||2;var l=k*k,n=new Array(l),j=k+1;for(var h=0;h-10000?s:0}})(jQuery,this,this.document);(function(d,c,a,f){d.extend(d.transform.prototype,{safeOuterHeight:function(){return this.safeOuterLength("height")},safeOuterWidth:function(){return this.safeOuterLength("width")},safeOuterLength:function(l){var p="outer"+(l=="width"?"Width":"Height");if(!d.support.csstransforms&&d.browser.msie){l=l=="width"?"width":"height";if(this.applyingMatrix&&!this[p]&&this.matrix){var k=new d.matrix.calc(this.matrix,1,1),n=k.offset(),g=this.$elem[p]()/n[l];this[p]=g;return g}else{if(this.applyingMatrix&&this[p]){return this[p]}}var o={height:["top","bottom"],width:["left","right"]};var h=this.$elem[0],j=parseFloat(d.css(h,l,true)),q=this.boxSizingProperty,i=this.boxSizingValue;if(!this.boxSizingProperty){q=this.boxSizingProperty=e()||"box-sizing";i=this.boxSizingValue=this.$elem.css(q)||"content-box"}if(this[p]&&this[l]==j){return this[p]}else{this[l]=j}if(q&&(i=="padding-box"||i=="content-box")){j+=parseFloat(d.css(h,"padding-"+o[l][0],true))||0+parseFloat(d.css(h,"padding-"+o[l][1],true))||0}if(q&&i=="content-box"){j+=parseFloat(d.css(h,"border-"+o[l][0]+"-width",true))||0+parseFloat(d.css(h,"border-"+o[l][1]+"-width",true))||0}this[p]=j;return j}return this.$elem[p]()}});var b=null;function e(){if(b){return b}var h={boxSizing:"box-sizing",MozBoxSizing:"-moz-box-sizing",WebkitBoxSizing:"-webkit-box-sizing",OBoxSizing:"-o-box-sizing"},g=a.body;for(var i in h){if(typeof g.style[i]!="undefined"){b=h[i];return b}}return null}})(jQuery,this,this.document);(function(g,f,b,h){var d=/([\w\-]*?)\((.*?)\)/g,a="data-transform",e=/\s/,c=/,\s?/;g.extend(g.transform.prototype,{setAttrs:function(i){var j="",l;for(var k in i){l=i[k];if(g.isArray(l)){l=l.join(", ")}j+=" "+k+"("+l+")"}this.attr=g.trim(j);this.$elem.attr(a,this.attr)},setAttr:function(k,l){if(g.isArray(l)){l=l.join(", ")}var j=this.attr||this.$elem.attr(a);if(!j||j.indexOf(k)==-1){this.attr=g.trim(j+" "+k+"("+l+")");this.$elem.attr(a,this.attr)}else{var i=[],n;d.lastIndex=0;while(n=d.exec(j)){if(k==n[1]){i.push(k+"("+l+")")}else{i.push(n[0])}}this.attr=i.join(" ");this.$elem.attr(a,this.attr)}},getAttrs:function(){var j=this.attr||this.$elem.attr(a);if(!j){return{}}var i={},l,k;d.lastIndex=0;while((l=d.exec(j))!==null){if(l){k=l[2].split(c);i[l[1]]=k.length==1?k[0]:k}}return i},getAttr:function(j){var i=this.getAttrs();if(typeof i[j]!=="undefined"){return i[j]}if(j==="origin"&&g.support.csstransforms){return this.$elem.css(this.transformOriginProperty).split(e)}else{if(j==="origin"){return["50%","50%"]}}return g.cssDefault[j]||0}});if(typeof(g.cssAngle)=="undefined"){g.cssAngle={}}g.extend(g.cssAngle,{rotate:true,skew:true,skewX:true,skewY:true});if(typeof(g.cssDefault)=="undefined"){g.cssDefault={}}g.extend(g.cssDefault,{scale:[1,1],scaleX:1,scaleY:1,matrix:[1,0,0,1,0,0],origin:["50%","50%"],reflect:[1,0,0,1,0,0],reflectX:[1,0,0,1,0,0],reflectXY:[1,0,0,1,0,0],reflectY:[1,0,0,1,0,0]});if(typeof(g.cssMultipleValues)=="undefined"){g.cssMultipleValues={}}g.extend(g.cssMultipleValues,{matrix:6,origin:{length:2,duplicate:true},reflect:6,reflectX:6,reflectXY:6,reflectY:6,scale:{length:2,duplicate:true},skew:2,translate:2});g.extend(g.cssNumber,{matrix:true,reflect:true,reflectX:true,reflectXY:true,reflectY:true,scale:true,scaleX:true,scaleY:true});g.each(g.transform.funcs,function(j,k){g.cssHooks[k]={set:function(n,o){var l=n.transform||new g.transform(n),i={};i[k]=o;l.exec(i,{preserve:true})},get:function(n,l){var i=n.transform||new g.transform(n);return i.getAttr(k)}}});g.each(["reflect","reflectX","reflectXY","reflectY"],function(j,k){g.cssHooks[k].get=function(n,l){var i=n.transform||new g.transform(n);return i.getAttr("matrix")||g.cssDefault[k]}})})(jQuery,this,this.document);(function(e,g,h,c){var d=/^([+\-]=)?([\d+.\-]+)(.*)$/;var a=e.fn.animate;e.fn.animate=function(p,l,o,n){var k=e.speed(l,o,n),j=e.cssMultipleValues;k.complete=k.old;if(!e.isEmptyObject(p)){if(typeof k.original==="undefined"){k.original={}}e.each(p,function(s,u){if(j[s]||e.cssAngle[s]||(!e.cssNumber[s]&&e.inArray(s,e.transform.funcs)!==-1)){var t=null;if(jQuery.isArray(p[s])){var r=1,q=u.length;if(j[s]){r=(typeof j[s].length==="undefined"?j[s]:j[s].length)}if(q>r||(q-10000?j:0}var f=e.fx.prototype.custom;e.fx.prototype.custom=function(u,v,w){var y=e.cssMultipleValues[this.prop],p=e.cssAngle[this.prop];if(y||(!e.cssNumber[this.prop]&&e.inArray(this.prop,e.transform.funcs)!==-1)){this.values=[];if(!y){y=1}var x=this.options.original[this.prop],t=e(this.elem).css(this.prop),j=e.cssDefault[this.prop]||0;if(!e.isArray(t)){t=[t]}if(!e.isArray(x)){if(e.type(x)==="string"){x=x.split(",")}else{x=[x]}}var l=y.length||y,s=0;while(x.lengthi||h>i||k<1||h<1){return 0}return this.elements[(k-1)*j+h-1]},decompose:function(){var v=this.e(1,1),t=this.e(2,1),q=this.e(1,2),p=this.e(2,2),o=this.e(1,3),n=this.e(2,3);if(Math.abs(v*p-t*q)<0.01){return{rotate:0+"deg",skewX:0+"deg",scaleX:1,scaleY:1,translateX:0+"px",translateY:0+"px"}}var l=o,j=n;var u=Math.sqrt(v*v+t*t);v=v/u;t=t/u;var i=v*q+t*p;q-=v*i;p-=t*i;var s=Math.sqrt(q*q+p*p);q=q/s;p=p/s;i=i/s;if((v*p-t*q)<0){v=-v;t=-t;u=-u}var w=f.angle.radianToDegree;var h=w(Math.atan2(t,v));i=w(Math.atan(i));return{rotate:h+"deg",skewX:i+"deg",scaleX:u,scaleY:s,translateX:l+"px",translateY:j+"px"}}};f.extend(d.M2x2.prototype,c,{toM3x3:function(){var h=this.elements;return new d.M3x3(h[0],h[1],0,h[2],h[3],0,0,0,1)},x:function(j){var k=typeof(j.rows)==="undefined";if(!k&&j.rows==3){return this.toM3x3().x(j)}var i=this.elements,h=j.elements;if(k&&h.length==2){return new d.V2(i[0]*h[0]+i[1]*h[1],i[2]*h[0]+i[3]*h[1])}else{if(h.length==i.length){return new d.M2x2(i[0]*h[0]+i[1]*h[2],i[0]*h[1]+i[1]*h[3],i[2]*h[0]+i[3]*h[2],i[2]*h[1]+i[3]*h[3])}}return false},inverse:function(){var i=1/this.determinant(),h=this.elements;return new d.M2x2(i*h[3],i*-h[1],i*-h[2],i*h[0])},determinant:function(){var h=this.elements;return h[0]*h[3]-h[1]*h[2]}});f.extend(d.M3x3.prototype,c,{x:function(j){var k=typeof(j.rows)==="undefined";if(!k&&j.rows<3){j=j.toM3x3()}var i=this.elements,h=j.elements;if(k&&h.length==3){return new d.V3(i[0]*h[0]+i[1]*h[1]+i[2]*h[2],i[3]*h[0]+i[4]*h[1]+i[5]*h[2],i[6]*h[0]+i[7]*h[1]+i[8]*h[2])}else{if(h.length==i.length){return new d.M3x3(i[0]*h[0]+i[1]*h[3]+i[2]*h[6],i[0]*h[1]+i[1]*h[4]+i[2]*h[7],i[0]*h[2]+i[1]*h[5]+i[2]*h[8],i[3]*h[0]+i[4]*h[3]+i[5]*h[6],i[3]*h[1]+i[4]*h[4]+i[5]*h[7],i[3]*h[2]+i[4]*h[5]+i[5]*h[8],i[6]*h[0]+i[7]*h[3]+i[8]*h[6],i[6]*h[1]+i[7]*h[4]+i[8]*h[7],i[6]*h[2]+i[7]*h[5]+i[8]*h[8])}}return false},inverse:function(){var i=1/this.determinant(),h=this.elements;return new d.M3x3(i*(h[8]*h[4]-h[7]*h[5]),i*(-(h[8]*h[1]-h[7]*h[2])),i*(h[5]*h[1]-h[4]*h[2]),i*(-(h[8]*h[3]-h[6]*h[5])),i*(h[8]*h[0]-h[6]*h[2]),i*(-(h[5]*h[0]-h[3]*h[2])),i*(h[7]*h[3]-h[6]*h[4]),i*(-(h[7]*h[0]-h[6]*h[1])),i*(h[4]*h[0]-h[3]*h[1]))},determinant:function(){var h=this.elements;return h[0]*(h[8]*h[4]-h[7]*h[5])-h[3]*(h[8]*h[1]-h[7]*h[2])+h[6]*(h[5]*h[1]-h[4]*h[2])}});var a={e:function(h){return this.elements[h-1]}};f.extend(d.V2.prototype,a);f.extend(d.V3.prototype,a)})(jQuery,this,this.document);(function(c,b,a,d){if(typeof(c.matrix)=="undefined"){c.extend({matrix:{}})}c.extend(c.matrix,{calc:function(e,f,g){this.matrix=e;this.outerHeight=f;this.outerWidth=g}});c.matrix.calc.prototype={coord:function(e,i,h){h=typeof(h)!=="undefined"?h:0;var g=this.matrix,f;switch(g.rows){case 2:f=g.x(new c.matrix.V2(e,i));break;case 3:f=g.x(new c.matrix.V3(e,i,h));break}return f},corners:function(e,h){var f=!(typeof(e)!=="undefined"||typeof(h)!=="undefined"),g;if(!this.c||!f){h=h||this.outerHeight;e=e||this.outerWidth;g={tl:this.coord(0,0),bl:this.coord(0,h),tr:this.coord(e,0),br:this.coord(e,h)}}else{g=this.c}if(f){this.c=g}return g},sides:function(e){var f=e||this.corners();return{top:Math.min(f.tl.e(2),f.tr.e(2),f.br.e(2),f.bl.e(2)),bottom:Math.max(f.tl.e(2),f.tr.e(2),f.br.e(2),f.bl.e(2)),left:Math.min(f.tl.e(1),f.tr.e(1),f.br.e(1),f.bl.e(1)),right:Math.max(f.tl.e(1),f.tr.e(1),f.br.e(1),f.bl.e(1))}},offset:function(e){var f=this.sides(e);return{height:Math.abs(f.bottom-f.top),width:Math.abs(f.right-f.left)}},area:function(e){var h=e||this.corners();var g={x:h.tr.e(1)-h.tl.e(1)+h.br.e(1)-h.bl.e(1),y:h.tr.e(2)-h.tl.e(2)+h.br.e(2)-h.bl.e(2)},f={x:h.bl.e(1)-h.tl.e(1)+h.br.e(1)-h.tr.e(1),y:h.bl.e(2)-h.tl.e(2)+h.br.e(2)-h.tr.e(2)};return 0.25*Math.abs(g.e(1)*f.e(2)-g.e(2)*f.e(1))},nonAffinity:function(){var f=this.sides(),g=f.top-f.bottom,e=f.left-f.right;return parseFloat(parseFloat(Math.abs((Math.pow(g,2)+Math.pow(e,2))/(f.top*f.bottom+f.left*f.right))).toFixed(8))},originOffset:function(h,g){h=h?h:new c.matrix.V2(this.outerWidth*0.5,this.outerHeight*0.5);g=g?g:new c.matrix.V2(0,0);var e=this.coord(h.e(1),h.e(2));var f=this.coord(g.e(1),g.e(2));return{top:(f.e(2)-g.e(2))-(e.e(2)-h.e(2)),left:(f.e(1)-g.e(1))-(e.e(1)-h.e(1))}}}})(jQuery,this,this.document);(function(e,d,a,f){if(typeof(e.matrix)=="undefined"){e.extend({matrix:{}})}var c=e.matrix,g=c.M2x2,b=c.M3x3;e.extend(c,{identity:function(k){k=k||2;var l=k*k,n=new Array(l),j=k+1;for(var h=0;h -10000 ? r : 0; - } -})(jQuery, this, this.document); - - -/////////////////////////////////////////////////////// -// Safe Outer Length -/////////////////////////////////////////////////////// -(function($, window, document, undefined) { - $.extend($.transform.prototype, { - /** - * @param void - * @return Number - */ - safeOuterHeight: function() { - return this.safeOuterLength('height'); - }, - - /** - * @param void - * @return Number - */ - safeOuterWidth: function() { - return this.safeOuterLength('width'); - }, - - /** - * Returns reliable outer dimensions for an object that may have been transformed. - * Only use this if the matrix isn't handy - * @param String dim height or width - * @return Number - */ - safeOuterLength: function(dim) { - var funcName = 'outer' + (dim == 'width' ? 'Width' : 'Height'); - - if (!$.support.csstransforms && $.browser.msie) { - // make the variables more generic - dim = dim == 'width' ? 'width' : 'height'; - - // if we're transforming and have a matrix; we can shortcut. - // the true outerHeight is the transformed outerHeight divided by the ratio. - // the ratio is equal to the height of a 1px by 1px box that has been transformed by the same matrix. - if (this.applyingMatrix && !this[funcName] && this.matrix) { - // calculate and return the correct size - var calc = new $.matrix.calc(this.matrix, 1, 1), - ratio = calc.offset(), - length = this.$elem[funcName]() / ratio[dim]; - this[funcName] = length; - - return length; - } else if (this.applyingMatrix && this[funcName]) { - // return the cached calculation - return this[funcName]; - } - - // map dimensions to box sides - var side = { - height: ['top', 'bottom'], - width: ['left', 'right'] - }; - - // setup some variables - var elem = this.$elem[0], - outerLen = parseFloat($.curCSS(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width - boxSizingProp = this.boxSizingProperty, - boxSizingValue = this.boxSizingValue; - - // IE6 && IE7 will never have a box-sizing property, so fake it - if (!this.boxSizingProperty) { - boxSizingProp = this.boxSizingProperty = _findBoxSizingProperty() || 'box-sizing'; - boxSizingValue = this.boxSizingValue = this.$elem.css(boxSizingProp) || 'content-box'; - } - - // return it immediately if we already know it - if (this[funcName] && this[dim] == outerLen) { - return this[funcName]; - } else { - this[dim] = outerLen; - } - - // add in the padding and border - if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { - outerLen += parseFloat($.curCSS(elem, 'padding-' + side[dim][0], true)) || 0 + - parseFloat($.curCSS(elem, 'padding-' + side[dim][1], true)) || 0; - } - if (boxSizingProp && boxSizingValue == 'content-box') { - outerLen += parseFloat($.curCSS(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + - parseFloat($.curCSS(elem, 'border-' + side[dim][1] + '-width', true)) || 0; - } - - // remember and return the outerHeight - this[funcName] = outerLen; - return outerLen; - } - return this.$elem[funcName](); - } - }); - - /** - * Determine the correct property for checking the box-sizing property - * @param void - * @return string - */ - var _boxSizingProperty = null; - function _findBoxSizingProperty () { - if (_boxSizingProperty) { - return _boxSizingProperty; - } - - var property = { - boxSizing : 'box-sizing', - MozBoxSizing : '-moz-box-sizing', - WebkitBoxSizing : '-webkit-box-sizing', - OBoxSizing : '-o-box-sizing' - }, - elem = document.body; - - for (var p in property) { - if (typeof elem.style[p] != 'undefined') { - _boxSizingProperty = property[p]; - return _boxSizingProperty; - } - } - return null; - } -})(jQuery, this, this.document); - +/*! + * jQuery 2d Transform v0.9.3 + * http://wiki.github.com/heygrady/transform/ + * + * Copyright 2010, Grady Kuhnline + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Date: Sat Dec 4 16:40:39 2010 -0800 + */ +/////////////////////////////////////////////////////// +// Transform +/////////////////////////////////////////////////////// +(function($, window, document, undefined) { + /** + * @var Regex identify the matrix filter in IE + */ + var rmatrix = /progid:DXImageTransform\.Microsoft\.Matrix\(.*?\)/, + rfxnum = /^([\+\-]=)?([\d+.\-]+)(.*)$/, + rperc = /%/; + + // Steal some code from Modernizr + var m = document.createElement( 'modernizr' ), + m_style = m.style; + + function stripUnits(arg) { + return parseFloat(arg); + } + + /** + * Find the prefix that this browser uses + */ + function getVendorPrefix() { + var property = { + transformProperty : '', + MozTransform : '-moz-', + WebkitTransform : '-webkit-', + OTransform : '-o-', + msTransform : '-ms-' + }; + for (var p in property) { + if (typeof m_style[p] != 'undefined') { + return property[p]; + } + } + return null; + } + + function supportCssTransforms() { + if (typeof(window.Modernizr) !== 'undefined') { + return Modernizr.csstransforms; + } + + var props = [ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]; + for ( var i in props ) { + if ( m_style[ props[i] ] !== undefined ) { + return true; + } + } + } + + // Capture some basic properties + var vendorPrefix = getVendorPrefix(), + transformProperty = vendorPrefix !== null ? vendorPrefix + 'transform' : false, + transformOriginProperty = vendorPrefix !== null ? vendorPrefix + 'transform-origin' : false; + + // store support in the jQuery Support object + $.support.csstransforms = supportCssTransforms(); + + // IE9 public preview 6 requires the DOM names + if (vendorPrefix == '-ms-') { + transformProperty = 'msTransform'; + transformOriginProperty = 'msTransformOrigin'; + } + + /** + * Class for creating cross-browser transformations + * @constructor + */ + $.extend({ + transform: function(elem) { + // Cache the transform object on the element itself + elem.transform = this; + + /** + * The element we're working with + * @var jQueryCollection + */ + this.$elem = $(elem); + + /** + * Remember the matrix we're applying to help the safeOuterLength func + */ + this.applyingMatrix = false; + this.matrix = null; + + /** + * Remember the css height and width to save time + * This is only really used in IE + * @var Number + */ + this.height = null; + this.width = null; + this.outerHeight = null; + this.outerWidth = null; + + /** + * We need to know the box-sizing in IE for building the outerHeight and outerWidth + * @var string + */ + this.boxSizingValue = null; + this.boxSizingProperty = null; + + this.attr = null; + this.transformProperty = transformProperty; + this.transformOriginProperty = transformOriginProperty; + } + }); + + $.extend($.transform, { + /** + * @var Array list of all valid transform functions + */ + funcs: ['matrix', 'origin', 'reflect', 'reflectX', 'reflectXY', 'reflectY', 'rotate', 'scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY', 'translate', 'translateX', 'translateY'] + }); + + /** + * Create Transform as a jQuery plugin + * @param Object funcs + * @param Object options + */ + $.fn.transform = function(funcs, options) { + return this.each(function() { + var t = this.transform || new $.transform(this); + if (funcs) { + t.exec(funcs, options); + } + }); + }; + + $.transform.prototype = { + /** + * Applies all of the transformations + * @param Object funcs + * @param Object options + * forceMatrix - uses the matrix in all browsers + * preserve - tries to preserve the values from previous runs + */ + exec: function(funcs, options) { + // extend options + options = $.extend(true, { + forceMatrix: false, + preserve: false + }, options); + + // preserve the funcs from the previous run + this.attr = null; + if (options.preserve) { + funcs = $.extend(true, this.getAttrs(true, true), funcs); + } else { + funcs = $.extend(true, {}, funcs); // copy the object to prevent weirdness + } + + // Record the custom attributes on the element itself + this.setAttrs(funcs); + + // apply the funcs + if ($.support.csstransforms && !options.forceMatrix) { + // CSS3 is supported + return this.execFuncs(funcs); + } else if ($.browser.msie || ($.support.csstransforms && options.forceMatrix)) { + // Internet Explorer or Forced matrix + return this.execMatrix(funcs); + } + return false; + }, + + /** + * Applies all of the transformations as functions + * @param Object funcs + */ + execFuncs: function(funcs) { + var values = []; + + // construct a CSS string + for (var func in funcs) { + // handle origin separately + if (func == 'origin') { + this[func].apply(this, $.isArray(funcs[func]) ? funcs[func] : [funcs[func]]); + } else if ($.inArray(func, $.transform.funcs) !== -1) { + values.push(this.createTransformFunc(func, funcs[func])); + } + } + this.$elem.css(transformProperty, values.join(' ')); + return true; + }, + + /** + * Applies all of the transformations as a matrix + * @param Object funcs + */ + execMatrix: function(funcs) { + var matrix, + tempMatrix, + args; + + var elem = this.$elem[0], + _this = this; + function normalPixels(val, i) { + if (rperc.test(val)) { + // this really only applies to translation + return parseFloat(val) / 100 * _this['safeOuter' + (i ? 'Height' : 'Width')](); + } + return toPx(elem, val); + } + + var rtranslate = /translate[X|Y]?/, + trans = []; + + for (var func in funcs) { + switch ($.type(funcs[func])) { + case 'array': args = funcs[func]; break; + case 'string': args = $.map(funcs[func].split(','), $.trim); break; + default: args = [funcs[func]]; + } + + if ($.matrix[func]) { + + if ($.cssAngle[func]) { + // normalize on degrees + args = $.map(args, $.angle.toDegree); + } else if (!$.cssNumber[func]) { + // normalize to pixels + args = $.map(args, normalPixels); + } else { + // strip units + args = $.map(args, stripUnits); + } + + tempMatrix = $.matrix[func].apply(this, args); + if (rtranslate.test(func)) { + //defer translation + trans.push(tempMatrix); + } else { + matrix = matrix ? matrix.x(tempMatrix) : tempMatrix; + } + } else if (func == 'origin') { + this[func].apply(this, args); + } + } + + // check that we have a matrix + matrix = matrix || $.matrix.identity(); + + // Apply translation + $.each(trans, function(i, val) { matrix = matrix.x(val); }); + + // pull out the relevant values + var a = parseFloat(matrix.e(1,1).toFixed(6)), + b = parseFloat(matrix.e(2,1).toFixed(6)), + c = parseFloat(matrix.e(1,2).toFixed(6)), + d = parseFloat(matrix.e(2,2).toFixed(6)), + tx = matrix.rows === 3 ? parseFloat(matrix.e(1,3).toFixed(6)) : 0, + ty = matrix.rows === 3 ? parseFloat(matrix.e(2,3).toFixed(6)) : 0; + + //apply the transform to the element + if ($.support.csstransforms && vendorPrefix === '-moz-') { + // -moz- + this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + 'px, ' + ty + 'px)'); + } else if ($.support.csstransforms) { + // -webkit, -o-, w3c + // NOTE: WebKit and Opera don't allow units on the translate variables + this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + ', ' + ty + ')'); + } else if ($.browser.msie) { + // IE requires the special transform Filter + + //TODO: Use Nearest Neighbor during animation FilterType=\'nearest neighbor\' + var filterType = ', FilterType=\'nearest neighbor\''; //bilinear + var style = this.$elem[0].style; + var matrixFilter = 'progid:DXImageTransform.Microsoft.Matrix(' + + 'M11=' + a + ', M12=' + c + ', M21=' + b + ', M22=' + d + + ', sizingMethod=\'auto expand\'' + filterType + ')'; + var filter = style.filter || $.css( this.$elem[0], "filter" ) || ""; + style.filter = rmatrix.test(filter) ? filter.replace(rmatrix, matrixFilter) : filter ? filter + ' ' + matrixFilter : matrixFilter; + + // Let's know that we're applying post matrix fixes and the height/width will be static for a bit + this.applyingMatrix = true; + this.matrix = matrix; + + // IE can't set the origin or translate directly + this.fixPosition(matrix, tx, ty); + + this.applyingMatrix = false; + this.matrix = null; + } + return true; + }, + + /** + * Sets the transform-origin + * This really needs to be percentages + * @param Number x length + * @param Number y length + */ + origin: function(x, y) { + // use CSS in supported browsers + if ($.support.csstransforms) { + if (typeof y === 'undefined') { + this.$elem.css(transformOriginProperty, x); + } else { + this.$elem.css(transformOriginProperty, x + ' ' + y); + } + return true; + } + + // correct for keyword lengths + switch (x) { + case 'left': x = '0'; break; + case 'right': x = '100%'; break; + case 'center': // no break + case undefined: x = '50%'; + } + switch (y) { + case 'top': y = '0'; break; + case 'bottom': y = '100%'; break; + case 'center': // no break + case undefined: y = '50%'; //TODO: does this work? + } + + // store mixed values with units, assumed pixels + this.setAttr('origin', [ + rperc.test(x) ? x : toPx(this.$elem[0], x) + 'px', + rperc.test(y) ? y : toPx(this.$elem[0], y) + 'px' + ]); + //console.log(this.getAttr('origin')); + return true; + }, + + /** + * Create a function suitable for a CSS value + * @param string func + * @param Mixed value + */ + createTransformFunc: function(func, value) { + if (func.substr(0, 7) === 'reflect') { + // let's fake reflection, false value + // falsey sets an identity matrix + var m = value ? $.matrix[func]() : $.matrix.identity(); + return 'matrix(' + m.e(1,1) + ', ' + m.e(2,1) + ', ' + m.e(1,2) + ', ' + m.e(2,2) + ', 0, 0)'; + } + + //value = _correctUnits(func, value); + + if (func == 'matrix') { + if (vendorPrefix === '-moz-') { + value[4] = value[4] ? value[4] + 'px' : 0; + value[5] = value[5] ? value[5] + 'px' : 0; + } + } + return func + '(' + ($.isArray(value) ? value.join(', ') : value) + ')'; + }, + + /** + * @param Matrix matrix + * @param Number tx + * @param Number ty + * @param Number height + * @param Number width + */ + fixPosition: function(matrix, tx, ty, height, width) { + // now we need to fix it! + var calc = new $.matrix.calc(matrix, this.safeOuterHeight(), this.safeOuterWidth()), + origin = this.getAttr('origin'); // mixed percentages and px + + // translate a 0, 0 origin to the current origin + var offset = calc.originOffset(new $.matrix.V2( + rperc.test(origin[0]) ? parseFloat(origin[0])/100*calc.outerWidth : parseFloat(origin[0]), + rperc.test(origin[1]) ? parseFloat(origin[1])/100*calc.outerHeight : parseFloat(origin[1]) + )); + + // IE glues the top-most and left-most pixels of the transformed object to top/left of the original object + //TODO: This seems wrong in the calculations + var sides = calc.sides(); + + // Protect against an item that is already positioned + var cssPosition = this.$elem.css('position'); + if (cssPosition == 'static') { + cssPosition = 'relative'; + } + + //TODO: if the element is already positioned, we should attempt to respect it (somehow) + //NOTE: we could preserve our offset top and left in an attr on the elem + var pos = {top: 0, left: 0}; + + // Approximates transform-origin, tx, and ty + var css = { + 'position': cssPosition, + 'top': (offset.top + ty + sides.top + pos.top) + 'px', + 'left': (offset.left + tx + sides.left + pos.left) + 'px', + 'zoom': 1 + }; + + this.$elem.css(css); + } + }; + + /** + * Ensure that values have the appropriate units on them + * @param string func + * @param Mixed value + */ + function toPx(elem, val) { + var parts = rfxnum.exec($.trim(val)); + + if (parts[3] && parts[3] !== 'px') { + var prop = 'paddingBottom', + orig = $.style( elem, prop ); + + $.style( elem, prop, val ); + val = cur( elem, prop ); + $.style( elem, prop, orig ); + return val; + } + return parseFloat( val ); + } + + function cur(elem, prop) { + if ( elem[prop] != null && (!elem.style || elem.style[prop] == null) ) { + return elem[ prop ]; + } + + var r = parseFloat( $.css( elem, prop ) ); + return r && r > -10000 ? r : 0; + } +})(jQuery, this, this.document); + + +/////////////////////////////////////////////////////// +// Safe Outer Length +/////////////////////////////////////////////////////// +(function($, window, document, undefined) { + $.extend($.transform.prototype, { + /** + * @param void + * @return Number + */ + safeOuterHeight: function() { + return this.safeOuterLength('height'); + }, + + /** + * @param void + * @return Number + */ + safeOuterWidth: function() { + return this.safeOuterLength('width'); + }, + + /** + * Returns reliable outer dimensions for an object that may have been transformed. + * Only use this if the matrix isn't handy + * @param String dim height or width + * @return Number + */ + safeOuterLength: function(dim) { + var funcName = 'outer' + (dim == 'width' ? 'Width' : 'Height'); + + if (!$.support.csstransforms && $.browser.msie) { + // make the variables more generic + dim = dim == 'width' ? 'width' : 'height'; + + // if we're transforming and have a matrix; we can shortcut. + // the true outerHeight is the transformed outerHeight divided by the ratio. + // the ratio is equal to the height of a 1px by 1px box that has been transformed by the same matrix. + if (this.applyingMatrix && !this[funcName] && this.matrix) { + // calculate and return the correct size + var calc = new $.matrix.calc(this.matrix, 1, 1), + ratio = calc.offset(), + length = this.$elem[funcName]() / ratio[dim]; + this[funcName] = length; + + return length; + } else if (this.applyingMatrix && this[funcName]) { + // return the cached calculation + return this[funcName]; + } + + // map dimensions to box sides + var side = { + height: ['top', 'bottom'], + width: ['left', 'right'] + }; + + // setup some variables + var elem = this.$elem[0], + outerLen = parseFloat($.css(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width + boxSizingProp = this.boxSizingProperty, + boxSizingValue = this.boxSizingValue; + + // IE6 && IE7 will never have a box-sizing property, so fake it + if (!this.boxSizingProperty) { + boxSizingProp = this.boxSizingProperty = _findBoxSizingProperty() || 'box-sizing'; + boxSizingValue = this.boxSizingValue = this.$elem.css(boxSizingProp) || 'content-box'; + } + + // return it immediately if we already know it + if (this[funcName] && this[dim] == outerLen) { + return this[funcName]; + } else { + this[dim] = outerLen; + } + + // add in the padding and border + if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { + outerLen += parseFloat($.css(elem, 'padding-' + side[dim][0], true)) || 0 + + parseFloat($.css(elem, 'padding-' + side[dim][1], true)) || 0; + } + if (boxSizingProp && boxSizingValue == 'content-box') { + outerLen += parseFloat($.css(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + + parseFloat($.css(elem, 'border-' + side[dim][1] + '-width', true)) || 0; + } + + // remember and return the outerHeight + this[funcName] = outerLen; + return outerLen; + } + return this.$elem[funcName](); + } + }); + + /** + * Determine the correct property for checking the box-sizing property + * @param void + * @return string + */ + var _boxSizingProperty = null; + function _findBoxSizingProperty () { + if (_boxSizingProperty) { + return _boxSizingProperty; + } + + var property = { + boxSizing : 'box-sizing', + MozBoxSizing : '-moz-box-sizing', + WebkitBoxSizing : '-webkit-box-sizing', + OBoxSizing : '-o-box-sizing' + }, + elem = document.body; + + for (var p in property) { + if (typeof elem.style[p] != 'undefined') { + _boxSizingProperty = property[p]; + return _boxSizingProperty; + } + } + return null; + } +})(jQuery, this, this.document); + /////////////////////////////////////////////////////// // Attr diff --git a/src/jquery.transform.js b/src/jquery.transform.js index 64987e7..489e158 100644 --- a/src/jquery.transform.js +++ b/src/jquery.transform.js @@ -280,7 +280,7 @@ var matrixFilter = 'progid:DXImageTransform.Microsoft.Matrix(' + 'M11=' + a + ', M12=' + c + ', M21=' + b + ', M22=' + d + ', sizingMethod=\'auto expand\'' + filterType + ')'; - var filter = style.filter || $.curCSS( this.$elem[0], "filter" ) || ""; + var filter = style.filter || $.css( this.$elem[0], "filter" ) || ""; style.filter = rmatrix.test(filter) ? filter.replace(rmatrix, matrixFilter) : filter ? filter + ' ' + matrixFilter : matrixFilter; // Let's know that we're applying post matrix fixes and the height/width will be static for a bit @@ -493,7 +493,7 @@ // setup some variables var elem = this.$elem[0], - outerLen = parseFloat($.curCSS(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width + outerLen = parseFloat($.css(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width boxSizingProp = this.boxSizingProperty, boxSizingValue = this.boxSizingValue; @@ -512,12 +512,12 @@ // add in the padding and border if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { - outerLen += parseFloat($.curCSS(elem, 'padding-' + side[dim][0], true)) || 0 + - parseFloat($.curCSS(elem, 'padding-' + side[dim][1], true)) || 0; + outerLen += parseFloat($.css(elem, 'padding-' + side[dim][0], true)) || 0 + + parseFloat($.css(elem, 'padding-' + side[dim][1], true)) || 0; } if (boxSizingProp && boxSizingValue == 'content-box') { - outerLen += parseFloat($.curCSS(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + - parseFloat($.curCSS(elem, 'border-' + side[dim][1] + '-width', true)) || 0; + outerLen += parseFloat($.css(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + + parseFloat($.css(elem, 'border-' + side[dim][1] + '-width', true)) || 0; } // remember and return the outerHeight