Skip to content
This repository was archived by the owner on Mar 20, 2024. It is now read-only.

Commit 6eb5bfd

Browse files
committed
Refine implementation and tests
1 parent 267316f commit 6eb5bfd

File tree

4 files changed

+145
-13
lines changed

4 files changed

+145
-13
lines changed

src/apply-preserving-inline-style.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@
2020
* See https://connect.microsoft.com/IE/feedback/details/811744/ie11-bug-with-implementation-of-css-transforms-in-svg,
2121
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/1173754/,
2222
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101242/, etc.
23+
* Unfortunately, there's no easy way to feature-detect it.
2324
*/
24-
var applySvgTransforms =
25-
/Trident|MSIE|IEMobile|Edge/i.test(window.navigator.userAgent);
25+
function updateSvgTransformAttr(window) {
26+
if (window._webAnimationsUpdateSvgTransformAttr == null) {
27+
window._webAnimationsUpdateSvgTransformAttr =
28+
/Trident|MSIE|IEMobile|Edge/i.test(window.navigator.userAgent);
29+
}
30+
return window._webAnimationsUpdateSvgTransformAttr;
31+
}
2632

2733
var styleAttributes = {
2834
cssText: 1,
@@ -62,8 +68,10 @@
6268
this._style = element.style;
6369
this._length = 0;
6470
this._isAnimatedProperty = {};
65-
this._isSvg = element.namespaceURI &&
66-
element.namespaceURI.indexOf('/svg') != -1;
71+
this._updateSvgTransformAttr =
72+
element.namespaceURI &&
73+
element.namespaceURI.indexOf('/svg') != -1 &&
74+
updateSvgTransformAttr(window);
6775
this._savedTransformAttr = null;
6876

6977
// Copy the inline style contents over to the surrogate.
@@ -124,24 +132,29 @@
124132
_set: function(property, value) {
125133
this._style[property] = value;
126134
this._isAnimatedProperty[property] = true;
127-
if (this._isSvg && property == 'transform' && applySvgTransforms) {
135+
if (this._updateSvgTransformAttr &&
136+
scope.canonicalPropertyName(property) == 'transform') {
128137
// On IE/Edge, also set SVG element's `transform` attribute to 2d
129138
// matrix of the transform. The `transform` style does not work, but
130139
// `transform` attribute can be used instead.
140+
// Notice, if the platform indeed supports SVG/CSS transforms the CSS
141+
// declaration is supposed to override the attribute.
131142
if (this._savedTransformAttr == null) {
132143
this._savedTransformAttr = this._element.getAttribute('transform');
133144
}
134-
this._element.setAttribute('transform', scope.transformToMatrix2d(value));
145+
this._element.setAttribute('transform', scope.transformToSvgMatrix(value));
135146
}
136147
},
137148
_clear: function(property) {
138149
this._style[property] = this._surrogateStyle[property];
139-
if (this._isSvg && property == 'transform' && applySvgTransforms) {
150+
if (this._updateSvgTransformAttr &&
151+
scope.canonicalPropertyName(property) == 'transform') {
140152
if (this._savedTransformAttr) {
141153
this._element.setAttribute('transform', this._savedTransformAttr);
142154
} else {
143155
this._element.removeAttribute('transform');
144156
}
157+
this._savedTransformAttr = null;
145158
}
146159
delete this._isAnimatedProperty[property];
147160
},
@@ -215,7 +228,9 @@
215228
}
216229
};
217230

218-
if (WEB_ANIMATIONS_TESTING)
231+
if (WEB_ANIMATIONS_TESTING) {
219232
testing.ensureStyleIsPatched = ensureStyleIsPatched;
233+
testing.updateSvgTransformAttr = updateSvgTransformAttr;
234+
}
220235

221236
})(webAnimations1, webAnimationsTesting);

