1/*! 2* jQuery 2d Transform v0.9.3 3* http://wiki.github.com/heygrady/transform/ 4* 5* Copyright 2010, Grady Kuhnline 6* Dual licensed under the MIT or GPL Version 2 licenses. 7* http://jquery.org/license 8* 9* Date: Sat Dec 4 15:46:09 2010 -0800 10*/ 11/////////////////////////////////////////////////////// 12// Transform 13/////////////////////////////////////////////////////// 14(function($, window, document, undefined) { 15/** 16* @var Regex identify the matrix filter in IE 17*/ 18var rmatrix = /progid:DXImageTransform\.Microsoft\.Matrix\(.*?\)/, 19rfxnum = /^([\+\-]=)?([\d+.\-]+)(.*)$/, 20rperc = /%/; 21 22// Steal some code from Modernizr 23var m = document.createElement( 'modernizr' ), 24m_style = m.style; 25 26function stripUnits(arg) { 27return parseFloat(arg); 28} 29 30/** 31* Find the prefix that this browser uses 32*/ 33function getVendorPrefix() { 34var property = { 35transformProperty : '', 36MozTransform : '-moz-', 37WebkitTransform : '-webkit-', 38OTransform : '-o-', 39msTransform : '-ms-' 40}; 41for (var p in property) { 42if (typeof m_style[p] != 'undefined') { 43return property[p]; 44} 45} 46return null; 47} 48 49function supportCssTransforms() { 50if (typeof(window.Modernizr) !== 'undefined') { 51return Modernizr.csstransforms; 52} 53 54var props = [ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]; 55for ( var i in props ) { 56if ( m_style[ props[i] ] !== undefined ) { 57return true; 58} 59} 60} 61 62// Capture some basic properties 63var vendorPrefix = getVendorPrefix(), 64transformProperty = vendorPrefix !== null ? vendorPrefix + 'transform' : false, 65transformOriginProperty = vendorPrefix !== null ? vendorPrefix + 'transform-origin' : false; 66 67// store support in the jQuery Support object 68$.support.csstransforms = supportCssTransforms(); 69 70// IE9 public preview 6 requires the DOM names 71if (vendorPrefix == '-ms-') { 72transformProperty = 'msTransform'; 73transformOriginProperty = 'msTransformOrigin'; 74} 75 76/** 77* Class for creating cross-browser transformations 78* @constructor 79*/ 80$.extend({ 81transform: function(elem) { 82// Cache the transform object on the element itself 83elem.transform = this; 84 85/** 86* The element we're working with 87* @var jQueryCollection 88*/ 89this.$elem = $(elem); 90 91/** 92* Remember the matrix we're applying to help the safeOuterLength func 93*/ 94this.applyingMatrix = false; 95this.matrix = null; 96 97/** 98* Remember the css height and width to save time 99* This is only really used in IE 100* @var Number 101*/ 102this.height = null; 103this.width = null; 104this.outerHeight = null; 105this.outerWidth = null; 106 107/** 108* We need to know the box-sizing in IE for building the outerHeight and outerWidth 109* @var string 110*/ 111this.boxSizingValue = null; 112this.boxSizingProperty = null; 113 114this.attr = null; 115this.transformProperty = transformProperty; 116this.transformOriginProperty = transformOriginProperty; 117} 118}); 119 120$.extend($.transform, { 121/** 122* @var Array list of all valid transform functions 123*/ 124funcs: ['matrix', 'origin', 'reflect', 'reflectX', 'reflectXY', 'reflectY', 'rotate', 'scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY', 'translate', 'translateX', 'translateY'] 125}); 126 127/** 128* Create Transform as a jQuery plugin 129* @param Object funcs 130* @param Object options 131*/ 132$.fn.transform = function(funcs, options) { 133return this.each(function() { 134var t = this.transform || new $.transform(this); 135if (funcs) { 136t.exec(funcs, options); 137} 138}); 139}; 140 141$.transform.prototype = { 142/** 143* Applies all of the transformations 144* @param Object funcs 145* @param Object options 146* forceMatrix - uses the matrix in all browsers 147* preserve - tries to preserve the values from previous runs 148*/ 149exec: function(funcs, options) { 150// extend options 151options = $.extend(true, { 152forceMatrix: false, 153preserve: false 154}, options); 155 156// preserve the funcs from the previous run 157this.attr = null; 158if (options.preserve) { 159funcs = $.extend(true, this.getAttrs(true, true), funcs); 160} else { 161funcs = $.extend(true, {}, funcs); // copy the object to prevent weirdness 162} 163 164// Record the custom attributes on the element itself 165this.setAttrs(funcs); 166 167// apply the funcs 168if ($.support.csstransforms && !options.forceMatrix) { 169// CSS3 is supported 170return this.execFuncs(funcs); 171}
171 else if ($.browser.msie || ($.support.csstransforms && options.forceMatrix)) { 172// Internet Explorer or Forced matrix 173return this.execMatrix(funcs); 174} 175return false; 176}, 177 178/** 179* Applies all of the transformations as functions 180* @param Object funcs 181*/ 182execFuncs: function(funcs) { 183var values = []; 184 185// construct a CSS string 186for (var func in funcs) { 187// handle origin separately 188if (func == 'origin') { 189this[func].apply(this, $.isArray(funcs[func]) ? funcs[func] : [funcs[func]]); 190} else if ($.inArray(func, $.transform.funcs) !== -1) { 191values.push(this.createTransformFunc(func, funcs[func])); 192} 193} 194this.$elem.css(transformProperty, values.join(' ')); 195return true; 196}, 197 198/** 199* Applies all of the transformations as a matrix 200* @param Object funcs 201*/ 202execMatrix: function(funcs) { 203var matrix, 204tempMatrix, 205args; 206 207var elem = this.$elem[0], 208_this = this; 209function normalPixels(val, i) { 210if (rperc.test(val)) { 211// this really only applies to translation 212return parseFloat(val) / 100 * _this['safeOuter' + (i ? 'Height' : 'Width')](); 213} 214return toPx(elem, val); 215} 216 217var rtranslate = /translate[X|Y]?/, 218trans = []; 219 220for (var func in funcs) { 221switch ($.type(funcs[func])) { 222case 'array': args = funcs[func]; break; 223case 'string': args = $.map(funcs[func].split(','), $.trim); break; 224default: args = [funcs[func]]; 225} 226 227if ($.matrix[func]) { 228 229if ($.cssAngle[func]) { 230// normalize on degrees 231args = $.map(args, $.angle.toDegree); 232} else if (!$.cssNumber[func]) { 233// normalize to pixels 234args = $.map(args, normalPixels); 235} else { 236// strip units 237args = $.map(args, stripUnits); 238} 239 240tempMatrix = $.matrix[func].apply(this, args); 241if (rtranslate.test(func)) { 242//defer translation 243trans.push(tempMatrix); 244} else { 245matrix = matrix ? matrix.x(tempMatrix) : tempMatrix; 246} 247} else if (func == 'origin') { 248this[func].apply(this, args); 249} 250} 251 252// check that we have a matrix 253matrix = matrix || $.matrix.identity(); 254 255// Apply translation 256$.each(trans, function(i, val) { matrix = matrix.x(val); }); 257 258// pull out the relevant values 259var a = parseFloat(matrix.e(1,1).toFixed(6)), 260b = parseFloat(matrix.e(2,1).toFixed(6)), 261c = parseFloat(matrix.e(1,2).toFixed(6)), 262d = parseFloat(matrix.e(2,2).toFixed(6)), 263tx = matrix.rows === 3 ? parseFloat(matrix.e(1,3).toFixed(6)) : 0, 264ty = matrix.rows === 3 ? parseFloat(matrix.e(2,3).toFixed(6)) : 0; 265 266//apply the transform to the element 267if ($.support.csstransforms && vendorPrefix === '-moz-') { 268// -moz- 269this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + 'px, ' + ty + 'px)'); 270} else if ($.support.csstransforms) { 271// -webkit, -o-, w3c 272// NOTE: WebKit and Opera don't allow units on the translate variables 273this.$elem.css(transformProperty, 'matrix(' + a + ', ' + b + ', ' + c + ', ' + d + ', ' + tx + ', ' + ty + ')'); 274} else if ($.browser.msie) { 275// IE requires the special transform Filter 276 277//TODO: Use Nearest Neighbor during animation FilterType=\'nearest neighbor\' 278var filterType = ', FilterType=\'nearest neighbor\''; //bilinear 279var style = this.$elem[0].style; 280var matrixFilter = 'progid:DXImageTransform.Microsoft.Matrix(' + 281'M11=' + a + ', M12=' + c + ', M21=' + b + ', M22=' + d + 282', sizingMethod=\'auto expand\'' + filterType + ')'; 283var filter = style.filter || $.curCSS( this.$elem[0], "filter" ) || ""; 284style.filter = rmatrix.test(filter) ? filter.replace(rmatrix, matrixFilter) : filter ? filter + ' ' + matrixFilter : matrixFilter; 285 286// Let's know that we're applying post matrix fixes and the height/width will be static for a bit 287this.applyingMatrix = true; 288this.matrix = matrix; 289 290// IE can't set the origin or translate directly 291this.fixPosition(matrix, tx, ty); 292 293this.applyingMatrix = false; 294this.matrix = null; 295} 296return true; 297}, 298 299/** 300* Sets the transform-origin 301* This really needs to be percentages 302* @param Number x length 303* @param Number y length 304*/ 305origin: function(x, y) { 306// use CSS in supported browsers
307if ($.support.csstransforms) { 308if (typeof y === 'undefined') { 309this.$elem.css(transformOriginProperty, x); 310} else { 311this.$elem.css(transformOriginProperty, x + ' ' + y); 312} 313return true; 314} 315 316// correct for keyword lengths 317switch (x) { 318case 'left': x = '0'; break; 319case 'right': x = '100%'; break; 320case 'center': // no break 321case undefined: x = '50%'; 322} 323switch (y) { 324case 'top': y = '0'; break; 325case 'bottom': y = '100%'; break; 326case 'center': // no break 327case undefined: y = '50%'; //TODO: does this work? 328} 329 330// store mixed values with units, assumed pixels 331this.setAttr('origin', [ 332rperc.test(x) ? x : toPx(this.$elem[0], x) + 'px', 333rperc.test(y) ? y : toPx(this.$elem[0], y) + 'px' 334]); 335//console.log(this.getAttr('origin')); 336return true; 337}, 338 339/** 340* Create a function suitable for a CSS value 341* @param string func 342* @param Mixed value 343*/ 344createTransformFunc: function(func, value) { 345if (func.substr(0, 7) === 'reflect') { 346// let's fake reflection, false value 347// falsey sets an identity matrix 348var m = value ? $.matrix[func]() : $.matrix.identity(); 349return 'matrix(' + m.e(1,1) + ', ' + m.e(2,1) + ', ' + m.e(1,2) + ', ' + m.e(2,2) + ', 0, 0)'; 350} 351 352//value = _correctUnits(func, value); 353 354if (func == 'matrix') { 355if (vendorPrefix === '-moz-') { 356value[4] = value[4] ? value[4] + 'px' : 0; 357value[5] = value[5] ? value[5] + 'px' : 0; 358} 359} 360return func + '(' + ($.isArray(value) ? value.join(', ') : value) + ')'; 361}, 362 363/** 364* @param Matrix matrix 365* @param Number tx 366* @param Number ty 367* @param Number height 368* @param Number width 369*/ 370fixPosition: function(matrix, tx, ty, height, width) { 371// now we need to fix it! 372var calc = new $.matrix.calc(matrix, this.safeOuterHeight(), this.safeOuterWidth()), 373origin = this.getAttr('origin'); // mixed percentages and px 374 375// translate a 0, 0 origin to the current origin 376var offset = calc.originOffset(new $.matrix.V2( 377rperc.test(origin[0]) ? parseFloat(origin[0])/100*calc.outerWidth : parseFloat(origin[0]), 378rperc.test(origin[1]) ? parseFloat(origin[1])/100*calc.outerHeight : parseFloat(origin[1]) 379)); 380 381// IE glues the top-most and left-most pixels of the transformed object to top/left of the original object 382//TODO: This seems wrong in the calculations 383var sides = calc.sides(); 384 385// Protect against an item that is already positioned 386var cssPosition = this.$elem.css('position'); 387if (cssPosition == 'static') { 388cssPosition = 'relative'; 389} 390 391//TODO: if the element is already positioned, we should attempt to respect it (somehow) 392//NOTE: we could preserve our offset top and left in an attr on the elem 393var pos = {top: 0, left: 0}; 394 395// Approximates transform-origin, tx, and ty 396var css = { 397'position': cssPosition, 398'top': (offset.top + ty + sides.top + pos.top) + 'px', 399'left': (offset.left + tx + sides.left + pos.left) + 'px', 400'zoom': 1 401}; 402 403this.$elem.css(css); 404} 405}; 406 407/** 408* Ensure that values have the appropriate units on them 409* @param string func 410* @param Mixed value 411*/ 412function toPx(elem, val) { 413var parts = rfxnum.exec($.trim(val)); 414 415if (parts[3] && parts[3] !== 'px') { 416var prop = 'paddingBottom', 417orig = $.style( elem, prop ); 418 419$.style( elem, prop, val ); 420val = cur( elem, prop ); 421$.style( elem, prop, orig ); 422return val; 423} 424return parseFloat( val ); 425} 426 427function cur(elem, prop) { 428if ( elem[prop] != null && (!elem.style || elem.style[prop] == null) ) { 429return elem[ prop ]; 430} 431 432var r = parseFloat( $.css( elem, prop ) ); 433return r && r > -10000 ? r : 0; 434} 435})(jQuery, this, this.document); 436 437 438/////////////////////////////////////////////////////// 439// Safe Outer Length 440/////////////////////////////////////////////////////// 441(function($, window, document, undefined) { 442$.extend($.transform.prototype, { 443/** 444* @param void 445* @return Number 446*/ 447safeOuterHeight: function() { 448return this.safeOuterLength('height'); 449}, 450 451/** 452* @param void 453* @return Number 454*/ 455safeOuterWidth: function() { 456return this.safeOuterLength('width'); 457}, 458 459/** 460* Returns reliable outer dimensions for an object that may have been transformed. 461* Only use this if the matrix isn't handy 462* @param String dim height or width 463* @return Number 464*/ 465safeOuterLength: function(dim) { 466var funcName = 'outer' + (dim == 'width' ? 'Width' : 'Height'); 467 468if (!$.support.csstransforms && $.browser.msie) { 469// make the variables more generic 470dim = dim == 'width' ? 'width' : 'height';
471 472// if we're transforming and have a matrix; we can shortcut. 473// the true outerHeight is the transformed outerHeight divided by the ratio. 474// the ratio is equal to the height of a 1px by 1px box that has been transformed by the same matrix. 475if (this.applyingMatrix && !this[funcName] && this.matrix) { 476// calculate and return the correct size 477var calc = new $.matrix.calc(this.matrix, 1, 1), 478ratio = calc.offset(), 479length = this.$elem[funcName]() / ratio[dim]; 480this[funcName] = length; 481 482return length; 483} else if (this.applyingMatrix && this[funcName]) { 484// return the cached calculation 485return this[funcName]; 486} 487 488// map dimensions to box sides 489var side = { 490height: ['top', 'bottom'], 491width: ['left', 'right'] 492}; 493 494// setup some variables 495var elem = this.$elem[0], 496outerLen = parseFloat($.curCSS(elem, dim, true)), //TODO: this can be cached on animations that do not animate height/width 497boxSizingProp = this.boxSizingProperty, 498boxSizingValue = this.boxSizingValue; 499 500// IE6 && IE7 will never have a box-sizing property, so fake it 501if (!this.boxSizingProperty) { 502boxSizingProp = this.boxSizingProperty = _findBoxSizingProperty() || 'box-sizing'; 503boxSizingValue = this.boxSizingValue = this.$elem.css(boxSizingProp) || 'content-box'; 504} 505 506// return it immediately if we already know it 507if (this[funcName] && this[dim] == outerLen) { 508return this[funcName]; 509} else { 510this[dim] = outerLen; 511} 512 513// add in the padding and border 514if (boxSizingProp && (boxSizingValue == 'padding-box' || boxSizingValue == 'content-box')) { 515outerLen += parseFloat($.curCSS(elem, 'padding-' + side[dim][0], true)) || 0 + 516parseFloat($.curCSS(elem, 'padding-' + side[dim][1], true)) || 0; 517} 518if (boxSizingProp && boxSizingValue == 'content-box') { 519outerLen += parseFloat($.curCSS(elem, 'border-' + side[dim][0] + '-width', true)) || 0 + 520parseFloat($.curCSS(elem, 'border-' + side[dim][1] + '-width', true)) || 0; 521} 522 523// remember and return the outerHeight 524this[funcName] = outerLen; 525return outerLen; 526} 527return this.$elem[funcName](); 528} 529}); 530 531/** 532* Determine the correct property for checking the box-sizing property 533* @param void 534* @return string 535*/ 536var _boxSizingProperty = null; 537function _findBoxSizingProperty () { 538if (_boxSizingProperty) { 539return _boxSizingProperty; 540} 541 542var property = { 543boxSizing : 'box-sizing', 544MozBoxSizing : '-moz-box-sizing', 545WebkitBoxSizing : '-webkit-box-sizing', 546OBoxSizing : '-o-box-sizing' 547}, 548elem = document.body; 549 550for (var p in property) { 551if (typeof elem.style[p] != 'undefined') { 552_boxSizingProperty = property[p]; 553return _boxSizingProperty; 554} 555} 556return null; 557} 558})(jQuery, this, this.document); 559 560 561/////////////////////////////////////////////////////// 562// Attr 563/////////////////////////////////////////////////////// 564(function($, window, document, undefined) { 565var rfuncvalue = /([\w\-]*?)\((.*?)\)/g, // with values 566attr = 'data-transform', 567rspace = /\s/, 568rcspace = /,\s?/; 569 570$.extend($.transform.prototype, { 571/** 572* This overrides all of the attributes 573* @param Object funcs a list of transform functions to store on this element 574* @return void 575*/ 576setAttrs: function(funcs) { 577var string = '', 578value; 579for (var func in funcs) { 580value = funcs[func]; 581if ($.isArray(value)) { 582value = value.join(', '); 583} 584string += ' ' + func + '(' + value + ')'; 585} 586this.attr = $.trim(string); 587this.$elem.attr(attr, this.attr); 588}, 589 590/** 591* This sets only a specific atribute 592* @param string func name of a transform function 593* @param mixed value with proper units 594* @return void 595*/ 596setAttr: function(func, value) { 597// stringify the value 598if ($.isArray(value)) { 599value = value.join(', '); 600} 601 602// pull from a local variable to look it up 603var transform = this.attr || this.$elem.attr(attr); 604if (!transform || transform.indexOf(func) == -1) { 605// we don't have any existing values, save it 606// we don't have this function yet, save it 607this.attr = $.trim(transform + ' ' + func + '(' + value + ')'); 608this.$elem.attr(attr, this.attr); 609} else { 610// replace the existing value 611var funcs = [], parts; 612 613// regex split 614rfuncvalue.lastIndex = 0; // reset the regex pointer 615while (parts = rfuncvalue.exec(transform)) { 616if (func == parts[1]) { 617funcs.push(func + '(' + value + ')'); 618} else { 619funcs.push(parts[0]); 620} 621} 622this.attr = funcs.join(' '); 623this.$elem.attr(attr, this.attr); 624} 625}, 626 627/** 628* @return Object 629*/ 630getAttrs: function() { 631var transform = this.attr || this.$elem.attr(attr); 632if (!transform) { 633// We don't have any existing values, return empty object 634return {}; 635} 636 637// replace the existing value 638var attrs = {}, parts, value; 639 640rfuncvalue.lastIndex = 0; // reset the regex pointer 641while ((parts = rfuncvalue.exec(transform)) !== null) { 642if (parts) { 643value = parts[2].split(rcspace); 644attrs[parts[1]] = value.length == 1 ? value[0] : value; 645} 646} 647return attrs; 648}, 649 650/** 651* @param String func 652* @return mixed 653*/ 654getAttr: function(func) { 655var attrs = this.getAttrs(); 656if (typeof attrs[func] !== 'undefined') { 657return attrs[func]; 658} 659 660//TODO: move the origin to a function 661if (func === 'origin' && $.support.csstransforms) { 662// supported browsers return percentages always 663return this.$elem.css(this.transformOriginProperty).split(rspace); 664} else if (func === 'origin') { 665// just force IE to also return a percentage 666return ['50%', '50%']; 667} 668 669return $.cssDefault[func] || 0; 670} 671}); 672 673// Define 674if (typeof($.cssAngle) == 'undefined') { 675$.cssAngle = {}; 676} 677$.extend($.cssAngle, { 678rotate: true, 679skew: true, 680skewX: true, 681skewY: true 682}); 683 684// Define default values 685if (typeof($.cssDefault) == 'undefined') { 686$.cssDefault = {}; 687} 688 689$.extend($.cssDefault, { 690scale: [1, 1], 691scaleX: 1, 692scaleY: 1, 693matrix: [1, 0, 0, 1, 0, 0], 694origin: ['50%', '50%'], // TODO: allow this to be a function, like get 695reflect: [1, 0, 0, 1, 0, 0], 696reflectX: [1, 0, 0, 1, 0, 0], 697reflectXY: [1, 0, 0, 1, 0, 0], 698reflectY: [1, 0, 0, 1, 0, 0] 699}); 700 701// Define functons with multiple values 702if (typeof($.cssMultipleValues) == 'undefined') { 703$.cssMultipleValues = {}; 704} 705$.extend($.cssMultipleValues, { 706matrix: 6, 707origin: { 708length: 2, 709duplicate: true 710}, 711reflect: 6, 712reflectX: 6, 713reflectXY: 6, 714reflectY: 6, 715scale: { 716length: 2, 717duplicate: true 718}, 719skew: 2, 720translate: 2 721}); 722 723// specify unitless funcs 724$.extend($.cssNumber, { 725matrix: true, 726reflect: true, 727reflectX: true, 728reflectXY: true, 729reflectY: true, 730scale: true,
731scaleX: true, 732scaleY: true 733}); 734 735// override all of the css functions 736$.each($.transform.funcs, function(i, func) { 737$.cssHooks[func] = { 738set: function(elem, value) { 739var transform = elem.transform || new $.transform(elem), 740funcs = {}; 741funcs[func] = value; 742transform.exec(funcs, {preserve: true}); 743}, 744get: function(elem, computed) { 745var transform = elem.transform || new $.transform(elem); 746return transform.getAttr(func); 747} 748}; 749}); 750 751// Support Reflection animation better by returning a matrix 752$.each(['reflect', 'reflectX', 'reflectXY', 'reflectY'], function(i, func) { 753$.cssHooks[func].get = function(elem, computed) { 754var transform = elem.transform || new $.transform(elem); 755return transform.getAttr('matrix') || $.cssDefault[func]; 756}; 757}); 758})(jQuery, this, this.document); 759/////////////////////////////////////////////////////// 760// Animation 761/////////////////////////////////////////////////////// 762(function($, window, document, undefined) { 763/** 764* @var Regex looks for units on a string 765*/ 766var rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/; 767 768/** 769* Doctors prop values in the event that they contain spaces 770* @param Object prop 771* @param String speed 772* @param String easing 773* @param Function callback 774* @return bool 775*/ 776var _animate = $.fn.animate; 777$.fn.animate = function( prop, speed, easing, callback ) { 778var optall = $.speed(speed, easing, callback), 779mv = $.cssMultipleValues; 780 781// Speed always creates a complete function that must be reset 782optall.complete = optall.old; 783 784// Capture multiple values 785if (!$.isEmptyObject(prop)) { 786if (typeof optall.original === 'undefined') { 787optall.original = {}; 788} 789$.each( prop, function( name, val ) { 790if (mv[name] 791|| $.cssAngle[name] 792|| (!$.cssNumber[name] && $.inArray(name, $.transform.funcs) !== -1)) { 793 794// Handle special easing 795var specialEasing = null; 796if (jQuery.isArray(prop[name])) { 797var mvlen = 1, len = val.length; 798if (mv[name]) { 799mvlen = (typeof mv[name].length === 'undefined' ? mv[name] : mv[name].length); 800} 801if ( len > mvlen 802|| (len < mvlen && len == 2) 803|| (len == 2 && mvlen == 2 && isNaN(parseFloat(val[len - 1])))) { 804 805specialEasing = val[len - 1]; 806val.splice(len - 1, 1); 807} 808} 809 810// Store the original values onto the optall 811optall.original[name] = val.toString(); 812 813// reduce to a unitless number (to trick animate) 814prop[name] = parseFloat(val); 815} 816} ); 817} 818 819//NOTE: we edited prop above to trick animate 820//NOTE: we pre-convert to an optall so we can doctor it 821return _animate.apply(this, [arguments[0], optall]); 822}; 823 824var prop = 'paddingBottom'; 825function cur(elem, prop) { 826if ( elem[prop] != null && (!elem.style || elem.style[prop] == null) ) { 827//return elem[ prop ]; 828} 829 830var r = parseFloat( $.css( elem, prop ) ); 831return r && r > -10000 ? r : 0; 832} 833 834var _custom = $.fx.prototype.custom; 835$.fx.prototype.custom = function(from, to, unit) { 836var multiple = $.cssMultipleValues[this.prop], 837angle = $.cssAngle[this.prop]; 838 839//TODO: simply check for the existence of CSS Hooks? 840if (multiple || (!$.cssNumber[this.prop] && $.inArray(this.prop, $.transform.funcs) !== -1)) { 841this.values = []; 842 843if (!multiple) { 844multiple = 1; 845} 846 847// Pull out the known values 848var values = this.options.original[this.prop], 849currentValues = $(this.elem).css(this.prop), 850defaultValues = $.cssDefault[this.prop] || 0; 851 852// make sure the current css value is an array 853if (!$.isArray(currentValues)) { 854currentValues = [currentValues]; 855} 856 857// make sure the new values are an array 858if (!$.isArray(values)) { 859if ($.type(values) === 'string') { 860values = values.split(','); 861} else { 862values = [values]; 863} 864} 865 866// make sure we have enough new values 867var length = multiple.length || multiple, i = 0; 868while (values.length < length) { 869values.push(multiple.duplicate ? values[0] : defaultValues[i] || 0); 870i++; 871} 872 873// calculate a start, end and unit for each new value 874var start, parts, end, //unit, 875fx = this, 876transform = fx.elem.transform; 877orig = $.style(fx.elem, prop); 878 879$.each(values, function(i, val) { 880// find a sensible start value 881if (currentValues[i]) { 882start = currentValues[i]; 883} else if (defaultValues[i] && !multiple.duplicate) { 884start = defaultValues[i]; 885} else if (multiple.duplicate) { 886start = currentValues[0]; 887} else { 888start = 0; 889} 890 891// Force the correct unit on the start 892if (angle) { 893start = $.angle.toDegree(start); 894} else if (!$.cssNumber[fx.prop]) { 895parts = rfxnum.exec($.trim(start)); 896if (parts[3] && parts[3] !== 'px') { 897if (parts[3] === '%') { 898start = parseFloat( parts[2] ) / 100 * transform['safeOuter' + (i ? 'Height' : 'Width')](); 899} else { 900$.style( fx.elem, prop, start); 901start = cur(fx.elem, prop); 902$.style( fx.elem, prop, orig); 903} 904} 905} 906start = parseFloat(start); 907 908// parse the value with a regex 909parts = rfxnum.exec($.trim(val)); 910 911if (parts) { 912// we found a sensible value and unit 913end = parseFloat( parts[2] ); 914unit = parts[3] || "px"; //TODO: change to an appropriate default unit 915 916if (angle) { 917end = $.angle.toDegree(end + unit); 918unit = 'deg'; 919} else if (!$.cssNumber[fx.prop] && unit === '%') { 920start = (start / transform['safeOuter' + (i ? 'Height' : 'Width')]()) * 100; 921} else if (!$.cssNumber[fx.prop] && unit !== 'px') {
922$.style( fx.elem, prop, (end || 1) + unit); 923start = ((end || 1) / cur(fx.elem, prop)) * start; 924$.style( fx.elem, prop, orig); 925} 926 927// If a +=/-= token was provided, we're doing a relative animation 928if (parts[1]) { 929end = ((parts[1] === "-=" ? -1 : 1) * end) + start; 930} 931} else { 932// I don't know when this would happen 933end = val; 934unit = ''; 935} 936 937// Save the values 938fx.values.push({ 939start: start, 940end: end, 941unit: unit 942}); 943}); 944} 945return _custom.apply(this, arguments); 946}; 947 948/** 949* Animates a multi value attribute 950* @param Object fx 951* @return null 952*/ 953$.fx.multipleValueStep = { 954_default: function(fx) { 955$.each(fx.values, function(i, val) { 956fx.values[i].now = val.start + ((val.end - val.start) * fx.pos); 957}); 958} 959}; 960$.each(['matrix', 'reflect', 'reflectX', 'reflectXY', 'reflectY'], function(i, func) { 961$.fx.multipleValueStep[func] = function(fx) { 962var d = fx.decomposed, 963$m = $.matrix; 964m = $m.identity(); 965 966d.now = {}; 967 968// increment each part of the decomposition and recompose it 969$.each(d.start, function(k) { 970// calculate the current value 971d.now[k] = parseFloat(d.start[k]) + ((parseFloat(d.end[k]) - parseFloat(d.start[k])) * fx.pos); 972 973// skip functions that won't affect the transform 974if (((k === 'scaleX' || k === 'scaleY') && d.now[k] === 1) || 975(k !== 'scaleX' && k !== 'scaleY' && d.now[k] === 0)) { 976return true; 977} 978 979// calculating 980m = m.x($m[k](d.now[k])); 981}); 982 983// save the correct matrix values for the value of now 984var val; 985$.each(fx.values, function(i) { 986switch (i) { 987case 0: val = parseFloat(m.e(1, 1).toFixed(6)); break; 988case 1: val = parseFloat(m.e(2, 1).toFixed(6)); break; 989case 2: val = parseFloat(m.e(1, 2).toFixed(6)); break; 990case 3: val = parseFloat(m.e(2, 2).toFixed(6)); break; 991case 4: val = parseFloat(m.e(1, 3).toFixed(6)); break; 992case 5: val = parseFloat(m.e(2, 3).toFixed(6)); break; 993} 994fx.values[i].now = val; 995}); 996}; 997}); 998/** 999* Step for animating tranformations 1000*/ 1001$.each($.transform.funcs, function(i, func) { 1002$.fx.step[func] = function(fx) { 1003var transform = fx.elem.transform || new $.transform(fx.elem), 1004funcs = {}; 1005 1006if ($.cssMultipleValues[func] || (!$.cssNumber[func] && $.inArray(func, $.transform.funcs) !== -1)) { 1007($.fx.multipleValueStep[fx.prop] || $.fx.multipleValueStep._default)(fx); 1008funcs[fx.prop] = []; 1009$.each(fx.values, function(i, val) { 1010funcs[fx.prop].push(val.now + ($.cssNumber[fx.prop] ? '' : val.unit)); 1011}); 1012} else { 1013funcs[fx.prop] = fx.now + ($.cssNumber[fx.prop] ? '' : fx.unit); 1014} 1015 1016transform.exec(funcs, {preserve: true}); 1017}; 1018}); 1019 1020// Support matrix animation 1021$.each(['matrix', 'reflect', 'reflectX', 'reflectXY', 'reflectY'], function(i, func) { 1022$.fx.step[func] = function(fx) { 1023var transform = fx.elem.transform || new $.transform(fx.elem), 1024funcs = {}; 1025 1026if (!fx.initialized) { 1027fx.initialized = true; 1028 1029// Reflections need a sensible end value set 1030if (func !== 'matrix') { 1031var values = $.matrix[func]().elements; 1032var val; 1033$.each(fx.values, function(i) { 1034switch (i) { 1035case 0: val = values[0]; break; 1036case 1: val = values[2]; break; 1037case 2: val = values[1]; break; 1038case 3: val = values[3]; break; 1039default: val = 0; 1040} 1041fx.values[i].end = val; 1042}); 1043} 1044 1045// Decompose the start and end 1046fx.decomposed = {}; 1047var v = fx.values; 1048 1049fx.decomposed.start = $.matrix.matrix(v[0].start, v[1].start, v[2].start, v[3].start, v[4].start, v[5].start).decompose(); 1050fx.decomposed.end = $.matrix.matrix(v[0].end, v[1].end, v[2].end, v[3].end, v[4].end, v[5].end).decompose(); 1051} 1052 1053($.fx.multipleValueStep[fx.prop] || $.fx.multipleValueStep._default)(fx); 1054funcs.matrix = []; 1055$.each(fx.values, function(i, val) { 1056funcs.matrix.push(val.now); 1057}); 1058 1059transform.exec(funcs, {preserve: true}); 1060}; 1061}); 1062})(jQuery, this, this.document); 1063/////////////////////////////////////////////////////// 1064// Angle 1065/////////////////////////////////////////////////////// 1066(function($, window, document, undefined) { 1067/** 1068* Converting a radian to a degree 1069* @const 1070*/ 1071var RAD_DEG = 180/Math.PI; 1072 1073/** 1074* Converting a radian to a grad 1075* @const 1076*/ 1077var RAD_GRAD = 200/Math.PI; 1078 1079/** 1080* Converting a degree to a radian 1081* @const 1082*/ 1083var DEG_RAD = Math.PI/180; 1084 1085/** 1086* Converting a degree to a grad 1087* @const 1088*/ 1089var DEG_GRAD = 2/1.8; 1090 1091/**
1092* Converting a grad to a degree 1093* @const 1094*/ 1095var GRAD_DEG = 0.9; 1096 1097/** 1098* Converting a grad to a radian 1099* @const 1100*/ 1101var GRAD_RAD = Math.PI/200; 1102 1103 1104var rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/; 1105 1106/** 1107* Functions for converting angles 1108* @var Object 1109*/ 1110$.extend({ 1111angle: { 1112/** 1113* available units for an angle 1114* @var Regex 1115*/ 1116runit: /(deg|g?rad)/, 1117 1118/** 1119* Convert a radian into a degree 1120* @param Number rad 1121* @return Number 1122*/ 1123radianToDegree: function(rad) { 1124return rad * RAD_DEG; 1125}, 1126 1127/** 1128* Convert a radian into a degree 1129* @param Number rad 1130* @return Number 1131*/ 1132radianToGrad: function(rad) { 1133return rad * RAD_GRAD; 1134}, 1135 1136/** 1137* Convert a degree into a radian 1138* @param Number deg 1139* @return Number 1140*/ 1141degreeToRadian: function(deg) { 1142return deg * DEG_RAD; 1143}, 1144 1145/** 1146* Convert a degree into a radian 1147* @param Number deg 1148* @return Number 1149*/ 1150degreeToGrad: function(deg) { 1151return deg * DEG_GRAD; 1152}, 1153 1154/** 1155* Convert a grad into a degree 1156* @param Number grad 1157* @return Number 1158*/ 1159gradToDegree: function(grad) { 1160return grad * GRAD_DEG; 1161}, 1162 1163/** 1164* Convert a grad into a radian 1165* @param Number grad 1166* @return Number 1167*/ 1168gradToRadian: function(grad) { 1169return grad * GRAD_RAD; 1170}, 1171 1172/** 1173* Convert an angle with a unit to a degree 1174* @param String val angle with a unit 1175* @return Number 1176*/ 1177toDegree: function (val) { 1178var parts = rfxnum.exec(val); 1179if (parts) { 1180val = parseFloat( parts[2] ); 1181switch (parts[3] || 'deg') { 1182case 'grad': 1183val = $.angle.gradToDegree(val); 1184break; 1185case 'rad': 1186val = $.angle.radianToDegree(val); 1187break; 1188} 1189return val; 1190} 1191return 0; 1192} 1193} 1194}); 1195})(jQuery, this, this.document); 1196/////////////////////////////////////////////////////// 1197// Matrix 1198/////////////////////////////////////////////////////// 1199(function($, window, document, undefined) { 1200/** 1201* Matrix object for creating matrices relevant for 2d Transformations 1202* @var Object 1203*/ 1204if (typeof($.matrix) == 'undefined') { 1205$.extend({ 1206matrix: {} 1207}); 1208} 1209var $m = $.matrix; 1210 1211$.extend( $m, { 1212/** 1213* A 2-value vector 1214* @param Number x 1215* @param Number y 1216* @constructor 1217*/ 1218V2: function(x, y){ 1219if ($.isArray(arguments[0])) { 1220this.elements = arguments[0].slice(0, 2); 1221} else { 1222this.elements = [x, y]; 1223} 1224this.length = 2; 1225}, 1226 1227/** 1228* A 2-value vector 1229* @param Number x 1230* @param Number y 1231* @param Number z 1232* @constructor 1233*/ 1234V3: function(x, y, z){ 1235if ($.isArray(arguments[0])) { 1236this.elements = arguments[0].slice(0, 3); 1237} else { 1238this.elements = [x, y, z]; 1239} 1240this.length = 3; 1241}, 1242 1243/** 1244* A 2x2 Matrix, useful for 2D-transformations without translations 1245* @param Number mn 1246* @constructor 1247*/ 1248M2x2: function(m11, m12, m21, m22) { 1249if ($.isArray(arguments[0])) { 1250this.elements = arguments[0].slice(0, 4); 1251} else { 1252this.elements = Array.prototype.slice.call(arguments).slice(0, 4); 1253} 1254this.rows = 2; 1255this.cols = 2; 1256}, 1257 1258/** 1259* A 3x3 Matrix, useful for 3D-transformations without translations 1260* @param Number mn 1261* @constructor 1262*/ 1263M3x3: function(m11, m12, m13, m21, m22, m23, m31, m32, m33) { 1264if ($.isArray(arguments[0])) { 1265this.elements = arguments[0].slice(0, 9); 1266} else { 1267this.elements = Array.prototype.slice.call(arguments).slice(0, 9); 1268} 1269this.rows = 3; 1270this.cols = 3; 1271} 1272}); 1273 1274/** generic matrix prototype */ 1275var Matrix = { 1276/** 1277* Return a specific element from the matrix 1278* @param Number row where 1 is the 0th row 1279* @param Number col where 1 is the 0th column 1280* @return Number 1281*/ 1282e: function(row, col) { 1283var rows = this.rows, 1284cols = this.cols; 1285 1286// return 0 on nonsense rows and columns 1287if (row > rows || col > rows || row < 1 || col < 1) { 1288return 0; 1289} 1290 1291return this.elements[(row - 1) * cols + col - 1]; 1292}, 1293 1294/** 1295* Taken from Zoomooz 1296* https://github.com/jaukia/zoomooz/blob/c7a37b9a65a06ba730bd66391bbd6fe8e55d3a49/js/jquery.zoomooz.js 1297*/ 1298decompose: function() { 1299var a = this.e(1, 1), 1300b = this.e(2, 1), 1301c = this.e(1, 2), 1302d = this.e(2, 2), 1303e = this.e(1, 3), 1304f = this.e(2, 3); 1305 1306// In case the matrix can't be decomposed 1307if (Math.abs(a * d - b * c) < 0.01) { 1308return { 1309rotate: 0 + 'deg', 1310skewX: 0 + 'deg', 1311scaleX: 1, 1312scaleY: 1, 1313translateX: 0 + 'px', 1314translateY: 0 + 'px' 1315}; 1316} 1317 1318// Translate is easy 1319var tx = e, ty = f; 1320 1321// factor out the X scale 1322var sx = Math.sqrt(a * a + b * b); 1323a = a/sx; 1324b = b/sx; 1325 1326// factor out the skew 1327var k = a * c + b * d; 1328c -= a * k; 1329d -= b * k; 1330 1331// factor out the Y scale 1332var sy = Math.sqrt(c * c + d * d); 1333c = c / sy; 1334d = d / sy; 1335k = k / sy; 1336 1337// account for negative scale 1338if ((a * d - b * c) < 0.0) { 1339a = -a; 1340b = -b; 1341//c = -c; // accomplishes nothing to negate it 1342//d = -d; // accomplishes nothing to negate it 1343sx = -sx; 1344//sy = -sy //Scale Y shouldn't ever be negated 1345}
1345 1346 1347// calculate the rotation angle and skew angle 1348var rad2deg = $.angle.radianToDegree; 1349var r = rad2deg(Math.atan2(b, a)); 1350k = rad2deg(Math.atan(k)); 1351 1352return { 1353rotate: r + 'deg', 1354skewX: k + 'deg', 1355scaleX: sx, 1356scaleY: sy, 1357translateX: tx + 'px', 1358translateY: ty + 'px' 1359}; 1360} 1361}; 1362 1363/** Extend all of the matrix types with the same prototype */ 1364$.extend($m.M2x2.prototype, Matrix, { 1365toM3x3: function() { 1366var a = this.elements; 1367return new $m.M3x3( 1368a[0], a[1], 0, 1369a[2], a[3], 0, 13700, 0, 1 1371); 1372}, 1373 1374/** 1375* Multiply a 2x2 matrix by a similar matrix or a vector 1376* @param M2x2 | V2 matrix 1377* @return M2x2 | V2 1378*/ 1379x: function(matrix) { 1380var isVector = typeof(matrix.rows) === 'undefined'; 1381 1382// Ensure the right-sized matrix 1383if (!isVector && matrix.rows == 3) { 1384return this.toM3x3().x(matrix); 1385} 1386 1387var a = this.elements, 1388b = matrix.elements; 1389 1390if (isVector && b.length == 2) { 1391// b is actually a vector 1392return new $m.V2( 1393a[0] * b[0] + a[1] * b[1], 1394a[2] * b[0] + a[3] * b[1] 1395); 1396} else if (b.length == a.length) { 1397// b is a 2x2 matrix 1398return new $m.M2x2( 1399a[0] * b[0] + a[1] * b[2], 1400a[0] * b[1] + a[1] * b[3], 1401 1402a[2] * b[0] + a[3] * b[2], 1403a[2] * b[1] + a[3] * b[3] 1404); 1405} 1406return false; // fail 1407}, 1408 1409/** 1410* Generates an inverse of the current matrix 1411* @param void 1412* @return M2x2 1413* @link http://www.dr-lex.be/random/matrix_inv.html 1414*/ 1415inverse: function() { 1416var d = 1/this.determinant(), 1417a = this.elements; 1418return new $m.M2x2( 1419d * a[3], d * -a[1], 1420d * -a[2], d * a[0] 1421); 1422}, 1423 1424/** 1425* Calculates the determinant of the current matrix 1426* @param void 1427* @return Number 1428* @link http://www.dr-lex.be/random/matrix_inv.html 1429*/ 1430determinant: function() { 1431var a = this.elements; 1432return a[0] * a[3] - a[1] * a[2]; 1433} 1434}); 1435 1436$.extend($m.M3x3.prototype, Matrix, { 1437/** 1438* Multiply a 3x3 matrix by a similar matrix or a vector 1439* @param M3x3 | V3 matrix 1440* @return M3x3 | V3 1441*/ 1442x: function(matrix) { 1443var isVector = typeof(matrix.rows) === 'undefined'; 1444 1445// Ensure the right-sized matrix 1446if (!isVector && matrix.rows < 3) { 1447matrix = matrix.toM3x3(); 1448} 1449 1450var a = this.elements, 1451b = matrix.elements; 1452 1453if (isVector && b.length == 3) { 1454// b is actually a vector 1455return new $m.V3( 1456a[0] * b[0] + a[1] * b[1] + a[2] * b[2], 1457a[3] * b[0] + a[4] * b[1] + a[5] * b[2], 1458a[6] * b[0] + a[7] * b[1] + a[8] * b[2] 1459); 1460} else if (b.length == a.length) { 1461// b is a 3x3 matrix 1462return new $m.M3x3( 1463a[0] * b[0] + a[1] * b[3] + a[2] * b[6], 1464a[0] * b[1] + a[1] * b[4] + a[2] * b[7], 1465a[0] * b[2] + a[1] * b[5] + a[2] * b[8], 1466 1467a[3] * b[0] + a[4] * b[3] + a[5] * b[6], 1468a[3] * b[1] + a[4] * b[4] + a[5] * b[7], 1469a[3] * b[2] + a[4] * b[5] + a[5] * b[8], 1470 1471a[6] * b[0] + a[7] * b[3] + a[8] * b[6], 1472a[6] * b[1] + a[7] * b[4] + a[8] * b[7], 1473a[6] * b[2] + a[7] * b[5] + a[8] * b[8] 1474); 1475} 1476return false; // fail 1477}, 1478 1479/** 1480* Generates an inverse of the current matrix 1481* @param void 1482* @return M3x3 1483* @link http://www.dr-lex.be/random/matrix_inv.html 1484*/ 1485inverse: function() { 1486var d = 1/this.determinant(), 1487a = this.elements; 1488return new $m.M3x3( 1489d * ( a[8] * a[4] - a[7] * a[5]), 1490d * (-(a[8] * a[1] - a[7] * a[2])), 1491d * ( a[5] * a[1] - a[4] * a[2]), 1492 1493d * (-(a[8] * a[3] - a[6] * a[5])), 1494d * ( a[8] * a[0] - a[6] * a[2]), 1495d * (-(a[5] * a[0] - a[3] * a[2])), 1496 1497d * ( a[7] * a[3] - a[6] * a[4]), 1498d * (-(a[7] * a[0] - a[6] * a[1])), 1499d * ( a[4] * a[0] - a[3] * a[1]) 1500); 1501}, 1502 1503/** 1504* Calculates the determinant of the current matrix 1505* @param void 1506* @return Number 1507* @link http://www.dr-lex.be/random/matrix_inv.html 1508*/ 1509determinant: function() { 1510var a = this.elements; 1511return a[0] * (a[8] * a[4] - a[7] * a[5]) - a[3] * (a[8] * a[1] - a[7] * a[2]) + a[6] * (a[5] * a[1] - a[4] * a[2]); 1512} 1513}); 1514 1515/** generic vector prototype */ 1516var Vector = { 1517/** 1518* Return a specific element from the vector 1519* @param Number i where 1 is the 0th value 1520* @return Number 1521*/ 1522e: function(i) { 1523return this.elements[i - 1]; 1524} 1525}; 1526 1527/** Extend all of the vector types with the same prototype */ 1528$.extend($m.V2.prototype, Vector); 1529$.extend($m.V3.prototype, Vector); 1530})(jQuery, this, this.document); 1531/////////////////////////////////////////////////////// 1532// Matrix Calculations 1533/////////////////////////////////////////////////////// 1534(function($, window, document, undefined) { 1535/** 1536* Matrix object for creating matrices relevant for 2d Transformations 1537* @var Object 1538*/ 1539if (typeof($.matrix) == 'undefined') { 1540$.extend({ 1541matrix: {} 1542}); 1543} 1544 1545$.extend( $.matrix, { 1546/** 1547* Class for calculating coordinates on a matrix 1548* @param Matrix matrix 1549* @param Number outerHeight 1550* @param Number outerWidth 1551* @constructor 1552*/ 1553calc: function(matrix, outerHeight, outerWidth) { 1554/** 1555* @var Matrix 1556*/ 1557this.matrix = matrix; 1558 1559/** 1560* @var Number 1561*/ 1562this.outerHeight = outerHeight; 1563 1564/** 1565* @var Number 1566*/ 1567this.outerWidth = outerWidth; 1568} 1569}); 1570 1571$.matrix.calc.prototype = { 1572/** 1573* Calculate a coord on the new object 1574* @return Object 1575*/ 1576coord: function(x, y, z) { 1577//default z and w 1578z = typeof(z) !== 'undefined' ? z : 0; 1579 1580var matrix = this.matrix, 1581vector; 1582 1583switch (matrix.rows) { 1584case 2: 1585vector = matrix.x(new $.matrix.V2(x, y)); 1586break; 1587case 3: 1588vector = matrix.x(new $.matrix.V3(x, y, z)); 1589break; 1590} 1591 1592return vector; 1593}, 1594 1595/** 1596* Calculate the corners of the new object 1597* @return Object 1598*/ 1599corners: function(x, y) { 1600// Try to save the corners if this is called a lot 1601var save = !(typeof(x) !=='undefined' || typeof(y) !=='undefined'), 1602c; 1603if (!this.c || !save) { 1604y = y || this.outerHeight; 1605x = x || this.outerWidth; 1606 1607c = { 1608tl: this.coord(0, 0), 1609bl: this.coord(0, y), 1610tr: this.coord(x, 0), 1611br: this.coord(x, y) 1612}; 1613} else { 1614c = this.c; 1615} 1616 1617if (save) { 1618this.c = c; 1619} 1620return c; 1621}, 1622 1623/** 1624* Calculate the sides of the new object 1625* @return Object 1626*/ 1627sides: function(corners) { 1628// The corners of the box 1629var c = corners || this.corners(); 1630 1631return { 1632top: Math.min(c.tl.e(2), c.tr.e(2), c.br.e(2), c.bl.e(2)), 1633bottom: Math.max(c.tl.e(2), c.tr.e(2), c.br.e(2), c.bl.e(2)), 1634left: Math.min(c.tl.e(1), c.tr.e(1), c.br.e(1), c.bl.e(1)), 1635right: Math.max(c.tl.e(1), c.tr.e(1), c.br.e(1), c.bl.e(1)) 1636}; 1637}, 1638 1639/** 1640* Calculate the offset of the new object 1641* @return Object 1642*/ 1643offset: function(corners) { 1644// The corners of the box 1645var s = this.sides(corners); 1646 1647// return size 1648return { 1649height: Math.abs(s.bottom - s.top), 1650width: Math.abs(s.right - s.left) 1651}; 1652}, 1653 1654/** 1655* Calculate the area of the new object 1656* @return Number 1657* @link http://en.wikipedia.org/wiki/Quadrilateral#Area_of_a_convex_quadrilateral 1658*/ 1659area: function(corners) { 1660// The corners of the box 1661var c = corners || this.corners(); 1662 1663// calculate the two diagonal vectors 1664var v1 = { 1665x: c.tr.e(1) - c.tl.e(1) + c.br.e(1) - c.bl.e(1), 1666y: c.tr.e(2) - c.tl.e(2) + c.br.e(2) - c.bl.e(2) 1667}, 1668v2 = { 1669x: c.bl.e(1) - c.tl.e(1) + c.br.e(1) - c.tr.e(1), 1670y: c.bl.e(2) - c.tl.e(2) + c.br.e(2) - c.tr.e(2) 1671}; 1672 1673return 0.25 * Math.abs(v1.e(1) * v2.e(2) - v1.e(2) * v2.e(1)); 1674}, 1675 1676/** 1677* Calculate the non-affinity of the new object 1678* @return Number 1679*/ 1680nonAffinity: function() { 1681// The corners of the box 1682var sides = this.sides(), 1683xDiff = sides.top - sides.bottom, 1684yDiff = sides.left - sides.right; 1685 1686return parseFloat(parseFloat(Math.abs( 1687(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) / 1688(sides.top * sides.bottom + sides.left * sides.right) 1689)).toFixed(8)); 1690}, 1691 1692/** 1693* Calculate a proper top and left for IE 1694* @param Object toOrigin 1695* @param Object fromOrigin 1696* @return Object 1697*/ 1698originOffset: function(toOrigin, fromOrigin) { 1699// the origin to translate to 1700toOrigin = toOrigin ? toOrigin : new $.matrix.V2( 1701this.outerWidth * 0.5, 1702this.outerHeight * 0.5 1703); 1704 1705// the origin to translate from (IE has a fixed origin of 0, 0) 1706fromOrigin = fromOrigin ? fromOrigin : new $.matrix.V2( 17070, 17080 1709); 1710 1711// transform the origins 1712var toCenter = this.coord(toOrigin.e(1), toOrigin.e(2)); 1713var fromCenter = this.coord(fromOrigin.e(1), fromOrigin.e(2)); 1714 1715// return the offset 1716return { 1717top: (fromCenter.e(2) - fromOrigin.e(2)) - (toCenter.e(2) - toOrigin.e(2)), 1718left: (fromCenter.e(1) - fromOrigin.e(1)) - (toCenter.e(1) - toOrigin.e(1)) 1719}; 1720} 1721}; 1722})(jQuery, this, this.document); 1723/////////////////////////////////////////////////////// 1724// 2d Matrix Functions
1725/////////////////////////////////////////////////////// 1726(function($, window, document, undefined) { 1727/** 1728* Matrix object for creating matrices relevant for 2d Transformations 1729* @var Object 1730*/ 1731if (typeof($.matrix) == 'undefined') { 1732$.extend({ 1733matrix: {} 1734}); 1735} 1736var $m = $.matrix, 1737$m2x2 = $m.M2x2, 1738$m3x3 = $m.M3x3; 1739 1740$.extend( $m, { 1741/** 1742* Identity matrix 1743* @param Number size 1744* @return Matrix 1745*/ 1746identity: function(size) { 1747size = size || 2; 1748var length = size * size, 1749elements = new Array(length), 1750mod = size + 1; 1751for (var i = 0; i < length; i++) { 1752elements[i] = (i % mod) === 0 ? 1 : 0; 1753} 1754return new $m['M'+size+'x'+size](elements); 1755}, 1756 1757/** 1758* Matrix 1759* @return Matrix 1760*/ 1761matrix: function() { 1762var args = Array.prototype.slice.call(arguments); 1763// arguments are in column-major order 1764switch (arguments.length) { 1765case 4: 1766return new $m2x2( 1767args[0], args[2], 1768args[1], args[3] 1769); 1770case 6: 1771return new $m3x3( 1772args[0], args[2], args[4], 1773args[1], args[3], args[5], 17740, 0, 1 1775); 1776} 1777}, 1778 1779/** 1780* Reflect (same as rotate(180)) 1781* @return Matrix 1782*/ 1783reflect: function() { 1784return new $m2x2( 1785-1, 0, 17860, -1 1787); 1788}, 1789 1790/** 1791* Reflect across the x-axis (mirrored upside down) 1792* @return Matrix 1793*/ 1794reflectX: function() { 1795return new $m2x2( 17961, 0, 17970, -1 1798); 1799}, 1800 1801/** 1802* Reflect by swapping x an y (same as reflectX + rotate(-90)) 1803* @return Matrix 1804*/ 1805reflectXY: function() { 1806return new $m2x2( 18070, 1, 18081, 0 1809); 1810}, 1811 1812/** 1813* Reflect across the y-axis (mirrored) 1814* @return Matrix 1815*/ 1816reflectY: function() { 1817return new $m2x2( 1818-1, 0, 18190, 1 1820); 1821}, 1822 1823/** 1824* Rotates around the origin 1825* @param Number deg 1826* @return Matrix 1827* @link http://www.w3.org/TR/SVG/coords.html#RotationDefined 1828*/ 1829rotate: function(deg) { 1830//TODO: detect units 1831var rad = $.angle.degreeToRadian(deg), 1832costheta = Math.cos(rad), 1833sintheta = Math.sin(rad); 1834 1835var a = costheta, 1836b = sintheta, 1837c = -sintheta, 1838d = costheta; 1839 1840return new $m2x2( 1841a, c, 1842b, d 1843); 1844}, 1845 1846/** 1847* Scale 1848* @param Number sx 1849* @param Number sy 1850* @return Matrix 1851* @link http://www.w3.org/TR/SVG/coords.html#ScalingDefined 1852*/ 1853scale: function (sx, sy) { 1854sx = sx || sx === 0 ? sx : 1; 1855sy = sy || sy === 0 ? sy : sx; 1856 1857return new $m2x2( 1858sx, 0, 18590, sy 1860); 1861}, 1862 1863/** 1864* Scale on the X-axis 1865* @param Number sx 1866* @return Matrix 1867*/ 1868scaleX: function (sx) { 1869return $m.scale(sx, 1); 1870}, 1871 1872/** 1873* Scale on the Y-axis 1874* @param Number sy 1875* @return Matrix 1876*/ 1877scaleY: function (sy) { 1878return $m.scale(1, sy); 1879}, 1880 1881/** 1882* Skews on the X-axis and Y-axis 1883* @param Number degX 1884* @param Number degY 1885* @return Matrix 1886*/ 1887skew: function (degX, degY) { 1888degX = degX || 0; 1889degY = degY || 0; 1890 1891//TODO: detect units 1892var radX = $.angle.degreeToRadian(degX), 1893radY = $.angle.degreeToRadian(degY), 1894x = Math.tan(radX), 1895y = Math.tan(radY); 1896 1897return new $m2x2( 18981, x, 1899y, 1 1900); 1901}, 1902 1903/** 1904* Skews on the X-axis 1905* @param Number degX 1906* @return Matrix 1907* @link http://www.w3.org/TR/SVG/coords.html#SkewXDefined 1908*/ 1909skewX: function (degX) { 1910return $m.skew(degX); 1911}, 1912 1913/** 1914* Skews on the Y-axis 1915* @param Number degY 1916* @return Matrix 1917* @link http://www.w3.org/TR/SVG/coords.html#SkewYDefined 1918*/ 1919skewY: function (degY) { 1920return $m.skew(0, degY); 1921}, 1922 1923/** 1924* Translate 1925* @param Number tx 1926* @param Number ty 1927* @return Matrix 1928* @link http://www.w3.org/TR/SVG/coords.html#TranslationDefined 1929*/ 1930translate: function (tx, ty) { 1931tx = tx || 0; 1932ty = ty || 0; 1933 1934return new $m3x3( 19351, 0, tx, 19360, 1, ty, 19370, 0, 1 1938); 1939}, 1940 1941/** 1942* Translate on the X-axis 1943* @param Number tx 1944* @return Matrix 1945* @link http://www.w3.org/TR/SVG/coords.html#TranslationDefined 1946*/ 1947translateX: function (tx) { 1948return $m.translate(tx); 1949}, 1950 1951/** 1952* Translate on the Y-axis 1953* @param Number ty 1954* @return Matrix 1955* @link http://www.w3.org/TR/SVG/coords.html#TranslationDefined 1956*/ 1957translateY: function (ty) { 1958return $m.translate(0, ty); 1959} 1960}); 1961})(jQuery, this, this.document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.