/* KUTE.js - The Light Tweening Engine * by dnp_theme * Licensed under MIT-License */ (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['KUTE'], factory); } else if (typeof exports == 'object') { // Node, not strict CommonJS module.exports = factory(); } else { // Browser globals root.KUTE = root.KUTE || factory(); } }(this, function () { var K = K || {}, _tws = [], _t, _stk = false, // _stoppedTick // _tweens // KUTE, _tween, _tick, _pf = getPrefix(), // prefix _rafR = _rafR || ((!('requestAnimationFrame' in window)) ? true : false), // is prefix required for requestAnimationFrame _pfT = _pfT || ((!('transform' in document.getElementsByTagName('div')[0].style)) ? true : false), // is prefix required for transform _pfB = _pfB || ((!('border-radius' in document.getElementsByTagName('div')[0].style)) ? true : false), // is prefix required for border-radius _tch = _tch || (('ontouchstart' in window || navigator.msMaxTouchPoints) || false), // support Touch? _ev = _ev || (_tch ? 'touchstart' : 'mousewheel'), //event to prevent on scroll _bd = document.body, _htm = document.getElementsByTagName('HTML')[0], _sct = (/webkit/i.test(navigator.userAgent) || document.compatMode == 'BackCompat' ? _bd : _htm), _isIE8 = /ie8/.test(document.documentElement.className), //assign preffix to DOM properties _pfp = _pfp || _pfT ? _pf + 'Perspective' : 'perspective', _pfo = _pfo || _pfT ? _pf + 'PerspectiveOrigin' : 'perspectiveOrigin', _tr = _tr || _pfT ? _pf + 'Transform' : 'transform', _br = _br || _pfB ? _pf + 'BorderRadius' : 'borderRadius', _brtl = _brtl || _pfB ? _pf + 'BorderTopLeftRadius' : 'borderTopLeftRadius', _brtr = _brtr || _pfB ? _pf + 'BorderTopRightRadius' : 'borderTopRightRadius', _brbl = _brbl || _pfB ? _pf + 'BorderBottomLeftRadius' : 'borderBottomLeftRadius', _brbr = _brbr || _pfB ? _pf + 'BorderBottomRightRadius' : 'borderBottomRightRadius', _raf = _raf || _rafR ? window[_pf + 'RequestAnimationFrame'] : window['requestAnimationFrame'], _caf = _caf || _rafR ? window[_pf + 'CancelAnimationFrame'] : window['cancelAnimationFrame'], //supported properties _cls = ['color', 'backgroundColor', 'borderColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'], // colors 'hex', 'rgb', 'rgba' -- #fff / rgb(0,0,0) / rgba(0,0,0,0) _sc = ['scrollTop', 'scroll'], //scroll, it has no default value, it's calculated on tween start _clp = ['clip'], // clip _op = ['opacity'], // opacity _rd = ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], // border radius px/any _bm = ['top', 'left', 'right', 'bottom', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'padding', 'margin', 'paddingTop','paddingBottom', 'paddingLeft', 'paddingRight', 'marginTop','marginBottom', 'marginLeft', 'marginRight', 'borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'], // dimensions / box model _tp = ['fontSize','lineHeight','letterSpacing'], // text properties _bg = ['backgroundPosition'], // background position _3d = ['rotateX', 'rotateY','translateZ'], // transform properties that require perspective _tf = ['translate3d', 'translateX', 'translateY', 'translateZ', 'rotate', 'translate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'scale'], // transform _all = _cls.concat(_sc, _clp, _op, _rd, _bm, _tp, _bg, _tf), al = _all.length, _tfS = {}, _tfE = {}, _tlS = {}, _tlE = {}, _rtS = {}, _rtE = {}, //internal temp _d = _d || {}; //all properties default values //populate default values object for ( var i=0; i< al; i++){ var p = _all[i]; if (_cls.indexOf(p) !== -1){ _d[p] = 'rgba(0,0,0,0)'; // _d[p] = {r:0,g:0,b:0,a:1}; } else if ( _rd.indexOf(p) !== -1 || _bm.indexOf(p) !== -1 || _tp.indexOf(p) !== -1){ _d[p] = 0; } else if ( _bg.indexOf(p) !== -1 ){ _d[p] = [50,50]; } else if ( p === 'clip' ){ _d[p] = [0,0,0,0]; } else if ( p === 'translate3d' ){ _d[p] = [0,0,0]; } else if ( p === 'translate' ){ _d[p] = [0,0]; } else if ( p === 'rotate' || /X|Y|Z/.test(p) ){ _d[p] = 0; } else if ( p === 'scale' || p === 'opacity' ){ _d[p] = 1; } } //more internals K.getAll = function () { return _tws; }; K.removeAll = function () { _tws = []; }; K.add = function (tw) { _tws.push(tw); }; K.remove = function (tw) { var i = _tws.indexOf(tw); if (i !== -1) { _tws.splice(i, 1); } }; // internal ticker K.t = function (t) { _t = _raf(K.t); var i = 0, l = _tws.length; while ( i < l ) { if (!_tws[i]) {return false;} if (K.u(_tws[i],t)) { i++; } else { _tws.splice(i, 1); } } _stk = false; return true; }; // internal stopTick K.s = function () { if ( _stk === false ) { _caf(_t); _stk = true; _t = null; } }; //main methods K.to = function (el, to, o) { if ( o === undefined ) { o = {}; } var _el = _el || typeof el === 'object' ? el : document.querySelector(el), _o = _o || o; _o.rpr = true; _o.easing = _o && K.pe(_o.easing) || K.Easing.linear; var _vS = to, // we're gonna have to build this object at start _vE = K.prP(to, true), _tw = new K.Tween(_el, _vS, _vE, _o); return _tw; }; K.fromTo = function (el, f, to, o) { if ( o === undefined ) { o = {}; } var _el = _el || typeof el === 'object' ? el : document.querySelector(el); var _o = o; _o.easing = _o && K.pe(_o.easing) || K.Easing.linear; var _vS = K.prP(f, false), _vE = K.prP(to, true), _tw = new K.Tween(_el, _vS, _vE, _o); return _tw; }; // fallback method for previous versions K.Animate = function (el, f, to, o) { return K.fromTo(el, f, to, o); }; //main worker, doing update on tick K.u = function(w,t) { if (t < w._sT) { return true; } if (!w._sCF) { if (w._sC) { w._sC.call(); } w._sCF = true; } var e = ( t - w._sT ) / w._dr; //elapsed e = e > 1 ? 1 : e; var _v = w._e(e); //render the CSS update K.r(w,_v); if (w._uC) { w._uC.call(); } if (e === 1) { if (w._r > 0) { if ( w._r !== Infinity ) {w._r--; } var p; // reassign starting values, restart by making _sT = now for (p in w._vSR) { if (w._y) { var tmp = w._vSR[p]; w._vSR[p] = w._vE[p]; w._vE[p] = tmp; } w._vS[p] = w._vSR[p]; } if (w._y) { w._rv = !w._rv; } //set the right time for delay w._sT = (w._y && !w._rv) ? t + w._rD : t; return true; } else { if (w._cC) { w._cC.call(); } //stop preventing scroll when scroll tween finished w.scrollOut(); var i = 0, ctl = w._cT.length; for (i; i < ctl; i++) { w._cT[i].start(); } //stop ticking when finished w.close(); return false; } } return true; }; // render for each property K.r = function (w,v) { var p, css = w._el && w._el.style, ets = (w._el === undefined || w._el === null) ? _sct : w._el, opp = _isIE8 ? 'filter':'opacity'; for (p in w._vE) { var _start = w._vS[p], _end = w._vE[p], v1 = _start.value || 0, v2 = _end.value || 0, tv = v1 + (v2 - v1) * v, u = _end.unit, // checking array on every frame takes time so let's cache these cls = _cls.indexOf(p) !== -1, bm = _tp.indexOf(p) !== -1 || _bm.indexOf(p) !== -1, rd = _rd.indexOf(p) !== -1 && !_isIE8, sc = _sc.indexOf(p) !== -1, bg = _bg.indexOf(p) !== -1, clp = _clp.indexOf(p) !== -1, op = _op.indexOf(p) !== -1, tf = p === 'transform' && !_isIE8; //process styles by property / property type if ( rd ) { if (p === 'borderRadius') { css[_br] = tv + u; } else if (p === 'borderTopLeftRadius') { css[_brtl] = tv + u; } else if (p === 'borderTopRightRadius') { css[_brtr] = tv + u; } else if (p === 'borderBottomLeftRadius') { css[_brbl] = tv + u; } else if (p === 'borderBottomRightRadius') { css[_brbr] = tv + u; } } else if (tf) { var _tS = '', tP, rps, pps = 'perspective('+w._pp+'px) '; //transform style & property for (tP in _end) { var t1 = _start[tP], t2 = _end[tP]; rps = _3d.indexOf(tP) !== -1; if ( tP === 'translate' ) { var tls = '', ts = {}, ax; for (ax in t2){ var x1 = t1[ax].value || 0, x2 = t2[ax].value || 0, xu = t2[ax].unit || 'px'; ts[ax] = x1===x2 ? x2+xu : (x1 + ( x2 - x1 ) * v) + xu; } tls = t2.x ? 'translate(' + ts.x + ',' + ts.y + ')' : 'translate3d(' + ts.translateX + ',' + ts.translateY + ',' + ts.translateZ + ')'; _tS = (_tS === '') ? tls : (tls + ' ' + _tS); } else if ( tP === 'rotate' ) { var rt = '', rS = {}, rx; for ( rx in t2 ){ if ( t1[rx] ) { var a1 = t1[rx].value, a2 = t2[rx].value, au = t2[rx].unit||'deg', av = a1 + (a2 - a1) * v; rS[rx] = rx ==='z' ? 'rotate('+av+au+')' : rx + '(' + av + au + ') '; } } rt = t2.z ? rS.z : (rS.rotateX||'') + (rS.rotateY||'') + (rS.rotateZ||''); _tS = (_tS === '') ? rt : (_tS + ' ' + rt); } else if (tP==='skew') { var sk = '', sS = {}; for ( var sx in t2 ){ if ( t1[sx] ) { var s1 = t1[sx].value, s2 = t2[sx].value, su = t2[sx].unit||'deg', sv = s1 + (s2 - s1) * v; sS[sx] = sx + '(' + sv + su + ') '; } } sk = (sS.skewX||'') + (sS.skewY||''); _tS = (_tS === '') ? sk : (_tS + ' ' + sk); } else if (tP === 'scale') { var sc1 = t1.value, sc2 = t2.value, s = sc1 + (sc2 - sc1) * v, scS = tP + '(' + s + ')'; _tS = (_tS === '') ? scS : (_tS + ' ' + scS); } } css[_tr] = rps || ( w._pp !== undefined && w._pp !== 0 ) ? pps + _tS : _tS; } else if ( cls ) { var _c = {}, c; for (c in v2) { if ( c !== 'a' ){ _c[c] = parseInt(v1[c] + (v2[c] - v1[c]) * v); } else { _c[c] = (v1[c] && v2[c]) ? parseFloat(v1[c] + (v2[c] - v1[c]) * v) : null; } } if ( w._hex ) { css[p] = K.rth( parseInt(_c.r), parseInt(_c.g), parseInt(_c.b) ); } else { css[p] = !_c.a || _isIE8 ? 'rgb(' + _c.r + ',' + _c.g + ',' + _c.b + ')' : 'rgba(' + _c.r + ',' + _c.g + ',' + _c.b + ',' + _c.a + ')'; } } else if ( bm ) { css[p] = tv ? tv+u : 'auto'; } else if ( sc ) { ets.scrollTop = v1 + ( v2 - v1 ) * v; } else if ( bg ) { var px1 = _start.x.v||50, px2 = _end.x.v||50, py1 = _start.y.v||50, py2 = _end.y.v||50, px = px1 + ( px2 - px1 ) * v, pxu = _end.x.u || '%', py = py1 + ( py2 - py1 ) * v, pyu = _end.y.u || '%'; css[p] = px + pxu + ' ' + py + pyu; } else if ( clp ) { var h = 0, cl = []; for (h;h<4;h++){ var c1 = _start[h].v||0, c2 = _end[h].v||0, cu = _end[h].u || 'px'; cl[h] = (c1 + ( c2 - c1 ) * v) + cu; } css[p] = 'rect('+cl+')'; } else if ( op ) { css[opp] = !_isIE8 ? tv : "alpha(opacity=" + parseInt(tv*100) + ")"; } } }; K.perspective = function (l,w) { if ( w._ppo !== undefined ) { l.style[_pfo] = w._ppo; } // element perspective origin if ( w._ppp !== undefined ) { l.parentNode.style[_pfp] = w._ppp + 'px'; } // parent perspective if ( w._pppo !== undefined ) { l.parentNode.style[_pfo] = w._pppo; } // parent perspective origin }; K.Tween = function (_el, _vS, _vE, _o) { this._el = this._el || _el; // element animation is applied to this._dr = this._dr || _o&&_o.duration || 700; //duration this._r = this._r || _o&&_o.repeat || 0; // _repeat this._vSR = {}; // internal valuesStartRepeat this._vS = _vS; // valuesStart this._vE = _vE; // valuesEnd this._y = this._y || _o&&_o.yoyo || false; // _yoyo this._P = false; // _isPlaying this._rv = false; // _reversed this._rD = this._rD || _o&&_o.repeatDelay || 0; // _repeatDelay this._dl = this._dl || _o&&_o.delay || 0; //delay this._sT = null; // startTime this._ps = false; //_paused this._pST = null; //_pauseStartTime this._pp = this._pp || _o.perspective; // perspective this._ppo = this._ppo || _o.perspectiveOrigin; // perspective origin this._ppp = this._ppp || _o.parentPerspective; // parent perspective this._pppo = this._pppo || _o.parentPerspectiveOrigin; // parent perspective origin this._rpr = this._rpr || _o.rpr || false; // internal option to process inline/computed style at start instead of init true/false this._hex = this._hex || _o.keepHex || false; // option to keep hex for color tweens true/false this._e = this._e || _o.easing; // _easing this._cT = this._cT || []; //_chainedTweens this._sC = this._sC || _o&&_o.start || null; // _on StartCallback this._sCF = false; //_on StartCallbackFIRED this._uC = _o&&_o.update || null; // _on UpdateCallback this._cC = _o&&_o.complete || null; // _on CompleteCallback this._pC = _o&&_o.pause || null; // _on PauseCallback this._rC = _o&&_o.play || null; // _on ResumeCallback this._stC = _o&&_o.stop || null; // _on StopCallback }; var w = K.Tween.prototype; w.start = function (t) { K.add(this); this._P = true; this._sCF = false; this._sT = t || window.performance.now(); this._sT += this._dl; this.scrollIn(); var f = {}; K.perspective(this._el,this); // apply the perspective if ( this._rpr ) { // on start we reprocess the valuesStart for TO() method f = this.prS(); this._vS = {}; this._vS = K.prP(f,false); for ( p in this._vS ) { if ( p === 'transform' && (p in this._vE) ){ for ( var sp in this._vS[p]) { if (!(sp in this._vE[p])) { this._vE[p][sp] = {}; } for ( var spp in this._vS[p][sp] ) { // 3rd level if ( this._vS[p][sp][spp].value !== undefined /*&& */ ) { if (!(spp in this._vE[p][sp])) { this._vE[p][sp][spp] = {}; } for ( var sppp in this._vS[p][sp][spp]) { // spp = translateX | rotateX | skewX | rotate2d if ( !(sppp in this._vE[p][sp][spp])) { this._vE[p][sp][spp][sppp] = this._vS[p][sp][spp][sppp]; // sppp = unit | value } } } } if ( 'value' in this._vS[p][sp] && (!('value' in this._vE[p][sp])) ) { // 2nd level for ( var spp in this._vS[p][sp] ) { // scale if (!(spp in this._vE[p][sp])) { this._vE[p][sp][spp] = this._vS[p][sp][spp]; // spp = unit | value } } } } } } } for ( p in this._vE ) { this._vSR[p] = this._vS[p]; } if (!_t) K.t(); return this; }; w.prS = function () { //prepare valuesStart for .to() method var f = {}, el = this._el, to = this._vS, cs = this.gIS('transform'), deg = ['rotate','skew'], ax = ['X','Y','Z']; for (var p in to){ if ( _tf.indexOf(p) !== -1 ) { var r2d = (p === 'rotate' || p === 'translate' || p === 'scale'); if ( /translate/.test(p) && p !== 'translate' ) { f['translate3d'] = cs['translate3d'] || _d[p]; } else if ( r2d ) { // 2d transforms f[p] = cs[p] || _d[p]; } else if ( !r2d && /rotate|skew/.test(p) ) { // all angles for (var d=0; d<2; d++) { for (var a = 0; a<3; a++) { var s = deg[d]+ax[a]; if (_tf.indexOf(s) !== -1 && (s in to) ) { f[s] = cs[s] || _d[s]; } } } } } else { if ( _sc.indexOf(p) === -1 ) { if (p === 'opacity' && _isIE8 ) { // handle IE8 opacity var co = this.gCS('filter'); f['opacity'] = typeof co === 'number' ? co : _d['opacity']; } else{ f[p] = this.gCS(p) || _d[p]; } } else { f[p] = (el === null || el === undefined) ? (window.pageYOffset || _sct.scrollTop) : el.scrollTop; } } } for ( var p in cs ){ // also add to _vS values from previous tweens if ( _tf.indexOf(p) !== -1 && (!( p in to )) ) { f[p] = cs[p] || _d[p]; } } return f; }; w.gIS = function(p) { // gIS = get transform style for element from cssText for .to() method, the sp is for transform property if (!this._el) return; // if the scroll applies to `window` it returns as it has no styling var l = this._el, cst = l.style.cssText,//the cssText trsf = {}; //the transform object // if we have any inline style in the cssText attribute, usually it has higher priority var css = cst.replace(/\s/g,'').split(';'), i=0, csl = css.length; for ( i; i