src/property-names.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
(function(scope, testing) {
1616

1717
var aliased = {};
18+
var canonical = {};
1819

1920
function alias(name, aliases) {
2021
aliases.concat([name]).forEach(function(candidate) {
2122
if (candidate in document.documentElement.style) {
2223
aliased[name] = candidate;
2324
}
25+
canonical[candidate] = name;
2426
});
2527
}
2628
alias('transform', ['webkitTransform', 'msTransform']);
@@ -31,5 +33,8 @@
3133
scope.propertyName = function(property) {
3234
return aliased[property] || property;
3335
};
36+
scope.canonicalPropertyName = function(property) {
37+
return canonical[property] || property;
38+
};
3439

3540
})(webAnimations1, webAnimationsTesting);

src/transform-handler.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,14 @@
256256

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

259-
scope.transformToMatrix2d = function(string) {
259+
scope.transformToSvgMatrix = function(string) {
260260
// matrix(<a> <b> <c> <d> <e> <f>)
261261
var mat = scope.transformListToMatrix(parseTransform(string));
262262
return 'matrix(' +
263-
numberToLongString(mat[0]) + ' ' + // <a>
264-
numberToLongString(mat[1]) + ' ' + // <b>
265-
numberToLongString(mat[4]) + ' ' + // <c>
266-
numberToLongString(mat[5]) + ' ' + // <d>
263+
numberToLongString(mat[0]) + ' ' + // <a>
264+
numberToLongString(mat[1]) + ' ' + // <b>
265+
numberToLongString(mat[4]) + ' ' + // <c>
266+
numberToLongString(mat[5]) + ' ' + // <d>
267267
numberToLongString(mat[12]) + ' ' + // <e>
268268
numberToLongString(mat[13]) + // <f>
269269
')';

test/js/apply-preserving-inline-style.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ suite('apply-preserving-inline-style', function() {
44
ensureStyleIsPatched(this.element);
55
this.style = this.element.style;
66
document.documentElement.appendChild(this.element);
7+
this.svgContainer = document.createElementNS(
8+
'http://www.w3.org/2000/svg', 'svg');
9+
document.documentElement.appendChild(this.svgContainer);
10+
window._webAnimationsUpdateSvgTransformAttr = null;
711
});
812
teardown(function() {
913
document.documentElement.removeChild(this.element);
14+
document.documentElement.removeChild(this.svgContainer);
15+
window._webAnimationsUpdateSvgTransformAttr = null;
1016
});
1117

1218
test('Style is patched', function() {
@@ -69,4 +75,110 @@ suite('apply-preserving-inline-style', function() {
6975
this.style.cssText = 'top: 0px';
7076
assert.equal(this.style.length, 1);
7177
});
78+
test('Detect SVG transform compatibility', function() {
79+
var win = {navigator: {userAgent: ''}};
80+
function agent(str) {
81+
win._webAnimationsUpdateSvgTransformAttr = null;
82+
win.navigator.userAgent = str;
83+
}
84+
// Unknown data: assume that transforms supported.
85+
assert.equal(updateSvgTransformAttr(win), false);
86+
// Chrome: transforms supported.
87+
agent('Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E)' +
88+
' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20' +
89+
' Mobile Safari/537.36');
90+
assert.equal(updateSvgTransformAttr(win), false);
91+
// Safary: transforms supported.
92+
agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) ' +
93+
'AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 ' +
94+
'Safari/7046A194A');
95+
assert.equal(updateSvgTransformAttr(win), false);
96+
// Firefox: transforms supported.
97+
agent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) ' +
98+
'Gecko/20100101 Firefox/40.1');
99+
assert.equal(updateSvgTransformAttr(win), false);
100+
// IE: transforms are NOT supported.
101+
agent('Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 7.0;' +
102+
' InfoPath.3; .NET CLR 3.1.40767; Trident/6.0; en-IN)');
103+
assert.equal(updateSvgTransformAttr(win), true);
104+
// Edge: transforms are NOT supported.
105+
agent('Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36' +
106+
' (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36' +
107+
' Edge/12.10136');
108+
assert.equal(updateSvgTransformAttr(win), true);
109+
});
110+
test('Set and clear transform', function() {
111+
// This is not an SVG element, so CSS transform support is not consulted.
112+
window._webAnimationsUpdateSvgTransformAttr = true;
113+
// Set.
114+
this.element.style._set('transform', 'translate(10px, 10px) scale(2)');
115+
assert.equal(getComputedStyle(this.element).transform,
116+
'matrix(2, 0, 0, 2, 10, 10)');
117+
assert.equal(this.element.hasAttribute('transform'), false);
118+
// Clear.
119+
this.element.style._clear('transform');
120+
assert.equal(getComputedStyle(this.element).transform, 'none');
121+
assert.equal(this.element.hasAttribute('transform'), false);
122+
});
123+
test('Set and clear supported transform on SVG element', function() {
124+
window._webAnimationsUpdateSvgTransformAttr = false;
125+
var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
126+
ensureStyleIsPatched(svgElement);
127+
this.svgContainer.appendChild(svgElement);
128+
// Set.
129+
svgElement.style._set('transform', 'translate(10px, 10px) scale(2)');
130+
assert.equal(getComputedStyle(svgElement).transform,
131+
'matrix(2, 0, 0, 2, 10, 10)');
132+
assert.equal(svgElement.hasAttribute('transform'), false);
133+
// Clear.
134+
svgElement.style._clear('transform');
135+
assert.equal(getComputedStyle(svgElement).transform, 'none');
136+
assert.equal(svgElement.hasAttribute('transform'), false);
137+
});
138+
test('Set and clear NOT supported transform on SVG element', function() {
139+
window._webAnimationsUpdateSvgTransformAttr = true;
140+
var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
141+
ensureStyleIsPatched(svgElement);
142+
this.svgContainer.appendChild(svgElement);
143+
// Set.
144+
svgElement.style._set('transform', 'translate(10px, 10px) scale(2)');
145+
assert.equal(getComputedStyle(svgElement).transform,
146+
'matrix(2, 0, 0, 2, 10, 10)');
147+
assert.equal(svgElement.getAttribute('transform'),
148+
'matrix(2 0 0 2 10 10)');
149+
// Clear.
150+
svgElement.style._clear('transform');
151+
assert.equal(getComputedStyle(svgElement).transform, 'none');
152+
assert.equal(svgElement.getAttribute('transform'), null);
153+
});
154+
test('Set and clear NOT supported prefixed transform on SVG element', function() {
155+
window._webAnimationsUpdateSvgTransformAttr = true;
156+
var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
157+
ensureStyleIsPatched(svgElement);
158+
this.svgContainer.appendChild(svgElement);
159+
// Set.
160+
svgElement.style._set('msTransform', 'translate(10px, 10px) scale(2)');
161+
assert.equal(svgElement.getAttribute('transform'),
162+
'matrix(2 0 0 2 10 10)');
163+
// Clear.
164+
svgElement.style._clear('msTransform');
165+
assert.equal(svgElement.getAttribute('transform'), null);
166+
});
167+
test('Restore NOT supported transform on SVG element', function() {
168+
window._webAnimationsUpdateSvgTransformAttr = true;
169+
var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
170+
svgElement.setAttribute('transform', 'matrix(2 0 0 2 0 0)');
171+
ensureStyleIsPatched(svgElement);
172+
this.svgContainer.appendChild(svgElement);
173+
// Set.
174+
svgElement.style._set('transform', 'translate(10px, 10px) scale(2)');
175+
assert.equal(getComputedStyle(svgElement).transform,
176+
'matrix(2, 0, 0, 2, 10, 10)');
177+
assert.equal(svgElement.getAttribute('transform'),
178+
'matrix(2 0 0 2 10 10)');
179+
// Clear.
180+
svgElement.style._clear('transform');
181+
assert.equal(getComputedStyle(svgElement).transform, 'none');
182+
assert.equal(svgElement.getAttribute('transform'), 'matrix(2 0 0 2 0 0)');
183+
});
72184
});

0 commit comments

Comments
 (0)