Documentation updates and performance test page reworked with safety features.

This commit is contained in:
thednp 2016-11-26 17:47:17 +02:00
parent 7aa15a43b5
commit 72a915c051
22 changed files with 134 additions and 90 deletions

View file

@ -1,6 +1,6 @@
{
"name": "KUTE.js",
"version": "1.5.98a",
"version": "1.5.99",
"homepage": "http://thednp.github.io/kute.js",
"authors": [
"thednp"

View file

@ -72,7 +72,7 @@
<div class="content-wrap">
<h2>Did you know?</h2>
<p><strong>Tween</strong> is a term used by animators and software engineers to define the numeric start, end and the <a href="https://en.wikipedia.org/wiki/Inbetweening" target="_blank"><em>inbetween</em></a> values used in digital animation, while the digital animation uses these tween values on a given frequency (interval) or scaled by hardware capability (monitors refresh rate, GPU frames per second, etc). The term was introduced to the world of web development by early Javascrpt libraries and later used in dedicated animation libraries such as <a href="https://greensock.com" target="_blank">GSAP</a>, <a href="http://dynamicsjs.com" target="_blank">Dynamics</a>, <a href="http://julian.com/research/velocity/" target="_blank">Velocity</a>, <a href="https://jeremyckahn.github.io/shifty/" target="_blank">Shifty</a>, our own <strong>KUTE.js</strong> here and many others. When used as a verb, it actually reffers to the interpolation of the values.</p>
<p><strong>Tween</strong> is a term used by animators and software engineers to define the numeric start, end and the <a href="https://en.wikipedia.org/wiki/Inbetweening" target="_blank"><em>inbetween</em></a> values used in digital animation, while the digital animation uses these tween values on a given frequency (interval) or scaled by hardware capability (monitors refresh rate, GPU vertical sync, etc). The term was introduced to the world of web development by early Javascrpt libraries and later used in dedicated animation libraries such as <a href="https://greensock.com" target="_blank">GSAP</a>, <a href="http://dynamicsjs.com" target="_blank">Dynamics</a>, <a href="http://julian.com/research/velocity/" target="_blank">Velocity</a>, <a href="https://jeremyckahn.github.io/shifty/" target="_blank">Shifty</a>, our own <strong>KUTE.js</strong> here and many others. When used as a verb, it actually reffers to the interpolation of the values.</p>
<p><strong>Tween Object</strong> is a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" target="_blank"><em>Javascript Object</em></a> that stores temporarily or for a given time a set of variables such as tween values, HTML elements to animate, CSS properties and other tween options to be used for animation. To improve performance on repetitive animations, this object can be cached and reused whenever needed. In Javascript animation, the term <strong>tween</strong> actually refers to the <strong>tween object</strong>.</p>
<p><strong>polyfill</strong> is a term introduced by Remy Sharp back in 2009 as "a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide <em>natively</em>". Basically a polyfill covers what legacy browsers don't support or in other cases corrects the implemented behavior that is different from the standards. <a href="https://remysharp.com/2010/10/08/what-is-a-polyfill" target="_blank">More details</a>.</p>
<p><strong>requestAnimationFrame</strong> is a <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame" target="_blank"><em>Javascript method</em></a> developed to enable hardware acceleration animations for the web today. In Javascript, the <code>window.requestAnimationFrame(callback);</code> method is all we need to setup animations really for all the above mentioned animation engines. Some developers built a <a href="http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/">polyfil</a> to cover the legacy browsers chaos.</p>
@ -107,7 +107,7 @@
<p>Similarly, if you animate the 2D <code>translate</code> this always goes <code>translate(x,y)</code> even if you use <code>translate:150</code> (only for the X axis) or <code>translate:[150,0]</code> (both X and Y axis), for better performance as well. And by the way, this works great on IE9 and other legacy browsers.</p>
<h3>Box Model</h3>
<p><span class="ion-nuclear media"></span>We compared position with transition above, but now we are going to talk about other issues related to <strong>resizers</strong>: <code>width</code>, <code>height</code>, <code>margin</code>, <code>padding</code> and <code>borderWidth</code> or any of their variations. The code execution is super fast, but when resizing the window while animations are running, the browser is also computing the resize handlers, the animation performance is very very low on <strong>all</strong> browsers, especially when you animate these resize properties. When this <strong>toxic combination</strong> occurs animating a large amount of elements to animate could crash any browser, no exception, and I think any developer should know about this.</p>
<p><span class="ion-nuclear media"></span>We compared position with transition above, but now we are going to talk about other issues related to <strong>resizers</strong>: <code>width</code>, <code>height</code>, <code>margin</code>, <code>padding</code> and <code>borderWidth</code> or any of their variations. The code execution is super fast, but when resizing the window while animations are running, the browser is also computing the resize handlers, the animation performance is very very low on <strong>all</strong> browsers, especially when you animate these resize properties. When this <strong>toxic combination</strong> occurs animating a large amount of elements could crash any browser, no exception, and I think any developer should know about this.</p>
<p>The <code>resize</code> event triggered by these resizer properties can cause some <strong>severe issues with legacy browsers</strong> such as IE8. These good old browsers don't understand much about Javascript driven layout changes and thus skip/fail to execute any handlers attached to window resize event bubbles.</p>
<p>A workaound for the resizers' effect on the layout would be to use them only for absolute positioned elements, this way the layout will not need to be repainted and the recomposition is limited to the elements themselves. If not, and you are required to provide legacy support, you must DISABLE any resize handlers for IE8 and any other browser that runs slow or crashes. You should also consider not using any resize animation for legacy browsers especially when usability and larger reach is expected.</p>

View file

@ -86,12 +86,12 @@
<p>These methods allow you to create <strong>tween objects</strong> and collections of <strong>tween objects</strong>; as we know, a tween object is essentially like an animation setup for a given HTML element, defining CSS properties, animation duration, repeat or other options. The methods have different uses and performance scores while making it easy to work with.</p>
<h3>Single Tween Object</h3>
<p>As the heading suggests, the following two methods allow you to create tween objects for a single HTML element, except when used in combination with jQuery and the KUTE.js plugin for jQuery, where, as jQuery always does, it always works with collections of elements.</p>
<p>As the heading suggests, the following two methods allow you to create tween objects for individual HTML elements, except when used in combination with jQuery and the KUTE.js plugin for jQuery, where, as jQuery always does, it always works with collections of elements.</p>
<p><kbd>.to()</kbd> method is the most simple method which allows you to create tween objects for animating CSS properties from a specific default value OR from current/computed value TO a desired value.
It's performance is not the same as for the <strong>.fromTo()</strong> method as it has to compute the default/current value on tween <code>.start()</code> and thus delays the animation for a couple of miliseconds; still this feature is great for simple animations AND it has the ability to stack transform properties as they go, making smooth transform animations on chained tweens. See the <a href="#start">.start()</a> method for the solution for sync/delay issue.</p>
<p>Considering a given <em>div</em> element is already transparent, a super quick example would be:</p>
<pre><code class="language-javascript">KUTE.to(div,{opacity:1}).start()</code></pre>
<p>As you might have guessed, this method is useful for creating simple animations such as for scroll, hide/reveal elements, or generally when you don't know the current value of the property you are trying to animate.</p>
<p><kbd>.fromTo()</kbd> method is the best way to build animations for BEST performance and absolute control. The tests prove this method to be the fastest method but unlike the <code>.to()</code> method, it does not stack transform properties on chained tweens. Along with the performance advantage, you can set measurement units for both starting and end values, to avoid glitches. We've talked about this in the <a href="features.html">features page</a>. Here's a quick example:</p>
<pre><code class="language-javascript">KUTE.fromTo(div,{opacity:1},{opacity:0}).start()</code></pre>

View file

@ -21,18 +21,19 @@
}(this, function (KUTE) {
'use strict';
// filter unsupported browsers
if (!('boxShadow' in document.body.style)) {return;}
// add a reference to KUTE object
var g = typeof global !== 'undefined' ? global : window, K = KUTE, getComputedStyle = K.getCurrentStyle,
trueColor = K.truC, prepareStart = K.prepareStart, parseProperty = K.parseProperty, DOM = g.dom,
unit = g._unit, color = g._color,
var g = typeof global !== 'undefined' ? global : window, K = KUTE,
// add a reference to KUTE utilities
prepareStart = K.prepareStart, parseProperty = K.parseProperty,
property = K.property, getCurrentStyle = K.getCurrentStyle, trueColor = K.truC,
DOM = g.dom, unit = g._unit, color = g._color, // interpolation functions
// the preffixed boxShadow property, mostly for legacy browsers
// maybe the browser is supporting the property with its vendor preffix
// box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit;
_boxShadow = K.property('boxShadow'), // note we're using the KUTE.property() autopreffix utility
_boxShadow = property('boxShadow'), // note we're using the KUTE.property() autopreffix utility
colRegEx = /(\s?(?:#(?:[\da-f]{3}){1,2}|rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\))\s?)/gi, // a full RegEx for color strings
// utility function to process values accordingly
// numbers must be integers and color must be rgb object
processBoxShadowArray = function(shadow){
@ -60,11 +61,11 @@
// for the .to() method, you need to prepareStart the boxShadow property
// which means you need to read the current computed value
prepareStart['boxShadow'] = function(element,property,value){
var cssBoxShadow = getComputedStyle(element,_boxShadow);
var cssBoxShadow = getCurrentStyle(element,_boxShadow);
return /^none$|^initial$|^inherit$|^inset$/.test(cssBoxShadow) ? '0px 0px 0px 0px rgb(0,0,0)' : cssBoxShadow;
}
// the processProperty for boxShadow
// the parseProperty for boxShadow
// registers the K.dom['boxShadow'] function
// returns an array of 6 values with the following format
// [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset]
@ -73,33 +74,33 @@
// the DOM update function for boxShadow registers here
// we only enqueue it if the boxShadow property is used to tween
DOM['boxShadow'] = function(l,p,a,b,v) {
DOM['boxShadow'] = function(element,property,startValue,endValue,progress) {
// let's start with the numbers | set unit | also determine inset
var numbers = [], px = 'px', // the unit is always px
inset = a[5] !== 'none' || b[5] !== 'none' ? ' inset' : false;
inset = startValue[5] !== 'none' || endValue[5] !== 'none' ? ' inset' : false;
for (var i=0; i<4; i++){
numbers.push( unit( a[i], b[i], px, v ) );
numbers.push( unit( startValue[i], endValue[i], px, progress ) );
}
// now we handle the color
var colorValue = color(a[4],b[4],v);
var colorValue = color(startValue[4], endValue[4], progress);
// the final piece of the puzzle, the DOM update
l.style[_boxShadow] = inset ? colorValue + numbers.join(' ') + inset : colorValue + numbers.join(' ');
element.style[_boxShadow] = inset ? colorValue + numbers.join(' ') + inset : colorValue + numbers.join(' ');
};
}
// parseProperty for boxShadow, builds basic structure with ready to tween values
if (typeof value === 'string'){
var currentColor, inset = 'none';
var shadowColor, inset = 'none';
// make sure to always have the inset last if possible
inset = /inset/.test(value) ? 'inset' : inset;
value = /inset/.test(value) ? value.replace(/(\s+inset|inset+\s)/g,'') : value;
// also getComputedStyle often returns color first "rgb(0, 0, 0) 15px 15px 6px 0px inset"
currentColor = value.match(colRegEx);
value = value.replace(currentColor[0],'').split(' ').concat([currentColor[0].replace(/\s/g,'')],[inset]);
shadowColor = value.match(colRegEx);
value = value.replace(shadowColor[0],'').split(' ').concat([shadowColor[0].replace(/\s/g,'')],[inset]);
value = processBoxShadowArray(value);
} else if (value instanceof Array){

View file

@ -1,16 +1,59 @@
// testing grounds
"use strict";
var mobileType = '', check,
isMobile = {
Windows: function() {
check = /IEMobile/i.test(navigator.userAgent);
mobileType += check ? 'Windows Phones.' : '';
return check;
},
Android: function() {
check = /Android/i.test(navigator.userAgent)
mobileType += check ? 'Android Phones.' : '';
return check;
},
BlackBerry: function() {
check = /BlackBerry/i.test(navigator.userAgent);
mobileType += check ? 'BlackBerry.' : '';
return check;
},
iOS: function() {
check = /iPhone|iPad|iPod/i.test(navigator.userAgent);
mobileType += check ? 'Apple iPhone, iPad or iPod.' : '';
return check;
},
any: function() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
}
};
// protect older / low end devices
if (document.body.offsetWidth < 1200 || isMobile.any()) {
var explain = '';
explain += mobileType !== '' ? 'For safety reasons, this page does not work with ' + mobileType : '';
explain += document.body.offsetWidth < 1200 ? 'For safety reasons this page does not work on your machine because it might be very old. In other cases the browser window size is not enough for the animation to work properly, so if that\'s the case, maximize the window, refresh and proceed with the tests.' : '';
var warning = '<div style="padding: 20px;">';
warning +='<h1 class="text-danger">Warning!</h1>';
warning +='<p class="lead text-danger">This web page is only for high-end desktop computers.</p>';
warning +='<p class="text-danger">We do not take any responsibility and we are not liable for any damage caused through use of this website, be it indirect, special, incidental or consequential damages to your devices.</p>';
warning +='<p class="text-info">'+explain+'</p>';
warning +='</div>';
document.body.innerHTML = warning;
throw new Error('This page is only for high-end desktop computers. ' + explain);
}
// generate a random number within a given range
function random(min, max) {
return Math.random() * (max - min) + min;
}
// vendor prefix handle
var transformProperty = KUTE.property('transform');
// the variables
var container = document.getElementById('container'), tws = [];
var container = document.getElementById('container');
// vendor prefix handle
var transformProperty = KUTE.property('transform'), tws = [];
function complete(){
document.getElementById('info').style.display = 'block';
@ -38,16 +81,16 @@ function buildObjects(){
warning.className = 'text-warning padding lead';
container.innerHTML = '';
if (count && engine && property && repeat) {
if (engine === 'gsap') {
document.getElementById('info').style.display = 'none';
}
if (engine === 'gsap') {
document.getElementById('info').style.display = 'none';
}
createTest(count,property,engine,repeat);
// since our engines don't do sync, we make it our own here
if (engine==='tween'||engine==='kute') {
document.getElementById('info').style.display = 'none';
start();
}
// since our engines don't do sync, we make it our own here
if (engine==='tween'||engine==='kute') {
document.getElementById('info').style.display = 'none';
start();
}
} else {
if (!count && !property && !repeat && !engine){
@ -146,7 +189,7 @@ for (var i=0; i<l; i++) {
"use strict";
var link = this, b = link.parentNode.parentNode.parentNode.querySelector('.btn');
b.innerHTML = link.id.toUpperCase() + ' <span class="caret"></span>';
b.setAttribute('data-'+link.parentNode.parentNode.parentNode.id,link.id);
b.setAttribute('data-'+link.parentNode.parentNode.parentNode.id, link.id);
}
}
}

View file

@ -160,7 +160,7 @@ Tween.prototype.onUpdate = function(){
}
</code></pre>
<p>For some reasons these methods aren't included into the core/plugins by default, but let you decide what you need and how to customize the animation engine for your very secific need.</p>
<p>For some reasons these methods aren't included into the core/plugins by default, but let you decide what you need and how to customize the animation engine for your very specific need.</p>
<h3>Support For Additional CSS Properties</h3>
<p>KUTE.js core engine and plugins cover what I consider to be most essential for animation, but you may have a different opinion. In case you may want to know how to animate properties that are not currently supported, stick to this guide and you'll master it real quick, it's very easy.</p>
@ -168,48 +168,50 @@ Tween.prototype.onUpdate = function(){
<ul>
<li><code>KUTE.prepareStart['propertyName']</code> <kbd class="bg-red">required</kbd> a function to get the current value of the property required for the <code>.to()</code> method;</li>
<li><code>KUTE.parseProperty['propertyName']</code> <kbd class="bg-red">required</kbd> a function to process the user value / current value to have it ready to tween;</li>
<li><code>KUTE.crossCheck['propertyName']</code> <kbd class="bg-green">optional</kbd> a function to help you set proper values when for instance startValues unit is different than endValues unit; so far this is used for CSS3/SVG transforms and SVG Morph, but it can be extended for many properties such as box-model properties or border-radius properties;</li>
<li><code>window.dom['propertyName']</code> <kbd class="bg-red">required</kbd> a <strong>domUpdate</strong> function that will update the property value into the DOM;</li>
<li><strong>optional</strong> one or more functions that will work as an utility for your value processing.</li>
<li><code>KUTE.crossCheck['propertyName']</code> <kbd class="bg-green">optional</kbd> a function to help you set proper values when for instance startValues unit is different than endValues unit; so far this is used for CSS3/SVG transforms and SVG Morph, but it can be extended for many properties such as box-model properties or border-radius properties;</li>
<li>also <kbd class="bg-green">optional</kbd> additional functions that will help with value processing.</li>
</ul>
<p>So let's add support for <kbd class="bg-olive">boxShadow</kbd>! It should be a medium difficulty guide most developers can follow and the purpose of this guide is to showcase how easy it actually is to extend KUTE.js. So grab the above template and let's break it down to pieces:</p>
<pre><code class="language-javascript">// add a reference to global and KUTE object
var g = typeof global !== 'undefined' ? global : window, K = KUTE,
// add a reference to KUTE utilities
prepareStart = K.prepareStart, DOM = g.dom, parseProperty = K.parseProperty, trueColor = K.truC,
color = g._color, unit = g._unit, getComputedStyle = K.getCurrentStyle;
// filter unsupported browsers
if (!('boxShadow' in document.body.style)) {return;}
prepareStart = K.prepareStart, getCurrentStyle = K.getCurrentStyle,
property = K.property, parseProperty = K.parseProperty, trueColor = K.truC,
DOM = g.dom, color = g._color, unit = g._unit; // interpolation functions
// the preffixed boxShadow property, mostly for legacy browsers
// maybe the browser is supporting the property with its vendor preffix
// box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit;
var _boxShadow = K.property('boxShadow'); // note we're using the KUTE.property() autopreffix utility
var _boxShadow = property('boxShadow'); // note we're using the KUTE.property() autopreffix utility
var colRegEx = /(\s?(?:#(?:[\da-f]{3}){1,2}|rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\))\s?)/gi; // a full RegEx for color strings
// for browsers that don't support the property, use a filter
// if (!(_boxShadow in document.body.style)) {return;}
</code></pre>
<p>Now we have access to the KUTE object, prototypes and it's utility functions, let's write a <code>prepareStart</code> function that will read the current <code>boxShadow</code> value:</p>
<pre><code class="language-javascript">// for the .to() method, you need to prepareStart the boxShadow property
// which means you need to read the current computed value
// if the current computed value is not acceptable, use a default value
prepareStart['boxShadow'] = function(element,property,value){
var cssBoxShadow = getComputedStyle(element,'boxShadow'); // where K.getCurrentStyle() is an accurate getComputedStyle() core method
return /^none$|^initial$|^inherit$|^inset$/.test(cssBoxShadow) ? '0px 0px 0px 0px rgb(0,0,0)' : cssBoxShadow;
var cssBoxShadow = getCurrentStyle(element,'boxShadow'); // where getCurrentStyle() is an accurate method to read the current property value
return /^none$|^initial$|^inherit$|^inset$/.test(cssBoxShadow) ? '0px 0px 0px 0px rgb(0,0,0)' : cssBoxShadow; // if the current value is not valid, use a default one
}
// note that in some cases the window.getComputedStyle(element,null) can be more accurate
// we are using a hybrid function that's trying to get proper colors and other stuff that
// some legacy browsers lack in this matter
// note that in some cases the window.getComputedStyle(element,null) can be faster or more appropriate
// we are using a hybrid function that's trying to get proper colors and other stuff
// some legacy browsers lack in matters of accuracy so the KUTE.js core methods would suffice
// also to read the current value of an attribute, replace first line of the above function body with this
// var attrValue = element.getAttribute(property);
// and return the value or a default value, mostly rgb(0,0,0) for colors or 0 for other types
// and return the value or a default value, mostly rgb(0,0,0) for colors, 1 for opacity, or 0 for most other types
</code></pre>
<p>Now we need an utility function that makes sure the structure looks right for the DOM update function.</p>
<pre><code class="language-javascript">// utility function to process values accordingly
// numbers must be floats/integers and color must be rgb object
var processBoxShadowArray = function(shadow){
var newShadow, i;
var newShadow;
// properly process the shadow based on amount of values
if (shadow.length === 3) { // [h-shadow, v-shadow, color]
newShadow = [shadow[0], shadow[1], 0, 0, shadow[2], 'none'];
@ -222,7 +224,7 @@ var processBoxShadowArray = function(shadow){
}
// make sure the numbers are ready to tween
for (i=0;i&lt;4;i++){
for (var i=0; i&lt;4; i++){
newShadow[i] = parseFloat(newShadow[i]);
}
// make sure color is an rgb object
@ -233,7 +235,7 @@ var processBoxShadowArray = function(shadow){
<p>Next we'll need to write a <code>processProperty</code> function that will prepare the property value and build an Object or Array of values ready to tween. This function also registers the <code>window.dom['boxShadow']</code> function into the KUTE object, and this way we avoid filling the main object with unnecessary functions, just to keep performance tight.</p>
<pre><code class="language-javascript">// the processProperty for boxShadow
<pre><code class="language-javascript">// the parseProperty for boxShadow
// registers the window.dom['boxShadow'] function
// returns an array of 6 values in the following format
// [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset]
@ -241,34 +243,34 @@ parseProperty['boxShadow'] = function(property,value,element){
// the DOM update function for boxShadow registers here
// we only enqueue it if the boxShadow property is used to tween
if ( !('boxShadow' in DOM) ) {
DOM['boxShadow'] = function(l,p,a,b,v) { // element, propertyName, valuesStart.boxShadow, valuesEnd.boxShadow, progress
DOM['boxShadow'] = function(element,property,startValue,endValue,progress) { // element, propertyName, valuesStart.boxShadow, valuesEnd.boxShadow, progress
// let's start with the numbers | set unit | also determine inset
var numbers = [], px = 'px', // the unit is always px
inset = a[5] !== 'none' || b[5] !== 'none' ? ' inset' : false;
inset = startValue[5] !== 'none' || endValue[5] !== 'none' ? ' inset' : false;
for (var i=0; i&lt;4; i++){ // for boxShadow coordinates we do the math for an array of numbers
numbers.push( unit(a[i], b[i], px, v) );
numbers.push( unit(startValue[i], endValue[i], px, progress) );
}
// now we handle the color
var colorValue = color(a[4],b[4],v);
var colorValue = color(startValue[4],endValue[4],progress);
// last piece of the puzzle, the DOM update
l.style[_boxShadow] = inset ? colorValue + numbers.join(' ') + inset : colorValue + numbers.join(' ');
element.style[_boxShadow] = inset ? colorValue + numbers.join(' ') + inset : colorValue + numbers.join(' ');
};
}
// processProperty for boxShadow, builds basic structure with ready to tween values
if (typeof value === 'string'){
var color, inset = 'none';
var shadowColor, inset = 'none';
// make sure to always have the inset last if possible
inset = /inset/.test(value) ? 'inset' : inset;
value = /inset/.test(value) ? value.replace(/(\s+inset|inset+\s)/g,'') : value;
// also getComputedStyle often returns color first "rgb(0, 0, 0) 15px 15px 6px 0px inset"
color = value.match(colRegEx);
value = value.replace(color[0],'').split(' ').concat([color[0].replace(/\s/g,'')],[inset]);
shadowColor = value.match(colRegEx);
value = value.replace(shadowColor[0],'').split(' ').concat([shadowColor[0].replace(/\s/g,'')],[inset]);
// now we can use the above specific utitlity
value = processBoxShadowArray(value);

View file

@ -89,13 +89,12 @@
<li><a id="700" href="#">700</a></li>
<li><a id="800" href="#">800</a></li>
<li><a id="900" href="#">900</a></li>
<li><a id="1000" href="#">1000</a></li>
<li><a id="1500" href="#">1500</a></li>
<li><a id="2000" href="#">2000</a></li>
<li><a id="1000" href="#"><span style="color: red">1000</span></a></li>
<li><a id="1500" href="#"><span style="color: red">1500</span></a></li>
<li><a id="2000" href="#"><span style="color: red">2000</span></a></li>
</ul>
</span>
<hr>
<div style="width:100%;clear: both">
@ -106,7 +105,6 @@
<!--[if !IE ]><!-->
<p>These tests are only for modern browsers. In Google Chrome you can enable the FPS metter in developer tools, <a href="https://developer.chrome.com/devtools/docs/rendering-settings" target="_blank">here's how</a>.</p>
<p class="text-note">Please know that a local copy of this page will outperform the live site demo on Google Chrome, the reason is unknown.</p>
<p class="text-danger">Do not try this test on lower end or mobile devices.</p>
<!--<![endif]-->
</div>

View file

@ -164,7 +164,7 @@
<p>The synthax is slightly different to make sure we don't mess up with CSS properties that have the same name because the presentation attribute may be a unitless attribute while the CSS property might require a suffix (%,px,etc). For instance <code>KUTE.to('selector', {attr:{width:150}})</code> is clearly different from <code>KUTE.to('selector', {width:150})</code> which is the the CSS property with the same name.</p>
<p>Starting KUTE.js 1.6.0 the <a href="attr.html">Attributes Plugin</a> can also animate color attributes such as <kbd class="bg-olive">stroke</kbd>, <kbd class="bg-olive">fill</kbd> or <kbd class="bg-olive">stop-color</kbd>, and they are removed from the SVG Plugin, and the reason for that is the new bundle build that incorporates both plugins into an unified file.<p>
<p>The plugin handles attribute namespaces properly which means you can use both Javascript notation (like <kbd class="bg-olive">stopColor</kbd>) and HTML markup notation (like <kbd class="bg-olive">'stop-color'</kbd>), see the below example.</p>
<p>EG: <code>KUTE.to('selector', {attr:{stroke:'blue'}})</code> to animate the stroke of an SVG element or <code>KUTE.to('selector', {attr:{'stop-color':'rgb(135,16,122)'}})</code> to animate the stop color of some SVG gradient.</p>
<p>EG: <code>KUTE.to('selector', {attr:{stroke:'blue'}})</code> to animate the stroke of an SVG element or <code>KUTE.to('selector', {attr:{'stop-color':'red'}})</code> to animate the stop color of some SVG gradient.</p>
<h3>Typography Properties</h3>
<p>The <a href="css.html">CSS Plugin</a> also cover the text properties, and these can be combinated with each other when applied to text elements (paragraphs, headings) as animation fallback for <code>scale</code> on browsers that don't support <code>transform</code> at all. Yes, IE8 and other legacy browsers.</p>
@ -174,7 +174,7 @@
<li><kbd class="bg-olive">letterSpacing</kbd> allows you to animate the <code>letter-spacing</code> for a given element.</li>
<li><kbd class="bg-olive">wordSpacing</kbd> allows you to animate the <code>word-spacing</code> for a given element.</li>
</ul>
<p><strong>Remember</strong>: these properties are also <strong>layout modifiers</strong>.</p>
<p><strong>Remember</strong>: these properties are <strong>layout modifiers</strong>.</p>
<h3>Scroll Animation</h3>
<p>KUTE.js core engine currently supports only vertical <kbd class="bg-blue">scroll</kbd> for both the window and a given element that's scrollable (when <code>scrollHeight</code> is higher than <code>offsetHeight</code>). Both <code>scroll: 150</code> or <code>scrollTop: 150</code> notations will do. When animating scroll, KUTE.js will disable all scroll and swipe handlers to prevent animation bubbles as well as scroll bottlenecks.</p>

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | Attributes Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | Attributes Plugin | MIT-License
!function(t,e){if("function"==typeof define&&define.amd)define(["kute.js"],e);else if("object"==typeof module&&"function"==typeof require)module.exports=e(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("Attributes Plugin require KUTE.js.");e(t.KUTE)}}(this,function(t){"use strict";var e,r="undefined"!=typeof global?global:window,n=t,i=r.dom,u=n.prepareStart,o=n.parseProperty,a=n.truC,f=n.truD,s=(n.crossCheck,r._unit),l=r._number,c=r._color,p=function(t,e){return t.getAttribute(e)},d=["fill","stroke","stop-color"],b=function(t){return t.replace(/[A-Z]/g,"-$&").toLowerCase()};return u.attr=function(t,e,r){var n={};for(var i in r){var u=b(i).replace(/_+[a-z]+/,""),o=p(t,u);n[u]=d.indexOf(u)!==-1?o||"rgba(0,0,0,0)":o||(/opacity/i.test(i)?1:0)}return n},o.attr=function(t,r,n){"attr"in i||(i.attr=function(t,e,r,n,u){for(var o in n)i.attributes[o](t,o,r[o],n[o],u)},e=i.attributes={});var u={};for(var o in r){var v=b(o),y=p(n,v.replace(/_+[a-z]+/,""));if(d.indexOf(v)===-1)if(null!==y&&/(%|[a-z]+)$/.test(y)){var _=f(y).u||f(r[o]).u,g=/%/.test(_)?"_percent":"_"+_;v+g in e||(e[v+g]=function(t,e,r,n,i){var u=u||e.replace(g,"");t.setAttribute(u,s(r.v,n.v,n.u,i))}),u[v+g]=f(r[o])}else/(%|[a-z]+)$/.test(r[o])&&null!==y&&(null===y||/(%|[a-z]+)$/.test(y))||(v in e||(e[v]=function(t,e,r,n,i){t.setAttribute(e,l(r,n,i))}),u[v]=parseFloat(r[o]));else v in e||(e[v]=function(t,e,n,i,u){t.setAttribute(e,c(n,i,u,r.keepHex))}),u[v]=a(r[o])}return u},this});

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | CSS Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | CSS Plugin | MIT-License
!function(t,r){if("function"==typeof define&&define.amd)define(["kute.js"],r);else if("object"==typeof module&&"function"==typeof require)module.exports=r(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("CSS Plugin require KUTE.js.");r(t.KUTE)}}(this,function(t){"use strict";for(var r="undefined"!=typeof global?global:window,e=t,o=r.dom,n=e.parseProperty,i=e.prepareStart,u=e.property,d=e.getCurrentStyle,f=e.truD,a=e.truC,c=(r._number,r._unit),g=r._color,l=["borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],p=["borderRadius","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"],s=["right","bottom","minWidth","minHeight","maxWidth","maxHeight","padding","margin","paddingTop","paddingBottom","paddingLeft","paddingRight","marginTop","marginBottom","marginLeft","marginRight","borderWidth","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","outlineWidth"],h=["fontSize","lineHeight","letterSpacing","wordSpacing"],b=["clip"],m=["backgroundPosition"],v=s.concat(h),y=p.concat(s,h),x=l.concat(b,p,s,h,m),R=x.length,C=C||{},T=0;T<R;T++)l.indexOf(x[T])!==-1?C[x[T]]="rgba(0,0,0,0)":y.indexOf(x[T])!==-1?C[x[T]]=0:m.indexOf(x[T])!==-1?C[x[T]]=[50,50]:"clip"===x[T]&&(C[x[T]]=[0,0,0,0]);for(var T=0,W=l.length;T<W;T++)n[l[T]]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n,i){t.style[r]=g(e,o,n,i.keepHex)}),a(r)},i[l[T]]=function(t,r,e){return d(t,r)||C[r]};for(var T=0,W=v.length;T<W;T++)n[v[T]]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.v,o.v,o.u,n)}),f(r)},i[v[T]]=function(t,r,e){return d(t,r)||C[r]};for(var T=0,W=p.length;T<W;T++){var S=u(p[T]);n[S]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.v,o.v,o.u,n)}),f(r)},i[S]=function(t,r,e){return d(t,S)||C[r]}}return n.clip=function(t,r){if(t in o||(o[t]=function(t,r,e,o,n){var i=0,u=[];for(i;i<4;i++){var d=e[i].v,f=o[i].v,a=o[i].u||"px";u[i]=c(d,f,a,n)}t.style[r]="rect("+u+")"}),r instanceof Array)return[f(r[0]),f(r[1]),f(r[2]),f(r[3])];var e=r.replace(/rect|\(|\)/g,"");return e=/\,/g.test(e)?e.split(/\,/g):e.split(/\s/g),[f(e[0]),f(e[1]),f(e[2]),f(e[3])]},i.clip=function(t,r,e){var o=d(t,r),n=d(t,"width"),i=d(t,"height");return/rect/.test(o)?o:[0,n,i,0]},n.backgroundPosition=function(t,r){if(t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.x.v,o.x.v,"%",n)+" "+c(e.y.v,o.y.v,"%",n)}),r instanceof Array)return{x:f(r[0])||{v:50,u:"%"},y:f(r[1])||{v:50,u:"%"}};var e,n,i=r.replace(/top|left/g,0).replace(/right|bottom/g,100).replace(/center|middle/g,50);return i=/\,/g.test(i)?i.split(/\,/g):i.split(/\s/g),i=2===i.length?i:[i[0],50],e=f(i[0]),n=f(i[1]),{x:e,y:n}},i.backgroundPosition=function(t,r,e){return d(t,r)||C[r]},this});

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | jQuery Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | jQuery Plugin | MIT-License
!function(e,t){if("function"==typeof define&&define.amd)define(["./kute.js","jquery"],function(e,n){return t(n,e),e});else if("object"==typeof module&&"function"==typeof require){var n=require("./kute.js"),r=require("jquery");module.exports=t(r,n)}else{if("undefined"==typeof e.KUTE||"undefined"==typeof e.$&&"undefined"==typeof e.jQuery)throw new Error("jQuery Plugin for KUTE.js depend on KUTE.js and jQuery");var r=e.jQuery||e.$,n=e.KUTE;r.fn.KUTE=t(r,n)}}(this,function(e,t){"use strict";return e.fn.fromTo=function(e,n,r){var i=this.length>1?this:this[0],o=this.length>1?"allFromTo":"fromTo";return t[o](i,e,n,r)},e.fn.to=function(e,n){var r=this.length>1?this:this[0],i=this.length>1?"allTo":"to";return t[i](r,e,n)},this});

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | Text Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | Text Plugin | MIT-License
!function(t,e){if("function"==typeof define&&define.amd)define(["kute.js"],e);else if("object"==typeof module&&"function"==typeof require)module.exports=e(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("Text-Plugin require KUTE.js.");e(t.KUTE)}}(this,function(t){"use strict";var e="undefined"!=typeof global?global:window,n=t,r=e.dom,i=n.prepareStart,s=n.parseProperty,u=e._number,o=String("abcdefghijklmnopqrstuvwxyz").split(""),a=String("abcdefghijklmnopqrstuvwxyz".toUpperCase()).split(""),l=String("~!@#$%^&*()_+{}[];'<>,./?=-").split(""),f=String("0123456789").split(""),p=o.concat(a,f),h=(p.concat(l),Math.random),c=Math.floor,g=Math.min;return i.text=i.number=function(t,e,n){return t.innerHTML},s.text=function(t,e,n){return"text"in r||(r.text=function(t,e,n,r,i,s){var u=u||"alpha"===s.textChars?o:"upper"===s.textChars?a:"numeric"===s.textChars?f:"alphanumeric"===s.textChars?p:"symbols"===s.textChars?l:s.textChars?s.textChars.split(""):o,m=u.length,b=u[c(h()*m)],d="",x="",y=n.substring(0),C=r.substring(0);d=""!==n?y.substring(y.length,c(g(i*y.length,y.length))):"",x=C.substring(0,c(g(i*C.length,C.length))),t.innerHTML=i<1?x+b+d:r}),e},s.number=function(t,e,n){return"number"in r||(r.number=function(t,e,n,r,i){t.innerHTML=parseInt(u(n,r,i))}),parseInt(e)||0},this});

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | Attributes Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | Attributes Plugin | MIT-License
!function(t,e){if("function"==typeof define&&define.amd)define(["kute.js"],e);else if("object"==typeof module&&"function"==typeof require)module.exports=e(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("Attributes Plugin require KUTE.js.");e(t.KUTE)}}(this,function(t){"use strict";var e,r="undefined"!=typeof global?global:window,n=t,i=r.dom,u=n.prepareStart,o=n.parseProperty,a=n.truC,f=n.truD,s=(n.crossCheck,r._unit),l=r._number,c=r._color,p=function(t,e){return t.getAttribute(e)},d=["fill","stroke","stop-color"],b=function(t){return t.replace(/[A-Z]/g,"-$&").toLowerCase()};return u.attr=function(t,e,r){var n={};for(var i in r){var u=b(i).replace(/_+[a-z]+/,""),o=p(t,u);n[u]=d.indexOf(u)!==-1?o||"rgba(0,0,0,0)":o||(/opacity/i.test(i)?1:0)}return n},o.attr=function(t,r,n){"attr"in i||(i.attr=function(t,e,r,n,u){for(var o in n)i.attributes[o](t,o,r[o],n[o],u)},e=i.attributes={});var u={};for(var o in r){var v=b(o),y=p(n,v.replace(/_+[a-z]+/,""));if(d.indexOf(v)===-1)if(null!==y&&/(%|[a-z]+)$/.test(y)){var _=f(y).u||f(r[o]).u,g=/%/.test(_)?"_percent":"_"+_;v+g in e||(e[v+g]=function(t,e,r,n,i){var u=u||e.replace(g,"");t.setAttribute(u,s(r.v,n.v,n.u,i))}),u[v+g]=f(r[o])}else/(%|[a-z]+)$/.test(r[o])&&null!==y&&(null===y||/(%|[a-z]+)$/.test(y))||(v in e||(e[v]=function(t,e,r,n,i){t.setAttribute(e,l(r,n,i))}),u[v]=parseFloat(r[o]));else v in e||(e[v]=function(t,e,n,i,u){t.setAttribute(e,c(n,i,u,r.keepHex))}),u[v]=a(r[o])}return u},this});

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | CSS Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | CSS Plugin | MIT-License
!function(t,r){if("function"==typeof define&&define.amd)define(["kute.js"],r);else if("object"==typeof module&&"function"==typeof require)module.exports=r(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("CSS Plugin require KUTE.js.");r(t.KUTE)}}(this,function(t){"use strict";for(var r="undefined"!=typeof global?global:window,e=t,o=r.dom,n=e.parseProperty,i=e.prepareStart,u=e.property,d=e.getCurrentStyle,f=e.truD,a=e.truC,c=(r._number,r._unit),g=r._color,l=["borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],p=["borderRadius","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"],s=["right","bottom","minWidth","minHeight","maxWidth","maxHeight","padding","margin","paddingTop","paddingBottom","paddingLeft","paddingRight","marginTop","marginBottom","marginLeft","marginRight","borderWidth","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","outlineWidth"],h=["fontSize","lineHeight","letterSpacing","wordSpacing"],b=["clip"],m=["backgroundPosition"],v=s.concat(h),y=p.concat(s,h),x=l.concat(b,p,s,h,m),R=x.length,C=C||{},T=0;T<R;T++)l.indexOf(x[T])!==-1?C[x[T]]="rgba(0,0,0,0)":y.indexOf(x[T])!==-1?C[x[T]]=0:m.indexOf(x[T])!==-1?C[x[T]]=[50,50]:"clip"===x[T]&&(C[x[T]]=[0,0,0,0]);for(var T=0,W=l.length;T<W;T++)n[l[T]]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n,i){t.style[r]=g(e,o,n,i.keepHex)}),a(r)},i[l[T]]=function(t,r,e){return d(t,r)||C[r]};for(var T=0,W=v.length;T<W;T++)n[v[T]]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.v,o.v,o.u,n)}),f(r)},i[v[T]]=function(t,r,e){return d(t,r)||C[r]};for(var T=0,W=p.length;T<W;T++){var S=u(p[T]);n[S]=function(t,r){return t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.v,o.v,o.u,n)}),f(r)},i[S]=function(t,r,e){return d(t,S)||C[r]}}return n.clip=function(t,r){if(t in o||(o[t]=function(t,r,e,o,n){var i=0,u=[];for(i;i<4;i++){var d=e[i].v,f=o[i].v,a=o[i].u||"px";u[i]=c(d,f,a,n)}t.style[r]="rect("+u+")"}),r instanceof Array)return[f(r[0]),f(r[1]),f(r[2]),f(r[3])];var e=r.replace(/rect|\(|\)/g,"");return e=/\,/g.test(e)?e.split(/\,/g):e.split(/\s/g),[f(e[0]),f(e[1]),f(e[2]),f(e[3])]},i.clip=function(t,r,e){var o=d(t,r),n=d(t,"width"),i=d(t,"height");return/rect/.test(o)?o:[0,n,i,0]},n.backgroundPosition=function(t,r){if(t in o||(o[t]=function(t,r,e,o,n){t.style[r]=c(e.x.v,o.x.v,"%",n)+" "+c(e.y.v,o.y.v,"%",n)}),r instanceof Array)return{x:f(r[0])||{v:50,u:"%"},y:f(r[1])||{v:50,u:"%"}};var e,n,i=r.replace(/top|left/g,0).replace(/right|bottom/g,100).replace(/center|middle/g,50);return i=/\,/g.test(i)?i.split(/\,/g):i.split(/\s/g),i=2===i.length?i:[i[0],50],e=f(i[0]),n=f(i[1]),{x:e,y:n}},i.backgroundPosition=function(t,r,e){return d(t,r)||C[r]},this});

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | jQuery Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | jQuery Plugin | MIT-License
!function(e,t){if("function"==typeof define&&define.amd)define(["./kute.js","jquery"],function(e,n){return t(n,e),e});else if("object"==typeof module&&"function"==typeof require){var n=require("./kute.js"),r=require("jquery");module.exports=t(r,n)}else{if("undefined"==typeof e.KUTE||"undefined"==typeof e.$&&"undefined"==typeof e.jQuery)throw new Error("jQuery Plugin for KUTE.js depend on KUTE.js and jQuery");var r=e.jQuery||e.$,n=e.KUTE;r.fn.KUTE=t(r,n)}}(this,function(e,t){"use strict";return e.fn.fromTo=function(e,n,r){var i=this.length>1?this:this[0],o=this.length>1?"allFromTo":"fromTo";return t[o](i,e,n,r)},e.fn.to=function(e,n){var r=this.length>1?this:this[0],i=this.length>1?"allTo":"to";return t[i](r,e,n)},this});

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
// KUTE.js v1.5.98a | © dnp_theme | Text Plugin | MIT-License
// KUTE.js v1.5.99 | © dnp_theme | Text Plugin | MIT-License
!function(t,e){if("function"==typeof define&&define.amd)define(["kute.js"],e);else if("object"==typeof module&&"function"==typeof require)module.exports=e(require("kute.js"));else{if("undefined"==typeof t.KUTE)throw new Error("Text-Plugin require KUTE.js.");e(t.KUTE)}}(this,function(t){"use strict";var e="undefined"!=typeof global?global:window,n=t,r=e.dom,i=n.prepareStart,s=n.parseProperty,u=e._number,o=String("abcdefghijklmnopqrstuvwxyz").split(""),a=String("abcdefghijklmnopqrstuvwxyz".toUpperCase()).split(""),l=String("~!@#$%^&*()_+{}[];'<>,./?=-").split(""),f=String("0123456789").split(""),p=o.concat(a,f),h=(p.concat(l),Math.random),c=Math.floor,g=Math.min;return i.text=i.number=function(t,e,n){return t.innerHTML},s.text=function(t,e,n){return"text"in r||(r.text=function(t,e,n,r,i,s){var u=u||"alpha"===s.textChars?o:"upper"===s.textChars?a:"numeric"===s.textChars?f:"alphanumeric"===s.textChars?p:"symbols"===s.textChars?l:s.textChars?s.textChars.split(""):o,m=u.length,b=u[c(h()*m)],d="",x="",y=n.substring(0),C=r.substring(0);d=""!==n?y.substring(y.length,c(g(i*y.length,y.length))):"",x=C.substring(0,c(g(i*C.length,C.length))),t.innerHTML=i<1?x+b+d:r}),e},s.number=function(t,e,n){return"number"in r||(r.number=function(t,e,n,r,i){t.innerHTML=parseInt(u(n,r,i))}),parseInt(e)||0},this});

4
dist/kute.min.js vendored

File diff suppressed because one or more lines are too long

16
kute.js
View file

@ -82,7 +82,7 @@
b: parseInt(result[3], 16)
} : null;
},
getInlineStyle = function(el,p) { // getInlineStyle = get transform style for element from cssText for .to() method, the sp is for transform property
getInlineStyle = function(el,p) { // get transform style for element from cssText for .to() method, the sp is for transform property
if (!el) return; // if the scroll applies to `window` it returns as it has no styling
var css = el.style.cssText.replace(/\s/g,'').split(';'),//the cssText
trsf = {}; //the transform object
@ -100,16 +100,16 @@
}
return trsf;
},
getCurrentStyle = function (el,p) { // gCS = get style property for element from computedStyle for .to() method
getCurrentStyle = function (el,p) { // get computed style property for element for .to() method
var styleAttribute = el.style, computedStyle = g.getComputedStyle(el,null) || el.currentStyle, pp = property(p), //the computed style | prefixed property
s = styleAttribute[p] && !/auto|initial|none|unset/.test(styleAttribute[p]) ? styleAttribute[p] : computedStyle[pp]; // s the property style value
styleValue = styleAttribute[p] && !/auto|initial|none|unset/.test(styleAttribute[p]) ? styleAttribute[p] : computedStyle[pp]; // s the property style value
if ( p !== 'transform' && (pp in computedStyle || pp in styleAttribute) ) {
if ( s ){
if ( styleValue ){
if (pp==='filter') { // handle IE8 opacity
var si1 = parseInt(s.split('=')[1].replace(')','')), si = parseFloat(si1/100);
return si;
var filterValue = parseInt(styleValue.split('=')[1].replace(')',''));
return parseFloat(filterValue/100);
} else {
return s;
return styleValue;
}
} else {
return _defaults[p];
@ -609,7 +609,7 @@
},
// single Tween object construct
Tween = function (_el, _vS, _vE, _o) {
Tween = g._tween = function (_el, _vS, _vE, _o) {
this._el = 'scroll' in _vE && (_el === undefined || _el === null) ? scrollContainer : _el; // element animation is applied to
this.playing = false;

View file

@ -1,6 +1,6 @@
{
"name": "kute.js",
"version": "1.5.98a",
"version": "1.5.99",
"description": "Complete Native Javascript animation engine.",
"main": "kute.js",
"scripts": {