aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js')
-rw-r--r--catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js239
1 files changed, 239 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js b/catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js
new file mode 100644
index 00000000..4002a2f5
--- /dev/null
+++ b/catapult/third_party/polymer/components/web-animations-js/src/apply-preserving-inline-style.js
@@ -0,0 +1,239 @@
+// 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 SVG_TRANSFORM_PROP = '_webAnimationsUpdateSvgTransformAttr';
+
+ /**
+ * IE/Edge do not support `transform` styles for SVG elements. Instead,
+ * `transform` attribute can be animated with some restrictions.
+ * See https://connect.microsoft.com/IE/feedback/details/811744/ie11-bug-with-implementation-of-css-transforms-in-svg,
+ * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/1173754/,
+ * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101242/, etc.
+ * The same problem is exhibited by pre-Chrome Android browsers (ICS).
+ * Unfortunately, there's no easy way to feature-detect it.
+ */
+ function updateSvgTransformAttr(window, element) {
+ if (!element.namespaceURI || element.namespaceURI.indexOf('/svg') == -1) {
+ return false;
+ }
+ if (!(SVG_TRANSFORM_PROP in window)) {
+ window[SVG_TRANSFORM_PROP] =
+ /Trident|MSIE|IEMobile|Edge|Android 4/i.test(window.navigator.userAgent);
+ }
+ return window[SVG_TRANSFORM_PROP];
+ }
+
+ 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.');
+
+ this._element = element;
+ // 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 = {};
+ this._updateSvgTransformAttr = updateSvgTransformAttr(window, element);
+ this._savedTransformAttr = null;
+
+ // 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;
+ if (this._updateSvgTransformAttr &&
+ scope.unprefixedPropertyName(property) == 'transform') {
+ // On IE/Edge, also set SVG element's `transform` attribute to 2d
+ // matrix of the transform. The `transform` style does not work, but
+ // `transform` attribute can be used instead.
+ // Notice, if the platform indeed supports SVG/CSS transforms the CSS
+ // declaration is supposed to override the attribute.
+ if (this._savedTransformAttr == null) {
+ this._savedTransformAttr = this._element.getAttribute('transform');
+ }
+ this._element.setAttribute('transform', scope.transformToSvgMatrix(value));
+ }
+ },
+ _clear: function(property) {
+ this._style[property] = this._surrogateStyle[property];
+ if (this._updateSvgTransformAttr &&
+ scope.unprefixedPropertyName(property) == 'transform') {
+ if (this._savedTransformAttr) {
+ this._element.setAttribute('transform', this._savedTransformAttr);
+ } else {
+ this._element.removeAttribute('transform');
+ }
+ this._savedTransformAttr = null;
+ }
+ 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;
+ testing.updateSvgTransformAttr = updateSvgTransformAttr;
+ }
+
+})(webAnimations1, webAnimationsTesting);