Remove LOAD_SUB_FRAME load flag.
[chromium-blink-merge.git] / third_party / polymer / components / core-animated-pages / transitions / hero-transition.html
blob8e02dfd5dbf7d17ef557f912ba70e57cffa8bfb8
1 <!--
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6 Code distributed by Google as part of the polymer project is also
7 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
8 -->
10 <link href="core-transition-pages.html" rel="import">
12 <core-style id="hero-transition">
13 /* Hide heroes that are not currently transitioning */
14 polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [hero]'; }
15 ::content > [animate]:not(.core-selected) /deep/ [hero] {
16 opacity: 0;
19 polyfill-next-selector { content: ':host > .core-selected[animate] [hero]'; }
20 ::content > .core-selected[animate] /deep/ [hero] {
21 opacity: 1;
22 z-index: 10000;
25 polyfill-next-selector { content: ':host > * [hero-p]'; }
26 ::content > * /deep/ [hero-p] {
27 -webkit-transition: box-shadow 100ms ease-out;
28 transition: box-shadow 100ms ease-out;
31 polyfill-next-selector { content: ':host > [animate] [hero-p]'; }
32 ::content > [animate] /deep/ [hero-p] {
33 box-shadow: none !important;
35 </core-style>
38 <!--
40 `hero-transition` transforms two elements in different pages such that they appear
41 to be shared across the pages.
43 Example:
45 <core-animated-pages transition="hero-transition">
46 <section layout horizontal>
47 <div id="div1" flex></div>
48 <div id="div2" flex hero-id="shared" hero></div>
49 </section>
50 <section>
51 <section layout horizontal>
52 <div id="div3" flex hero-id="shared" hero></div>
53 <div id="div4" flex></div>
54 </section>
55 </section>
56 </core-animated-pages>
58 In the above example, the elements `#div2` and `#div3` shares the same `hero-id`
59 attribute and a single element appears to translate and scale smoothly between
60 the two positions during a page transition.
62 Both elements from the source and destination pages must share the same `hero-id`
63 and must both contain the `hero` attribute to trigger the transition. The separate
64 `hero` attribute allows you to use binding to configure the transition:
66 Example:
68 <core-animated-pages transition="hero-transition">
69 <section layout horizontal>
70 <div id="div1" flex hero-id="shared" hero?="{{selected == 0}}"></div>
71 <div id="div2" flex hero-id="shared" hero?="{{selected == 1}}"></div>
72 </section>
73 <section>
74 <section layout horizontal>
75 <div id="div3" flex hero-id="shared" hero></div>
76 </section>
77 </section>
78 </core-animated-pages>
80 In the above example, either `#div1` or `#div2` scales to `#div3` during a page transition,
81 depending on the value of `selected`.
83 Because it is common to share elements with different `border-radius` values, by default
84 this transition will also animate the `border-radius` property.
86 You can configure the duration of the hero transition with the global variable
87 `CoreStyle.g.transitions.heroDuration`.
89 @class hero-transition
90 @extends core-transition-pages
91 @status beta
92 @homepage github.io
93 -->
94 <polymer-element name="hero-transition" extends="core-transition-pages">
95 <script>
96 (function() {
98 var webkitStyles = '-webkit-transition' in document.documentElement.style
99 var TRANSITION_CSSNAME = webkitStyles ? '-webkit-transition' : 'transition';
100 var TRANSFORM_CSSNAME = webkitStyles ? '-webkit-transform' : 'transform';
101 var TRANSITION_NAME = webkitStyles ? 'webkitTransition' : 'transition';
102 var TRANSFORM_NAME = webkitStyles ? 'webkitTransform' : 'transform';
104 var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
106 Polymer({
108 go: function(scope, options) {
109 var props = [
110 'border-radius',
111 'width',
112 'height',
113 TRANSFORM_CSSNAME
116 var duration = options && options.duration ||
117 (CoreStyle.g.transitions.heroDuration ||
118 CoreStyle.g.transitions.duration);
120 scope._heroes.forEach(function(h) {
121 var d = h.h0.hasAttribute('hero-delayed') ? CoreStyle.g.transitions.heroDelay : '';
122 var wt = [];
123 props.forEach(function(p) {
124 wt.push(p + ' ' + duration + ' ' + options.easing + ' ' + d);
127 h.h1.style[TRANSITION_NAME] = wt.join(', ');
128 h.h1.style.borderRadius = h.r1;
129 h.h1.style[TRANSFORM_NAME] = '';
132 this.super(arguments);
134 if (!scope._heroes.length) {
135 this.completed = true;
139 prepare: function(scope, options) {
140 this.super(arguments);
141 var src = options.src, dst = options.dst;
143 if (scope._heroes && scope._heroes.length) {
144 this.ensureComplete(scope);
145 } else {
146 scope._heroes = [];
149 // FIXME(yvonne): basic support for nested pages.
150 // Look for heroes in the light DOM and one level of shadow DOM of the src and dst,
151 // and also in src.selectedItem or dst.selectedItem, then transform the dst hero to src
152 var ss = '[hero]';
153 var h$ = this.findAllInShadows(src, ss);
154 if (src.selectedItem) {
155 hs$ = this.findAllInShadows(src.selectedItem, ss);
156 hsa$ = [];
157 // De-duplicate items
158 Array.prototype.forEach.call(hs$, function(hs) {
159 if (h$.indexOf(hs) === -1) {
160 hsa$.push(hs);
163 h$ = h$.concat(hsa$);
166 for (var i=0, h0; h0=h$[i]; i++) {
167 var v = h0.getAttribute('hero-id');
168 var ds = '[hero][hero-id="' + v + '"]';
169 var h1 = this.findInShadows(dst, ds);
171 if (!h1 && dst.selectedItem) {
172 h1 = this.findInShadows(dst.selectedItem, ds);
175 // console.log('src', src);
176 // console.log('dst', dst, dst.selectedItem);
177 // console.log(v, h0, h1);
178 if (v && h1) {
179 var c0 = getComputedStyle(h0);
180 var c1 = getComputedStyle(h1);
181 var h = {
182 h0: h0,
183 b0: h0.getBoundingClientRect(),
184 r0: c0.borderRadius,
185 h1: h1,
186 b1: h1.getBoundingClientRect(),
187 r1: c1.borderRadius
190 var dl = h.b0.left - h.b1.left;
191 var dt = h.b0.top - h.b1.top;
192 var sw = h.b0.width / h.b1.width;
193 var sh = h.b0.height / h.b1.height;
195 // h.scaley = h.h0.hasAttribute('scaley');
196 // if (!h.scaley && (sw !== 1 || sh !== 1)) {
197 // sw = sh = 1;
198 // h.h1.style.width = h.b0.width + 'px';
199 // h.h1.style.height = h.b0.height + 'px';
200 // }
202 // Also animate the border-radius for the circle-to-square transition
203 if (h.r0 !== h.r1) {
204 h.h1.style.borderRadius = h.r0;
207 // console.log(h);
209 h.h1.style[TRANSFORM_NAME] = 'translate(' + dl + 'px,' + dt + 'px)' + ' scale(' + sw + ',' + sh + ')';
210 h.h1.style[TRANSFORM_NAME + 'Origin'] = '0 0';
212 scope._heroes.push(h);
218 // carefully look into ::shadow with polyfill specific hack
219 findInShadows: function(node, selector) {
220 return node.querySelector(selector) || (hasShadowDOMPolyfill ?
221 queryAllShadows(node, selector) :
222 node.querySelector('::shadow ' + selector));
225 findAllInShadows: function(node, selector) {
226 if (hasShadowDOMPolyfill) {
227 var nodes = node.querySelectorAll(selector).array();
228 var shadowNodes = queryAllShadows(node, selector, true);
229 return nodes.concat(shadowNodes);
230 } else {
231 return node.querySelectorAll(selector).array().concat(node.shadowRoot ? node.shadowRoot.querySelectorAll(selector).array() : []);
235 ensureComplete: function(scope) {
236 this.super(arguments);
237 if (scope._heroes) {
238 scope._heroes.forEach(function(h) {
239 h.h1.style[TRANSITION_NAME] = '';
240 h.h1.style[TRANSFORM_NAME] = '';
242 scope._heroes = [];
246 complete: function(scope, e) {
247 // if (e.propertyName === TRANSFORM_CSSNAME) {
248 var done = false;
249 scope._heroes.forEach(function(h) {
250 if (h.h1 === e.path[0]) {
251 done = true;
255 if (done) {
256 this.super(arguments);
258 // }
264 // utility method for searching through shadowRoots.
265 function queryShadow(node, selector) {
266 var m, el = node.firstElementChild;
267 var shadows, sr, i;
268 shadows = [];
269 sr = node.shadowRoot;
270 while(sr) {
271 shadows.push(sr);
272 sr = sr.olderShadowRoot;
274 for(i = shadows.length - 1; i >= 0; i--) {
275 m = shadows[i].querySelector(selector);
276 if (m) {
277 return m;
280 while(el) {
281 m = queryShadow(el, selector);
282 if (m) {
283 return m;
285 el = el.nextElementSibling;
287 return null;
290 function _queryAllShadows(node, selector, results) {
291 var el = node.firstElementChild;
292 var temp, sr, shadows, i, j;
293 shadows = [];
294 sr = node.shadowRoot;
295 while(sr) {
296 shadows.push(sr);
297 sr = sr.olderShadowRoot;
299 for (i = shadows.length - 1; i >= 0; i--) {
300 temp = shadows[i].querySelectorAll(selector);
301 for(j = 0; j < temp.length; j++) {
302 results.push(temp[j]);
305 while (el) {
306 _queryAllShadows(el, selector, results);
307 el = el.nextElementSibling;
309 return results;
312 queryAllShadows = function(node, selector, all) {
313 if (all) {
314 return _queryAllShadows(node, selector, []);
315 } else {
316 return queryShadow(node, selector);
320 })();
321 </script>
322 </polymer-element>
324 <hero-transition id="hero-transition"></hero-transition>