Skip to content

Commit 232186b

Browse files
authored
Merge pull request #156 from ewilligers/master
Publish version 2.3.0
2 parents b0ca1f7 + c037b10 commit 232186b

20 files changed

+2623
-953
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ is the default target for pull requests.
2020
1. Commit changes to your fork.
2121
1. Create a pull request from your fork of web-animations-js to
2222
[web-animations/web-animations-js/dev](https://github.com/web-animations/web-animations-js/tree/dev).
23+
1. Ensure that you've signed the [Google Contributor License Agreement](https://cla.developers.google.com/clas).
2324

2425

2526
## Debugging tests
@@ -83,7 +84,7 @@ Example: `http://localhost:9876/base/test/web-platform-tests/web-animations/anim
8384
npm install
8485
grunt
8586
# Optional "grunt test" to make sure everything still passes.
86-
git add -f *.min.js*
87+
git add -f *.min.js{,.map}
8788
git rm .gitignore
8889
git commit -m 'Add build artifacts from '`cat .git/refs/heads/dev`
8990
git push HEAD:refs/heads/master

Gruntfile.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ module.exports = function(grunt) {
206206
}
207207

208208
function filterTests(testFiles) {
209+
console.assert(testFiles.length > 0);
209210
if (!testFilter) {
210211
return testFiles;
211212
}
@@ -226,18 +227,20 @@ module.exports = function(grunt) {
226227
karmaConfig.files = ['test/karma-mocha-setup.js'].concat(config.src, testFiles);
227228
});
228229
}
229-
function runWebPlatformTests() {
230+
function runWebPlatformTests(withNativeFallback) {
230231
var testFiles = filterTests(grunt.file.expand(config.webPlatformTests));
231232
if (testFiles.length == 0) {
232233
return Promise.resolve(true);
233234
}
234235

235-
console.info('Running web-platform-tests/web-animations tests...');
236+
var withOrWithout = withNativeFallback ? 'with' : 'without';
237+
console.info('Running web-platform-tests/web-animations tests for target ' + task.target + ' ' + withOrWithout + ' native fallback...');
236238
return runKarma(function(karmaConfig) {
237239
configCallback(karmaConfig);
238240
karmaConfig.client.testharnessTests = require('./test/web-platform-tests-expectations.js');
239241
karmaConfig.client.testharnessTests.testURLList = testFiles;
240-
karmaConfig.proxies['/base/polyfill.js'] = '/base/' + task.target + '.min.js';
242+
karmaConfig.client.testharnessTests.target = task.target;
243+
karmaConfig.client.testharnessTests.withNativeFallback = withNativeFallback;
241244
karmaConfig.files.push('test/karma-testharness-adapter.js');
242245
var servedFiles = [
243246
'test/web-platform-tests/resources/**',
@@ -256,10 +259,15 @@ module.exports = function(grunt) {
256259
}
257260

258261
var polyfillTestsPassed = false;
262+
var webPlatformTestsWithFallbackPassed = false;
263+
var webPlatformTestsWithoutFallbackPassed = false;
259264
runPolyfillTests().then(success => {
260265
polyfillTestsPassed = success;
261-
}).then(runWebPlatformTests).then(webPlatformTestsPassed => {
262-
done(polyfillTestsPassed && webPlatformTestsPassed);
266+
}).then(() => runWebPlatformTests(true)).then(success => {
267+
webPlatformTestsWithFallbackPassed = success;
268+
}).then(() => runWebPlatformTests(false)).then(success => {
269+
webPlatformTestsWithoutFallbackPassed = success;
270+
done(polyfillTestsPassed && webPlatformTestsWithFallbackPassed && webPlatformTestsWithoutFallbackPassed);
263271
}).catch(function(error) {
264272
console.error(error);
265273
done(false);

History.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### 2.3.0 - *July 20 2017*
2+
3+
* [Support IE/Edge SVG transforms.](https://github.com/web-animations/web-animations-js/pull/148)
4+
5+
* [Parse and evaluate calc expressions without eval.](https://github.com/web-animations/web-animations-js/pull/151)
6+
17
### 2.2.5 - *April 17 2017*
28

39
* Removed erroneously added *.gz files from release.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "git",
66
"url": "https://github.com/web-animations/web-animations-js.git"
77
},
8-
"version": "2.2.5",
8+
"version": "2.3.0",
99
"keywords": [
1010
"animations",
1111
"polyfill"

src/apply-preserving-inline-style.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@
1414

1515
(function(scope, testing) {
1616

17+
var SVG_TRANSFORM_PROP = '_webAnimationsUpdateSvgTransformAttr';
18+
19+
/**
20+
* IE/Edge do not support `transform` styles for SVG elements. Instead,
21+
* `transform` attribute can be animated with some restrictions.
22+
* See https://connect.microsoft.com/IE/feedback/details/811744/ie11-bug-with-implementation-of-css-transforms-in-svg,
23+
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/1173754/,
24+
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101242/, etc.
25+
* The same problem is exhibited by pre-Chrome Android browsers (ICS).
26+
* Unfortunately, there's no easy way to feature-detect it.
27+
*/
28+
function updateSvgTransformAttr(window, element) {
29+
if (!element.namespaceURI || element.namespaceURI.indexOf('/svg') == -1) {
30+
return false;
31+
}
32+
if (!(SVG_TRANSFORM_PROP in window)) {
33+
window[SVG_TRANSFORM_PROP] =
34+
/Trident|MSIE|IEMobile|Edge|Android 4/i.test(window.navigator.userAgent);
35+
}
36+
return window[SVG_TRANSFORM_PROP];
37+
}
38+
1739
var styleAttributes = {
1840
cssText: 1,
1941
length: 1,
@@ -44,13 +66,16 @@
4466
WEB_ANIMATIONS_TESTING && console.assert(!(element.style instanceof AnimatedCSSStyleDeclaration),
4567
'Element must not already have an animated style attached.');
4668

69+
this._element = element;
4770
// Stores the inline style of the element on its behalf while the
4871
// polyfill uses the element's inline style to simulate web animations.
4972
// This is needed to fake regular inline style CSSOM access on the element.
5073
this._surrogateStyle = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style;
5174
this._style = element.style;
5275
this._length = 0;
5376
this._isAnimatedProperty = {};
77+
this._updateSvgTransformAttr = updateSvgTransformAttr(window, element);
78+
this._savedTransformAttr = null;
5479

5580
// Copy the inline style contents over to the surrogate.
5681
for (var i = 0; i < this._style.length; i++) {
@@ -110,9 +135,30 @@
110135
_set: function(property, value) {
111136
this._style[property] = value;
112137
this._isAnimatedProperty[property] = true;
138+
if (this._updateSvgTransformAttr &&
139+
scope.unprefixedPropertyName(property) == 'transform') {
140+
// On IE/Edge, also set SVG element's `transform` attribute to 2d
141+
// matrix of the transform. The `transform` style does not work, but
142+
// `transform` attribute can be used instead.
143+
// Notice, if the platform indeed supports SVG/CSS transforms the CSS
144+
// declaration is supposed to override the attribute.
145+
if (this._savedTransformAttr == null) {
146+
this._savedTransformAttr = this._element.getAttribute('transform');
147+
}
148+
this._element.setAttribute('transform', scope.transformToSvgMatrix(value));
149+
}
113150
},
114151
_clear: function(property) {
115152
this._style[property] = this._surrogateStyle[property];
153+
if (this._updateSvgTransformAttr &&
154+
scope.unprefixedPropertyName(property) == 'transform') {
155+
if (this._savedTransformAttr) {
156+
this._element.setAttribute('transform', this._savedTransformAttr);
157+
} else {
158+
this._element.removeAttribute('transform');
159+
}
160+
this._savedTransformAttr = null;
161+
}
116162
delete this._isAnimatedProperty[property];
117163
},
118164
};
@@ -185,7 +231,9 @@
185231
}
186232
};
187233

188-
if (WEB_ANIMATIONS_TESTING)
234+
if (WEB_ANIMATIONS_TESTING) {
189235
testing.ensureStyleIsPatched = ensureStyleIsPatched;
236+
testing.updateSvgTransformAttr = updateSvgTransformAttr;
237+
}
190238

191239
})(webAnimations1, webAnimationsTesting);

src/dimension-handler.js

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,78 @@
1414

1515
(function(scope, testing) {
1616

17+
// Evaluates a calc expression.
18+
// https://drafts.csswg.org/css-values-3/#calc-notation
19+
function calculate(expression) {
20+
// In calc expressions, white space is required on both sides of the
21+
// + and - operators. https://drafts.csswg.org/css-values-3/#calc-notation
22+
// Thus any + or - immediately adjacent to . or 0..9 is part of the number,
23+
// e.g. -1.23e+45
24+
// This regular expression matches ( ) * / + - and numbers.
25+
var tokenRegularExpression = /([\+\-\w\.]+|[\(\)\*\/])/g;
26+
var currentToken;
27+
function consume() {
28+
var matchResult = tokenRegularExpression.exec(expression);
29+
if (matchResult)
30+
currentToken = matchResult[0];
31+
else
32+
currentToken = undefined;
33+
}
34+
consume(); // Read the initial token.
35+
36+
function calcNumber() {
37+
// https://drafts.csswg.org/css-values-3/#number-value
38+
var result = Number(currentToken);
39+
consume();
40+
return result;
41+
}
42+
43+
function calcValue() {
44+
// <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
45+
if (currentToken !== '(')
46+
return calcNumber();
47+
consume();
48+
var result = calcSum();
49+
if (currentToken !== ')')
50+
return NaN;
51+
consume();
52+
return result;
53+
}
54+
55+
function calcProduct() {
56+
// <calc-product> = <calc-value> [ '*' <calc-value> | '/' <calc-number-value> ]*
57+
var left = calcValue();
58+
while (currentToken === '*' || currentToken === '/') {
59+
var operator = currentToken;
60+
consume();
61+
var right = calcValue();
62+
if (operator === '*')
63+
left *= right;
64+
else
65+
left /= right;
66+
}
67+
return left;
68+
}
69+
70+
function calcSum() {
71+
// <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
72+
var left = calcProduct();
73+
while (currentToken === '+' || currentToken === '-') {
74+
var operator = currentToken;
75+
consume();
76+
var right = calcProduct();
77+
if (operator === '+')
78+
left += right;
79+
else
80+
left -= right;
81+
}
82+
return left;
83+
}
84+
85+
// <calc()> = calc( <calc-sum> )
86+
return calcSum();
87+
}
88+
1789
function parseDimension(unitRegExp, string) {
1890
string = string.trim().toLowerCase();
1991

@@ -36,7 +108,7 @@
36108
var taggedUnitRegExp = 'U(' + unitRegExp.source + ')';
37109

38110
// Validating input is simply applying as many reductions as we can.
39-
var typeCheck = string.replace(/[-+]?(\d*\.)?\d+/g, 'N')
111+
var typeCheck = string.replace(/[-+]?(\d*\.)?\d+([Ee][-+]?\d+)?/g, 'N')
40112
.replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D')
41113
.replace(/\s[+-]\s/g, 'O')
42114
.replace(/\s/g, '');
@@ -54,7 +126,7 @@
54126
return;
55127

56128
for (var unit in matchedUnits) {
57-
var result = eval(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0'));
129+
var result = calculate(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0'));
58130
if (!isFinite(result))
59131
return;
60132
matchedUnits[unit] = result;

src/matrix-decomposition.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,5 +435,6 @@
435435

436436
scope.dot = dot;
437437
scope.makeMatrixDecomposition = makeMatrixDecomposition;
438+
scope.transformListToMatrix = convertToMatrix;
438439

439440
})(webAnimations1, webAnimationsTesting);

src/property-names.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
(function(scope, testing) {
1616

17-
var aliased = {};
17+
var prefixed = {};
18+
var unprefixed = {};
1819

1920
function alias(name, aliases) {
2021
aliases.concat([name]).forEach(function(candidate) {
2122
if (candidate in document.documentElement.style) {
22-
aliased[name] = candidate;
23+
prefixed[name] = candidate;
2324
}
25+
unprefixed[candidate] = name;
2426
});
2527
}
2628
alias('transform', ['webkitTransform', 'msTransform']);
@@ -29,7 +31,10 @@
2931
alias('perspectiveOrigin', ['webkitPerspectiveOrigin']);
3032

3133
scope.propertyName = function(property) {
32-
return aliased[property] || property;
34+
return prefixed[property] || property;
35+
};
36+
scope.unprefixedPropertyName = function(property) {
37+
return unprefixed[property] || property;
3338
};
3439

3540
})(webAnimations1, webAnimationsTesting);

src/transform-handler.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,19 @@
256256

257257
scope.addPropertiesHandler(parseTransform, mergeTransforms, ['transform']);
258258

259+
scope.transformToSvgMatrix = function(string) {
260+
// matrix(<a> <b> <c> <d> <e> <f>)
261+
var mat = scope.transformListToMatrix(parseTransform(string));
262+
return 'matrix(' +
263+
numberToLongString(mat[0]) + ' ' + // <a>
264+
numberToLongString(mat[1]) + ' ' + // <b>
265+
numberToLongString(mat[4]) + ' ' + // <c>
266+
numberToLongString(mat[5]) + ' ' + // <d>
267+
numberToLongString(mat[12]) + ' ' + // <e>
268+
numberToLongString(mat[13]) + // <f>
269+
')';
270+
};
271+
259272
if (WEB_ANIMATIONS_TESTING)
260273
testing.parseTransform = parseTransform;
261274

0 commit comments

Comments
 (0)