diff --git a/gulpfile.js b/gulpfile.js index 5551782853..3e1eed62b1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -366,7 +366,7 @@ gulp.task('old.build', function() { 'old.ionic.examples', 'old.sass', 'old.fonts', - 'old.polyfills'); + 'old.vendor'); }) gulp.task('old.watch', function() { @@ -377,7 +377,7 @@ gulp.task('old.watch', function() { 'old.ionic.examples', 'old.sass', 'old.fonts', - 'old.polyfills', + 'old.vendor', function() { watch('ionic/**/*.js', function(file) { @@ -413,8 +413,8 @@ function doubleCheckDistFiles() { gulp.start('old.fonts'); } - if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/polyfills')) { - gulp.start('old.polyfills'); + if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/vendor')) { + gulp.start('old.vendor'); } } @@ -475,9 +475,9 @@ gulp.task('old.fonts', function() { }); -gulp.task('old.polyfills', function() { - return gulp.src('ionic/animations/web-animations*') - .pipe(gulp.dest('../angular-ionic/dist/js/dev/es5/polyfills')); +gulp.task('old.vendor', function() { + return gulp.src(['scripts/vendor/**/*']) + .pipe(gulp.dest('../angular-ionic/dist/js/dev/es5/vendor')); }); diff --git a/ionic/animations/web-animations.min.js b/ionic/animations/web-animations.min.js deleted file mode 100644 index bf20829071..0000000000 --- a/ionic/animations/web-animations.min.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -!function(a,b){b["true"]=a,function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}var c={},d={},e={},f=null;!function(a){function b(b,c){var d={delay:0,endDelay:0,fill:c?"both":"none",iterationStart:0,iterations:1,duration:c?"auto":0,playbackRate:1,direction:"normal",easing:"linear"};return"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof d[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==p.indexOf(b[c]))return;if("direction"==c&&-1==q.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;d[c]=b[c]}}):d.duration=b,d}function c(a,c){var d=b(a,c);return d.easing=f(d.easing),d}function d(a,b,c,d){return 0>a||a>1||0>c||c>1?y:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function e(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function f(a){var b=w.exec(a);if(b)return d.apply(this,b.slice(1).map(Number));var c=x.exec(a);if(c)return e(Number(c[1]),{start:r,middle:s,end:t}[c[2]]);var f=u[a];return f?f:y}function g(a){return Math.abs(h(a)/a.playbackRate)}function h(a){return a.duration*a.iterations}function i(a,b,c){return null==b?z:b=c.delay+a?B:C}function j(a,b,c,d,e){switch(d){case A:return"backwards"==b||"both"==b?0:null;case C:return c-e;case B:return"forwards"==b||"both"==b?a:null;case z:return null}}function k(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function l(a,b,c,d,e){return 1/0===c||c===-1/0||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function m(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function n(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function o(a,b,c){var d=i(a,b,c),e=j(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===A?0:1;var f=c.iterationStart*c.duration,g=k(a,e,f,c),o=l(c.duration,h(c),g,f,c),p=m(c.duration,o,g,c);return n(p,c.duration,o,c)/c.duration}var p="backwards|forwards|both|none".split("|"),q="reverse|alternate|alternate-reverse".split("|"),r=1,s=.5,t=0,u={ease:d(.25,.1,.25,1),"ease-in":d(.42,0,1,1),"ease-out":d(0,0,.58,1),"ease-in-out":d(.42,0,.58,1),"step-start":e(1,r),"step-middle":e(1,s),"step-end":e(1,t)},v="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",w=new RegExp("cubic-bezier\\("+v+","+v+","+v+","+v+"\\)"),x=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,y=function(a){return a},z=0,A=1,B=2,C=3;a.makeTiming=b,a.normalizeTimingInput=c,a.calculateActiveDuration=g,a.calculateTimeFraction=o,a.calculatePhase=i,a.toTimingFunction=f}(c,f),function(a){function b(a,b){return a in h?h[a][b]||b:b}function c(a,c,d){var g=e[a];if(g){f.style[a]=c;for(var h in g){var i=g[h],j=f.style[i];d[i]=b(i,j)}}else d[a]=b(a,c)}function d(b){function d(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var d={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}c(e,f,d)}return void 0==d.offset&&(d.offset=null),void 0==d.easing&&(d.easing=a.toTimingFunction("linear")),d}),f=!0,g=-1/0,h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||d(),e}var e={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},f=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g={thin:"1px",medium:"3px",thick:"5px"},h={borderBottomWidth:g,borderLeftWidth:g,borderRightWidth:g,borderTopWidth:g,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:g,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=d}(c,f),function(a){var b={};a.isDeprecated=function(a,c,d,e){var f=e?"are":"is",g=new Date,h=new Date(c);return h.setMonth(h.getMonth()+3),h>g?(a in b||console.warn("Web Animations: "+a+" "+f+" deprecated and will stop working on "+h.toDateString()+". "+d),b[a]=!0,!1):!0},a.deprecated=function(b,c,d,e){var f=e?"are":"is";if(a.isDeprecated(b,c,d,e))throw new Error(b+" "+f+" no longer supported. "+d)}}(c),function(a,b){function c(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a){function b(a,b,c){e[c]=e[c]||[],e[c].push([a,b])}function c(a,c,d){for(var e=0;ethis._surrogateStyle.length;)this._length--,Object.defineProperty(this,this._length,{configurable:!0,enumerable:!1,value:void 0})},_set:function(a,b){this._style[a]=b,this._isAnimatedProperty[a]=!0},_clear:function(a){this._style[a]=this._surrogateStyle[a],delete this._isAnimatedProperty[a]}};for(var h in f)c.prototype[h]=function(a,b){return function(){var c=this._surrogateStyle[a].apply(this._surrogateStyle,arguments);return b&&(this._isAnimatedProperty[arguments[0]]||this._style[a].apply(this._style,arguments),this._updateIndices()),c}}(h,h in g);for(var i in document.documentElement.style)i in e||i in f||!function(a){b(c.prototype,a,{get:function(){return this._surrogateStyle[a]},set:function(b){this._surrogateStyle[a]=b,this._updateIndices(),this._isAnimatedProperty[a]||(this._style[a]=b)}})}(i);a.apply=function(b,c,e){d(b),b.style._set(a.propertyName(c),e)},a.clear=function(b,c){b._webAnimationsPatchedStyle&&b.style._clear(a.propertyName(c))}}(d,f),function(a){window.Element.prototype.animate=function(b,c){return a.timeline._play(a.KeyframeEffect(this,b,c))}}(d),function(a){function b(a,c,d){if("number"==typeof a&&"number"==typeof c)return a*(1-d)+c*d;if("boolean"==typeof a&&"boolean"==typeof c)return.5>d?a:c;if(a.length==c.length){for(var e=[],f=0;fj;j++)g.push(c[j]*(Math.cos(e*h)-f*i)+d[j]*i);return g}var d=function(){function a(a,b){for(var c=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],d=0;4>d;d++)for(var e=0;4>e;e++)for(var f=0;4>f;f++)c[d][e]+=b[d][f]*a[f][e];return c}function b(a){return 0==a[0][2]&&0==a[0][3]&&0==a[1][2]&&0==a[1][3]&&0==a[2][0]&&0==a[2][1]&&1==a[2][2]&&0==a[2][3]&&0==a[3][2]&&1==a[3][3]}function c(c,d,e,f,g){for(var h=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],i=0;4>i;i++)h[i][3]=g[i];for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[3][i]+=c[j]*h[j][i];var k=f[0],l=f[1],m=f[2],n=f[3],o=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];o[0][0]=1-2*(l*l+m*m),o[0][1]=2*(k*l-m*n),o[0][2]=2*(k*m+l*n),o[1][0]=2*(k*l+m*n),o[1][1]=1-2*(k*k+m*m),o[1][2]=2*(l*m-k*n),o[2][0]=2*(k*m-l*n),o[2][1]=2*(l*m+k*n),o[2][2]=1-2*(k*k+l*l),h=a(h,o);var p=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];e[2]&&(p[2][1]=e[2],h=a(h,p)),e[1]&&(p[2][1]=0,p[2][0]=e[0],h=a(h,p)),e[0]&&(p[2][0]=0,p[1][0]=e[0],h=a(h,p));for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[i][j]*=d[i];return b(h)?[h[0][0],h[0][1],h[1][0],h[1][1],h[3][0],h[3][1]]:h[0].concat(h[1],h[2],h[3])}return c}();a.composeMatrix=d,a.quat=c}(d,f),function(a){var b=0,c=function(a,b,c){this.target=a,this.currentTime=b,this.timelineTime=c,this.type="finish",this.bubbles=!1,this.cancelable=!1,this.currentTarget=a,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()};a.Animation=function(a){this._sequenceNumber=b++,this._currentTime=0,this._startTime=null,this.paused=!1,this._playbackRate=1,this._inTimeline=!0,this._finishedFlag=!1,this.onfinish=null,this._finishHandlers=[],this._effect=a,this._inEffect=this._effect._update(0),this._idle=!0,this._currentTimePending=!1},a.Animation.prototype={_ensureAlive:function(){this._inEffect=this._effect._update(this.playbackRate<0&&0===this.currentTime?-1:this.currentTime),this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,a.timeline._animations.push(this))},_tickCurrentTime:function(a,b){a!=this._currentTime&&(this._currentTime=a,this.finished&&!b&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(b){b=+b,isNaN(b)||(a.restart(),this.paused||null==this._startTime||(this._startTime=this._timeline.currentTime-b/this._playbackRate),this._currentTimePending=!1,this._currentTime!=b&&(this._tickCurrentTime(b,!0),a.invalidateEffects()))},get startTime(){return this._startTime},set startTime(b){b=+b,isNaN(b)||this.paused||this._idle||(this._startTime=b,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),a.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get finished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this.paused&&0!=this.playbackRate||this._currentTimePending?"pending":this.paused?"paused":this.finished?"finished":"running"},play:function(){this.paused=!1,(this.finished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,a.invalidateEffects()),this._finishedFlag=!1,a.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this.finished||this.paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this.paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this.finished;if((b||this._idle)&&!this._finishedFlag){var d=new c(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);setTimeout(function(){e.forEach(function(a){a.call(d.target,d)})},0)}this._finishedFlag=b},_tick:function(a){return this._idle||this.paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this.finished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(d,f),function(a,b){function c(a){var b=i;i=[],g(a),b.forEach(function(b){b[1](a)}),m&&g(a),f()}function d(a,b){return a._sequenceNumber-b._sequenceNumber}function e(){this._animations=[],this.currentTime=window.performance&&performance.now?performance.now():0}function f(){n.forEach(function(a){a()}),n.length=0}function g(a){l=!1;var c=b.timeline;c.currentTime=a,c._animations.sort(d),k=!1;var e=c._animations;c._animations=[];var f=[],g=[];e=e.filter(function(b){return b._inTimeline=b._tick(a),b._inEffect?g.push(b._effect):f.push(b._effect),b.finished||b.paused||b._idle||(k=!0),b._inTimeline}),n.push.apply(n,f),n.push.apply(n,g),c._animations.push.apply(c._animations,e),m=!1,k&&requestAnimationFrame(function(){})}var h=window.requestAnimationFrame,i=[],j=0;window.requestAnimationFrame=function(a){var b=j++;return 0==i.length&&h(c),i.push([b,a]),b},window.cancelAnimationFrame=function(a){i.forEach(function(b){b[0]==a&&(b[1]=function(){})})},e.prototype={_play:function(c){c._timing=a.normalizeTimingInput(c.timing);var d=new b.Animation(c);return d._idle=!1,d._timeline=this,this._animations.push(d),b.restart(),b.invalidateEffects(),d}};var k=!1,l=!1;b.restart=function(){return k||(k=!0,requestAnimationFrame(function(){}),l=!0),l};var m=!1;b.invalidateEffects=function(){m=!0};var n=[],o=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){return m&&g(p.currentTime),f(),o.apply(this,arguments)}});var p=new e;b.timeline=p}(c,d,f),function(a){function b(a,b){for(var c=0,d=0;do;o++){for(var p=0,q=0;3>q;q++)p+=b[3][q]*m[q][o];n.push(p)}return n.push(1),m.push(n),m}function d(a){return[[a[0][0],a[1][0],a[2][0],a[3][0]],[a[0][1],a[1][1],a[2][1],a[3][1]],[a[0][2],a[1][2],a[2][2],a[3][2]],[a[0][3],a[1][3],a[2][3],a[3][3]]]}function e(a,b){for(var c=[],d=0;4>d;d++){for(var e=0,f=0;4>f;f++)e+=a[f]*b[f][d];c.push(e)}return c}function f(a){var b=g(a);return[a[0]/b,a[1]/b,a[2]/b]}function g(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])}function h(a,b,c,d){return[c*a[0]+d*b[0],c*a[1]+d*b[1],c*a[2]+d*b[2]]}function i(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]}function j(j){var k=[j.slice(0,4),j.slice(4,8),j.slice(8,12),j.slice(12,16)];if(1!==k[3][3])return null;for(var l=[],m=0;4>m;m++)l.push(k[m].slice());for(var m=0;3>m;m++)l[m][3]=0;if(0===a(l))return!1;var n,o=[];if(k[0][3]||k[1][3]||k[2][3]){o.push(k[0][3]),o.push(k[1][3]),o.push(k[2][3]),o.push(k[3][3]);var p=c(l),q=d(p);n=e(o,q)}else n=[0,0,0,1];var r=k[3].slice(0,3),s=[];s.push(k[0].slice(0,3));var t=[];t.push(g(s[0])),s[0]=f(s[0]);var u=[];s.push(k[1].slice(0,3)),u.push(b(s[0],s[1])),s[1]=h(s[1],s[0],1,-u[0]),t.push(g(s[1])),s[1]=f(s[1]),u[0]/=t[1],s.push(k[2].slice(0,3)),u.push(b(s[0],s[2])),s[2]=h(s[2],s[0],1,-u[1]),u.push(b(s[1],s[2])),s[2]=h(s[2],s[1],1,-u[2]),t.push(g(s[2])),s[2]=f(s[2]),u[1]/=t[2],u[2]/=t[2];var v=i(s[1],s[2]);if(b(s[0],v)<0)for(var m=0;3>m;m++)t[m]*=-1,s[m][0]*=-1,s[m][1]*=-1,s[m][2]*=-1;var w,x,y=s[0][0]+s[1][1]+s[2][2]+1;return y>1e-4?(w=.5/Math.sqrt(y),x=[(s[2][1]-s[1][2])*w,(s[0][2]-s[2][0])*w,(s[1][0]-s[0][1])*w,.25/w]):s[0][0]>s[1][1]&&s[0][0]>s[2][2]?(w=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]),x=[.25*w,(s[0][1]+s[1][0])/w,(s[0][2]+s[2][0])/w,(s[2][1]-s[1][2])/w]):s[1][1]>s[2][2]?(w=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]),x=[(s[0][1]+s[1][0])/w,.25*w,(s[1][2]+s[2][1])/w,(s[0][2]-s[2][0])/w]):(w=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]),x=[(s[0][2]+s[2][0])/w,(s[1][2]+s[2][1])/w,.25*w,(s[1][0]-s[0][1])/w]),[r,t,u,x,n]}return j}();a.dot=b,a.makeMatrixDecomposition=f}(d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,b,["visibility"])}(d),function(a){function b(a){a=a.trim(),e.fillStyle="#000",e.fillStyle=a;var b=e.fillStyle;if(e.fillStyle="#fff",e.fillStyle=a,b==e.fillStyle){e.fillRect(0,0,1,1);var c=e.getImageData(0,0,1,1).data;e.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function c(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=d.height=1;var e=d.getContext("2d");a.addPropertiesHandler(b,c,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,b),a.mergeColors=c}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a){function b(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function c(c){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,b,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],c);return d&&4==d[0].length?d[0]:void 0}function d(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function e(a){return"rect("+a+")"}var f=a.mergeWrappedNestedRepeated.bind(null,e,d,", ");a.parseBox=c,a.mergeBoxes=f,a.addPropertiesHandler(c,f,["clip"]) -}(d,f),function(a){function b(a){return function(b){var c=0;return a.map(function(a){return a===j?b[c++]:a})}}function c(a){return a}function d(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=m[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.lengthb||b>900||b%100!==0?void 0:b}function c(b){return b=100*Math.round(b/100),b=a.clamp(100,900,b),400===b?"normal":700===b?"bold":String(b)}function d(a,b){return[a,b,c]}a.addPropertiesHandler(b,d,["font-weight"])}(d),function(a){function b(a){var b={};for(var c in a)b[c]=-a[c];return b}function c(b){return a.consumeToken(/^(left|center|right|top|bottom)\b/i,b)||a.consumeLengthOrPercent(b)}function d(b,d){var e=a.consumeRepeated(c,/^/,d);if(e&&""==e[1]){var f=e[0];if(f[0]=f[0]||"center",f[1]=f[1]||"center",3==b&&(f[2]=f[2]||{px:0}),f.length==b){if(/top|bottom/.test(f[0])||/left|right/.test(f[1])){var h=f[0];f[0]=f[1],f[1]=h}if(/left|right|center|Object/.test(f[0])&&/top|bottom|center|Object/.test(f[1]))return f.map(function(a){return"object"==typeof a?a:g[a]})}}}function e(d){var e=a.consumeRepeated(c,/^/,d);if(e){for(var f=e[0],h=[{"%":50},{"%":50}],i=0,j=!1,k=0;k { + console.log('transition play') + transAnimation.play(true).then(() => { + console.log('transition finished') // transition has completed, update each item's state enteringItem.state = ACTIVE_STATE; diff --git a/ionic/util/tap.js b/ionic/util/tap.js index 96dbe65988..9b4bd92d18 100644 --- a/ionic/util/tap.js +++ b/ionic/util/tap.js @@ -114,8 +114,6 @@ export let Tap = { run: function() { dom.ready().then(() => { - console.log('ADAM CLICK: GOOOO!!!!'); - Tap.register(document); }); }, diff --git a/scripts/e2e/angular.template.html b/scripts/e2e/angular.template.html index 07f140dde0..9e75080298 100644 --- a/scripts/e2e/angular.template.html +++ b/scripts/e2e/angular.template.html @@ -43,7 +43,7 @@ $SCRIPTS$ - + diff --git a/scripts/vendor/web-animations-js/.travis-setup.sh b/scripts/vendor/web-animations-js/.travis-setup.sh new file mode 100755 index 0000000000..e688e4f173 --- /dev/null +++ b/scripts/vendor/web-animations-js/.travis-setup.sh @@ -0,0 +1,100 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#! /bin/bash + +set -x +set -e + +# Make sure /dev/shm has correct permissions. +ls -l /dev/shm +sudo chmod 1777 /dev/shm +ls -l /dev/shm + +uname -a +cat /etc/lsb-release + +npm install +npm install -g grunt-cli + +sudo apt-get update --fix-missing + +# Install python-imaging from the environment rather then build it. +# If the below fails, pip will build it via the requirements.txt +# sudo apt-get install python-imaging +# VIRTUAL_ENV_site_packages=$(echo $VIRTUAL_ENV/lib/*/site-packages) +# VIRTUAL_ENV_python_version=$(echo $VIRTUAL_ENV_site_packages | sed -e's@.*/\(.*\)/site-packages@\1@') +# ln -s /usr/lib/$VIRTUAL_ENV_python_version/dist-packages/PIL.pth $VIRTUAL_ENV_site_packages/PIL.pth +# ln -s /usr/lib/$VIRTUAL_ENV_python_version/dist-packages/PIL $VIRTUAL_ENV_site_packages/PIL + +export VERSION=$(echo $BROWSER | sed -e's/[^-]*-//') +export BROWSER=$(echo $BROWSER | sed -e's/-.*//') + +echo BROWSER=$BROWSER +echo VERSION=$VERSION + +sudo ln -sf $(which true) $(which xdg-desktop-menu) + +case $BROWSER in +Android) + sudo apt-get install -qq --force-yes \ + libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 \ + libstdc++6:i386 lib32z1 libreadline6-dev:i386 \ + libncurses5-dev:i386 + bash tools/android/setup.sh + ;; + +Chrome) + echo "Getting $VERSION of $BROWSER" + export CHROME=google-chrome-${VERSION}_current_amd64.deb + wget https://dl.google.com/linux/direct/$CHROME + sudo dpkg --install $CHROME || sudo apt-get -f install + which google-chrome + ls -l `which google-chrome` + + if [ -f /opt/google/chrome/chrome-sandbox ]; then + export CHROME_SANDBOX=/opt/google/chrome/chrome-sandbox + else + export CHROME_SANDBOX=$(ls /opt/google/chrome*/chrome-sandbox) + fi + + # Download a custom chrome-sandbox which works inside OpenVC containers (used on travis). + sudo rm -f $CHROME_SANDBOX + sudo wget https://googledrive.com/host/0B5VlNZ_Rvdw6NTJoZDBSVy1ZdkE -O $CHROME_SANDBOX + sudo chown root:root $CHROME_SANDBOX; sudo chmod 4755 $CHROME_SANDBOX + sudo md5sum $CHROME_SANDBOX + + google-chrome --version + ;; + +Firefox) + sudo rm -f /usr/local/bin/firefox + case $VERSION in + beta) + yes "\n" | sudo add-apt-repository -y ppa:mozillateam/firefox-next + ;; + aurora) + yes "\n" | sudo add-apt-repository -y ppa:ubuntu-mozilla-daily/firefox-aurora + ;; + esac + sudo apt-get update --fix-missing + sudo apt-get install firefox + which firefox + ls -l `which firefox` + firefox --version + ;; +esac + +# R=tools/python/requirements.txt +# pip install -r $R --use-mirrors || pip install -r $R diff --git a/scripts/vendor/web-animations-js/.travis.yml b/scripts/vendor/web-animations-js/.travis.yml new file mode 100755 index 0000000000..83979d8372 --- /dev/null +++ b/scripts/vendor/web-animations-js/.travis.yml @@ -0,0 +1,11 @@ +language: node_js + +node_js: + - "0.10" + +install: + - BROWSER="Firefox-aurora" ./.travis-setup.sh + +before_script: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start diff --git a/scripts/vendor/web-animations-js/COPYING b/scripts/vendor/web-animations-js/COPYING new file mode 100755 index 0000000000..d645695673 --- /dev/null +++ b/scripts/vendor/web-animations-js/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/scripts/vendor/web-animations-js/Gruntfile.js b/scripts/vendor/web-animations-js/Gruntfile.js new file mode 100755 index 0000000000..842d2ac86f --- /dev/null +++ b/scripts/vendor/web-animations-js/Gruntfile.js @@ -0,0 +1,293 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module.exports = function(grunt) { + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-gjslint'); + grunt.loadNpmTasks('grunt-checkrepo'); + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-saucelabs'); + grunt.loadNpmTasks('grunt-git-status'); + grunt.loadNpmTasks('grunt-template'); + + var targetConfig = require('./target-config.js'); + + var sourceMap = require('source-map'); + + var config = { + uglify: {}, + template: {}, + wrap: {}, + sourceMapConcat: {}, + }; + + function concat(sources, target, defines) { + config.uglify[target] = { + options: { + sourceMap: true, + sourceMapName: target + '.map', + wrap: false, + compress: { + global_defs: defines, + dead_code: false + }, + mangle: false + }, + nonull: true, + dest: target, + src: sources + }; + return 'uglify:' + target; + } + + function compress(source, target, defines) { + var name = concat([source], target, defines); + var record = config.uglify[target]; + record.options.sourceMapIn = source + '.map'; + record.options.banner = grunt.file.read('templates/boilerplate'); + record.options.wrap = true; + record.options.compress.dead_code = true; + record.options.mangle = { eval: true }; + return name; + } + + function genTarget(target) { + var config = targetConfig[target]; + var newGens = [ + generateFromTemplate('templates/web-animations.js', {target: target}, target + '.dev.js'), + generateFromTemplate('templates/web-animations.html', {src: config.src}, target + '.dev.html'), + generateFromTemplate('templates/runner.html', {target: target}, 'test/runner-' + target + '.html')]; + return newGens; + } + + function generateFromTemplate(source, data, target) { + var targetSpec = {}; + targetSpec[target] = [source]; + config.template[target] = { + options: { + data: data + }, + files: targetSpec + } + return 'template:' + target; + } + + function guard(source, target) { + config.wrap[target] = { + source: source, + preamble: '(function() {\n' + + ' if (document.documentElement.animate) {\n' + + ' var player = document.documentElement.animate([], 0);\n' + + ' var load = true;\n' + + ' if (player) {\n' + + ' load = false;\n' + + ' "play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(t) {\n' + + ' if (player[t] === undefined) {\n' + + ' load = true;\n' + + ' }\n' + + ' });\n' + + ' }\n' + + ' if (!load) { return; }' + + ' }\n', + postamble: '})();' + }; + return 'wrap:' + target; + } + + function concatWithMaps(sources, target) { + config.sourceMapConcat[target] = { + sources: sources + } + return 'sourceMapConcat:' + target; + }; + + var concatDefines = { + WEB_ANIMATIONS_TESTING: false + }; + + function buildWebAnimations1(target) { + var config = targetConfig[target]; + return genTarget(target).concat([ + concat(config.scopeSrc.concat(config.sharedSrc).concat(config.webAnimations1Src), 'inter-raw-' + target + '.js', concatDefines), + guard('inter-raw-' + target + '.js', 'inter-' + target + '.js'), + compress('inter-' + target + '.js', target + '.min.js', concatDefines) + ]); + } + + function buildWebAnimationsNext(target) { + var config = targetConfig[target]; + return genTarget(target).concat([ + concat(config.scopeSrc.concat(config.sharedSrc), 'inter-' + target + '-preamble.js', concatDefines), + concat(config.webAnimations1Src, 'inter-component-' + target + 'web-animations-1.js', concatDefines), + guard('inter-component-' + target + 'web-animations-1.js', 'inter-guarded-' + target + '-web-animations-1.js'), + concat(config.webAnimationsNextSrc, 'inter-component-' + target + '.js', concatDefines), + concatWithMaps(['inter-' + target + '-preamble.js', 'inter-guarded-' + target + '-web-animations-1.js', 'inter-component-' + target + '.js'], + 'inter-' + target + '.js'), + compress('inter-' + target + '.js', target + '.min.js', concatDefines) + ]); + } + + grunt.registerTask('web-animations', buildWebAnimations1('web-animations')); + grunt.registerTask('web-animations-next', buildWebAnimationsNext('web-animations-next')); + grunt.registerTask('web-animations-next-lite', buildWebAnimationsNext('web-animations-next-lite')); + + var testTargets = {'web-animations': {}, 'web-animations-next': {}}; + + grunt.initConfig({ + uglify: config.uglify, + template: config.template, + wrap: config.wrap, + sourceMapConcat: config.sourceMapConcat, + checkrepo: { + all: { + clean: true, + }, + }, + 'git-status': { + all: { + }, + }, + gjslint: { + options: { + flags: [ + '--nojsdoc', + '--strict', + '--disable 7,121,110', // 7: Wrong blank line count + // 121: Illegal comma at end of object literal + // 110: Line too long + ], + reporter: { + name: 'console' + } + }, + all: { + src: [ + 'src/*.js', + 'test/*.js', + 'test/js/*.js', + ], + } + }, + test: testTargets, + sauce: testTargets, + }); + + + grunt.task.registerMultiTask('test', 'Run tests under Karma', function() { + var done = this.async(); + var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config.js'), {}); + var config = targetConfig[this.target]; + karmaConfig.files = ['test/runner.js'].concat(config.src, config.test); + var karmaServer = require('karma').server; + karmaServer.start(karmaConfig, function(exitCode) { + done(exitCode === 0); + }); + }); + + grunt.task.registerMultiTask('sauce', 'Run tests under Karma on Saucelabs', function() { + var done = this.async(); + var karmaConfig = require('karma/lib/config').parseConfig(require('path').resolve('test/karma-config-ci.js'), {}); + var config = targetConfig[this.target]; + karmaConfig.files = ['test/runner.js'].concat(config.src, config.test); + karmaConfig.sauceLabs.testName = 'web-animation-next ' + this.target + ' Unit tests'; + var karmaServer = require('karma').server; + karmaServer.start(karmaConfig, function(exitCode) { + done(exitCode === 0); + }); + }); + + grunt.task.registerMultiTask('sourceMapConcat', 'concat source files and produce combined source map', + function() { + var sources = this.data.sources.map(grunt.file.read); + var sourceMaps = this.data.sources.map(function(f) { return grunt.file.read(f + '.map'); }); + var out = ""; + var outMapGenerator = new sourceMap.SourceMapGenerator({file: this.target}); + var lineDelta = 0; + for (var i = 0; i < sources.length; i++) { + out += sources[i]; + new sourceMap.SourceMapConsumer(sourceMaps[i]).eachMapping(function(mapping) { + outMapGenerator.addMapping({ + generated: {line: mapping.generatedLine + lineDelta, column: mapping.generatedColumn}, + original: {line: mapping.originalLine, column: mapping.originalColumn}, + source: mapping.source, name: mapping.name}); + }); + var sourceLines = sources[i].split('\n'); + lineDelta += sourceLines.length; + if (sources[i][sources[i].length - 1] !== '\n') { + out += '\n'; + } + } + grunt.file.write(this.target, out); + grunt.file.write(this.target + '.map', outMapGenerator.toString()); + }); + + grunt.task.registerMultiTask('wrap', 'Wrap source file and update source map', + function() { + var inFile = grunt.file.read(this.data.source); + var inMap = grunt.file.read(this.data.source + '.map'); + var inLines = inFile.split('\n'); + var i = 0; + + // Discover copyright header + while (inLines[i].length < 2 || inLines[i].substring(0, 2) == '//') { + i++; + } + + // Fix mapping footer + var postamble = this.data.postamble; + if (inLines[inLines.length - 1].substring(0, 21) == '//# sourceMappingURL=') { + postamble += '\n//# sourceMappingURL=' + this.target + '.map'; + } + + if (i > 0) { + var banner = inLines.slice(0, i).join('\n') + '\n'; + } else { + var banner = ''; + } + + var source = inLines.slice(i, inLines.length - 1).join('\n'); + + grunt.file.write(this.target, banner + this.data.preamble + source + postamble); + var preLines = this.data.preamble.split('\n'); + var lineDelta = preLines.length; + if (this.data.preamble[this.data.preamble.length - 1] == '\n') { + var charDelta = 0; + } else { + var charDelta = preLines[lineDelta - 1].length; + lineDelta -= 1; + } + var inMapConsumer = new sourceMap.SourceMapConsumer(inMap); + var outMapGenerator = new sourceMap.SourceMapGenerator({file: this.target}); + inMapConsumer.eachMapping(function(mapping) { + if (mapping.generatedLine == i + 1) { + mapping.generatedColumn += charDelta; + } + mapping.generatedLine += lineDelta; + outMapGenerator.addMapping( + {generated: {line: mapping.generatedLine, column: mapping.generatedColumn}, + original: {line: mapping.originalLine, column: mapping.originalColumn}, + source: mapping.source, name: mapping.name}); + }); + grunt.file.write(this.target + '.map', outMapGenerator.toString()); + }); + + grunt.task.registerTask('clean', 'Remove files generated by grunt', function() { + grunt.file.expand('web-animations*').concat(grunt.file.expand('test/runner-*.html')).concat(grunt.file.expand('inter-*')).forEach(function(file) { + grunt.file.delete(file); + grunt.log.writeln('File ' + file + ' removed'); + }); + }); + + grunt.task.registerTask('default', ['web-animations', 'web-animations-next', 'web-animations-next-lite', 'gjslint']); +}; diff --git a/scripts/vendor/web-animations-js/History.md b/scripts/vendor/web-animations-js/History.md new file mode 100755 index 0000000000..4c50afa409 --- /dev/null +++ b/scripts/vendor/web-animations-js/History.md @@ -0,0 +1,108 @@ +### 2.0.0 - *April 5 2015* + + * Improve behavior of group Animation playback rate. + * Rename Animation to KeyframeEffect. + * Rename AnimationSequence to SequenceEffect. + * Rename AnimationGroup to GroupEffect. + * Rename AnimationPlayer to Animation. + * Remove KeyframeEffect.effect and add KeyframeEffect.getFrames. + * Rename Animation.source to Animation.effect. + * Rename Timeline.getAnimationPlayers to Timeline.getAnimations. + * Rename Element.getAnimationPlayers to Element.getAnimations. + +### 1.0.7 - *March 10 2015* + + * Improve performance of constructing groups and sequences. + * Remove support for animating zoom. + * Add bower file. + +### 1.0.6 - *February 5 2015* + + * Implement playbackRate setter for group players. + * Fix pausing a group player before its first tick. + * Fix cancelling a group player before its first tick. + * Fix excess CPU use on idle pages where custom effects and groups were used. + * Suppress AnimationTiming.playbackRate deprecation warning for cases where AnimationTiming.playbackRate == 1. + +### 1.0.5 - *January 6 2015* + + * Fix loading the polyfill in an SVG document + * Fix a problem where groups didn't take effect in their first frame + * Don't rely on performance.now + +### 1.0.4 - *December 8 2014* + + * Fix a critical bug where deprecation logic wasn't being loaded + when `web-animations-next` and `web-animations-next-lite` were + executed on top of a native `element.animate`. + +### 1.0.3 - *December 4 2014* + + * Fix a critical bug on iOS 7 and Safari <= 6. Due to limitations, + inline style patching is not supported on these platforms. + +### 1.0.2 - *November 28 2014* + + * Deprecated `AnimationTiming.playbackRate`. + + For example, this is no longer supported: + + var player = element.animate( + keyframes, + {duration: 1000, playbackRate: 2}); + + Use `AnimationPlayer.playbackRate` instead: + + var player = element.animate( + keyframes, + {duration: 1000}); + player.playbackRate = 2; + + If you have any feedback on this change, please start a discussion + on the public-fx mailing list: + http://lists.w3.org/Archives/Public/public-fx/ + + Or file an issue against the specification on GitHub: + https://github.com/w3c/web-animations/issues/new + +### 1.0.1 - *November 26 2014* + + * Players should be constructed in idle state + * `play()` and `reverse()` should not force a start times + * Add `requestAnimationFrame` ids and `cancelAnimationFrame` + +### 1.0.0 — *November 21 2014* + + The web-animations-js hackers are pleased to announce the release of + a new codebase for the Web Animations Polyfill: + https://github.com/web-animations/web-animations-js + + The previous polyfill has been moved to: + https://github.com/web-animations/web-animations-js-legacy + + The new codebase is focused on code-size -- our smallest target is + now only 33kb or 11kb after gzip. + + We've implemented native fallback. If the target browser provides + Web Animations features natively, the Polyfill will use them. + + We now provide three different build targets: + + `web-animations.min.js` - Tracks the Web Animations features that + are supported natively in browsers. Today that means Element.animate + and Playback Control in Chrome. If you’re not sure what features you + will need, start with this. + + `web-animations-next.min.js` - All of web-animations.min.js plus + features that are still undergoing discussion or have yet to be + implemented natively. + + `web-animations-next-lite.min.js` - A cut down version of + web-animations-next, removes several lesser used property handlers + and some of the larger and less used features such as matrix + interpolation/decomposition. + + Not all features of the previous polyfill have been ported to the + new codebase; most notably mutation of Animations and Groups and + Additive Animations are not yet supported. These features are still + important and will be implemented in the coming weeks. diff --git a/scripts/vendor/web-animations-js/README.md b/scripts/vendor/web-animations-js/README.md new file mode 100755 index 0000000000..e3e7d53adc --- /dev/null +++ b/scripts/vendor/web-animations-js/README.md @@ -0,0 +1,161 @@ + +Quick Start +----------- + +To provide native Chrome Web Animation features (`Element.animate` and Playback +Control) in other browsers, use `web-animations.min.js`. To explore all of the +proposed Web Animations API, use `web-animations-next.min.js`. + +What is Web Animations? +----------------------- + +Web Animations is a new JavaScript API for driving animated content on the web. +By unifying the animation features of SVG and CSS, Web Animations unlocks +features previously only usable declaratively, and exposes powerful, +high-performance animation capabilities to developers. + +For more details see the +[W3C specification](http://w3c.github.io/web-animations/). + +What is the polyfill? +--------------------- + +The polyfill is a JavaScript implementation of the Web Animations API. It works +on modern versions of all major browsers. For more details about browser +support see . + +Getting Started +--------------- + +Here's a simple example of an animation that scales and changes the opacity of +a `
` over 0.5 seconds. The animation alternates producing a pulsing +effect. + + +
Hello world!
+ + +Web Animations supports off-main-thread animations, and also allows procedural +generation of animations and fine-grained control of animation playback. See + for ideas and inspiration! + +Native Fallback +--------------- + +When the polyfill runs on a browser that implements `Element.animate` and +`Animation` Playback Control it will detect and use the underlying native +features. + +Different Build Targets +----------------------- + +### web-animations.min.js + +Tracks the Web Animations features that are supported natively in browsers. +Today that means Element.animate and Playback Control in Chrome. If you’re not +sure what features you will need, start with this. + +### web-animations-next.min.js + +Contains all of web-animations.min.js plus features that are still undergoing +discussion or have yet to be implemented natively. + +### web-animations-next-lite.min.js + +A cut down version of web-animations-next, it removes several lesser used +property handlers and some of the larger and less used features such as matrix +interpolation/decomposition. + +### Build Target Comparison + +| | web-animations | web-animations-next | web-animations-next-lite | +|------------------------|:--------------:|:-------------------:|:------------------------:| +|Size (gzipped) | 12.5kb | 14kb | 10.5kb | +|Element.animate | ✔ | ✔ | ✔ | +|Timing input (easings, duration, fillMode, etc.) for animation effects| ✔ | ✔ | ✔ | +|Playback control | ✔ | ✔ | ✔ | +|Support for animating lengths, transforms and opacity| ✔ | ✔ | ✔ | +|Support for animating other CSS properties| ✔ | ✔ | 🚫 | +|Matrix fallback for transform animations | ✔ | ✔ | 🚫 | +|KeyframeEffect constructor | 🚫 | ✔ | ✔ | +|Simple GroupEffects & SequenceEffects | 🚫 | ✔ | ✔ | +|Custom Effects | 🚫 | ✔ | ✔ | +|Timing input (easings, duration, fillMode, etc.) for groups
| 🚫 | 🚫\* | 🚫 | +|Additive animation | 🚫 | 🚫\* | 🚫 | +|Motion path | 🚫\* | 🚫\* | 🚫 | +|Modifiable keyframe effect timing| 🚫 | 🚫\* | 🚫\* | +|Modifiable group timing | 🚫 | 🚫\* | 🚫\* | +|Usable inline style\*\* | ✔ | ✔ | 🚫 | + +\* support is planned for these features. +\*\* see inline style caveat below. + +Caveats +------- + +Some things won’t ever be faithful to the native implementation due to browser +and CSS API limitations. These include: + +### Inline Style + +Inline style modification is the mechanism used by the polyfill to animate +properties. Both web-animations and web-animations-next incorporate a module +that emulates a vanilla inline style object, so that style modification from +JavaScript can still work in the presence of animations. However, to keep the +size of web-animations-next-lite as small as possible, the style emulation +module is not included. When using this version of the polyfill, JavaScript +inline style modification will be overwritten by animations. +Due to browser constraints inline style modification is not supported on iOS 7 +or Safari 6 (or earlier versions). + +### Prefix handling + +The polyfill will automatically detect the correctly prefixed name to use when +writing animated properties back to the platform. Where possible, the polyfill +will only accept unprefixed versions of experimental features. For example: + + var effect = new KeyframeEffect(elem, {"transform": "translate(100px, 100px)"}, 2000); + +will work in all browsers that implement a conforming version of transform, but + + var effect = new KeyframeEffect(elem, {"-webkit-transform": "translate(100px, 100px)"}, 2000); + +will not work anywhere. + +API and Specification Feedback +------------------------------ + +File an issue on GitHub: . +Alternatively, send an email to with subject line +“[web-animations] … message topic …” +([archives](http://lists.w3.org/Archives/Public/public-fx/)). + +Polyfill Issues +--------------- + +Report any issues with this implementation on GitHub: +. + +Breaking changes +---------------- + +When we make a potentially breaking change to the polyfill's API +surface (like a rename) we will, where possible, continue supporting the +old version, deprecated, for three months, and ensure that there are +console warnings to indicate that a change is pending. After three +months, the old version of the API surface (e.g. the old version of a +function name) will be removed. *If you see deprecation warnings you +can't avoid it by not updating*. + +We also announce anything that isn't a bug fix on +[web-animations-changes@googlegroups.com](https://groups.google.com/forum/#!forum/web-animations-changes). diff --git a/scripts/vendor/web-animations-js/bower.json b/scripts/vendor/web-animations-js/bower.json new file mode 100755 index 0000000000..22f26b5e5c --- /dev/null +++ b/scripts/vendor/web-animations-js/bower.json @@ -0,0 +1,31 @@ +{ + "name": "web-animations-js", + "description": "JavaScript implementation of the Web Animations API", + "homepage": "https://github.com/web-animations/web-animations-js", + "main": "web-animations.min.js", + "moduleType": [ + "globals" + ], + "keywords": [ + "animations", + "polyfill" + ], + "license": "Apache-2.0", + "ignore": [ + "**/.*", + "node_modules", + "templates", + "test", + "src", + "Gruntfile.js", + "package.json", + "target-config.js", + "target-loader.js", + "web-animations.dev.html", + "web-animations.dev.js", + "web-animations-next.dev.html", + "web-animations-next.dev.js", + "web-animations-next-lite.dev.html", + "web-animations-next-lite.dev.js" + ] +} diff --git a/scripts/vendor/web-animations-js/package.json b/scripts/vendor/web-animations-js/package.json new file mode 100755 index 0000000000..b579b79d6c --- /dev/null +++ b/scripts/vendor/web-animations-js/package.json @@ -0,0 +1,33 @@ +{ + "name": "web-animations-js", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/web-animations/web-animations-js.git" + }, + "devDependencies": { + "mocha": "1.21.4", + "chai": "^1.9.1", + "grunt": "~0.4.5", + "grunt-contrib-uglify": "^0.4.0", + "grunt-gjslint": "^0.1.4", + "grunt-karma": "^0.8.2", + "karma": "^0.12.14", + "karma-mocha": "^0.1.3", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "~0.1.4", + "karma-firefox-launcher": "~0.1.3", + "karma-ie-launcher": "~0.1.5", + "karma-safari-launcher": "~0.1.1", + "karma-sauce-launcher": "~0.2.3", + "grunt-checkrepo": "~0.1.0", + "grunt-saucelabs": "~4.0.2", + "grunt-checkrepo": "~0.1.0", + "grunt-git-status": "~1.0.0", + "grunt-template": "~0.2.3", + "source-map": "~0.1.40" + }, + "scripts": { + "test": "grunt test gjslint git-status checkrepo" + } +} diff --git a/scripts/vendor/web-animations-js/src/animation.js b/scripts/vendor/web-animations-js/src/animation.js new file mode 100755 index 0000000000..ecc77d7062 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/animation.js @@ -0,0 +1,215 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var sequenceNumber = 0; + + var AnimationEvent = function(target, currentTime, timelineTime) { + this.target = target; + this.currentTime = currentTime; + this.timelineTime = timelineTime; + + this.type = 'finish'; + this.bubbles = false; + this.cancelable = false; + this.currentTarget = target; + this.defaultPrevented = false; + this.eventPhase = Event.AT_TARGET; + this.timeStamp = Date.now(); + }; + + scope.Animation = function(effect) { + this._sequenceNumber = sequenceNumber++; + this._currentTime = 0; + this._startTime = null; + this.paused = false; + this._playbackRate = 1; + this._inTimeline = true; + this._finishedFlag = false; + this.onfinish = null; + this._finishHandlers = []; + this._effect = effect; + this._inEffect = this._effect._update(0); + this._idle = true; + this._currentTimePending = false; + }; + + scope.Animation.prototype = { + _ensureAlive: function() { + // If an animation is playing backwards and is not fill backwards/both + // then it should go out of effect when it reaches the start of its + // active interval (currentTime == 0). + if (this.playbackRate < 0 && this.currentTime === 0) { + this._inEffect = this._effect._update(-1); + } else { + this._inEffect = this._effect._update(this.currentTime); + } + if (!this._inTimeline && (this._inEffect || !this._finishedFlag)) { + this._inTimeline = true; + scope.timeline._animations.push(this); + } + }, + _tickCurrentTime: function(newTime, ignoreLimit) { + if (newTime != this._currentTime) { + this._currentTime = newTime; + if (this.finished && !ignoreLimit) + this._currentTime = this._playbackRate > 0 ? this._totalDuration : 0; + this._ensureAlive(); + } + }, + get currentTime() { + if (this._idle || this._currentTimePending) + return null; + return this._currentTime; + }, + set currentTime(newTime) { + newTime = +newTime; + if (isNaN(newTime)) + return; + scope.restart(); + if (!this.paused && this._startTime != null) { + this._startTime = this._timeline.currentTime - newTime / this._playbackRate; + } + this._currentTimePending = false; + if (this._currentTime == newTime) + return; + this._tickCurrentTime(newTime, true); + scope.invalidateEffects(); + }, + get startTime() { + return this._startTime; + }, + set startTime(newTime) { + newTime = +newTime; + if (isNaN(newTime)) + return; + if (this.paused || this._idle) + return; + this._startTime = newTime; + this._tickCurrentTime((this._timeline.currentTime - this._startTime) * this.playbackRate); + scope.invalidateEffects(); + }, + get playbackRate() { + return this._playbackRate; + }, + set playbackRate(value) { + if (value == this._playbackRate) { + return; + } + var oldCurrentTime = this.currentTime; + this._playbackRate = value; + this._startTime = null; + if (this.playState != 'paused' && this.playState != 'idle') { + this.play(); + } + if (oldCurrentTime != null) { + this.currentTime = oldCurrentTime; + } + }, + get finished() { + return !this._idle && (this._playbackRate > 0 && this._currentTime >= this._totalDuration || + this._playbackRate < 0 && this._currentTime <= 0); + }, + get _totalDuration() { return this._effect._totalDuration; }, + get playState() { + if (this._idle) + return 'idle'; + if ((this._startTime == null && !this.paused && this.playbackRate != 0) || this._currentTimePending) + return 'pending'; + if (this.paused) + return 'paused'; + if (this.finished) + return 'finished'; + return 'running'; + }, + play: function() { + this.paused = false; + if (this.finished || this._idle) { + this._currentTime = this._playbackRate > 0 ? 0 : this._totalDuration; + this._startTime = null; + scope.invalidateEffects(); + } + this._finishedFlag = false; + scope.restart(); + this._idle = false; + this._ensureAlive(); + }, + pause: function() { + if (!this.finished && !this.paused && !this._idle) { + this._currentTimePending = true; + } + this._startTime = null; + this.paused = true; + }, + finish: function() { + if (this._idle) + return; + this.currentTime = this._playbackRate > 0 ? this._totalDuration : 0; + this._startTime = this._totalDuration - this.currentTime; + this._currentTimePending = false; + }, + cancel: function() { + this._inEffect = false; + this._idle = true; + this.currentTime = 0; + this._startTime = null; + }, + reverse: function() { + this.playbackRate *= -1; + this.play(); + }, + addEventListener: function(type, handler) { + if (typeof handler == 'function' && type == 'finish') + this._finishHandlers.push(handler); + }, + removeEventListener: function(type, handler) { + if (type != 'finish') + return; + var index = this._finishHandlers.indexOf(handler); + if (index >= 0) + this._finishHandlers.splice(index, 1); + }, + _fireEvents: function(baseTime) { + var finished = this.finished; + if ((finished || this._idle) && !this._finishedFlag) { + var event = new AnimationEvent(this, this._currentTime, baseTime); + var handlers = this._finishHandlers.concat(this.onfinish ? [this.onfinish] : []); + setTimeout(function() { + handlers.forEach(function(handler) { + handler.call(event.target, event); + }); + }, 0); + } + this._finishedFlag = finished; + }, + _tick: function(timelineTime) { + if (!this._idle && !this.paused) { + if (this._startTime == null) + this.startTime = timelineTime - this._currentTime / this.playbackRate; + else if (!this.finished) + this._tickCurrentTime((timelineTime - this._startTime) * this.playbackRate); + } + + this._currentTimePending = false; + this._fireEvents(timelineTime); + return !this._idle && (this._inEffect || !this._finishedFlag); + }, + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimations1Animation = scope.Animation; + } + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/apply-preserving-inline-style.js b/scripts/vendor/web-animations-js/src/apply-preserving-inline-style.js new file mode 100755 index 0000000000..795be36452 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/apply-preserving-inline-style.js @@ -0,0 +1,191 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var styleAttributes = { + cssText: 1, + length: 1, + parentRule: 1, + }; + + var styleMethods = { + getPropertyCSSValue: 1, + getPropertyPriority: 1, + getPropertyValue: 1, + item: 1, + removeProperty: 1, + setProperty: 1, + }; + + var styleMutatingMethods = { + removeProperty: 1, + setProperty: 1, + }; + + function configureProperty(object, property, descriptor) { + descriptor.enumerable = true; + descriptor.configurable = true; + Object.defineProperty(object, property, descriptor); + } + + function AnimatedCSSStyleDeclaration(element) { + WEB_ANIMATIONS_TESTING && console.assert(!(element.style instanceof AnimatedCSSStyleDeclaration), + 'Element must not already have an animated style attached.'); + + // Stores the inline style of the element on its behalf while the + // polyfill uses the element's inline style to simulate web animations. + // This is needed to fake regular inline style CSSOM access on the element. + this._surrogateStyle = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style; + this._style = element.style; + this._length = 0; + this._isAnimatedProperty = {}; + + // Copy the inline style contents over to the surrogate. + for (var i = 0; i < this._style.length; i++) { + var property = this._style[i]; + this._surrogateStyle[property] = this._style[property]; + } + this._updateIndices(); + } + + AnimatedCSSStyleDeclaration.prototype = { + get cssText() { + return this._surrogateStyle.cssText; + }, + set cssText(text) { + var isAffectedProperty = {}; + for (var i = 0; i < this._surrogateStyle.length; i++) { + isAffectedProperty[this._surrogateStyle[i]] = true; + } + this._surrogateStyle.cssText = text; + this._updateIndices(); + for (var i = 0; i < this._surrogateStyle.length; i++) { + isAffectedProperty[this._surrogateStyle[i]] = true; + } + for (var property in isAffectedProperty) { + if (!this._isAnimatedProperty[property]) { + this._style.setProperty(property, this._surrogateStyle.getPropertyValue(property)); + } + } + }, + get length() { + return this._surrogateStyle.length; + }, + get parentRule() { + return this._style.parentRule; + }, + // Mirror the indexed getters and setters of the surrogate style. + _updateIndices: function() { + while (this._length < this._surrogateStyle.length) { + Object.defineProperty(this, this._length, { + configurable: true, + enumerable: false, + get: (function(index) { + return function() { return this._surrogateStyle[index]; }; + })(this._length) + }); + this._length++; + } + while (this._length > this._surrogateStyle.length) { + this._length--; + Object.defineProperty(this, this._length, { + configurable: true, + enumerable: false, + value: undefined + }); + } + }, + _set: function(property, value) { + this._style[property] = value; + this._isAnimatedProperty[property] = true; + }, + _clear: function(property) { + this._style[property] = this._surrogateStyle[property]; + delete this._isAnimatedProperty[property]; + }, + }; + + // Wrap the style methods. + for (var method in styleMethods) { + AnimatedCSSStyleDeclaration.prototype[method] = (function(method, modifiesStyle) { + return function() { + var result = this._surrogateStyle[method].apply(this._surrogateStyle, arguments); + if (modifiesStyle) { + if (!this._isAnimatedProperty[arguments[0]]) + this._style[method].apply(this._style, arguments); + this._updateIndices(); + } + return result; + } + })(method, method in styleMutatingMethods); + } + + // Wrap the style.cssProperty getters and setters. + for (var property in document.documentElement.style) { + if (property in styleAttributes || property in styleMethods) { + continue; + } + (function(property) { + configureProperty(AnimatedCSSStyleDeclaration.prototype, property, { + get: function() { + return this._surrogateStyle[property]; + }, + set: function(value) { + this._surrogateStyle[property] = value; + this._updateIndices(); + if (!this._isAnimatedProperty[property]) + this._style[property] = value; + } + }); + })(property); + } + + function ensureStyleIsPatched(element) { + if (element._webAnimationsPatchedStyle) + return; + + var animatedStyle = new AnimatedCSSStyleDeclaration(element); + try { + configureProperty(element, 'style', { get: function() { return animatedStyle; } }); + } catch (_) { + // iOS and older versions of Safari (pre v7) do not support overriding an element's + // style object. Animations will clobber any inline styles as a result. + element.style._set = function(property, value) { + element.style[property] = value; + }; + element.style._clear = function(property) { + element.style[property] = ''; + }; + } + + // We must keep a handle on the patched style to prevent it from getting GC'd. + element._webAnimationsPatchedStyle = element.style; + } + + scope.apply = function(element, property, value) { + ensureStyleIsPatched(element); + element.style._set(scope.propertyName(property), value); + }; + + scope.clear = function(element, property) { + if (element._webAnimationsPatchedStyle) { + element.style._clear(scope.propertyName(property)); + } + }; + + if (WEB_ANIMATIONS_TESTING) + testing.ensureStyleIsPatched = ensureStyleIsPatched; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/apply.js b/scripts/vendor/web-animations-js/src/apply.js new file mode 100755 index 0000000000..3200f967ea --- /dev/null +++ b/scripts/vendor/web-animations-js/src/apply.js @@ -0,0 +1,25 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + scope.apply = function(element, property, value) { + element.style[scope.propertyName(property)] = value; + }; + + scope.clear = function(element, property) { + element.style[scope.propertyName(property)] = ''; + }; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/box-handler.js b/scripts/vendor/web-animations-js/src/box-handler.js new file mode 100755 index 0000000000..3399263a48 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/box-handler.js @@ -0,0 +1,57 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + function consumeLengthPercentOrAuto(string) { + return scope.consumeLengthOrPercent(string) || scope.consumeToken(/^auto/, string); + } + function parseBox(string) { + var result = scope.consumeList([ + scope.ignore(scope.consumeToken.bind(null, /^rect/)), + scope.ignore(scope.consumeToken.bind(null, /^\(/)), + scope.consumeRepeated.bind(null, consumeLengthPercentOrAuto, /^,/), + scope.ignore(scope.consumeToken.bind(null, /^\)/)), + ], string); + if (result && result[0].length == 4) { + return result[0]; + } + } + + function mergeComponent(left, right) { + if (left == 'auto' || right == 'auto') { + return [true, false, function(t) { + var result = t ? left : right; + if (result == 'auto') { + return 'auto'; + } + // FIXME: There's probably a better way to turn a dimension back into a string. + var merged = scope.mergeDimensions(result, result); + return merged[2](merged[0]); + }]; + } + return scope.mergeDimensions(left, right); + } + + function wrap(result) { + return 'rect(' + result + ')'; + } + + var mergeBoxes = scope.mergeWrappedNestedRepeated.bind(null, wrap, mergeComponent, ', '); + + scope.parseBox = parseBox; + scope.mergeBoxes = mergeBoxes; + + scope.addPropertiesHandler(parseBox, mergeBoxes, ['clip']); + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/color-handler.js b/scripts/vendor/web-animations-js/src/color-handler.js new file mode 100755 index 0000000000..b32a889962 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/color-handler.js @@ -0,0 +1,62 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas'); + canvas.width = canvas.height = 1; + var context = canvas.getContext('2d'); + + function parseColor(string) { + string = string.trim(); + // The context ignores invalid colors + context.fillStyle = '#000'; + context.fillStyle = string; + var contextSerializedFillStyle = context.fillStyle; + context.fillStyle = '#fff'; + context.fillStyle = string; + if (contextSerializedFillStyle != context.fillStyle) + return; + context.fillRect(0, 0, 1, 1); + var pixelColor = context.getImageData(0, 0, 1, 1).data; + context.clearRect(0, 0, 1, 1); + var alpha = pixelColor[3] / 255; + return [pixelColor[0] * alpha, pixelColor[1] * alpha, pixelColor[2] * alpha, alpha]; + } + + function mergeColors(left, right) { + return [left, right, function(x) { + function clamp(v) { + return Math.max(0, Math.min(255, v)); + } + if (x[3]) { + for (var i = 0; i < 3; i++) + x[i] = Math.round(clamp(x[i] / x[3])); + } + x[3] = scope.numberToString(scope.clamp(0, 1, x[3])); + return 'rgba(' + x.join(',') + ')'; + }]; + } + + scope.addPropertiesHandler(parseColor, mergeColors, + ['background-color', 'border-bottom-color', 'border-left-color', 'border-right-color', + 'border-top-color', 'color', 'outline-color', 'text-decoration-color']); + scope.consumeColor = scope.consumeParenthesised.bind(null, parseColor); + scope.mergeColors = mergeColors; + + if (WEB_ANIMATIONS_TESTING) { + testing.parseColor = parseColor; + } + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/deprecation.js b/scripts/vendor/web-animations-js/src/deprecation.js new file mode 100755 index 0000000000..3349937987 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/deprecation.js @@ -0,0 +1,43 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared) { + + var silenced = {}; + + shared.isDeprecated = function(feature, date, advice, plural) { + var auxVerb = plural ? 'are' : 'is'; + var today = new Date(); + var expiry = new Date(date); + expiry.setMonth(expiry.getMonth() + 3); // 3 months grace period + + if (today < expiry) { + if (!(feature in silenced)) { + console.warn('Web Animations: ' + feature + ' ' + auxVerb + ' deprecated and will stop working on ' + expiry.toDateString() + '. ' + advice); + } + silenced[feature] = true; + return false; + } else { + return true; + } + }; + + shared.deprecated = function(feature, date, advice, plural) { + var auxVerb = plural ? 'are' : 'is'; + if (shared.isDeprecated(feature, date, advice, plural)) { + throw new Error(feature + ' ' + auxVerb + ' no longer supported. ' + advice); + } + }; + +})(webAnimationsShared); diff --git a/scripts/vendor/web-animations-js/src/dev.js b/scripts/vendor/web-animations-js/src/dev.js new file mode 100755 index 0000000000..a5e225c08c --- /dev/null +++ b/scripts/vendor/web-animations-js/src/dev.js @@ -0,0 +1,16 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var WEB_ANIMATIONS_TESTING = false; +var webAnimationsTesting = null; diff --git a/scripts/vendor/web-animations-js/src/dimension-handler.js b/scripts/vendor/web-animations-js/src/dimension-handler.js new file mode 100755 index 0000000000..66afe0d2e2 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/dimension-handler.js @@ -0,0 +1,167 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function parseDimension(unitRegExp, string) { + string = string.trim().toLowerCase(); + + if (string == '0' && 'px'.search(unitRegExp) >= 0) + return {px: 0}; + + // If we have parenthesis, we're a calc and need to start with 'calc'. + if (!/^[^(]*$|^calc/.test(string)) + return; + string = string.replace(/calc\(/g, '('); + + // We tag units by prefixing them with 'U' (note that we are already + // lowercase) to prevent problems with types which are substrings of + // each other (although prefixes may be problematic!) + var matchedUnits = {}; + string = string.replace(unitRegExp, function(match) { + matchedUnits[match] = null; + return 'U' + match; + }); + var taggedUnitRegExp = 'U(' + unitRegExp.source + ')'; + + // Validating input is simply applying as many reductions as we can. + var typeCheck = string.replace(/[-+]?(\d*\.)?\d+/g, 'N') + .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D') + .replace(/\s[+-]\s/g, 'O') + .replace(/\s/g, ''); + var reductions = [/N\*(D)/g, /(N|D)[*/]N/g, /(N|D)O\1/g, /\((N|D)\)/g]; + var i = 0; + while (i < reductions.length) { + if (reductions[i].test(typeCheck)) { + typeCheck = typeCheck.replace(reductions[i], '$1'); + i = 0; + } else { + i++; + } + } + if (typeCheck != 'D') + return; + + for (var unit in matchedUnits) { + var result = eval(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0')); + if (!isFinite(result)) + return; + matchedUnits[unit] = result; + } + return matchedUnits; + } + + function mergeDimensionsNonNegative(left, right) { + return mergeDimensions(left, right, true); + } + + function mergeDimensions(left, right, nonNegative) { + var units = [], unit; + for (unit in left) + units.push(unit); + for (unit in right) { + if (units.indexOf(unit) < 0) + units.push(unit); + } + + left = units.map(function(unit) { return left[unit] || 0; }); + right = units.map(function(unit) { return right[unit] || 0; }); + return [left, right, function(values) { + var result = values.map(function(value, i) { + if (values.length == 1 && nonNegative) { + value = Math.max(value, 0); + } + // Scientific notation (e.g. 1e2) is not yet widely supported by browser vendors. + return scope.numberToString(value) + units[i]; + }).join(' + '); + return values.length > 1 ? 'calc(' + result + ')' : result; + }]; + } + + var lengthUnits = 'px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc'; + var parseLength = parseDimension.bind(null, new RegExp(lengthUnits, 'g')); + var parseLengthOrPercent = parseDimension.bind(null, new RegExp(lengthUnits + '|%', 'g')); + var parseAngle = parseDimension.bind(null, /deg|rad|grad|turn/g); + + scope.parseLength = parseLength; + scope.parseLengthOrPercent = parseLengthOrPercent; + scope.consumeLengthOrPercent = scope.consumeParenthesised.bind(null, parseLengthOrPercent); + scope.parseAngle = parseAngle; + scope.mergeDimensions = mergeDimensions; + + var consumeLength = scope.consumeParenthesised.bind(null, parseLength); + var consumeSizePair = scope.consumeRepeated.bind(undefined, consumeLength, /^/); + var consumeSizePairList = scope.consumeRepeated.bind(undefined, consumeSizePair, /^,/); + scope.consumeSizePairList = consumeSizePairList; + + var parseSizePairList = function(input) { + var result = consumeSizePairList(input); + if (result && result[1] == '') { + return result[0]; + } + }; + + var mergeNonNegativeSizePair = scope.mergeNestedRepeated.bind(undefined, mergeDimensionsNonNegative, ' '); + var mergeNonNegativeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeNonNegativeSizePair, ','); + scope.mergeNonNegativeSizePair = mergeNonNegativeSizePair; + + scope.addPropertiesHandler(parseSizePairList, mergeNonNegativeSizePairList, [ + 'background-size' + ]); + + scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensionsNonNegative, [ + 'border-bottom-width', + 'border-image-width', + 'border-left-width', + 'border-right-width', + 'border-top-width', + 'flex-basis', + 'font-size', + 'height', + 'line-height', + 'max-height', + 'max-width', + 'outline-width', + 'width', + ]); + + scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensions, [ + 'border-bottom-left-radius', + 'border-bottom-right-radius', + 'border-top-left-radius', + 'border-top-right-radius', + 'bottom', + 'left', + 'letter-spacing', + 'margin-bottom', + 'margin-left', + 'margin-right', + 'margin-top', + 'min-height', + 'min-width', + 'outline-offset', + 'padding-bottom', + 'padding-left', + 'padding-right', + 'padding-top', + 'perspective', + 'right', + 'shape-margin', + 'text-indent', + 'top', + 'vertical-align', + 'word-spacing', + ]); + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/effect-callback.js b/scripts/vendor/web-animations-js/src/effect-callback.js new file mode 100755 index 0000000000..e187241eab --- /dev/null +++ b/scripts/vendor/web-animations-js/src/effect-callback.js @@ -0,0 +1,87 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +(function(shared, scope, testing) { + + var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + + var sequenceNumber = 0; + scope.bindAnimationForCustomEffect = function(animation) { + var target = animation.effect.target; + var effectFunction = animation.effect._normalizedKeyframes; + var timing = animation.effect.timing; + var last = null; + timing = shared.normalizeTimingInput(timing); + var callback = function() { + var t = callback._animation ? callback._animation.currentTime : null; + if (t !== null) { + t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + if (isNaN(t)) + t = null; + } + // FIXME: There are actually more conditions under which the effectFunction + // should be called. + if (t !== last) + effectFunction(t, target, animation.effect); + last = t; + }; + + callback._animation = animation; + callback._registered = false; + callback._sequenceNumber = sequenceNumber++; + animation._callback = callback; + register(callback); + }; + + var callbacks = []; + var ticking = false; + function register(callback) { + if (callback._registered) + return; + callback._registered = true; + callbacks.push(callback); + if (!ticking) { + ticking = true; + requestAnimationFrame(tick); + } + } + + function tick(t) { + var updating = callbacks; + callbacks = []; + updating.sort(function(left, right) { + return left._sequenceNumber - right._sequenceNumber; + }); + updating = updating.filter(function(callback) { + callback(); + var playState = callback._animation ? callback._animation.playState : 'idle'; + if (playState != 'running' && playState != 'pending') + callback._registered = false; + return callback._registered; + }); + callbacks.push.apply(callbacks, updating); + + if (callbacks.length) { + ticking = true; + requestAnimationFrame(tick); + } else { + ticking = false; + } + } + + scope.Animation.prototype._register = function() { + if (this._callback) + register(this._callback); + }; + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/element-animatable.js b/scripts/vendor/web-animations-js/src/element-animatable.js new file mode 100755 index 0000000000..6bcf1dce7a --- /dev/null +++ b/scripts/vendor/web-animations-js/src/element-animatable.js @@ -0,0 +1,19 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + window.Element.prototype.animate = function(effectInput, timingInput) { + return scope.timeline._play(scope.KeyframeEffect(this, effectInput, timingInput)); + }; +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/font-weight-handler.js b/scripts/vendor/web-animations-js/src/font-weight-handler.js new file mode 100755 index 0000000000..4760486a66 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/font-weight-handler.js @@ -0,0 +1,42 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + function parse(string) { + var out = Number(string); + if (isNaN(out) || out < 100 || out > 900 || out % 100 !== 0) { + return; + } + return out; + } + + function toCss(value) { + value = Math.round(value / 100) * 100; + value = scope.clamp(100, 900, value); + if (value === 400) { + return 'normal'; + } + if (value === 700) { + return 'bold'; + } + return String(value); + } + + function merge(left, right) { + return [left, right, toCss]; + } + + scope.addPropertiesHandler(parse, merge, ['font-weight']); + +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/group-constructors.js b/scripts/vendor/web-animations-js/src/group-constructors.js new file mode 100755 index 0000000000..1700dde736 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/group-constructors.js @@ -0,0 +1,124 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + function groupChildDuration(node) { + return node._timing.delay + node.activeDuration + node._timing.endDelay; + } + + function constructor(children, timingInput) { + this.children = children || []; + this._timing = shared.normalizeTimingInput(timingInput, true); + this.timing = shared.makeTiming(timingInput, true); + + if (this._timing.duration === 'auto') + this._timing.duration = this.activeDuration; + } + + window.SequenceEffect = function() { + constructor.apply(this, arguments); + }; + + window.GroupEffect = function() { + constructor.apply(this, arguments); + }; + + window.SequenceEffect.prototype = { + get activeDuration() { + var total = 0; + this.children.forEach(function(child) { + total += groupChildDuration(child); + }); + return Math.max(total, 0); + } + }; + + window.GroupEffect.prototype = { + get activeDuration() { + var max = 0; + this.children.forEach(function(child) { + max = Math.max(max, groupChildDuration(child)); + }); + return max; + } + }; + + scope.newUnderlyingAnimationForGroup = function(group) { + var underlyingAnimation; + var timing = null; + var ticker = function(tf) { + var animation = underlyingAnimation._wrapper; + if (animation.playState == 'pending') + return; + + if (!animation.effect) + return; + + if (tf == null) { + animation._removeChildren(); + return; + } + + // If the group has a negative playback rate and is not fill backwards/both, then it should go + // out of effect when it reaches the start of its active interval (tf == 0). If it is fill + // backwards/both then it should stay in effect. calculateTimeFraction will return 0 in the + // backwards-filling case, and null otherwise. + if (tf == 0 && animation.playbackRate < 0) { + if (!timing) { + timing = shared.normalizeTimingInput(animation.effect.timing); + } + tf = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), -1, timing); + if (isNaN(tf) || tf == null) { + animation._forEachChild(function(child) { + child.currentTime = -1; + }); + animation._removeChildren(); + return; + } + } + }; + + underlyingAnimation = scope.timeline.play(new scope.KeyframeEffect(null, ticker, group._timing)); + return underlyingAnimation; + }; + + scope.bindAnimationForGroup = function(animation) { + animation._animation._wrapper = animation; + animation._isGroup = true; + scope.awaitStartTime(animation); + animation._constructChildren(); + animation._setExternalAnimation(animation); + }; + + scope.groupChildDuration = groupChildDuration; + + // Alias GroupEffect & SequenceEffect to AnimationGroup & AnimationSequence respectively, to + // support old constructors (Animation*) for a deprecation period. Should be removed after 23 June + // 2015. + window.AnimationSequence = function() { + shared.deprecated('window.AnimationSequence', '2015-03-23', 'Use window.SequenceEffect instead.'); + window.SequenceEffect.apply(this, arguments); + }; + window.AnimationSequence.prototype = Object.create(window.SequenceEffect.prototype); + window.AnimationSequence.prototype.constructor = window.AnimationSequence; + + window.AnimationGroup = function() { + shared.deprecated('window.AnimationGroup', '2015-03-23', 'Use window.GroupEffect instead.'); + window.GroupEffect.apply(this, arguments); + }; + window.AnimationGroup.prototype = Object.create(window.GroupEffect.prototype); + window.AnimationGroup.prototype.constructor = window.AnimationGroup; + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/handler-utils.js b/scripts/vendor/web-animations-js/src/handler-utils.js new file mode 100755 index 0000000000..d9f05e17e9 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/handler-utils.js @@ -0,0 +1,177 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + // consume* functions return a 2 value array of [parsed-data, '' or not-yet consumed input] + + // Regex should be anchored with /^ + function consumeToken(regex, string) { + var result = regex.exec(string); + if (result) { + result = regex.ignoreCase ? result[0].toLowerCase() : result[0]; + return [result, string.substr(result.length)]; + } + } + + function consumeTrimmed(consumer, string) { + string = string.replace(/^\s*/, ''); + var result = consumer(string); + if (result) { + return [result[0], result[1].replace(/^\s*/, '')]; + } + } + + function consumeRepeated(consumer, separator, string) { + consumer = consumeTrimmed.bind(null, consumer); + var list = []; + while (true) { + var result = consumer(string); + if (!result) { + return [list, string]; + } + list.push(result[0]); + string = result[1]; + result = consumeToken(separator, string); + if (!result || result[1] == '') { + return [list, string]; + } + string = result[1]; + } + } + + // Consumes a token or expression with balanced parentheses + function consumeParenthesised(parser, string) { + var nesting = 0; + for (var n = 0; n < string.length; n++) { + if (/\s|,/.test(string[n]) && nesting == 0) { + break; + } else if (string[n] == '(') { + nesting++; + } else if (string[n] == ')') { + nesting--; + if (nesting == 0) + n++; + if (nesting <= 0) + break; + } + } + var parsed = parser(string.substr(0, n)); + return parsed == undefined ? undefined : [parsed, string.substr(n)]; + } + + function lcm(a, b) { + var c = a; + var d = b; + while (c && d) + c > d ? c %= d : d %= c; + c = (a * b) / (c + d); + return c; + } + + function ignore(value) { + return function(input) { + var result = value(input); + if (result) + result[0] = undefined; + return result; + } + } + + function optional(value, defaultValue) { + return function(input) { + var result = value(input); + if (result) + return result; + return [defaultValue, input]; + } + } + + function consumeList(list, input) { + var output = []; + for (var i = 0; i < list.length; i++) { + var result = scope.consumeTrimmed(list[i], input); + if (!result || result[0] == '') + return; + if (result[0] !== undefined) + output.push(result[0]); + input = result[1]; + } + if (input == '') { + return output; + } + } + + function mergeWrappedNestedRepeated(wrap, nestedMerge, separator, left, right) { + var matchingLeft = []; + var matchingRight = []; + var reconsititution = []; + var length = lcm(left.length, right.length); + for (var i = 0; i < length; i++) { + var thing = nestedMerge(left[i % left.length], right[i % right.length]); + if (!thing) { + return; + } + matchingLeft.push(thing[0]); + matchingRight.push(thing[1]); + reconsititution.push(thing[2]); + } + return [matchingLeft, matchingRight, function(positions) { + var result = positions.map(function(position, i) { + return reconsititution[i](position); + }).join(separator); + return wrap ? wrap(result) : result; + }]; + } + + function mergeList(left, right, list) { + var lefts = []; + var rights = []; + var functions = []; + var j = 0; + for (var i = 0; i < list.length; i++) { + if (typeof list[i] == 'function') { + var result = list[i](left[j], right[j++]); + lefts.push(result[0]); + rights.push(result[1]); + functions.push(result[2]); + } else { + (function(pos) { + lefts.push(false); + rights.push(false); + functions.push(function() { return list[pos]; }); + })(i); + } + } + return [lefts, rights, function(results) { + var result = ''; + for (var i = 0; i < results.length; i++) { + result += functions[i](results[i]); + } + return result; + }]; + } + + scope.consumeToken = consumeToken; + scope.consumeTrimmed = consumeTrimmed; + scope.consumeRepeated = consumeRepeated; + scope.consumeParenthesised = consumeParenthesised; + scope.ignore = ignore; + scope.optional = optional; + scope.consumeList = consumeList; + scope.mergeNestedRepeated = mergeWrappedNestedRepeated.bind(null, null); + scope.mergeWrappedNestedRepeated = mergeWrappedNestedRepeated; + scope.mergeList = mergeList; + +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/interpolation.js b/scripts/vendor/web-animations-js/src/interpolation.js new file mode 100755 index 0000000000..ba63ed358f --- /dev/null +++ b/scripts/vendor/web-animations-js/src/interpolation.js @@ -0,0 +1,49 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function interpolate(from, to, f) { + if ((typeof from == 'number') && (typeof to == 'number')) { + return from * (1 - f) + to * f; + } + if ((typeof from == 'boolean') && (typeof to == 'boolean')) { + return f < 0.5 ? from : to; + } + + WEB_ANIMATIONS_TESTING && console.assert( + Array.isArray(from) && Array.isArray(to), + 'If interpolation arguments are not numbers or bools they must be arrays'); + + if (from.length == to.length) { + var r = []; + for (var i = 0; i < from.length; i++) { + r.push(interpolate(from[i], to[i], f)); + } + return r; + } + throw 'Mismatched interpolation arguments ' + from + ':' + to; + } + + scope.Interpolation = function(from, to, convertToString) { + return function(f) { + return convertToString(interpolate(from, to, f)); + } + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.interpolate = interpolate; + } + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/keyframe-effect-constructor.js b/scripts/vendor/web-animations-js/src/keyframe-effect-constructor.js new file mode 100755 index 0000000000..4e37f8ec07 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/keyframe-effect-constructor.js @@ -0,0 +1,137 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + // FIXME: Make this shareable and rename to SharedKeyframeList. + function KeyframeList(effectInput) { + this._frames = shared.normalizeKeyframes(effectInput); + } + + // FIXME: This constructor is also used for custom effects. This won't be the case once custom + // effects are change to callbacks. + scope.KeyframeEffect = function(target, effectInput, timingInput) { + this.target = target; + + // TODO: Store a clone, not the same instance. + this._timingInput = timingInput; + this._timing = shared.normalizeTimingInput(timingInput); + + // TODO: Make modifications to timing update the underlying animation + this.timing = shared.makeTiming(timingInput); + // TODO: Make this a live object - will need to separate normalization of keyframes into a + // shared module. + // FIXME: This is a bit weird. Custom effects will soon be implemented as + // callbacks, and effectInput will no longer be allowed to be a function. + if (typeof effectInput == 'function') + this._normalizedKeyframes = effectInput; + else + this._normalizedKeyframes = new KeyframeList(effectInput); + this._keyframes = effectInput; + this.activeDuration = shared.calculateActiveDuration(this._timing); + return this; + }; + + scope.KeyframeEffect.prototype = { + getFrames: function() { + // FIXME: Once custom effects are switched over to callbacks we can + // always return this._normalizedKeyframes._frames here. + if (typeof this._normalizedKeyframes == 'function') + return this._normalizedKeyframes; + return this._normalizedKeyframes._frames; + }, + get effect() { + shared.deprecated('KeyframeEffect.effect', '2015-03-23', 'Use KeyframeEffect.getFrames() instead.'); + return this._normalizedKeyframes; + } + }; + + var originalElementAnimate = Element.prototype.animate; + Element.prototype.animate = function(effectInput, timing) { + return scope.timeline.play(new scope.KeyframeEffect(this, effectInput, timing)); + }; + + var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + scope.newUnderlyingAnimationForKeyframeEffect = function(keyframeEffect) { + var target = keyframeEffect.target || nullTarget; + var keyframes = keyframeEffect._keyframes; + if (typeof keyframes == 'function') { + keyframes = []; + } + return originalElementAnimate.apply(target, [keyframes, keyframeEffect._timingInput]); + }; + + scope.bindAnimationForKeyframeEffect = function(animation) { + if (animation.effect && typeof animation.effect._normalizedKeyframes == 'function') { + scope.bindAnimationForCustomEffect(animation); + } + }; + + var pendingGroups = []; + scope.awaitStartTime = function(groupAnimation) { + if (groupAnimation.startTime !== null || !groupAnimation._isGroup) + return; + if (pendingGroups.length == 0) { + requestAnimationFrame(updatePendingGroups); + } + pendingGroups.push(groupAnimation); + }; + function updatePendingGroups() { + var updated = false; + while (pendingGroups.length) { + pendingGroups.shift()._updateChildren(); + updated = true; + } + return updated; + } + var originalGetComputedStyle = window.getComputedStyle; + Object.defineProperty(window, 'getComputedStyle', { + configurable: true, + enumerable: true, + value: function() { + var result = originalGetComputedStyle.apply(this, arguments); + if (updatePendingGroups()) + result = originalGetComputedStyle.apply(this, arguments); + return result; + }, + }); + + window.KeyframeEffect = scope.KeyframeEffect; + window.Element.prototype.getAnimations = function() { + return document.timeline.getAnimations().filter(function(animation) { + return animation.effect !== null && animation.effect.target == this; + }.bind(this)); + }; + window.Element.prototype.getAnimationPlayers = function() { + shared.deprecated('Element.getAnimationPlayers', '2015-03-23', 'Use Element.getAnimations instead.'); + return this.getAnimations(); + }; + + // Alias KeyframeEffect to Animation, to support old constructor (Animation) for a deprecation + // period. Should be removed after 23 June 2015. + // + // This is only on window and not on scope, because the constructor that was called + // webAnimationsNext.Player - now called webAnimationsNext.Animation - is already on the scope. + // + // FIXME: Add this to scope & expose the other scope.Animation (nee scope.Player). I.e. both this + // function and the constructor in web-animations-next-animation should be scope.Animation and + // window.Animation until 23 June 2015. + window.Animation = function() { + shared.deprecated('window.Animation', '2015-03-23', 'Use window.KeyframeEffect instead.'); + window.KeyframeEffect.apply(this, arguments); + }; + window.Animation.prototype = Object.create(window.KeyframeEffect.prototype); + window.Animation.prototype.constructor = window.Animation; + +}(webAnimationsShared, webAnimationsNext, webAnimationsTesting)); diff --git a/scripts/vendor/web-animations-js/src/keyframe-effect.js b/scripts/vendor/web-animations-js/src/keyframe-effect.js new file mode 100755 index 0000000000..c910d35e03 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/keyframe-effect.js @@ -0,0 +1,80 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + function EffectTime(timing) { + var timeFraction = 0; + var activeDuration = shared.calculateActiveDuration(timing); + var effectTime = function(localTime) { + return shared.calculateTimeFraction(activeDuration, localTime, timing); + }; + effectTime._totalDuration = timing.delay + activeDuration + timing.endDelay; + effectTime._isCurrent = function(localTime) { + var phase = shared.calculatePhase(activeDuration, localTime, timing); + return phase === PhaseActive || phase === PhaseBefore; + }; + return effectTime; + } + + scope.KeyframeEffect = function(target, effectInput, timingInput) { + var effectTime = EffectTime(shared.normalizeTimingInput(timingInput)); + var interpolations = scope.convertEffectInput(effectInput); + var timeFraction; + var keyframeEffect = function() { + WEB_ANIMATIONS_TESTING && console.assert(typeof timeFraction !== 'undefined'); + interpolations(target, timeFraction); + }; + // Returns whether the keyframeEffect is in effect or not after the timing update. + keyframeEffect._update = function(localTime) { + timeFraction = effectTime(localTime); + return timeFraction !== null; + }; + keyframeEffect._clear = function() { + interpolations(target, null); + }; + keyframeEffect._hasSameTarget = function(otherTarget) { + return target === otherTarget; + }; + keyframeEffect._isCurrent = effectTime._isCurrent; + keyframeEffect._totalDuration = effectTime._totalDuration; + return keyframeEffect; + }; + + scope.NullEffect = function(clear) { + var nullEffect = function() { + if (clear) { + clear(); + clear = null; + } + }; + nullEffect._update = function() { + return null; + }; + nullEffect._totalDuration = 0; + nullEffect._isCurrent = function() { + return false; + }; + nullEffect._hasSameTarget = function() { + return false; + }; + return nullEffect; + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.webAnimations1KeyframeEffect = scope.KeyframeEffect; + testing.effectTime = EffectTime; + } + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/keyframe-interpolations.js b/scripts/vendor/web-animations-js/src/keyframe-interpolations.js new file mode 100755 index 0000000000..cdd6fc2bef --- /dev/null +++ b/scripts/vendor/web-animations-js/src/keyframe-interpolations.js @@ -0,0 +1,110 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + + scope.convertEffectInput = function(effectInput) { + var keyframes = shared.normalizeKeyframes(effectInput); + var propertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups(keyframes); + var interpolations = makeInterpolations(propertySpecificKeyframeGroups); + return function(target, fraction) { + if (fraction != null) { + interpolations.filter(function(interpolation) { + return (fraction <= 0 && interpolation.startTime == 0) || + (fraction >= 1 && interpolation.endTime == 1) || + (fraction >= interpolation.startTime && fraction <= interpolation.endTime); + }).forEach(function(interpolation) { + var offsetFraction = fraction - interpolation.startTime; + var localDuration = interpolation.endTime - interpolation.startTime; + var scaledLocalTime = localDuration == 0 ? 0 : interpolation.easing(offsetFraction / localDuration); + scope.apply(target, interpolation.property, interpolation.interpolation(scaledLocalTime)); + }); + } else { + for (var property in propertySpecificKeyframeGroups) + if (property != 'offset' && property != 'easing' && property != 'composite') + scope.clear(target, property); + } + }; + }; + + + function makePropertySpecificKeyframeGroups(keyframes) { + var propertySpecificKeyframeGroups = {}; + + for (var i = 0; i < keyframes.length; i++) { + for (var member in keyframes[i]) { + if (member != 'offset' && member != 'easing' && member != 'composite') { + var propertySpecificKeyframe = { + offset: keyframes[i].offset, + easing: keyframes[i].easing, + value: keyframes[i][member] + }; + propertySpecificKeyframeGroups[member] = propertySpecificKeyframeGroups[member] || []; + propertySpecificKeyframeGroups[member].push(propertySpecificKeyframe); + } + } + } + + for (var groupName in propertySpecificKeyframeGroups) { + var group = propertySpecificKeyframeGroups[groupName]; + if (group[0].offset != 0 || group[group.length - 1].offset != 1) { + throw { + type: DOMException.NOT_SUPPORTED_ERR, + name: 'NotSupportedError', + message: 'Partial keyframes are not supported' + }; + } + } + return propertySpecificKeyframeGroups; + } + + + function makeInterpolations(propertySpecificKeyframeGroups) { + var interpolations = []; + for (var groupName in propertySpecificKeyframeGroups) { + var group = propertySpecificKeyframeGroups[groupName]; + for (var i = 0; i < group.length - 1; i++) { + var startTime = group[i].offset; + var endTime = group[i + 1].offset; + var startValue = group[i].value; + var endValue = group[i + 1].value; + if (startTime == endTime) { + if (endTime == 1) { + startValue = endValue; + } else { + endValue = startValue; + } + } + interpolations.push({ + startTime: startTime, + endTime: endTime, + easing: group[i].easing, + property: groupName, + interpolation: scope.propertyInterpolation(groupName, startValue, endValue) + }); + } + } + interpolations.sort(function(leftInterpolation, rightInterpolation) { + return leftInterpolation.startTime - rightInterpolation.startTime; + }); + return interpolations; + } + + + if (WEB_ANIMATIONS_TESTING) { + testing.makePropertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups; + testing.makeInterpolations = makeInterpolations; + } + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/matrix-decomposition.js b/scripts/vendor/web-animations-js/src/matrix-decomposition.js new file mode 100755 index 0000000000..c825372e3d --- /dev/null +++ b/scripts/vendor/web-animations-js/src/matrix-decomposition.js @@ -0,0 +1,452 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + var decomposeMatrix = (function() { + function determinant(m) { + return m[0][0] * m[1][1] * m[2][2] + + m[1][0] * m[2][1] * m[0][2] + + m[2][0] * m[0][1] * m[1][2] - + m[0][2] * m[1][1] * m[2][0] - + m[1][2] * m[2][1] * m[0][0] - + m[2][2] * m[0][1] * m[1][0]; + } + + // from Wikipedia: + // + // [A B]^-1 = [A^-1 + A^-1B(D - CA^-1B)^-1CA^-1 -A^-1B(D - CA^-1B)^-1] + // [C D] [-(D - CA^-1B)^-1CA^-1 (D - CA^-1B)^-1 ] + // + // Therefore + // + // [A [0]]^-1 = [A^-1 [0]] + // [C 1 ] [ -CA^-1 1 ] + function inverse(m) { + var iDet = 1 / determinant(m); + var a = m[0][0], b = m[0][1], c = m[0][2]; + var d = m[1][0], e = m[1][1], f = m[1][2]; + var g = m[2][0], h = m[2][1], k = m[2][2]; + var Ainv = [ + [(e * k - f * h) * iDet, (c * h - b * k) * iDet, + (b * f - c * e) * iDet, 0], + [(f * g - d * k) * iDet, (a * k - c * g) * iDet, + (c * d - a * f) * iDet, 0], + [(d * h - e * g) * iDet, (g * b - a * h) * iDet, + (a * e - b * d) * iDet, 0] + ]; + var lastRow = []; + for (var i = 0; i < 3; i++) { + var val = 0; + for (var j = 0; j < 3; j++) { + val += m[3][j] * Ainv[j][i]; + } + lastRow.push(val); + } + lastRow.push(1); + Ainv.push(lastRow); + return Ainv; + } + + function transposeMatrix4(m) { + return [[m[0][0], m[1][0], m[2][0], m[3][0]], + [m[0][1], m[1][1], m[2][1], m[3][1]], + [m[0][2], m[1][2], m[2][2], m[3][2]], + [m[0][3], m[1][3], m[2][3], m[3][3]]]; + } + + function multVecMatrix(v, m) { + var result = []; + for (var i = 0; i < 4; i++) { + var val = 0; + for (var j = 0; j < 4; j++) { + val += v[j] * m[j][i]; + } + result.push(val); + } + return result; + } + + function normalize(v) { + var len = length(v); + return [v[0] / len, v[1] / len, v[2] / len]; + } + + function length(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + } + + function combine(v1, v2, v1s, v2s) { + return [v1s * v1[0] + v2s * v2[0], v1s * v1[1] + v2s * v2[1], + v1s * v1[2] + v2s * v2[2]]; + } + + function cross(v1, v2) { + return [v1[1] * v2[2] - v1[2] * v2[1], + v1[2] * v2[0] - v1[0] * v2[2], + v1[0] * v2[1] - v1[1] * v2[0]]; + } + + // TODO: Implement 2D matrix decomposition. + // http://dev.w3.org/csswg/css-transforms/#decomposing-a-2d-matrix + function decomposeMatrix(matrix) { + var m3d = [ + matrix.slice(0, 4), + matrix.slice(4, 8), + matrix.slice(8, 12), + matrix.slice(12, 16) + ]; + + // skip normalization step as m3d[3][3] should always be 1 + if (m3d[3][3] !== 1) { + return null; + } + + var perspectiveMatrix = []; + for (var i = 0; i < 4; i++) { + perspectiveMatrix.push(m3d[i].slice()); + } + + for (var i = 0; i < 3; i++) { + perspectiveMatrix[i][3] = 0; + } + + if (determinant(perspectiveMatrix) === 0) { + return false; + } + + var rhs = []; + + var perspective; + if (m3d[0][3] || m3d[1][3] || m3d[2][3]) { + rhs.push(m3d[0][3]); + rhs.push(m3d[1][3]); + rhs.push(m3d[2][3]); + rhs.push(m3d[3][3]); + + var inversePerspectiveMatrix = inverse(perspectiveMatrix); + var transposedInversePerspectiveMatrix = + transposeMatrix4(inversePerspectiveMatrix); + perspective = multVecMatrix(rhs, transposedInversePerspectiveMatrix); + } else { + perspective = [0, 0, 0, 1]; + } + + var translate = m3d[3].slice(0, 3); + + var row = []; + row.push(m3d[0].slice(0, 3)); + var scale = []; + scale.push(length(row[0])); + row[0] = normalize(row[0]); + + var skew = []; + row.push(m3d[1].slice(0, 3)); + skew.push(dot(row[0], row[1])); + row[1] = combine(row[1], row[0], 1.0, -skew[0]); + + scale.push(length(row[1])); + row[1] = normalize(row[1]); + skew[0] /= scale[1]; + + row.push(m3d[2].slice(0, 3)); + skew.push(dot(row[0], row[2])); + row[2] = combine(row[2], row[0], 1.0, -skew[1]); + skew.push(dot(row[1], row[2])); + row[2] = combine(row[2], row[1], 1.0, -skew[2]); + + scale.push(length(row[2])); + row[2] = normalize(row[2]); + skew[1] /= scale[2]; + skew[2] /= scale[2]; + + var pdum3 = cross(row[1], row[2]); + if (dot(row[0], pdum3) < 0) { + for (var i = 0; i < 3; i++) { + scale[i] *= -1; + row[i][0] *= -1; + row[i][1] *= -1; + row[i][2] *= -1; + } + } + + var t = row[0][0] + row[1][1] + row[2][2] + 1; + var s; + var quaternion; + + if (t > 1e-4) { + s = 0.5 / Math.sqrt(t); + quaternion = [ + (row[2][1] - row[1][2]) * s, + (row[0][2] - row[2][0]) * s, + (row[1][0] - row[0][1]) * s, + 0.25 / s + ]; + } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { + s = Math.sqrt(1 + row[0][0] - row[1][1] - row[2][2]) * 2.0; + quaternion = [ + 0.25 * s, + (row[0][1] + row[1][0]) / s, + (row[0][2] + row[2][0]) / s, + (row[2][1] - row[1][2]) / s + ]; + } else if (row[1][1] > row[2][2]) { + s = Math.sqrt(1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; + quaternion = [ + (row[0][1] + row[1][0]) / s, + 0.25 * s, + (row[1][2] + row[2][1]) / s, + (row[0][2] - row[2][0]) / s + ]; + } else { + s = Math.sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; + quaternion = [ + (row[0][2] + row[2][0]) / s, + (row[1][2] + row[2][1]) / s, + 0.25 * s, + (row[1][0] - row[0][1]) / s + ]; + } + + return [translate, scale, skew, quaternion, perspective]; + } + return decomposeMatrix; + })(); + + function dot(v1, v2) { + var result = 0; + for (var i = 0; i < v1.length; i++) { + result += v1[i] * v2[i]; + } + return result; + } + + function multiplyMatrices(a, b) { + return [ + a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3], + a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3], + a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3], + a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], + + a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7], + a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7], + a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7], + a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], + + a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11], + a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11], + a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11], + a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], + + a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15], + a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15], + a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15], + a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15] + ]; + } + + // TODO: This can probably be made smaller. + function convertItemToMatrix(item) { + switch (item.t) { + // TODO: Handle units other than rads and degs. + case 'rotatex': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, 0, 0, 0, + 0, Math.cos(angle), Math.sin(angle), 0, + 0, -Math.sin(angle), Math.cos(angle), 0, + 0, 0, 0, 1]; + case 'rotatey': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [Math.cos(angle), 0, -Math.sin(angle), 0, + 0, 1, 0, 0, + Math.sin(angle), 0, Math.cos(angle), 0, + 0, 0, 0, 1]; + case 'rotate': + case 'rotatez': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [Math.cos(angle), Math.sin(angle), 0, 0, + -Math.sin(angle), Math.cos(angle), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'rotate3d': + var x = item.d[0]; + var y = item.d[1]; + var z = item.d[2]; + var rads = item.d[3].rad || 0; + var degs = item.d[3].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + + var sqrLength = x * x + y * y + z * z; + if (sqrLength === 0) { + x = 1; + y = 0; + z = 0; + } else if (sqrLength !== 1) { + var length = Math.sqrt(sqrLength); + x /= length; + y /= length; + z /= length; + } + + var s = Math.sin(angle / 2); + var sc = s * Math.cos(angle / 2); + var sq = s * s; + return [ + 1 - 2 * (y * y + z * z) * sq, + 2 * (x * y * sq + z * sc), + 2 * (x * z * sq - y * sc), + 0, + + 2 * (x * y * sq - z * sc), + 1 - 2 * (x * x + z * z) * sq, + 2 * (y * z * sq + x * sc), + 0, + + 2 * (x * z * sq + y * sc), + 2 * (y * z * sq - x * sc), + 1 - 2 * (x * x + y * y) * sq, + 0, + + 0, 0, 0, 1 + ]; + case 'scale': + return [item.d[0], 0, 0, 0, + 0, item.d[1], 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scalex': + return [item.d[0], 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scaley': + return [1, 0, 0, 0, + 0, item.d[0], 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'scalez': + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, item.d[0], 0, + 0, 0, 0, 1]; + case 'scale3d': + return [item.d[0], 0, 0, 0, + 0, item.d[1], 0, 0, + 0, 0, item.d[2], 0, + 0, 0, 0, 1]; + // FIXME: Skew behaves differently in Blink, FireFox and here. Need to work out why. + case 'skew': + var xDegs = item.d[0].deg || 0; + var xRads = item.d[0].rad || 0; + var yDegs = item.d[1].deg || 0; + var yRads = item.d[1].rad || 0; + var xAngle = (xDegs * Math.PI / 180) + xRads; + var yAngle = (yDegs * Math.PI / 180) + yRads; + return [1, Math.tan(yAngle), 0, 0, + Math.tan(xAngle), 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'skewx': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, 0, 0, 0, + Math.tan(angle), 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + case 'skewy': + var rads = item.d[0].rad || 0; + var degs = item.d[0].deg || 0; + var angle = (degs * Math.PI / 180) + rads; + return [1, Math.tan(angle), 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + // TODO: Work out what to do with non-px values. + case 'translate': + var x = item.d[0].px || 0; + var y = item.d[1].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, 0, 1]; + case 'translatex': + var x = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, 0, 0, 1]; + case 'translatey': + var y = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, y, 0, 1]; + case 'translatez': + var z = item.d[0].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, z, 1]; + case 'translate3d': + var x = item.d[0].px || 0; + var y = item.d[1].px || 0; + var z = item.d[2].px || 0; + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1]; + case 'perspective': + var p = item.d[0].px ? (-1 / item.d[0].px) : 0; + return [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, p, + 0, 0, 0, 1]; + case 'matrix': + return [item.d[0], item.d[1], 0, 0, + item.d[2], item.d[3], 0, 0, + 0, 0, 1, 0, + item.d[4], item.d[5], 0, 1]; + case 'matrix3d': + return item.d; + default: + WEB_ANIMATIONS_TESTING && console.assert(false, 'Transform item type ' + item.t + + ' conversion to matrix not yet implemented.'); + } + } + + function convertToMatrix(transformList) { + if (transformList.length === 0) { + return [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + } + return transformList.map(convertItemToMatrix).reduce(multiplyMatrices); + } + + function makeMatrixDecomposition(transformList) { + return [decomposeMatrix(convertToMatrix(transformList))]; + } + + scope.dot = dot; + scope.makeMatrixDecomposition = makeMatrixDecomposition; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/matrix-interpolation.js b/scripts/vendor/web-animations-js/src/matrix-interpolation.js new file mode 100755 index 0000000000..9a35de3bef --- /dev/null +++ b/scripts/vendor/web-animations-js/src/matrix-interpolation.js @@ -0,0 +1,130 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + var composeMatrix = (function() { + function multiply(a, b) { + var result = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; + for (var i = 0; i < 4; i++) { + for (var j = 0; j < 4; j++) { + for (var k = 0; k < 4; k++) { + result[i][j] += b[i][k] * a[k][j]; + } + } + } + return result; + } + + function is2D(m) { + return ( + m[0][2] == 0 && + m[0][3] == 0 && + m[1][2] == 0 && + m[1][3] == 0 && + m[2][0] == 0 && + m[2][1] == 0 && + m[2][2] == 1 && + m[2][3] == 0 && + m[3][2] == 0 && + m[3][3] == 1); + } + + function composeMatrix(translate, scale, skew, quat, perspective) { + var matrix = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + + for (var i = 0; i < 4; i++) { + matrix[i][3] = perspective[i]; + } + + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + matrix[3][i] += translate[j] * matrix[j][i]; + } + } + + var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; + + var rotMatrix = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + + rotMatrix[0][0] = 1 - 2 * (y * y + z * z); + rotMatrix[0][1] = 2 * (x * y - z * w); + rotMatrix[0][2] = 2 * (x * z + y * w); + rotMatrix[1][0] = 2 * (x * y + z * w); + rotMatrix[1][1] = 1 - 2 * (x * x + z * z); + rotMatrix[1][2] = 2 * (y * z - x * w); + rotMatrix[2][0] = 2 * (x * z - y * w); + rotMatrix[2][1] = 2 * (y * z + x * w); + rotMatrix[2][2] = 1 - 2 * (x * x + y * y); + + matrix = multiply(matrix, rotMatrix); + + var temp = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; + if (skew[2]) { + temp[2][1] = skew[2]; + matrix = multiply(matrix, temp); + } + + if (skew[1]) { + temp[2][1] = 0; + temp[2][0] = skew[0]; + matrix = multiply(matrix, temp); + } + + if (skew[0]) { + temp[2][0] = 0; + temp[1][0] = skew[0]; + matrix = multiply(matrix, temp); + } + + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + matrix[i][j] *= scale[i]; + } + } + + if (is2D(matrix)) { + return [matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1], matrix[3][0], matrix[3][1]]; + } + return matrix[0].concat(matrix[1], matrix[2], matrix[3]); + } + return composeMatrix; + })(); + + function clamp(x, min, max) { + return Math.max(Math.min(x, max), min); + }; + + function quat(fromQ, toQ, f) { + var product = scope.dot(fromQ, toQ); + product = clamp(product, -1.0, 1.0); + + var quat = []; + if (product === 1.0) { + quat = fromQ; + } else { + var theta = Math.acos(product); + var w = Math.sin(f * theta) * 1 / Math.sqrt(1 - product * product); + + for (var i = 0; i < 4; i++) { + quat.push(fromQ[i] * (Math.cos(f * theta) - product * w) + + toQ[i] * w); + } + } + return quat; + } + + scope.composeMatrix = composeMatrix; + scope.quat = quat; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/normalize-keyframes.js b/scripts/vendor/web-animations-js/src/normalize-keyframes.js new file mode 100755 index 0000000000..dbab8bf87a --- /dev/null +++ b/scripts/vendor/web-animations-js/src/normalize-keyframes.js @@ -0,0 +1,259 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, testing) { + var shorthandToLonghand = { + background: [ + 'backgroundImage', + 'backgroundPosition', + 'backgroundSize', + 'backgroundRepeat', + 'backgroundAttachment', + 'backgroundOrigin', + 'backgroundClip', + 'backgroundColor' + ], + border: [ + 'borderTopColor', + 'borderTopStyle', + 'borderTopWidth', + 'borderRightColor', + 'borderRightStyle', + 'borderRightWidth', + 'borderBottomColor', + 'borderBottomStyle', + 'borderBottomWidth', + 'borderLeftColor', + 'borderLeftStyle', + 'borderLeftWidth' + ], + borderBottom: [ + 'borderBottomWidth', + 'borderBottomStyle', + 'borderBottomColor' + ], + borderColor: [ + 'borderTopColor', + 'borderRightColor', + 'borderBottomColor', + 'borderLeftColor' + ], + borderLeft: [ + 'borderLeftWidth', + 'borderLeftStyle', + 'borderLeftColor' + ], + borderRadius: [ + 'borderTopLeftRadius', + 'borderTopRightRadius', + 'borderBottomRightRadius', + 'borderBottomLeftRadius' + ], + borderRight: [ + 'borderRightWidth', + 'borderRightStyle', + 'borderRightColor' + ], + borderTop: [ + 'borderTopWidth', + 'borderTopStyle', + 'borderTopColor' + ], + borderWidth: [ + 'borderTopWidth', + 'borderRightWidth', + 'borderBottomWidth', + 'borderLeftWidth' + ], + flex: [ + 'flexGrow', + 'flexShrink', + 'flexBasis' + ], + font: [ + 'fontFamily', + 'fontSize', + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'lineHeight' + ], + margin: [ + 'marginTop', + 'marginRight', + 'marginBottom', + 'marginLeft' + ], + outline: [ + 'outlineColor', + 'outlineStyle', + 'outlineWidth' + ], + padding: [ + 'paddingTop', + 'paddingRight', + 'paddingBottom', + 'paddingLeft' + ] + }; + + var shorthandExpanderElem = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + + var borderWidthAliases = { + thin: '1px', + medium: '3px', + thick: '5px' + }; + + var aliases = { + borderBottomWidth: borderWidthAliases, + borderLeftWidth: borderWidthAliases, + borderRightWidth: borderWidthAliases, + borderTopWidth: borderWidthAliases, + fontSize: { + 'xx-small': '60%', + 'x-small': '75%', + 'small': '89%', + 'medium': '100%', + 'large': '120%', + 'x-large': '150%', + 'xx-large': '200%' + }, + fontWeight: { + normal: '400', + bold: '700' + }, + outlineWidth: borderWidthAliases, + textShadow: { + none: '0px 0px 0px transparent' + }, + boxShadow: { + none: '0px 0px 0px 0px transparent' + } + }; + + function antiAlias(property, value) { + if (property in aliases) { + return aliases[property][value] || value; + } + return value; + } + + // This delegates parsing shorthand value syntax to the browser. + function expandShorthandAndAntiAlias(property, value, result) { + var longProperties = shorthandToLonghand[property]; + if (longProperties) { + shorthandExpanderElem.style[property] = value; + for (var i in longProperties) { + var longProperty = longProperties[i]; + var longhandValue = shorthandExpanderElem.style[longProperty]; + result[longProperty] = antiAlias(longProperty, longhandValue); + } + } else { + result[property] = antiAlias(property, value); + } + }; + + function normalizeKeyframes(effectInput) { + if (!Array.isArray(effectInput) && effectInput !== null) + throw new TypeError('Keyframes must be null or an array of keyframes'); + + if (effectInput == null) + return []; + + var keyframes = effectInput.map(function(originalKeyframe) { + var keyframe = {}; + for (var member in originalKeyframe) { + var memberValue = originalKeyframe[member]; + if (member == 'offset') { + if (memberValue != null) { + memberValue = Number(memberValue); + if (!isFinite(memberValue)) + throw new TypeError('keyframe offsets must be numbers.'); + } + } else if (member == 'composite') { + throw { + type: DOMException.NOT_SUPPORTED_ERR, + name: 'NotSupportedError', + message: 'add compositing is not supported' + }; + } else if (member == 'easing') { + memberValue = shared.toTimingFunction(memberValue); + } else { + memberValue = '' + memberValue; + } + expandShorthandAndAntiAlias(member, memberValue, keyframe); + } + if (keyframe.offset == undefined) + keyframe.offset = null; + if (keyframe.easing == undefined) + keyframe.easing = shared.toTimingFunction('linear'); + return keyframe; + }); + + var everyFrameHasOffset = true; + var looselySortedByOffset = true; + var previousOffset = -Infinity; + for (var i = 0; i < keyframes.length; i++) { + var offset = keyframes[i].offset; + if (offset != null) { + if (offset < previousOffset) { + throw { + code: DOMException.INVALID_MODIFICATION_ERR, + name: 'InvalidModificationError', + message: 'Keyframes are not loosely sorted by offset. Sort or specify offsets.' + }; + } + previousOffset = offset; + } else { + everyFrameHasOffset = false; + } + } + + keyframes = keyframes.filter(function(keyframe) { + return keyframe.offset >= 0 && keyframe.offset <= 1; + }); + + function spaceKeyframes() { + var length = keyframes.length; + if (keyframes[length - 1].offset == null) + keyframes[length - 1].offset = 1; + if (length > 1 && keyframes[0].offset == null) + keyframes[0].offset = 0; + + var previousIndex = 0; + var previousOffset = keyframes[0].offset; + for (var i = 1; i < length; i++) { + var offset = keyframes[i].offset; + if (offset != null) { + for (var j = 1; j < i - previousIndex; j++) + keyframes[previousIndex + j].offset = previousOffset + (offset - previousOffset) * j / (i - previousIndex); + previousIndex = i; + previousOffset = offset; + } + } + } + if (!everyFrameHasOffset) + spaceKeyframes(); + + return keyframes; + } + + shared.normalizeKeyframes = normalizeKeyframes; + + if (WEB_ANIMATIONS_TESTING) { + testing.normalizeKeyframes = normalizeKeyframes; + } + +})(webAnimationsShared, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/number-handler.js b/scripts/vendor/web-animations-js/src/number-handler.js new file mode 100755 index 0000000000..750937392d --- /dev/null +++ b/scripts/vendor/web-animations-js/src/number-handler.js @@ -0,0 +1,70 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function numberToString(x) { + return x.toFixed(3).replace('.000', ''); + } + + function clamp(min, max, x) { + return Math.min(max, Math.max(min, x)); + } + + function parseNumber(string) { + if (/^\s*[-+]?(\d*\.)?\d+\s*$/.test(string)) + return Number(string); + } + + function mergeNumbers(left, right) { + return [left, right, numberToString]; + } + + // FIXME: This should probably go in it's own handler. + function mergeFlex(left, right) { + if (left == 0) + return; + return clampedMergeNumbers(0, Infinity)(left, right); + } + + function mergePositiveIntegers(left, right) { + return [left, right, function(x) { + return Math.round(clamp(1, Infinity, x)); + }]; + } + + function clampedMergeNumbers(min, max) { + return function(left, right) { + return [left, right, function(x) { + return numberToString(clamp(min, max, x)); + }]; + }; + } + + function round(left, right) { + return [left, right, Math.round]; + } + + scope.clamp = clamp; + scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, Infinity), ['border-image-width', 'line-height']); + scope.addPropertiesHandler(parseNumber, clampedMergeNumbers(0, 1), ['opacity', 'shape-image-threshold']); + scope.addPropertiesHandler(parseNumber, mergeFlex, ['flex-grow', 'flex-shrink']); + scope.addPropertiesHandler(parseNumber, mergePositiveIntegers, ['orphans', 'widows']); + scope.addPropertiesHandler(parseNumber, round, ['z-index']); + + scope.parseNumber = parseNumber; + scope.mergeNumbers = mergeNumbers; + scope.numberToString = numberToString; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/position-handler.js b/scripts/vendor/web-animations-js/src/position-handler.js new file mode 100755 index 0000000000..18cea438cd --- /dev/null +++ b/scripts/vendor/web-animations-js/src/position-handler.js @@ -0,0 +1,117 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + function negateDimension(dimension) { + var result = {}; + for (var k in dimension) { + result[k] = -dimension[k]; + } + return result; + } + + function consumeOffset(string) { + return scope.consumeToken(/^(left|center|right|top|bottom)\b/i, string) || scope.consumeLengthOrPercent(string); + } + + var offsetMap = { + left: {'%': 0}, + center: {'%': 50}, + right: {'%': 100}, + top: {'%': 0}, + bottom: {'%': 100}, + }; + + function parseOrigin(slots, string) { + var result = scope.consumeRepeated(consumeOffset, /^/, string); + if (!result || result[1] != '') return; + var tokens = result[0]; + tokens[0] = tokens[0] || 'center'; + tokens[1] = tokens[1] || 'center'; + if (slots == 3) { + tokens[2] = tokens[2] || {px: 0}; + } + if (tokens.length != slots) { + return; + } + // Reorder so that the horizontal axis comes first. + if (/top|bottom/.test(tokens[0]) || /left|right/.test(tokens[1])) { + var tmp = tokens[0]; + tokens[0] = tokens[1]; + tokens[1] = tmp; + } + // Invalid if not horizontal then vertical. + if (!/left|right|center|Object/.test(tokens[0])) + return; + if (!/top|bottom|center|Object/.test(tokens[1])) + return; + return tokens.map(function(position) { + return typeof position == 'object' ? position : offsetMap[position]; + }); + } + + var mergeOffsetList = scope.mergeNestedRepeated.bind(null, scope.mergeDimensions, ' '); + scope.addPropertiesHandler(parseOrigin.bind(null, 3), mergeOffsetList, ['transform-origin']); + scope.addPropertiesHandler(parseOrigin.bind(null, 2), mergeOffsetList, ['perspective-origin']); + + function consumePosition(string) { + var result = scope.consumeRepeated(consumeOffset, /^/, string); + if (!result) { + return; + } + + var tokens = result[0]; + var out = [{'%': 50}, {'%': 50}]; + var pos = 0; + var bottomOrRight = false; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (typeof token == 'string') { + bottomOrRight = /bottom|right/.test(token); + pos = {left: 0, right: 0, center: pos, top: 1, bottom: 1}[token]; + out[pos] = offsetMap[token]; + if (token == 'center') { + // Center doesn't accept a length offset. + pos++; + } + } else { + if (bottomOrRight) { + // If bottom or right we need to subtract the length from 100% + token = negateDimension(token); + token['%'] = (token['%'] || 0) + 100; + } + out[pos] = token; + pos++; + bottomOrRight = false; + } + } + return [out, result[1]]; + } + + function parsePositionList(string) { + var result = scope.consumeRepeated(consumePosition, /^,/, string); + if (result && result[1] == '') { + return result[0]; + } + } + + scope.consumePosition = consumePosition; + scope.mergeOffsetList = mergeOffsetList; + + var mergePositionList = scope.mergeNestedRepeated.bind(null, mergeOffsetList, ', '); + scope.addPropertiesHandler(parsePositionList, mergePositionList, ['background-position', 'object-position']); + +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/property-interpolation.js b/scripts/vendor/web-animations-js/src/property-interpolation.js new file mode 100755 index 0000000000..8634bf6b89 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/property-interpolation.js @@ -0,0 +1,62 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var propertyHandlers = {}; + + function addPropertyHandler(parser, merger, property) { + propertyHandlers[property] = propertyHandlers[property] || []; + propertyHandlers[property].push([parser, merger]); + } + function addPropertiesHandler(parser, merger, properties) { + for (var i = 0; i < properties.length; i++) { + var property = properties[i]; + WEB_ANIMATIONS_TESTING && console.assert(property.toLowerCase() === property); + addPropertyHandler(parser, merger, property); + if (/-/.test(property)) { + // Add camel cased variant. + addPropertyHandler(parser, merger, property.replace(/-(.)/g, function(_, c) { + return c.toUpperCase(); + })); + } + } + } + scope.addPropertiesHandler = addPropertiesHandler; + + function propertyInterpolation(property, left, right) { + var handlers = left == right ? [] : propertyHandlers[property]; + for (var i = 0; handlers && i < handlers.length; i++) { + var parsedLeft = handlers[i][0](left); + var parsedRight = handlers[i][0](right); + if (parsedLeft !== undefined && parsedRight !== undefined) { + var interpolationArgs = handlers[i][1](parsedLeft, parsedRight); + if (interpolationArgs) { + var interp = scope.Interpolation.apply(null, interpolationArgs); + return function(t) { + if (t == 0) return left; + if (t == 1) return right; + return interp(t); + }; + } + } + } + return scope.Interpolation(false, true, function(bool) { + return bool ? right : left; + }); + } + scope.propertyInterpolation = propertyInterpolation; + +})(webAnimations1, webAnimationsTesting); + diff --git a/scripts/vendor/web-animations-js/src/property-names.js b/scripts/vendor/web-animations-js/src/property-names.js new file mode 100755 index 0000000000..c52d990cdb --- /dev/null +++ b/scripts/vendor/web-animations-js/src/property-names.js @@ -0,0 +1,35 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + var aliased = {}; + + function alias(name, aliases) { + aliases.concat([name]).forEach(function(candidate) { + if (candidate in document.documentElement.style) { + aliased[name] = candidate; + } + }); + } + alias('transform', ['webkitTransform', 'msTransform']); + alias('transformOrigin', ['webkitTransformOrigin']); + alias('perspective', ['webkitPerspective']); + alias('perspectiveOrigin', ['webkitPerspectiveOrigin']); + + scope.propertyName = function(property) { + return aliased[property] || property; + }; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/scope.js b/scripts/vendor/web-animations-js/src/scope.js new file mode 100755 index 0000000000..c8248802bc --- /dev/null +++ b/scripts/vendor/web-animations-js/src/scope.js @@ -0,0 +1,20 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var webAnimationsShared = {}; +var webAnimations1 = {}; +var webAnimationsNext = {}; + +if (!WEB_ANIMATIONS_TESTING) + var webAnimationsTesting = null; diff --git a/scripts/vendor/web-animations-js/src/shadow-handler.js b/scripts/vendor/web-animations-js/src/shadow-handler.js new file mode 100755 index 0000000000..3f8201d8a4 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/shadow-handler.js @@ -0,0 +1,108 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + function consumeShadow(string) { + var shadow = { + inset: false, + lengths: [], + color: null, + }; + function consumePart(string) { + var result = scope.consumeToken(/^inset/i, string); + if (result) { + shadow.inset = true; + return result; + } + var result = scope.consumeLengthOrPercent(string); + if (result) { + shadow.lengths.push(result[0]); + return result; + } + var result = scope.consumeColor(string); + if (result) { + shadow.color = result[0]; + return result; + } + } + var result = scope.consumeRepeated(consumePart, /^/, string); + if (result && result[0].length) { + return [shadow, result[1]]; + } + } + + function parseShadowList(string) { + var result = scope.consumeRepeated(consumeShadow, /^,/, string); + if (result && result[1] == '') { + return result[0]; + } + } + + function mergeShadow(left, right) { + while (left.lengths.length < Math.max(left.lengths.length, right.lengths.length)) + left.lengths.push({px: 0}); + while (right.lengths.length < Math.max(left.lengths.length, right.lengths.length)) + right.lengths.push({px: 0}); + + if (left.inset != right.inset || !!left.color != !!right.color) { + return; + } + var lengthReconstitution = []; + var colorReconstitution; + var matchingLeft = [[], 0]; + var matchingRight = [[], 0]; + for (var i = 0; i < left.lengths.length; i++) { + var mergedDimensions = scope.mergeDimensions(left.lengths[i], right.lengths[i], i == 2); + matchingLeft[0].push(mergedDimensions[0]); + matchingRight[0].push(mergedDimensions[1]); + lengthReconstitution.push(mergedDimensions[2]); + } + if (left.color && right.color) { + var mergedColor = scope.mergeColors(left.color, right.color); + matchingLeft[1] = mergedColor[0]; + matchingRight[1] = mergedColor[1]; + colorReconstitution = mergedColor[2]; + } + return [matchingLeft, matchingRight, function(value) { + var result = left.inset ? 'inset ' : ' '; + for (var i = 0; i < lengthReconstitution.length; i++) { + result += lengthReconstitution[i](value[0][i]) + ' '; + } + if (colorReconstitution) { + result += colorReconstitution(value[1]); + } + return result; + }]; + } + + function mergeNestedRepeatedShadow(nestedMerge, separator, left, right) { + var leftCopy = []; + var rightCopy = []; + function defaultShadow(inset) { + return {inset: inset, color: [0, 0, 0, 0], lengths: [{px: 0}, {px: 0}, {px: 0}, {px: 0}]}; + } + for (var i = 0; i < left.length || i < right.length; i++) { + var l = left[i] || defaultShadow(right[i].inset); + var r = right[i] || defaultShadow(left[i].inset); + leftCopy.push(l); + rightCopy.push(r); + } + return scope.mergeNestedRepeated(nestedMerge, separator, leftCopy, rightCopy); + } + + var mergeShadowList = mergeNestedRepeatedShadow.bind(null, mergeShadow, ', '); + scope.addPropertiesHandler(parseShadowList, mergeShadowList, ['box-shadow', 'text-shadow']); + +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/shape-handler.js b/scripts/vendor/web-animations-js/src/shape-handler.js new file mode 100755 index 0000000000..6bbf79fe48 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/shape-handler.js @@ -0,0 +1,85 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope) { + + var consumeLengthOrPercent = scope.consumeParenthesised.bind(null, scope.parseLengthOrPercent); + var consumeLengthOrPercentPair = scope.consumeRepeated.bind(undefined, consumeLengthOrPercent, /^/); + + var mergeSizePair = scope.mergeNestedRepeated.bind(undefined, scope.mergeDimensions, ' '); + var mergeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeSizePair, ','); + + function parseShape(input) { + var circle = scope.consumeToken(/^circle/, input); + if (circle && circle[0]) { + return ['circle'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + consumeLengthOrPercent, + scope.ignore(scope.consumeToken.bind(undefined, /^at/)), + scope.consumePosition, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], circle[1])); + } + var ellipse = scope.consumeToken(/^ellipse/, input); + if (ellipse && ellipse[0]) { + return ['ellipse'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + consumeLengthOrPercentPair, + scope.ignore(scope.consumeToken.bind(undefined, /^at/)), + scope.consumePosition, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], ellipse[1])); + } + var polygon = scope.consumeToken(/^polygon/, input); + if (polygon && polygon[0]) { + return ['polygon'].concat(scope.consumeList([ + scope.ignore(scope.consumeToken.bind(undefined, /^\(/)), + scope.optional(scope.consumeToken.bind(undefined, /^nonzero\s*,|^evenodd\s*,/), 'nonzero,'), + scope.consumeSizePairList, + scope.ignore(scope.consumeToken.bind(undefined, /^\)/)) + ], polygon[1])); + } + } + + function mergeShapes(left, right) { + if (left[0] !== right[0]) + return; + if (left[0] == 'circle') { + return scope.mergeList(left.slice(1), right.slice(1), [ + 'circle(', + scope.mergeDimensions, + ' at ', + scope.mergeOffsetList, + ')']); + } + if (left[0] == 'ellipse') { + return scope.mergeList(left.slice(1), right.slice(1), [ + 'ellipse(', + scope.mergeNonNegativeSizePair, + ' at ', + scope.mergeOffsetList, + ')']); + } + if (left[0] == 'polygon' && left[1] == right[1]) { + return scope.mergeList(left.slice(2), right.slice(2), [ + 'polygon(', + left[1], + mergeSizePairList, + ')']); + } + } + + scope.addPropertiesHandler(parseShape, mergeShapes, ['shape-outside']); + +})(webAnimations1); diff --git a/scripts/vendor/web-animations-js/src/tick.js b/scripts/vendor/web-animations-js/src/tick.js new file mode 100755 index 0000000000..57baac4184 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/tick.js @@ -0,0 +1,149 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +(function(shared, scope, testing) { + var originalRequestAnimationFrame = window.requestAnimationFrame; + var rafCallbacks = []; + var rafId = 0; + window.requestAnimationFrame = function(f) { + var id = rafId++; + if (rafCallbacks.length == 0 && !WEB_ANIMATIONS_TESTING) { + originalRequestAnimationFrame(processRafCallbacks); + } + rafCallbacks.push([id, f]); + return id; + }; + + window.cancelAnimationFrame = function(id) { + rafCallbacks.forEach(function(entry) { + if (entry[0] == id) { + entry[1] = function() {}; + } + }); + }; + + function processRafCallbacks(t) { + var processing = rafCallbacks; + rafCallbacks = []; + tick(t); + processing.forEach(function(entry) { entry[1](t); }); + if (needsRetick) + tick(t); + applyPendingEffects(); + } + + function compareAnimations(leftAnimation, rightAnimation) { + return leftAnimation._sequenceNumber - rightAnimation._sequenceNumber; + } + + function InternalTimeline() { + this._animations = []; + // Android 4.3 browser has window.performance, but not window.performance.now + this.currentTime = window.performance && performance.now ? performance.now() : 0; + }; + + InternalTimeline.prototype = { + _play: function(effect) { + effect._timing = shared.normalizeTimingInput(effect.timing); + var animation = new scope.Animation(effect); + animation._idle = false; + animation._timeline = this; + this._animations.push(animation); + scope.restart(); + scope.invalidateEffects(); + return animation; + } + }; + + var ticking = false; + var hasRestartedThisFrame = false; + + scope.restart = function() { + if (!ticking) { + ticking = true; + requestAnimationFrame(function() {}); + hasRestartedThisFrame = true; + } + return hasRestartedThisFrame; + }; + + var needsRetick = false; + scope.invalidateEffects = function() { + needsRetick = true; + }; + + var pendingEffects = []; + function applyPendingEffects() { + pendingEffects.forEach(function(f) { f(); }); + pendingEffects.length = 0; + } + + var originalGetComputedStyle = window.getComputedStyle; + Object.defineProperty(window, 'getComputedStyle', { + configurable: true, + enumerable: true, + value: function() { + if (needsRetick) tick(timeline.currentTime); + applyPendingEffects(); + return originalGetComputedStyle.apply(this, arguments); + }, + }); + + function tick(t) { + hasRestartedThisFrame = false; + var timeline = scope.timeline; + timeline.currentTime = t; + timeline._animations.sort(compareAnimations); + ticking = false; + var updatingAnimations = timeline._animations; + timeline._animations = []; + + var newPendingClears = []; + var newPendingEffects = []; + updatingAnimations = updatingAnimations.filter(function(animation) { + animation._inTimeline = animation._tick(t); + + if (!animation._inEffect) + newPendingClears.push(animation._effect); + else + newPendingEffects.push(animation._effect); + + if (!animation.finished && !animation.paused && !animation._idle) + ticking = true; + + return animation._inTimeline; + }); + + // FIXME: Should remove dupliactes from pendingEffects. + pendingEffects.push.apply(pendingEffects, newPendingClears); + pendingEffects.push.apply(pendingEffects, newPendingEffects); + + timeline._animations.push.apply(timeline._animations, updatingAnimations); + needsRetick = false; + + if (ticking) + requestAnimationFrame(function() {}); + }; + + if (WEB_ANIMATIONS_TESTING) { + testing.tick = processRafCallbacks; + testing.isTicking = function() { return ticking; }; + testing.setTicking = function(newVal) { ticking = newVal; }; + } + + var timeline = new InternalTimeline(); + scope.timeline = timeline; + +})(webAnimationsShared, webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/timeline.js b/scripts/vendor/web-animations-js/src/timeline.js new file mode 100755 index 0000000000..0209e2df38 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/timeline.js @@ -0,0 +1,86 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +(function(shared, scope, testing) { + + scope.AnimationTimeline = function() { + this._animations = []; + this.currentTime = undefined; + }; + + scope.AnimationTimeline.prototype = { + // FIXME: This needs to return the wrapped animations in Web Animations Next + // TODO: Does this need to be sorted? + // TODO: Do we need to consider needsRetick? + getAnimations: function() { + this._discardAnimations(); + return this._animations.slice(); + }, + getAnimationPlayers: function() { + shared.deprecated('AnimationTimeline.getAnimationPlayers', '2015-03-23', 'Use AnimationTimeline.getAnimations instead.'); + return this.getAnimations(); + }, + _discardAnimations: function() { + this._animations = this._animations.filter(function(animation) { + return animation.playState != 'finished' && animation.playState != 'idle'; + }); + }, + play: function(effect) { + var animation = new scope.Animation(effect); + this._animations.push(animation); + scope.restartWebAnimationsNextTick(); + // Use animation._animation.play() here, NOT animation.play(). + // + // Timeline.play calls new scope.Animation(effect) which (indirectly) calls Timeline.play on + // effect's children, and Animation.play is also recursive. We only need to call play on each + // animation in the tree once. + animation._animation.play(); + return animation; + }, + }; + + var ticking = false; + + scope.restartWebAnimationsNextTick = function() { + if (!ticking) { + ticking = true; + requestAnimationFrame(webAnimationsNextTick); + } + }; + + function webAnimationsNextTick(t) { + var timeline = window.document.timeline; + timeline.currentTime = t; + timeline._discardAnimations(); + if (timeline._animations.length == 0) + ticking = false; + else + requestAnimationFrame(webAnimationsNextTick); + } + + var timeline = new scope.AnimationTimeline(); + scope.timeline = timeline; + + try { + Object.defineProperty(window.document, 'timeline', { + configurable: true, + get: function() { return timeline; } + }); + } catch (e) { } + try { + window.document.timeline = timeline; + } catch (e) { } + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/timing-utilities.js b/scripts/vendor/web-animations-js/src/timing-utilities.js new file mode 100755 index 0000000000..43558cc7f9 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/timing-utilities.js @@ -0,0 +1,242 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, testing) { + + var fills = 'backwards|forwards|both|none'.split('|'); + var directions = 'reverse|alternate|alternate-reverse'.split('|'); + + function makeTiming(timingInput, forGroup) { + var timing = { + delay: 0, + endDelay: 0, + fill: forGroup ? 'both' : 'none', + iterationStart: 0, + iterations: 1, + duration: forGroup ? 'auto' : 0, + playbackRate: 1, + direction: 'normal', + easing: 'linear', + }; + if (typeof timingInput == 'number' && !isNaN(timingInput)) { + timing.duration = timingInput; + } else if (timingInput !== undefined) { + Object.getOwnPropertyNames(timingInput).forEach(function(property) { + if (timingInput[property] != 'auto') { + if (typeof timing[property] == 'number' || property == 'duration') { + if (typeof timingInput[property] != 'number' || isNaN(timingInput[property])) { + return; + } + } + if ((property == 'fill') && (fills.indexOf(timingInput[property]) == -1)) { + return; + } + if ((property == 'direction') && (directions.indexOf(timingInput[property]) == -1)) { + return; + } + if (property == 'playbackRate' && timingInput[property] !== 1 && shared.isDeprecated('AnimationEffectTiming.playbackRate', '2014-11-28', 'Use Animation.playbackRate instead.')) { + return; + } + timing[property] = timingInput[property]; + } + }); + } + return timing; + } + + function normalizeTimingInput(timingInput, forGroup) { + var timing = makeTiming(timingInput, forGroup); + timing.easing = toTimingFunction(timing.easing); + return timing; + } + + function cubic(a, b, c, d) { + if (a < 0 || a > 1 || c < 0 || c > 1) { + return linear; + } + return function(x) { + var start = 0, end = 1; + while (1) { + var mid = (start + end) / 2; + function f(a, b, m) { return 3 * a * (1 - m) * (1 - m) * m + 3 * b * (1 - m) * m * m + m * m * m}; + var xEst = f(a, c, mid); + if (Math.abs(x - xEst) < 0.001) { + return f(b, d, mid); + } + if (xEst < x) { + start = mid; + } else { + end = mid; + } + } + } + } + + var Start = 1; + var Middle = 0.5; + var End = 0; + + function step(count, pos) { + return function(x) { + if (x >= 1) { + return 1; + } + var stepSize = 1 / count; + x += pos * stepSize; + return x - x % stepSize; + } + } + + var presets = { + 'ease': cubic(0.25, 0.1, 0.25, 1), + 'ease-in': cubic(0.42, 0, 1, 1), + 'ease-out': cubic(0, 0, 0.58, 1), + 'ease-in-out': cubic(0.42, 0, 0.58, 1), + 'step-start': step(1, Start), + 'step-middle': step(1, Middle), + 'step-end': step(1, End) + }; + + var numberString = '\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*'; + var cubicBezierRe = new RegExp('cubic-bezier\\(' + numberString + ',' + numberString + ',' + numberString + ',' + numberString + '\\)'); + var stepRe = /steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/; + var linear = function(x) { return x; }; + + function toTimingFunction(easing) { + var cubicData = cubicBezierRe.exec(easing); + if (cubicData) { + return cubic.apply(this, cubicData.slice(1).map(Number)); + } + var stepData = stepRe.exec(easing); + if (stepData) { + return step(Number(stepData[1]), {'start': Start, 'middle': Middle, 'end': End}[stepData[2]]); + } + var preset = presets[easing]; + if (preset) { + return preset; + } + return linear; + }; + + function calculateActiveDuration(timing) { + return Math.abs(repeatedDuration(timing) / timing.playbackRate); + } + + function repeatedDuration(timing) { + return timing.duration * timing.iterations; + } + + var PhaseNone = 0; + var PhaseBefore = 1; + var PhaseAfter = 2; + var PhaseActive = 3; + + function calculatePhase(activeDuration, localTime, timing) { + if (localTime == null) { + return PhaseNone; + } + if (localTime < timing.delay) { + return PhaseBefore; + } + if (localTime >= timing.delay + activeDuration) { + return PhaseAfter; + } + return PhaseActive; + } + + function calculateActiveTime(activeDuration, fillMode, localTime, phase, delay) { + switch (phase) { + case PhaseBefore: + if (fillMode == 'backwards' || fillMode == 'both') + return 0; + return null; + case PhaseActive: + return localTime - delay; + case PhaseAfter: + if (fillMode == 'forwards' || fillMode == 'both') + return activeDuration; + return null; + case PhaseNone: + return null; + } + } + + function calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing) { + return (timing.playbackRate < 0 ? activeTime - activeDuration : activeTime) * timing.playbackRate + startOffset; + } + + function calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, timing) { + if (scaledActiveTime === Infinity || scaledActiveTime === -Infinity || (scaledActiveTime - startOffset == repeatedDuration && timing.iterations && ((timing.iterations + timing.iterationStart) % 1 == 0))) { + return iterationDuration; + } + + return scaledActiveTime % iterationDuration; + } + + function calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, timing) { + if (scaledActiveTime === 0) { + return 0; + } + if (iterationTime == iterationDuration) { + return timing.iterationStart + timing.iterations - 1; + } + return Math.floor(scaledActiveTime / iterationDuration); + } + + function calculateTransformedTime(currentIteration, iterationDuration, iterationTime, timing) { + var currentIterationIsOdd = currentIteration % 2 >= 1; + var currentDirectionIsForwards = timing.direction == 'normal' || timing.direction == (currentIterationIsOdd ? 'alternate-reverse' : 'alternate'); + var directedTime = currentDirectionIsForwards ? iterationTime : iterationDuration - iterationTime; + var timeFraction = directedTime / iterationDuration; + return iterationDuration * timing.easing(timeFraction); + } + + function calculateTimeFraction(activeDuration, localTime, timing) { + var phase = calculatePhase(activeDuration, localTime, timing); + var activeTime = calculateActiveTime(activeDuration, timing.fill, localTime, phase, timing.delay); + if (activeTime === null) + return null; + if (activeDuration === 0) + return phase === PhaseBefore ? 0 : 1; + var startOffset = timing.iterationStart * timing.duration; + var scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, timing); + var iterationTime = calculateIterationTime(timing.duration, repeatedDuration(timing), scaledActiveTime, startOffset, timing); + var currentIteration = calculateCurrentIteration(timing.duration, iterationTime, scaledActiveTime, timing); + return calculateTransformedTime(currentIteration, timing.duration, iterationTime, timing) / timing.duration; + } + + shared.makeTiming = makeTiming; + shared.normalizeTimingInput = normalizeTimingInput; + shared.calculateActiveDuration = calculateActiveDuration; + shared.calculateTimeFraction = calculateTimeFraction; + shared.calculatePhase = calculatePhase; + shared.toTimingFunction = toTimingFunction; + + if (WEB_ANIMATIONS_TESTING) { + testing.normalizeTimingInput = normalizeTimingInput; + testing.toTimingFunction = toTimingFunction; + testing.calculateActiveDuration = calculateActiveDuration; + testing.calculatePhase = calculatePhase; + testing.PhaseNone = PhaseNone; + testing.PhaseBefore = PhaseBefore; + testing.PhaseActive = PhaseActive; + testing.PhaseAfter = PhaseAfter; + testing.calculateActiveTime = calculateActiveTime; + testing.calculateScaledActiveTime = calculateScaledActiveTime; + testing.calculateIterationTime = calculateIterationTime; + testing.calculateCurrentIteration = calculateCurrentIteration; + testing.calculateTransformedTime = calculateTransformedTime; + } + +})(webAnimationsShared, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/transform-handler.js b/scripts/vendor/web-animations-js/src/transform-handler.js new file mode 100755 index 0000000000..c44829610b --- /dev/null +++ b/scripts/vendor/web-animations-js/src/transform-handler.js @@ -0,0 +1,262 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + // This returns a function for converting transform functions to equivalent + // primitive functions, which will take an array of values from the + // derivative type and fill in the blanks (underscores) with them. + var _ = null; + function cast(pattern) { + return function(contents) { + var i = 0; + return pattern.map(function(x) { return x === _ ? contents[i++] : x; }); + } + } + + function id(x) { return x; } + + var Opx = {px: 0}; + var Odeg = {deg: 0}; + + // type: [argTypes, convertTo3D, convertTo2D] + // In the argument types string, lowercase characters represent optional arguments + var transformFunctions = { + matrix: ['NNNNNN', [_, _, 0, 0, _, _, 0, 0, 0, 0, 1, 0, _, _, 0, 1], id], + matrix3d: ['NNNNNNNNNNNNNNNN', id], + rotate: ['A'], + rotatex: ['A'], + rotatey: ['A'], + rotatez: ['A'], + rotate3d: ['NNNA'], + perspective: ['L'], + scale: ['Nn', cast([_, _, 1]), id], + scalex: ['N', cast([_, 1, 1]), cast([_, 1])], + scaley: ['N', cast([1, _, 1]), cast([1, _])], + scalez: ['N', cast([1, 1, _])], + scale3d: ['NNN', id], + skew: ['Aa', null, id], + skewx: ['A', null, cast([_, Odeg])], + skewy: ['A', null, cast([Odeg, _])], + translate: ['Tt', cast([_, _, Opx]), id], + translatex: ['T', cast([_, Opx, Opx]), cast([_, Opx])], + translatey: ['T', cast([Opx, _, Opx]), cast([Opx, _])], + translatez: ['L', cast([Opx, Opx, _])], + translate3d: ['TTL', id], + }; + + function parseTransform(string) { + string = string.toLowerCase().trim(); + if (string == 'none') + return []; + // FIXME: Using a RegExp means calcs won't work here + var transformRegExp = /\s*(\w+)\(([^)]*)\)/g; + var result = []; + var match; + var prevLastIndex = 0; + while (match = transformRegExp.exec(string)) { + if (match.index != prevLastIndex) + return; + prevLastIndex = match.index + match[0].length; + var functionName = match[1]; + var functionData = transformFunctions[functionName]; + if (!functionData) + return; + var args = match[2].split(','); + var argTypes = functionData[0]; + if (argTypes.length < args.length) + return; + + var parsedArgs = []; + for (var i = 0; i < argTypes.length; i++) { + var arg = args[i]; + var type = argTypes[i]; + var parsedArg; + if (!arg) + parsedArg = ({a: Odeg, + n: parsedArgs[0], + t: Opx})[type]; + else + parsedArg = ({A: function(s) { return s.trim() == '0' ? Odeg : scope.parseAngle(s); }, + N: scope.parseNumber, + T: scope.parseLengthOrPercent, + L: scope.parseLength})[type.toUpperCase()](arg); + if (parsedArg === undefined) + return; + parsedArgs.push(parsedArg); + } + result.push({t: functionName, d: parsedArgs}); + + if (transformRegExp.lastIndex == string.length) + return result; + } + }; + + function numberToLongString(x) { + return x.toFixed(6).replace('.000000', ''); + } + + function mergeMatrices(left, right) { + if (left.decompositionPair !== right) { + left.decompositionPair = right; + var leftArgs = scope.makeMatrixDecomposition(left); + } + if (right.decompositionPair !== left) { + right.decompositionPair = left; + var rightArgs = scope.makeMatrixDecomposition(right); + } + if (leftArgs[0] == null || rightArgs[0] == null) + return [[false], [true], function(x) { return x ? right[0].d : left[0].d; }]; + leftArgs[0].push(0); + rightArgs[0].push(1); + return [ + leftArgs, + rightArgs, + function(list) { + var quat = scope.quat(leftArgs[0][3], rightArgs[0][3], list[5]); + var mat = scope.composeMatrix(list[0], list[1], list[2], quat, list[4]); + var stringifiedArgs = mat.map(numberToLongString).join(','); + return stringifiedArgs; + } + ]; + } + + function typeTo2D(type) { + return type.replace(/[xy]/, ''); + } + + function typeTo3D(type) { + return type.replace(/(x|y|z|3d)?$/, '3d'); + } + + function mergeTransforms(left, right) { + var matrixModulesLoaded = scope.makeMatrixDecomposition && true; + + var flipResults = false; + if (!left.length || !right.length) { + if (!left.length) { + flipResults = true; + left = right; + right = []; + } + for (var i = 0; i < left.length; i++) { + var type = left[i].t; + var args = left[i].d; + var defaultValue = type.substr(0, 5) == 'scale' ? 1 : 0; + right.push({t: type, d: args.map(function(arg) { + if (typeof arg == 'number') + return defaultValue; + var result = {}; + for (var unit in arg) + result[unit] = defaultValue; + return result; + })}); + } + } + + var isMatrixOrPerspective = function(lt, rt) { + return ((lt == 'perspective') && (rt == 'perspective')) || + ((lt == 'matrix' || lt == 'matrix3d') && (rt == 'matrix' || rt == 'matrix3d')); + }; + var leftResult = []; + var rightResult = []; + var types = []; + + if (left.length != right.length) { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices(left, right); + leftResult = [merged[0]]; + rightResult = [merged[1]]; + types = [['matrix', [merged[2]]]]; + } else { + for (var i = 0; i < left.length; i++) { + var leftType = left[i].t; + var rightType = right[i].t; + var leftArgs = left[i].d; + var rightArgs = right[i].d; + + var leftFunctionData = transformFunctions[leftType]; + var rightFunctionData = transformFunctions[rightType]; + + var type; + if (isMatrixOrPerspective(leftType, rightType)) { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices([left[i]], [right[i]]); + leftResult.push(merged[0]); + rightResult.push(merged[1]); + types.push(['matrix', [merged[2]]]); + continue; + } else if (leftType == rightType) { + type = leftType; + } else if (leftFunctionData[2] && rightFunctionData[2] && typeTo2D(leftType) == typeTo2D(rightType)) { + type = typeTo2D(leftType); + leftArgs = leftFunctionData[2](leftArgs); + rightArgs = rightFunctionData[2](rightArgs); + } else if (leftFunctionData[1] && rightFunctionData[1] && typeTo3D(leftType) == typeTo3D(rightType)) { + type = typeTo3D(leftType); + leftArgs = leftFunctionData[1](leftArgs); + rightArgs = rightFunctionData[1](rightArgs); + } else { + if (!matrixModulesLoaded) + return; + var merged = mergeMatrices(left, right); + leftResult = [merged[0]]; + rightResult = [merged[1]]; + types = [['matrix', [merged[2]]]]; + break; + } + + var leftArgsCopy = []; + var rightArgsCopy = []; + var stringConversions = []; + for (var j = 0; j < leftArgs.length; j++) { + var merge = typeof leftArgs[j] == 'number' ? scope.mergeNumbers : scope.mergeDimensions; + var merged = merge(leftArgs[j], rightArgs[j]); + leftArgsCopy[j] = merged[0]; + rightArgsCopy[j] = merged[1]; + stringConversions.push(merged[2]); + } + leftResult.push(leftArgsCopy); + rightResult.push(rightArgsCopy); + types.push([type, stringConversions]); + } + } + + if (flipResults) { + var tmp = leftResult; + leftResult = rightResult; + rightResult = tmp; + } + + return [leftResult, rightResult, function(list) { + return list.map(function(args, i) { + var stringifiedArgs = args.map(function(arg, j) { + return types[i][1][j](arg); + }).join(','); + if (types[i][0] == 'matrix' && stringifiedArgs.split(',').length == 16) + types[i][0] = 'matrix3d'; + return types[i][0] + '(' + stringifiedArgs + ')'; + + }).join(' '); + }]; + } + + scope.addPropertiesHandler(parseTransform, mergeTransforms, ['transform']); + + if (WEB_ANIMATIONS_TESTING) + testing.parseTransform = parseTransform; + +})(webAnimations1, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/src/visibility-handler.js b/scripts/vendor/web-animations-js/src/visibility-handler.js new file mode 100755 index 0000000000..53f2953554 --- /dev/null +++ b/scripts/vendor/web-animations-js/src/visibility-handler.js @@ -0,0 +1,29 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(scope, testing) { + + function merge(left, right) { + if (left != 'visible' && right != 'visible') return; + return [0, 1, function(x) { + if (x <= 0) return left; + if (x >= 1) return right; + return 'visible'; + }]; + } + + scope.addPropertiesHandler(String, merge, ['visibility']); + +})(webAnimations1); + diff --git a/scripts/vendor/web-animations-js/src/web-animations-next-animation.js b/scripts/vendor/web-animations-js/src/web-animations-next-animation.js new file mode 100755 index 0000000000..33fd3ffb4d --- /dev/null +++ b/scripts/vendor/web-animations-js/src/web-animations-next-animation.js @@ -0,0 +1,235 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function(shared, scope, testing) { + scope.Animation = function(effect) { + this.effect = effect; + if (effect) { + // FIXME: detach existing animation. + effect.animation = this; + } + this._isGroup = false; + this._animation = null; + this._childAnimations = []; + this._callback = null; + this._rebuildUnderlyingAnimation(); + // Animations are constructed in the idle state. + this._animation.cancel(); + }; + + // TODO: add an effect getter/setter + scope.Animation.prototype = { + _rebuildUnderlyingAnimation: function() { + if (this._animation) { + this._animation.cancel(); + this._animation = null; + } + + if (!this.effect || this.effect instanceof window.KeyframeEffect) { + this._animation = scope.newUnderlyingAnimationForKeyframeEffect(this.effect); + scope.bindAnimationForKeyframeEffect(this); + } + if (this.effect instanceof window.SequenceEffect || this.effect instanceof window.GroupEffect) { + this._animation = scope.newUnderlyingAnimationForGroup(this.effect); + scope.bindAnimationForGroup(this); + } + + // FIXME: move existing currentTime/startTime/playState to new animation + }, + _updateChildren: function() { + if (!this.effect || this.playState == 'idle') + return; + + var offset = this.effect._timing.delay; + this._childAnimations.forEach(function(childAnimation) { + this._arrangeChildren(childAnimation, offset); + if (this.effect instanceof window.SequenceEffect) + offset += scope.groupChildDuration(childAnimation.effect); + }.bind(this)); + }, + _setExternalAnimation: function(animation) { + if (!this.effect || !this._isGroup) + return; + for (var i = 0; i < this.effect.children.length; i++) { + this.effect.children[i].animation = animation; + this._childAnimations[i]._setExternalAnimation(animation); + } + }, + _constructChildren: function() { + if (!this.effect || !this._isGroup) + return; + var offset = this.effect._timing.delay; + this.effect.children.forEach(function(child) { + var childAnimation = window.document.timeline.play(child); + this._childAnimations.push(childAnimation); + childAnimation.playbackRate = this.playbackRate; + if (this.paused) + childAnimation.pause(); + child.animation = this.effect.animation; + + this._arrangeChildren(childAnimation, offset); + + if (this.effect instanceof window.SequenceEffect) + offset += scope.groupChildDuration(child); + }.bind(this)); + }, + _arrangeChildren: function(childAnimation, offset) { + if (this.startTime === null) { + childAnimation.currentTime = this.currentTime - offset / this.playbackRate; + childAnimation._startTime = null; + } else if (childAnimation.startTime !== this.startTime + offset / this.playbackRate) { + childAnimation.startTime = this.startTime + offset / this.playbackRate; + } + }, + get paused() { + return this._animation.paused; + }, + get playState() { + return this._animation.playState; + }, + get onfinish() { + return this._onfinish; + }, + set onfinish(v) { + if (typeof v == 'function') { + this._onfinish = v; + this._animation.onfinish = (function(e) { + e.target = this; + v.call(this, e); + }).bind(this); + } else { + this._animation.onfinish = v; + this.onfinish = this._animation.onfinish; + } + }, + get currentTime() { + return this._animation.currentTime; + }, + set currentTime(v) { + this._animation.currentTime = v; + this._register(); + this._forEachChild(function(child, offset) { + child.currentTime = v - offset; + }); + }, + get startTime() { + return this._animation.startTime; + }, + set startTime(v) { + this._animation.startTime = v; + this._register(); + this._forEachChild(function(child, offset) { + child.startTime = v + offset; + }); + }, + get playbackRate() { + return this._animation.playbackRate; + }, + set playbackRate(value) { + var oldCurrentTime = this.currentTime; + this._animation.playbackRate = value; + this._forEachChild(function(childAnimation) { + childAnimation.playbackRate = value; + }); + if (this.playState != 'paused' && this.playState != 'idle') { + this.play(); + } + if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } + }, + get finished() { + return this._animation.finished; + }, + get source() { + shared.deprecated('Animation.source', '2015-03-23', 'Use Animation.effect instead.'); + return this.effect; + }, + play: function() { + this._animation.play(); + this._register(); + scope.awaitStartTime(this); + this._forEachChild(function(child) { + var time = child.currentTime; + child.play(); + child.currentTime = time; + }); + }, + pause: function() { + this._animation.pause(); + this._register(); + this._forEachChild(function(child) { + child.pause(); + }); + }, + finish: function() { + this._animation.finish(); + this._register(); + // TODO: child animations?? + }, + cancel: function() { + this._animation.cancel(); + this._register(); + this._removeChildren(); + }, + reverse: function() { + var oldCurrentTime = this.currentTime; + this._animation.reverse(); + this._forEachChild(function(childAnimation) { + childAnimation.reverse(); + }); + if (oldCurrentTime !== null) { + this.currentTime = oldCurrentTime; + } + }, + addEventListener: function(type, handler) { + var wrapped = handler; + if (typeof handler == 'function') { + wrapped = (function(e) { + e.target = this; + handler.call(this, e); + }).bind(this); + handler._wrapper = wrapped; + } + this._animation.addEventListener(type, wrapped); + }, + removeEventListener: function(type, handler) { + this._animation.removeEventListener(type, (handler && handler._wrapper) || handler); + }, + _removeChildren: function() { + while (this._childAnimations.length) + this._childAnimations.pop().cancel(); + }, + _forEachChild: function(f) { + var offset = 0; + if (this.effect.children && this._childAnimations.length < this.effect.children.length) + this._constructChildren(); + this._childAnimations.forEach(function(child) { + f.call(this, child, offset); + if (this.effect instanceof window.SequenceEffect) + offset += child.effect.activeDuration; + }.bind(this)); + + if (this._animation.playState == 'pending') + return; + var timing = this.effect._timing; + var t = this._animation.currentTime; + if (t !== null) + t = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), t, timing); + if (t == null || isNaN(t)) + this._removeChildren(); + }, + }; + +})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); diff --git a/scripts/vendor/web-animations-js/target-config.js b/scripts/vendor/web-animations-js/target-config.js new file mode 100755 index 0000000000..47e3c23021 --- /dev/null +++ b/scripts/vendor/web-animations-js/target-config.js @@ -0,0 +1,136 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + + var scopeSrc = [ + 'src/scope.js']; + + var webAnimations1Src = [ + 'src/keyframe-interpolations.js', + 'src/property-interpolation.js', + 'src/keyframe-effect.js', + 'src/apply-preserving-inline-style.js', + 'src/element-animatable.js', + 'src/interpolation.js', + 'src/matrix-interpolation.js', + 'src/animation.js', + 'src/tick.js', + 'src/matrix-decomposition.js', + 'src/handler-utils.js', + 'src/shadow-handler.js', + 'src/number-handler.js', + 'src/visibility-handler.js', + 'src/color-handler.js', + 'src/dimension-handler.js', + 'src/box-handler.js', + 'src/transform-handler.js', + 'src/font-weight-handler.js', + 'src/position-handler.js', + 'src/shape-handler.js', + 'src/property-names.js', + ]; + + var liteWebAnimations1Src = [ + 'src/keyframe-interpolations.js', + 'src/property-interpolation.js', + 'src/keyframe-effect.js', + 'src/apply.js', + 'src/element-animatable.js', + 'src/interpolation.js', + 'src/animation.js', + 'src/tick.js', + 'src/handler-utils.js', + 'src/shadow-handler.js', + 'src/number-handler.js', + 'src/visibility-handler.js', + 'src/color-handler.js', + 'src/dimension-handler.js', + 'src/box-handler.js', + 'src/transform-handler.js', + 'src/property-names.js', + ]; + + + var sharedSrc = [ + 'src/timing-utilities.js', + 'src/normalize-keyframes.js', + 'src/deprecation.js', + ]; + + var webAnimationsNextSrc = [ + 'src/timeline.js', + 'src/web-animations-next-animation.js', + 'src/keyframe-effect-constructor.js', + 'src/effect-callback.js', + 'src/group-constructors.js']; + + var webAnimations1Test = [ + 'test/js/animation-finish-event.js', + 'test/js/animation.js', + 'test/js/apply-preserving-inline-style.js', + 'test/js/box-handler.js', + 'test/js/color-handler.js', + 'test/js/dimension-handler.js', + 'test/js/interpolation.js', + 'test/js/keyframes.js', + 'test/js/matrix-interpolation.js', + 'test/js/number-handler.js', + 'test/js/property-interpolation.js', + 'test/js/tick.js', + 'test/js/timing-utilities.js', + 'test/js/timing.js', + 'test/js/transform-handler.js']; + + var webAnimationsNextTest = webAnimations1Test.concat( + 'test/js/effect-callback.js', + 'test/js/group-animation-finish-event.js', + 'test/js/group-animation.js', + 'test/js/group-constructors.js', + 'test/js/keyframe-effect-constructor.js', + 'test/js/timeline.js'); + + // This object specifies the source and test files for different Web Animation build targets. + var targetConfig = { + 'web-animations': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + webAnimations1Src: webAnimations1Src, + webAnimationsNextSrc: [], + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src), + test: webAnimations1Test, + }, + 'web-animations-next': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + webAnimations1Src: webAnimations1Src, + webAnimationsNextSrc: webAnimationsNextSrc, + src: scopeSrc.concat(sharedSrc).concat(webAnimations1Src).concat(webAnimationsNextSrc), + test: webAnimationsNextTest, + }, + 'web-animations-next-lite': { + scopeSrc: scopeSrc, + sharedSrc: sharedSrc, + webAnimations1Src: liteWebAnimations1Src, + webAnimationsNextSrc: webAnimationsNextSrc, + src: scopeSrc.concat(sharedSrc).concat(liteWebAnimations1Src).concat(webAnimationsNextSrc), + test: [], + }, + }; + + if (typeof module != 'undefined') + module.exports = targetConfig; + else + window.webAnimationsTargetConfig = targetConfig; +})(); diff --git a/scripts/vendor/web-animations-js/target-loader.js b/scripts/vendor/web-animations-js/target-loader.js new file mode 100755 index 0000000000..979f5c800d --- /dev/null +++ b/scripts/vendor/web-animations-js/target-loader.js @@ -0,0 +1,27 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + var target = webAnimationsTargetConfig.defaultTarget; + if (typeof webAnimationsSourceTarget != 'undefined') + target = webAnimationsSourceTarget; + + // Native implementation detection. + + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + webAnimationsTargetConfig[target].src.forEach(function(sourceFile) { + document.write(''); + }); +})(); diff --git a/scripts/vendor/web-animations-js/templates/boilerplate b/scripts/vendor/web-animations-js/templates/boilerplate new file mode 100755 index 0000000000..5b902b59fd --- /dev/null +++ b/scripts/vendor/web-animations-js/templates/boilerplate @@ -0,0 +1,13 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/scripts/vendor/web-animations-js/templates/runner.html b/scripts/vendor/web-animations-js/templates/runner.html new file mode 100755 index 0000000000..48d5d4c5e3 --- /dev/null +++ b/scripts/vendor/web-animations-js/templates/runner.html @@ -0,0 +1,26 @@ + + + + + + + + + +
diff --git a/scripts/vendor/web-animations-js/templates/web-animations.html b/scripts/vendor/web-animations-js/templates/web-animations.html new file mode 100755 index 0000000000..4af996eac6 --- /dev/null +++ b/scripts/vendor/web-animations-js/templates/web-animations.html @@ -0,0 +1,18 @@ + + +<% _.forEach(src, function(src) { %> +<% }); %> diff --git a/scripts/vendor/web-animations-js/templates/web-animations.js b/scripts/vendor/web-animations-js/templates/web-animations.js new file mode 100755 index 0000000000..4a81d9936f --- /dev/null +++ b/scripts/vendor/web-animations-js/templates/web-animations.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = '<%= target %>'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/vendor/web-animations-js/test/blink/2-keyframes-with-offsets.html b/scripts/vendor/web-animations-js/test/blink/2-keyframes-with-offsets.html new file mode 100755 index 0000000000..248d131210 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/2-keyframes-with-offsets.html @@ -0,0 +1,56 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/3-keyframes-with-offsets.html b/scripts/vendor/web-animations-js/test/blink/3-keyframes-with-offsets.html new file mode 100755 index 0000000000..fcd421d404 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/3-keyframes-with-offsets.html @@ -0,0 +1,147 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/add-keyframes.html b/scripts/vendor/web-animations-js/test/blink/add-keyframes.html new file mode 100755 index 0000000000..d53044c8d1 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/add-keyframes.html @@ -0,0 +1,33 @@ + +Web Animations API: Add Keyframe tests + + +
+
+ diff --git a/scripts/vendor/web-animations-js/test/blink/eased-keyframes.html b/scripts/vendor/web-animations-js/test/blink/eased-keyframes.html new file mode 100755 index 0000000000..518772ff72 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/eased-keyframes.html @@ -0,0 +1,95 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/get-animations.html b/scripts/vendor/web-animations-js/test/blink/get-animations.html new file mode 100755 index 0000000000..878ea51aef --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/get-animations.html @@ -0,0 +1,90 @@ + + + + +
+
+
+ + diff --git a/scripts/vendor/web-animations-js/test/blink/get-css-animations.html b/scripts/vendor/web-animations-js/test/blink/get-css-animations.html new file mode 100755 index 0000000000..429a337008 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/get-css-animations.html @@ -0,0 +1,40 @@ + + + + +
+
+
+ + diff --git a/scripts/vendor/web-animations-js/test/blink/insufficient-keyframes.html b/scripts/vendor/web-animations-js/test/blink/insufficient-keyframes.html new file mode 100755 index 0000000000..dbbecc4dfa --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/insufficient-keyframes.html @@ -0,0 +1,39 @@ + +Web Animations API: Insufficient Keyframe tests + + +
+
+ diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/background-color-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/background-color-interpolation.html new file mode 100755 index 0000000000..289cf9f948 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/background-color-interpolation.html @@ -0,0 +1,46 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/background-image-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/background-image-interpolation.html new file mode 100755 index 0000000000..fec614cbd3 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/background-image-interpolation.html @@ -0,0 +1,143 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-interpolation.html new file mode 100755 index 0000000000..0b20bc598d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-interpolation.html @@ -0,0 +1,69 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-origin-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-origin-interpolation.html new file mode 100755 index 0000000000..60009ee1e6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/background-position-origin-interpolation.html @@ -0,0 +1,142 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/background-size-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/background-size-interpolation.html new file mode 100755 index 0000000000..ab02bba5c3 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/background-size-interpolation.html @@ -0,0 +1,101 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-color-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-color-interpolation.html new file mode 100755 index 0000000000..9b6d0ec261 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-color-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-outset-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-outset-interpolation.html new file mode 100755 index 0000000000..c2ed07edaf --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-outset-interpolation.html @@ -0,0 +1,65 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-slice-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-slice-interpolation.html new file mode 100755 index 0000000000..acb00e457a --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-slice-interpolation.html @@ -0,0 +1,43 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-source-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-source-interpolation.html new file mode 100755 index 0000000000..aabae3da53 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-source-interpolation.html @@ -0,0 +1,83 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-width-interpolation.html new file mode 100755 index 0000000000..bfbbf753aa --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-image-width-interpolation.html @@ -0,0 +1,154 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-radius-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-radius-interpolation.html new file mode 100755 index 0000000000..e4db09cd71 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-radius-interpolation.html @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-spacing-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-spacing-interpolation.html new file mode 100755 index 0000000000..afd4c02f5b --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-spacing-interpolation.html @@ -0,0 +1,74 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/border-width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/border-width-interpolation.html new file mode 100755 index 0000000000..4492671e48 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/border-width-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/bottom-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/bottom-interpolation.html new file mode 100755 index 0000000000..f14b521163 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/bottom-interpolation.html @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/box-shadow-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/box-shadow-interpolation.html new file mode 100755 index 0000000000..548f12e3eb --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/box-shadow-interpolation.html @@ -0,0 +1,64 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/calc-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/calc-interpolation.html new file mode 100755 index 0000000000..e40cfcfe21 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/calc-interpolation.html @@ -0,0 +1,92 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/clip-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/clip-interpolation.html new file mode 100755 index 0000000000..103a366988 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/clip-interpolation.html @@ -0,0 +1,93 @@ + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/color-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/color-interpolation.html new file mode 100755 index 0000000000..0da034c4c7 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/color-interpolation.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/filter-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/filter-interpolation.html new file mode 100755 index 0000000000..2fd4bd7d87 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/filter-interpolation.html @@ -0,0 +1,256 @@ + + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/flex-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/flex-interpolation.html new file mode 100755 index 0000000000..857918e525 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/flex-interpolation.html @@ -0,0 +1,56 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/font-size-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/font-size-interpolation.html new file mode 100755 index 0000000000..69cb624781 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/font-size-interpolation.html @@ -0,0 +1,55 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/font-weight-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/font-weight-interpolation.html new file mode 100755 index 0000000000..630aaf1a59 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/font-weight-interpolation.html @@ -0,0 +1,93 @@ + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/height-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/height-interpolation.html new file mode 100755 index 0000000000..697f2ca3c2 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/height-interpolation.html @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/left-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/left-interpolation.html new file mode 100755 index 0000000000..c03e7d0647 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/left-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/letter-spacing-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/letter-spacing-interpolation.html new file mode 100755 index 0000000000..b1275fd99b --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/letter-spacing-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/line-height-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/line-height-interpolation.html new file mode 100755 index 0000000000..0d1139d985 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/line-height-interpolation.html @@ -0,0 +1,188 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/list-style-image-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/list-style-image-interpolation.html new file mode 100755 index 0000000000..8986e904a4 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/list-style-image-interpolation.html @@ -0,0 +1,84 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/margin-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/margin-interpolation.html new file mode 100755 index 0000000000..4ae490b6c6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/margin-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/max-height-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/max-height-interpolation.html new file mode 100755 index 0000000000..f41897503a --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/max-height-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/max-width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/max-width-interpolation.html new file mode 100755 index 0000000000..5549b3acb2 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/max-width-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/min-height-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/min-height-interpolation.html new file mode 100755 index 0000000000..a37ff8fcec --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/min-height-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/min-width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/min-width-interpolation.html new file mode 100755 index 0000000000..ceda43e0c5 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/min-width-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/object-position-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/object-position-interpolation.html new file mode 100755 index 0000000000..45b4f2cec8 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/object-position-interpolation.html @@ -0,0 +1,84 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/opacity-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/opacity-interpolation.html new file mode 100755 index 0000000000..d9209c61a6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/opacity-interpolation.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/orphans-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/orphans-interpolation.html new file mode 100755 index 0000000000..8733c788b2 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/orphans-interpolation.html @@ -0,0 +1,28 @@ + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/outline-color-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-color-interpolation.html new file mode 100755 index 0000000000..c40efeaa44 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-color-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/outline-offset-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-offset-interpolation.html new file mode 100755 index 0000000000..2a3f7b05b9 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-offset-interpolation.html @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/outline-width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-width-interpolation.html new file mode 100755 index 0000000000..acbad53294 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/outline-width-interpolation.html @@ -0,0 +1,47 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/padding-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/padding-interpolation.html new file mode 100755 index 0000000000..a74e977c85 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/padding-interpolation.html @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-interpolation.html new file mode 100755 index 0000000000..8c1340f085 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-interpolation.html @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-origin-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-origin-interpolation.html new file mode 100755 index 0000000000..8eaccfbd7f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/perspective-origin-interpolation.html @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/resources/interpolation-test.js b/scripts/vendor/web-animations-js/test/blink/interpolation/resources/interpolation-test.js new file mode 100755 index 0000000000..a5a4711ec2 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/resources/interpolation-test.js @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This script is intended to be used for constructing layout tests which + * exercise the interpolation functionaltiy of the animation system. + * Tests which run using this script should be portable across browsers. + * + * The following function is exported: + * * assertInterpolation({property: x, from: y, to: z}, [{at: fraction, is: value}]) + * Constructs a test case which for each fraction will output a PASS + * or FAIL depending on whether the interpolated result matches + * 'value'. Replica elements are constructed to aid eyeballing test + * results. + */ +'use strict'; +(function() { + var endEvent = 'animationend'; + var testCount = 0; + var animationEventCount = 0; + var durationSeconds = 0; + var iterationCount = 0.5; + var delaySeconds = 0; + var fragment = document.createDocumentFragment(); + var fragmentAttachedListeners = []; + var style = document.createElement('style'); + var afterTestCallback = null; + fragment.appendChild(style); + + var tests = document.createElement('div'); + tests.id = 'interpolation-tests'; + tests.textContent = 'Interpolation Tests:'; + fragment.appendChild(tests); + + var updateScheduled = false; + function maybeScheduleUpdate() { + if (updateScheduled) { + return; + } + updateScheduled = true; + setTimeout(function() { + updateScheduled = false; + document.body.appendChild(fragment); + fragmentAttachedListeners.forEach(function(listener) {listener();}); + }, 0); + } + + function evaluateTests() { + var targets = document.querySelectorAll('.target.active'); + for (var i = 0; i < targets.length; i++) { + targets[i].evaluate(); + } + } + + function afterTest(callback) { + afterTestCallback = callback; + } + + // Constructs a timing function which produces 'y' at x = 0.5 + function createEasing(y) { + // FIXME: if 'y' is > 0 and < 1 use a linear timing function and allow + // 'x' to vary. Use a bezier only for values < 0 or > 1. + if (y == 0) { + return 'steps(1, end)'; + } + if (y == 1) { + return 'steps(1, start)'; + } + if (y == 0.5) { + return 'steps(2, end)'; + } + // Approximate using a bezier. + var b = (8 * y - 1) / 6; + return 'cubic-bezier(0, ' + b + ', 1, ' + b + ')'; + } + + function createTestContainer(description, className) { + var testContainer = document.createElement('div'); + testContainer.setAttribute('description', description); + testContainer.classList.add('test'); + if (className) { + testContainer.classList.add(className); + } + return testContainer; + } + + function convertPropertyToCamelCase(property) { + return property.replace(/^-/, '').replace(/-\w/g, function(m) {return m[1].toUpperCase();}); + } + + function describeTest(params) { + return convertPropertyToCamelCase(params.property) + ': from [' + params.from + '] to [' + params.to + ']'; + } + + var nextKeyframeId = 0; + function assertInterpolation(params, expectations) { + var testId = 'test-' + ++nextKeyframeId; + var nextCaseId = 0; + var testContainer = createTestContainer(describeTest(params), testId); + tests.appendChild(testContainer); + expectations.forEach(function(expectation) { + testContainer.appendChild(makeInterpolationTest( + expectation.at, testId, 'case-' + ++nextCaseId, params, expectation.is)); + }); + maybeScheduleUpdate(); + } + + function roundNumbers(value) { + // Round numbers to two decimal places. + return value.replace(/-?\d*\.\d+/g, function(n) { + return (parseFloat(n).toFixed(2)). + replace(/\.\d+/, function(m) { + return m.replace(/0+$/, ''); + }). + replace(/\.$/, ''). + replace(/^-0$/, '0'); + }); + } + + function normalizeValue(value) { + return roundNumbers(value). + // Place whitespace between tokens. + replace(/([\w\d.]+|[^\s])/g, '$1 '). + replace(/\s+/g, ' '); + } + + function createTargetContainer(id) { + var targetContainer = document.createElement('div'); + var template = document.querySelector('#target-template'); + if (template) { + if (template.content) + targetContainer.appendChild(template.content.cloneNode(true)); + else if (template.querySelector('div')) + targetContainer.appendChild(template.querySelector('div').cloneNode(true)); + else + targetContainer.appendChild(template.cloneNode(true)); + // Remove whitespace text nodes at start / end. + while (targetContainer.firstChild.nodeType != Node.ELEMENT_NODE && !/\S/.test(targetContainer.firstChild.nodeValue)) { + targetContainer.removeChild(targetContainer.firstChild); + } + while (targetContainer.lastChild.nodeType != Node.ELEMENT_NODE && !/\S/.test(targetContainer.lastChild.nodeValue)) { + targetContainer.removeChild(targetContainer.lastChild); + } + // If the template contains just one element, use that rather than a wrapper div. + if (targetContainer.children.length == 1 && targetContainer.childNodes.length == 1) { + targetContainer = targetContainer.firstChild; + targetContainer.parentNode.removeChild(targetContainer); + } + } + var target = targetContainer.querySelector('.target') || targetContainer; + target.classList.add('target'); + target.classList.add(id); + return targetContainer; + } + + function sanitizeUrls(value) { + var matches = value.match(/url\([^\)]*\)/g); + if (matches !== null) { + for (var i = 0; i < matches.length; ++i) { + var url = /url\(([^\)]*)\)/g.exec(matches[i])[1]; + var anchor = document.createElement('a'); + anchor.href = url; + anchor.pathname = '...' + anchor.pathname.substring(anchor.pathname.lastIndexOf('/')); + value = value.replace(matches[i], 'url(' + anchor.href + ')'); + } + } + return value; + } + + function makeInterpolationTest(fraction, testId, caseId, params, expectation) { + var t = async_test(describeTest(params) + ' at ' + fraction); + var targetContainer = createTargetContainer(caseId); + var target = targetContainer.querySelector('.target') || targetContainer; + target.classList.add('active'); + var replicaContainer, replica; + replicaContainer = createTargetContainer(caseId); + replica = replicaContainer.querySelector('.target') || replicaContainer; + replica.classList.add('replica'); + replica.style.setProperty(params.property, expectation); + if (params.prefixedProperty) { + for (var i = 0; i < params.prefixedProperty.length; i++) { + replica.style.setProperty(params.prefixedProperty[i], expectation); + } + } + + target.evaluate = function() { + var target = this; + t.step(function() { + window.CSS && assert_true(CSS.supports(params.property, expectation)); + var value = getComputedStyle(target).getPropertyValue(params.property); + var property = params.property; + if (params.prefixedProperty) { + var i = 0; + while (i < params.prefixedProperty.length && !value) { + property = params.prefixedProperty[i++]; + value = getComputedStyle(target).getPropertyValue(property) + } + } + if (!value) { + assert_false(params.property + ' not supported by this browser'); + } + var originalValue = value; + var parsedExpectation = getComputedStyle(replica).getPropertyValue(property); + assert_equals(normalizeValue(originalValue), normalizeValue(parsedExpectation)); + t.done(); + }); + }; + + var easing = createEasing(fraction); + testCount++; + var keyframes = [{}, {}]; + keyframes[0][convertPropertyToCamelCase(params.property)] = params.from; + keyframes[1][convertPropertyToCamelCase(params.property)] = params.to; + fragmentAttachedListeners.push(function() { + target.animate(keyframes, { + fill: 'forwards', + duration: 1, + easing: easing, + delay: -0.5, + iterations: 0.5, + }); + animationEnded(); + }); + var testFragment = document.createDocumentFragment(); + testFragment.appendChild(targetContainer); + replica && testFragment.appendChild(replicaContainer); + testFragment.appendChild(document.createTextNode('\n')); + return testFragment; + } + + var finished = false; + function finishTest() { + finished = true; + evaluateTests(); + if (afterTestCallback) { + afterTestCallback(); + } + if (window.testRunner) { + var results = document.querySelector('#results'); + document.documentElement.textContent = ''; + document.documentElement.appendChild(results); + testRunner.dumpAsText(); + testRunner.notifyDone(); + } + } + + if (window.testRunner) { + testRunner.waitUntilDone(); + } + + function isLastAnimationEvent() { + return !finished && animationEventCount === testCount; + } + + function animationEnded() { + animationEventCount++; + if (!isLastAnimationEvent()) { + return; + } + finishTest(); + } + + document.documentElement.addEventListener(endEvent, animationEnded); + + if (!window.testRunner) { + setTimeout(function() { + if (finished) { + return; + } + finishTest(); + }, 10000); + } + + window.assertInterpolation = assertInterpolation; + window.afterTest = afterTest; +})(); diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/right-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/right-interpolation.html new file mode 100755 index 0000000000..42c59a367c --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/right-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/shape-image-threshold.html b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-image-threshold.html new file mode 100755 index 0000000000..d461f39fd6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-image-threshold.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/shape-margin.html b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-margin.html new file mode 100755 index 0000000000..28f40f2574 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-margin.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/shape-outside.html b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-outside.html new file mode 100755 index 0000000000..71ebf1c070 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/shape-outside.html @@ -0,0 +1,86 @@ + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/text-decoration-color-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/text-decoration-color-interpolation.html new file mode 100755 index 0000000000..d164103f37 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/text-decoration-color-interpolation.html @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/text-indent-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/text-indent-interpolation.html new file mode 100755 index 0000000000..88df5d61ae --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/text-indent-interpolation.html @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/text-shadow-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/text-shadow-interpolation.html new file mode 100755 index 0000000000..09c659b8e5 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/text-shadow-interpolation.html @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/top-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/top-interpolation.html new file mode 100755 index 0000000000..b2b935ea03 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/top-interpolation.html @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-matrix-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-matrix-interpolation.html new file mode 100755 index 0000000000..7330498c4c --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-matrix-interpolation.html @@ -0,0 +1,133 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-none-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-none-interpolation.html new file mode 100755 index 0000000000..f7518732f1 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-none-interpolation.html @@ -0,0 +1,76 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-origin-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-origin-interpolation.html new file mode 100755 index 0000000000..9b4f7b0a2c --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-origin-interpolation.html @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-perspective-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-perspective-interpolation.html new file mode 100755 index 0000000000..2cd1514cd0 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-perspective-interpolation.html @@ -0,0 +1,75 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-rotate-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-rotate-interpolation.html new file mode 100755 index 0000000000..abfd2c339a --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-rotate-interpolation.html @@ -0,0 +1,140 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-scale-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-scale-interpolation.html new file mode 100755 index 0000000000..c2abd03b82 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-scale-interpolation.html @@ -0,0 +1,206 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-skew-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-skew-interpolation.html new file mode 100755 index 0000000000..ffceae0e21 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-skew-interpolation.html @@ -0,0 +1,62 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/transform-translate-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-translate-interpolation.html new file mode 100755 index 0000000000..f00f24773f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/transform-translate-interpolation.html @@ -0,0 +1,178 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/vertical-align-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/vertical-align-interpolation.html new file mode 100755 index 0000000000..b31d950d7c --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/vertical-align-interpolation.html @@ -0,0 +1,56 @@ + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/viewport-unit-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/viewport-unit-interpolation.html new file mode 100755 index 0000000000..e78969cee9 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/viewport-unit-interpolation.html @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/visibility-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/visibility-interpolation.html new file mode 100755 index 0000000000..677cafb906 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/visibility-interpolation.html @@ -0,0 +1,57 @@ + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/widows-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/widows-interpolation.html new file mode 100755 index 0000000000..d4683c49e6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/widows-interpolation.html @@ -0,0 +1,29 @@ + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/width-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/width-interpolation.html new file mode 100755 index 0000000000..14cdf3ad6f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/width-interpolation.html @@ -0,0 +1,56 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/word-spacing-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/word-spacing-interpolation.html new file mode 100755 index 0000000000..7e43c1c3d7 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/word-spacing-interpolation.html @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/interpolation/z-index-interpolation.html b/scripts/vendor/web-animations-js/test/blink/interpolation/z-index-interpolation.html new file mode 100755 index 0000000000..663182a466 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/interpolation/z-index-interpolation.html @@ -0,0 +1,68 @@ + + + + + +
+ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/keyframe-properties.html b/scripts/vendor/web-animations-js/test/blink/keyframe-properties.html new file mode 100755 index 0000000000..6963ca07fb --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/keyframe-properties.html @@ -0,0 +1,53 @@ + +Web Animations API: Keyframe Property tests + + +
+
+ diff --git a/scripts/vendor/web-animations-js/test/blink/keyframes-with-null-offsets.html b/scripts/vendor/web-animations-js/test/blink/keyframes-with-null-offsets.html new file mode 100755 index 0000000000..753222dd9f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/keyframes-with-null-offsets.html @@ -0,0 +1,41 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/out-of-order-keyframes.html b/scripts/vendor/web-animations-js/test/blink/out-of-order-keyframes.html new file mode 100755 index 0000000000..15db42c8c9 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/out-of-order-keyframes.html @@ -0,0 +1,26 @@ + +Web Animations API: Out of order Keyframe tests + + +
+
+ diff --git a/scripts/vendor/web-animations-js/test/blink/resources/blue-100.png b/scripts/vendor/web-animations-js/test/blink/resources/blue-100.png new file mode 100755 index 0000000000..f578ae7253 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/blink/resources/blue-100.png differ diff --git a/scripts/vendor/web-animations-js/test/blink/resources/green-100.png b/scripts/vendor/web-animations-js/test/blink/resources/green-100.png new file mode 100755 index 0000000000..e45bbbe5c5 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/blink/resources/green-100.png differ diff --git a/scripts/vendor/web-animations-js/test/blink/resources/green-20.png b/scripts/vendor/web-animations-js/test/blink/resources/green-20.png new file mode 100755 index 0000000000..738d1db846 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/blink/resources/green-20.png differ diff --git a/scripts/vendor/web-animations-js/test/blink/resources/keyframes-test.js b/scripts/vendor/web-animations-js/test/blink/resources/keyframes-test.js new file mode 100755 index 0000000000..c6f01099e1 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/resources/keyframes-test.js @@ -0,0 +1,33 @@ +(function(){ +'use strict' + +function createElement() { + var element = document.createElement('div'); + element.style.position = 'absolute'; + document.documentElement.appendChild(element); + return element; +} + +function heldTiming(progress) { + return { + duration: 1000, + fill: 'forwards', + delay: -progress * 1000, + }; +} + +function assertAnimationStyles(keyframes, expectations, description) { + for (var progress in expectations) { + var element = createElement(); + element.animate(keyframes, heldTiming(progress)); + + var computedStyle = getComputedStyle(element); + for (var property in expectations[progress]) { + assert_equals(computedStyle[property], expectations[progress][property], + property + ' at ' + (progress * 100) + '%' + (description ? ' ' + description : '')); + } + } +} + +window.assertAnimationStyles = assertAnimationStyles; +})(); diff --git a/scripts/vendor/web-animations-js/test/blink/resources/stripes-100.png b/scripts/vendor/web-animations-js/test/blink/resources/stripes-100.png new file mode 100755 index 0000000000..cfb6980439 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/blink/resources/stripes-100.png differ diff --git a/scripts/vendor/web-animations-js/test/blink/resources/stripes-20.png b/scripts/vendor/web-animations-js/test/blink/resources/stripes-20.png new file mode 100755 index 0000000000..de30887ea3 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/blink/resources/stripes-20.png differ diff --git a/scripts/vendor/web-animations-js/test/blink/same-offset-keyframes.html b/scripts/vendor/web-animations-js/test/blink/same-offset-keyframes.html new file mode 100755 index 0000000000..163fc019aa --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/same-offset-keyframes.html @@ -0,0 +1,52 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/simple-keyframes.html b/scripts/vendor/web-animations-js/test/blink/simple-keyframes.html new file mode 100755 index 0000000000..59e06e70ce --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/simple-keyframes.html @@ -0,0 +1,45 @@ + + + + + diff --git a/scripts/vendor/web-animations-js/test/blink/testharness/testharness.css b/scripts/vendor/web-animations-js/test/blink/testharness/testharness.css new file mode 100755 index 0000000000..3967004bb2 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/testharness/testharness.css @@ -0,0 +1,107 @@ +html { + font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans; +} + +#log .warning, +#log .warning a { + color: black; + background: yellow; +} + +#log .error, +#log .error a { + color: white; + background: red; +} + +#log pre { + border: 1px solid black; + padding: 1em; +} + +section#summary { + margin-bottom:1em; +} + +table#results { + border-collapse:collapse; + table-layout:fixed; + width:100%; +} + +table#results th:first-child, +table#results td:first-child { + width:4em; +} + +table#results th:last-child, +table#results td:last-child { + width:50%; +} + +table#results.assertions th:last-child, +table#results.assertions td:last-child { + width:35%; +} + +table#results th { + padding:0; + padding-bottom:0.5em; + border-bottom:medium solid black; +} + +table#results td { + padding:1em; + padding-bottom:0.5em; + border-bottom:thin solid black; +} + +tr.pass > td:first-child { + color:green; +} + +tr.fail > td:first-child { + color:red; +} + +tr.timeout > td:first-child { + color:red; +} + +tr.notrun > td:first-child { + color:blue; +} + +.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child { + font-variant:small-caps; +} + +table#results span { + display:block; +} + +table#results span.expected { + font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace; + white-space:pre; +} + +table#results span.actual { + font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace; + white-space:pre; +} + +span.ok { + color:green; +} + +tr.error { + color:red; +} + +span.timeout { + color:red; +} + +span.ok, span.timeout, span.error { + font-variant:small-caps; +} \ No newline at end of file diff --git a/scripts/vendor/web-animations-js/test/blink/testharness/testharness.js b/scripts/vendor/web-animations-js/test/blink/testharness/testharness.js new file mode 100755 index 0000000000..5bac9dc28f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/testharness/testharness.js @@ -0,0 +1,1926 @@ +/*global self*/ +/*jshint latedef: nofunc*/ +/* +Distributed under both the W3C Test Suite License [1] and the W3C +3-clause BSD License [2]. To contribute to a W3C Test Suite, see the +policies and contribution forms [3]. + +[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license +[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license +[3] http://www.w3.org/2004/10/27-testcases +*/ + +/* Documentation is in docs/api.md */ + +(function () +{ + var debug = false; + // default timeout is 10 seconds, test can override if needed + var settings = { + output:true, + harness_timeout:{ + "normal":10000, + "long":60000 + }, + test_timeout:null + }; + + var xhtml_ns = "http://www.w3.org/1999/xhtml"; + + // script_prefix is used by Output.prototype.show_results() to figure out + // where to get testharness.css from. It's enclosed in an extra closure to + // not pollute the library's namespace with variables like "src". + var script_prefix = null; + (function () + { + var scripts = document.getElementsByTagName("script"); + for (var i = 0; i < scripts.length; i++) { + var src; + if (scripts[i].src) { + src = scripts[i].src; + } else if (scripts[i].href) { + //SVG case + src = scripts[i].href.baseVal; + } + + if (src && src.slice(src.length - "testharness.js".length) === "testharness.js") { + script_prefix = src.slice(0, src.length - "testharness.js".length); + break; + } + } + })(); + + /* + * API functions + */ + + var name_counter = 0; + function next_default_name() + { + //Don't use document.title to work around an Opera bug in XHTML documents + var title = document.getElementsByTagName("title")[0]; + var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled"; + var suffix = name_counter > 0 ? " " + name_counter : ""; + name_counter++; + return prefix + suffix; + } + + function test(func, name, properties) + { + var test_name = name ? name : next_default_name(); + properties = properties ? properties : {}; + var test_obj = new Test(test_name, properties); + test_obj.step(func, test_obj, test_obj); + if (test_obj.phase === test_obj.phases.STARTED) { + test_obj.done(); + } + } + + function async_test(func, name, properties) + { + if (typeof func !== "function") { + properties = name; + name = func; + func = null; + } + var test_name = name ? name : next_default_name(); + properties = properties ? properties : {}; + var test_obj = new Test(test_name, properties); + if (func) { + test_obj.step(func, test_obj, test_obj); + } + return test_obj; + } + + function setup(func_or_properties, maybe_properties) + { + var func = null; + var properties = {}; + if (arguments.length === 2) { + func = func_or_properties; + properties = maybe_properties; + } else if (func_or_properties instanceof Function) { + func = func_or_properties; + } else { + properties = func_or_properties; + } + tests.setup(func, properties); + output.setup(properties); + } + + function done() { + if (tests.tests.length === 0) { + tests.set_file_is_test(); + } + if (tests.file_is_test) { + tests.tests[0].done(); + } + tests.end_wait(); + } + + function generate_tests(func, args, properties) { + forEach(args, function(x, i) + { + var name = x[0]; + test(function() + { + func.apply(this, x.slice(1)); + }, + name, + Array.isArray(properties) ? properties[i] : properties); + }); + } + + function on_event(object, event, callback) + { + object.addEventListener(event, callback, false); + } + + expose(test, 'test'); + expose(async_test, 'async_test'); + expose(generate_tests, 'generate_tests'); + expose(setup, 'setup'); + expose(done, 'done'); + expose(on_event, 'on_event'); + + /* + * Return a string truncated to the given length, with ... added at the end + * if it was longer. + */ + function truncate(s, len) + { + if (s.length > len) { + return s.substring(0, len - 3) + "..."; + } + return s; + } + + /* + * Return true if object is probably a Node object. + */ + function is_node(object) + { + // I use duck-typing instead of instanceof, because + // instanceof doesn't work if the node is from another window (like an + // iframe's contentWindow): + // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295 + if ("nodeType" in object && + "nodeName" in object && + "nodeValue" in object && + "childNodes" in object) { + try { + object.nodeType; + } catch (e) { + // The object is probably Node.prototype or another prototype + // object that inherits from it, and not a Node instance. + return false; + } + return true; + } + return false; + } + + /* + * Convert a value to a nice, human-readable string + */ + function format_value(val, seen) + { + if (!seen) { + seen = []; + } + if (typeof val === "object" && val !== null) { + if (seen.indexOf(val) >= 0) { + return "[...]"; + } + seen.push(val); + } + if (Array.isArray(val)) { + return "[" + val.map(function(x) {return format_value(x, seen);}).join(", ") + "]"; + } + + switch (typeof val) { + case "string": + val = val.replace("\\", "\\\\"); + for (var i = 0; i < 32; i++) { + var replace = "\\"; + switch (i) { + case 0: replace += "0"; break; + case 1: replace += "x01"; break; + case 2: replace += "x02"; break; + case 3: replace += "x03"; break; + case 4: replace += "x04"; break; + case 5: replace += "x05"; break; + case 6: replace += "x06"; break; + case 7: replace += "x07"; break; + case 8: replace += "b"; break; + case 9: replace += "t"; break; + case 10: replace += "n"; break; + case 11: replace += "v"; break; + case 12: replace += "f"; break; + case 13: replace += "r"; break; + case 14: replace += "x0e"; break; + case 15: replace += "x0f"; break; + case 16: replace += "x10"; break; + case 17: replace += "x11"; break; + case 18: replace += "x12"; break; + case 19: replace += "x13"; break; + case 20: replace += "x14"; break; + case 21: replace += "x15"; break; + case 22: replace += "x16"; break; + case 23: replace += "x17"; break; + case 24: replace += "x18"; break; + case 25: replace += "x19"; break; + case 26: replace += "x1a"; break; + case 27: replace += "x1b"; break; + case 28: replace += "x1c"; break; + case 29: replace += "x1d"; break; + case 30: replace += "x1e"; break; + case 31: replace += "x1f"; break; + } + val = val.replace(RegExp(String.fromCharCode(i), "g"), replace); + } + return '"' + val.replace(/"/g, '\\"') + '"'; + case "boolean": + case "undefined": + return String(val); + case "number": + // In JavaScript, -0 === 0 and String(-0) == "0", so we have to + // special-case. + if (val === -0 && 1/val === -Infinity) { + return "-0"; + } + return String(val); + case "object": + if (val === null) { + return "null"; + } + + // Special-case Node objects, since those come up a lot in my tests. I + // ignore namespaces. + if (is_node(val)) { + switch (val.nodeType) { + case Node.ELEMENT_NODE: + var ret = "<" + val.localName; + for (var i = 0; i < val.attributes.length; i++) { + ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"'; + } + ret += ">" + val.innerHTML + ""; + return "Element node " + truncate(ret, 60); + case Node.TEXT_NODE: + return 'Text node "' + truncate(val.data, 60) + '"'; + case Node.PROCESSING_INSTRUCTION_NODE: + return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60)); + case Node.COMMENT_NODE: + return "Comment node "; + case Node.DOCUMENT_NODE: + return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + case Node.DOCUMENT_TYPE_NODE: + return "DocumentType node"; + case Node.DOCUMENT_FRAGMENT_NODE: + return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + default: + return "Node object of unknown type"; + } + } + + /* falls through */ + default: + return typeof val + ' "' + truncate(String(val), 60) + '"'; + } + } + expose(format_value, "format_value"); + + /* + * Assertions + */ + + function assert_true(actual, description) + { + assert(actual === true, "assert_true", description, + "expected true got ${actual}", {actual:actual}); + } + expose(assert_true, "assert_true"); + + function assert_false(actual, description) + { + assert(actual === false, "assert_false", description, + "expected false got ${actual}", {actual:actual}); + } + expose(assert_false, "assert_false"); + + function same_value(x, y) { + if (y !== y) { + //NaN case + return x !== x; + } + if (x === 0 && y === 0) { + //Distinguish +0 and -0 + return 1/x === 1/y; + } + return x === y; + } + + function assert_equals(actual, expected, description) + { + /* + * Test if two primitives are equal or two objects + * are the same object + */ + if (typeof actual != typeof expected) { + assert(false, "assert_equals", description, + "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}", + {expected:expected, actual:actual}); + return; + } + assert(same_value(actual, expected), "assert_equals", description, + "expected ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_equals, "assert_equals"); + + function assert_not_equals(actual, expected, description) + { + /* + * Test if two primitives are unequal or two objects + * are different objects + */ + assert(!same_value(actual, expected), "assert_not_equals", description, + "got disallowed value ${actual}", + {actual:actual}); + } + expose(assert_not_equals, "assert_not_equals"); + + function assert_in_array(actual, expected, description) + { + assert(expected.indexOf(actual) != -1, "assert_in_array", description, + "value ${actual} not in array ${expected}", + {actual:actual, expected:expected}); + } + expose(assert_in_array, "assert_in_array"); + + function assert_object_equals(actual, expected, description) + { + //This needs to be improved a great deal + function check_equal(actual, expected, stack) + { + stack.push(actual); + + var p; + for (p in actual) { + assert(expected.hasOwnProperty(p), "assert_object_equals", description, + "unexpected property ${p}", {p:p}); + + if (typeof actual[p] === "object" && actual[p] !== null) { + if (stack.indexOf(actual[p]) === -1) { + check_equal(actual[p], expected[p], stack); + } + } else { + assert(same_value(actual[p], expected[p]), "assert_object_equals", description, + "property ${p} expected ${expected} got ${actual}", + {p:p, expected:expected, actual:actual}); + } + } + for (p in expected) { + assert(actual.hasOwnProperty(p), + "assert_object_equals", description, + "expected property ${p} missing", {p:p}); + } + stack.pop(); + } + check_equal(actual, expected, []); + } + expose(assert_object_equals, "assert_object_equals"); + + function assert_array_equals(actual, expected, description) + { + assert(actual.length === expected.length, + "assert_array_equals", description, + "lengths differ, expected ${expected} got ${actual}", + {expected:expected.length, actual:actual.length}); + + for (var i = 0; i < actual.length; i++) { + assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i), + "assert_array_equals", description, + "property ${i}, property expected to be $expected but was $actual", + {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing", + actual:actual.hasOwnProperty(i) ? "present" : "missing"}); + assert(same_value(expected[i], actual[i]), + "assert_array_equals", description, + "property ${i}, expected ${expected} but got ${actual}", + {i:i, expected:expected[i], actual:actual[i]}); + } + } + expose(assert_array_equals, "assert_array_equals"); + + function assert_approx_equals(actual, expected, epsilon, description) + { + /* + * Test if two primitive numbers are equal withing +/- epsilon + */ + assert(typeof actual === "number", + "assert_approx_equals", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(Math.abs(actual - expected) <= epsilon, + "assert_approx_equals", description, + "expected ${expected} +/- ${epsilon} but got ${actual}", + {expected:expected, actual:actual, epsilon:epsilon}); + } + expose(assert_approx_equals, "assert_approx_equals"); + + function assert_less_than(actual, expected, description) + { + /* + * Test if a primitive number is less than another + */ + assert(typeof actual === "number", + "assert_less_than", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual < expected, + "assert_less_than", description, + "expected a number less than ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_less_than, "assert_less_than"); + + function assert_greater_than(actual, expected, description) + { + /* + * Test if a primitive number is greater than another + */ + assert(typeof actual === "number", + "assert_greater_than", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual > expected, + "assert_greater_than", description, + "expected a number greater than ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_greater_than, "assert_greater_than"); + + function assert_less_than_equal(actual, expected, description) + { + /* + * Test if a primitive number is less than or equal to another + */ + assert(typeof actual === "number", + "assert_less_than_equal", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual <= expected, + "assert_less_than", description, + "expected a number less than or equal to ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_less_than_equal, "assert_less_than_equal"); + + function assert_greater_than_equal(actual, expected, description) + { + /* + * Test if a primitive number is greater than or equal to another + */ + assert(typeof actual === "number", + "assert_greater_than_equal", description, + "expected a number but got a ${type_actual}", + {type_actual:typeof actual}); + + assert(actual >= expected, + "assert_greater_than_equal", description, + "expected a number greater than or equal to ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_greater_than_equal, "assert_greater_than_equal"); + + function assert_regexp_match(actual, expected, description) { + /* + * Test if a string (actual) matches a regexp (expected) + */ + assert(expected.test(actual), + "assert_regexp_match", description, + "expected ${expected} but got ${actual}", + {expected:expected, actual:actual}); + } + expose(assert_regexp_match, "assert_regexp_match"); + + function assert_class_string(object, class_string, description) { + assert_equals({}.toString.call(object), "[object " + class_string + "]", + description); + } + expose(assert_class_string, "assert_class_string"); + + + function _assert_own_property(name) { + return function(object, property_name, description) + { + assert(object.hasOwnProperty(property_name), + name, description, + "expected property ${p} missing", {p:property_name}); + }; + } + expose(_assert_own_property("assert_exists"), "assert_exists"); + expose(_assert_own_property("assert_own_property"), "assert_own_property"); + + function assert_not_exists(object, property_name, description) + { + assert(!object.hasOwnProperty(property_name), + "assert_not_exists", description, + "unexpected property ${p} found", {p:property_name}); + } + expose(assert_not_exists, "assert_not_exists"); + + function _assert_inherits(name) { + return function (object, property_name, description) + { + assert(typeof object === "object", + name, description, + "provided value is not an object"); + + assert("hasOwnProperty" in object, + name, description, + "provided value is an object but has no hasOwnProperty method"); + + assert(!object.hasOwnProperty(property_name), + name, description, + "property ${p} found on object expected in prototype chain", + {p:property_name}); + + assert(property_name in object, + name, description, + "property ${p} not found in prototype chain", + {p:property_name}); + }; + } + expose(_assert_inherits("assert_inherits"), "assert_inherits"); + expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute"); + + function assert_readonly(object, property_name, description) + { + var initial_value = object[property_name]; + try { + //Note that this can have side effects in the case where + //the property has PutForwards + object[property_name] = initial_value + "a"; //XXX use some other value here? + assert(same_value(object[property_name], initial_value), + "assert_readonly", description, + "changing property ${p} succeeded", + {p:property_name}); + } finally { + object[property_name] = initial_value; + } + } + expose(assert_readonly, "assert_readonly"); + + function assert_throws(code, func, description) + { + try { + func.call(this); + assert(false, "assert_throws", description, + "${func} did not throw", {func:func}); + } catch (e) { + if (e instanceof AssertionError) { + throw e; + } + if (code === null) { + return; + } + if (typeof code === "object") { + assert(typeof e == "object" && "name" in e && e.name == code.name, + "assert_throws", description, + "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})", + {func:func, actual:e, actual_name:e.name, + expected:code, + expected_name:code.name}); + return; + } + + var code_name_map = { + INDEX_SIZE_ERR: 'IndexSizeError', + HIERARCHY_REQUEST_ERR: 'HierarchyRequestError', + WRONG_DOCUMENT_ERR: 'WrongDocumentError', + INVALID_CHARACTER_ERR: 'InvalidCharacterError', + NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError', + NOT_FOUND_ERR: 'NotFoundError', + NOT_SUPPORTED_ERR: 'NotSupportedError', + INVALID_STATE_ERR: 'InvalidStateError', + SYNTAX_ERR: 'SyntaxError', + INVALID_MODIFICATION_ERR: 'InvalidModificationError', + NAMESPACE_ERR: 'NamespaceError', + INVALID_ACCESS_ERR: 'InvalidAccessError', + TYPE_MISMATCH_ERR: 'TypeMismatchError', + SECURITY_ERR: 'SecurityError', + NETWORK_ERR: 'NetworkError', + ABORT_ERR: 'AbortError', + URL_MISMATCH_ERR: 'URLMismatchError', + QUOTA_EXCEEDED_ERR: 'QuotaExceededError', + TIMEOUT_ERR: 'TimeoutError', + INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError', + DATA_CLONE_ERR: 'DataCloneError' + }; + + var name = code in code_name_map ? code_name_map[code] : code; + + var name_code_map = { + IndexSizeError: 1, + HierarchyRequestError: 3, + WrongDocumentError: 4, + InvalidCharacterError: 5, + NoModificationAllowedError: 7, + NotFoundError: 8, + NotSupportedError: 9, + InvalidStateError: 11, + SyntaxError: 12, + InvalidModificationError: 13, + NamespaceError: 14, + InvalidAccessError: 15, + TypeMismatchError: 17, + SecurityError: 18, + NetworkError: 19, + AbortError: 20, + URLMismatchError: 21, + QuotaExceededError: 22, + TimeoutError: 23, + InvalidNodeTypeError: 24, + DataCloneError: 25, + + UnknownError: 0, + ConstraintError: 0, + DataError: 0, + TransactionInactiveError: 0, + ReadOnlyError: 0, + VersionError: 0 + }; + + if (!(name in name_code_map)) { + throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()'); + } + + var required_props = { code: name_code_map[name] }; + + if (required_props.code === 0 || + ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException")) { + // New style exception: also test the name property. + required_props.name = name; + } + + //We'd like to test that e instanceof the appropriate interface, + //but we can't, because we don't know what window it was created + //in. It might be an instanceof the appropriate interface on some + //unknown other window. TODO: Work around this somehow? + + assert(typeof e == "object", + "assert_throws", description, + "${func} threw ${e} with type ${type}, not an object", + {func:func, e:e, type:typeof e}); + + for (var prop in required_props) { + assert(typeof e == "object" && prop in e && e[prop] == required_props[prop], + "assert_throws", description, + "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}", + {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]}); + } + } + } + expose(assert_throws, "assert_throws"); + + function assert_unreached(description) { + assert(false, "assert_unreached", description, + "Reached unreachable code"); + } + expose(assert_unreached, "assert_unreached"); + + function assert_any(assert_func, actual, expected_array) + { + var args = [].slice.call(arguments, 3); + var errors = []; + var passed = false; + forEach(expected_array, + function(expected) + { + try { + assert_func.apply(this, [actual, expected].concat(args)); + passed = true; + } catch (e) { + errors.push(e.message); + } + }); + if (!passed) { + throw new AssertionError(errors.join("\n\n")); + } + } + expose(assert_any, "assert_any"); + + function Test(name, properties) + { + if (tests.file_is_test && tests.tests.length) { + throw new Error("Tried to create a test with file_is_test"); + } + this.name = name; + + this.phases = { + INITIAL:0, + STARTED:1, + HAS_RESULT:2, + COMPLETE:3 + }; + this.phase = this.phases.INITIAL; + + this.status = this.NOTRUN; + this.timeout_id = null; + + this.properties = properties; + var timeout = properties.timeout ? properties.timeout : settings.test_timeout; + if (timeout != null) { + this.timeout_length = timeout * tests.timeout_multiplier; + } else { + this.timeout_length = null; + } + + this.message = null; + + this.steps = []; + + this.cleanup_callbacks = []; + + tests.push(this); + } + + Test.statuses = { + PASS:0, + FAIL:1, + TIMEOUT:2, + NOTRUN:3 + }; + + Test.prototype = merge({}, Test.statuses); + + Test.prototype.structured_clone = function() + { + if (!this._structured_clone) { + var msg = this.message; + msg = msg ? String(msg) : msg; + this._structured_clone = merge({ + name:String(this.name), + status:this.status, + message:msg + }, Test.statuses); + } + return this._structured_clone; + }; + + Test.prototype.step = function(func, this_obj) + { + if (this.phase > this.phases.STARTED) { + return; + } + this.phase = this.phases.STARTED; + //If we don't get a result before the harness times out that will be a test timout + this.set_status(this.TIMEOUT, "Test timed out"); + + tests.started = true; + + if (this.timeout_id === null) { + this.set_timeout(); + } + + this.steps.push(func); + + if (arguments.length === 1) { + this_obj = this; + } + + try { + return func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); + } catch (e) { + if (this.phase >= this.phases.HAS_RESULT) { + return; + } + var message = (typeof e === "object" && e !== null) ? e.message : e; + if (typeof e.stack != "undefined" && typeof e.message == "string") { + //Try to make it more informative for some exceptions, at least + //in Gecko and WebKit. This results in a stack dump instead of + //just errors like "Cannot read property 'parentNode' of null" + //or "root is null". Makes it a lot longer, of course. + message += "(stack: " + e.stack + ")"; + } + this.set_status(this.FAIL, message); + this.phase = this.phases.HAS_RESULT; + this.done(); + } + }; + + Test.prototype.step_func = function(func, this_obj) + { + var test_this = this; + + if (arguments.length === 1) { + this_obj = test_this; + } + + return function() + { + return test_this.step.apply(test_this, [func, this_obj].concat( + Array.prototype.slice.call(arguments))); + }; + }; + + Test.prototype.step_func_done = function(func, this_obj) + { + var test_this = this; + + if (arguments.length === 1) { + this_obj = test_this; + } + + return function() + { + if (func) { + test_this.step.apply(test_this, [func, this_obj].concat( + Array.prototype.slice.call(arguments))); + } + test_this.done(); + }; + }; + + Test.prototype.unreached_func = function(description) + { + return this.step_func(function() { + assert_unreached(description); + }); + }; + + Test.prototype.add_cleanup = function(callback) { + this.cleanup_callbacks.push(callback); + }; + + Test.prototype.force_timeout = function() { + this.set_status(this.TIMEOUT); + this.phase = this.phases.HAS_RESULT; + } + + Test.prototype.set_timeout = function() + { + if (this.timeout_length !== null) { + var this_obj = this; + this.timeout_id = setTimeout(function() + { + this_obj.timeout(); + }, this.timeout_length); + } + }; + + Test.prototype.set_status = function(status, message) + { + this.status = status; + this.message = message; + }; + + Test.prototype.timeout = function() + { + this.timeout_id = null; + this.set_status(this.TIMEOUT, "Test timed out"); + this.phase = this.phases.HAS_RESULT; + this.done(); + }; + + Test.prototype.done = function() + { + if (this.phase == this.phases.COMPLETE) { + return; + } + + if (this.phase <= this.phases.STARTED) { + this.set_status(this.PASS, null); + } + + if (this.status == this.NOTRUN) { + alert(this.phase); + } + + this.phase = this.phases.COMPLETE; + + clearTimeout(this.timeout_id); + tests.result(this); + this.cleanup(); + }; + + Test.prototype.cleanup = function() { + forEach(this.cleanup_callbacks, + function(cleanup_callback) { + cleanup_callback(); + }); + }; + + /* + * Harness + */ + + function TestsStatus() + { + this.status = null; + this.message = null; + } + + TestsStatus.statuses = { + OK:0, + ERROR:1, + TIMEOUT:2 + }; + + TestsStatus.prototype = merge({}, TestsStatus.statuses); + + TestsStatus.prototype.structured_clone = function() + { + if (!this._structured_clone) { + var msg = this.message; + msg = msg ? String(msg) : msg; + this._structured_clone = merge({ + status:this.status, + message:msg + }, TestsStatus.statuses); + } + return this._structured_clone; + }; + + function Tests() + { + this.tests = []; + this.num_pending = 0; + + this.phases = { + INITIAL:0, + SETUP:1, + HAVE_TESTS:2, + HAVE_RESULTS:3, + COMPLETE:4 + }; + this.phase = this.phases.INITIAL; + + this.properties = {}; + + //All tests can't be done until the load event fires + this.all_loaded = false; + this.wait_for_finish = false; + this.processing_callbacks = false; + + this.allow_uncaught_exception = false; + + this.file_is_test = false; + + this.timeout_multiplier = 1; + this.timeout_length = this.get_timeout(); + this.timeout_id = null; + + this.start_callbacks = []; + this.test_done_callbacks = []; + this.all_done_callbacks = []; + + this.status = new TestsStatus(); + + var this_obj = this; + + on_event(window, "load", + function() + { + this_obj.all_loaded = true; + if (this_obj.all_done()) + { + this_obj.complete(); + } + }); + + this.set_timeout(); + } + + Tests.prototype.setup = function(func, properties) + { + if (this.phase >= this.phases.HAVE_RESULTS) { + return; + } + + if (this.phase < this.phases.SETUP) { + this.phase = this.phases.SETUP; + } + + this.properties = properties; + + for (var p in properties) { + if (properties.hasOwnProperty(p)) { + var value = properties[p]; + if (p == "allow_uncaught_exception") { + this.allow_uncaught_exception = value; + } else if (p == "explicit_done" && value) { + this.wait_for_finish = true; + } else if (p == "explicit_timeout" && value) { + this.timeout_length = null; + if (this.timeout_id) + { + clearTimeout(this.timeout_id); + } + } else if (p == "timeout_multiplier") { + this.timeout_multiplier = value; + } + } + } + + if (func) { + try { + func(); + } catch (e) { + this.status.status = this.status.ERROR; + this.status.message = String(e); + } + } + this.set_timeout(); + }; + + Tests.prototype.set_file_is_test = function() { + if (this.tests.length > 0) { + throw new Error("Tried to set file as test after creating a test"); + } + this.wait_for_finish = true; + this.file_is_test = true; + // Create the test, which will add it to the list of tests + async_test(); + }; + + Tests.prototype.get_timeout = function() { + var metas = document.getElementsByTagName("meta"); + for (var i = 0; i < metas.length; i++) { + if (metas[i].name == "timeout") { + if (metas[i].content == "long") { + return settings.harness_timeout.long; + } + break; + } + } + return settings.harness_timeout.normal; + }; + + Tests.prototype.set_timeout = function() { + var this_obj = this; + clearTimeout(this.timeout_id); + if (this.timeout_length !== null) { + this.timeout_id = setTimeout(function() { + this_obj.timeout(); + }, this.timeout_length); + } + }; + + Tests.prototype.timeout = function() { + if (this.status.status === null) { + this.status.status = this.status.TIMEOUT; + } + this.complete(); + }; + + Tests.prototype.end_wait = function() + { + this.wait_for_finish = false; + if (this.all_done()) { + this.complete(); + } + }; + + Tests.prototype.push = function(test) + { + if (this.phase < this.phases.HAVE_TESTS) { + this.start(); + } + this.num_pending++; + this.tests.push(test); + }; + + Tests.prototype.all_done = function() { + return (this.tests.length > 0 && this.all_loaded && this.num_pending === 0 && + !this.wait_for_finish && !this.processing_callbacks); + }; + + Tests.prototype.start = function() { + this.phase = this.phases.HAVE_TESTS; + this.notify_start(); + }; + + Tests.prototype.notify_start = function() { + var this_obj = this; + forEach (this.start_callbacks, + function(callback) + { + callback(this_obj.properties); + }); + forEach_windows( + function(w, is_same_origin) + { + if (is_same_origin && w.start_callback) { + try { + w.start_callback(this_obj.properties); + } catch (e) { + if (debug) { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) { + w.postMessage({ + type: "start", + properties: this_obj.properties + }, "*"); + } + }); + }; + + Tests.prototype.result = function(test) + { + if (this.phase > this.phases.HAVE_RESULTS) { + return; + } + this.phase = this.phases.HAVE_RESULTS; + this.num_pending--; + this.notify_result(test); + }; + + Tests.prototype.notify_result = function(test) { + var this_obj = this; + this.processing_callbacks = true; + forEach(this.test_done_callbacks, + function(callback) + { + callback(test, this_obj); + }); + + forEach_windows( + function(w, is_same_origin) + { + if (is_same_origin && w.result_callback) { + try { + w.result_callback(test); + } catch (e) { + if (debug) { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) { + w.postMessage({ + type: "result", + test: test.structured_clone() + }, "*"); + } + }); + this.processing_callbacks = false; + if (this_obj.all_done()) { + this_obj.complete(); + } + }; + + Tests.prototype.complete = function() { + if (this.phase === this.phases.COMPLETE) { + return; + } + this.phase = this.phases.COMPLETE; + var this_obj = this; + this.tests.forEach( + function(x) + { + if (x.status === x.NOTRUN) { + this_obj.notify_result(x); + x.cleanup(); + } + } + ); + this.notify_complete(); + }; + + Tests.prototype.notify_complete = function() + { + clearTimeout(this.timeout_id); + var this_obj = this; + var tests = map(this_obj.tests, + function(test) + { + return test.structured_clone(); + }); + if (this.status.status === null) { + this.status.status = this.status.OK; + } + + forEach (this.all_done_callbacks, + function(callback) + { + callback(this_obj.tests, this_obj.status); + }); + + forEach_windows( + function(w, is_same_origin) + { + if (is_same_origin && w.completion_callback) { + try { + w.completion_callback(this_obj.tests, this_obj.status); + } catch (e) { + if (debug) { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) { + w.postMessage({ + type: "complete", + tests: tests, + status: this_obj.status.structured_clone() + }, "*"); + } + }); + }; + + var tests = new Tests(); + + addEventListener("error", function(e) { + if (tests.file_is_test) { + var test = tests.tests[0]; + if (test.phase >= test.phases.HAS_RESULT) { + return; + } + var message = e.message; + test.set_status(test.FAIL, message); + test.phase = test.phases.HAS_RESULT; + test.done(); + done(); + } else if (!tests.allow_uncaught_exception) { + tests.status.status = tests.status.ERROR; + tests.status.message = e.message; + } + }); + + function timeout() { + if (tests.timeout_length === null) { + tests.timeout(); + } + } + expose(timeout, 'timeout'); + + function add_start_callback(callback) { + tests.start_callbacks.push(callback); + } + + function add_result_callback(callback) + { + tests.test_done_callbacks.push(callback); + } + + function add_completion_callback(callback) + { + tests.all_done_callbacks.push(callback); + } + + expose(add_start_callback, 'add_start_callback'); + expose(add_result_callback, 'add_result_callback'); + expose(add_completion_callback, 'add_completion_callback'); + + /* + * Output listener + */ + + function Output() { + this.output_document = document; + this.output_node = null; + this.done_count = 0; + this.enabled = settings.output; + this.phase = this.INITIAL; + } + + Output.prototype.INITIAL = 0; + Output.prototype.STARTED = 1; + Output.prototype.HAVE_RESULTS = 2; + Output.prototype.COMPLETE = 3; + + Output.prototype.setup = function(properties) { + if (this.phase > this.INITIAL) { + return; + } + + //If output is disabled in testharnessreport.js the test shouldn't be + //able to override that + this.enabled = this.enabled && (properties.hasOwnProperty("output") ? + properties.output : settings.output); + }; + + Output.prototype.init = function(properties) { + if (this.phase >= this.STARTED) { + return; + } + if (properties.output_document) { + this.output_document = properties.output_document; + } else { + this.output_document = document; + } + this.phase = this.STARTED; + }; + + Output.prototype.resolve_log = function() { + var output_document; + if (typeof this.output_document === "function") { + output_document = this.output_document.apply(undefined); + } else { + output_document = this.output_document; + } + if (!output_document) { + return; + } + var node = output_document.getElementById("log"); + if (!node) { + if (!document.body || document.readyState == "loading") { + return; + } + node = output_document.createElement("div"); + node.id = "log"; + output_document.body.appendChild(node); + } + this.output_document = output_document; + this.output_node = node; + }; + + Output.prototype.show_status = function() { + if (this.phase < this.STARTED) { + this.init(); + } + if (!this.enabled) { + return; + } + if (this.phase < this.HAVE_RESULTS) { + this.resolve_log(); + this.phase = this.HAVE_RESULTS; + } + this.done_count++; + if (this.output_node) { + if (this.done_count < 100 || + (this.done_count < 1000 && this.done_count % 100 === 0) || + this.done_count % 1000 === 0) { + this.output_node.textContent = "Running, " + + this.done_count + " complete, " + + tests.num_pending + " remain"; + } + } + }; + + Output.prototype.show_results = function (tests, harness_status) { + if (this.phase >= this.COMPLETE) { + return; + } + if (!this.enabled) { + return; + } + if (!this.output_node) { + this.resolve_log(); + } + this.phase = this.COMPLETE; + + var log = this.output_node; + if (!log) { + return; + } + var output_document = this.output_document; + + while (log.lastChild) { + log.removeChild(log.lastChild); + } + + if (script_prefix != null) { + var stylesheet = output_document.createElementNS(xhtml_ns, "link"); + stylesheet.setAttribute("rel", "stylesheet"); + stylesheet.setAttribute("href", script_prefix + "testharness.css"); + var heads = output_document.getElementsByTagName("head"); + if (heads.length) { + heads[0].appendChild(stylesheet); + } + } + + var status_text_harness = {}; + status_text_harness[harness_status.OK] = "OK"; + status_text_harness[harness_status.ERROR] = "Error"; + status_text_harness[harness_status.TIMEOUT] = "Timeout"; + + var status_text = {}; + status_text[Test.prototype.PASS] = "Pass"; + status_text[Test.prototype.FAIL] = "Fail"; + status_text[Test.prototype.TIMEOUT] = "Timeout"; + status_text[Test.prototype.NOTRUN] = "Not Run"; + + var status_number = {}; + forEach(tests, + function(test) { + var status = status_text[test.status]; + if (status_number.hasOwnProperty(status)) { + status_number[status] += 1; + } else { + status_number[status] = 1; + } + }); + + function status_class(status) + { + return status.replace(/\s/g, '').toLowerCase(); + } + + var summary_template = ["section", {"id":"summary"}, + ["h2", {}, "Summary"], + function() + { + + var status = status_text_harness[harness_status.status]; + var rv = [["section", {}, + ["p", {}, + "Harness status: ", + ["span", {"class":status_class(status)}, + status + ], + ] + ]]; + + if (harness_status.status === harness_status.ERROR) { + rv[0].push(["pre", {}, harness_status.message]); + } + return rv; + }, + ["p", {}, "Found ${num_tests} tests"], + function() { + var rv = [["div", {}]]; + var i = 0; + while (status_text.hasOwnProperty(i)) { + if (status_number.hasOwnProperty(status_text[i])) { + var status = status_text[i]; + rv[0].push(["div", {"class":status_class(status)}, + ["label", {}, + ["input", {type:"checkbox", checked:"checked"}], + status_number[status] + " " + status]]); + } + i++; + } + return rv; + }, + ]; + + log.appendChild(render(summary_template, {num_tests:tests.length}, output_document)); + + forEach(output_document.querySelectorAll("section#summary label"), + function(element) + { + on_event(element, "click", + function(e) + { + if (output_document.getElementById("results") === null) { + e.preventDefault(); + return; + } + var result_class = element.parentNode.getAttribute("class"); + var style_element = output_document.querySelector("style#hide-" + result_class); + var input_element = element.querySelector("input"); + if (!style_element && !input_element.checked) { + style_element = output_document.createElementNS(xhtml_ns, "style"); + style_element.id = "hide-" + result_class; + style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}"; + output_document.body.appendChild(style_element); + } else if (style_element && input_element.checked) { + style_element.parentNode.removeChild(style_element); + } + }); + }); + + // This use of innerHTML plus manual escaping is not recommended in + // general, but is necessary here for performance. Using textContent + // on each individual adds tens of seconds of execution time for + // large test suites (tens of thousands of tests). + function escape_html(s) + { + return s.replace(/\&/g, "&") + .replace(/" + + "ResultTest Name" + + (assertions ? "Assertion" : "") + + "Message" + + ""; + for (var i = 0; i < tests.length; i++) { + html += '' + + escape_html(status_text[tests[i].status]) + + "" + + escape_html(tests[i].name) + + "" + + (assertions ? escape_html(get_assertion(tests[i])) + "" : "") + + escape_html(tests[i].message ? tests[i].message : " ") + + ""; + } + html += ""; + try { + log.lastChild.innerHTML = html; + } catch (e) { + log.appendChild(document.createElementNS(xhtml_ns, "p")) + .textContent = "Setting innerHTML for the log threw an exception."; + log.appendChild(document.createElementNS(xhtml_ns, "pre")) + .textContent = html; + } + }; + + var output = new Output(); + add_start_callback(function (properties) {output.init(properties);}); + add_result_callback(function () {output.show_status();}); + add_completion_callback(function (tests, harness_status) {output.show_results(tests, harness_status);}); + + /* + * Template code + * + * A template is just a javascript structure. An element is represented as: + * + * [tag_name, {attr_name:attr_value}, child1, child2] + * + * the children can either be strings (which act like text nodes), other templates or + * functions (see below) + * + * A text node is represented as + * + * ["{text}", value] + * + * String values have a simple substitution syntax; ${foo} represents a variable foo. + * + * It is possible to embed logic in templates by using a function in a place where a + * node would usually go. The function must either return part of a template or null. + * + * In cases where a set of nodes are required as output rather than a single node + * with children it is possible to just use a list + * [node1, node2, node3] + * + * Usage: + * + * render(template, substitutions) - take a template and an object mapping + * variable names to parameters and return either a DOM node or a list of DOM nodes + * + * substitute(template, substitutions) - take a template and variable mapping object, + * make the variable substitutions and return the substituted template + * + */ + + function is_single_node(template) + { + return typeof template[0] === "string"; + } + + function substitute(template, substitutions) + { + if (typeof template === "function") { + var replacement = template(substitutions); + if (!replacement) { + return null; + } + + return substitute(replacement, substitutions); + } + + if (is_single_node(template)) { + return substitute_single(template, substitutions); + } + + return filter(map(template, function(x) { + return substitute(x, substitutions); + }), function(x) {return x !== null;}); + } + + function substitute_single(template, substitutions) + { + var substitution_re = /\$\{([^ }]*)\}/g; + + function do_substitution(input) { + var components = input.split(substitution_re); + var rv = []; + for (var i = 0; i < components.length; i += 2) { + rv.push(components[i]); + if (components[i + 1]) { + rv.push(String(substitutions[components[i + 1]])); + } + } + return rv; + } + + function substitute_attrs(attrs, rv) + { + rv[1] = {}; + for (var name in template[1]) { + if (attrs.hasOwnProperty(name)) { + var new_name = do_substitution(name).join(""); + var new_value = do_substitution(attrs[name]).join(""); + rv[1][new_name] = new_value; + } + } + } + + function substitute_children(children, rv) + { + for (var i = 0; i < children.length; i++) { + if (children[i] instanceof Object) { + var replacement = substitute(children[i], substitutions); + if (replacement !== null) { + if (is_single_node(replacement)) { + rv.push(replacement); + } else { + extend(rv, replacement); + } + } + } else { + extend(rv, do_substitution(String(children[i]))); + } + } + return rv; + } + + var rv = []; + rv.push(do_substitution(String(template[0])).join("")); + + if (template[0] === "{text}") { + substitute_children(template.slice(1), rv); + } else { + substitute_attrs(template[1], rv); + substitute_children(template.slice(2), rv); + } + + return rv; + } + + function make_dom_single(template, doc) + { + var output_document = doc || document; + var element; + if (template[0] === "{text}") { + element = output_document.createTextNode(""); + for (var i = 1; i < template.length; i++) { + element.data += template[i]; + } + } else { + element = output_document.createElementNS(xhtml_ns, template[0]); + for (var name in template[1]) { + if (template[1].hasOwnProperty(name)) { + element.setAttribute(name, template[1][name]); + } + } + for (var i = 2; i < template.length; i++) { + if (template[i] instanceof Object) { + var sub_element = make_dom(template[i]); + element.appendChild(sub_element); + } else { + var text_node = output_document.createTextNode(template[i]); + element.appendChild(text_node); + } + } + } + + return element; + } + + + + function make_dom(template, substitutions, output_document) + { + if (is_single_node(template)) { + return make_dom_single(template, output_document); + } + + return map(template, function(x) { + return make_dom_single(x, output_document); + }); + } + + function render(template, substitutions, output_document) + { + return make_dom(substitute(template, substitutions), output_document); + } + + /* + * Utility funcions + */ + function assert(expected_true, function_name, description, error, substitutions) + { + if (tests.tests.length === 0) { + tests.set_file_is_test(); + } + if (expected_true !== true) { + var msg = make_message(function_name, description, + error, substitutions); + throw new AssertionError(msg); + } + } + + function AssertionError(message) + { + this.message = message; + } + + AssertionError.prototype.toString = function() { + return this.message; + }; + + function make_message(function_name, description, error, substitutions) + { + for (var p in substitutions) { + if (substitutions.hasOwnProperty(p)) { + substitutions[p] = format_value(substitutions[p]); + } + } + var node_form = substitute(["{text}", "${function_name}: ${description}" + error], + merge({function_name:function_name, + description:(description?description + " ":"")}, + substitutions)); + return node_form.slice(1).join(""); + } + + function filter(array, callable, thisObj) { + var rv = []; + for (var i = 0; i < array.length; i++) { + if (array.hasOwnProperty(i)) { + var pass = callable.call(thisObj, array[i], i, array); + if (pass) { + rv.push(array[i]); + } + } + } + return rv; + } + + function map(array, callable, thisObj) + { + var rv = []; + rv.length = array.length; + for (var i = 0; i < array.length; i++) { + if (array.hasOwnProperty(i)) { + rv[i] = callable.call(thisObj, array[i], i, array); + } + } + return rv; + } + + function extend(array, items) + { + Array.prototype.push.apply(array, items); + } + + function forEach (array, callback, thisObj) + { + for (var i = 0; i < array.length; i++) { + if (array.hasOwnProperty(i)) { + callback.call(thisObj, array[i], i, array); + } + } + } + + function merge(a,b) + { + var rv = {}; + var p; + for (p in a) { + rv[p] = a[p]; + } + for (p in b) { + rv[p] = b[p]; + } + return rv; + } + + function expose(object, name) + { + var components = name.split("."); + var target = window; + for (var i = 0; i < components.length - 1; i++) { + if (!(components[i] in target)) { + target[components[i]] = {}; + } + target = target[components[i]]; + } + target[components[components.length - 1]] = object; + } + + function forEach_windows(callback) { + // Iterate of the the windows [self ... top, opener]. The callback is passed + // two objects, the first one is the windows object itself, the second one + // is a boolean indicating whether or not its on the same origin as the + // current window. + var cache = forEach_windows.result_cache; + if (!cache) { + cache = [[self, true]]; + var w = self; + var i = 0; + var so; + var origins = location.ancestorOrigins; + while (w != w.parent) { + w = w.parent; + // In WebKit, calls to parent windows' properties that aren't on the same + // origin cause an error message to be displayed in the error console but + // don't throw an exception. This is a deviation from the current HTML5 + // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504 + // The problem with WebKit's behavior is that it pollutes the error console + // with error messages that can't be caught. + // + // This issue can be mitigated by relying on the (for now) proprietary + // `location.ancestorOrigins` property which returns an ordered list of + // the origins of enclosing windows. See: + // http://trac.webkit.org/changeset/113945. + if (origins) { + so = (location.origin == origins[i]); + } else { + so = is_same_origin(w); + } + cache.push([w, so]); + i++; + } + w = window.opener; + if (w) { + // window.opener isn't included in the `location.ancestorOrigins` prop. + // We'll just have to deal with a simple check and an error msg on WebKit + // browsers in this case. + cache.push([w, is_same_origin(w)]); + } + forEach_windows.result_cache = cache; + } + + forEach(cache, + function(a) + { + callback.apply(null, a); + }); + } + + function is_same_origin(w) { + try { + 'random_prop' in w; + return true; + } catch (e) { + return false; + } + } + + function supports_post_message(w) + { + var supports; + var type; + // Given IE implements postMessage across nested iframes but not across + // windows or tabs, you can't infer cross-origin communication from the presence + // of postMessage on the current window object only. + // + // Touching the postMessage prop on a window can throw if the window is + // not from the same origin AND post message is not supported in that + // browser. So just doing an existence test here won't do, you also need + // to wrap it in a try..cacth block. + try { + type = typeof w.postMessage; + if (type === "function") { + supports = true; + } + + // IE8 supports postMessage, but implements it as a host object which + // returns "object" as its `typeof`. + else if (type === "object") { + supports = true; + } + + // This is the case where postMessage isn't supported AND accessing a + // window property across origins does NOT throw (e.g. old Safari browser). + else { + supports = false; + } + } catch (e) { + // This is the case where postMessage isn't supported AND accessing a + // window property across origins throws (e.g. old Firefox browser). + supports = false; + } + return supports; + } +})(); +// vim: set expandtab shiftwidth=4 tabstop=4: diff --git a/scripts/vendor/web-animations-js/test/blink/testharness/testharnessreport.js b/scripts/vendor/web-animations-js/test/blink/testharness/testharnessreport.js new file mode 100755 index 0000000000..71f14c1ac5 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/blink/testharness/testharnessreport.js @@ -0,0 +1,409 @@ +/*global add_completion_callback, setup */ +/* + * This file is intended for vendors to implement + * code needed to integrate testharness.js tests with their own test systems. + * + * The default implementation extracts metadata from the tests and validates + * it against the cached version that should be present in the test source + * file. If the cache is not found or is out of sync, source code suitable for + * caching the metadata is optionally generated. + * + * The cached metadata is present for extraction by test processing tools that + * are unable to execute javascript. + * + * Metadata is attached to tests via the properties parameter in the test + * constructor. See testharness.js for details. + * + * Typically test system integration will attach callbacks when each test has + * run, using add_result_callback(callback(test)), or when the whole test file + * has completed, using + * add_completion_callback(callback(tests, harness_status)). + * + * For more documentation about the callback functions and the + * parameters they are called with see testharness.js + */ + + + +var metadata_generator = { + + currentMetadata: {}, + cachedMetadata: false, + metadataProperties: ['help', 'assert', 'author'], + + error: function(message) { + var messageElement = document.createElement('p'); + messageElement.setAttribute('class', 'error'); + this.appendText(messageElement, message); + + var summary = document.getElementById('summary'); + if (summary) { + summary.parentNode.insertBefore(messageElement, summary); + } + else { + document.body.appendChild(messageElement); + } + }, + + /** + * Ensure property value has contact information + */ + validateContact: function(test, propertyName) { + var result = true; + var value = test.properties[propertyName]; + var values = Array.isArray(value) ? value : [value]; + for (var index = 0; index < values.length; index++) { + value = values[index]; + var re = /(\S+)(\s*)<(.*)>(.*)/; + if (! re.test(value)) { + re = /(\S+)(\s+)(http[s]?:\/\/)(.*)/; + if (! re.test(value)) { + this.error('Metadata property "' + propertyName + + '" for test: "' + test.name + + '" must have name and contact information ' + + '("name " or "name http(s)://")'); + result = false; + } + } + } + return result; + }, + + /** + * Extract metadata from test object + */ + extractFromTest: function(test) { + var testMetadata = {}; + // filter out metadata from other properties in test + for (var metaIndex = 0; metaIndex < this.metadataProperties.length; + metaIndex++) { + var meta = this.metadataProperties[metaIndex]; + if (test.properties.hasOwnProperty(meta)) { + if ('author' == meta) { + this.validateContact(test, meta); + } + testMetadata[meta] = test.properties[meta]; + } + } + return testMetadata; + }, + + /** + * Compare cached metadata to extracted metadata + */ + validateCache: function() { + for (var testName in this.currentMetadata) { + if (! this.cachedMetadata.hasOwnProperty(testName)) { + return false; + } + var testMetadata = this.currentMetadata[testName]; + var cachedTestMetadata = this.cachedMetadata[testName]; + delete this.cachedMetadata[testName]; + + for (var metaIndex = 0; metaIndex < this.metadataProperties.length; + metaIndex++) { + var meta = this.metadataProperties[metaIndex]; + if (cachedTestMetadata.hasOwnProperty(meta) && + testMetadata.hasOwnProperty(meta)) { + if (Array.isArray(cachedTestMetadata[meta])) { + if (! Array.isArray(testMetadata[meta])) { + return false; + } + if (cachedTestMetadata[meta].length == + testMetadata[meta].length) { + for (var index = 0; + index < cachedTestMetadata[meta].length; + index++) { + if (cachedTestMetadata[meta][index] != + testMetadata[meta][index]) { + return false; + } + } + } + else { + return false; + } + } + else { + if (Array.isArray(testMetadata[meta])) { + return false; + } + if (cachedTestMetadata[meta] != testMetadata[meta]) { + return false; + } + } + } + else if (cachedTestMetadata.hasOwnProperty(meta) || + testMetadata.hasOwnProperty(meta)) { + return false; + } + } + } + for (var testName in this.cachedMetadata) { + return false; + } + return true; + }, + + appendText: function(elemement, text) { + elemement.appendChild(document.createTextNode(text)); + }, + + jsonifyArray: function(arrayValue, indent) { + var output = '['; + + if (1 == arrayValue.length) { + output += JSON.stringify(arrayValue[0]); + } + else { + for (var index = 0; index < arrayValue.length; index++) { + if (0 < index) { + output += ',\n ' + indent; + } + output += JSON.stringify(arrayValue[index]); + } + } + output += ']'; + return output; + }, + + jsonifyObject: function(objectValue, indent) { + var output = '{'; + var value; + + var count = 0; + for (var property in objectValue) { + ++count; + if (Array.isArray(objectValue[property]) || + ('object' == typeof(value))) { + ++count; + } + } + if (1 == count) { + for (var property in objectValue) { + output += ' "' + property + '": ' + + JSON.stringify(objectValue[property]) + + ' '; + } + } + else { + var first = true; + for (var property in objectValue) { + if (! first) { + output += ','; + } + first = false; + output += '\n ' + indent + '"' + property + '": '; + value = objectValue[property]; + if (Array.isArray(value)) { + output += this.jsonifyArray(value, indent + + ' '.substr(0, 5 + property.length)); + } + else if ('object' == typeof(value)) { + output += this.jsonifyObject(value, indent + ' '); + } + else { + output += JSON.stringify(value); + } + } + if (1 < output.length) { + output += '\n' + indent; + } + } + output += '}'; + return output; + }, + + /** + * Generate javascript source code for captured metadata + * Metadata is in pretty-printed JSON format + */ + generateSource: function() { + var source = + '\n'; + return source; + }, + + /** + * Add element containing metadata source code + */ + addSourceElement: function(event) { + var sourceWrapper = document.createElement('div'); + sourceWrapper.setAttribute('id', 'metadata_source'); + + var instructions = document.createElement('p'); + if (this.cachedMetadata) { + this.appendText(instructions, + 'Replace the existing '); +} else { + document.write(''); +} + +if (window.parent && parent.window.initTestHarness) { + parent.window.initTestHarness(window); +} else { + metadata_generator.setup(); +} + +/* If the parent window has a testharness_properties object, + * we use this to provide the test settings. This is used by the + * default in-browser runner to configure the timeout and the + * rendering of results + */ +try { + if (window.opener && "testharness_properties" in window.opener) { + /* If we pass the testharness_properties object as-is here without + * JSON stringifying and reparsing it, IE fails & emits the message + * "Could not complete the operation due to error 80700019". + */ + setup(JSON.parse(JSON.stringify(window.opener.testharness_properties))); + } +} catch (e) { +} +// vim: set expandtab shiftwidth=4 tabstop=4: diff --git a/scripts/vendor/web-animations-js/test/js/animation-finish-event.js b/scripts/vendor/web-animations-js/test/js/animation-finish-event.js new file mode 100755 index 0000000000..987d010391 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/animation-finish-event.js @@ -0,0 +1,79 @@ +suite('animation-finish-event', function() { + setup(function() { + this.element = document.createElement('div'); + document.documentElement.appendChild(this.element); + this.animation = this.element.animate([], 1000); + }); + teardown(function() { + if (this.element.parent) + this.element.removeChild(this.target); + }); + + test('fire when animation completes', function(done) { + var ready = false; + var fired = false; + var animation = this.animation; + animation.onfinish = function(event) { + assert(ready, 'must not be called synchronously'); + assert.equal(this, animation); + assert.equal(event.target, animation); + assert.equal(event.currentTime, 1000); + assert.equal(event.timelineTime, 1100); + if (fired) + assert(false, 'must not get fired twice'); + fired = true; + done(); + }; + tick(100); + tick(1100); + tick(2100); + ready = true; + }); + + test('fire when reversed animation completes', function(done) { + this.animation.onfinish = function(event) { + assert.equal(event.currentTime, 0); + assert.equal(event.timelineTime, 1001); + done(); + }; + tick(0); + tick(500); + this.animation.reverse(); + tick(501); + tick(1001); + }); + + test('fire after animation is cancelled', function(done) { + this.animation.onfinish = function(event) { + assert.equal(event.currentTime, 0); + assert.equal(event.timelineTime, 1, 'event must be fired on next sample'); + done(); + }; + tick(0); + this.animation.cancel(); + tick(1); + }); + + test('multiple event listeners', function(done) { + var count = 0; + function createHandler(expectedCount) { + return function() { + count++; + assert.equal(count, expectedCount); + }; + } + var toRemove = createHandler(0); + this.animation.addEventListener('finish', createHandler(1)); + this.animation.addEventListener('finish', createHandler(2)); + this.animation.addEventListener('finish', toRemove); + this.animation.addEventListener('finish', createHandler(3)); + this.animation.removeEventListener('finish', toRemove); + this.animation.onfinish = function() { + assert.equal(count, 3); + done(); + }; + tick(0); + this.animation.cancel(); + tick(1000); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/animation.js b/scripts/vendor/web-animations-js/test/js/animation.js new file mode 100755 index 0000000000..aa57d3790d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/animation.js @@ -0,0 +1,536 @@ +suite('animation', function() { + setup(function() { + webAnimations1.timeline._animations = []; + }); + test('zero duration animation works', function() { + tick(90); + var a = document.body.animate([], 0); + tick(100); + assert.equal(a.startTime, 100); + assert.equal(a.currentTime, 0); + }); + test('playing works as expected', function() { + tick(90); + var a = document.body.animate([], 2000); + tick(100); + assert.equal(a.startTime, 100); + assert.equal(a.currentTime, 0); + tick(300); + assert.equal(a.startTime, 100); + assert.equal(a.currentTime, 200); + }); + test('pause at start of play', function() { + tick(90); + var a = document.body.animate([], 2000); + a.pause(); + tick(100); + assert.equal(a.currentTime, 0); + tick(300); + a.play(); + assert.equal(a.currentTime, 0); + tick(310); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 310); + + var a = document.body.animate([], 2000); + a.startTime = -690; + a.pause(); + assert.equal(a.currentTime, null); + tick(700); + a.play(); + tick(701); + assert.equal(a.currentTime, 1000); + tick(800); + assert.equal(a.currentTime, 1099); + assert.equal(a.startTime, -299); + }); + test('pausing works as expected', function() { + tick(190); + var a = document.body.animate([], 3000); + tick(200); + tick(1500); + assert.equal(a.startTime, 200); + assert.equal(a.currentTime, 1300); + a.pause(); + assert.equal(a.startTime, null); + assert.equal(a.currentTime, null); + tick(2500); + assert.equal(a.startTime, null); + assert.equal(a.currentTime, 1300); + a.play(); + tick(2510); + assert.equal(a.startTime, 1210); + assert.equal(a.currentTime, 1300); + tick(3500); + assert.equal(a.startTime, 1210); + assert.equal(a.currentTime, 2290); + }); + test('reversing works as expected', function() { + tick(290); + var a = document.body.animate([], 1000); + tick(300); + assert.equal(a.startTime, 300); + assert.equal(a.currentTime, 0); + tick(600); + assert.equal(a.startTime, 300); + assert.equal(a.currentTime, 300); + assert.equal(a.playbackRate, 1); + a.reverse(); + tick(600); + assert.equal(a.startTime, 900); + assert.equal(a.currentTime, 300); + assert.equal(a.playbackRate, -1); + tick(700); + assert.equal(a.startTime, 900); + assert.equal(a.currentTime, 200); + }); + test('reversing after pausing', function() { + tick(90); + var a = document.body.animate([], 1000); + tick(100); + tick(600); + a.reverse(); + tick(601); + tick(700); + assert.equal(a.startTime, 1101); + assert.equal(a.currentTime, 401); + }); + test('reversing after finishing works as expected', function() { + tick(90); + var a = document.body.animate([], 1000); + tick(100); + tick(1200); + assert.equal(a.finished, true); + assert.equal(a.startTime, 100); + assert.equal(a.currentTime, 1000); + tick(1500); + assert.equal(a.currentTime, 1000); + assert.equal(isTicking(), false); + a.reverse(); + assert.equal(a._startTime, null); + assert.equal(a.currentTime, 1000); + tick(1600); + assert.equal(a.startTime, 2600); + assert.equal(a.currentTime, 1000); + }); + test('playing after finishing works as expected', function() { + tick(90); + var a = document.body.animate([], 1000); + tick(100); + tick(1200); + assert.equal(a.finished, true); + assert.equal(a.startTime, 100); + assert.equal(a.currentTime, 1000); + tick(1500); + assert.equal(a.currentTime, 1000); + assert.equal(isTicking(), false); + a.play(); + assert.equal(a.startTime, null); + assert.equal(a.currentTime, 0); + tick(1600); + assert.equal(a.startTime, 1600); + assert.equal(a.currentTime, 0); + }); + test('limiting works as expected', function() { + tick(390); + var a = document.body.animate([], 1000); + tick(400); + assert.equal(a.startTime, 400); + assert.equal(a.currentTime, 0); + tick(900); + assert.equal(a.startTime, 400); + assert.equal(a.currentTime, 500); + tick(1400); + assert.equal(a.startTime, 400); + assert.equal(a.currentTime, 1000); + tick(1500); + assert.equal(a.startTime, 400); + assert.equal(a.currentTime, 1000); + a.reverse(); + assert.equal(a.playbackRate, -1); + assert.equal(a.currentTime, 1000); + assert.equal(a._startTime, null); + tick(2000); + assert.equal(a.currentTime, 1000); + assert.equal(a.startTime, 3000); + tick(2200); + assert.equal(a.currentTime, 800); + assert.equal(a.startTime, 3000); + tick(3200); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 3000); + tick(3500); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 3000); + }); + test('play after limit works as expected', function() { + tick(490); + var a = document.body.animate([], 2000); + tick(500); + tick(2600); + assert.equal(a.currentTime, 2000); + assert.equal(a.startTime, 500); + assert.equal(a.finished, true); + assert.equal(a.playbackRate, 1); + setTicking(true); + a.play(); + tick(2700); + assert.equal(a.startTime, 2700); + assert.equal(a.currentTime, 0); + assert.equal(a.finished, false); + assert.equal(a.playbackRate, 1); + }); + test('play after limit works as expected (reversed)', function() { + tick(590); + var a = document.body.animate([], 3000); + tick(600); + tick(700); + a.reverse(); + tick(701); + tick(900); + assert.equal(a.startTime, 801); + assert.equal(a.currentTime, 0); + assert.equal(a.finished, true); + assert.equal(a.playbackRate, -1); + setTicking(true); + a.play(); + tick(1000); + assert.equal(a.startTime, 4000); + assert.equal(a.currentTime, 3000); + assert.equal(a.finished, false); + assert.equal(a.playbackRate, -1); + }); + test('seeking works as expected', function() { + tick(690); + var a = document.body.animate([], 2000); + tick(700); + tick(900); + assert.equal(a.currentTime, 200); + a.currentTime = 600; + assert.equal(a.currentTime, 600); + assert.equal(a.startTime, 300); + a.reverse(); + tick(1000); + assert.equal(a.startTime, 1600); + a.currentTime = 300; + assert.equal(a.currentTime, 300); + assert.equal(a.startTime, 1300); + }); + test('seeking while paused works as expected', function() { + tick(790); + var a = document.body.animate([], 1000); + tick(800); + tick(1000); + a.pause(); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + assert.equal(a.paused, true); + a.currentTime = 500; + assert.equal(a.startTime, null); + assert.equal(a.paused, true); + }); + test('setting start time while paused is ignored', function() { + tick(900); + var a = document.body.animate([], 1234); + a.pause(); + assert.equal(a.startTime, null); + assert.equal(a.currentTime, null); + a.startTime = 2232; + assert.equal(a.startTime, null); + assert.equal(a.currentTime, null); + }); + test('setting playbackRate sets startTime to null unless the playbackRate is not changing, ' + + 'preserves the current time', function() { + tick(0); + var a = document.body.animate([], 1000); + tick(1); + tick(11); + assert.equal(a.currentTime, 10); + + a.playbackRate = 2; + assert.equal(a.playbackRate, 2); + assert.equal(a.currentTime, 10); + assert.equal(a.startTime, null); + tick(12); + assert.equal(a.currentTime, 10); + assert.equal(a.startTime, 7); + tick(22); + assert.equal(a.currentTime, 30); + assert.equal(a.startTime, 7); + + a.playbackRate = -1; + assert.equal(a.playbackRate, -1); + assert.equal(a.currentTime, 30); + assert.equal(a.startTime, null); + tick(23); + assert.equal(a.currentTime, 30); + assert.equal(a.startTime, 53); + tick(33); + assert.equal(a.currentTime, 20); + assert.equal(a.startTime, 53); + + a.playbackRate = -1; + assert.equal(a.playbackRate, -1); + assert.equal(a.currentTime, 20); + assert.equal(a.startTime, 53); + tick(43); + assert.equal(a.currentTime, 10); + assert.equal(a.startTime, 53); + } + ); + test('setting playbackRate puts animation back into effect if it is not finished', function() { + tick(0); + var a = document.body.animate([], 1000); + assert.equal(a.playbackRate, 1); + tick(1); + tick(1002); + assert.equal(a.currentTime, 1000); + + a.playbackRate = -1; + assert.equal(a.playbackRate, -1); + assert.equal(a.currentTime, 1000); + tick(1003); + assert.equal(a.currentTime, 1000); + tick(1503); + assert.equal(a.currentTime, 500); + }); + test('setting playbackRate does not put animation back into effect if it is finished', function() { + tick(0); + var a = document.body.animate([], 1000); + assert.equal(a.playbackRate, 1); + tick(1); + tick(1002); + assert.equal(a.currentTime, 1000); + assert.equal(a.startTime, 1); + + a.playbackRate = 0.5; + assert.equal(a.playbackRate, 0.5); + assert.equal(a.currentTime, 1000); + assert.equal(a.startTime, null); + tick(1003); + assert.equal(a.currentTime, 1000); + assert.equal(a.startTime, -997); + tick(1503); + assert.equal(a.currentTime, 1000); + assert.equal(a.startTime, -997); + }); + test('finishing works as expected', function() { + tick(1000); + var a = document.body.animate([], 2000); + a.finish(); + assert.equal(a.startTime, 0); + assert.equal(a.currentTime, 2000); + a.reverse(); + a.finish(); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 2000); + tick(2000); + }); + test('cancelling clears all effects', function() { + tick(0); + var target = document.createElement('div'); + document.documentElement.appendChild(target); + var animation = target.animate([{marginLeft: '50px'}, {marginLeft: '50px'}], 1000); + tick(10); + tick(110); + assert.equal(getComputedStyle(target).marginLeft, '50px'); + animation.cancel(); + // getComputedStyle forces a tick. + assert.equal(getComputedStyle(target).marginLeft, '0px'); + assert.deepEqual(webAnimations1.timeline._animations, []); + tick(120); + assert.equal(getComputedStyle(target).marginLeft, '0px'); + assert.deepEqual(webAnimations1.timeline._animations, []); + document.documentElement.removeChild(target); + }); + test('startTime is set on first tick if timeline hasn\'t started', function() { + webAnimations1.timeline.currentTime = undefined; + var a = document.body.animate([], 1000); + tick(0); + tick(100); + assert.equal(a.startTime, 0); + }); + test('animations which are finished and not filling get discarded', function() { + tick(90); + var nofill = document.body.animate([], 100); + var fill = document.body.animate([], {duration: 100, fill: 'forwards'}); + assert.deepEqual(webAnimations1.timeline._animations, [nofill._animation || nofill, fill._animation || fill]); + tick(100); + assert.deepEqual(webAnimations1.timeline._animations, [nofill._animation || nofill, fill._animation || fill]); + tick(400); + assert.deepEqual(webAnimations1.timeline._animations, [fill._animation || fill]); + }); + test('discarded animations get re-added on modification', function() { + tick(90); + var animation = document.body.animate([], 100); + tick(100); + tick(400); + assert.deepEqual(webAnimations1.timeline._animations, []); + animation.currentTime = 0; + assert.deepEqual(webAnimations1.timeline._animations, [animation._animation || animation]); + }); + test('animations in the before phase are not discarded', function() { + tick(100); + var animation = document.body.animate([], 100); + animation.currentTime = -50; + tick(110); + assert.deepEqual(webAnimations1.timeline._animations, [animation._animation || animation]); + }); + test('animations that go out of effect should not clear the effect of animations that are in effect', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + tick(0); + var animationBehind = target.animate([{marginLeft: '200px'}, {marginLeft: '200px'}], 200); + var animationInfront = target.animate([{marginLeft: '100px'}, {marginLeft: '100px'}], 100); + tick(50); + assert.equal(getComputedStyle(target).marginLeft, '100px', 't = 50'); + tick(150); + assert.equal(getComputedStyle(target).marginLeft, '200px', 't = 150'); + tick(250); + assert.equal(getComputedStyle(target).marginLeft, '0px', 't = 250'); + document.body.removeChild(target); + }); + test('animation modifications should update CSS effects immediately', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + tick(0); + var animationBehind = target.animate([{width: '1234px'}, {width: '1234px'}], {duration: 1, fill: 'both'}); + var animationInfront = target.animate([{width: '0px'}, {width: '100px'}], 100); + assert.equal(getComputedStyle(target).width, '0px'); + animationInfront.currentTime = 50; + assert.equal(getComputedStyle(target).width, '50px'); + animationInfront.currentTime = 100; + assert.equal(getComputedStyle(target).width, '1234px'); + animationInfront.play(); + assert.equal(getComputedStyle(target).width, '0px'); + animationInfront.startTime = -50; + assert.equal(getComputedStyle(target).width, '50px'); + document.body.removeChild(target); + }); + test('KeyframeEffect that hasn\'t been played has playState \'idle\'', function() { + var effect = new webAnimations1KeyframeEffect(document.body, [], 1000); + var a = new webAnimations1Animation(effect); + assert.equal(a.playState, 'idle'); + }); + test('playState works for a simple effect', function() { + var a = document.body.animate([], 1000); + tick(0); + assert.equal(a.playState, 'running'); + tick(100); + assert.equal(a.playState, 'running'); + a.pause(); + assert.equal(a.playState, 'pending'); + tick(101); + assert.equal(a.playState, 'paused'); + a.play(); + assert.equal(a.playState, 'pending'); + tick(102); + assert.equal(a.playState, 'running'); + tick(1002); + assert.equal(a.playState, 'finished'); + }); + test('Play after cancel', function() { + var a = document.body.animate([], 1000); + assert.equal(a.playState, 'pending'); + tick(0); + a.cancel(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + tick(1); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + a.play(); + assert.equal(a.playState, 'pending'); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, null); + tick(10); + assert.equal(a.playState, 'running'); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 10); + }); + test('Reverse after cancel', function() { + var a = document.body.animate([], 300); + tick(0); + a.cancel(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + tick(1); + a.reverse(); + assert.equal(a.playState, 'pending'); + assert.equal(a.currentTime, 300); + assert.equal(a.startTime, null); + tick(100); + assert.equal(a.playState, 'running'); + assert.equal(a.currentTime, 300); + assert.equal(a.startTime, 400); + tick(300); + assert.equal(a.playState, 'running'); + assert.equal(a.currentTime, 100); + assert.equal(a.startTime, 400); + tick(400); + assert.equal(a.playState, 'finished'); + assert.equal(a.currentTime, 0); + assert.equal(a.startTime, 400); + }); + test('Finish after cancel', function() { + var a = document.body.animate([], 300); + tick(0); + a.cancel(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + tick(1); + a.finish(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + tick(2); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + }); + test('Pause after cancel', function() { + var a = document.body.animate([], 300); + tick(0); + a.cancel(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + tick(1); + a.pause(); + assert.equal(a.playState, 'idle'); + assert.equal(a.currentTime, null); + assert.equal(a.startTime, null); + }); + test('Animations ignore NaN times', function() { + var a = document.body.animate([], 300); + a.startTime = 100; + tick(110); + assert.equal(a.currentTime, 10); + a.startTime = NaN; + assert.equal(a.startTime, 100); + a.currentTime = undefined; + assert.equal(a.currentTime, 10); + }); + test('play() should not set a start time', function() { + var a = document.body.animate([], 1000); + a.cancel(); + assert.equal(a.startTime, null); + assert.equal(a.playState, 'idle'); + a.play(); + assert.equal(a.startTime, null); + assert.equal(a.playState, 'pending'); + }); + test('reverse() should not set a start time', function() { + var a = document.body.animate([], 1000); + a.cancel(); + assert.equal(a.startTime, null); + assert.equal(a.playState, 'idle'); + a.reverse(); + assert.equal(a.startTime, null); + assert.equal(a.playState, 'pending'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/apply-preserving-inline-style.js b/scripts/vendor/web-animations-js/test/js/apply-preserving-inline-style.js new file mode 100755 index 0000000000..fe080e6b2d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/apply-preserving-inline-style.js @@ -0,0 +1,72 @@ +suite('apply-preserving-inline-style', function() { + setup(function() { + this.element = document.createElement('div'); + ensureStyleIsPatched(this.element); + this.style = this.element.style; + document.documentElement.appendChild(this.element); + }); + teardown(function() { + document.documentElement.removeChild(this.element); + }); + + test('Style is patched', function() { + assert(this.element._webAnimationsPatchedStyle); + }); + test('Setting animated style', function() { + this.style.left = '0px'; + this.element.style._set('left', '100px'); + assert.equal(this.style.left, '0px'); + }); + test('Clearing animated style', function() { + this.style.left = '0px'; + this.element.style._set('left', '100px'); + this.element.style._clear('left'); + assert.equal(this.style.left, '0px'); + }); + test('Patched length', function() { + this.element.style._set('left', '100px'); + this.style.cssText = 'left: 0px; background-color: green;'; + assert.equal(this.style.cssText, 'left: 0px; background-color: green;'); + assert.equal(this.style.left, '0px'); + assert.equal(this.style.backgroundColor, 'green'); + assert.equal(this.style.length, 2); + }); + test('Patched property getters and setters', function() { + this.style._set('left', '100px'); + this.style.left = '0px'; + this.style.backgroundColor = 'rgb(1, 2, 3)'; + assert.equal(this.style.left, '0px'); + assert.equal(this.style.backgroundColor, 'rgb(1, 2, 3)'); + assert.equal(getComputedStyle(this.element).left, '100px'); + assert.equal(getComputedStyle(this.element).backgroundColor, 'rgb(1, 2, 3)'); + }); + test('Patched setProperty/getPropertyValue', function() { + this.style._set('left', '100px'); + this.style.setProperty('left', '0px'); + this.style.setProperty('background-color', 'rgb(1, 2, 3)'); + assert.equal(this.style.getPropertyValue('left'), '0px'); + assert.equal(this.style.getPropertyValue('background-color'), 'rgb(1, 2, 3)'); + assert.equal(getComputedStyle(this.element).left, '100px'); + assert.equal(getComputedStyle(this.element).backgroundColor, 'rgb(1, 2, 3)'); + }); + test('Patched item()', function() { + this.style._set('left', '100px'); + this.style.setProperty('left', '0px'); + this.style.setProperty('background-color', 'rgb(1, 2, 3)'); + assert.equal(this.style.item(0), 'left'); + assert.equal(this.style.item(1), 'background-color'); + assert.equal(this.style.item(2), ''); + this.style.cssText = 'top: 0px'; + assert.equal(this.style.item(0), 'top'); + assert.equal(this.style.item(1), ''); + }); + test('Patched cssText', function() { + this.style._set('left', '100px'); + assert.equal(this.style.length, 0); + this.style.setProperty('left', '0px'); + this.style.setProperty('background-color', 'rgb(1, 2, 3)'); + assert.equal(this.style.length, 2); + this.style.cssText = 'top: 0px'; + assert.equal(this.style.length, 1); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/box-handler.js b/scripts/vendor/web-animations-js/test/js/box-handler.js new file mode 100755 index 0000000000..6aff2dbbc4 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/box-handler.js @@ -0,0 +1,70 @@ +suite('box-handler', function() { + test('parse rectangle values', function() { + assert.deepEqual(webAnimations1.parseBox(' rect(0px, 20px, 20px, 0px) '), [{px: 0}, {px: 20}, {px: 20}, {px: 0}]); + assert.deepEqual(webAnimations1.parseBox('rect(0px, 20px, 20px, 0px)'), [{px: 0}, {px: 20}, {px: 20}, {px: 0}]); + assert.deepEqual(webAnimations1.parseBox('rect(0px, 20px, 20px, 0)'), [{px: 0}, {px: 20}, {px: 20}, {px: 0}]); + assert.deepEqual(webAnimations1.parseBox('rect(10px, 100%, 500px, 10%)'), [{px: 10}, {'%': 100}, {px: 500}, {'%': 10}]); + assert.deepEqual(webAnimations1.parseBox('rect(10%, 100%, 500%, 10%)'), [{'%': 10}, {'%': 100}, {'%': 500}, {'%': 10}]); + assert.deepEqual(webAnimations1.parseBox('rect(0px, calc(10px*3), 20px, 0%)'), [{px: 0}, {px: 30}, {px: 20}, {'%': 0}]); + assert.deepEqual(webAnimations1.parseBox('rect(0px, 0%, 20px, calc(10px*3))'), [{px: 0}, {'%': 0}, {px: 20}, {px: 30}]); + assert.deepEqual(webAnimations1.parseBox('rect(0px, 0%, 20px, calc((10px) + (3px)))'), [{px: 0}, {'%': 0}, {px: 20}, {px: 13}]); + assert.deepEqual(webAnimations1.parseBox('rect(calc(10px + 5em), calc(10px + 5em), calc(10px + 5em), calc(10px + 5em))'), + [{px: 10, em: 5}, {px: 10, em: 5}, {px: 10, em: 5}, {px: 10, em: 5}]); + }); + test('invalid rectangles fail to parse', function() { + assert.isUndefined(webAnimations1.parseBox('rect(0, 20, 20, 0)')); + assert.isUndefined(webAnimations1.parseBox('rect(0px, 0px, 0px)')); + assert.isUndefined(webAnimations1.parseBox('rect(0px, 0px, 0px, 0px, 0px)')); + assert.isUndefined(webAnimations1.parseBox('rect()')); + assert.isUndefined(webAnimations1.parseBox('rect(calc(10px + 5), 0px, 0px, 0px)')); + assert.isUndefined(webAnimations1.parseBox('Rect(0px, 0px, 0px, 0px)')); + }); + test('interpolate lengths, percents and calcs in rectangles', function() { + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(10px, 10px, 10px, 10px)', 'rect(50px, 50px, 50px, 50px)')(0.25), + 'rect(20px, 20px, 20px, 20px)', + 'Interpolate lengths in a rect'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(-10px, -10px, -10px, -10px)', 'rect(50px, 50px, 50px, 50px)')(0.25), + 'rect(5px, 5px, 5px, 5px)', + 'Interpolate negative lengths in a rect'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(10%, 10%, 10%, 10%)', 'rect(50%, 50%, 50%, 50%)')(0.25), + 'rect(20%, 20%, 20%, 20%)', + 'Interpolate percents in a rect'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(10px, 10%, 10px, 10%)', 'rect(50px, 50%, 50px, 50%)')(0.25), + 'rect(20px, 20%, 20px, 20%)', + 'Interpolate mixed lengths and percents in a rect, where units are aligned'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(0px, 0px, 0px, 0px)', 'rect(0.001px, 0.001px, 0.001px, 0.001px)')(0.05), + 'rect(0px, 0px, 0px, 0px)', + 'Round interpolation result'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(0px, 0px, 0px, 0px)', 'rect(0.001px, 0.001px, 0.001px, 0.001px)')(0.5), + 'rect(0.001px, 0.001px, 0.001px, 0.001px)', + 'Round interpolation result'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(10px, 10px, 10px, 10px)', 'rect(20px, 20px, 20px, 20px)')(0.25), + 'rect(12.500px, 12.500px, 12.500px, 12.500px)', + 'Round interpolation result'); + assert.equal( + webAnimations1.propertyInterpolation('clip', 'rect(10px, 10%, 10px, 10%)', 'rect(10em, 10px, 10em, 10px)')(0.4), + 'rect(calc(6px + 4em), calc(6% + 4px), calc(6px + 4em), calc(6% + 4px))', + 'Interpolate from pixels to ems and from percents to pixels'); + assert.equal( + webAnimations1.propertyInterpolation( + 'clip', + 'rect(calc(10px + 5em), calc(10px + 5em), calc(10px + 5em), calc(10px + 5em))', + 'rect(calc(20px + 35em), calc(20px + 35em), calc(20px + 35em), calc(20px + 35em))')(0.4), + 'rect(calc(14px + 17em), calc(14px + 17em), calc(14px + 17em), calc(14px + 17em))', + 'Interpolate calcs in a rect'); + assert.equal( + webAnimations1.propertyInterpolation( + 'clip', + 'rect(calc(10px + (5em)), calc(10px + (5em)), calc(10px + (5em)), calc(10px + (5em)))', + 'rect(calc(20px + 35em), calc(20px + 35em), calc(20% + 35em), calc(20% + 35em))')(0.5), + 'rect(calc(15px + 20em), calc(15px + 20em), calc(5px + 20em + 10%), calc(5px + 20em + 10%))', + 'Interpolate calcs in a rect'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/color-handler.js b/scripts/vendor/web-animations-js/test/js/color-handler.js new file mode 100755 index 0000000000..3cebf6167b --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/color-handler.js @@ -0,0 +1,23 @@ +suite('color-handler', function() { + test('parse colors', function() { + assert.deepEqual(parseColor(' ReD '), [255, 0, 0, 1]); + assert.deepEqual(parseColor(' magenta'), [255, 0, 255, 1]); + assert.deepEqual(parseColor('transparent'), [0, 0, 0, 0]); + assert.deepEqual(parseColor('#0f0'), [0, 255, 0, 1]); + assert.deepEqual(parseColor('rgb(0,10,20)'), [0, 10, 20, 1]); + assert.deepEqual(parseColor('rgba(65,40,20,0.2)'), [13, 8, 4, 0.2]); + assert.deepEqual(parseColor('hsl(120, 100%, 50%)'), [0, 255, 0, 1]); + }); + test('invalid colors fail to parse', function() { + assert.isUndefined(parseColor('')); + assert.isUndefined(parseColor('bananayellow')); + assert.isUndefined(parseColor('rgb(10, 20, 30, 40)')); + }); + test('color interpolation', function() { + assert.equal(webAnimations1.propertyInterpolation('color', '#00aa11', '#aa00bb')(0.2), 'rgba(34,136,51,1)'); + assert.equal(webAnimations1.propertyInterpolation('color', 'transparent', '#004488')(0), 'transparent'); + assert.equal(webAnimations1.propertyInterpolation('color', 'transparent', '#004488')(0.5), 'rgba(0,68,136,0.500)'); + assert.equal(webAnimations1.propertyInterpolation('color', 'red', 'green')(2), 'rgba(0,255,0,1)'); + assert.equal(webAnimations1.propertyInterpolation('color', 'red', 'green')(-1), 'rgba(255,0,0,1)'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/dimension-handler.js b/scripts/vendor/web-animations-js/test/js/dimension-handler.js new file mode 100755 index 0000000000..e34ae366b5 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/dimension-handler.js @@ -0,0 +1,74 @@ +suite('dimension-handler', function() { + test('parse simple length values', function() { + assert.deepEqual(webAnimations1.parseLength(' 0 '), {px: 0}); + assert.deepEqual(webAnimations1.parseLength('10px'), {px: 10}); + assert.deepEqual(webAnimations1.parseLength('5VmIN'), {vmin: 5}); + assert.deepEqual(webAnimations1.parseLength('-12.5em'), {em: -12.5}); + }); + test('parse length calcs', function() { + assert.deepEqual(webAnimations1.parseLength('calc(10px*3) '), + {px: 30}); + assert.deepEqual(webAnimations1.parseLength('calc(10vmin + -5in) '), + {vmin: 10, 'in': -5}); + assert.deepEqual(webAnimations1.parseLength('calc(5EM + 10px) '), + {em: 5, px: 10}); + assert.deepEqual(webAnimations1.parseLength(' calc( 10px + 5em ) '), + {px: 10, em: 5}); + assert.deepEqual(webAnimations1.parseLength('calc(5*(10px + 5em) - 5.25em * 6)'), + {px: 50.0, em: -6.5}); + assert.deepEqual(webAnimations1.parseLength('calc((5px + 2px)*(1 + 2*(4 + 2*-5)) + 7px - (5em + 6vw/2)*4)'), + {px: -70, em: -20, vw: -12}); + assert.deepEqual(webAnimations1.parseLength('calc(calc(5px) + calc(((3))) *calc(calc(10px)))'), + {px: 35}); + }); + test('invalid lengths fail to parse', function() { + assert.isUndefined(webAnimations1.parseLength('10')); + assert.isUndefined(webAnimations1.parseLength('()')); + assert.isUndefined(webAnimations1.parseLength('(10px)')); + assert.isUndefined(webAnimations1.parseLength('(10px + 5em)')); + assert.isUndefined(webAnimations1.parseLength('calc(10px + 5)')); + assert.isUndefined(webAnimations1.parseLength('calc(10px+ 5em)')); + assert.isUndefined(webAnimations1.parseLength('calc(10px +5em)')); + assert.isUndefined(webAnimations1.parseLength('calc(10px * 5em)')); + assert.isUndefined(webAnimations1.parseLength('(calc(10px + 5em))')); + assert.isUndefined(webAnimations1.parseLength('calc(10px + 5em))')); + assert.isUndefined(webAnimations1.parseLength('calc(10)')); + assert.isUndefined(webAnimations1.parseLength('calccalc(10px)')); + assert.isUndefined(webAnimations1.parseLength('calc(5 / 10px)')); + assert.isUndefined(webAnimations1.parseLength('calc(10px / 0)')); + assert.isUndefined(webAnimations1.parseLength('calc()')); + assert.isUndefined(webAnimations1.parseLength('ch')); + }); + test('interpolate lengths and percents', function() { + assert.equal(webAnimations1.propertyInterpolation('left', '10px', '50px')(0.25), '20px'); + assert.equal(webAnimations1.propertyInterpolation('left', '10%', '50%')(0.25), '20%'); + assert.equal(webAnimations1.propertyInterpolation('left', '0px', '0.001px')(0.05), '0px'); + assert.equal(webAnimations1.propertyInterpolation('left', '0px', '10px')(0.234), '2.340px'); + assert.equal(webAnimations1.propertyInterpolation('left', '10px', '10em')(0.4), 'calc(6px + 4em)'); + assert.equal(webAnimations1.propertyInterpolation('left', '10px', '10%')(0.4), 'calc(6px + 4%)'); + assert.equal(webAnimations1.propertyInterpolation('left', 'calc(10px + 5em)', 'calc(20px + 35em)')(0.4), 'calc(14px + 17em)'); + assert.equal(webAnimations1.propertyInterpolation('left', 'calc(10px + 5em)', 'calc(20% + 35em)')(0.4), 'calc(6px + 17em + 8%)'); + assert.equal(webAnimations1.propertyInterpolation('left', 'calc(10px + 5vw)', 'calc(20% + 35em)')(0.4), 'calc(6px + 3vw + 8% + 14em)'); + }); + test('consume simple length values', function() { + assert.isUndefined(webAnimations1.consumeLengthOrPercent('10px()')); + assert.deepEqual(webAnimations1.consumeLengthOrPercent('10px,'), + [{px: 10}, ',']); + assert.deepEqual(webAnimations1.consumeLengthOrPercent('10px,20px'), + [{px: 10}, ',20px']); + assert.deepEqual(webAnimations1.consumeLengthOrPercent('0 blah'), + [{px: 0}, ' blah']); + }); + test('consume length calcs', function() { + assert.deepEqual(webAnimations1.consumeLengthOrPercent('calc(10px)()'), + [{px: 10}, '()']); + assert.deepEqual(webAnimations1.consumeLengthOrPercent('calc((5px + 2px)*(1 + 2*(4 + 2*-5)) + 7px - (5em + 6vw/2)*4)blah'), + [{px: -70, em: -20, vw: -12}, 'blah']); + }); + test('consume fails on invalid input', function() { + assert.isUndefined(webAnimations1.consumeLengthOrPercent('()')); + assert.isUndefined(webAnimations1.consumeLengthOrPercent('(10px')); + assert.isUndefined(webAnimations1.consumeLengthOrPercent('(10px)')); + assert.isUndefined(webAnimations1.consumeLengthOrPercent('calc(10px,10px)')); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/effect-callback.js b/scripts/vendor/web-animations-js/test/js/effect-callback.js new file mode 100755 index 0000000000..d441d41e27 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/effect-callback.js @@ -0,0 +1,76 @@ +suite('effect-callback', function() { + setup(function() { + document.timeline._animations = []; + webAnimations1.timeline._animations = []; + }); + + test('animations starting in the future are not in effect', function() { + var fractions = []; + tick(100); + var animation = document.body.animate(function(fraction) { fractions.push(fraction); }, 1000); + animation.startTime = 1000; + tick(200); + tick(1000); + tick(1100); + assert.deepEqual(fractions, [0, 0.1]); + }); + + test('duration 0 animations get sampled at least once', function() { + var timeFraction; + tick(0); + var animation = document.body.animate(function(t) { + timeFraction = t; + }, {duration: 0, fill: 'both'}); + tick(100); + assert.equal(timeFraction, 1); + assert.equal(isTicking(), false); + }); + + test('animations added during custom effect callbacks get updated in the same tick', function() { + var animation; + var called = false; + tick(0); + document.body.animate(function() { + animation = document.body.animate(function() { + called = true; + }, 1); + }, 2); + tick(1); + assert.isTrue(animation.startTime >= 0); + assert.isFalse(called); + }); + + test('custom effect should be called after cancel', function() { + var fractions = []; + var animation = document.body.animate(function(fraction) { fractions.push(fraction); }, 1000); + tick(0); + tick(500); + animation.cancel(); + tick(501); + assert.deepEqual(fractions, [0, 0.5, null]); + }); + + test('element.animate is given effect', function() { + var callbackAnim; + var animation = document.body.animate(function(t, target, a) { + callbackAnim = a; + }, 100); + tick(50); + tick(150); + assert.equal(isTicking(), false); + assert(callbackAnim, 'callback should be set'); + assert.equal(callbackAnim.target, document.body); + }); + + test('custom callback on effect is given source effect', function() { + var callbackAnim; + var effect = new KeyframeEffect(document.body, function(t, target, a) { + callbackAnim = a; + }, 1000); + var animation = document.timeline.play(effect); + tick(50); + tick(550); + assert.equal(animation.currentTime, 500); + assert.equal(callbackAnim, effect); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/group-animation-finish-event.js b/scripts/vendor/web-animations-js/test/js/group-animation-finish-event.js new file mode 100755 index 0000000000..c3ad7a5cc3 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/group-animation-finish-event.js @@ -0,0 +1,87 @@ +suite('group-animation-finish-event', function() { + setup(function() { + document.timeline.currentTime = undefined; + this.element = document.createElement('div'); + document.documentElement.appendChild(this.element); + var sequenceEffect = new SequenceEffect([ + new KeyframeEffect(this.element, [], 500), + new GroupEffect([ + new KeyframeEffect(this.element, [], 250), + new KeyframeEffect(this.element, [], 500), + ]), + ]); + this.animation = document.timeline.play(sequenceEffect, 1000); + }); + teardown(function() { + if (this.element.parent) + this.element.removeChild(this.element); + }); + + test('fire when animation completes', function(done) { + var ready = false; + var fired = false; + var animation = this.animation; + animation.onfinish = function(event) { + assert(ready, 'must not be called synchronously'); + assert.equal(this, animation); + assert.equal(event.target, animation); + assert.equal(event.currentTime, 1000); + assert.equal(event.timelineTime, 1100); + if (fired) + assert(false, 'must not get fired twice'); + fired = true; + done(); + }; + tick(100); + tick(1100); + tick(2100); + ready = true; + }); + + test('fire when reversed animation completes', function(done) { + this.animation.onfinish = function(event) { + assert.equal(event.currentTime, 0); + assert.equal(event.timelineTime, 1001); + done(); + }; + tick(0); + tick(500); + this.animation.reverse(); + tick(501); + tick(1001); + }); + + test('fire after animation is cancelled', function(done) { + this.animation.onfinish = function(event) { + assert.equal(event.currentTime, 0); + assert.equal(event.timelineTime, 1, 'event must be fired on next sample'); + done(); + }; + tick(0); + this.animation.cancel(); + tick(1); + }); + + test('multiple event listeners', function(done) { + var count = 0; + function createHandler(expectedCount) { + return function() { + count++; + assert.equal(count, expectedCount); + }; + } + var toRemove = createHandler(0); + this.animation.addEventListener('finish', createHandler(1)); + this.animation.addEventListener('finish', createHandler(2)); + this.animation.addEventListener('finish', toRemove); + this.animation.addEventListener('finish', createHandler(3)); + this.animation.removeEventListener('finish', toRemove); + this.animation.onfinish = function() { + assert.equal(count, 3); + done(); + }; + tick(0); + this.animation.cancel(); + tick(1000); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/group-animation.js b/scripts/vendor/web-animations-js/test/js/group-animation.js new file mode 100755 index 0000000000..a2d3180815 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/group-animation.js @@ -0,0 +1,1488 @@ +suite('group-animation', function() { + setup(function() { + document.timeline._animations = []; + webAnimations1.timeline._animations = []; + this.elements = []; + + var marginEffect = function(target) { + return new KeyframeEffect( + target, + [ + {marginLeft: '0px'}, + {marginLeft: '100px'} + ], + 500); + }; + var colorEffect = function(target) { + return new KeyframeEffect( + target, + [ + {backgroundColor: 'black'}, + {backgroundColor: 'white'} + ], + 500); + }; + var sequenceEmpty = function() { + return new SequenceEffect(); + }; + var groupEmpty = function() { + return new GroupEffect(); + }; + var sequenceWithContent = function(target) { + return new SequenceEffect( + [ + marginEffect(target), + colorEffect(target) + ]); + }; + var groupWithContent = function(target) { + return new GroupEffect( + [ + marginEffect(target), + colorEffect(target) + ]); + }; + + var emptySeq = sequenceEmpty(); + + var seqSimple_target = document.createElement('div'); + this.elements.push(seqSimple_target); + var seqSimple = sequenceWithContent(seqSimple_target); + + var seqWithSeq_target = document.createElement('div'); + this.elements.push(seqWithSeq_target); + var seqWithSeq = new SequenceEffect( + [ + marginEffect(seqWithSeq_target), + colorEffect(seqWithSeq_target), + sequenceWithContent(seqWithSeq_target) + ]); + + var seqWithGroup_target = document.createElement('div'); + this.elements.push(seqWithGroup_target); + var seqWithGroup = new SequenceEffect( + [ + marginEffect(seqWithGroup_target), + colorEffect(seqWithGroup_target), + groupWithContent(seqWithGroup_target) + ]); + + var seqWithEmptyGroup = new SequenceEffect([groupEmpty()]); + var seqWithEmptySeq = new SequenceEffect([sequenceEmpty()]); + + var emptyGroup = groupEmpty(); + + var groupSimple_target = document.createElement('div'); + var groupSimple = groupWithContent(groupSimple_target); + + var groupWithSeq_target = document.createElement('div'); + this.elements.push(groupWithSeq_target); + var groutWithSeq = new GroupEffect( + [ + marginEffect(groupWithSeq_target), + colorEffect(groupWithSeq_target), + sequenceWithContent(groupWithSeq_target) + ]); + + var groupWithGroup_target = document.createElement('div'); + this.elements.push(groupWithGroup_target); + var groupWithGroup = new GroupEffect( + [ + marginEffect(groupWithGroup_target), + colorEffect(groupWithGroup_target), + groupWithContent(groupWithGroup_target) + ]); + + var groupWithEmptyGroup = new GroupEffect([groupEmpty()]); + var groupWithEmptySeq = new GroupEffect([sequenceEmpty()]); + + this.emptySeq = emptySeq; + this.seqSimple = seqSimple; + this.seqWithSeq = seqWithSeq; + this.seqWithGroup = seqWithGroup; + this.seqWithEmptyGroup = seqWithEmptyGroup; + this.seqWithEmptySeq = seqWithEmptySeq; + + this.emptyGroup = emptyGroup; + this.groupSimple = groupSimple; + this.groutWithSeq = groutWithSeq; + this.groupWithGroup = groupWithGroup; + this.groupWithEmptyGroup = groupWithEmptyGroup; + this.groupWithEmptySeq = groupWithEmptySeq; + + this.staticEffect = function(target, value, duration) { + var keyframeEffect = new KeyframeEffect(target, [{marginLeft: value}, {marginLeft: value}], duration); + keyframeEffect.testValue = value; + return keyframeEffect; + }; + // The following animation structure looks like: + // 44444 + // 11 + // 33 + // 2 + // 0 + this.complexTarget = document.createElement('div'); + this.elements.push(this.complexTarget); + this.complexSource = new GroupEffect([ + this.staticEffect(this.complexTarget, '4px', 5), + new SequenceEffect([ + this.staticEffect(this.complexTarget, '1px', 2), + new GroupEffect([ + this.staticEffect(this.complexTarget, '3px', 2), + this.staticEffect(this.complexTarget, '2px', 1), + ]), + ]), + this.staticEffect(this.complexTarget, '0px', 1), + ]); + + this.target = document.createElement('div'); + this.target1 = document.createElement('div'); + this.target2 = document.createElement('div'); + this.target3 = document.createElement('div'); + this.elements.push(this.target); + this.elements.push(this.target1); + this.elements.push(this.target2); + this.elements.push(this.target3); + + for (var i = 0; i < this.elements.length; i++) + document.documentElement.appendChild(this.elements[i]); + + // Playback rate test helpers. + var target1 = this.target1; + var target2 = this.target2; + var target3 = this.target3; + target1.style.transform = 'translate(500px)'; + target2.style.transform = 'translate(500px)'; + target3.style.transform = 'translate(500px)'; + var underlyingPosition = 'matrix(1, 0, 0, 1, 500, 0)'; + var startPosition = 'matrix(1, 0, 0, 1, 0, 0)'; + var endPosition = 'matrix(1, 0, 0, 1, 300, 0)'; + this.prChildDuration = 100; + this.sequenceForPR = function(parentFill, childFill) { + return new SequenceEffect([ + new KeyframeEffect( + target1, + [{transform: 'translate(0,0)'}, {transform: 'translate(300px)'}], + {duration: this.prChildDuration, fill: childFill}), + new KeyframeEffect( + target2, + [{transform: 'translate(0,0)'}, {transform: 'translate(300px)'}], + {duration: this.prChildDuration, fill: childFill}), + new KeyframeEffect( + target3, + [{transform: 'translate(0,0)'}, {transform: 'translate(300px)'}], + {duration: this.prChildDuration, fill: childFill}) + ], + {fill: parentFill}); + }; + this.isUnderlyingPosition = function() { + assert.equal(getComputedStyle(target1).transform, startPosition); + assert.equal(getComputedStyle(target2).transform, underlyingPosition); + assert.equal(getComputedStyle(target3).transform, underlyingPosition); + }; + this.isFillingForwards = function() { + assert.equal(getComputedStyle(target1).transform, endPosition); + assert.equal(getComputedStyle(target2).transform, endPosition); + }; + this.isNotFillingForwards = function() { + assert.equal(getComputedStyle(target1).transform, underlyingPosition); + assert.equal(getComputedStyle(target2).transform, underlyingPosition); + }; + this.isFillingBackwardsDuring = function() { + assert.equal(getComputedStyle(target2).transform, startPosition); + assert.equal(getComputedStyle(target3).transform, startPosition); + }; + this.isNotFillingBackwardsDuring = function() { + assert.equal(getComputedStyle(target2).transform, underlyingPosition); + assert.equal(getComputedStyle(target3).transform, underlyingPosition); + }; + this.isFillingBackwards = function() { + assert.equal(getComputedStyle(target1).transform, startPosition); + assert.equal(getComputedStyle(target2).transform, startPosition); + assert.equal(getComputedStyle(target3).transform, startPosition); + }; + this.isNotFillingBackwards = function() { + assert.equal(getComputedStyle(target1).transform, underlyingPosition); + assert.equal(getComputedStyle(target2).transform, underlyingPosition); + assert.equal(getComputedStyle(target3).transform, underlyingPosition); + }; + this.checkFills = function(parentFillMode, childFillMode, startFill, normalFill, reverseFill, endFill, reverse) { + var animation = document.timeline.play(this.sequenceForPR(parentFillMode, childFillMode)); + tick(0); + startFill(); + tick(2 * this.prChildDuration); + normalFill(); + tick(this.prChildDuration * 2.5); + reverse ? animation.reverse() : animation.playbackRate *= -1; + tick(3.5 * this.prChildDuration); + tick(5 * this.prChildDuration); + reverseFill(); + tick(6); + tick(7.5 * this.prChildDuration); + endFill(); + animation.cancel(); + }; + }); + + teardown(function() { + for (var i = 0; i < this.elements.length; i++) { + if (this.elements[i].parent) + this.elements[i].parent.removeChild(this.elements[i]); + } + }); + + function simpleGroupEffect() { + return new GroupEffect([new KeyframeEffect(document.body, [], 2000), new KeyframeEffect(document.body, [], 1000), new KeyframeEffect(document.body, [], 3000)]); + } + + function simpleSequenceEffect() { + return new SequenceEffect([new KeyframeEffect(document.body, [], 2000), new KeyframeEffect(document.body, [], 1000), new KeyframeEffect(document.body, [], 3000)]); + } + + // FIXME: Remove _startOffset. + // animationState is [startTime, currentTime, _startOffset?, offset?] + // innerAnimationStates is a nested array tree of animationStates e.g. [[0, 0], [[1, -1], [2, -2]]] + function checkTimes(animation, animationState, innerAnimationStates, description) { + description = description ? (description + ' ') : ''; + _checkTimes(animation, animationState, 0, description + 'top animation'); + _checkTimes(animation, innerAnimationStates, 0, description + 'inner animation'); + } + + function _checkTimes(animation, timingList, index, trace) { + assert.isDefined(animation, trace + ' exists'); + if (timingList.length == 0) { + assert.equal(animation._childAnimations.length, index, trace + ' no remaining animations'); + return; + } + if (timingList[0] === null || typeof timingList[0] == 'number') { + assert.equal(animation.startTime, timingList[0], trace + ' startTime'); + assert.equal(animation.currentTime, timingList[1], trace + ' currentTime'); + } else { + _checkTimes(animation._childAnimations[index], timingList[0], 0, trace + ' ' + index); + _checkTimes(animation, timingList.slice(1), index + 1, trace); + } + } + + test('playing a GroupEffect works as expected', function() { + tick(90); + var a = document.timeline.play(simpleGroupEffect()); + checkTimes(a, [null, 0], [[null, 0], [null, 0], [null, 0]]); + tick(100); + checkTimes(a, [100, 0], [[100, 0], [100, 0], [100, 0]]); + tick(300); + checkTimes(a, [100, 200], [[100, 200], [100, 200], [100, 200]]); + tick(1200); + checkTimes(a, [100, 1100], [[100, 1100], [100, 1000], [100, 1100]]); + tick(2200); + checkTimes(a, [100, 2100], [[100, 2000], [100, 1000], [100, 2100]]); + tick(3200); + checkTimes(a, [100, 3000], [[100, 2000], [100, 1000], [100, 3000]]); + }); + + test('can seek a GroupEffect', function() { + tick(90); + var a = document.timeline.play(simpleGroupEffect()); + tick(100); + checkTimes(a, [100, 0], [[100, 0], [100, 0], [100, 0]]); + a.currentTime = 200; + checkTimes(a, [-100, 200], [[-100, 200], [-100, 200], [-100, 200]]); + a.currentTime = 1100; + checkTimes(a, [-1000, 1100], [[-1000, 1100], [-1000, 1100], [-1000, 1100]]); + a.currentTime = 2100; + checkTimes(a, [-2000, 2100], [[-2000, 2100], [-2000, 2100], [-2000, 2100]]); + a.currentTime = 3100; + checkTimes(a, [-3000, 3100], [[-3000, 3100], [-3000, 3100], [-3000, 3100]]); + }); + + test('can startTime seek a GroupEffect', function() { + tick(90); + var a = document.timeline.play(simpleGroupEffect()); + tick(100); + checkTimes(a, [100, 0], [[100, 0], [100, 0], [100, 0]]); + a.startTime = -100; + checkTimes(a, [-100, 200], [[-100, 200], [-100, 200], [-100, 200]]); + a.startTime = -1000; + checkTimes(a, [-1000, 1100], [[-1000, 1100], [-1000, 1000], [-1000, 1100]]); + a.startTime = -2000; + checkTimes(a, [-2000, 2100], [[-2000, 2000], [-2000, 1000], [-2000, 2100]]); + a.startTime = -3000; + checkTimes(a, [-3000, 3000], [[-3000, 2000], [-3000, 1000], [-3000, 3000]]); + }); + + test('playing a SequenceEffect works as expected', function() { + tick(100); + var a = document.timeline.play(simpleSequenceEffect()); + tick(110); + checkTimes(a, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]); + tick(210); + checkTimes(a, [110, 100], [[110, 100], [2110, -1900], [3110, -2900]]); + tick(2210); + checkTimes(a, [110, 2100], [[110, 2000], [2110, 100], [3110, -900]]); + tick(3210); + checkTimes(a, [110, 3100], [[110, 2000], [2110, 1000], [3110, 100]]); + tick(6210); + checkTimes(a, [110, 6000], [[110, 2000], [2110, 1000], [3110, 3000]]); + }); + + test('can seek a SequenceEffect', function() { + tick(100); + var a = document.timeline.play(simpleSequenceEffect()); + tick(110); + checkTimes(a, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]); + a.currentTime = 100; + checkTimes(a, [10, 100], [[10, 100], [2010, -1900], [3010, -2900]]); + a.currentTime = 2100; + checkTimes(a, [-1990, 2100], [[-1990, 2100], [10, 100], [1010, -900]]); + a.currentTime = 3100; + checkTimes(a, [-2990, 3100], [[-2990, 3100], [-990, 1100], [10, 100]]); + a.currentTime = 6100; + checkTimes(a, [-5990, 6100], [[-5990, 6100], [-3990, 4100], [-2990, 3100]]); + }); + + test('can startTime seek a SequenceEffect', function() { + tick(100); + var a = document.timeline.play(simpleSequenceEffect()); + tick(110); + checkTimes(a, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]); + a.startTime = 10; + checkTimes(a, [10, 100], [[10, 100], [2010, -1900], [3010, -2900]]); + a.startTime = -1990; + checkTimes(a, [-1990, 2100], [[-1990, 2000], [10, 100], [1010, -900]]); + a.startTime = -2990; + checkTimes(a, [-2990, 3100], [[-2990, 2000], [-990, 1000], [10, 100]]); + a.startTime = -5990; + checkTimes(a, [-5990, 6000], [[-5990, 2000], [-3990, 1000], [-2990, 3000]]); + }); + + test('complex animation tree timing while playing', function() { + tick(90); + var animation = document.timeline.play(this.complexSource); + tick(100); + checkTimes(animation, [100, 0], [ + [100, 0], [ // 4 + [100, 0], [ // 1 + [102, -2], // 3 + [102, -2]]], // 2 + [100, 0], // 0 + ], 't = 100'); + tick(101); + checkTimes(animation, [100, 1], [ + [100, 1], [ // 4 + [100, 1], [ // 1 + [102, -1], // 3 + [102, -1]]], // 2 + [100, 1], // 0 + ], 't = 101'); + tick(102); + checkTimes(animation, [100, 2], [ + [100, 2], [ // 4 + [100, 2], [ // 1 + [102, 0], // 3 + [102, 0]]], // 2 + [100, 1], // 0 + ], 't = 102'); + }); + + test('effects apply in the correct order', function() { + tick(0); + var animation = document.timeline.play(this.complexSource); + animation.currentTime = 0; + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px'); + animation.currentTime = 1; + checkTimes(animation, [-1, 1], [[-1, 1, 0], [[-1, 1, 0], [[1, -1, 0], [1, -1, 0]]], [-1, 1, 0]]); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '1px'); + animation.currentTime = 2; + // TODO: When we seek we don't limit. Is this OK? + checkTimes(animation, [-2, 2], [[-2, 2, 0], [[-2, 2, 0], [[0, 0, 0], [0, 0, 0]]], [-2, 2, 0]]); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '2px'); + animation.currentTime = 3; + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '3px'); + animation.currentTime = 4; + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '4px'); + animation.currentTime = 5; + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px'); + }); + + test('cancelling group animations', function() { + tick(0); + var animation = document.timeline.play(this.complexSource); + tick(1); + tick(4); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '3px'); + animation.cancel(); + assert.equal(animation.currentTime, null); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px'); + }); + + test('cancelling group animations before tick', function() { + tick(0); + var animation = document.timeline.play(this.complexSource); + animation.cancel(); + assert.equal(animation.currentTime, null); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px'); + tick(4); + assert.equal(animation.currentTime, null); + assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px'); + }); + + test('redundant effect node wrapping', function() { + tick(100); + var sequenceEffect = new SequenceEffect([ + this.staticEffect(this.target, '0px', 1), + new GroupEffect([ + new SequenceEffect([ + this.staticEffect(this.target, '1px', 1), + this.staticEffect(this.target, '2px', 1), + ]), + ]), + ]); + var animation = document.timeline.play(sequenceEffect); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + checkTimes(animation, [100, 0], [ + [100, 0, 0, 0], [[ // 0 + [101, -1, 0, 1], // 1 + [102, -2, 1, 2]]] // 2 + ], 't = 100'); + tick(101); + assert.equal(getComputedStyle(this.target).marginLeft, '1px'); + checkTimes(animation, [100, 1], [ + [100, 1, 0, 0], [[ // 0 + [101, 0, 0, 1], // 1 + [102, -1, 1, 2]]] // 2 + ], 't = 101'); + tick(102); + assert.equal(getComputedStyle(this.target).marginLeft, '2px'); + assert.equal(document.timeline.currentTime, 102); + checkTimes(animation, [100, 2], [ // FIXME: Implement limiting on group animations + [100, 1, 0, 0], [[ // 0 + [101, 1, 0, 1], // 1 + [102, 0, 1, 2]]] // 2 + ], 't = 102'); + tick(103); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + checkTimes(animation, [100, 3], [ // FIXME: Implement limiting on group animations + [100, 1, 0, 0], [[ // 0 + [101, 1, 0, 1], // 1 + [102, 1, 1, 2]]] // 2 + ], 't = 103'); + if (this.target.parent) + this.target.parent.removeChild(target); + }); + + test('Fill modes work for sequence fill both with children none after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'both', + 'none', + this.isUnderlyingPosition, + this.isNotFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill both with children both after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'both', + 'both', + this.isFillingBackwards, + this.isFillingForwards, + this.isFillingBackwardsDuring, + this.isFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill both with children backwards after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'both', + 'backwards', + this.isFillingBackwards, + this.isNotFillingForwards, + this.isFillingBackwardsDuring, + this.isFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill both with children forwards after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'both', + 'forwards', + this.isUnderlyingPosition, + this.isFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill none with children fill none after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'none', + 'none', + this.isUnderlyingPosition, + this.isNotFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill none with children fill both after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'none', + 'both', + this.isFillingBackwards, + this.isFillingForwards, + this.isFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill none with children fill backwards after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'none', + 'backwards', + this.isFillingBackwards, + this.isNotFillingForwards, + this.isFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + test('Fill modes work for sequence fill none with children fill forwards after setting playbackRate from positive to negative.', function() { + this.checkFills( + 'none', + 'forwards', + this.isUnderlyingPosition, + this.isFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + false + ); + }); + + test('Fill modes work for sequence fill both with children none after reverse.', function() { + this.checkFills( + 'both', + 'none', + this.isUnderlyingPosition, + this.isNotFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill both with children both after reverse.', function() { + this.checkFills( + 'both', + 'both', + this.isFillingBackwards, + this.isFillingForwards, + this.isFillingBackwardsDuring, + this.isFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill both with children backwards after reverse.', function() { + this.checkFills( + 'both', + 'backwards', + this.isFillingBackwards, + this.isNotFillingForwards, + this.isFillingBackwardsDuring, + this.isFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill both with children forwards after reverse.', function() { + this.checkFills( + 'both', + 'forwards', + this.isUnderlyingPosition, + this.isFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill none with children fill none after reverse.', function() { + this.checkFills( + 'none', + 'none', + this.isUnderlyingPosition, + this.isNotFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill none with children fill both after reverse.', function() { + this.checkFills( + 'none', + 'both', + this.isFillingBackwards, + this.isFillingForwards, + this.isFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill none with children fill backwards after reverse.', function() { + this.checkFills( + 'none', + 'backwards', + this.isFillingBackwards, + this.isNotFillingForwards, + this.isFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + test('Fill modes work for sequence fill none with children fill forwards after reverse.', function() { + this.checkFills( + 'none', + 'forwards', + this.isUnderlyingPosition, + this.isFillingForwards, + this.isNotFillingBackwardsDuring, + this.isNotFillingBackwards, + true + ); + }); + + test('Setting the playbackRate on sequence animations updates child timing. ' + + 'Any children who are not finished go into effect.', function() { + var sequenceEffect = new SequenceEffect([ + new KeyframeEffect(null, [], 1000), + new KeyframeEffect(null, [], 1000), + ]); + var a = document.timeline.play(sequenceEffect); + tick(0); + + a.playbackRate = 2; + assert.equal(a._animation.playbackRate, 2, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, 2, 'It also updates the child animations'); + }); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, null); + assert.equal(a._childAnimations[0].startTime, null); + assert.equal(a._childAnimations[1].startTime, null); + + tick(1); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, 1); + assert.equal(a._childAnimations[0].startTime, 1); + assert.equal(a._childAnimations[1].startTime, 501); + + tick(601); + assert.equal(a.currentTime, 1200); + assert.equal(a._childAnimations[0].currentTime, 1000); + assert.equal(a._childAnimations[1].currentTime, 200); + assert.equal(a.startTime, 1); + assert.equal(a._childAnimations[0].startTime, 1); + assert.equal(a._childAnimations[1].startTime, 501); + + tick(1101); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 1000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, 1); + assert.equal(a._childAnimations[0].startTime, 1); + assert.equal(a._childAnimations[1].startTime, 501); + + a.playbackRate = -1; + assert.equal(a._animation.playbackRate, -1, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, -1, 'It also updates the child animations'); + }); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 2000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, null); + assert.equal(a._childAnimations[0].startTime, null); + assert.equal(a._childAnimations[1].startTime, null); + + tick(1102); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 2000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, 3102); + assert.equal(a._childAnimations[0].startTime, 3102); + assert.equal(a._childAnimations[1].startTime, 2102); + + tick(1602); + assert.equal(a.currentTime, 1500); + assert.equal(a._childAnimations[0].currentTime, 1500); + assert.equal(a._childAnimations[1].currentTime, 500); + assert.equal(a.startTime, 3102); + assert.equal(a._childAnimations[0].startTime, 3102); + assert.equal(a._childAnimations[1].startTime, 2102); + + tick(3103); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, 0); + assert.equal(a.startTime, 3102); + assert.equal(a._childAnimations[0].startTime, 3102); + assert.equal(a._childAnimations[1].startTime, 2102); + + a.playbackRate = 1; + assert.equal(a._animation.playbackRate, 1, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, 1, 'It also updates the child animations'); + }); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, null); + assert.equal(a._childAnimations[0].startTime, null); + assert.equal(a._childAnimations[1].startTime, null); + + tick(3104); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, 3104); + assert.equal(a._childAnimations[0].startTime, 3104); + assert.equal(a._childAnimations[1].startTime, 4104); + + tick(3604); + assert.equal(a.currentTime, 500); + assert.equal(a._childAnimations[0].currentTime, 500); + assert.equal(a._childAnimations[1].currentTime, -500); + assert.equal(a.startTime, 3104); + assert.equal(a._childAnimations[0].startTime, 3104); + assert.equal(a._childAnimations[1].startTime, 4104); + } + ); + + test('Reversing a sequence animation updates child timing correctly', function() { + var sequenceEffect = new SequenceEffect([ + new KeyframeEffect(null, [], 1000), + new KeyframeEffect(null, [], 1000), + ]); + var a = document.timeline.play(sequenceEffect); + tick(0); + + a.playbackRate = 2; + assert.equal(a._animation.playbackRate, 2, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, 2, 'It also updates the child animations'); + }); + tick(1); + tick(1101); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 1000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, 1); + assert.equal(a._childAnimations[0].startTime, 1); + assert.equal(a._childAnimations[1].startTime, 501); + + a.reverse(); + assert.equal(a._animation.playbackRate, -2, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, -2, 'It also updates the child animations'); + }); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 2000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, null); + assert.equal(a._childAnimations[0].startTime, null); + assert.equal(a._childAnimations[1].startTime, null); + + tick(1102); + assert.equal(a.currentTime, 2000); + assert.equal(a._childAnimations[0].currentTime, 2000); + assert.equal(a._childAnimations[1].currentTime, 1000); + assert.equal(a.startTime, 2102); + assert.equal(a._childAnimations[0].startTime, 2102); + assert.equal(a._childAnimations[1].startTime, 1602); + + tick(1602); + assert.equal(a.currentTime, 1000); + assert.equal(a._childAnimations[0].currentTime, 1000); + assert.equal(a._childAnimations[1].currentTime, 0); + assert.equal(a.startTime, 2102); + assert.equal(a._childAnimations[0].startTime, 2102); + assert.equal(a._childAnimations[1].startTime, 1602); + + tick(3103); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, 0); + assert.equal(a.startTime, 2102); + assert.equal(a._childAnimations[0].startTime, 2102); + assert.equal(a._childAnimations[1].startTime, 1602); + + a.reverse(); + assert.equal(a._animation.playbackRate, 2, 'Updates the playbackRate of the inner animation'); + a._childAnimations.forEach(function(childAnimation) { + assert.equal(childAnimation.playbackRate, 2, 'It also updates the child animations'); + }); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, null); + assert.equal(a._childAnimations[0].startTime, null); + assert.equal(a._childAnimations[1].startTime, null); + + tick(3104); + assert.equal(a.currentTime, 0); + assert.equal(a._childAnimations[0].currentTime, 0); + assert.equal(a._childAnimations[1].currentTime, -1000); + assert.equal(a.startTime, 3104); + assert.equal(a._childAnimations[0].startTime, 3104); + assert.equal(a._childAnimations[1].startTime, 3604); + + tick(3604); + assert.equal(a.currentTime, 1000); + assert.equal(a._childAnimations[0].currentTime, 1000); + assert.equal(a._childAnimations[1].currentTime, 0); + assert.equal(a.startTime, 3104); + assert.equal(a._childAnimations[0].startTime, 3104); + assert.equal(a._childAnimations[1].startTime, 3604); + }); + + test('delays on groups work correctly', function() { + // 444 + // 1 + // 0 + // 33 + // 2 + var groupEffect = new GroupEffect([ + new GroupEffect([ + this.staticEffect(this.target, '4px', {duration: 3, delay: 1}), + this.staticEffect(this.target, '1px', {duration: 1, delay: 0}), + ], {delay: 1}), + new SequenceEffect([ + this.staticEffect(this.target, '0px', {duration: 1, delay: 0}), + this.staticEffect(this.target, '3px', {duration: 2, delay: 1}), + this.staticEffect(this.target, '2px', {duration: 1, delay: -2}), + ]), + ]); + var animation = document.timeline.play(groupEffect); + tick(100); + checkTimes(animation, [100, 0], [ + [ + [101, -1], + [101, -1], + ], [ + [100, 0], + [101, -1], + [104, -4], + ] + ]); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + tick(101); + assert.equal(getComputedStyle(this.target).marginLeft, '1px'); + tick(102); + assert.equal(getComputedStyle(this.target).marginLeft, '2px'); + tick(103); + assert.equal(getComputedStyle(this.target).marginLeft, '3px'); + tick(104); + assert.equal(getComputedStyle(this.target).marginLeft, '4px'); + tick(105); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + }); + + test('end delays on groups work correctly', function() { + // 11 + // 4 + // 0 + // 33 + // 2 + var sequenceEffect = new SequenceEffect([ + new SequenceEffect([ + this.staticEffect(this.target, '1px', {duration: 2, endDelay: 2}), + this.staticEffect(this.target, '4px', {duration: 1, endDelay: 1}), + ], {endDelay: -6}), + new SequenceEffect([ + this.staticEffect(this.target, '0px', {duration: 1, endDelay: 1}), + this.staticEffect(this.target, '3px', {duration: 2, endDelay: -2}), + this.staticEffect(this.target, '2px', {duration: 1, endDelay: 2}), + ]), + ]); + var animation = document.timeline.play(sequenceEffect); + tick(100); + checkTimes(animation, [100, 0], [ + [ + [100, 0], + [104, -4], + ], [ + [100, 0], + [102, -2], + [102, -2], + ] + ]); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + tick(101); + assert.equal(getComputedStyle(this.target).marginLeft, '1px'); + tick(102); + assert.equal(getComputedStyle(this.target).marginLeft, '2px'); + tick(103); + assert.equal(getComputedStyle(this.target).marginLeft, '3px'); + tick(104); + // FIXME: Group child animation limiting bounds should match the parent animation's limiting bounds. + // assert.equal(getComputedStyle(this.target).marginLeft, '4px'); + // tick(105); + // assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + }); + + test('basic animation operations are working', function() { + var animations = []; + animations.push(document.timeline.play(this.emptySeq)); + animations.push(document.timeline.play(this.seqSimple)); + animations.push(document.timeline.play(this.seqWithSeq)); + animations.push(document.timeline.play(this.seqWithGroup)); + animations.push(document.timeline.play(this.seqWithEmptyGroup)); + animations.push(document.timeline.play(this.seqWithEmptySeq)); + + animations.push(document.timeline.play(this.emptyGroup)); + animations.push(document.timeline.play(this.groupSimple)); + animations.push(document.timeline.play(this.groutWithSeq)); + animations.push(document.timeline.play(this.groupWithGroup)); + animations.push(document.timeline.play(this.groupWithEmptyGroup)); + animations.push(document.timeline.play(this.groupWithEmptySeq)); + + var length = animations.length; + + tick(50); + for (var i = 0; i < length; i++) + animations[i].pause(); + + tick(100); + for (var i = 0; i < length; i++) + animations[i].play(); + + tick(200); + for (var i = 0; i < length; i++) + animations[i].currentTime += 1; + + tick(300); + for (var i = 0; i < length; i++) + animations[i].startTime += 1; + + tick(350); + for (var i = 0; i < length; i++) + animations[i].reverse(); + + tick(400); + for (var i = 0; i < length; i++) + animations[i].finish(); + + tick(500); + tick(600); + for (var i = 0; i < length; i++) + animations[i].cancel(); + + for (var i = 0; i < length; i++) + animations[i].play(); + }); + + test('pausing works as expected with an empty SequenceEffect', function() { + var animation = document.timeline.play(this.emptySeq); + tick(0); + assert.equal(animation.startTime, 0); + assert.equal(animation.currentTime, 0); + + animation.pause(); + assert.equal(animation.startTime, null); + assert.equal(animation.currentTime, 0); + }); + + test('pausing works as expected with a simple SequenceEffect', function() { + var animation = document.timeline.play(this.seqSimple); + var target = this.seqSimple.children[0].target; + tick(0); + checkTimes(animation, [0, 0], [[0, 0], [500, -500]], 't = 0'); + + tick(200); + checkTimes(animation, [0, 200], [[0, 200], [500, -300]], 't = 200'); + + animation.pause(); + checkTimes(animation, [null, null], [[null, null], [null, null]], 't = 200'); + assert.equal(getComputedStyle(target).marginLeft, '40px'); + + tick(300); + checkTimes(animation, [null, 200], [[null, 200], [null, -300]], 't = 300'); + assert.equal(getComputedStyle(target).marginLeft, '40px'); + + animation.play(); + checkTimes(animation, [null, 200], [[null, 200], [null, -300]], 't = 300'); + assert.equal(getComputedStyle(target).marginLeft, '40px'); + + tick(301); + checkTimes(animation, [101, 200], [[101, 200], [601, -300]], 't = 301'); + assert.equal(getComputedStyle(target).marginLeft, '40px'); + + tick(401); + checkTimes(animation, [101, 300], [[101, 300], [601, -200]], 't = 401'); + assert.equal(getComputedStyle(target).marginLeft, '60px'); + + tick(700); + checkTimes(animation, [101, 599], [[101, 500], [601, 99]], 't = 700'); + assert.equal(getComputedStyle(target).marginLeft, '0px'); + }); + + test('pausing before tick works as expected with a simple SequenceEffect', function() { + var animation = document.timeline.play(this.seqSimple); + var target = this.seqSimple.children[0].target; + checkTimes(animation, [null, 0], [[null, 0], [null, -500]], 't = 0'); + + animation.pause(); + checkTimes(animation, [null, null], [[null, null], [null, null]], 't = 0'); + assert.equal(getComputedStyle(target).marginLeft, '0px'); + + tick(10); + checkTimes(animation, [null, 0], [[null, 0], [null, -500]], 't = 10'); + assert.equal(getComputedStyle(target).marginLeft, '0px'); + + tick(20); + checkTimes(animation, [null, 0], [[null, 0], [null, -500]], 't = 10'); + assert.equal(getComputedStyle(target).marginLeft, '0px'); + }); + + test('pausing and seeking before tick works as expected with a simple SequenceEffect', function() { + var animation = document.timeline.play(this.seqSimple); + animation.pause(); + + animation.currentTime = 0; + checkTimes(animation, [null, 0], [[null, 0], [null, -500]], 't = 10'); + + animation.currentTime = 250; + checkTimes(animation, [null, 250], [[null, 250], [null, -250]], 't = 10'); + + animation.currentTime = 500; + checkTimes(animation, [null, 500], [[null, 500], [null, 0]], 't = 10'); + + // FIXME: Expectation should be [null, 1000], [[null, 500], [null, 500]]. + animation.currentTime = 1000; + checkTimes(animation, [null, 1000], [[null, 1000], [null, 500]], 't = 10'); + }); + + test('pausing works as expected with an SequenceEffect inside an SequenceEffect', function() { + var animation = document.timeline.play(this.seqWithSeq); + tick(0); + checkTimes( + animation, + [0, 0], [ + [0, 0], + [500, -500], [ + [1000, -1000], + [1500, -1500]]], + 't = 0'); + + tick(200); + checkTimes( + animation, + [0, 200], [ + [0, 200], + [500, -300], [ + [1000, -800], + [1500, -1300]]], + 't = 200'); + + animation.pause(); + checkTimes( + animation, + [null, null], [ + [null, null], + [null, null], [ + [null, null], + [null, null]]], + 't = 200'); + + tick(300); + checkTimes( + animation, + [null, 200], [ + [null, 200], + [null, -300], [ + [null, -800], + [null, -1300]]], + 't = 300'); + + animation.play(); + tick(310); + checkTimes( + animation, + [110, 200], [ + [110, 200], + [610, -300], [ + [1110, -800], + [1610, -1300]]], + 't = 310'); + + tick(1300); + checkTimes( + animation, + [110, 1190], [ + [110, 500], + [610, 500], [ + [1110, 190], + [1610, -310]]], + 't = 1300'); + + animation.pause(); + checkTimes( + animation, + [null, null], [ + [null, 500], + [null, 500], [ + [null, null], + [null, null]]], + 't = 1300'); + + tick(1400); + checkTimes( + animation, + [null, 1190], [ + [null, 500], + [null, 500], [ + [null, 190], + [null, -310]]], + 't = 1400'); + + animation.play(); + checkTimes( + animation, + [null, 1190], [ + [null, 500], + [null, 500], [ + [null, 190], + [null, -310]]], + 't = 1400'); + + tick(1410); + checkTimes( + animation, + [220, 1190], [ + [220, 500], + [720, 500], [ + [1220, 190], + [1720, -310]]], + 't = 1410'); + + tick(1600); + checkTimes( + animation, + [220, 1380], [ + [220, 500], + [720, 500], [ + [1220, 380], + [1720, -120]]], + 't = 1600'); + + animation.pause(); + checkTimes( + animation, + [null, null], [ + [null, 500], + [null, 500], [ + [null, null], + [null, null]]], + 't = 1600'); + + tick(1700); + checkTimes( + animation, + [null, 1380], [ + [null, 500], + [null, 500], [ + [null, 380], + [null, -120]]], + 't = 1700'); + + animation.play(); + tick(1710); + checkTimes( + animation, + [330, 1380], [ + [330, 500], + [830, 500], [ + [1330, 380], + [1830, -120]]], + 't = 1710'); + + tick(2400); + checkTimes( + animation, + [330, 2000], [ + [330, 500], + [830, 500], [ + [1330, 500], + [1830, 500]]], + 't = 2400'); + }); + + test('pausing works as expected with a GroupEffect inside an SequenceEffect', function() { + var animation = document.timeline.play(this.seqWithGroup); + tick(0); + checkTimes( + animation, + [0, 0], [ + [0, 0], + [500, -500], [ + [1000, -1000], + [1000, -1000]]], + 't = 0'); + + tick(200); + checkTimes( + animation, + [0, 200], [ + [0, 200], + [500, -300], [ + [1000, -800], + [1000, -800]]], + 't = 200'); + + animation.pause(); + checkTimes( + animation, + [null, null], [ + [null, null], + [null, null], [ + [null, null], + [null, null]]], + 't = 200'); + + tick(300); + checkTimes( + animation, + [null, 200], [ + [null, 200], + [null, -300], [ + [null, -800], + [null, -800]]], + 't = 300'); + + animation.play(); + tick(310); + checkTimes( + animation, + [110, 200], [ + [110, 200], + [610, -300], [ + [1110, -800], + [1110, -800]]], + 't = 310'); + + tick(1310); + checkTimes( + animation, + [110, 1200], [ + [110, 500], + [610, 500], [ + [1110, 200], + [1110, 200]]], + 't = 1310'); + + animation.pause(); + checkTimes( + animation, + [null, null], [ + [null, 500], + [null, 500], [ + [null, null], + [null, null]]], + 't = 1310'); + + tick(1400); + checkTimes( + animation, + [null, 1200], [ + [null, 500], + [null, 500], [ + [null, 200], + [null, 200]]], + 't = 1410'); + + animation.play(); + tick(1410); + checkTimes( + animation, + [210, 1200], [ + [210, 500], + [710, 500], [ + [1210, 200], + [1210, 200]]], + 't = 1410'); + + tick(1610); + checkTimes( + animation, + [210, 1400], [ + [210, 500], + [710, 500], [ + [1210, 400], + [1210, 400]]], + 't = 1610'); + + animation.pause(); + tick(1810); + checkTimes( + animation, + [null, 1400], [ + [null, 500], + [null, 500], [ + [null, 400], + [null, 400]]], + 't = 1810'); + + animation.play(); + tick(1820); + checkTimes( + animation, + [420, 1400], [ + [420, 500], + [920, 500], [ + [1420, 400], + [1420, 400]]], + 't = 1820'); + + tick(2020); + checkTimes( + animation, + [420, 1500], [ + [420, 500], + [920, 500], [ + [1420, 500], + [1420, 500]]], + 't = 2020'); + + animation.pause(); + checkTimes( + animation, + [null, 1500], [ + [null, 500], + [null, 500], [ + [null, 500], + [null, 500]]], + 't = 2020'); + }); + + test('pausing works as expected with an empty SequenceEffect inside an SequenceEffect', function() { + var animation = document.timeline.play(this.seqWithEmptySeq); + tick(0); + checkTimes( + animation, + [0, 0], [0, 0], + 't = 0'); + + animation.pause(); + checkTimes( + animation, + [null, 0], [null, 0], + 't = 0 after pause'); + }); + + test('pausing works as expected with an empty GroupEffect inside an SequenceEffect', function() { + var animation = document.timeline.play(this.seqWithEmptyGroup); + tick(0); + checkTimes( + animation, + [0, 0], [0, 0], + 't = 0'); + + animation.pause(); + checkTimes( + animation, + [null, 0], [null, 0], + 't = 0 after pause'); + }); + + test('playState works for groups', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + var sequenceEffect = new SequenceEffect([new KeyframeEffect(target, [], 100), new KeyframeEffect(target, [], 100)]); + var a = document.timeline.play(sequenceEffect); + assert.equal(a.playState, 'pending'); + tick(1); + assert.equal(a.playState, 'running'); + assert.equal(a._childAnimations[0]._animation.playState, 'running'); + assert.equal(a._childAnimations[1]._animation.playState, 'running'); + tick(101); + assert.equal(a.playState, 'running'); + assert.equal(a._childAnimations[0]._animation.playState, 'finished'); + assert.equal(a._childAnimations[1]._animation.playState, 'running'); + a.pause(); + assert.equal(a.playState, 'pending'); + assert.equal(a._childAnimations[0]._animation.playState, 'paused'); + assert.equal(a._childAnimations[1]._animation.playState, 'pending'); + tick(102); + assert.equal(a.playState, 'paused'); + assert.equal(a._childAnimations[0]._animation.playState, 'paused'); + assert.equal(a._childAnimations[1]._animation.playState, 'paused'); + a.play(); + assert.equal(a.playState, 'pending'); + assert.equal(a._childAnimations[0]._animation.playState, 'pending'); + assert.equal(a._childAnimations[1]._animation.playState, 'pending'); + tick(103); + assert.equal(a.playState, 'running'); + assert.equal(a._childAnimations[0]._animation.playState, 'finished'); + assert.equal(a._childAnimations[1]._animation.playState, 'running'); + tick(204); + assert.equal(a.playState, 'finished'); + assert.equal(a._childAnimations[0]._animation.playState, 'finished'); + assert.equal(a._childAnimations[1]._animation.playState, 'finished'); + }); + + test('pausing then seeking out of range then seeking into range works', function() { + var target = document.createElement('div'); + var keyframeEffect = new KeyframeEffect(target, [], {duration: 2000, fill: 'both'}); + var groupEffect = new GroupEffect([keyframeEffect], {fill: 'none'}); + var animation = document.timeline.play(groupEffect); + + animation.pause(); + animation.currentTime = 3000; + assert.equal(animation._childAnimations.length, 0); + tick(100); + animation.currentTime = 1000; + assert.equal(animation._childAnimations.length, 1); + assert.equal(animation._childAnimations[0]._animation.playState, 'paused'); + assert.equal(animation._childAnimations[0]._animation.currentTime, 1000); + + }); + + test('reversing then seeking out of range then seeking into range works', function() { + var target = document.createElement('div'); + var keyframeEffect = new KeyframeEffect(target, [], {duration: 2000, fill: 'both'}); + var groupEffect = new GroupEffect([keyframeEffect], {fill: 'none'}); + var animation = document.timeline.play(groupEffect); + + animation.currentTime = 1000; + tick(100); + animation.reverse(); + tick(105); + animation.currentTime = 3000; + assert.equal(animation._childAnimations.length, 0); + tick(110); + animation.currentTime = 1000; + assert.equal(animation.playbackRate, -1); + assert.equal(animation._childAnimations.length, 1); + assert.equal(animation._childAnimations[0]._animation.playState, 'running'); + assert.equal(animation._childAnimations[0]._animation.currentTime, 1000); + assert.equal(animation._childAnimations[0]._animation.playbackRate, -1); + + }); + + test('fill none groups with fill none children do not fill', function() { + var keyframeEffect = new KeyframeEffect( + this.target, + [{marginLeft: '0px'}, {marginLeft: '100px'}], + {duration: 500, fill: 'none'}); + var groupEffect = new GroupEffect([keyframeEffect], {fill: 'none'}); + var animation = document.timeline.play(groupEffect); + + tick(0); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + tick(250); + assert.equal(getComputedStyle(this.target).marginLeft, '50px'); + tick(501); + assert.equal(getComputedStyle(this.target).marginLeft, '0px'); + tick(502); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/group-constructors.js b/scripts/vendor/web-animations-js/test/js/group-constructors.js new file mode 100755 index 0000000000..b8ba6a6cc8 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/group-constructors.js @@ -0,0 +1,22 @@ +suite('group-constructors', function() { + function simpleGroupEffect() { + return new SequenceEffect([ + new KeyframeEffect(document.body, [], 2000), + new GroupEffect([ + new KeyframeEffect(document.body, [], 2000), + new KeyframeEffect(document.body, [], 1000) + ]) + ]); + } + + test('animation getter for children in groups works as expected', function() { + var anim = document.timeline.play(simpleGroupEffect()); + tick(0); + assert.equal(anim.effect.animation, anim); + assert.equal(anim._childAnimations[0].effect.animation, anim); + assert.equal(anim._childAnimations[1].effect.animation, anim); + tick(2100); + assert.equal(anim._childAnimations[1]._childAnimations[0].effect.animation, anim); + assert.equal(anim._childAnimations[1]._childAnimations[1].effect.animation, anim); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/interpolation.js b/scripts/vendor/web-animations-js/test/js/interpolation.js new file mode 100755 index 0000000000..d69158d35d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/interpolation.js @@ -0,0 +1,16 @@ +suite('interpolation', function() { + test('interpolate numbers', function() { + assert.equal(interpolate(4, 2, 0.2), 3.6); + }); + test('interpolate bools', function() { + assert.equal(interpolate(false, true, 0.4), false); + assert.equal(interpolate(false, true, 0.5), true); + assert.equal(interpolate(false, true, 0.5), true); + }); + test('interpolate lists', function() { + assert.deepEqual(interpolate([1, 2, 3], [4, 5, 6], 0.5), [2.5, 3.5, 4.5]); + assert.deepEqual(interpolate([1], [4], 0.6), [2.8]); + assert.deepEqual(interpolate([false], [true], 0.6), [true]); + assert.deepEqual(interpolate([1, false, [3, 6]], [4, true, [6, 8]], 0.6), [2.8, true, [4.8, 7.2]]); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/keyframe-effect-constructor.js b/scripts/vendor/web-animations-js/test/js/keyframe-effect-constructor.js new file mode 100755 index 0000000000..2b7be6c4a0 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/keyframe-effect-constructor.js @@ -0,0 +1,80 @@ +suite('keyframe-effect-constructor', function() { + setup(function() { + document.timeline.getAnimations().forEach(function(animation) { + animation.cancel(); + }); + }); + + test('Playing a KeyframeEffect makes an Animation', function() { + var keyframeEffect = new KeyframeEffect(document.body, [], 1000); + assert.equal(document.body.getAnimations().length, 0); + + var animation = document.timeline.play(keyframeEffect); + tick(200); + assert.equal(document.body.getAnimations().length, 1); + + tick(1600); + assert.equal(document.body.getAnimations().length, 0); + }); + + test('Setting the timing function on a KeyframeEffect works', function() { + function leftAsNumber(target) { + left = getComputedStyle(target).left; + return Number(left.substring(0, left.length - 2)); + } + + var target1 = document.createElement('div'); + var target2 = document.createElement('div'); + target1.style.position = 'absolute'; + target2.style.position = 'absolute'; + document.body.appendChild(target1); + document.body.appendChild(target2); + + var keyframeEffect1 = new KeyframeEffect(target1, [{left: '0px'}, {left: '50px'}], 1000); + var keyframeEffect2 = new KeyframeEffect(target2, [{left: '0px'}, {left: '50px'}], {duration: 1000, easing: 'ease-in'}); + + var animation1 = document.timeline.play(keyframeEffect1); + var animation2 = document.timeline.play(keyframeEffect2); + + tick(0); + assert.equal(leftAsNumber(target1), 0); + assert.equal(leftAsNumber(target2), 0); + + tick(250); + assert.closeTo(leftAsNumber(target1), 12.5, 1); + assert.closeTo(leftAsNumber(target2), 4.65, 1); + + tick(500); + assert.closeTo(leftAsNumber(target1), 25, 1); + assert.closeTo(leftAsNumber(target2), 15.25, 1); + }); + + test('Timing is always converted to an AnimationEffectTiming', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + + var keyframes = [{background: 'blue'}, {background: 'red'}]; + + var keyframeEffect = new KeyframeEffect(target, keyframes, 200); + assert.equal(keyframeEffect.timing.duration, 200); + + keyframeEffect = new KeyframeEffect(target, keyframes); + assert.isDefined(keyframeEffect.timing); + + keyframeEffect = new KeyframeEffect(target, keyframes, {duration: 200}); + var group = new GroupEffect([keyframeEffect]); + assert.equal(group.timing.duration, 'auto'); + }); + + test('Handle null target for KeyframeEffect', function() { + var keyframeEffect = new KeyframeEffect(null, function(tf) { + // noop + }, 200); + + var animation = document.timeline.play(keyframeEffect); + assert.isNotNull(animation); + tick(50); + tick(150); + assert.equal(animation.currentTime, 100); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/keyframes.js b/scripts/vendor/web-animations-js/test/js/keyframes.js new file mode 100755 index 0000000000..d46b154d20 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/keyframes.js @@ -0,0 +1,498 @@ + +function leftAsNumber(target) { + var left = getComputedStyle(target).left; + return Number(left.substring(0, left.length - 2)); +} + +suite('keyframes', function() { + // Test normalize. + test('Normalize keyframes with all offsets specified but not sorted by offset. Some offsets are out of [0, 1] range.', function() { + var normalizedKeyframes; + assert.throws(function() { + normalizedKeyframes = normalizeKeyframes([ + {offset: 0}, + {offset: -1}, + {offset: 1}, + {offset: 0.5}, + {offset: 2} + ]); + }); + }); + + test('Normalize keyframes with some offsets not specified, and not sorted by offset.', function() { + assert.throws(function() { + normalizeKeyframes([ + {offset: 0.5}, + {offset: 0}, + {offset: 0.8}, + {}, + {offset: 1} + ]); + }); + }); + + test('Normalize keyframes with some offsets not specified, and not sorted by offset. Out of order keyframes are out of [0, 1] range.', function() { + assert.throws(function() { + normalizeKeyframes([ + {offset: 0}, + {offset: -1}, + {offset: 0.5}, + {}, + {offset: 1} + ]); + }); + }); + + test('Normalize keyframes with some offsets not specified, but sorted by offset where specified. Some offsets are out of [0, 1] range.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {offset: -1}, + {offset: 0}, + {offset: 0.5}, + {}, + {}, + {offset: 2} + ]); + }); + assert.equal(normalizedKeyframes.length, 4); + assert.closeTo(normalizedKeyframes[0].offset, 0, 0.001); + assert.closeTo(normalizedKeyframes[1].offset, 0.5, 0.001); + assert.closeTo(normalizedKeyframes[2].offset, 0.75, 0.001); + assert.closeTo(normalizedKeyframes[3].offset, 1, 0.001); + }); + + test('Normalize keyframes with some offsets not specified, but sorted by offset where specified. All specified offsets in [0, 1] range.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {left: '0px', offset: 0}, + {left: '10px'}, + {left: '20px'}, + {left: '30px', offset: 0.6}, + {left: '40px'}, + {left: '50px'} + ]); + }); + assert.equal(normalizedKeyframes.length, 6); + assert.closeTo(normalizedKeyframes[0].offset, 0, 0.001); + assert.equal(normalizedKeyframes[0].left, '0px'); + assert.closeTo(normalizedKeyframes[1].offset, 0.2, 0.001); + assert.equal(normalizedKeyframes[1].left, '10px'); + assert.closeTo(normalizedKeyframes[2].offset, 0.4, 0.001); + assert.equal(normalizedKeyframes[2].left, '20px'); + assert.closeTo(normalizedKeyframes[3].offset, 0.6, 0.001); + assert.equal(normalizedKeyframes[3].left, '30px'); + assert.closeTo(normalizedKeyframes[4].offset, 0.8, 0.001); + assert.equal(normalizedKeyframes[4].left, '40px'); + assert.closeTo(normalizedKeyframes[5].offset, 1, 0.001); + assert.equal(normalizedKeyframes[5].left, '50px'); + }); + + test('Normalize keyframes with no offsets specified.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {left: '0px'}, + {left: '10px'}, + {left: '20px'}, + {left: '30px'}, + {left: '40px'} + ]); + }); + assert.equal(normalizedKeyframes.length, 5); + assert.closeTo(normalizedKeyframes[0].offset, 0, 0.001); + assert.equal(normalizedKeyframes[0].left, '0px'); + assert.closeTo(normalizedKeyframes[1].offset, 0.25, 0.001); + assert.equal(normalizedKeyframes[1].left, '10px'); + assert.closeTo(normalizedKeyframes[2].offset, 0.5, 0.001); + assert.equal(normalizedKeyframes[2].left, '20px'); + assert.closeTo(normalizedKeyframes[3].offset, 0.75, 0.001); + assert.equal(normalizedKeyframes[3].left, '30px'); + assert.closeTo(normalizedKeyframes[4].offset, 1, 0.001); + assert.equal(normalizedKeyframes[4].left, '40px'); + }); + + test('Normalize keyframes where a keyframe has an offset that is not a number.', function() { + assert.throws(function() { + normalizeKeyframes([ + {offset: 0}, + {offset: 'one'}, + {offset: 1} + ]); + }); + }); + + test('Normalize keyframes where a keyframe has an offset that is a numeric string.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {offset: 0}, + {offset: '0.5'}, + {offset: 1} + ]); + }); + assert.equal(normalizedKeyframes.length, 3); + assert.closeTo(normalizedKeyframes[0].offset, 0, 0.001); + assert.closeTo(normalizedKeyframes[1].offset, 0.5, 0.001); + assert.closeTo(normalizedKeyframes[2].offset, 1, 0.001); + }); + + test('Normalize keyframes where some keyframes have easings.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {left: '0px', easing: 'ease-in'}, + {left: '10px'}, + {left: '0px'} + ]); + }); + }); + + test('Normalize keyframes with invalid specified easing.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {left: '0px', easing: 'easy-peasy'}, + {left: '10px'}, + {left: '0px'} + ]); + }); + assert.equal('' + normalizedKeyframes[0].easing, 'function (x) { return x; }'); + }); + + test('Normalize keyframes where some properties are given non-string, non-number values.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([ + {left: {}}, + {left: '100px'}, + {left: []} + ]); + }); + assert(normalizedKeyframes.length, 3); + assert.equal(normalizedKeyframes[0].left, '[object Object]'); + assert.equal(normalizedKeyframes[1].left, '100px'); + assert.equal(normalizedKeyframes[2].left, ''); + }); + + test('Normalize input that is not an array.', function() { + assert.throws(function() { + normalizeKeyframes(10); + }); + }); + + test('Normalize an empty array.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([]); + }); + assert.deepEqual(normalizedKeyframes, []); + }); + + test('Normalize null.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes(null); + }); + assert.deepEqual(normalizedKeyframes, []); + }); + + test('Normalize shorthands.', function() { + var normalizedKeyframes; + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([{borderColor: 'purple green orange blue'}, {borderColor: 'red'}]); + }); + assert.equal(normalizedKeyframes[0].borderTopColor, 'purple'); + assert.equal(normalizedKeyframes[0].borderRightColor, 'green'); + assert.equal(normalizedKeyframes[0].borderBottomColor, 'orange'); + assert.equal(normalizedKeyframes[0].borderLeftColor, 'blue'); + assert.equal(normalizedKeyframes[1].borderTopColor, 'red'); + assert.equal(normalizedKeyframes[1].borderRightColor, 'red'); + assert.equal(normalizedKeyframes[1].borderBottomColor, 'red'); + assert.equal(normalizedKeyframes[1].borderLeftColor, 'red'); + + assert.doesNotThrow(function() { + normalizedKeyframes = normalizeKeyframes([{font: 'italic bold 20pt / 200% serif'}, {font: 'italic normal bold 50pt serif'}]); + }); + assert.equal(normalizedKeyframes[0].fontStyle, 'italic'); + assert.equal(normalizedKeyframes[0].fontVariant, 'normal'); + assert.equal(normalizedKeyframes[0].fontWeight, '700'); + assert.equal(normalizedKeyframes[0].fontSize, '20pt'); + assert.equal(normalizedKeyframes[0].lineHeight, '200%'); + assert.equal(normalizedKeyframes[0].fontFamily, 'serif'); + assert.equal(normalizedKeyframes[1].fontStyle, 'italic'); + assert.equal(normalizedKeyframes[1].fontVariant, 'normal'); + assert.equal(normalizedKeyframes[1].fontWeight, '700'); + assert.equal(normalizedKeyframes[1].fontSize, '50pt'); + assert.equal(normalizedKeyframes[1].lineHeight, 'normal'); + assert.equal(normalizedKeyframes[1].fontFamily, 'serif'); + }); + + // Test makePropertySpecificKeyframeGroups. + test('Make property specific keyframe groups for a simple keyframe list with one property.', function() { + var groups; + assert.doesNotThrow(function() { + groups = makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px'}, + {left: '200px', offset: 0.3}, + {left: '0px'} + ])); + }); + assert.equal(Object.getOwnPropertyNames(groups).length, 1); + assert.equal(groups.left.length, 3); + assert.closeTo(groups.left[0].offset, 0, 0.001); + assert.equal(groups.left[0].value, '0px'); + assert.closeTo(groups.left[1].offset, 0.3, 0.001); + assert.equal(groups.left[1].value, '200px'); + assert.closeTo(groups.left[2].offset, 1, 0.001); + assert.equal(groups.left[2].value, '0px'); + }); + + test('Make property specific keyframe groups for an keyframe list with three properties.', function() { + var groups; + assert.doesNotThrow(function() { + groups = makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px', top: '200px', opacity: 1}, + {left: '200px', top: '0px'}, + {left: '0px', top: '200px', opacity: 0}, + {top: '0px', opacity: 1}, + {left: '200px', top: '200px', opacity: 0} + ])); + }); + assert.equal(Object.getOwnPropertyNames(groups).length, 3); + + assert.equal(groups.left.length, 4); + assert.closeTo(groups.left[0].offset, 0, 0.001); + assert.equal(groups.left[0].value, '0px'); + assert.closeTo(groups.left[1].offset, 0.25, 0.001); + assert.equal(groups.left[1].value, '200px'); + assert.closeTo(groups.left[2].offset, 0.5, 0.001); + assert.equal(groups.left[2].value, '0px'); + assert.closeTo(groups.left[3].offset, 1, 0.001); + assert.equal(groups.left[3].value, '200px'); + + assert.equal(groups.top.length, 5); + assert.closeTo(groups.top[0].offset, 0, 0.001); + assert.equal(groups.top[0].value, '200px'); + assert.closeTo(groups.top[1].offset, 0.25, 0.001); + assert.equal(groups.top[1].value, '0px'); + assert.closeTo(groups.top[2].offset, 0.5, 0.001); + assert.equal(groups.top[2].value, '200px'); + assert.closeTo(groups.top[3].offset, 0.75, 0.001); + assert.equal(groups.top[3].value, '0px'); + assert.closeTo(groups.top[4].offset, 1, 0.001); + assert.equal(groups.top[4].value, '200px'); + + assert.equal(groups.opacity.length, 4); + assert.closeTo(groups.opacity[0].offset, 0, 0.001); + assert.equal(groups.opacity[0].value, 1); + assert.closeTo(groups.opacity[1].offset, 0.5, 0.001); + assert.equal(groups.opacity[1].value, 0); + assert.closeTo(groups.opacity[2].offset, 0.75, 0.001); + assert.equal(groups.opacity[2].value, 1); + assert.closeTo(groups.opacity[3].offset, 1, 0.001); + assert.equal(groups.opacity[3].value, 0); + }); + + test('Make property specific keyframes when the offset of the last keyframe is specified but not equal to 1.', function() { + assert.throws(function() { + makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px', offset: 0}, + {left: '20px'}, + {left: '30px', offset: 0.9} + ])); + }); + }); + + test('Make property specific keyframes when no properties are animated, and the offset of the last keyframe is specified but not equal to 1.', function() { + var groups; + assert.doesNotThrow(function() { + groups = makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {offset: 0}, + {}, + {offset: 0.9} + ])); + }); + assert.equal(Object.getOwnPropertyNames(groups).length, 0); + }); + + test('Make property specific keyframes when a property appears in some keyframes, but not in the last keyframe.', function() { + assert.throws(function() { + makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px', top: '0px'}, + {left: '10px', top: '10px'}, + {top: '20px'} + ])); + }); + }); + + test('Make property specific keyframes when a property appears in some keyframes, but not in the first keyframe.', function() { + assert.throws(function() { + makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px'}, + {left: '10px', top: '10px'}, + {left: '20px', top: '20px'} + ])); + }); + }); + + test('Make property specific keyframes where two properties are animated. One property in a keyframe with offset 1. One property in the last keyframe, with no offset.', function() { + var groups; + assert.doesNotThrow(function() { + groups = makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px', top: '0px', offset: 0}, + {left: '20px', offset: 1}, + {top: '20px'} + ])); + }); + assert.equal(Object.getOwnPropertyNames(groups).length, 2); + }); + + test('Make property specific keyframes where two properties are animated. One property in a keyframe with offset 0. One property in the first keyframe, with no offset.', function() { + var groups; + assert.doesNotThrow(function() { + groups = makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {top: '0px'}, + {left: '0px', offset: 0}, + {left: '20px', top: '20px', offset: 1} + ])); + }); + assert.equal(Object.getOwnPropertyNames(groups).length, 2); + }); + + // Test per-keyframe easings. + test('Apply keyframe easings.', function() { + var target1 = document.createElement('div'); + var target2 = document.createElement('div'); + target1.style.position = 'absolute'; + target2.style.position = 'absolute'; + document.body.appendChild(target1); + document.body.appendChild(target2); + + var animation1 = target1.animate( + [ + {left: '0px'}, + {left: '50px', offset: 0.25}, + {left: '0px'} + ], + {duration: 4000, fill: 'forwards'}); + var animation2 = target2.animate( + [ + {left: '0px', easing: 'ease-in'}, + {left: '50px', offset: 0.25}, + {left: '0px'} + ], + {duration: 4000, fill: 'forwards'}); + + tick(0); + assert.equal(leftAsNumber(target1), 0); + assert.equal(leftAsNumber(target2), 0); + tick(250); + assert.closeTo(leftAsNumber(target1), 12.5, 1); + assert.closeTo(leftAsNumber(target2), 4.65, 1); + tick(500); + assert.closeTo(leftAsNumber(target1), 25, 1); + assert.closeTo(leftAsNumber(target2), 15.25, 1); + tick(1000); + assert.equal(leftAsNumber(target1), 50); + assert.equal(leftAsNumber(target2), 50); + + tick(2500); + assert.equal(leftAsNumber(target1), 25); + assert.equal(leftAsNumber(target2), 25); + tick(4000); + assert.equal(leftAsNumber(target1), 0); + assert.equal(leftAsNumber(target2), 0); + }); + + // Test makeInterpolations. + test('Make interpolations for a simple keyframe list with one property.', function() { + var interpolations; + assert.doesNotThrow(function() { + interpolations = makeInterpolations(makePropertySpecificKeyframeGroups(normalizeKeyframes([ + {left: '0px'}, + {left: '200px', offset: 0.3}, + {left: '0px'} + ]))); + }); + assert.equal(interpolations.length, 2); + + assert.closeTo(interpolations[0].startTime, 0, 0.001); + assert.closeTo(interpolations[0].endTime, 0.3, 0.001); + assert.equal(interpolations[0].property, 'left'); + assert.equal(typeof interpolations[0].interpolation, 'function'); + + assert.closeTo(interpolations[1].startTime, 0.3, 0.001); + assert.closeTo(interpolations[1].endTime, 1, 0.001); + assert.equal(interpolations[1].property, 'left'); + assert.equal(typeof interpolations[1].interpolation, 'function'); + }); +}); + +suite('keyframe-interpolations - convertEffectInput', function() { + setup(function() { + this.target = document.createElement('div'); + this.target.style.position = 'absolute'; + document.documentElement.appendChild(this.target); + }); + teardown(function() { + if (this.target.parent) + this.target.removeChild(this.target); + }); + + test('Convert effect input for a simple keyframe list with one property.', function() { + var keyframeInterpolations; + assert.doesNotThrow(function() { + keyframeInterpolations = webAnimations1.convertEffectInput([ + {left: '0px'}, + {left: '200px', offset: 0.3}, + {left: '100px'} + ]); + }); + + keyframeInterpolations(this.target, 0); + assert.closeTo(leftAsNumber(this.target), 0, 0.001); + keyframeInterpolations(this.target, 0.075); + assert.closeTo(leftAsNumber(this.target), 50, 0.001); + keyframeInterpolations(this.target, 0.15); + assert.closeTo(leftAsNumber(this.target), 100, 0.001); + keyframeInterpolations(this.target, 0.65); + assert.closeTo(leftAsNumber(this.target), 150, 0.001); + keyframeInterpolations(this.target, 1); + assert.closeTo(leftAsNumber(this.target), 100, 0.001); + keyframeInterpolations(this.target, 2); + assert.closeTo(leftAsNumber(this.target), -42.856, 0.01); + }); + + test('Convert effect input where one property is animated and the property has two keyframes at offset 1.', function() { + var keyframeInterpolations; + assert.doesNotThrow(function() { + keyframeInterpolations = webAnimations1.convertEffectInput([ + {left: '0px', offset: 0}, + {left: '20px', offset: 1}, + {left: '30px'} + ]); + }); + keyframeInterpolations(this.target, 1); + assert.equal(getComputedStyle(this.target).left, '30px'); + keyframeInterpolations(this.target, 2); + assert.equal(getComputedStyle(this.target).left, '30px'); + }); + + test('Convert effect input and apply result at fraction null.', function() { + var keyframeInterpolations; + var underlying = getComputedStyle(this.target).left; + assert.doesNotThrow(function() { + keyframeInterpolations = webAnimations1.convertEffectInput([ + {left: '0px'}, + {left: '100px'} + ]); + }); + + keyframeInterpolations(this.target, 1); + assert.equal(getComputedStyle(this.target).left, '100px'); + keyframeInterpolations(this.target, null); + assert.equal(getComputedStyle(this.target).left, underlying); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/matrix-interpolation.js b/scripts/vendor/web-animations-js/test/js/matrix-interpolation.js new file mode 100755 index 0000000000..8f8bb581f9 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/matrix-interpolation.js @@ -0,0 +1,532 @@ +suite('matrix interpolation', function() { + function compareMatrices(actual, expected, expectedLength) { + var actualElements = actual.slice( + actual.indexOf('(') + 1, actual.lastIndexOf(')')).split(','); + assert.equal(actualElements.length, expectedLength); + for (var i = 0; i < expectedLength; i++) + assert.closeTo(Number(actualElements[i]), expected[i], 0.01); + } + + function compareInterpolatedTransforms(actual, expected, timeFraction) { + var actualInterp = webAnimations1.propertyInterpolation( + 'transform', + actual[0], + actual[1]); + var expectedInterp = webAnimations1.propertyInterpolation( + 'transform', + expected[0], + expected[1]); + var evaluatedActualInterp = actualInterp(timeFraction); + var evaluatedExpectedInterp = expectedInterp(timeFraction); + var actualElements = evaluatedActualInterp.slice( + evaluatedActualInterp.indexOf('(') + 1, + evaluatedActualInterp.lastIndexOf(')') + ).split(','); + var expectedElements = evaluatedExpectedInterp.slice( + evaluatedExpectedInterp.indexOf('(') + 1, + evaluatedExpectedInterp.lastIndexOf(')') + ).split(','); + assert.equal(actualElements.length, expectedElements.length); + for (var i = 0; i < expectedElements.length; i++) + assert.closeTo(Number(actualElements[i]), Number(expectedElements[i]), 0.01); + } + + test('transform interpolations with matrices only', function() { + var interpolatedMatrix = webAnimations1.propertyInterpolation( + 'transform', + 'matrix(1, 0, 0, 1, 0, 0)', + 'matrix(1, -0.2, 0, 1, 0, 0)'); + var evaluatedInterp = interpolatedMatrix(0.5); + compareMatrices(evaluatedInterp, [1, -0.1, 0, 1, 0, 0], 6); + + interpolatedMatrix = webAnimations1.propertyInterpolation( + 'transform', + 'matrix(1, 0, 0, 1, 0, 0)', + 'matrix3d(1, 1, 0, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)'); + evaluatedInterp = interpolatedMatrix(0.5); + compareMatrices(evaluatedInterp, [1.12, 0.46, -0.84, 1.34, 5, 5], 6); + + interpolatedMatrix = webAnimations1.propertyInterpolation( + 'transform', + 'matrix(1, 0, 0, 1, 0, 0)', + 'matrix3d(1, 1, 3, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)'); + evaluatedInterp = interpolatedMatrix(0.5); + // FIXME: Values at 8, 9, 10 are different from Blink and FireFox, which give 0.31, 0.04, 1.01. + // Result looks the same. + compareMatrices( + evaluatedInterp, + [1.73, 0.67, 1.10, 0, -0.85, 1.34, 0.29, 0, -0.35, -0.22, 0.58, 0, 5, 5, 0, 1], + 16); + + interpolatedMatrix = webAnimations1.propertyInterpolation( + 'transform', + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)', + 'matrix3d(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 10, 10, 1)'); + evaluatedInterp = interpolatedMatrix(0.5); + compareMatrices( + evaluatedInterp, + [1.38, 0.85, 0, 0, 0.24, 1.00, 0, 0, 0, 0, 1, 0, 0, 5, 5, 1], + 16); + + interpolatedMatrix = webAnimations1.propertyInterpolation( + 'transform', + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)', + 'matrix3d(1, 1, 0, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)'); + evaluatedInterp = interpolatedMatrix(0.5); + compareMatrices(evaluatedInterp, [1.12, 0.46, -0.84, 1.34, 5, 5], 6); + + // Test matrices with [3][3] != 1 + interp = webAnimations1.propertyInterpolation( + 'transform', + 'matrix(1, 0, 0, 1, 0, 0)', + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2)'); + evaluatedInterp = interp(0.4); + compareMatrices( + evaluatedInterp, + [1, 0, 0, 1, 0, 0], + 6); + evaluatedInterp = interp(0.6); + compareMatrices( + evaluatedInterp, + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2], + 16); + }); + + test('transform interpolations with matrices and other functions', function() { + var interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(100px) matrix(1, 0, 0, 1, 0, 0)', + 'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)'); + var evaluatedInterp = interp(0.5); + var functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 2); + assert.equal(functions[0], 'translate(55px,0px)'); + compareMatrices(functions[1], [1, -0.1, 0, 1, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)', + 'translate(10px) matrix(1, -0.2, 0, 1, 0, 0) rotate(100deg)'); + evaluatedInterp = interp(0.5); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(55px,0px)'); + compareMatrices(functions[1], [1, -0.1, 0, 1, 0, 0], 6); + assert.equal(functions[2], 'rotate(55deg)'); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)', + 'translate(10px) matrix3d(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 10, 10, 1) rotate(100deg)'); + evaluatedInterp = interp(0.5); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(55px,0px)'); + compareMatrices( + functions[1], + [1.38, 0.85, 0, 0, 0.24, 1.00, 0, 0, 0, 0, 1, 0, 0, 5, 5, 1], + 16); + assert.equal(functions[2], 'rotate(55deg)'); + + // Contains matrices and requires matrix decomposition. + interp = webAnimations1.propertyInterpolation( + 'transform', + 'matrix(1, 0, 0, 1, 0, 0) translate(100px)', + 'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, -0.1, 0, 1, 55, 0], 6); + + // Test matrices with [3][3] != 1 + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)', + 'translate(10px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2) rotate(100deg)'); + evaluatedInterp = interp(0.4); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(64px,0px)'); + compareMatrices( + functions[1], + [1, 0, 0, 1, 0, 0], + 6); + assert.equal(functions[2], 'rotate(46deg)'); + evaluatedInterp = interp(0.6); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(46px,0px)'); + compareMatrices( + functions[1], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2], + 16); + assert.equal(functions[2], 'rotate(64deg)'); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(10px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2) rotate(100deg)', + 'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)'); + evaluatedInterp = interp(0.4); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(46px,0px)'); + compareMatrices( + functions[1], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2], + 16); + assert.equal(functions[2], 'rotate(64deg)'); + evaluatedInterp = interp(0.6); + functions = evaluatedInterp.split(' '); + assert.equal(functions.length, 3); + assert.equal(functions[0], 'translate(64px,0px)'); + compareMatrices( + functions[1], + [1, 0, 0, 1, 0, 0], + 6); + assert.equal(functions[2], 'rotate(46deg)'); + }); + + test('transform interpolations that require matrix decomposition', function() { + var interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(10px)', + 'scale(2)'); + var evaluatedInterp = interp(0.4); + compareMatrices(evaluatedInterp, [1.4, 0, 0, 1.4, 6, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotateX(10deg)', + 'rotateY(20deg)'); + evaluatedInterp = interp(0.4); + compareMatrices( + evaluatedInterp, + [0.99, 0.01, -0.14, 0, 0.01, 1.00, 0.10, 0, 0.14, -0.10, 0.98, 0, 0, 0, 0, 1], + 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotate(0rad) translate(0px)', + 'translate(800px) rotate(9rad)'); + evaluatedInterp = interp(0.4); + compareMatrices(evaluatedInterp, [0.47, 0.89, -0.89, 0.47, 320, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotateX(10deg)', + 'translate(10px) rotateX(200deg)'); + evaluatedInterp = interp(0.4); + compareMatrices( + evaluatedInterp, + [1, 0, 0, 0, 0, 0.53, -0.85, 0, 0, 0.85, 0.53, 0, 4, 0, 0, 1], + 16); + + // This case agrees with FireFox and the spec, but not with the old polyfill or Blink. The old + // polyfill only does matrix decomposition on the rotate section of the function + // lists. + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(0px)', + 'translate(800px) rotate(9rad)'); + evaluatedInterp = interp(0.4); + compareMatrices(evaluatedInterp, [0.47, 0.89, -0.89, 0.47, 320, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(0px, 0px) rotate(0deg) scale(1)', + 'translate(900px, 190px) scale(3) rotate(9rad)'); + evaluatedInterp = interp(0.4); + compareMatrices(evaluatedInterp, [0.84, 1.59, -1.59, 0.84, 360, 76], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'perspective(1000px)', + 'perspective(200px)'); + evaluatedInterp = interp(0.2); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0018, 0, 0, 0, 1], 16); + }); + + test('transforms that decompose to a 2D matrix result in a 2D matrix transform in computed style', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + + var animation = target.animate( + [{transform: 'translate(100px)'}, + {transform: 'rotate(45deg)'}], + 2000); + animation.currentTime = 500; + animation.pause(); + + var styleTransform = getComputedStyle(target).transform || getComputedStyle(target).webkitTransform; + var elements = styleTransform.slice( + styleTransform.indexOf('(') + 1, styleTransform.lastIndexOf(')')).split(','); + assert.equal(elements.length, 6); + }); + + test('decompose various CSS properties', function() { + var interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotateX(110deg)', + 'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)'); + var evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 0.500, 0.866, 0, 0, -0.866, 0.500, 0, 0, 0, 0, 1], 16); + + // FIXME: This test case differs from blink transitions which gives -1(this) + // This case agrees with FireFox transitions. + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotateY(10rad)', + 'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [0.960, 0, 0.279, 0, 0, 1, 0, 0, -0.279, 0, 0.960, 0, 0, 0, 0, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotate(320deg)', + 'rotate(10deg) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [0.966, -0.259, 0.259, 0.966, 0, 0], 6); + + // FIXME: This test case differs from blink transitions which gives -1(this) + // This case agrees with FireFox transitions. + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotateZ(10rad)', + 'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [0.960, -0.279, 0.279, 0.960, 0, 0], 6); + + // FIXME: This test case differs from blink transitions + // which gives matrix3d(-0.24, +0.91, +0.33, +0, +0.33, -0.24, +0.91, +0, +0.91, +0.33, -0.24, +0, +0, +0, +0, +1) + // versus our matrix3d(+0.91, -0.24, +0.33, +0, +0.33, +0.91, -0.24, +0, -0.24, +0.33, +0.91, +0, +0, +0, +0, +1) + // This case agrees with FireFox transitions. + interp = webAnimations1.propertyInterpolation( + 'transform', + 'rotate3d(1, 1, 1, 100deg)', + 'rotate3d(1, 1, 1, 200deg) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [0.911, -0.244, 0.333, 0, 0.333, 0.911, -0.244, 0, -0.244, 0.333, 0.911, 0, 0, 0, 0, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'scale(10)', + 'scale(2) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [6, 0, 0, 6, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'scalex(10)', + 'scalex(2) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [6, 0, 0, 1, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'scaley(10)', + 'scaley(2) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 6, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'scalez(10)', + 'scalez(2) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 6, 0, 0, 0, 0, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'scale3d(6, 8, 10)', + 'scale3d(2, 2, 2) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'skew(30deg)', + 'skew(0deg) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0.289, 1, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'skewx(3rad)', + 'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0.707, 1, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'skewy(3rad)', + 'skewy(1rad) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1.301, 0.595, 0.174, 0.921, 0, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate(10px, 20px)', + 'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 1, 55, 110], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translatex(10px)', + 'translatex(100px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 1, 55, 0], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translatey(10px)', + 'translatey(100px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 1, 0, 55], 6); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translatez(20px)', + 'translatez(200px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 110, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'translate3d(10px, 10px, 10px)', + 'translate3d(20px, 20px, 20px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 15, 15, 15, 1], 16); + + interp = webAnimations1.propertyInterpolation( + 'transform', + 'perspective(300px)', + 'perspective(900px) matrix(1, 0, 0, 1, 0, 0)'); + evaluatedInterp = interp(0.5); + compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.002222, 0, 0, 0, 1], 16); + }); + + test('decompose various CSS properties with unsupported units', function() { + compareInterpolatedTransforms( + ['rotateX(110grad)', 'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)'], + ['rotateX(0deg)', 'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['rotateY(2turn)', 'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)'], + ['rotateY(0rad)', 'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['rotate(320deg)', 'rotateY(10grad) matrix(1, 0, 0, 1, 0, 0)'], + ['rotate(320deg)', 'rotateY(0deg) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['rotateZ(10grad)', 'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)'], + ['rotateZ(0rad)', 'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['rotate3d(1, 1, 1, 100deg)', 'rotate3d(1, 1, 1, 2turn) matrix(1, 0, 0, 1, 0, 0)'], + ['rotate3d(1, 1, 1, 100deg)', 'rotate3d(1, 1, 1, 0deg) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['skew(30grad)', 'skew(10deg) matrix(1, 0, 0, 1, 0, 0)'], + ['skew(0deg)', 'skew(10deg) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['skewx(3grad)', 'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)'], + ['skewx(0rad)', 'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['skewy(3rad)', 'skewy(1grad) matrix(1, 0, 0, 1, 0, 0)'], + ['skewy(3rad)', 'skewy(0rad) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['translate(10in, 20in)', 'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)'], + ['translate(0px, 0px)', 'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['translatex(20in)', 'translatex(200px) matrix(1, 0, 0, 1, 0, 0)'], + ['translatex(0px)', 'translatex(200px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['translatey(10in)', 'translatey(100px) matrix(1, 0, 0, 1, 0, 0)'], + ['translatey(0px)', 'translatey(100px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['translatez(10em)', 'translatez(100px) matrix(1, 0, 0, 1, 0, 0)'], + ['translatez(0px)', 'translatez(100px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['translate3d(10px, 10px, 10px)', 'translate3d(2rem, 2rem, 2rem) matrix(1, 0, 0, 1, 0, 0)'], + ['translate3d(10px, 10px, 10px)', 'translate3d(0px, 0px, 0px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + + compareInterpolatedTransforms( + ['perspective(300px)', 'perspective(9em) matrix(1, 0, 0, 1, 0, 0)'], + ['perspective(300px)', 'perspective(0px) matrix(1, 0, 0, 1, 0, 0)'], + 0.5); + }); + + test('transform interpolations involving matrices when matrix code is not available', function() { + // FIXME: This is vulnerable to module interface changes. Can we disable modules? + var composeMatrix = webAnimations1.composeMatrix; + var quat = webAnimations1.quat; + var dot = webAnimations1.dot; + var makeMatrixDecomposition = webAnimations1.makeMatrixDecomposition; + webAnimations1.composeMatrix = undefined; + webAnimations1.quat = undefined; + webAnimations1.dot = undefined; + webAnimations1.makeMatrixDecomposition = undefined; + + var testFlipTransformLists = function(keyframeFrom, keyframeTo) { + var interp = webAnimations1.propertyInterpolation( + 'transform', + keyframeFrom, + keyframeTo); + var evaluatedInterp = interp(0.49); + assert.equal(evaluatedInterp, keyframeFrom); + evaluatedInterp = interp(0.51); + assert.equal(evaluatedInterp, keyframeTo); + }; + + try { + // Function lists with just matrices. + testFlipTransformLists('matrix(1, 0, 0, 1, 0, 0)', 'matrix(1, -0.2, 0, 1, 0, 0)'); + // Function lists with matrices and other functions. + testFlipTransformLists( + 'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)', + 'translate(10px) matrix(1, -0.2, 0, 1, 0, 0) rotate(100deg)'); + // Function lists that require matrix decomposition to be interpolated. + testFlipTransformLists('translate(10px)', 'scale(2)'); + testFlipTransformLists('scale(2)', 'translate(10px)'); + testFlipTransformLists('rotateX(10deg)', 'rotateY(20deg)'); + testFlipTransformLists('rotateX(10deg)', 'translate(10px) rotateX(200deg)'); + testFlipTransformLists( + 'rotate(0rad) translate(0px)', + 'translate(800px) rotate(9rad)'); + testFlipTransformLists( + 'translate(0px, 0px) rotate(0deg) scale(1)', + 'scale(3) translate(300px, 90px) rotate(9rad)'); + testFlipTransformLists( + 'translate(0px, 0px) skew(30deg)', + 'skew(0deg) translate(300px, 90px)'); + testFlipTransformLists( + 'matrix(1, 0, 0, 1, 0, 0) translate(100px)', + 'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)'); + } finally { + webAnimations1.composeMatrix = composeMatrix; + webAnimations1.quat = quat; + webAnimations1.dot = dot; + webAnimations1.makeMatrixDecomposition = makeMatrixDecomposition; + } + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/number-handler.js b/scripts/vendor/web-animations-js/test/js/number-handler.js new file mode 100755 index 0000000000..0b42c30d6e --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/number-handler.js @@ -0,0 +1,35 @@ +suite('number-handler', function() { + test('parse numbers', function() { + var tests = { + '0': 0, + '1234': 1234, + '-40': -40, + '+40': 40, + ' -40 ': -40, + '4.0': 4, + '0.4': 0.4, + '.1234': 0.1234, + '12.34': 12.34, + '+.1234': 0.1234, + '+12.34': 12.34, + '-.1234': -0.1234, + '-12.34': -12.34, + }; + for (var string in tests) { + assert.equal(webAnimations1.parseNumber(string), tests[string], 'Parsing "' + string + '"'); + } + }); + test('invalid numbers fail to parse', function() { + assert.isUndefined(webAnimations1.parseNumber('')); + assert.isUndefined(webAnimations1.parseNumber('nine')); + assert.isUndefined(webAnimations1.parseNumber('1 2')); + assert.isUndefined(webAnimations1.parseNumber('+-0')); + assert.isUndefined(webAnimations1.parseNumber('50px')); + assert.isUndefined(webAnimations1.parseNumber('1.2.3')); + }); + test('opacity clamping', function() { + var interpolation = webAnimations1.propertyInterpolation('opacity', '0', '1'); + assert.equal(interpolation(-1), '0'); + assert.equal(interpolation(2), '1'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/property-interpolation.js b/scripts/vendor/web-animations-js/test/js/property-interpolation.js new file mode 100755 index 0000000000..678d31d139 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/property-interpolation.js @@ -0,0 +1,30 @@ +suite('property-interpolation', function() { + test('unmatched inputs return step interpolation', function() { + tests = [['unknown', 'input', 'tuple'], + ['unknown', '10px', '50px'], + ['width', '100px', 'auto'], + ['width', 'auto', '100px']]; + for (var i = 0; i < tests.length; i++) { + var property = tests[i][0]; + var left = tests[i][1]; + var right = tests[i][2]; + interpolation = webAnimations1.propertyInterpolation(property, left, right); + assert.equal(interpolation(-1), left); + assert.equal(interpolation(0), left); + assert.equal(interpolation(0.45), left); + assert.equal(interpolation(0.5), right); + assert.equal(interpolation(0.55), right); + assert.equal(interpolation(1), right); + assert.equal(interpolation(2), right); + } + }); + + test('registers camel cased property names', function() { + function merge(a, b) { + return [a, b, function(x) { return a + b; }]; + }; + webAnimations1.addPropertiesHandler(Number, merge, ['dummy-property']); + assert.equal(webAnimations1.propertyInterpolation('dummy-property', 1, 2)(0.5), 3); + assert.equal(webAnimations1.propertyInterpolation('dummyProperty', 5, 3)(0.5), 8); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/tick.js b/scripts/vendor/web-animations-js/test/js/tick.js new file mode 100755 index 0000000000..1c42dd4294 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/tick.js @@ -0,0 +1,16 @@ +suite('tick-tests', function() { + setup(function() { webAnimations1.timeline._animations = []; }); + + test('animations are in effect but ticking stops once forward fill is reached', function() { + tick(90); + var animation = document.body.animate([], {duration: 1000, fill: 'forwards'}); + tick(100); + tick(600); + assert.equal(webAnimations1.timeline._animations.length, 1); + assert.equal(isTicking(), true); + tick(1100); + assert.equal(animation.finished, true); + assert.equal(webAnimations1.timeline._animations.length, 1); + assert.equal(isTicking(), false); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/timeline.js b/scripts/vendor/web-animations-js/test/js/timeline.js new file mode 100755 index 0000000000..9590ab7f53 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/timeline.js @@ -0,0 +1,36 @@ +suite('timeline-tests', function() { + setup(function() { + document.timeline._animations = []; + webAnimations1.timeline._animation = []; + }); + + test('no current animations', function() { + assert.equal(document.timeline.getAnimations().length, 0); + }); + + test('getAnimations', function() { + tick(90); + assert.equal(document.timeline.getAnimations().length, 0); + var animation = document.body.animate([], {duration: 500, iterations: 1}); + tick(300); + assert.equal(document.timeline.getAnimations().length, 1); + + var animation2 = document.body.animate([], {duration: 1000}); + assert.equal(document.timeline.getAnimations().length, 2); + tick(800); + assert.equal(animation.finished, true); + assert.equal(document.timeline.getAnimations().length, 1); + tick(2000); + assert.equal(document.timeline.getAnimations().length, 0); + }); + + test('getAnimations checks cancelled animation', function() { + tick(90); + assert.equal(document.timeline.getAnimations().length, 0); + var animation = document.body.animate([], {duration: 500, iterations: 1}); + tick(300); + assert.equal(document.timeline.getAnimations().length, 1); + animation.cancel(); + assert.equal(document.timeline.getAnimations().length, 0); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/timing-utilities.js b/scripts/vendor/web-animations-js/test/js/timing-utilities.js new file mode 100755 index 0000000000..a5f3b5839f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/timing-utilities.js @@ -0,0 +1,114 @@ +suite('timing-utilities', function() { + test('normalize timing input', function() { + assert.equal(normalizeTimingInput(1).duration, 1); + assert.equal(normalizeTimingInput(1).easing(0.2), 0.2); + assert.equal(normalizeTimingInput(undefined).duration, 0); + }); + test('calculating active duration', function() { + assert.equal(calculateActiveDuration({duration: 1000, playbackRate: 4, iterations: 20}), 5000); + assert.equal(calculateActiveDuration({duration: 500, playbackRate: 0.1, iterations: 300}), 1500000); + }); + test('conversion of timing functions', function() { + var f = toTimingFunction('ease'); + var g = toTimingFunction('cubic-bezier(.25, 0.1, 0.25, 1.)'); + for (var i = 0; i < 1; i += 0.1) { + assert.equal(f(i), g(i)); + } + assert.closeTo(f(0.1844), 0.2601, 0.01); + assert.closeTo(g(0.1844), 0.2601, 0.01); + + f = toTimingFunction('cubic-bezier(0, 1, 1, 0)'); + assert.closeTo(f(0.104), 0.392, 0.01); + + function isLinear(f) { + assert.equal(f(0.1), 0.1); + assert.equal(f(0.4), 0.4); + assert.equal(f(0.9), 0.9); + } + + f = toTimingFunction('cubic-bezier(0, 1, -1, 1)'); + isLinear(f); + + f = toTimingFunction('an elephant'); + isLinear(f); + + f = toTimingFunction('cubic-bezier(-1, 1, 1, 1)'); + isLinear(f); + + f = toTimingFunction('cubic-bezier(1, 1, 1)'); + isLinear(f); + + f = toTimingFunction('steps(10, end)'); + assert.equal(f(0), 0); + assert.equal(f(0.09), 0); + assert.equal(f(0.1), 0.1); + assert.equal(f(0.25), 0.2); + }); + test('calculating phase', function() { + // calculatePhase(activeDuration, localTime, timing); + assert.equal(calculatePhase(1000, 100, {delay: 0}), PhaseActive); + assert.equal(calculatePhase(1000, 100, {delay: 200}), PhaseBefore); + assert.equal(calculatePhase(1000, 2000, {delay: 200}), PhaseAfter); + assert.equal(calculatePhase(1000, null, {delay: 200}), PhaseNone); + }); + test('calculating active time', function() { + // calculateActiveTime(activeDuration, fillMode, localTime, phase, delay); + assert.equal(calculateActiveTime(1000, 'forwards', 100, PhaseActive, 0), 100); + assert.equal(calculateActiveTime(1000, 'forwards', 100, PhaseBefore, 200), null); + assert.equal(calculateActiveTime(1000, 'both', 100, PhaseBefore, 200), 0); + assert.equal(calculateActiveTime(1000, 'forwards', 500, PhaseActive, 200), 300); + assert.equal(calculateActiveTime(1000, 'forwards', 1100, PhaseAfter, 200), 1000); + assert.equal(calculateActiveTime(1000, 'none', 1100, PhaseAfter, 200), null); + assert.equal(calculateActiveTime(Infinity, 'both', 5000000, PhaseActive, 2000000), 3000000); + assert.equal(calculateActiveTime(Infinity, 'both', 50000, PhaseBefore, 2000000), 0); + }); + test('calculating scaled active time', function() { + // calculateScaledActiveTime(activeDuration, activeTime, startOffset, timingInput); + assert.equal(calculateScaledActiveTime(1000, 200, 300, {playbackRate: 1.5}), 600); + assert.equal(calculateScaledActiveTime(1000, 200, 300, {playbackRate: -4}), 3500); + assert.equal(calculateScaledActiveTime(Infinity, 400, 200, {playbackRate: 1}), 600); + assert.equal(calculateScaledActiveTime(Infinity, 400, 200, {playbackRate: -4}), Infinity); + }); + test('calculating iteration time', function() { + // calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, timingInput); + assert.equal(calculateIterationTime(500, 5000, 600, 100, {iterations: 10, iterationStart: 0}), 100); + assert.equal(calculateIterationTime(500, 5000, Infinity, 100, {iterations: 10, iterationStart: 0}), 500); + assert.equal(calculateIterationTime(500, 5000, 5100, 100, {iterations: 3.2, iterationStart: 0.8}), 500); + }); + test('calculating current iteration', function() { + // calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, timingInput); + assert.equal(calculateCurrentIteration(1000, 400, 4400, {iterations: 50, iterationStart: 0.8}), 4); + assert.equal(calculateCurrentIteration(1000, 1000, 4400, {iterations: 50.2, iterationStart: 0.8}), 50); + }); + test('calculating transformed time', function() { + // calculateTransformedTime(currentIteration, iterationDuration, iterationTime, timingInput); + assert.equal(calculateTransformedTime(4, 1000, 200, {easing: function(x) { return x; }, direction: 'normal'}), 200); + assert.equal(calculateTransformedTime(4, 1000, 200, {easing: function(x) { return x; }, direction: 'reverse'}), 800); + assert.closeTo(calculateTransformedTime(4, 1000, 200, {easing: function(x) { return x * x; }, direction: 'reverse'}), 640, 0.0001); + assert.closeTo(calculateTransformedTime(4, 1000, 600, {easing: function(x) { return x * x; }, direction: 'alternate'}), 360, 0.0001); + assert.closeTo(calculateTransformedTime(3, 1000, 600, {easing: function(x) { return x * x; }, direction: 'alternate'}), 160, 0.0001); + assert.closeTo(calculateTransformedTime(4, 1000, 600, {easing: function(x) { return x * x; }, direction: 'alternate-reverse'}), 160, 0.0001); + assert.closeTo(calculateTransformedTime(3, 1000, 600, {easing: function(x) { return x * x; }, direction: 'alternate-reverse'}), 360, 0.0001); + }); + test('EffectTime', function() { + var timing = normalizeTimingInput({duration: 1000, iterations: 4, iterationStart: 0.5, easing: 'linear', direction: 'alternate', delay: 100, fill: 'forwards'}); + var timing2 = normalizeTimingInput({duration: 1000, iterations: 4, iterationStart: 0.5, easing: 'ease', direction: 'alternate', delay: 100, fill: 'forwards'}); + var effectTF = effectTime(timing); + var effectTF2 = effectTime(timing2); + assert.equal(effectTF(0), null); + assert.equal(effectTF(100), 0.5); + assert.closeTo(effectTF2(100), 0.8, 0.005); + assert.equal(effectTF(600), 1); + assert.closeTo(effectTF2(600), 1, 0.005); + assert.equal(effectTF(700), 0.9); + assert.closeTo(effectTF2(700), 0.99, 0.005); + assert.equal(effectTF(1600), 0); + assert.closeTo(effectTF2(1600), 0, 0.005); + assert.equal(effectTF(4000), 0.4); + assert.closeTo(effectTF2(4000), 0.68, 0.005); + assert.equal(effectTF(4100), 0.5); + assert.closeTo(effectTF2(4100), 0.8, 0.005); + assert.equal(effectTF(6000), 0.5); + assert.closeTo(effectTF2(6000), 0.8, 0.005); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/timing.js b/scripts/vendor/web-animations-js/test/js/timing.js new file mode 100755 index 0000000000..dae17d1dde --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/timing.js @@ -0,0 +1,52 @@ +suite('timing', function() { + test('pause and scrub', function() { + var animation = document.body.animate([], { duration: 1000 }); + animation.pause(); + + animation.currentTime = 500; + assert.equal(animation.currentTime, 500); + }); + + test('pause, scrub and play', function() { + var target = document.createElement('div'); + document.body.appendChild(target); + + var animation = target.animate([ + { background: 'blue' }, + { background: 'red' } + ], { duration: 1000 }); + tick(100); + animation.pause(); + + animation.currentTime = 200; + // http://www.w3.org/TR/web-animations/#the-current-time-of-an-animation + // currentTime should now mean 'hold time' - this allows scrubbing. + assert.equal(animation.currentTime, 200); + animation.play(); + + tick(200); + tick(300); + assert.equal(animation.currentTime, 300); + assert.equal(animation.startTime, 0); + }); + + test('sanity-check NaN timing', function() { + // This has no actual tests, but will infinite loop without fix. + + var animation = document.body.animate([], { + duration: 2000, + easing: 'ease-in' // fails only with cubic easing, not linear + }); + tick(100); + animation.currentTime = NaN; + tick(200); + + animation = document.body.animate([], { duration: NaN, easing: 'ease-out' }); + tick(300); + }); + + test('can set fill:none on group', function() { + var timing = webAnimationsShared.makeTiming({fill: 'none'}, true); + assert.equal(timing.fill, 'none'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/js/transform-handler.js b/scripts/vendor/web-animations-js/test/js/transform-handler.js new file mode 100755 index 0000000000..edcbac09c4 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/js/transform-handler.js @@ -0,0 +1,171 @@ +suite('transform-handler parsing', function() { + test('parse skew values', function() { + assert.deepEqual(parseTransform('skew(10deg) skew(12deg,45deg) skewX(0) skewY(1.5rad)'), [ + {t: 'skew', d: [{deg: 10}, {deg: 0}]}, + {t: 'skew', d: [{deg: 12}, {deg: 45}]}, + {t: 'skewx', d: [{deg: 0}]}, + {t: 'skewy', d: [{rad: 1.5}]} + ]); + }); + + test('parse scale values', function() { + assert.deepEqual(parseTransform('scale(-2) scale(3,-4) scaleX(5) scaleY(-1) scaleZ(-3)'), [ + {t: 'scale', d: [-2, -2]}, + {t: 'scale', d: [3, -4]}, + {t: 'scalex', d: [5]}, + {t: 'scaley', d: [-1]}, + {t: 'scalez', d: [-3]} + ]); + assert.deepEqual(parseTransform('scale3d(-2, 0, 7)'), + [{t: 'scale3d', d: [-2, 0, 7]}]); + }); + + test('parse rotate values', function() { + assert.deepEqual(parseTransform('rotate(10deg) rotateX(0) rotateY(1.5rad) rotateZ(50grad)'), [ + {t: 'rotate', d: [{deg: 10}]}, + {t: 'rotatex', d: [{deg: 0}]}, + {t: 'rotatey', d: [{rad: 1.5}]}, + {t: 'rotatez', d: [{grad: 50}]} + ]); + }); + + test('parse translate values', function() { + assert.deepEqual(parseTransform('translate(20%, 30px) translate(30em, 40%) translate(50vw) translate(0)'), [ + {t: 'translate', d: [{'%': 20}, {px: 30}]}, + {t: 'translate', d: [{em: 30}, {'%': 40}]}, + {t: 'translate', d: [{vw: 50}, {px: 0}]}, + {t: 'translate', d: [{px: 0}, {px: 0}]} + ]); + assert.deepEqual(parseTransform('translateX(10px) translateX(20%) translateX(0)'), [ + {t: 'translatex', d: [{px: 10}]}, + {t: 'translatex', d: [{'%': 20}]}, + {t: 'translatex', d: [{px: 0}]} + ]); + assert.deepEqual(parseTransform('translateY(10px) translateY(20%) translateY(0)'), [ + {t: 'translatey', d: [{px: 10}]}, + {t: 'translatey', d: [{'%': 20}]}, + {t: 'translatey', d: [{px: 0}]} + ]); + assert.deepEqual(parseTransform('translateZ(10px) translateZ(0)'), [ + {t: 'translatez', d: [{px: 10}]}, + {t: 'translatez', d: [{px: 0}]} + ]); + assert.deepEqual(parseTransform('translate3d(10px, 20px, 30px) translate3d(0, 40%, 0) translate3d(50%, 0, 60px)'), [ + {t: 'translate3d', d: [{px: 10}, {px: 20}, {px: 30}]}, + {t: 'translate3d', d: [{px: 0}, {'%': 40}, {px: 0}]}, + {t: 'translate3d', d: [{'%': 50}, {px: 0}, {px: 60}]} + ]); + }); + + test('invalid transforms fail to parse', function() { + assert.isUndefined(parseTransform('translate(10px')); + assert.isUndefined(parseTransform('translate()')); + assert.isUndefined(parseTransform('translatex()')); + assert.isUndefined(parseTransform('translatex(5)')); + assert.isUndefined(parseTransform('rotate(5)')); + assert.isUndefined(parseTransform('skew(5)')); + assert.isUndefined(parseTransform('scale(5px)')); + assert.isUndefined(parseTransform('rotatex(5px)')); + }); +}); + +suite('transform-handler interpolation', function() { + test('simple transform interpolations', function() { + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translateX(10px)', + 'translateX(20px)')(0.2), + 'translatex(12px)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translate(10px, 10px) rotate(20deg)', + 'translate(20px, 20px) rotate(90deg)')(0.2), + 'translate(12px,12px) rotate(34deg)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translate(10px, 10em) rotate(20deg)', + 'translate(20em, 20px) rotate(90deg)')(0.5), + 'translate(calc(5px + 10em),calc(5em + 10px)) rotate(55deg)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'rotateY(1000deg)', + 'rotateY(3000deg)')(0.4), + 'rotatey(1800deg)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'scale(6)', + 'scale(1,-4)')(0.2), + 'scale(5,4)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'skewX(5deg) translateY(5px)', + 'skewX(-35deg) translateY(45px)')(0.25), + 'skewx(-5deg) translatey(15px)'); + }); + + test('transform interpolations with conversion to primitives', function() { + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translateX(10px)', + 'translate(20px, 10px)')(0.2), + 'translate(12px,2px)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translateX(10px)', + 'translateY(10px)')(0.2), + 'translate(8px,2px)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'translateX(10px)', + 'translateZ(10px)')(0.2), + 'translate3d(8px,0px,2px)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'scaleX(6)', + 'scale(1,6)')(0.2), + 'scale(5,2)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'skew(10deg)', + 'skewY(30deg)')(0.2), + 'skew(8deg,6deg)'); + }); + + test('transform interpolations with none', function() { + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'none', + 'scale(5) translateX(100px) rotate(1000deg)')(0.25), + 'scale(2,2) translatex(25px) rotate(250deg)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'scale(5) translateX(100px) rotate(1000deg)', + 'none')(0.75), + 'scale(2,2) translatex(25px) rotate(250deg)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'none', + 'scaleX(5) skewY(100grad)')(0.25), + 'scalex(2) skewy(25grad)'); + assert.equal( + webAnimations1.propertyInterpolation( + 'transform', + 'none', + 'none')(0.4), + 'none'); + }); +}); diff --git a/scripts/vendor/web-animations-js/test/karma-config-ci.js b/scripts/vendor/web-animations-js/test/karma-config-ci.js new file mode 100755 index 0000000000..c41203551d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/karma-config-ci.js @@ -0,0 +1,50 @@ +module.exports = function(config) { + var customLaunchers = { + sl_chrome: { + base: 'SauceLabs', + browserName: 'chrome', + platform: 'Windows 7' + }, + sl_firefox: { + base: 'SauceLabs', + browserName: 'firefox', + version: '27' + }, + sl_ios_safari: { + base: 'SauceLabs', + browserName: 'iphone', + platform: 'OS X 10.9', + version: '7.1' + }, + sl_ie_11: { + base: 'SauceLabs', + browserName: 'internet explorer', + platform: 'Windows 8.1', + version: '11' + } + }; + + config.set({ + frameworks: ['mocha', 'chai'], + plugins: [ + 'karma-mocha', + 'karma-chai', + 'karma-sauce-launcher', + ], + sauceLabs: { + testName: 'Web App Unit Tests' + }, + customLaunchers: customLaunchers, + browsers: Object.keys(customLaunchers), + basePath: '..', + files: [ + // Populated in `grunt test` task. + ], + singleRun: true, + port: 9876, + reporters: ['dots', 'saucelabs'], + colors: true, + autoWatch: false, + captureTimeout: 300000, + }); +}; diff --git a/scripts/vendor/web-animations-js/test/karma-config.js b/scripts/vendor/web-animations-js/test/karma-config.js new file mode 100755 index 0000000000..cb1ea91694 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/karma-config.js @@ -0,0 +1,22 @@ +module.exports = function(config) { + config.set({ + frameworks: ['mocha', 'chai'], + plugins: [ + 'karma-mocha', + 'karma-chai', + 'karma-chrome-launcher', + 'karma-firefox-launcher' + ], + browsers: ['Firefox'], + // browsers: ['Safari', 'Chrome', 'ChromeCanary', 'Firefox', 'IE'], + basePath: '..', + files: [ + // Populated in `grunt test` task. + ], + singleRun: true, + port: 9876, + reporters: ['dots'], + colors: true, + autoWatch: false, + }); +}; diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher100.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher100.ttf new file mode 100755 index 0000000000..68c855c2d6 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher100.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher200.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher200.ttf new file mode 100755 index 0000000000..a1cfffb524 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher200.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher300.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher300.ttf new file mode 100755 index 0000000000..5d73ff5324 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher300.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher400.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher400.ttf new file mode 100755 index 0000000000..99fcd0fa8f Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher400.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher500.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher500.ttf new file mode 100755 index 0000000000..22daca4caf Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher500.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher600.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher600.ttf new file mode 100755 index 0000000000..f8a66a4a18 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher600.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher700.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher700.ttf new file mode 100755 index 0000000000..20011ccad0 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher700.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher800.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher800.ttf new file mode 100755 index 0000000000..7a41e5a1b0 Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher800.ttf differ diff --git a/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher900.ttf b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher900.ttf new file mode 100755 index 0000000000..e539809dfb Binary files /dev/null and b/scripts/vendor/web-animations-js/test/resources/WebKitWeightWatcher900.ttf differ diff --git a/scripts/vendor/web-animations-js/test/runner-web-animations-next-lite.html b/scripts/vendor/web-animations-js/test/runner-web-animations-next-lite.html new file mode 100755 index 0000000000..41f267a64f --- /dev/null +++ b/scripts/vendor/web-animations-js/test/runner-web-animations-next-lite.html @@ -0,0 +1,26 @@ + + + + + + + + + +
diff --git a/scripts/vendor/web-animations-js/test/runner-web-animations-next.html b/scripts/vendor/web-animations-js/test/runner-web-animations-next.html new file mode 100755 index 0000000000..9bc9f78588 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/runner-web-animations-next.html @@ -0,0 +1,26 @@ + + + + + + + + + +
diff --git a/scripts/vendor/web-animations-js/test/runner-web-animations.html b/scripts/vendor/web-animations-js/test/runner-web-animations.html new file mode 100755 index 0000000000..0a9500f1d6 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/runner-web-animations.html @@ -0,0 +1,26 @@ + + + + + + + + + +
diff --git a/scripts/vendor/web-animations-js/test/runner.js b/scripts/vendor/web-animations-js/test/runner.js new file mode 100755 index 0000000000..4e78b1346d --- /dev/null +++ b/scripts/vendor/web-animations-js/test/runner.js @@ -0,0 +1,35 @@ +var WEB_ANIMATIONS_TESTING = true; +var webAnimationsTesting = window; +var assert = chai.assert; +mocha.setup({ ui: 'tdd' }); + +function loadWebAnimationsBuildTarget(target) { + var config = webAnimationsTargetConfig[target]; + config.src.concat(config.test).forEach(function(file) { + document.write('\n'); + }); +} + +(function() { + + var pageError = null; + + addEventListener('error', function(event) { + pageError = event.filename + ':' + event.lineno + ' ' + event.message; + }); + + addEventListener('load', function() { + + // Inject test suite for page errors if any encountered. + if (pageError) { + suite('page-script-errors', function() { + test('no script errors on page', function() { + assert.fail(null, null, pageError); + }); + }); + } + + mocha.run(); + }); + +})(); diff --git a/scripts/vendor/web-animations-js/test/testharness-runner.html b/scripts/vendor/web-animations-js/test/testharness-runner.html new file mode 100755 index 0000000000..97d7eece36 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/testharness-runner.html @@ -0,0 +1,23 @@ + + + + + + + + +
diff --git a/scripts/vendor/web-animations-js/test/testharness-runner.js b/scripts/vendor/web-animations-js/test/testharness-runner.js new file mode 100755 index 0000000000..1a9a909e88 --- /dev/null +++ b/scripts/vendor/web-animations-js/test/testharness-runner.js @@ -0,0 +1,72 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +(function() { + var assert = chai.assert; + mocha.setup({ ui: 'tdd' }); + + var iframe; + function defineTestharnessTest(shouldPass, testFile) { + var name = shouldPass ? testFile : 'Expected Failure: ' + testFile; + test(name, function(done) { + window.initTestHarness = function(child) { + child.add_completion_callback(function(tests, harness_status) { + var failures = tests.filter(function(result) { + return result.status != 0; + }).map(function(failure) { + return failure.name + ':\n' + failure.message; + }); + var error; + if (shouldPass && failures.length) { + error = new Error('\n' + failures.join('\n\n')); + error.stack = null; + } else if (!shouldPass && failures.length == 0) { + error = new Error('\nExpected to fail, but passed'); + error.stack = null; + } + done(error); + }); + }; + iframe.src = testFile; + }); + } + + suite('testharness tests', function() { + setup(function() { + iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + }); + teardown(function() { + iframe.parentNode.removeChild(iframe); + }); + testHarnessTests.forEach(defineTestharnessTest.bind(null, true)); + testHarnessFailures.forEach(defineTestharnessTest.bind(null, false)); + }); + + suite('interpolation tests', function() { + setup(function() { + iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + }); + teardown(function() { + iframe.parentNode.removeChild(iframe); + }); + interpolationTests.forEach(defineTestharnessTest.bind(null, true)); + interpolationFailures.forEach(defineTestharnessTest.bind(null, false)); + }); + + addEventListener('load', function() { + mocha.run(); + }); +})(); diff --git a/scripts/vendor/web-animations-js/test/testharness-tests.js b/scripts/vendor/web-animations-js/test/testharness-tests.js new file mode 100755 index 0000000000..adf61f2c6a --- /dev/null +++ b/scripts/vendor/web-animations-js/test/testharness-tests.js @@ -0,0 +1,87 @@ +var testHarnessTests = [ + 'blink/2-keyframes-with-offsets.html', + 'blink/3-keyframes-with-offsets.html', + 'blink/add-keyframes.html', + 'blink/insufficient-keyframes.html', + 'blink/simple-keyframes.html', + 'blink/keyframes-with-null-offsets.html', + 'blink/keyframe-properties.html', + 'blink/out-of-order-keyframes.html', + 'blink/same-offset-keyframes.html', + 'blink/eased-keyframes.html', + 'blink/get-animations.html', +]; + +var testHarnessFailures = [ + 'blink/get-css-animations.html', +]; + +var interpolationTests = [ + 'blink/interpolation/background-color-interpolation.html', + 'blink/interpolation/background-position-interpolation.html', + 'blink/interpolation/background-position-origin-interpolation.html', + 'blink/interpolation/background-size-interpolation.html', + 'blink/interpolation/border-color-interpolation.html', + 'blink/interpolation/border-radius-interpolation.html', + 'blink/interpolation/border-width-interpolation.html', + 'blink/interpolation/bottom-interpolation.html', + 'blink/interpolation/box-shadow-interpolation.html', + 'blink/interpolation/calc-interpolation.html', + 'blink/interpolation/clip-interpolation.html', + 'blink/interpolation/color-interpolation.html', + 'blink/interpolation/flex-interpolation.html', + 'blink/interpolation/font-size-interpolation.html', + 'blink/interpolation/font-weight-interpolation.html', + 'blink/interpolation/height-interpolation.html', + 'blink/interpolation/left-interpolation.html', + 'blink/interpolation/letter-spacing-interpolation.html', + 'blink/interpolation/line-height-interpolation.html', + 'blink/interpolation/margin-interpolation.html', + 'blink/interpolation/max-height-interpolation.html', + 'blink/interpolation/max-width-interpolation.html', + 'blink/interpolation/min-height-interpolation.html', + 'blink/interpolation/min-width-interpolation.html', + 'blink/interpolation/object-position-interpolation.html', + 'blink/interpolation/opacity-interpolation.html', + 'blink/interpolation/orphans-interpolation.html', + 'blink/interpolation/outline-color-interpolation.html', + 'blink/interpolation/outline-offset-interpolation.html', + 'blink/interpolation/outline-width-interpolation.html', + 'blink/interpolation/padding-interpolation.html', + 'blink/interpolation/perspective-interpolation.html', + 'blink/interpolation/perspective-origin-interpolation.html', + 'blink/interpolation/right-interpolation.html', + 'blink/interpolation/shape-image-threshold.html', + 'blink/interpolation/shape-margin.html', + 'blink/interpolation/shape-outside.html', + 'blink/interpolation/text-indent-interpolation.html', + 'blink/interpolation/text-shadow-interpolation.html', + 'blink/interpolation/top-interpolation.html', + 'blink/interpolation/transform-none-interpolation.html', + 'blink/interpolation/transform-origin-interpolation.html', + 'blink/interpolation/transform-perspective-interpolation.html', + 'blink/interpolation/transform-rotate-interpolation.html', + 'blink/interpolation/transform-scale-interpolation.html', + 'blink/interpolation/transform-skew-interpolation.html', + 'blink/interpolation/transform-translate-interpolation.html', + 'blink/interpolation/vertical-align-interpolation.html', + 'blink/interpolation/viewport-unit-interpolation.html', + 'blink/interpolation/visibility-interpolation.html', + 'blink/interpolation/widows-interpolation.html', + 'blink/interpolation/width-interpolation.html', + 'blink/interpolation/word-spacing-interpolation.html', + 'blink/interpolation/z-index-interpolation.html', +]; + +var interpolationFailures = [ + 'blink/interpolation/background-image-interpolation.html', + 'blink/interpolation/border-image-outset-interpolation.html', + 'blink/interpolation/border-image-slice-interpolation.html', + 'blink/interpolation/border-image-source-interpolation.html', + 'blink/interpolation/border-image-width-interpolation.html', + 'blink/interpolation/border-spacing-interpolation.html', + 'blink/interpolation/filter-interpolation.html', + 'blink/interpolation/list-style-image-interpolation.html', + 'blink/interpolation/text-decoration-color-interpolation.html', + 'blink/interpolation/transform-matrix-interpolation.html', +]; diff --git a/scripts/vendor/web-animations-js/web-animations-next-lite.dev.html b/scripts/vendor/web-animations-js/web-animations-next-lite.dev.html new file mode 100755 index 0000000000..f367348cab --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations-next-lite.dev.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/web-animations-next-lite.dev.js b/scripts/vendor/web-animations-js/web-animations-next-lite.dev.js new file mode 100755 index 0000000000..8cc77540a2 --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations-next-lite.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations-next-lite'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/vendor/web-animations-js/web-animations-next-lite.min.js b/scripts/vendor/web-animations-js/web-animations-next-lite.min.js new file mode 100755 index 0000000000..ad13084900 --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations-next-lite.min.js @@ -0,0 +1,17 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +!function(a,b){b["true"]=a;var c={},d={},e={},f=null;!function(a){function b(b,c){var d={delay:0,endDelay:0,fill:c?"both":"none",iterationStart:0,iterations:1,duration:c?"auto":0,playbackRate:1,direction:"normal",easing:"linear"};return"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof d[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==p.indexOf(b[c]))return;if("direction"==c&&-1==q.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;d[c]=b[c]}}):d.duration=b,d}function c(a,c){var d=b(a,c);return d.easing=f(d.easing),d}function d(a,b,c,d){return 0>a||a>1||0>c||c>1?y:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function e(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function f(a){var b=w.exec(a);if(b)return d.apply(this,b.slice(1).map(Number));var c=x.exec(a);if(c)return e(Number(c[1]),{start:r,middle:s,end:t}[c[2]]);var f=u[a];return f?f:y}function g(a){return Math.abs(h(a)/a.playbackRate)}function h(a){return a.duration*a.iterations}function i(a,b,c){return null==b?z:b=c.delay+a?B:C}function j(a,b,c,d,e){switch(d){case A:return"backwards"==b||"both"==b?0:null;case C:return c-e;case B:return"forwards"==b||"both"==b?a:null;case z:return null}}function k(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function l(a,b,c,d,e){return 1/0===c||c===-1/0||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function m(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function n(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function o(a,b,c){var d=i(a,b,c),e=j(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===A?0:1;var f=c.iterationStart*c.duration,g=k(a,e,f,c),o=l(c.duration,h(c),g,f,c),p=m(c.duration,o,g,c);return n(p,c.duration,o,c)/c.duration}var p="backwards|forwards|both|none".split("|"),q="reverse|alternate|alternate-reverse".split("|"),r=1,s=.5,t=0,u={ease:d(.25,.1,.25,1),"ease-in":d(.42,0,1,1),"ease-out":d(0,0,.58,1),"ease-in-out":d(.42,0,.58,1),"step-start":e(1,r),"step-middle":e(1,s),"step-end":e(1,t)},v="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",w=new RegExp("cubic-bezier\\("+v+","+v+","+v+","+v+"\\)"),x=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,y=function(a){return a},z=0,A=1,B=2,C=3;a.makeTiming=b,a.normalizeTimingInput=c,a.calculateActiveDuration=g,a.calculateTimeFraction=o,a.calculatePhase=i,a.toTimingFunction=f}(c,f),function(a){function b(a,b){return a in h?h[a][b]||b:b}function c(a,c,d){var g=e[a];if(g){f.style[a]=c;for(var h in g){var i=g[h],j=f.style[i];d[i]=b(i,j)}}else d[a]=b(a,c)}function d(b){function d(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var d={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}c(e,f,d)}return void 0==d.offset&&(d.offset=null),void 0==d.easing&&(d.easing=a.toTimingFunction("linear")),d}),f=!0,g=-1/0,h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||d(),e}var e={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},f=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g={thin:"1px",medium:"3px",thick:"5px"},h={borderBottomWidth:g,borderLeftWidth:g,borderRightWidth:g,borderTopWidth:g,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:g,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=d}(c,f),function(a){var b={};a.isDeprecated=function(a,c,d,e){var f=e?"are":"is",g=new Date,h=new Date(c);return h.setMonth(h.getMonth()+3),h>g?(a in b||console.warn("Web Animations: "+a+" "+f+" deprecated and will stop working on "+h.toDateString()+". "+d),b[a]=!0,!1):!0},a.deprecated=function(b,c,d,e){var f=e?"are":"is";if(a.isDeprecated(b,c,d,e))throw new Error(b+" "+f+" no longer supported. "+d)}}(c),function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}!function(a,b){function c(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a){function b(a,b,c){e[c]=e[c]||[],e[c].push([a,b])}function c(a,c,d){for(var e=0;ed?a:c;if(a.length==c.length){for(var e=[],f=0;f0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(b){b=+b,isNaN(b)||(a.restart(),this.paused||null==this._startTime||(this._startTime=this._timeline.currentTime-b/this._playbackRate),this._currentTimePending=!1,this._currentTime!=b&&(this._tickCurrentTime(b,!0),a.invalidateEffects()))},get startTime(){return this._startTime},set startTime(b){b=+b,isNaN(b)||this.paused||this._idle||(this._startTime=b,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),a.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get finished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this.paused&&0!=this.playbackRate||this._currentTimePending?"pending":this.paused?"paused":this.finished?"finished":"running"},play:function(){this.paused=!1,(this.finished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,a.invalidateEffects()),this._finishedFlag=!1,a.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this.finished||this.paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this.paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this.finished;if((b||this._idle)&&!this._finishedFlag){var d=new c(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);setTimeout(function(){e.forEach(function(a){a.call(d.target,d)})},0)}this._finishedFlag=b},_tick:function(a){return this._idle||this.paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this.finished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(d,f),function(a,b){function c(a){var b=i;i=[],g(a),b.forEach(function(b){b[1](a)}),m&&g(a),f()}function d(a,b){return a._sequenceNumber-b._sequenceNumber}function e(){this._animations=[],this.currentTime=window.performance&&performance.now?performance.now():0}function f(){n.forEach(function(a){a()}),n.length=0}function g(a){l=!1;var c=b.timeline;c.currentTime=a,c._animations.sort(d),k=!1;var e=c._animations;c._animations=[];var f=[],g=[];e=e.filter(function(b){return b._inTimeline=b._tick(a),b._inEffect?g.push(b._effect):f.push(b._effect),b.finished||b.paused||b._idle||(k=!0),b._inTimeline}),n.push.apply(n,f),n.push.apply(n,g),c._animations.push.apply(c._animations,e),m=!1,k&&requestAnimationFrame(function(){})}var h=window.requestAnimationFrame,i=[],j=0;window.requestAnimationFrame=function(a){var b=j++;return 0==i.length&&h(c),i.push([b,a]),b},window.cancelAnimationFrame=function(a){i.forEach(function(b){b[0]==a&&(b[1]=function(){})})},e.prototype={_play:function(c){c._timing=a.normalizeTimingInput(c.timing);var d=new b.Animation(c);return d._idle=!1,d._timeline=this,this._animations.push(d),b.restart(),b.invalidateEffects(),d}};var k=!1,l=!1;b.restart=function(){return k||(k=!0,requestAnimationFrame(function(){}),l=!0),l};var m=!1;b.invalidateEffects=function(){m=!0};var n=[],o=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){return m&&g(p.currentTime),f(),o.apply(this,arguments)}});var p=new e;b.timeline=p}(c,d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,b,["visibility"])}(d),function(a){function b(a){a=a.trim(),e.fillStyle="#000",e.fillStyle=a;var b=e.fillStyle;if(e.fillStyle="#fff",e.fillStyle=a,b==e.fillStyle){e.fillRect(0,0,1,1);var c=e.getImageData(0,0,1,1).data;e.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function c(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=d.height=1;var e=d.getContext("2d");a.addPropertiesHandler(b,c,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,b),a.mergeColors=c}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a){function b(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function c(c){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,b,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],c);return d&&4==d[0].length?d[0]:void 0}function d(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function e(a){return"rect("+a+")"}var f=a.mergeWrappedNestedRepeated.bind(null,e,d,", ");a.parseBox=c,a.mergeBoxes=f,a.addPropertiesHandler(c,f,["clip"])}(d,f),function(a){function b(a){return function(b){var c=0;return a.map(function(a){return a===j?b[c++]:a})}}function c(a){return a}function d(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=m[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.length + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/web-animations-next.dev.js b/scripts/vendor/web-animations-js/web-animations-next.dev.js new file mode 100755 index 0000000000..8f2a4e2971 --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations-next.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations-next'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/vendor/web-animations-js/web-animations-next.min.js b/scripts/vendor/web-animations-js/web-animations-next.min.js new file mode 100755 index 0000000000..f163ff351a --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations-next.min.js @@ -0,0 +1,17 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +!function(a,b){b["true"]=a;var c={},d={},e={},f=null;!function(a){function b(b,c){var d={delay:0,endDelay:0,fill:c?"both":"none",iterationStart:0,iterations:1,duration:c?"auto":0,playbackRate:1,direction:"normal",easing:"linear"};return"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof d[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==p.indexOf(b[c]))return;if("direction"==c&&-1==q.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;d[c]=b[c]}}):d.duration=b,d}function c(a,c){var d=b(a,c);return d.easing=f(d.easing),d}function d(a,b,c,d){return 0>a||a>1||0>c||c>1?y:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function e(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function f(a){var b=w.exec(a);if(b)return d.apply(this,b.slice(1).map(Number));var c=x.exec(a);if(c)return e(Number(c[1]),{start:r,middle:s,end:t}[c[2]]);var f=u[a];return f?f:y}function g(a){return Math.abs(h(a)/a.playbackRate)}function h(a){return a.duration*a.iterations}function i(a,b,c){return null==b?z:b=c.delay+a?B:C}function j(a,b,c,d,e){switch(d){case A:return"backwards"==b||"both"==b?0:null;case C:return c-e;case B:return"forwards"==b||"both"==b?a:null;case z:return null}}function k(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function l(a,b,c,d,e){return 1/0===c||c===-1/0||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function m(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function n(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function o(a,b,c){var d=i(a,b,c),e=j(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===A?0:1;var f=c.iterationStart*c.duration,g=k(a,e,f,c),o=l(c.duration,h(c),g,f,c),p=m(c.duration,o,g,c);return n(p,c.duration,o,c)/c.duration}var p="backwards|forwards|both|none".split("|"),q="reverse|alternate|alternate-reverse".split("|"),r=1,s=.5,t=0,u={ease:d(.25,.1,.25,1),"ease-in":d(.42,0,1,1),"ease-out":d(0,0,.58,1),"ease-in-out":d(.42,0,.58,1),"step-start":e(1,r),"step-middle":e(1,s),"step-end":e(1,t)},v="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",w=new RegExp("cubic-bezier\\("+v+","+v+","+v+","+v+"\\)"),x=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,y=function(a){return a},z=0,A=1,B=2,C=3;a.makeTiming=b,a.normalizeTimingInput=c,a.calculateActiveDuration=g,a.calculateTimeFraction=o,a.calculatePhase=i,a.toTimingFunction=f}(c,f),function(a){function b(a,b){return a in h?h[a][b]||b:b}function c(a,c,d){var g=e[a];if(g){f.style[a]=c;for(var h in g){var i=g[h],j=f.style[i];d[i]=b(i,j)}}else d[a]=b(a,c)}function d(b){function d(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var d={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}c(e,f,d)}return void 0==d.offset&&(d.offset=null),void 0==d.easing&&(d.easing=a.toTimingFunction("linear")),d}),f=!0,g=-1/0,h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||d(),e}var e={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},f=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g={thin:"1px",medium:"3px",thick:"5px"},h={borderBottomWidth:g,borderLeftWidth:g,borderRightWidth:g,borderTopWidth:g,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:g,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=d}(c,f),function(a){var b={};a.isDeprecated=function(a,c,d,e){var f=e?"are":"is",g=new Date,h=new Date(c);return h.setMonth(h.getMonth()+3),h>g?(a in b||console.warn("Web Animations: "+a+" "+f+" deprecated and will stop working on "+h.toDateString()+". "+d),b[a]=!0,!1):!0},a.deprecated=function(b,c,d,e){var f=e?"are":"is";if(a.isDeprecated(b,c,d,e))throw new Error(b+" "+f+" no longer supported. "+d)}}(c),function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}!function(a,b){function c(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a){function b(a,b,c){e[c]=e[c]||[],e[c].push([a,b])}function c(a,c,d){for(var e=0;ethis._surrogateStyle.length;)this._length--,Object.defineProperty(this,this._length,{configurable:!0,enumerable:!1,value:void 0})},_set:function(a,b){this._style[a]=b,this._isAnimatedProperty[a]=!0},_clear:function(a){this._style[a]=this._surrogateStyle[a],delete this._isAnimatedProperty[a]}};for(var h in f)c.prototype[h]=function(a,b){return function(){var c=this._surrogateStyle[a].apply(this._surrogateStyle,arguments);return b&&(this._isAnimatedProperty[arguments[0]]||this._style[a].apply(this._style,arguments),this._updateIndices()),c}}(h,h in g);for(var i in document.documentElement.style)i in e||i in f||!function(a){b(c.prototype,a,{get:function(){return this._surrogateStyle[a]},set:function(b){this._surrogateStyle[a]=b,this._updateIndices(),this._isAnimatedProperty[a]||(this._style[a]=b)}})}(i);a.apply=function(b,c,e){d(b),b.style._set(a.propertyName(c),e)},a.clear=function(b,c){b._webAnimationsPatchedStyle&&b.style._clear(a.propertyName(c))}}(d,f),function(a){window.Element.prototype.animate=function(b,c){return a.timeline._play(a.KeyframeEffect(this,b,c))}}(d),function(a){function b(a,c,d){if("number"==typeof a&&"number"==typeof c)return a*(1-d)+c*d;if("boolean"==typeof a&&"boolean"==typeof c)return.5>d?a:c;if(a.length==c.length){for(var e=[],f=0;fj;j++)g.push(c[j]*(Math.cos(e*h)-f*i)+d[j]*i);return g}var d=function(){function a(a,b){for(var c=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],d=0;4>d;d++)for(var e=0;4>e;e++)for(var f=0;4>f;f++)c[d][e]+=b[d][f]*a[f][e];return c}function b(a){return 0==a[0][2]&&0==a[0][3]&&0==a[1][2]&&0==a[1][3]&&0==a[2][0]&&0==a[2][1]&&1==a[2][2]&&0==a[2][3]&&0==a[3][2]&&1==a[3][3]}function c(c,d,e,f,g){for(var h=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],i=0;4>i;i++)h[i][3]=g[i];for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[3][i]+=c[j]*h[j][i];var k=f[0],l=f[1],m=f[2],n=f[3],o=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];o[0][0]=1-2*(l*l+m*m),o[0][1]=2*(k*l-m*n),o[0][2]=2*(k*m+l*n),o[1][0]=2*(k*l+m*n),o[1][1]=1-2*(k*k+m*m),o[1][2]=2*(l*m-k*n),o[2][0]=2*(k*m-l*n),o[2][1]=2*(l*m+k*n),o[2][2]=1-2*(k*k+l*l),h=a(h,o);var p=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];e[2]&&(p[2][1]=e[2],h=a(h,p)),e[1]&&(p[2][1]=0,p[2][0]=e[0],h=a(h,p)),e[0]&&(p[2][0]=0,p[1][0]=e[0],h=a(h,p));for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[i][j]*=d[i];return b(h)?[h[0][0],h[0][1],h[1][0],h[1][1],h[3][0],h[3][1]]:h[0].concat(h[1],h[2],h[3])}return c}();a.composeMatrix=d,a.quat=c}(d,f),function(a){var b=0,c=function(a,b,c){this.target=a,this.currentTime=b,this.timelineTime=c,this.type="finish",this.bubbles=!1,this.cancelable=!1,this.currentTarget=a,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()};a.Animation=function(a){this._sequenceNumber=b++,this._currentTime=0,this._startTime=null,this.paused=!1,this._playbackRate=1,this._inTimeline=!0,this._finishedFlag=!1,this.onfinish=null,this._finishHandlers=[],this._effect=a,this._inEffect=this._effect._update(0),this._idle=!0,this._currentTimePending=!1},a.Animation.prototype={_ensureAlive:function(){this._inEffect=this._effect._update(this.playbackRate<0&&0===this.currentTime?-1:this.currentTime),this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,a.timeline._animations.push(this))},_tickCurrentTime:function(a,b){a!=this._currentTime&&(this._currentTime=a,this.finished&&!b&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(b){b=+b,isNaN(b)||(a.restart(),this.paused||null==this._startTime||(this._startTime=this._timeline.currentTime-b/this._playbackRate),this._currentTimePending=!1,this._currentTime!=b&&(this._tickCurrentTime(b,!0),a.invalidateEffects()))},get startTime(){return this._startTime},set startTime(b){b=+b,isNaN(b)||this.paused||this._idle||(this._startTime=b,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),a.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get finished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this.paused&&0!=this.playbackRate||this._currentTimePending?"pending":this.paused?"paused":this.finished?"finished":"running"},play:function(){this.paused=!1,(this.finished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,a.invalidateEffects()),this._finishedFlag=!1,a.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this.finished||this.paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this.paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this.finished;if((b||this._idle)&&!this._finishedFlag){var d=new c(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);setTimeout(function(){e.forEach(function(a){a.call(d.target,d)})},0)}this._finishedFlag=b},_tick:function(a){return this._idle||this.paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this.finished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(d,f),function(a,b){function c(a){var b=i;i=[],g(a),b.forEach(function(b){b[1](a)}),m&&g(a),f()}function d(a,b){return a._sequenceNumber-b._sequenceNumber}function e(){this._animations=[],this.currentTime=window.performance&&performance.now?performance.now():0}function f(){n.forEach(function(a){a()}),n.length=0}function g(a){l=!1;var c=b.timeline;c.currentTime=a,c._animations.sort(d),k=!1;var e=c._animations;c._animations=[];var f=[],g=[];e=e.filter(function(b){return b._inTimeline=b._tick(a),b._inEffect?g.push(b._effect):f.push(b._effect),b.finished||b.paused||b._idle||(k=!0),b._inTimeline}),n.push.apply(n,f),n.push.apply(n,g),c._animations.push.apply(c._animations,e),m=!1,k&&requestAnimationFrame(function(){})}var h=window.requestAnimationFrame,i=[],j=0;window.requestAnimationFrame=function(a){var b=j++;return 0==i.length&&h(c),i.push([b,a]),b},window.cancelAnimationFrame=function(a){i.forEach(function(b){b[0]==a&&(b[1]=function(){})})},e.prototype={_play:function(c){c._timing=a.normalizeTimingInput(c.timing);var d=new b.Animation(c);return d._idle=!1,d._timeline=this,this._animations.push(d),b.restart(),b.invalidateEffects(),d}};var k=!1,l=!1;b.restart=function(){return k||(k=!0,requestAnimationFrame(function(){}),l=!0),l};var m=!1;b.invalidateEffects=function(){m=!0};var n=[],o=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){return m&&g(p.currentTime),f(),o.apply(this,arguments)}});var p=new e;b.timeline=p}(c,d,f),function(a){function b(a,b){for(var c=0,d=0;do;o++){for(var p=0,q=0;3>q;q++)p+=b[3][q]*m[q][o];n.push(p)}return n.push(1),m.push(n),m}function d(a){return[[a[0][0],a[1][0],a[2][0],a[3][0]],[a[0][1],a[1][1],a[2][1],a[3][1]],[a[0][2],a[1][2],a[2][2],a[3][2]],[a[0][3],a[1][3],a[2][3],a[3][3]]]}function e(a,b){for(var c=[],d=0;4>d;d++){for(var e=0,f=0;4>f;f++)e+=a[f]*b[f][d];c.push(e)}return c}function f(a){var b=g(a);return[a[0]/b,a[1]/b,a[2]/b]}function g(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])}function h(a,b,c,d){return[c*a[0]+d*b[0],c*a[1]+d*b[1],c*a[2]+d*b[2]]}function i(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]}function j(j){var k=[j.slice(0,4),j.slice(4,8),j.slice(8,12),j.slice(12,16)];if(1!==k[3][3])return null;for(var l=[],m=0;4>m;m++)l.push(k[m].slice());for(var m=0;3>m;m++)l[m][3]=0;if(0===a(l))return!1;var n,o=[];if(k[0][3]||k[1][3]||k[2][3]){o.push(k[0][3]),o.push(k[1][3]),o.push(k[2][3]),o.push(k[3][3]);var p=c(l),q=d(p);n=e(o,q)}else n=[0,0,0,1];var r=k[3].slice(0,3),s=[];s.push(k[0].slice(0,3));var t=[];t.push(g(s[0])),s[0]=f(s[0]);var u=[];s.push(k[1].slice(0,3)),u.push(b(s[0],s[1])),s[1]=h(s[1],s[0],1,-u[0]),t.push(g(s[1])),s[1]=f(s[1]),u[0]/=t[1],s.push(k[2].slice(0,3)),u.push(b(s[0],s[2])),s[2]=h(s[2],s[0],1,-u[1]),u.push(b(s[1],s[2])),s[2]=h(s[2],s[1],1,-u[2]),t.push(g(s[2])),s[2]=f(s[2]),u[1]/=t[2],u[2]/=t[2];var v=i(s[1],s[2]);if(b(s[0],v)<0)for(var m=0;3>m;m++)t[m]*=-1,s[m][0]*=-1,s[m][1]*=-1,s[m][2]*=-1;var w,x,y=s[0][0]+s[1][1]+s[2][2]+1;return y>1e-4?(w=.5/Math.sqrt(y),x=[(s[2][1]-s[1][2])*w,(s[0][2]-s[2][0])*w,(s[1][0]-s[0][1])*w,.25/w]):s[0][0]>s[1][1]&&s[0][0]>s[2][2]?(w=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]),x=[.25*w,(s[0][1]+s[1][0])/w,(s[0][2]+s[2][0])/w,(s[2][1]-s[1][2])/w]):s[1][1]>s[2][2]?(w=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]),x=[(s[0][1]+s[1][0])/w,.25*w,(s[1][2]+s[2][1])/w,(s[0][2]-s[2][0])/w]):(w=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]),x=[(s[0][2]+s[2][0])/w,(s[1][2]+s[2][1])/w,.25*w,(s[1][0]-s[0][1])/w]),[r,t,u,x,n]}return j}();a.dot=b,a.makeMatrixDecomposition=f}(d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,b,["visibility"])}(d),function(a){function b(a){a=a.trim(),e.fillStyle="#000",e.fillStyle=a;var b=e.fillStyle;if(e.fillStyle="#fff",e.fillStyle=a,b==e.fillStyle){e.fillRect(0,0,1,1);var c=e.getImageData(0,0,1,1).data;e.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function c(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=d.height=1;var e=d.getContext("2d");a.addPropertiesHandler(b,c,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,b),a.mergeColors=c}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a){function b(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function c(c){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,b,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],c);return d&&4==d[0].length?d[0]:void 0}function d(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function e(a){return"rect("+a+")"}var f=a.mergeWrappedNestedRepeated.bind(null,e,d,", ");a.parseBox=c,a.mergeBoxes=f,a.addPropertiesHandler(c,f,["clip"]) +}(d,f),function(a){function b(a){return function(b){var c=0;return a.map(function(a){return a===j?b[c++]:a})}}function c(a){return a}function d(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=m[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.lengthb||b>900||b%100!==0?void 0:b}function c(b){return b=100*Math.round(b/100),b=a.clamp(100,900,b),400===b?"normal":700===b?"bold":String(b)}function d(a,b){return[a,b,c]}a.addPropertiesHandler(b,d,["font-weight"])}(d),function(a){function b(a){var b={};for(var c in a)b[c]=-a[c];return b}function c(b){return a.consumeToken(/^(left|center|right|top|bottom)\b/i,b)||a.consumeLengthOrPercent(b)}function d(b,d){var e=a.consumeRepeated(c,/^/,d);if(e&&""==e[1]){var f=e[0];if(f[0]=f[0]||"center",f[1]=f[1]||"center",3==b&&(f[2]=f[2]||{px:0}),f.length==b){if(/top|bottom/.test(f[0])||/left|right/.test(f[1])){var h=f[0];f[0]=f[1],f[1]=h}if(/left|right|center|Object/.test(f[0])&&/top|bottom|center|Object/.test(f[1]))return f.map(function(a){return"object"==typeof a?a:g[a]})}}}function e(d){var e=a.consumeRepeated(c,/^/,d);if(e){for(var f=e[0],h=[{"%":50},{"%":50}],i=0,j=!1,k=0;k + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/web-animations.dev.js b/scripts/vendor/web-animations-js/web-animations.dev.js new file mode 100755 index 0000000000..7f2b4571eb --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations.dev.js @@ -0,0 +1,21 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var webAnimationsSourceTarget = 'web-animations'; +var WEB_ANIMATIONS_TESTING = false; +(function() { + var scripts = document.getElementsByTagName('script'); + var location = scripts[scripts.length - 1].src.replace(/[^\/]+$/, ''); + document.write(''); + document.write(''); +})(); diff --git a/scripts/vendor/web-animations-js/web-animations.html b/scripts/vendor/web-animations-js/web-animations.html new file mode 100755 index 0000000000..b5de36c855 --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/vendor/web-animations-js/web-animations.min.js b/scripts/vendor/web-animations-js/web-animations.min.js new file mode 100755 index 0000000000..4dc2fb3850 --- /dev/null +++ b/scripts/vendor/web-animations-js/web-animations.min.js @@ -0,0 +1,36 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +console.log('Native Web Animations', !!document.documentElement.animate); + + +!function(a,b){b["true"]=a,function(){if(document.documentElement.animate || true){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}var c={},d={},e={},f=null;!function(a){function b(b,c){var d={delay:0,endDelay:0,fill:c?"both":"none",iterationStart:0,iterations:1,duration:c?"auto":0,playbackRate:1,direction:"normal",easing:"linear"};return"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof d[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==p.indexOf(b[c]))return;if("direction"==c&&-1==q.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;d[c]=b[c]}}):d.duration=b,d}function c(a,c){var d=b(a,c);return d.easing=f(d.easing),d}function d(a,b,c,d){return 0>a||a>1||0>c||c>1?y:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function e(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function f(a){var b=w.exec(a);if(b)return d.apply(this,b.slice(1).map(Number));var c=x.exec(a);if(c)return e(Number(c[1]),{start:r,middle:s,end:t}[c[2]]);var f=u[a];return f?f:y}function g(a){return Math.abs(h(a)/a.playbackRate)}function h(a){return a.duration*a.iterations}function i(a,b,c){return null==b?z:b=c.delay+a?B:C}function j(a,b,c,d,e){switch(d){case A:return"backwards"==b||"both"==b?0:null;case C:return c-e;case B:return"forwards"==b||"both"==b?a:null;case z:return null}}function k(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function l(a,b,c,d,e){return 1/0===c||c===-1/0||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function m(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function n(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function o(a,b,c){var d=i(a,b,c),e=j(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===A?0:1;var f=c.iterationStart*c.duration,g=k(a,e,f,c),o=l(c.duration,h(c),g,f,c),p=m(c.duration,o,g,c);return n(p,c.duration,o,c)/c.duration}var p="backwards|forwards|both|none".split("|"),q="reverse|alternate|alternate-reverse".split("|"),r=1,s=.5,t=0,u={ease:d(.25,.1,.25,1),"ease-in":d(.42,0,1,1),"ease-out":d(0,0,.58,1),"ease-in-out":d(.42,0,.58,1),"step-start":e(1,r),"step-middle":e(1,s),"step-end":e(1,t)},v="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",w=new RegExp("cubic-bezier\\("+v+","+v+","+v+","+v+"\\)"),x=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,y=function(a){return a},z=0,A=1,B=2,C=3;a.makeTiming=b,a.normalizeTimingInput=c,a.calculateActiveDuration=g,a.calculateTimeFraction=o,a.calculatePhase=i,a.toTimingFunction=f}(c,f),function(a){function b(a,b){return a in h?h[a][b]||b:b}function c(a,c,d){var g=e[a];if(g){f.style[a]=c;for(var h in g){var i=g[h],j=f.style[i];d[i]=b(i,j)}}else d[a]=b(a,c)}function d(b){function d(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var d={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}c(e,f,d)}return void 0==d.offset&&(d.offset=null),void 0==d.easing&&(d.easing=a.toTimingFunction("linear")),d}),f=!0,g=-1/0,h=0;hi)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||d(),e}var e={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},f=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g={thin:"1px",medium:"3px",thick:"5px"},h={borderBottomWidth:g,borderLeftWidth:g,borderRightWidth:g,borderTopWidth:g,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:g,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=d}(c,f),function(a){var b={};a.isDeprecated=function(a,c,d,e){var f=e?"are":"is",g=new Date,h=new Date(c);return h.setMonth(h.getMonth()+3),h>g?(a in b||console.warn("Web Animations: "+a+" "+f+" deprecated and will stop working on "+h.toDateString()+". "+d),b[a]=!0,!1):!0},a.deprecated=function(b,c,d,e){var f=e?"are":"is";if(a.isDeprecated(b,c,d,e))throw new Error(b+" "+f+" no longer supported. "+d)}}(c),function(a,b){function c(a){for(var b={},c=0;c=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a){function b(a,b,c){e[c]=e[c]||[],e[c].push([a,b])}function c(a,c,d){for(var e=0;ethis._surrogateStyle.length;)this._length--,Object.defineProperty(this,this._length,{configurable:!0,enumerable:!1,value:void 0})},_set:function(a,b){this._style[a]=b,this._isAnimatedProperty[a]=!0},_clear:function(a){this._style[a]=this._surrogateStyle[a],delete this._isAnimatedProperty[a]}};for(var h in f)c.prototype[h]=function(a,b){return function(){var c=this._surrogateStyle[a].apply(this._surrogateStyle,arguments);return b&&(this._isAnimatedProperty[arguments[0]]||this._style[a].apply(this._style,arguments),this._updateIndices()),c}}(h,h in g);for(var i in document.documentElement.style)i in e||i in f||!function(a){b(c.prototype,a,{get:function(){return this._surrogateStyle[a]},set:function(b){this._surrogateStyle[a]=b,this._updateIndices(),this._isAnimatedProperty[a]||(this._style[a]=b)}})}(i);a.apply=function(b,c,e){d(b),b.style._set(a.propertyName(c),e)},a.clear=function(b,c){b._webAnimationsPatchedStyle&&b.style._clear(a.propertyName(c))}}(d,f),function(a){window.Element.prototype.animate=function(b,c){return a.timeline._play(a.KeyframeEffect(this,b,c))}}(d),function(a){function b(a,c,d){if("number"==typeof a&&"number"==typeof c)return a*(1-d)+c*d;if("boolean"==typeof a&&"boolean"==typeof c)return.5>d?a:c;if(a.length==c.length){for(var e=[],f=0;fj;j++)g.push(c[j]*(Math.cos(e*h)-f*i)+d[j]*i);return g}var d=function(){function a(a,b){for(var c=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],d=0;4>d;d++)for(var e=0;4>e;e++)for(var f=0;4>f;f++)c[d][e]+=b[d][f]*a[f][e];return c}function b(a){return 0==a[0][2]&&0==a[0][3]&&0==a[1][2]&&0==a[1][3]&&0==a[2][0]&&0==a[2][1]&&1==a[2][2]&&0==a[2][3]&&0==a[3][2]&&1==a[3][3]}function c(c,d,e,f,g){for(var h=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],i=0;4>i;i++)h[i][3]=g[i];for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[3][i]+=c[j]*h[j][i];var k=f[0],l=f[1],m=f[2],n=f[3],o=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];o[0][0]=1-2*(l*l+m*m),o[0][1]=2*(k*l-m*n),o[0][2]=2*(k*m+l*n),o[1][0]=2*(k*l+m*n),o[1][1]=1-2*(k*k+m*m),o[1][2]=2*(l*m-k*n),o[2][0]=2*(k*m-l*n),o[2][1]=2*(l*m+k*n),o[2][2]=1-2*(k*k+l*l),h=a(h,o);var p=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];e[2]&&(p[2][1]=e[2],h=a(h,p)),e[1]&&(p[2][1]=0,p[2][0]=e[0],h=a(h,p)),e[0]&&(p[2][0]=0,p[1][0]=e[0],h=a(h,p));for(var i=0;3>i;i++)for(var j=0;3>j;j++)h[i][j]*=d[i];return b(h)?[h[0][0],h[0][1],h[1][0],h[1][1],h[3][0],h[3][1]]:h[0].concat(h[1],h[2],h[3])}return c}();a.composeMatrix=d,a.quat=c}(d,f),function(a){var b=0,c=function(a,b,c){this.target=a,this.currentTime=b,this.timelineTime=c,this.type="finish",this.bubbles=!1,this.cancelable=!1,this.currentTarget=a,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()};a.Animation=function(a){this._sequenceNumber=b++,this._currentTime=0,this._startTime=null,this.paused=!1,this._playbackRate=1,this._inTimeline=!0,this._finishedFlag=!1,this.onfinish=null,this._finishHandlers=[],this._effect=a,this._inEffect=this._effect._update(0),this._idle=!0,this._currentTimePending=!1},a.Animation.prototype={_ensureAlive:function(){this._inEffect=this._effect._update(this.playbackRate<0&&0===this.currentTime?-1:this.currentTime),this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,a.timeline._animations.push(this))},_tickCurrentTime:function(a,b){a!=this._currentTime&&(this._currentTime=a,this.finished&&!b&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(b){b=+b,isNaN(b)||(a.restart(),this.paused||null==this._startTime||(this._startTime=this._timeline.currentTime-b/this._playbackRate),this._currentTimePending=!1,this._currentTime!=b&&(this._tickCurrentTime(b,!0),a.invalidateEffects()))},get startTime(){return this._startTime},set startTime(b){b=+b,isNaN(b)||this.paused||this._idle||(this._startTime=b,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),a.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get finished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this.paused&&0!=this.playbackRate||this._currentTimePending?"pending":this.paused?"paused":this.finished?"finished":"running"},play:function(){this.paused=!1,(this.finished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,a.invalidateEffects()),this._finishedFlag=!1,a.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this.finished||this.paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this.paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this.finished;if((b||this._idle)&&!this._finishedFlag){var d=new c(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]); + + // cannot use setTimeout because it let's the browser + // do a repaint before the correct ending css classes are added/removed + // setTimeout(function(){ + // e.forEach(function(a){ + // a.call(d.target,d) + // }) + // }, 0) + + e.forEach(function(a){ + console.log('finished!') + a.call(d.target,d) + }) + +}this._finishedFlag=b},_tick:function(a){return this._idle||this.paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this.finished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(d,f),function(a,b){function c(a){var b=i;i=[],g(a),b.forEach(function(b){b[1](a)}),m&&g(a),f()}function d(a,b){return a._sequenceNumber-b._sequenceNumber}function e(){this._animations=[],this.currentTime=window.performance&&performance.now?performance.now():0}function f(){n.forEach(function(a){a()}),n.length=0}function g(a){l=!1;var c=b.timeline;c.currentTime=a,c._animations.sort(d),k=!1;var e=c._animations;c._animations=[];var f=[],g=[];e=e.filter(function(b){return b._inTimeline=b._tick(a),b._inEffect?g.push(b._effect):f.push(b._effect),b.finished||b.paused||b._idle||(k=!0),b._inTimeline}),n.push.apply(n,f),n.push.apply(n,g),c._animations.push.apply(c._animations,e),m=!1,k&&requestAnimationFrame(function(){})}var h=window.requestAnimationFrame,i=[],j=0;window.requestAnimationFrame=function(a){var b=j++;return 0==i.length&&h(c),i.push([b,a]),b},window.cancelAnimationFrame=function(a){i.forEach(function(b){b[0]==a&&(b[1]=function(){})})},e.prototype={_play:function(c){c._timing=a.normalizeTimingInput(c.timing);var d=new b.Animation(c);return d._idle=!1,d._timeline=this,this._animations.push(d),b.restart(),b.invalidateEffects(),d}};var k=!1,l=!1;b.restart=function(){return k||(k=!0,requestAnimationFrame(function(){}),l=!0),l};var m=!1;b.invalidateEffects=function(){m=!0};var n=[],o=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){return m&&g(p.currentTime),f(),o.apply(this,arguments)}});var p=new e;b.timeline=p}(c,d,f),function(a){function b(a,b){for(var c=0,d=0;do;o++){for(var p=0,q=0;3>q;q++)p+=b[3][q]*m[q][o];n.push(p)}return n.push(1),m.push(n),m}function d(a){return[[a[0][0],a[1][0],a[2][0],a[3][0]],[a[0][1],a[1][1],a[2][1],a[3][1]],[a[0][2],a[1][2],a[2][2],a[3][2]],[a[0][3],a[1][3],a[2][3],a[3][3]]]}function e(a,b){for(var c=[],d=0;4>d;d++){for(var e=0,f=0;4>f;f++)e+=a[f]*b[f][d];c.push(e)}return c}function f(a){var b=g(a);return[a[0]/b,a[1]/b,a[2]/b]}function g(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])}function h(a,b,c,d){return[c*a[0]+d*b[0],c*a[1]+d*b[1],c*a[2]+d*b[2]]}function i(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]}function j(j){var k=[j.slice(0,4),j.slice(4,8),j.slice(8,12),j.slice(12,16)];if(1!==k[3][3])return null;for(var l=[],m=0;4>m;m++)l.push(k[m].slice());for(var m=0;3>m;m++)l[m][3]=0;if(0===a(l))return!1;var n,o=[];if(k[0][3]||k[1][3]||k[2][3]){o.push(k[0][3]),o.push(k[1][3]),o.push(k[2][3]),o.push(k[3][3]);var p=c(l),q=d(p);n=e(o,q)}else n=[0,0,0,1];var r=k[3].slice(0,3),s=[];s.push(k[0].slice(0,3));var t=[];t.push(g(s[0])),s[0]=f(s[0]);var u=[];s.push(k[1].slice(0,3)),u.push(b(s[0],s[1])),s[1]=h(s[1],s[0],1,-u[0]),t.push(g(s[1])),s[1]=f(s[1]),u[0]/=t[1],s.push(k[2].slice(0,3)),u.push(b(s[0],s[2])),s[2]=h(s[2],s[0],1,-u[1]),u.push(b(s[1],s[2])),s[2]=h(s[2],s[1],1,-u[2]),t.push(g(s[2])),s[2]=f(s[2]),u[1]/=t[2],u[2]/=t[2];var v=i(s[1],s[2]);if(b(s[0],v)<0)for(var m=0;3>m;m++)t[m]*=-1,s[m][0]*=-1,s[m][1]*=-1,s[m][2]*=-1;var w,x,y=s[0][0]+s[1][1]+s[2][2]+1;return y>1e-4?(w=.5/Math.sqrt(y),x=[(s[2][1]-s[1][2])*w,(s[0][2]-s[2][0])*w,(s[1][0]-s[0][1])*w,.25/w]):s[0][0]>s[1][1]&&s[0][0]>s[2][2]?(w=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]),x=[.25*w,(s[0][1]+s[1][0])/w,(s[0][2]+s[2][0])/w,(s[2][1]-s[1][2])/w]):s[1][1]>s[2][2]?(w=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]),x=[(s[0][1]+s[1][0])/w,.25*w,(s[1][2]+s[2][1])/w,(s[0][2]-s[2][0])/w]):(w=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]),x=[(s[0][2]+s[2][0])/w,(s[1][2]+s[2][1])/w,.25*w,(s[1][0]-s[0][1])/w]),[r,t,u,x,n]}return j}();a.dot=b,a.makeMatrixDecomposition=f}(d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;ek;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,b,["visibility"])}(d),function(a){function b(a){a=a.trim(),e.fillStyle="#000",e.fillStyle=a;var b=e.fillStyle;if(e.fillStyle="#fff",e.fillStyle=a,b==e.fillStyle){e.fillRect(0,0,1,1);var c=e.getImageData(0,0,1,1).data;e.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function c(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=d.height=1;var e=d.getContext("2d");a.addPropertiesHandler(b,c,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,b),a.mergeColors=c}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a){function b(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function c(c){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,b,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],c);return d&&4==d[0].length?d[0]:void 0}function d(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function e(a){return"rect("+a+")"}var f=a.mergeWrappedNestedRepeated.bind(null,e,d,", ");a.parseBox=c,a.mergeBoxes=f,a.addPropertiesHandler(c,f,["clip"]) +}(d,f),function(a){function b(a){return function(b){var c=0;return a.map(function(a){return a===j?b[c++]:a})}}function c(a){return a}function d(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=m[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.lengthb||b>900||b%100!==0?void 0:b}function c(b){return b=100*Math.round(b/100),b=a.clamp(100,900,b),400===b?"normal":700===b?"bold":String(b)}function d(a,b){return[a,b,c]}a.addPropertiesHandler(b,d,["font-weight"])}(d),function(a){function b(a){var b={};for(var c in a)b[c]=-a[c];return b}function c(b){return a.consumeToken(/^(left|center|right|top|bottom)\b/i,b)||a.consumeLengthOrPercent(b)}function d(b,d){var e=a.consumeRepeated(c,/^/,d);if(e&&""==e[1]){var f=e[0];if(f[0]=f[0]||"center",f[1]=f[1]||"center",3==b&&(f[2]=f[2]||{px:0}),f.length==b){if(/top|bottom/.test(f[0])||/left|right/.test(f[1])){var h=f[0];f[0]=f[1],f[1]=h}if(/left|right|center|Object/.test(f[0])&&/top|bottom|center|Object/.test(f[1]))return f.map(function(a){return"object"==typeof a?a:g[a]})}}}function e(d){var e=a.consumeRepeated(c,/^/,d);if(e){for(var f=e[0],h=[{"%":50},{"%":50}],i=0,j=!1,k=0;k