Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components / paper-drawer-panel / paper-drawer-panel.html
blobf4cb1fb6ee0a82cadfde04850e68ece3239a46bd
1 <!--
2 Copyright (c) 2015 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 rel="import" href="../polymer/polymer.html">
11 <link rel="import" href="../iron-media-query/iron-media-query.html">
12 <link rel="import" href="../iron-selector/iron-selector.html">
14 <!--
15 `paper-drawer-panel` contains a drawer panel and a main panel. The drawer
16 and the main panel are side-by-side with drawer on the left. When the browser
17 window size is smaller than the `responsiveWidth`, `paper-drawer-panel`
18 changes to narrow layout. In narrow layout, the drawer will be stacked on top
19 of the main panel. The drawer will slide in/out to hide/reveal the main
20 panel.
22 Use the attribute `drawer` to indicate that the element is the drawer panel and
23 `main` to indicate that the element is the main panel.
25 Example:
27 <paper-drawer-panel>
28 <div drawer> Drawer panel... </div>
29 <div main> Main panel... </div>
30 </paper-drawer-panel>
32 The drawer and the main panels are not scrollable. You can set CSS overflow
33 property on the elements to make them scrollable or use `paper-header-panel`.
35 Example:
37 <paper-drawer-panel>
38 <paper-header-panel drawer>
39 <paper-toolbar></paper-toolbar>
40 <div> Drawer content... </div>
41 </paper-header-panel>
42 <paper-header-panel main>
43 <paper-toolbar></paper-toolbar>
44 <div> Main content... </div>
45 </paper-header-panel>
46 </paper-drawer-panel>
48 An element that should toggle the drawer will automatically do so if it's
49 given the `paper-drawer-toggle` attribute. Also this element will automatically
50 be hidden in wide layout.
52 Example:
54 <paper-drawer-panel>
55 <paper-header-panel drawer>
56 <paper-toolbar>
57 <div>Application</div>
58 </paper-toolbar>
59 <div> Drawer content... </div>
60 </paper-header-panel>
61 <paper-header-panel main>
62 <paper-toolbar>
63 <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
64 <div>Title</div>
65 </paper-toolbar>
66 <div> Main content... </div>
67 </paper-header-panel>
68 </paper-drawer-panel>
70 To position the drawer to the right, add `right-drawer` attribute.
72 <paper-drawer-panel right-drawer>
73 <div drawer> Drawer panel... </div>
74 <div main> Main panel... </div>
75 </paper-drawer-panel>
77 Styling `paper-drawer-panel`
79 To change the main container:
81 paper-drawer-panel {
82 --paper-drawer-panel-main-container: {
83 background-color: gray;
87 To change the drawer container when it's in the left side:
89 paper-drawer-panel {
90 --paper-drawer-panel-left-drawer-container: {
91 background-color: white;
95 To change the drawer container when it's in the right side:
97 paper-drawer-panel {
98 --paper-drawer-panel-right-drawer-container: {
99 background-color: white;
103 @group Paper elements
104 @element paper-drawer-panel
105 @demo demo/index.html
106 @hero hero.svg
109 <dom-module id="paper-drawer-panel">
110 <link rel="import" type="css" href="paper-drawer-panel.css">
112 <template>
113 <iron-media-query
114 id="mq"
115 on-query-matches-changed="_onQueryMatchesChanged"
116 query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]]">
117 </iron-media-query>
119 <iron-selector
120 attr-for-selected="id"
121 class$="[[_computeIronSelectorClass(narrow, transition, dragging, rightDrawer, peeking)]]"
122 activate-event=""
123 selected="[[selected]]">
125 <div id="main" style$="[[_computeMainStyle(narrow, rightDrawer, drawerWidth)]]">
126 <content select="[main]"></content>
127 <div id="scrim" on-tap="closeDrawer"></div>
128 </div>
130 <div id="drawer" style$="[[_computeDrawerStyle(drawerWidth)]]">
131 <content select="[drawer]"></content>
132 </div>
134 </iron-selector>
135 </template>
137 </dom-module>
139 <script>
141 (function() {
143 'use strict';
145 // this would be the only `paper-drawer-panel` in
146 // the whole app that can be in `dragging` state
147 var sharedPanel = null;
149 function classNames(obj) {
150 var classes = [];
151 for (var key in obj) {
152 if (obj.hasOwnProperty(key) && obj[key]) {
153 classes.push(key);
157 return classes.join(' ');
160 Polymer({
162 is: 'paper-drawer-panel',
165 * Fired when the narrow layout changes.
167 * @event paper-responsive-change {{narrow: boolean}} detail -
168 * narrow: true if the panel is in narrow layout.
172 * Fired when the a panel is selected.
174 * Listening for this event is an alternative to observing changes in the `selected` attribute.
175 * This event is fired both when a panel is selected.
177 * @event iron-select {{item: Object}} detail -
178 * item: The panel that the event refers to.
182 * Fired when a panel is deselected.
184 * Listening for this event is an alternative to observing changes in the `selected` attribute.
185 * This event is fired both when a panel is deselected.
187 * @event iron-deselect {{item: Object}} detail -
188 * item: The panel that the event refers to.
190 properties: {
193 * The panel to be selected when `paper-drawer-panel` changes to narrow
194 * layout.
196 defaultSelected: {
197 type: String,
198 value: 'main'
202 * If true, swipe from the edge is disable.
204 disableEdgeSwipe: {
205 type: Boolean,
206 value: false
210 * If true, swipe to open/close the drawer is disabled.
212 disableSwipe: {
213 type: Boolean,
214 value: false
218 * Whether the user is dragging the drawer interactively.
220 dragging: {
221 type: Boolean,
222 value: false,
223 readOnly: true,
224 notify: true
228 * Width of the drawer panel.
230 drawerWidth: {
231 type: String,
232 value: '256px'
236 * How many pixels on the side of the screen are sensitive to edge
237 * swipes and peek.
239 edgeSwipeSensitivity: {
240 type: Number,
241 value: 30
245 * If true, ignore `responsiveWidth` setting and force the narrow layout.
247 forceNarrow: {
248 type: Boolean,
249 value: false
253 * Whether the browser has support for the transform CSS property.
255 hasTransform: {
256 type: Boolean,
257 value: function() {
258 return 'transform' in this.style;
263 * Whether the browser has support for the will-change CSS property.
265 hasWillChange: {
266 type: Boolean,
267 value: function() {
268 return 'willChange' in this.style;
273 * Returns true if the panel is in narrow layout. This is useful if you
274 * need to show/hide elements based on the layout.
276 narrow: {
277 reflectToAttribute: true,
278 type: Boolean,
279 value: false,
280 readOnly: true,
281 notify: true
285 * Whether the drawer is peeking out from the edge.
287 peeking: {
288 type: Boolean,
289 value: false,
290 readOnly: true,
291 notify: true
295 * Max-width when the panel changes to narrow layout.
297 responsiveWidth: {
298 type: String,
299 value: '640px'
303 * If true, position the drawer to the right.
305 rightDrawer: {
306 type: Boolean,
307 value: false
311 * The panel that is being selected. `drawer` for the drawer panel and
312 * `main` for the main panel.
314 selected: {
315 reflectToAttribute: true,
316 notify: true,
317 type: String,
318 value: null
322 * The attribute on elements that should toggle the drawer on tap, also elements will
323 * automatically be hidden in wide layout.
325 drawerToggleAttribute: {
326 type: String,
327 value: 'paper-drawer-toggle'
331 * Whether the transition is enabled.
333 transition: {
334 type: Boolean,
335 value: false
340 listeners: {
341 tap: '_onTap',
342 track: '_onTrack',
343 down: '_downHandler',
344 up: '_upHandler'
347 observers: [
348 '_forceNarrowChanged(forceNarrow, defaultSelected)'
352 * Toggles the panel open and closed.
354 * @method togglePanel
356 togglePanel: function() {
357 if (this._isMainSelected()) {
358 this.openDrawer();
359 } else {
360 this.closeDrawer();
365 * Opens the drawer.
367 * @method openDrawer
369 openDrawer: function() {
370 this.selected = 'drawer';
374 * Closes the drawer.
376 * @method closeDrawer
378 closeDrawer: function() {
379 this.selected = 'main';
382 ready: function() {
383 // Avoid transition at the beginning e.g. page loads and enable
384 // transitions only after the element is rendered and ready.
385 this.transition = true;
388 _computeIronSelectorClass: function(narrow, transition, dragging, rightDrawer, peeking) {
389 return classNames({
390 dragging: dragging,
391 'narrow-layout': narrow,
392 'right-drawer': rightDrawer,
393 'left-drawer': !rightDrawer,
394 transition: transition,
395 peeking: peeking
399 _computeDrawerStyle: function(drawerWidth) {
400 return 'width:' + drawerWidth + ';';
403 _computeMainStyle: function(narrow, rightDrawer, drawerWidth) {
404 var style = '';
406 style += 'left:' + ((narrow || rightDrawer) ? '0' : drawerWidth) + ';';
408 if (rightDrawer) {
409 style += 'right:' + (narrow ? '' : drawerWidth) + ';';
412 return style;
415 _computeMediaQuery: function(forceNarrow, responsiveWidth) {
416 return forceNarrow ? '' : '(max-width: ' + responsiveWidth + ')';
419 _computeSwipeOverlayHidden: function(narrow, disableEdgeSwipe) {
420 return !narrow || disableEdgeSwipe;
423 _onTrack: function(event) {
424 if (sharedPanel && this !== sharedPanel) {
425 return;
427 switch (event.detail.state) {
428 case 'start':
429 this._trackStart(event);
430 break;
431 case 'track':
432 this._trackX(event);
433 break;
434 case 'end':
435 this._trackEnd(event);
436 break;
441 _responsiveChange: function(narrow) {
442 this._setNarrow(narrow);
444 if (this.narrow) {
445 this.selected = this.defaultSelected;
448 this.setScrollDirection(this._swipeAllowed() ? 'y' : 'all');
449 this.fire('paper-responsive-change', {narrow: this.narrow});
452 _onQueryMatchesChanged: function(event) {
453 this._responsiveChange(event.detail.value);
456 _forceNarrowChanged: function() {
457 // set the narrow mode only if we reached the `responsiveWidth`
458 this._responsiveChange(this.forceNarrow || this.$.mq.queryMatches);
461 _swipeAllowed: function() {
462 return this.narrow && !this.disableSwipe;
465 _isMainSelected: function() {
466 return this.selected === 'main';
469 _startEdgePeek: function() {
470 this.width = this.$.drawer.offsetWidth;
471 this._moveDrawer(this._translateXForDeltaX(this.rightDrawer ?
472 -this.edgeSwipeSensitivity : this.edgeSwipeSensitivity));
473 this._setPeeking(true);
476 _stopEdgePeek: function() {
477 if (this.peeking) {
478 this._setPeeking(false);
479 this._moveDrawer(null);
483 _downHandler: function(event) {
484 if (!this.dragging && this._isMainSelected() && this._isEdgeTouch(event) && !sharedPanel) {
485 this._startEdgePeek();
486 // cancel selection
487 event.preventDefault();
488 // grab this panel
489 sharedPanel = this;
493 _upHandler: function() {
494 this._stopEdgePeek();
495 // release the panel
496 sharedPanel = null;
499 _onTap: function(event) {
500 var targetElement = Polymer.dom(event).localTarget;
501 var isTargetToggleElement = targetElement &&
502 this.drawerToggleAttribute &&
503 targetElement.hasAttribute(this.drawerToggleAttribute);
505 if (isTargetToggleElement) {
506 this.togglePanel();
510 _isEdgeTouch: function(event) {
511 var x = event.detail.x;
513 return !this.disableEdgeSwipe && this._swipeAllowed() &&
514 (this.rightDrawer ?
515 x >= this.offsetWidth - this.edgeSwipeSensitivity :
516 x <= this.edgeSwipeSensitivity);
519 _trackStart: function(event) {
520 if (this._swipeAllowed()) {
521 sharedPanel = this;
522 this._setDragging(true);
524 if (this._isMainSelected()) {
525 this._setDragging(this.peeking || this._isEdgeTouch(event));
528 if (this.dragging) {
529 this.width = this.$.drawer.offsetWidth;
530 this.transition = false;
535 _translateXForDeltaX: function(deltaX) {
536 var isMain = this._isMainSelected();
538 if (this.rightDrawer) {
539 return Math.max(0, isMain ? this.width + deltaX : deltaX);
540 } else {
541 return Math.min(0, isMain ? deltaX - this.width : deltaX);
545 _trackX: function(event) {
546 if (this.dragging) {
547 var dx = event.detail.dx;
549 if (this.peeking) {
550 if (Math.abs(dx) <= this.edgeSwipeSensitivity) {
551 // Ignore trackx until we move past the edge peek.
552 return;
554 this._setPeeking(false);
557 this._moveDrawer(this._translateXForDeltaX(dx));
561 _trackEnd: function(event) {
562 if (this.dragging) {
563 var xDirection = event.detail.dx > 0;
565 this._setDragging(false);
566 this.transition = true;
567 sharedPanel = null;
568 this._moveDrawer(null);
570 if (this.rightDrawer) {
571 this[xDirection ? 'closeDrawer' : 'openDrawer']();
572 } else {
573 this[xDirection ? 'openDrawer' : 'closeDrawer']();
578 _transformForTranslateX: function(translateX) {
579 if (translateX === null) {
580 return '';
583 return this.hasWillChange ? 'translateX(' + translateX + 'px)' :
584 'translate3d(' + translateX + 'px, 0, 0)';
587 _moveDrawer: function(translateX) {
588 this.transform(this._transformForTranslateX(translateX), this.$.drawer);
593 }());
595 </script>