Skip to content

Commit

Permalink
Merge branch 'master' into greenkeeper-watchify-3.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl committed Nov 16, 2015
2 parents 996f891 + aa65caa commit e48b3e1
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 42 deletions.
20 changes: 0 additions & 20 deletions documentation/api.md
Expand Up @@ -145,26 +145,6 @@ wheel.play();

Returns **JogWheel** JogWheel instance

# getDefinedStyles

Gets map of defined styles from CSS2Properties object

**Parameters**

- `properties` **CSS2Properties** CSS2Properties object to return defined styles from

Returns **object** plain object containing defined styles as key value pairs

# toArray

Cast array-like objects and collections to Array

**Parameters**

- `arrayLike` **Object** array-like to cast to Array

Returns **Array** Array cast from arrayLike



---
Expand Down
27 changes: 27 additions & 0 deletions source/library/get-animation-properties.js
@@ -0,0 +1,27 @@
import {prefix} from './get-vendor-prefix';

const propertyNames = [
'name',
'duration',
'iterationCount',
'timingFunction',
'fillMode',
'playState'
];

/**
* Returns applicable animation properties for a given node
* @param {Node} node Node to read animation properties from
* @param {Window} window Global context to use
* @return {Object} Applicable animation properties for node in window
* @private
*/
export default function getAnimationProperties(node, window = global.window, document = global.document) {
const styles = window.getComputedStyle(node);

return propertyNames.reduce((properties, propertyName) => {
const cssName = `animation${propertyName[0].toUpperCase()}${propertyName.slice(1)}`;
properties[propertyName] = styles[prefix(cssName, window, document)];
return properties;
}, {});
}
2 changes: 2 additions & 0 deletions source/library/get-keyframes.js
Expand Up @@ -24,6 +24,7 @@ const empty = [];
* Cast array-like objects and collections to Array
* @param {Object} arrayLike array-like to cast to Array
* @return {Array} Array cast from arrayLike
* @private
*/
function toArray(arrayLike) {
return empty.slice.call(arrayLike); // eslint-disable-line prefer-reflect
Expand Down Expand Up @@ -95,6 +96,7 @@ export function parseKeyframeKey(keyText) {
* Gets map of defined styles from CSS2Properties object
* @param {CSS2Properties} properties CSS2Properties object to return defined styles from
* @return {object} plain object containing defined styles as key value pairs
* @private
*/
export function getDefinedStyles(properties) {
const styles = {};
Expand Down
46 changes: 27 additions & 19 deletions source/library/get-player.js
@@ -1,5 +1,6 @@
import {prefix} from './get-vendor-prefix';
import getKeyframes from './get-keyframes';
import {prefix as getPrefixed} from './get-vendor-prefix';
import getAnimationProperties from './get-animation-properties';

/**
* Converts CSS animation duration string to integer holding duration in milliseconds
Expand All @@ -14,6 +15,16 @@ function getAnimationDuration(CSSAnimationDuration = '0s') {
return parseFloat(duration, 10) * factor;
}

/**
* Converts CSS animation iteration count string to integer
* @param CSSIterationCount {string} [CSSIterationCount='1'] CSS animation iteration count
* @return {integer}
* @private
*/
function getAnimationIterations(CSSIterationCount = '1') {
return parseInt(CSSIterationCount, 10);
}

/**
* Gets a web animation player based on the currently assigned CSS animation
* @param element {HTMLElement} DOM element to scan for an applied CSS animation
Expand All @@ -23,41 +34,38 @@ function getAnimationDuration(CSSAnimationDuration = '0s') {
* @private
*/
export default function getPlayer(element, window = global.window, document = global.document) {
function prefix(propertyName) {
return getPrefixed(propertyName, window, document);
}

// TODO: Make this a function, test it
// Read all animation related styles from element, respect prefixes
const {
[prefix('animationName')]: animationName,
[prefix('animationDuration')]: CSSDuration,
[prefix('animationIterations')]: iterations,
[prefix('animationEasing')]: easing,
[prefix('animationFillMode')]: fill,
[prefix('animationPlayState')]: playState
} = window.getComputedStyle(element);
name,
duration,
iterationCount,
timingFunction,
fillMode,
playState
} = getAnimationProperties(element, window, document);

// Generate keyframes based on the assigned animationName
const keyframes = getKeyframes(animationName, window, document);
const keyframes = getKeyframes(name, window, document);

// TODO: Should bail/stub? here if no keyframes are found
// Construct options for the webanimation player instance
const options = {
duration: getAnimationDuration(CSSDuration),
iterations, easing, fill
duration: getAnimationDuration(duration),
iterations: getAnimationIterations(iterationCount),
fill: fillMode,
easing: timingFunction
};

// Sort by offset and remove duplicates
// TODO: Test get-keyframes for sorting and duplication
// Sort by offset and remove duplicates
keyframes.sort((a, b) => a.offset - b.offset);

// Construct webanimation player instance with keyframes and options
const player = element.animate(keyframes, options);
element.style[prefix('animationName')] = 'jogwheel-none';

// Detach the former animation to prevent problems with polyfill
player.__jogwheelName = animationName;
element.style[prefix('animationName', window, document)] = `__jogwheelName-${name}`;
player.__jogwheelName = name;

// Pause or play the webanimation player instance based on CSS animationPlayState
if (playState === 'paused') {
Expand Down
8 changes: 8 additions & 0 deletions source/test/unit/fixtures/filled-animation.js
@@ -0,0 +1,8 @@
export default {
animationName: 'filled-animation',
animationPlayState: 'running',
animationTimingFunction: 'linear',
animationDuration: '1s',
animationFillMode: 'both',
animationIterationCount: '10'
};
2 changes: 1 addition & 1 deletion source/test/unit/fixtures/paused-animation.js
@@ -1,6 +1,6 @@
export default {
animationName: 'default-animation',
animationPlayState: 'paused',
animationEasing: 'linear',
animationTimingFunction: 'linear',
animationDuration: '300ms'
};
2 changes: 1 addition & 1 deletion source/test/unit/fixtures/running-animation.js
@@ -1,6 +1,6 @@
export default {
animationName: 'default-animation',
animationPlayState: 'running',
animationEasing: 'linear',
animationTimingFunction: 'linear',
animationDuration: '.3s'
};
2 changes: 1 addition & 1 deletion source/test/unit/fixtures/slow-animation.js
@@ -1,6 +1,6 @@
export default {
animationName: 'default-animation',
animationPlayState: 'running',
animationEasing: 'linear',
animationTimingFunction: 'linear',
animationDuration: '1s'
};
77 changes: 77 additions & 0 deletions source/test/unit/get-animation-properties.js
@@ -0,0 +1,77 @@
import tape from 'tape';
import getAnimationProperties from '../../library/get-animation-properties.js';

import elementStub from './stubs/element.js';
import windowStub from './stubs/window.js';
import documentStub from './stubs/document.js';

import pausedAnimation from './fixtures/paused-animation';
import filledAnimation from './fixtures/filled-animation';

tape('get-animation-properties', t => {
t.throws(() => {
getAnimationProperties();
}, 'should throw when called without arguments');

t.doesNotThrow(() => {
getAnimationProperties(elementStub, windowStub, documentStub);
}, 'should not throw when called with arguments');

const pausedElement = {
...elementStub,
style: {
...elementStub.style,
...pausedAnimation
}
};

const pausedProperties = getAnimationProperties(pausedElement, windowStub, documentStub);

t.deepEqual(
Object.keys(pausedProperties),
[
'name',
'duration',
'iterationCount',
'timingFunction',
'fillMode',
'playState'
],
'should return an object with the expected property values');

t.deepEqual(
pausedProperties,
{
name: 'default-animation',
duration: '300ms',
iterationCount: undefined,
timingFunction: 'linear',
fillMode: undefined,
playState: 'paused'
},
'should return an object with the expected property values');

const filledElement = {
...elementStub,
style: {
...elementStub.style,
...filledAnimation
}
};

const filledProperties = getAnimationProperties(filledElement, windowStub, documentStub);

t.deepEqual(
filledProperties,
{
name: 'filled-animation',
duration: '1s',
iterationCount: '10',
timingFunction: 'linear',
fillMode: 'both',
playState: 'running'
},
'should return an object with the expected property values');

t.end();
});
1 change: 1 addition & 0 deletions source/test/unit/index.js
@@ -1,5 +1,6 @@
import 'babel-polyfill';

import './get-animation-properties';
import './get-defined-styles';
import './get-keyframe-declarations';
import './get-keyframes';
Expand Down

0 comments on commit e48b3e1

Please sign in to comment.