1 // Copyright 2014 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.
5 cr.define('extensions', function() {
9 * The ExtensionOptionsOverlay will show an extension's options page using
10 * an <extensionoptions> element.
13 function ExtensionOptionsOverlay() {}
15 cr.addSingletonGetter(ExtensionOptionsOverlay);
17 ExtensionOptionsOverlay.prototype = {
19 * The function that shows the given element in the overlay.
20 * @type {?function(HTMLDivElement)} Function that receives the element to
21 * show in the overlay.
27 * Initialize the page.
28 * @param {function(HTMLDivElement)} showOverlay The function to show or
29 * hide the ExtensionOptionsOverlay; this should take a single parameter
30 * which is either the overlay Div if the overlay should be displayed,
31 * or null if the overlay should be hidden.
33 initializePage: function(showOverlay) {
34 var overlay = $('overlay');
36 cr.ui.overlay.setupOverlay(overlay);
37 cr.ui.overlay.globalInitialization();
38 overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this));
40 this.showOverlay_ = showOverlay;
43 setInitialFocus: function() {
44 this.getExtensionOptions_().focus();
51 getExtensionOptions_: function() {
52 return $('extension-options-overlay-guest').querySelector(
57 * Handles a click on the close button.
58 * @param {Event} event The click event.
61 handleDismiss_: function(event) {
62 this.setVisible_(false);
63 var extensionoptions = this.getExtensionOptions_();
65 $('extension-options-overlay-guest').removeChild(extensionoptions);
67 $('extension-options-overlay-icon').removeAttribute('src');
69 // Remove the options query string.
70 uber.replaceState({}, '');
74 * Associate an extension with the overlay and display it.
75 * @param {string} extensionId The id of the extension whose options page
76 * should be displayed in the overlay.
77 * @param {string} extensionName The name of the extension, which is used
78 * as the header of the overlay.
79 * @param {string} extensionIcon The URL of the extension's icon.
80 * @param {function():void} shownCallback A function called when
82 * @suppress {checkTypes}
83 * TODO(vitalyp): remove the suppression after adding
84 * chrome/renderer/resources/extensions/extension_options.js
87 setExtensionAndShowOverlay: function(extensionId,
91 var overlay = $('extension-options-overlay');
92 var overlayHeader = $('extension-options-overlay-header');
93 var overlayGuest = $('extension-options-overlay-guest');
94 var overlayStyle = window.getComputedStyle(overlay);
96 $('extension-options-overlay-title').textContent = extensionName;
97 $('extension-options-overlay-icon').src = extensionIcon;
99 this.setVisible_(true);
101 var extensionoptions = new window.ExtensionOptions();
102 extensionoptions.extension = extensionId;
104 // The <extensionoptions> content's size needs to be restricted to the
105 // bounds of the overlay window. The overlay gives a minWidth and
106 // maxHeight, but the maxHeight does not include our header height (title
107 // and close button), so we need to subtract that to get the maxHeight
108 // for the extension options.
109 var maxHeight = parseInt(overlay.style.maxHeight, 10) -
110 overlayHeader.offsetHeight;
111 var minWidth = parseInt(overlayStyle.minWidth, 10);
113 extensionoptions.onclose = function() {
114 cr.dispatchSimpleEvent($('overlay'), 'cancelOverlay');
117 // Track the current animation (used to grow/shrink the overlay content),
118 // if any. Preferred size changes can fire more rapidly than the
119 // animation speed, and multiple animations running at the same time has
120 // undesirable effects.
121 var animation = null;
124 * Resize the overlay if the <extensionoptions> changes preferred size.
125 * @param {{width: number, height: number}} evt
127 extensionoptions.onpreferredsizechanged = function(evt) {
128 var oldWidth = parseInt(overlayStyle.width, 10);
129 var oldHeight = parseInt(overlayStyle.height, 10);
130 // The overlay must be slightly larger than the extension options to
131 // avoid creating scrollbars.
132 // TODO(paulmeyer): This shouldn't be necessary, but the preferred size
133 // (coming from Blink) seems to be too small for some zoom levels. The
134 // 2-pixel addition should be removed once this problem is investigated
136 var newWidth = Math.max(evt.width + 2, minWidth);
137 var newHeight = Math.min(evt.height + 2, maxHeight);
139 // animationTime is the amount of time in ms that will be used to resize
140 // the overlay. It is calculated by multiplying the pythagorean distance
141 // between old and the new size (in px) with a constant speed of
143 var loading = document.documentElement.classList.contains('loading');
144 var animationTime = loading ? 0 :
145 0.25 * Math.sqrt(Math.pow(newWidth - oldWidth, 2) +
146 Math.pow(newHeight - oldHeight, 2));
151 animation = overlay.animate([
152 {width: oldWidth + 'px', height: oldHeight + 'px'},
153 {width: newWidth + 'px', height: newHeight + 'px'}
155 duration: animationTime,
159 animation.onfinish = function(e) {
162 // The <extensionoptions> element is ready to place back in the
163 // overlay. Make sure that it's sized to take up the full width/height
165 overlayGuest.style.position = '';
166 overlayGuest.style.left = '';
167 overlayGuest.style.width = newWidth + 'px';
168 overlayGuest.style.height = newHeight + 'px';
172 shownCallback = null;
177 // Move the <extensionoptions> off screen until the overlay is ready.
178 overlayGuest.style.position = 'fixed';
179 overlayGuest.style.left = window.outerWidth + 'px';
180 // Begin rendering at the default dimensions. This is also necessary to
181 // cancel any width/height set on a previous render.
182 // TODO(kalman): This causes a visual jag where the overlay guest shows
183 // up briefly. It would be better to render this off-screen first, then
184 // swap it in place. See crbug.com/408274.
185 // This may also solve crbug.com/431001 (width is 0 on initial render).
186 overlayGuest.style.width = '';
187 overlayGuest.style.height = '';
189 overlayGuest.appendChild(extensionoptions);
193 * Toggles the visibility of the ExtensionOptionsOverlay.
194 * @param {boolean} isVisible Whether the overlay should be visible.
197 setVisible_: function(isVisible) {
198 this.showOverlay_(isVisible ?
199 /** @type {HTMLDivElement} */($('extension-options-overlay')) :
206 ExtensionOptionsOverlay: ExtensionOptionsOverlay