Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / webui / resources / js / cr / ui / overlay.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview Provides dialog-like behaviors for the tracing UI.
7  */
8 cr.define('cr.ui.overlay', function() {
9   /**
10    * Gets the top, visible overlay. It makes the assumption that if multiple
11    * overlays are visible, the last in the byte order is topmost.
12    * TODO(estade): rely on aria-visibility instead?
13    * @return {HTMLElement} The overlay.
14    */
15   function getTopOverlay() {
16     var overlays = document.querySelectorAll('.overlay:not([hidden])');
17     return overlays[overlays.length - 1];
18   }
19
20   /**
21    * Returns a visible default button of the overlay, if it has one. If the
22    * overlay has more than one, the first one will be returned.
23    *
24    * @param {HTMLElement} overlay The .overlay.
25    * @return {HTMLElement} The default button.
26    */
27   function getDefaultButton(overlay) {
28     function isHidden(node) { return node.hidden; }
29     var defaultButtons =
30         overlay.querySelectorAll('.page .button-strip > .default-button');
31     for (var i = 0; i < defaultButtons.length; i++) {
32       if (!findAncestor(defaultButtons[i], isHidden))
33         return defaultButtons[i];
34     }
35     return null;
36   }
37
38   /** @type {boolean} */
39   var globallyInitialized = false;
40
41   /**
42    * Makes initializations which must hook at the document level.
43    */
44   function globalInitialization() {
45     if (!globallyInitialized) {
46       document.addEventListener('keydown', function(e) {
47         var overlay = getTopOverlay();
48         if (!overlay)
49           return;
50
51         // Close the overlay on escape.
52         if (e.keyIdentifier == 'U+001B')
53           cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
54
55         // Execute the overlay's default button on enter, unless focus is on an
56         // element that has standard behavior for the enter key.
57         var forbiddenTagNames = /^(A|BUTTON|SELECT|TEXTAREA)$/;
58         if (e.keyIdentifier == 'Enter' &&
59             !forbiddenTagNames.test(document.activeElement.tagName)) {
60           var button = getDefaultButton(overlay);
61           if (button) {
62             button.click();
63             // Executing the default button may result in focus moving to a
64             // different button. Calling preventDefault is necessary to not have
65             // that button execute as well.
66             e.preventDefault();
67           }
68         }
69       });
70
71       window.addEventListener('resize', setMaxHeightAllPages);
72       globallyInitialized = true;
73     }
74
75     setMaxHeightAllPages();
76   }
77
78   /**
79    * Sets the max-height of all pages in all overlays, based on the window
80    * height.
81    */
82   function setMaxHeightAllPages() {
83     var pages = document.querySelectorAll(
84         '.overlay .page:not(.not-resizable)');
85
86     var maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';
87     for (var i = 0; i < pages.length; i++)
88       pages[i].style.maxHeight = maxHeight;
89   }
90
91   /**
92    * Adds behavioral hooks for the given overlay.
93    * @param {HTMLElement} overlay The .overlay.
94    */
95   function setupOverlay(overlay) {
96     // Close the overlay on clicking any of the pages' close buttons.
97     var closeButtons = overlay.querySelectorAll('.page > .close-button');
98     for (var i = 0; i < closeButtons.length; i++) {
99       closeButtons[i].addEventListener('click', function(e) {
100         cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
101       });
102     }
103
104     // Remove the 'pulse' animation any time the overlay is hidden or shown.
105     overlay.__defineSetter__('hidden', function(value) {
106       this.classList.remove('pulse');
107       if (value)
108         this.setAttribute('hidden', true);
109       else
110         this.removeAttribute('hidden');
111     });
112     overlay.__defineGetter__('hidden', function() {
113       return this.hasAttribute('hidden');
114     });
115
116     // Shake when the user clicks away.
117     overlay.addEventListener('click', function(e) {
118       // Only pulse if the overlay was the target of the click.
119       if (this != e.target)
120         return;
121
122       // This may be null while the overlay is closing.
123       var overlayPage = this.querySelector('.page:not([hidden])');
124       if (overlayPage)
125         overlayPage.classList.add('pulse');
126     });
127     overlay.addEventListener('webkitAnimationEnd', function(e) {
128       e.target.classList.remove('pulse');
129     });
130   }
131
132   return {
133     globalInitialization: globalInitialization,
134     setupOverlay: setupOverlay,
135   };
136 });