Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: pkg/polymer/lib/elements/polymer-overlay/polymer-overlay.html

Issue 175443005: [polymer] import all elements (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: updated from bower Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 <!--
2 Copyright 2013 The Polymer Authors. All rights reserved.
3 Use of this source code is governed by a BSD-style
4 license that can be found in the LICENSE file.
5 -->
6 <link rel="import" href="../polymer/polymer.html">
7
8 <link rel="import" href="../polymer-key-helper/polymer-key-helper.html">
9
10 <!--
11 /**
12 * @module Polymer Elements
13 */
14 /**
15 * polymer-overlay displays overlayed on top of other content. It starts
16 * out hidden and is displayed by setting it's opened property to true.
17 * A polymer-overlay's opened state can be toggled by calling the toggle
18 * method.
19 *
20 * It's common to want a polymer-overlay to animate to its opened
21 * position. A number of helper css classes provide some basic open/close
22 * animations. For example, assigning the class polymer-overlay-fade to a
23 * polymer-overlay will make it fade into and out of view as it opens and
24 * closes. Note, if multiple polymer-overlay's are opened, they should
25 * stack on top of each other.
26 *
27 * Styling: The size and position of a polymer-overlay should be setup
28 * via css.
29 * polymer-overlay is natually sized around its content. When a
30 * polymer-overlay is opened it is shown and the 'opened' class is added
31 * to it. This is typically where css transitions and animations are
32 * applied. When the polymer-overlay is closed, the 'opened' class is
33 * removed and a 'closing' class is added. Use 'closing' to customize
34 * the closing animation.
35 *
36 * Classes for animating polymer-overlay:
37 *
38 * * polymer-overlay-fade: fade in/out when opened/closed
39 * * polymer-overlay-scale-slideup: open: fade in and shrink;
40 * close: slide up
41 * * polymer-overlay-shake: open: fly in and shake; close: shake and
42 * fly out.
43 *
44 * It's common to use polymer-overlay to gather user input, for example
45 * a login dialog. To facilitate this, polymer-overlay supports automatic
46 * focusing of a specific element when it's opened. The element to be
47 * focused should be given an autofocus attribute.
48 *
49 * An element that should close the polymer-overlay will automatically
50 * do so if it is given the overlay-toggle attribute. Please note that
51 * polymer-overlay will close whenever the user taps outside it or
52 * presses the escape key. The behavior can be turned off via the
53 * autoCloseDisabled property.
54 *
55 * <div>
56 * <polymer-overlay></polymer-overlay>
57 * <h2>Dialog</h2>
58 * <input placeholder="say something..." autofocus>
59 * <div>I agree with this wholeheartedly.</div>
60 * <button overlay-toggle>OK</button>
61 * </div>
62 *
63 * @class polymer-overlay
64 */
65 /**
66 * Fired when the polymer-overlay opened property is set.
67 *
68 * @event polymer-overlay-open
69 * @param {Object} inDetail
70 * @param {Object} inDetail.opened the opened state
71 */
72 -->
73 <polymer-element name="polymer-overlay" attributes="target opened autoCloseDisab led transitions">
74 <template>
75 <link rel="stylesheet" polymer-scope="controller" href="polymer-overlay.css" >
76 <link rel="stylesheet" href="polymer-overlay.css">
77 <polymer-key-helper id="keyHelper"></polymer-key-helper>
78 </template>
79 <script>
80 (function() {
81 // track overlays for z-index and focus managemant
82 var overlays = [];
83 var trackOverlays = function(inOverlay) {
84 if (inOverlay.opened) {
85 //var overlayZ = window.getComputedStyle(inOverlay.target).zIndex;
86 //var z0 = Math.max(currentOverlayZ(), overlayZ);
87 var z0 = currentOverlayZ();
88 overlays.push(inOverlay);
89 var z1 = currentOverlayZ();
90 if (z1 <= z0) {
91 applyOverlayZ(inOverlay, z0);
92 }
93 } else {
94 var i = overlays.indexOf(inOverlay);
95 if (i >= 0) {
96 overlays.splice(i, 1);
97 setZ(inOverlay, null);
98 }
99 }
100 }
101
102 var applyOverlayZ = function(inOverlay, inAboveZ) {
103 setZ(inOverlay.target, inAboveZ + 2);
104 }
105
106 var setZ = function(inNode, inZ) {
107 inNode.style.zIndex = inZ;
108 }
109
110 var currentOverlay = function() {
111 return overlays[overlays.length-1];
112 }
113
114 var DEFAULT_Z = 10;
115
116 var currentOverlayZ = function() {
117 var z;
118 var current = currentOverlay();
119 if (current) {
120 var z1 = window.getComputedStyle(current.target).zIndex;
121 if (!isNaN(z1)) {
122 z = Number(z1);
123 }
124 }
125 return z || DEFAULT_Z;
126 }
127
128 var focusOverlay = function() {
129 var current = currentOverlay();
130 if (current) {
131 current.applyFocus();
132 }
133 }
134
135 Polymer('polymer-overlay', {
136 /**
137 * The target element.
138 *
139 * @attribute target
140 * @type Object
141 */
142 target: null,
143 /**
144 * Set opened to true to show an overlay and to false to hide it.
145 * A polymer-overlay may be made intially opened by setting its
146 * opened attribute.
147 * @attribute opened
148 * @type boolean
149 * @default false
150 */
151 opened: false,
152 /**
153 * By default an overlay will close automatically if the user
154 * taps outside it or presses the escape key. Disable this
155 * behavior by setting the autoCloseDisabled property to true.
156 * @attribute autoCloseDisabled
157 * @type boolean
158 * @default false
159 */
160 autoCloseDisabled: false,
161 /**
162 * This property specifies the animation to play when the overlay is
163 * opened/closed. It can be an array of two animations
164 * [opening, closing], a single animation, an array of two strings, or
165 * a string. The strings should the tag names of custom elements
166 * descending from a polymer-animation. In the case of a single
167 * animation the closing animation is the opening animation played
168 * backwards.
169 * @attribute transitions
170 * @type polymer-animation
171 * @type Array&lt;polymer-animation>
172 * @type string
173 * @type Array&lt;string>
174 */
175 transitions: null,
176 timeout: 1000,
177 captureEventType: 'tap',
178 ready: function() {
179 if (this.tabIndex === undefined) {
180 this.tabIndex = -1;
181 }
182 this.setAttribute('touch-action', 'none');
183 },
184 enteredView: function() {
185 this.installControllerStyles();
186 },
187 /**
188 * Toggle the opened state of the overlay.
189 * @method toggle
190 */
191 toggle: function() {
192 this.opened = !this.opened;
193 },
194 targetChanged: function(old) {
195 if (this.target) {
196 if (this.target.tabIndex === undefined) {
197 this.target.tabIndex = -1;
198 }
199 this.target.classList.add('polymer-overlay');
200 this.addListeners(this.target);
201 }
202 if (old) {
203 old.classList.remove('polymer-overlay');
204 this.removeListeners(old);
205 }
206 },
207 listeners: {
208 'tap': 'tapHandler',
209 'keydown': 'keydownHandler'
210 },
211 addListeners: function(node) {
212 for (e in this.listeners) {
213 node.addEventListener(e, this[this.listeners[e]].bind(this));
214 }
215 },
216 removeListeners: function(node) {
217 for (e in this.listeners) {
218 node.removeEventListener(e, this[this.listeners[e]].bind(this));
219 }
220 },
221 openedChanged: function() {
222 this.renderOpened();
223 trackOverlays(this);
224 this.async(function() {
225 if (!this.autoCloseDisabled) {
226 this.enableCaptureHandler(this.opened);
227 }
228 });
229 this.enableResizeHandler(this.opened);
230 this.fire('polymer-overlay-open', this.opened);
231 },
232 enableHandler: function(inEnable, inMethodName, inNode, inEventName, inC apture) {
233 var m = 'bound' + inMethodName;
234 this[m] = this[m] || this[inMethodName].bind(this);
235
236 inNode[inEnable ? 'addEventListener' : 'removeEventListener'](
237 inEventName, this[m], inCapture);
238 },
239 enableResizeHandler: function(inEnable) {
240 this.enableHandler(inEnable, 'resizeHandler', window,
241 'resize');
242 },
243 enableCaptureHandler: function(inEnable) {
244 this.enableHandler(inEnable, 'captureHandler', document,
245 this.captureEventType, true);
246 },
247 getFocusNode: function() {
248 return this.target.querySelector('[autofocus]') || this.target;
249 },
250 // TODO(sorvell): nodes stay focused when they become un-focusable
251 // due to an ancestory becoming display: none; file bug.
252 applyFocus: function() {
253 var focusNode = this.getFocusNode();
254 if (this.opened) {
255 focusNode.focus();
256 } else {
257 focusNode.blur();
258 focusOverlay();
259 }
260 },
261 positionTarget: function() {
262 if (this.opened) {
263 // vertically and horizontally center if not positioned
264 var computedStyle = getComputedStyle(this.target);
265 if (computedStyle.top === 'auto' && computedStyle.bottom === 'auto') {
266 this.target.style.top = ((window.innerHeight - this.target.getBoun dingClientRect().height) / 2) + 'px';
267 }
268 if (computedStyle.left === 'auto' && computedStyle.right === 'auto') {
269 this.target.style.left = ((window.innerWidth - this.target.getBoun dingClientRect().width) / 2) + 'px';
270 }
271 }
272 },
273 resetTargetPosition: function() {
274 this.target.style.top = this.target.style.left = null;
275 },
276 get transition() {
277 return (!Array.isArray(this.transitions) && this.transitions
278 || this.opened && this.transitions && this.transitions[0]
279 || !this.opened && this.transitions && this.transitions[1]);
280 },
281 applyTransition: function() {
282 var animation = typeof this.transition === 'string' ?
283 document.createElement(this.transition) : this.transition;
284 // FIXME: Apply a default duration.
285 if ((!animation.duration || animation.duration === 'auto') && !animati on.type) {
286 animation.duration = 0.3;
287 }
288 if (!animation.hasTarget()) {
289 animation.target = this.target;
290 }
291 // Make the overlay visible while the animation is running.
292 var transition = new ParGroup([
293 animation.apply(),
294 new Animation(this.target, [{'visibility': 'visible', 'display':'blo ck'}])
295 ], {fill: 'none'});
296 transition.onend = this.completeOpening.bind(this);
297 this.target.classList.add('animating');
298 document.timeline.play(transition);
299 },
300 renderOpened: function() {
301 this.target.classList.add('revealed');
302 // continue styling after delay so display state can change
303 // without aborting transitions
304 this.async('continueRenderOpened');
305 },
306 continueRenderOpened: function() {
307 this.positionTarget();
308 if (this.transition) {
309 this.applyTransition();
310 // FIXME: Apply the class after the animation starts playing to
311 // prevent a flicker at the end of the animation. Should be handled
312 // in polymer-animation-start event but not working in polyfill
313 this.async(function() {
314 this.target.classList.toggle('opened', this.opened);
315 }, null, 100);
316 } else {
317 this.target.classList.toggle('opened', this.opened);
318 this.async('completeOpening');
319 }
320 },
321 completeOpening: function() {
322 this.target.classList.remove('animating');
323 this.target.classList.toggle('revealed', this.opened);
324 if (!this.opened) {
325 this.resetTargetPosition();
326 }
327 this.applyFocus();
328 },
329 tapHandler: function(e) {
330 if (e.target && e.target.hasAttribute('overlay-toggle')) {
331 this.toggle();
332 } else {
333 if (this.autoCloseJob) {
334 this.autoCloseJob.stop();
335 this.autoCloseJob = null;
336 }
337 }
338 },
339 // TODO(sorvell): This approach will not work with modal. For
340 // this we need a scrim.
341 captureHandler: function(e) {
342 if (!this.autoCloseDisabled && (currentOverlay() == this) && (this
343 != e.target) && !(this.contains(e.target))) {
344 this.autoCloseJob = this.job(this.autoCloseJob, function() {
345 this.opened = false;
346 });
347 }
348 },
349 keydownHandler: function(e) {
350 if (!this.autoCloseDisabled && (e.keyCode == this.$.keyHelper.ESCAPE_K EY)) {
351 this.opened = false;
352 e.stopPropagation();
353 e.cancelBubble = true;
354 }
355 },
356 /**
357 * Extensions of polymer-overlay should implement the resizeHandler
358 * method to adjust the size and position of the overlay when the
359 * browser window resizes.
360 * @method resizeHandler
361 */
362 resizeHandler: function() {
363 }
364 });
365 })();
366 </script>
367 </polymer-element>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698