OLD | NEW |
| (Empty) |
1 | |
2 (function() { | |
3 | |
4 var webkitStyles = '-webkit-transition' in document.documentElement.style | |
5 var TRANSITION_CSSNAME = webkitStyles ? '-webkit-transition' : 'transition'; | |
6 var TRANSFORM_CSSNAME = webkitStyles ? '-webkit-transform' : 'transform'; | |
7 var TRANSITION_NAME = webkitStyles ? 'webkitTransition' : 'transition'; | |
8 var TRANSFORM_NAME = webkitStyles ? 'webkitTransform' : 'transform'; | |
9 | |
10 var hasShadowDOMPolyfill = window.ShadowDOMPolyfill; | |
11 | |
12 Polymer('hero-transition',{ | |
13 | |
14 go: function(scope, options) { | |
15 var props = [ | |
16 'border-radius', | |
17 'width', | |
18 'height', | |
19 TRANSFORM_CSSNAME | |
20 ]; | |
21 | |
22 var duration = options && options.duration || | |
23 (CoreStyle.g.transitions.heroDuration || | |
24 CoreStyle.g.transitions.duration); | |
25 | |
26 scope._heroes.forEach(function(h) { | |
27 var d = h.h0.hasAttribute('hero-delayed') ? CoreStyle.g.transitions.hero
Delay : ''; | |
28 var wt = []; | |
29 props.forEach(function(p) { | |
30 wt.push(p + ' ' + duration + ' ' + options.easing + ' ' + d); | |
31 }); | |
32 | |
33 h.h1.style[TRANSITION_NAME] = wt.join(', '); | |
34 h.h1.style.borderRadius = h.r1; | |
35 h.h1.style[TRANSFORM_NAME] = ''; | |
36 }); | |
37 | |
38 this.super(arguments); | |
39 | |
40 if (!scope._heroes.length) { | |
41 this.completed = true; | |
42 } | |
43 }, | |
44 | |
45 prepare: function(scope, options) { | |
46 this.super(arguments); | |
47 var src = options.src, dst = options.dst; | |
48 | |
49 if (scope._heroes && scope._heroes.length) { | |
50 this.ensureComplete(scope); | |
51 } else { | |
52 scope._heroes = []; | |
53 } | |
54 | |
55 // FIXME(yvonne): basic support for nested pages. | |
56 // Look for heroes in the light DOM and one level of shadow DOM of the src
and dst, | |
57 // and also in src.selectedItem or dst.selectedItem, then transform the ds
t hero to src | |
58 var ss = '[hero]'; | |
59 var h$ = this.findAllInShadows(src, ss); | |
60 if (src.selectedItem) { | |
61 hs$ = this.findAllInShadows(src.selectedItem, ss); | |
62 hsa$ = []; | |
63 // De-duplicate items | |
64 Array.prototype.forEach.call(hs$, function(hs) { | |
65 if (h$.indexOf(hs) === -1) { | |
66 hsa$.push(hs); | |
67 } | |
68 }) | |
69 h$ = h$.concat(hsa$); | |
70 } | |
71 | |
72 for (var i=0, h0; h0=h$[i]; i++) { | |
73 var v = h0.getAttribute('hero-id'); | |
74 var ds = '[hero][hero-id="' + v + '"]'; | |
75 var h1 = this.findInShadows(dst, ds); | |
76 | |
77 if (!h1 && dst.selectedItem) { | |
78 h1 = this.findInShadows(dst.selectedItem, ds); | |
79 } | |
80 | |
81 // console.log('src', src); | |
82 // console.log('dst', dst, dst.selectedItem); | |
83 // console.log(v, h0, h1); | |
84 if (v && h1) { | |
85 var c0 = getComputedStyle(h0); | |
86 var c1 = getComputedStyle(h1); | |
87 var h = { | |
88 h0: h0, | |
89 b0: h0.getBoundingClientRect(), | |
90 r0: c0.borderRadius, | |
91 h1: h1, | |
92 b1: h1.getBoundingClientRect(), | |
93 r1: c1.borderRadius | |
94 }; | |
95 | |
96 var dl = h.b0.left - h.b1.left; | |
97 var dt = h.b0.top - h.b1.top; | |
98 var sw = h.b0.width / h.b1.width; | |
99 var sh = h.b0.height / h.b1.height; | |
100 | |
101 // h.scaley = h.h0.hasAttribute('scaley'); | |
102 // if (!h.scaley && (sw !== 1 || sh !== 1)) { | |
103 // sw = sh = 1; | |
104 // h.h1.style.width = h.b0.width + 'px'; | |
105 // h.h1.style.height = h.b0.height + 'px'; | |
106 // } | |
107 | |
108 // Also animate the border-radius for the circle-to-square transition | |
109 if (h.r0 !== h.r1) { | |
110 h.h1.style.borderRadius = h.r0; | |
111 } | |
112 | |
113 // console.log(h); | |
114 | |
115 h.h1.style[TRANSFORM_NAME] = 'translate(' + dl + 'px,' + dt + 'px)' +
' scale(' + sw + ',' + sh + ')'; | |
116 h.h1.style[TRANSFORM_NAME + 'Origin'] = '0 0'; | |
117 | |
118 scope._heroes.push(h); | |
119 } | |
120 } | |
121 | |
122 }, | |
123 | |
124 // carefully look into ::shadow with polyfill specific hack | |
125 findInShadows: function(node, selector) { | |
126 return node.querySelector(selector) || (hasShadowDOMPolyfill ? | |
127 queryAllShadows(node, selector) : | |
128 node.querySelector('::shadow ' + selector)); | |
129 }, | |
130 | |
131 findAllInShadows: function(node, selector) { | |
132 if (hasShadowDOMPolyfill) { | |
133 var nodes = node.querySelectorAll(selector).array(); | |
134 var shadowNodes = queryAllShadows(node, selector, true); | |
135 return nodes.concat(shadowNodes); | |
136 } else { | |
137 return node.querySelectorAll(selector).array().concat(node.shadowRoot ?
node.shadowRoot.querySelectorAll(selector).array() : []); | |
138 } | |
139 }, | |
140 | |
141 ensureComplete: function(scope) { | |
142 this.super(arguments); | |
143 if (scope._heroes) { | |
144 scope._heroes.forEach(function(h) { | |
145 h.h1.style[TRANSITION_NAME] = ''; | |
146 h.h1.style[TRANSFORM_NAME] = ''; | |
147 }); | |
148 scope._heroes = []; | |
149 } | |
150 }, | |
151 | |
152 complete: function(scope, e) { | |
153 // if (e.propertyName === TRANSFORM_CSSNAME) { | |
154 var done = false; | |
155 scope._heroes.forEach(function(h) { | |
156 if (h.h1 === e.path[0]) { | |
157 done = true; | |
158 } | |
159 }); | |
160 | |
161 if (done) { | |
162 this.super(arguments); | |
163 } | |
164 // } | |
165 } | |
166 | |
167 }); | |
168 | |
169 | |
170 // utility method for searching through shadowRoots. | |
171 function queryShadow(node, selector) { | |
172 var m, el = node.firstElementChild; | |
173 var shadows, sr, i; | |
174 shadows = []; | |
175 sr = node.shadowRoot; | |
176 while(sr) { | |
177 shadows.push(sr); | |
178 sr = sr.olderShadowRoot; | |
179 } | |
180 for(i = shadows.length - 1; i >= 0; i--) { | |
181 m = shadows[i].querySelector(selector); | |
182 if (m) { | |
183 return m; | |
184 } | |
185 } | |
186 while(el) { | |
187 m = queryShadow(el, selector); | |
188 if (m) { | |
189 return m; | |
190 } | |
191 el = el.nextElementSibling; | |
192 } | |
193 return null; | |
194 } | |
195 | |
196 function _queryAllShadows(node, selector, results) { | |
197 var el = node.firstElementChild; | |
198 var temp, sr, shadows, i, j; | |
199 shadows = []; | |
200 sr = node.shadowRoot; | |
201 while(sr) { | |
202 shadows.push(sr); | |
203 sr = sr.olderShadowRoot; | |
204 } | |
205 for (i = shadows.length - 1; i >= 0; i--) { | |
206 temp = shadows[i].querySelectorAll(selector); | |
207 for(j = 0; j < temp.length; j++) { | |
208 results.push(temp[j]); | |
209 } | |
210 } | |
211 while (el) { | |
212 _queryAllShadows(el, selector, results); | |
213 el = el.nextElementSibling; | |
214 } | |
215 return results; | |
216 } | |
217 | |
218 queryAllShadows = function(node, selector, all) { | |
219 if (all) { | |
220 return _queryAllShadows(node, selector, []); | |
221 } else { | |
222 return queryShadow(node, selector); | |
223 } | |
224 }; | |
225 | |
226 })(); | |
OLD | NEW |