| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 Google Inc. All rights reserved. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 (function(scope, testing) { | |
| 16 | |
| 17 var styleAttributes = { | |
| 18 cssText: 1, | |
| 19 length: 1, | |
| 20 parentRule: 1, | |
| 21 }; | |
| 22 | |
| 23 var styleMethods = { | |
| 24 getPropertyCSSValue: 1, | |
| 25 getPropertyPriority: 1, | |
| 26 getPropertyValue: 1, | |
| 27 item: 1, | |
| 28 removeProperty: 1, | |
| 29 setProperty: 1, | |
| 30 }; | |
| 31 | |
| 32 var styleMutatingMethods = { | |
| 33 removeProperty: 1, | |
| 34 setProperty: 1, | |
| 35 }; | |
| 36 | |
| 37 function configureProperty(object, property, descriptor) { | |
| 38 descriptor.enumerable = true; | |
| 39 descriptor.configurable = true; | |
| 40 Object.defineProperty(object, property, descriptor); | |
| 41 } | |
| 42 | |
| 43 function AnimatedCSSStyleDeclaration(element) { | |
| 44 WEB_ANIMATIONS_TESTING && console.assert(!(element.style instanceof Animated
CSSStyleDeclaration), | |
| 45 'Element must not already have an animated style attached.'); | |
| 46 | |
| 47 // Stores the inline style of the element on its behalf while the | |
| 48 // polyfill uses the element's inline style to simulate web animations. | |
| 49 // This is needed to fake regular inline style CSSOM access on the element. | |
| 50 this._surrogateStyle = document.createElementNS('http://www.w3.org/1999/xhtm
l', 'div').style; | |
| 51 this._style = element.style; | |
| 52 this._length = 0; | |
| 53 this._isAnimatedProperty = {}; | |
| 54 | |
| 55 // Copy the inline style contents over to the surrogate. | |
| 56 for (var i = 0; i < this._style.length; i++) { | |
| 57 var property = this._style[i]; | |
| 58 this._surrogateStyle[property] = this._style[property]; | |
| 59 } | |
| 60 this._updateIndices(); | |
| 61 } | |
| 62 | |
| 63 AnimatedCSSStyleDeclaration.prototype = { | |
| 64 get cssText() { | |
| 65 return this._surrogateStyle.cssText; | |
| 66 }, | |
| 67 set cssText(text) { | |
| 68 var isAffectedProperty = {}; | |
| 69 for (var i = 0; i < this._surrogateStyle.length; i++) { | |
| 70 isAffectedProperty[this._surrogateStyle[i]] = true; | |
| 71 } | |
| 72 this._surrogateStyle.cssText = text; | |
| 73 this._updateIndices(); | |
| 74 for (var i = 0; i < this._surrogateStyle.length; i++) { | |
| 75 isAffectedProperty[this._surrogateStyle[i]] = true; | |
| 76 } | |
| 77 for (var property in isAffectedProperty) { | |
| 78 if (!this._isAnimatedProperty[property]) { | |
| 79 this._style.setProperty(property, this._surrogateStyle.getPropertyValu
e(property)); | |
| 80 } | |
| 81 } | |
| 82 }, | |
| 83 get length() { | |
| 84 return this._surrogateStyle.length; | |
| 85 }, | |
| 86 get parentRule() { | |
| 87 return this._style.parentRule; | |
| 88 }, | |
| 89 // Mirror the indexed getters and setters of the surrogate style. | |
| 90 _updateIndices: function() { | |
| 91 while (this._length < this._surrogateStyle.length) { | |
| 92 Object.defineProperty(this, this._length, { | |
| 93 configurable: true, | |
| 94 enumerable: false, | |
| 95 get: (function(index) { | |
| 96 return function() { return this._surrogateStyle[index]; }; | |
| 97 })(this._length) | |
| 98 }); | |
| 99 this._length++; | |
| 100 } | |
| 101 while (this._length > this._surrogateStyle.length) { | |
| 102 this._length--; | |
| 103 Object.defineProperty(this, this._length, { | |
| 104 configurable: true, | |
| 105 enumerable: false, | |
| 106 value: undefined | |
| 107 }); | |
| 108 } | |
| 109 }, | |
| 110 _set: function(property, value) { | |
| 111 this._style[property] = value; | |
| 112 this._isAnimatedProperty[property] = true; | |
| 113 }, | |
| 114 _clear: function(property) { | |
| 115 this._style[property] = this._surrogateStyle[property]; | |
| 116 delete this._isAnimatedProperty[property]; | |
| 117 }, | |
| 118 }; | |
| 119 | |
| 120 // Wrap the style methods. | |
| 121 for (var method in styleMethods) { | |
| 122 AnimatedCSSStyleDeclaration.prototype[method] = (function(method, modifiesSt
yle) { | |
| 123 return function() { | |
| 124 var result = this._surrogateStyle[method].apply(this._surrogateStyle, ar
guments); | |
| 125 if (modifiesStyle) { | |
| 126 if (!this._isAnimatedProperty[arguments[0]]) | |
| 127 this._style[method].apply(this._style, arguments); | |
| 128 this._updateIndices(); | |
| 129 } | |
| 130 return result; | |
| 131 } | |
| 132 })(method, method in styleMutatingMethods); | |
| 133 } | |
| 134 | |
| 135 // Wrap the style.cssProperty getters and setters. | |
| 136 for (var property in document.documentElement.style) { | |
| 137 if (property in styleAttributes || property in styleMethods) { | |
| 138 continue; | |
| 139 } | |
| 140 (function(property) { | |
| 141 configureProperty(AnimatedCSSStyleDeclaration.prototype, property, { | |
| 142 get: function() { | |
| 143 return this._surrogateStyle[property]; | |
| 144 }, | |
| 145 set: function(value) { | |
| 146 this._surrogateStyle[property] = value; | |
| 147 this._updateIndices(); | |
| 148 if (!this._isAnimatedProperty[property]) | |
| 149 this._style[property] = value; | |
| 150 } | |
| 151 }); | |
| 152 })(property); | |
| 153 } | |
| 154 | |
| 155 function ensureStyleIsPatched(element) { | |
| 156 if (element._webAnimationsPatchedStyle) | |
| 157 return; | |
| 158 | |
| 159 var animatedStyle = new AnimatedCSSStyleDeclaration(element); | |
| 160 try { | |
| 161 configureProperty(element, 'style', { get: function() { return animatedSty
le; } }); | |
| 162 } catch (_) { | |
| 163 // iOS and older versions of Safari (pre v7) do not support overriding an
element's | |
| 164 // style object. Animations will clobber any inline styles as a result. | |
| 165 element.style._set = function(property, value) { | |
| 166 element.style[property] = value; | |
| 167 }; | |
| 168 element.style._clear = function(property) { | |
| 169 element.style[property] = ''; | |
| 170 }; | |
| 171 } | |
| 172 | |
| 173 // We must keep a handle on the patched style to prevent it from getting GC'
d. | |
| 174 element._webAnimationsPatchedStyle = element.style; | |
| 175 } | |
| 176 | |
| 177 scope.apply = function(element, property, value) { | |
| 178 ensureStyleIsPatched(element); | |
| 179 element.style._set(scope.propertyName(property), value); | |
| 180 }; | |
| 181 | |
| 182 scope.clear = function(element, property) { | |
| 183 if (element._webAnimationsPatchedStyle) { | |
| 184 element.style._clear(scope.propertyName(property)); | |
| 185 } | |
| 186 }; | |
| 187 | |
| 188 if (WEB_ANIMATIONS_TESTING) | |
| 189 testing.ensureStyleIsPatched = ensureStyleIsPatched; | |
| 190 | |
| 191 })(webAnimations1, webAnimationsTesting); | |
| OLD | NEW |