1/* KUTE.js - The Light Tweening Engine 2 * by dnp_theme 3 * Licensed under MIT-License 4 */ 5(function (root,factory) { 6 if (typeof define === 'function' && define.amd) { 7 define([], factory); // AMD. Register as an anonymous module. 8 } else if (typeof exports == 'object') { 9 module.exports = factory(); // Node, not strict CommonJS 10 } else { 11 root.KUTE = factory(); 12 } 13}(this, function () { 14 "use strict"; 15 16 // set a custom scope for KUTE.js 17 var g = typeof global !== 'undefined' ? global : window, time = g.performance, 18 body = document.body, tweens = [], tick = null, // tick must be null!! 19 20 // strings 21 length = 'length', 22 split = 'split', 23 indexOf = 'indexOf', 24 replace = 'replace', 25 26 offsetWidth = 'offsetWidth', 27 offsetHeight = 'offsetHeight', 28 29 options = 'options', 30 valuesStart = 'valuesStart', 31 valuesEnd = 'valuesEnd', 32 valuesRepeat = 'valuesRepeat', 33 34 element = 'element', 35 playing = 'playing', 36 37 duration = 'duration', 38 delay = 'delay', 39 offset = 'offset', 40 repeat = 'repeat', 41 repeatDelay = 'repeatDelay', 42 yoyo = 'yoyo', 43 easing = 'easing', 44 chain = 'chain', 45 keepHex = 'keepHex', 46 47 style = 'style', 48 dataTweening = 'data-tweening', 49 getElementsByTagName = 'getElementsByTagName', 50 addEventListener = 'addEventListener', 51 removeEventListener = 'removeEventListener'; 52 53 54 //supported properties 55 var colorProps = ['color', 'backgroundColor'], // 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+) 56 boxModelProps = ['top', 'left', 'width', 'height'], 57 transformFunctions = ['translate3d', 'translateX', 'translateY', 'translateZ', 'rotate', 'translate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'scale'], 58 scrollProp = ['scroll'], // has no default value, it's calculated on tween start 59 opacityProp = ['opacity'], // opacity 60 coreProps = colorProps.concat( opacityProp, boxModelProps, transformFunctions), 61 defaultPropsValues = {}; 62 63 //populate default values object 64 for ( var propertyIndex=0, allCorePropLength = coreProps[length], coreProp; propertyIndex < allCorePropLength; propertyIndex++ ){ 65 coreProp = coreProps[propertyIndex]; 66 if (colorProps[indexOf](coreProp) !== -1){ 67 defaultPropsValues[coreProp] = 'rgba(0,0,0,0)'; // defaultPropsValues[coreProp] = {r:0,g:0,b:0,a:1}; 68 } else if ( boxModelProps[indexOf](coreProp) !== -1 ) { 69 defaultPropsValues[coreProp] = 0; 70 } else if ( coreProp === 'translate3d' ){ // px 71 defaultPropsValues[coreProp] = [0,0,0]; 72 } else if ( coreProp === 'translate' ){ // px 73 defaultPropsValues[coreProp] = [0,0]; 74 } else if ( coreProp === 'rotate' || /X|Y|Z/.test(coreProp) ){ // deg 75 defaultPropsValues[coreProp] = 0; 76 } else if ( coreProp === 'scale' || coreProp === 'opacity' ){ // unitless 77 defaultPropsValues[coreProp] = 1; 78 } 79 } 80 81 // default tween options, since 1.6.1 82 var defaultOptions = { 83 duration: 700, 84 delay: 0, 85 offset: 0, 86 repeat: 0, 87 repeatDelay: 0, 88 yoyo: false, 89 easing: 'linear', 90 keepHex: false, 91 }, 92 // tools / utils 93 getPrefix = function() { //returns browser prefix 94 var prefixes = ['Moz', 'moz', 'Webkit', 'webkit', 'O', 'o', 'Ms', 'ms'], thePrefix; 95 for (var pIndex = 0, pfl = prefixes[length]; pIndex < pfl; pIndex++) { 96 if (prefixes[pIndex]+'Transform' in body[style]) { thePrefix = prefixes[pIndex]; break; } 97 } 98 return thePrefix; 99 }, 100 property = function(propertyToPrefix){ // returns prefixed property | property 101 var prefixRequired = (!(propertyToPrefix in body[style])) ? true : false, prefix = getPrefix(); // is prefix required for property | prefix 102 return prefixRequired ? prefix + (propertyToPrefix.charAt(0).toUpperCase() + propertyToPrefix.slice(1)) : propertyToPrefix; 103 }, 104 selector = function(el,multi){ // a public selector utility 105 var requestedElem; 106 if (multi){ 107 requestedElem = el instanceof Object || typeof el === 'object' ? el : document.querySelectorAll(el); 108 } else { 109 requestedElem = typeof el === 'object' ? el : document.querySelector(el); 110 } 111 if (requestedElem === null && el !== 'window') throw new TypeError('Element not found or incorrect selector: '+el); 112 return requestedElem; 113 }, 114 radToDeg = function(a) { return a*180/Math.PI; }, 115 trueDimension = function (dimValue,isAngle) { //true dimension returns { v = value, u = unit } 116 var intValue = parseInt(dimValue) || 0, mUnits = ['px','%','deg','rad','em','rem','vh','vw'], theUnit; 117 for (var mIndex=0; mIndex<mUnits[length]; mIndex++) { 118 if ( typeof dimValue === 'string' && dimValue[indexOf](mUnits[mIndex]) !== -1 ) { 119 theUnit = mUnits[mIndex]; break; 120 } 121 } 122 theUnit = theUnit !== undefined ? theUnit : (isAngle ? 'deg' : 'px'); 123 return { v: intValue, u: theUnit }; 124 }, 125 trueColor = function (colorString) { // replace transparent and transform any color to rgba()/rgb() 126 if (/rgb|rgba/.test(colorString)) { // first check if it's a rgb string 127 var vrgb = colorString[replace](/\s|\)/,'')[split]('(')[1][split](','), colorAlpha = vrgb[3] ? vrgb[3] : null; 128 if (!colorAlpha) { 129 return { r: parseInt(vrgb[0]), g: parseInt(vrgb[1]), b: parseInt(vrgb[2]) }; 130 } else { 131 return { r: parseInt(vrgb[0]), g: parseInt(vrgb[1]), b: parseInt(vrgb[2]), a: parseFloat(colorAlpha) }; 132 } 133 } else if (/^#/.test(colorString)) { 134 var fromHex = hexToRGB(colorString); return { r: fromHex.r, g: fromHex.g, b: fromHex.b }; 135 } else if (/transparent|none|initial|inherit/.test(colorString)) { 136 return { r: 0, g: 0, b: 0, a: 0 }; 137 } else if (!/^#|^rgb/.test(colorString) ) { // maybe we can check for web safe colors 138 var siteHead = document[getElementsByTagName]('head')[0]; siteHead[style].color = colorString; 139 var webColor = g.getComputedStyle(siteHead,null).color; webColor = /rgb/.test(webColor) ? webColor[replace](/[^\d,]/g, '')[split](',') : [0,0,0]; 140 siteHead[style].color = ''; return { r: parseInt(webColor[0]), g: parseInt(webColor[1]), b: parseInt(webColor[2]) }; 141 } 142 }, 143 rgbToHex = function (r, g, b) { // transform rgb to hex or vice-versa | webkit browsers ignore HEX, always use RGB/RGBA 144 return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); 145 }, 146 hexToRGB = function (hex) { 147 var hexShorthand = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 148 hex = hex[replace](hexShorthand, function (m, r, g, b) { 149 return r + r + g + g + b + b; 150 }); 151 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 152 return result ? { 153 r: parseInt(result[1], 16), 154 g: parseInt(result[2], 16), 155 b: parseInt(result[3], 16) 156 } : null; 157 }, 158 getInlineStyle = function(el) { // get transform style for element from cssText for .to() method 159 if (!el) return; // if the scroll applies to `window` it returns as it has no styling
160 var css = el[style].cssText[replace](/\s/g,'')[split](';'), transformObject = {}; // the cssText | the resulting transform object 161 162 // if we have any inline style in the cssText attribute, usually it has higher priority 163 for ( var i=0, csl = css[length]; i<csl; i++ ){ 164 if ( /transform/i.test(css[i])) { 165 var tps = css[i][split](':')[1][split](')'); //all transform properties 166 for ( var k=0, tpl = tps[length]-1; k< tpl; k++){ 167 var tpv = tps[k][split]('('), tp = tpv[0], tv = tpv[1]; // each transform property, the sp is for transform property 168 if ( transformFunctions[indexOf](tp) !== -1 ){ 169 transformObject[tp] = /translate3d/.test(tp) ? tv[split](',') : tv; 170 } 171 } 172 } 173 } 174 return transformObject; 175 }, 176 getCurrentStyle = function (elem,propertyName) { // get computed style property for element for .to() method 177 var styleAttribute = elem[style], computedStyle = g.getComputedStyle(elem,null) || elem.currentStyle, 178 prefixedProp = property(propertyName), //the computed style | prefixed property 179 styleValue = styleAttribute[propertyName] && !/auto|initial|none|unset/.test(styleAttribute[propertyName]) ? styleAttribute[propertyName] : computedStyle[prefixedProp]; 180 if ( propertyName !== 'transform' && (prefixedProp in computedStyle || prefixedProp in styleAttribute) ) { 181 if ( styleValue ){ 182 if (prefixedProp === 'filter') { // handle IE8 opacity 183 var filterValue = parseInt(styleValue[split]('=')[1][replace](')','')); 184 return parseFloat(filterValue/100); 185 } else { 186 return styleValue; 187 } 188 } else { 189 return defaultPropsValues[propertyName]; 190 } 191 } 192 }, 193 194 //more internals 195 getAll = function () { return tweens; }, 196 removeAll = function () { tweens = []; }, 197 add = function (tw) { tweens.push(tw); }, 198 remove = function (tw) { var i = tweens[indexOf](tw); if (i !== -1) { tweens.splice(i, 1); }}, 199 stop = function () { if (tick) { _cancelAnimationFrame(tick); tick = null; } }, 200 201 canTouch = ('ontouchstart' in g || navigator && navigator.msMaxTouchPoints) || false, // support Touch? 202 touchOrWheel = canTouch ? 'touchstart' : 'mousewheel', mouseEnter = 'mouseenter', //events to prevent on scroll 203 _requestAnimationFrame = g.requestAnimationFrame || g.webkitRequestAnimationFrame || function (c) { return setTimeout(c, 16) }, 204 _cancelAnimationFrame = g.cancelAnimationFrame || g.webkitCancelRequestAnimationFrame || function (c) { return clearTimeout(c) }, 205 transformProperty = property('transform'), 206 207 // true scroll container 208 html = document[getElementsByTagName]('HTML')[0], 209 // scrollContainer = navigator && /webkit/i.test(navigator.userAgent) || document.compatMode == 'BackCompat' ? body : html, 210 scrollContainer = document.compatMode == 'BackCompat' ? body : html, // webkit browsers are now srolling the HTML 211 212 // browser detection 213 isIE = navigator && (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) !== null) ? parseFloat( RegExp.$1 ) : false, 214 isIE8 = isIE === 8, // check IE8/IE 215 216 217 // KUTE.js INTERPOLATORS 218 interpolate = g.Interpolate = {}, 219 number = interpolate.number = function(a,b,v) { // number1, number2, progress 220 a = +a; b -= a; return a + b * v; 221 }, 222 unit = interpolate.unit = function(a,b,u,v) { // number1, number2, unit, progress 223 a = +a; b -= a; return ( a + b * v ) + u; 224 }, 225 color = interpolate.color = function(a,b,v,toHex){ // rgba1, rgba2, progress, convertToHex(true/false) 226 var _c = {}, c, ep = ')', cm =',', rgb = 'rgb(', rgba = 'rgba('; 227 for (c in b) { _c[c] = c !== 'a' ? (number(a[c],b[c],v)>>0 || 0) : (a[c] && b[c]) ? (number(a[c],b[c],v) * 100 >> 0 )/100 : null; } 228 return toHex ? rgbToHex( _c.r, _c.g, _c.b ) : !_c.a ? rgb + _c.r + cm + _c.g + cm + _c.b + ep : rgba + _c.r + cm + _c.g + cm + _c.b + cm + _c.a + ep; 229 }, 230 translate = interpolate.translate = function (a,b,u,v){ 231 var translation = {}; 232 for (var ax in b){ 233 translation[ax] = ( a[ax]===b[ax] ? b[ax] : ( (a[ax] + ( b[ax] - a[ax] ) * v ) * 1000 >> 0 ) / 1000 ) + u; 234 } 235 return translation.x||translation.y ? 'translate(' + translation.x + ',' + translation.y + ')' : 236 'translate3d(' + translation.translateX + ',' + translation.translateY + ',' + translation.translateZ + ')'; 237 }, 238 rotate = interpolate.rotate = function (a,b,u,v){ 239 var rotation = {}; 240 for ( var rx in b ){ 241 rotation[rx] = rx === 'z' ? ('rotate('+ (((a[rx] + (b[rx] - a[rx]) * v) * 1000 >> 0 ) / 1000) + u + ')') 242 : (rx + '(' + (((a[rx] + (b[rx] - a[rx]) * v) * 1000 >> 0 ) / 1000) + u + ')'); 243 } 244 return rotation.z ? rotation.z : (rotation.rotateX||'') + (rotation.rotateY||'') + (rotation.rotateZ||''); 245 }, 246 skew = interpolate.skew = function (a,b,u,v){ 247 var skewProp = {}; 248 for ( var sx in b ){ 249 skewProp[sx] = sx + '(' + (((a[sx] + (b[sx] - a[sx]) * v) * 1000 >> 0) / 1000) + u + ')'; 250 } 251 return (skewProp.skewX||'') + (skewProp.skewY||''); 252 }, 253 scale = interpolate.scale = function(a,b,v){ 254 return 'scale(' + (((a + (b - a) * v) * 1000 >> 0 ) / 1000) + ')'; 255 }, 256 257 // KUTE.js DOM update functions 258 DOM = {}, 259 ticker = function(t) { 260 var i = 0; 261 while ( i < tweens[length] ) { 262 if ( update.call(tweens[i],t) ) { 263 i++; 264 } else { 265 tweens.splice(i, 1); 266 } 267 } 268 tick = _requestAnimationFrame(ticker); 269 }, 270 update = function(t) { 271 t = t || time.now(); 272 if ( t < this._startTime && this[playing] ) { return true; } 273
274 var elapsed = Math.min(( t - this._startTime ) / this[options][duration], 1), progress = this[options][easing](elapsed); // calculate progress 275 276 for (var tweenProp in this[valuesEnd]){ // render the DOM update 277 DOM[tweenProp](this[element],tweenProp,this[valuesStart][tweenProp],this[valuesEnd][tweenProp],progress,this[options]); 278 } 279 280 if (this[options].update) { this[options].update.call(); } // fire the updateCallback 281 282 if (elapsed === 1) { 283 if (this[options][repeat] > 0) { 284 if ( isFinite(this[options][repeat] ) ) { this[options][repeat]--; } 285 286 if (this[options][yoyo]) { // handle yoyo 287 this.reversed = !this.reversed; 288 reverse.call(this); 289 } 290 291 this._startTime = (this[options][yoyo] && !this.reversed) ? t + this[options][repeatDelay] : t; //set the right time for delay 292 return true; 293 } else { 294 295 if (this[options].complete) { this[options].complete.call(); } 296 297 scrollOut.call(this); // unbind preventing scroll when scroll tween finished 298 299 for (var i = 0, ctl = this[options][chain][length]; i < ctl; i++) { // start animating chained tweens 300 this[options][chain][i].start(); 301 } 302 303 //stop ticking when finished 304 close.call(this); 305 } 306 return false; 307 } 308 return true; 309 }, 310 311 // applies the transform origin and perspective 312 perspective = function () { 313 var el = this[element], ops = this[options]; 314 if ( ops.perspective !== undefined && transformProperty in this[valuesEnd] ) { // element perspective 315 this[valuesStart][transformProperty]['perspective'] = this[valuesEnd][transformProperty]['perspective']; 316 } 317 // element transform origin / we filter it out for svgTransform to fix the Firefox transformOrigin bug https://bugzilla.mozilla.org/show_bug.cgi?id=923193 318 if ( ops.transformOrigin !== undefined && (!('svgTransform' in this[valuesEnd])) ) { el[style][property('transformOrigin')] = ops.transformOrigin; } // set transformOrigin for CSS3 transforms only 319 if ( ops.perspectiveOrigin !== undefined ) { el[style][property('perspectiveOrigin')] = ops.perspectiveOrigin; } // element perspective origin 320 if ( ops.parentPerspective !== undefined ) { el.parentNode[style][property('perspective')] = ops.parentPerspective + 'px'; } // parent perspective 321 if ( ops.parentPerspectiveOrigin !== undefined ) { el.parentNode[style][property('perspectiveOrigin')] = ops.parentPerspectiveOrigin; } // parent perspective origin 322 }, 323 324 // plugin connector objects 325 prepareStart = {}, // check current property value when .to() method is used 326 crossCheck = {}, // checks for differences between start and end value, try to make sure start unit and end unit are same as well as consistent, stack transforms, process SVG paths 327 328 // parse properties object 329 // string parsing and property specific value processing 330 parseProperty = { // we already start working on core supported properties 331 boxModel : function(tweenProp,inputValue){ 332 if (!(tweenProp in DOM)){ 333 DOM[tweenProp] = function(elem,tweenProp,a,b,v){ 334 elem[style][tweenProp] = ( v > 0.99 || v < 0.01 ? ((number(a,b,v)*10)>>0)/10 : (number(a,b,v) ) >> 0 ) + 'px'; 335 } 336 } 337 var boxValue = trueDimension(inputValue), offsetProp = tweenProp === 'height' ? offsetHeight : offsetWidth; 338 return boxValue.u === '%' ? boxValue.v * this[element][offsetProp] / 100 : boxValue.v; 339 }, 340 transform : function(tweenProp,inputValue) { 341 if (!(transformProperty in DOM)) { 342 DOM[transformProperty] = function(elem,tweenProp,a,b,v,o){ 343 elem[style][tweenProp] = (a.perspective||'') 344 + ('translate' in a ? translate(a.translate,b.translate,'px',v):'') 345 + ('rotate' in a ? rotate(a.rotate,b.rotate,'deg',v):'') 346 + ('skew' in a ? skew(a.skew,b.skew,'deg',v):'') 347 + ('scale' in a ? scale(a.scale,b.scale,v):''); 348 } 349 } 350 351 // process each transform property 352 if (/translate/.test(tweenProp)) { 353 if (tweenProp === 'translate3d') { 354 var t3d = inputValue[split](','), t3d0 = trueDimension(t3d[0]), t3d1 = trueDimension(t3d[1], t3d2 = trueDimension(t3d[2])); 355 return { 356 translateX : t3d0.u === '%' ? (t3d0.v * this[element][offsetWidth] / 100) : t3d0.v, 357 translateY : t3d1.u === '%' ? (t3d1.v * this[element][offsetHeight] / 100) : t3d1.v, 358 translateZ : t3d2.u === '%' ? (t3d2.v * (this[element][offsetHeight] + this[element][offsetWidth]) / 200) : t3d2.v // to be changed with something like element and/or parent perspective 359 }; 360 } else if (/^translate(?:[XYZ])$/.test(tweenProp)) { 361 var t1d = trueDimension(inputValue), percentOffset = /X/.test(tweenProp) ? this[element][offsetWidth] / 100 : /Y/.test(tweenProp) ? this[element][offsetHeight] / 100 : (this[element][offsetWidth]+this[element][offsetHeight]) / 200; 362 363 return t1d.u === '%' ? (t1d.v * percentOffset) : t1d.v; 364 } else if (tweenProp === 'translate') { 365 var tv = typeof inputValue === 'string' ? inputValue[split](',') : inputValue, t2d = {}, t2dv, 366 t2d0 = trueDimension(tv[0]), t2d1 = tv[length] ? trueDimension(tv[1]) : {v: 0, u: 'px'}; 367 if (tv instanceof Array) { 368 t2d.x = t2d0.u === '%' ? (t2d0.v * this[element][offsetWidth] / 100) : t2d0.v, 369 t2d.y = t2d1.u === '%' ? (t2d1.v * this[element][offsetHeight] / 100) : t2d1.v 370 } else { 371 t2dv = trueDimension(tv); 372 t2d.x = t2dv.u === '%' ? (t2dv.v * this[element][offsetWidth] / 100) : t2dv.v, 373 t2d.y = 0 374 } 375 376 return t2d; 377 } 378 } else if (/rotate|skew/.test(tweenProp)) { 379 if (/^rotate(?:[XYZ])$|skew(?:[XY])$/.test(tweenProp)) { 380 var r3d = trueDimension(inputValue,true); 381 return r3d.u === 'rad' ? radToDeg(r3d.v) : r3d.v; 382 } else if (tweenProp === 'rotate') { 383 var r2d = {}, r2dv = trueDimension(inputValue,true); 384 r2d.z = r2dv.u === 'rad' ? radToDeg(r2dv.v) : r2dv.v; 385 return r2d; 386 } 387 } else if (tweenProp === 'scale') { 388 return parseFloat(inputValue); // this must be parseFloat(v) 389 } 390 }, 391 unitless : function(tweenProp,inputValue){ // scroll | opacity 392 if (/scroll/.test(tweenProp) && !(tweenProp in DOM) ){ 393 DOM[tweenProp] = function(elem,tweenProp,a,b,v) { 394 elem.scrollTop = (number(a,b,v))>>0; 395 }; 396 } else if (tweenProp === 'opacity') { 397 if (!(tweenProp in DOM)) { 398 if (isIE8) { 399 DOM[tweenProp] = function(elem,tweenProp,a,b,v) { 400 var st = "alpha(opacity=", ep = ')'; 401 elem[style].filter = st + ((number(a,b,v) * 100)>>0) + ep; 402 }; 403 } else { 404 DOM[tweenProp] = function(elem,tweenProp,a,b,v) { 405 elem[style].opacity = ((number(a,b,v) * 100)>>0)/100; 406 }; 407 } 408 } 409 } 410 return parseFloat(inputValue); 411 }, 412 colors : function(tweenProp,inputValue){ // colors 413 if (!(tweenProp in DOM)) { 414 DOM[tweenProp] = function(elem,tweenProp,a,b,v,o) { 415 elem[style][tweenProp] = color(a,b,v,o[keepHex]); 416 }; 417 } 418 return trueColor(inputValue); 419 } 420 }, 421 422 // process properties for endValues and startValues or one of them 423 preparePropertiesObject = function(obj, fn) { // this, props object, type: start/end 424 var propertiesObject = fn === 'start' ? this[valuesStart] : this[valuesEnd], 425 skewObject = {}, rotateObject = {}
425, translateObject = {}, transformObject = {}; 426 427 for (var x in obj) { 428 if (transformFunctions[indexOf](x) !== -1) { // transform object gets built here 429 var prepAxis = ['X', 'Y', 'Z']; //coordinates // translate[x] = pp(x, obj[x]); 430 if ( /^translate(?:[XYZ]|3d)$/.test(x) ) { //process translate3d 431 432 for (var fnIndex = 0; fnIndex < 3; fnIndex++) { 433 var translateAxis = prepAxis[fnIndex]; 434 if ( /3d/.test(x) ) { 435 translateObject['translate' + translateAxis] = parseProperty.transform.call(this,'translate' + translateAxis, obj[x][fnIndex]); 436 } else { 437 translateObject['translate' + translateAxis] = ('translate' + translateAxis in obj) ? parseProperty.transform.call(this,'translate' + translateAxis, obj['translate' + translateAxis]) : 0; 438 } 439 } 440 transformObject['translate'] = translateObject; 441 } else if ( /^rotate(?:[XYZ])$|^skew(?:[XY])$/.test(x) ) { //process rotation/skew 442 var objectName = /rotate/.test(x) ? 'rotate' : 'skew', 443 rotationOrSkew = objectName === 'rotate' ? rotateObject : skewObject; 444 for (var rIndex = 0; rIndex < 3; rIndex++) { 445 var oneAxis = prepAxis[rIndex]; 446 if ( obj[objectName+oneAxis] !== undefined && x !== 'skewZ' ) { 447 rotationOrSkew[objectName+oneAxis] = parseProperty.transform.call(this,objectName+oneAxis, obj[objectName+oneAxis]); 448 } 449 } 450 transformObject[objectName] = rotationOrSkew; 451 } else if ( /(rotate|translate|scale)$/.test(x) ) { //process 2d translation / rotation 452 transformObject[x] = parseProperty.transform.call(this, x, obj[x]); 453 } 454 propertiesObject[transformProperty] = transformObject; 455 } else { 456 if ( boxModelProps[indexOf](x) !== -1 ) { 457 propertiesObject[x] = parseProperty.boxModel.call(this,x,obj[x]
457); 458 } else if (opacityProp[indexOf](x) !== -1 || x === 'scroll') { 459 propertiesObject[x] = parseProperty.unitless.call(this,x,obj[x]); 460 } else if (colorProps[indexOf](x) !== -1) { 461 propertiesObject[x] = parseProperty.colors.call(this,x,obj[x]); 462 } else if (x in parseProperty) { // or any other property from css/ attr / svg / third party plugins 463 propertiesObject[x] = parseProperty[x].call(this,x,obj[x]); 464 } 465 } 466 } 467 }, 468 reverse = function () { 469 if (this[options][yoyo]) { 470 for (var reverseProp in this[valuesEnd]) { 471 var tmp = this[valuesRepeat][reverseProp]; 472 this[valuesRepeat][reverseProp] = this[valuesEnd][reverseProp]; 473 this[valuesEnd][reverseProp] = tmp; 474 this[valuesStart][reverseProp] = this[valuesRepeat][reverseProp]; 475 } 476 } 477 }, 478 close = function () { // when animation is finished reset repeat, yoyo&reversed tweens 479 if (this[repeat] > 0) { this[options][repeat] = this[repeat]; } 480 if (this[options][yoyo] && this.reversed===true) { reverse.call(this); this.reversed = false; } 481 this[playing] = false; 482 483 !tweens[length] && stop(); // when all animations are finished, stop ticking after ~3 frames 484 }, 485 preventScroll = function (eventObj) { // prevent mousewheel or touch events while tweening scroll 486 var data = body.getAttribute(dataTweening); 487 if (data && data === 'scroll') { eventObj.preventDefault(); } 488 }, 489 scrollOut = function(){ //prevent scroll when tweening scroll 490 if ( 'scroll' in this[valuesEnd] && body.getAttribute(dataTweening)) { 491 body.removeAttribute(dataTweening); 492 } 493 }, 494 scrollIn = function(){ 495 if ( 'scroll' in this[valuesEnd] && !body.getAttribute(dataTweening)) { 496 body.setAttribute(dataTweening, 'scroll'); 497 } 498 }, 499 processEasing = function (fn) { 500 if ( typeof fn === 'function') { 501 return fn; 502 } else if ( typeof fn === 'string' ) { 503 return easingFn[fn]; // regular Robert Penner Easing Functions 504 } 505 }, 506 getStartValues = function () { // stack transform props for .to() chains 507 var startValues = {}, currentStyle = getInlineStyle(this[element]), 508 degreeProps = ['rotate','skew'], startAxis = ['X','Y','Z']; 509 510 for (var tweenProperty in this[valuesStart]){ 511 if ( transformFunctions[indexOf](tweenProperty) !== -1 ) { 512 var r2d = (/(rotate|translate|scale)$/.test(tweenProperty)); 513 if ( /translate/.test(tweenProperty) && tweenProperty !== 'translate' ) { 514 startValues['translate3d'] = currentStyle['translate3d'] || defaultPropsValues[tweenProperty]; 515 } else if ( r2d ) { // 2d transforms 516 startValues[tweenProperty] = currentStyle[tweenProperty] || defaultPropsValues[tweenProperty]; 517 } else if ( !r2d && /rotate|skew/.test(tweenProperty) ) { // all angles 518 for (var degIndex=0; degIndex<2; degIndex++) { 519 for (var axisIndex = 0; axisIndex<3; axisIndex++) { 520 var s = degreeProps[degIndex]+startAxis[axisIndex]; 521 if (transformFunctions[indexOf](s) !== -1 && (s in this[valuesStart]) ) { startValues[s] = currentStyle[s] || defaultPropsValues[s]; } 522 } 523 } 524 } 525 } else { 526 if ( tweenProperty !== 'scroll' ) { 527 if (tweenProperty === 'opacity' && isIE8 ) { // handle IE8 opacity 528 var currentOpacity = getCurrentStyle(this[element],'filter'); 529 startValues['opacity'] = typeof currentOpacity === 'number' ? currentOpacity : defaultPropsValues['opacity']; 530 } else { 531 if ( coreProps[indexOf](tweenProperty) !== -1 ) { 532 startValues[tweenProperty] = getCurrentStyle(this[element],tweenProperty) || d[tweenProperty]; 533 } else { // plugins register here 534 startValues[tweenProperty] = tweenProperty in prepareStart ? prepareStart[tweenProperty].call(this,tweenProperty,this[valuesStart][tweenProperty]) : 0; 535 } 536 } 537 } else { 538 startValues[tweenProperty] = this[element] === scrollC
538ontainer ? (g.pageYOffset || scrollContainer.scrollTop) : this[element].scrollTop; 539 } 540 } 541 } 542 for ( var currentProperty in currentStyle ){ // also add to startValues values from previous tweens 543 if ( transformFunctions[indexOf](currentProperty) !== -1 && (!( currentProperty in this[valuesStart] )) ) { 544 startValues[currentProperty] = currentStyle[currentProperty] || defaultPropsValues[currentProperty]; 545 } 546 } 547 548 this[valuesStart] = {}; 549 preparePropertiesObject.call(this,startValues,'start'); 550 551 if ( transformProperty in this[valuesEnd] ) { // let's stack transform 552 for ( var sp in this[valuesStart][transformProperty]) { // sp is the object corresponding to the transform function objects translate / rotate / skew / scale 553 if ( sp !== 'perspective') { 554 if ( typeof this[valuesStart][transformProperty][sp] === 'object' ) { 555 for ( var spp in this[valuesStart][transformProperty][sp] ) { // 3rd level 556 if ( typeof this[valuesEnd][transformProperty][sp] === 'undefined' ) { this[valuesEnd][transformProperty][sp] = {}; } 557 if ( typeof this[valuesStart][transformProperty][sp][spp] === 'number' && typeof this[valuesEnd][transformProperty][sp][spp] === 'undefined' ) { 558 this[valuesEnd][transformProperty][sp][spp] = this[valuesStart][transformProperty][sp][spp]; 559 } 560 } 561 } else if ( typeof this[valuesStart][transformProperty][sp] === 'number' ) { 562 if ( typeof this[valuesEnd][transformProperty][sp] === 'undefined' ) { // scale 563 this[valuesEnd][transformProperty][sp] = this[valuesStart][transformProperty][sp]; 564 } 565 } 566 } 567 } 568 } 569 }; 570 571 // core easing functions 572 var easingFn = g.Easing = {}; 573 easingFn.linear = function (t) { return t; }; 574 easingFn.easingSinusoidalIn = function(t) { return -Math.cos(t * Math.PI / 2) + 1; }; 575 easingFn.easingSinusoidalOut = function(t) { return Math.sin(t * Math.PI / 2); }; 576 easingFn.easingSinusoidalInOut = function(t) { return -0.5 * (Math.cos(Math.PI * t) - 1); }; 577 easingFn.easingQuadraticIn = function (t) { return t*t; }; 578 easingFn.easingQuadraticOut = function (t) { return t*(2-t); }; 579 easingFn.easingQuadraticInOut = function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t; }; 580 easingFn.easingCubicIn = function (t) { return t*t*t; }; 581 easingFn.easingCubicOut = function (t) { return (--t)*t*t+1; }; 582 easingFn.easingCubicInOut = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1; }; 583 easingFn.easingQuarticIn = function (t) { return t*t*t*t; }; 584 easingFn.easingQuarticOut = function (t) { return 1-(--t)*t*t*t; }; 585 easingFn.easingQuarticInOut = function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; }; 586 easingFn.easingQuinticIn = function (t) { return t*t*t*t*t; }; 587 easingFn.easingQuinticOut = function (t) { return 1+(--t)*t*t*t*t; }; 588 easingFn.easingQuinticInOut = function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t; }; 589 easingFn.easingCircularIn = function(t) { return -(Math.sqrt(1 - (t * t)) - 1); }; 590 easingFn.easingCircularOut = function(t) { return Math.sqrt(1 - (t = t - 1) * t); }; 591 easingFn.easingCircularInOut = function(t) { return ((t*=2) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); }; 592 easingFn.easingExponentialIn = function(t) { return Math.pow(2, 10 * (t - 1)) - 0.001; }; 593 easingFn.easingExponentialOut = function(t) { return 1 - Math.pow(2, -10 * t); }; 594 easingFn.easingExponentialInOut = function(t) { return (t *= 2) < 1 ? 0.5 * Math.pow(2, 10 * (t - 1)) : 0.5 * (2 - Math.pow(2, -10 * (t - 1))); }; 595 easingFn.easingBackIn = function(t) { var s = 1.70158; return t * t * ((s + 1) * t - s); }; 596 easingFn.easingBackOut = function(t) { var s = 1.70158; return --t * t * ((s + 1) * t + s) + 1; }; 597 easingFn.easingBackInOut = function(t) { var s = 1.70158 * 1.525; if ((t *= 2) < 1) return 0.5 * (t * t * ((s + 1) * t - s)); return 0.5 * ((t -= 2) * t * ((s + 1) * t + s) + 2); }; 598 easingFn.easingElasticIn = function(t) { 599 var s, _kea = 0.1, _kep = 0.4; 600 if ( t === 0 ) return 0; if ( t === 1 ) return 1; 601 if ( !_kea || _kea < 1 ) { _kea = 1; s = _kep / 4; } else s = _kep * Math.asin( 1 / _kea ) / Math.PI * 2; 602 return - ( _kea * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t - s ) * Math.PI * 2 / _kep ) ); 603 }; 604 easingFn.easingElasticOut = function(t) { 605 var s, _kea = 0.1, _kep = 0.4; 606 if ( t === 0 ) return 0; if ( t === 1 ) return 1; 607 if ( !_kea || _kea < 1 ) { _kea = 1; s = _kep / 4; } else s = _kep * Math.asin( 1 / _kea ) / Math.PI * 2 ; 608 return ( _kea * Math.pow( 2, - 10 * t) * Math.sin( ( t - s ) * Math.PI * 2 / _kep ) + 1 ); 609 }; 610 easingFn.easingElasticInOut = function(t) { 611 var s, _kea = 0.1, _kep = 0.4; 612 if ( t === 0 ) return 0; if ( t === 1 ) return 1; 613 if ( !_kea || _kea < 1 ) { _kea = 1; s = _kep / 4; } else s = _kep * Math.asin( 1 / _kea ) / Math.PI * 2 ; 614 if ( ( t *= 2 ) < 1 ) return - 0.5 * ( _kea * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t - s ) * Math.PI * 2 / _kep ) ); 615 return _kea * Math.pow( 2, -10 * ( t -= 1 ) ) * Math.sin( ( t - s ) * Math.PI * 2 / _kep ) * 0.5 + 1; 616 }; 617 easingFn.easingBounceIn = function(t) { return 1 - easingFn.easingBounceOut( 1 - t ); }; 618 easingFn.easingBounceOut = function(t) { 619 if ( t < ( 1 / 2.75 ) ) { return 7.5625 * t * t; } 620 else if ( t < ( 2 / 2.75 ) ) { return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75; } 621 else if ( t < ( 2.5 / 2.75 ) ) { return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375; } 622 else {return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375; } 623 }; 624 easingFn.easingBounceInOut = function(t) { if ( t < 0.5 ) return easingFn.easingBounceIn( t * 2 ) * 0.5; return easingFn.easingBounceOut( t * 2 - 1 ) * 0.5 + 0.5;}; 625
626 // single Tween object construct 627 var Tween = function (targetElement, startObject, endObject, optionsObj) { 628 this[element] = 'scroll' in endObject && (targetElement === undefined || targetElement === null) ? scrollContainer : targetElement; // element animation is applied to 629 630 this[playing] = false; 631 this.reversed = false; 632 this.paused = false; 633 634 this._startTime = null; 635 this._pauseTime = null; 636 637 this._startFired = false; 638 this[options] = {}; for (var o in optionsObj) { this[options][o] = optionsObj[o]; } 639 this[options].rpr = optionsObj.rpr || false; // internal option to process inline/computed style at start instead of init true/false 640 641 this[valuesRepeat] = {}; // internal valuesRepeat 642 this[valuesEnd] = {}; // valuesEnd 643 this[valuesStart] = {}; // valuesStart 644 645 preparePropertiesObject.call(this,endObject,'end'); // valuesEnd 646 if ( this[options].rpr ) { this[valuesStart] = startObject; } else { preparePropertiesObject.call(this,startObject,'start'); } // valuesStart 647 648 if ( this[options].perspective !== undefined && transformProperty in this[valuesEnd] ) { // element transform perspective 649 var perspectiveString = 'perspective('+parseInt(this[options].perspective)+'px)'; 650 this[valuesEnd][transformProperty].perspective = perspectiveString; 651 } 652 653 for ( var repeatProp in this[valuesEnd] ) { 654 if (repeatProp in crossCheck && !this[options].rpr) crossCheck[repeatProp].call(this); // this is where we do the valuesStart and valuesEnd check for fromTo() method 655 } 656 657 this[options][chain] = []; // chained Tweens 658 this[options][easing] = processEasing(optionsObj[easing]) || easingFn[defaultOptions[easing]] || easingFn['linear']; // you can only set a core easing function as default 659 this[options][repeat] = optionsObj[repeat] || defaultOptions[repeat]; 660 this[options][repeatDelay] = optionsObj[repeatDelay] || defaultOptions[repeatDelay]; 661 this[options][yoyo] = optionsObj[yoyo] || defaultOptions[yoyo]; 662 this[options][duration] = optionsObj[duration] || defaultOptions[duration]; // duration option | default 663 this[options][delay] = optionsObj[delay] || defaultOptions[delay]; // delay option | default 664 665 this[repeat] = this[options][repeat]; // we cache the number of repeats to be able to put it back after all cycles finish 666 }, 667 // tween control and chain 668 TweenProto = Tween.prototype = { 669 // queue tween object to main frame update 670 start : function (t) { // move functions that use the ticker outside the prototype to be in the same scope with it 671 scrollIn.call(this); 672 673 if ( this[options].rpr ) { getStartValues.apply(this); } // on start we reprocess the valuesStart for TO() method 674 perspective.apply(this); // apply the perspective and transform origin 675 676 for ( var endProp in this[valuesEnd] ) { 677 if (endProp in crossCheck && this[options].rpr) crossCheck[endProp].call(this); // this is where we do the valuesStart and valuesEnd check for to() method 678 this[valuesRepeat][endProp] = this[valuesStart][endProp]; 679 } 680 681 // now it's a good time to start 682 tweens.push(this); 683 this[playing] = true; 684 this.paused = false; 685 this._startFired = false; 686 this._startTime = t || time.now(); 687 this._startTime += this[options][delay]; 688 689 if (!this._startFired) { 690 if (this[options].start) { this[options].start.call(); } 691 this._startFired = true; 692 } 693 !tick && ticker(); 694 return this; 695 }, 696 play : function () { 697 if (this.paused && this[playing]) { 698 this.paused = false; 699 if (this[options].resume) { this[options].resume.call(); } 700 this._startTime += time.now() - this._pauseTime; 701 add(this); 702 !tick && ticker(); // restart ticking if stopped 703 } 704 return this; 705 }, 706 resume : function () { return this.play(); }, 707 pause : function() { 708 if (!this.paused && this[playing]) { 709 remove(this); 710 this.paused = true; 711 this._pauseTime = time.now(); 712 if (this[options].pause) { this[options].pause.call(); } 713 } 714 return this; 715 }, 716 stop : function () { 717 if (!this.paused && this[playing]) { 718 remove(this); 719 this[playing] = false;
720 this.paused = false; 721 scrollOut.call(this); 722 723 if (this[options].stop) { this[options].stop.call(); } 724 this.stopChainedTweens(); 725 close.call(this); 726 } 727 return this; 728 }, 729 chain : function() { this[options][chain] = arguments; return this; }, 730 stopChainedTweens : function () { 731 for (var i = 0, ctl = this[options][chain][length]; i < ctl; i++) { 732 this[options][chain][i].stop(); 733 } 734 } 735 }, 736 737 // the multi elements Tween constructs 738 TweensTO = function (els, vE, o) { // .to 739 this.tweens = []; var optionsObj = []; 740 for ( var i = 0, tl = els[length]; i < tl; i++ ) { 741 optionsObj[i] = o || {}; o[delay] = o[delay] || defaultOptions[delay]; 742 optionsObj[i][delay] = i>0 ? o[delay] + (o[offset]||defaultOptions[offset]) : o[delay]; 743 this.tweens.push( to(els[i], vE, optionsObj[i]) ); 744 } 745 }, 746 TweensFT = function (els, vS, vE, o) { // .fromTo 747 this.tweens = []; var optionsObj = []; 748 for ( var i = 0, l = els[length]; i < l; i++ ) { 749 optionsObj[i] = o || {}; o[delay] = o[delay] || defaultOptions[delay]; 750 optionsObj[i][delay] = i>0 ? o[delay] + (o[offset]||defaultOptions[offset]) : o[delay]; 751 this.tweens.push( fromTo(els[i], vS, vE, optionsObj[i]) ); 752 } 753 }, 754 ws = TweensTO.prototype = TweensFT.prototype = { 755 start : function(t){ 756 t = t || time.now(); 757 for ( var i = 0, tl = this.tweens[length]; i < tl; i++ ) { 758 this.tweens[i].start(t); 759 } 760 return this; 761 }, 762 stop : function(){ for ( var i = 0, tl = this.tweens[length]; i < tl; i++ ) { this.tweens[i].stop(); } return this; }, 763 pause : function(){ for ( var i = 0, tl = this.tweens[length]; i < tl; i++ ) { this.tweens[i].pause(); } return this; }, 764 chain : function(){ this.tweens[this.tweens[length]-1][options][chain] = arguments; return this; }, 765 play : function(){ for ( var i = 0, tl = this.tweens[length]; i < tl; i++ ) { this.tweens[i].play(); } return this; }, 766 resume : function() {return this.play()} 767 }, 768 769 // main methods 770 to = function (element, endObject, optionsObj) { 771 optionsObj = optionsObj || {}; optionsObj.rpr = true; 772 return new Tween(selector(element), endObject, endObject, optionsObj); 773 }, 774 fromTo = function (element, startObject, endObject, optionsObj) { 775 optionsObj = optionsObj || {}; 776 return new Tween(selector(element), startObject, endObject, optionsObj); 777 }, 778 779 // multiple elements tweening 780 allTo = function (elements, endObject, optionsObj) { 781 return new TweensTO(selector(elements,true), endObject, optionsObj); 782 }, 783 allFromTo = function (elements, startObject, endObject, optionsObj) { 784 return new TweensFT(selector(elements,true), startObject, endObject, optionsObj); 785 }; 786 787 document[addEventListener](touchOrWheel, preventScroll, false); 788 document[addEventListener](mouseEnter, preventScroll, false); 789 790 return { // export core methods to public for plugins 791 property: property, getPrefix: getPrefix, selector: selector, processEasing : processEasing, // utils 792 defaultOptions : defaultOptions, // default tween options since 1.6.1 793 to: to, fromTo: fromTo, allTo: allTo, allFromTo: allFromTo, // main methods 794 ticker : ticker, tick : tick, tweens : tweens, update: update, dom : DOM, // update 795 parseProperty: parseProperty, prepareStart: prepareStart, crossCheck : crossCheck, Tween : Tween, // property parsing & preparation | Tween | crossCheck 796 truD: trueDimension, truC: trueColor, rth: rgbToHex, htr: hexToRGB, getCurrentStyle: getCurrentStyle, // property parsing 797 }; 798}));
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.