PageSourceSearch

http://www.honeyvig.com/legacy/js/jquery.transform.js

js honeyvig.com collected 2026-10-08 02:02:04 UTC 43,736 bytes, 1,961 lines download raw bytes

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.