options_page.js revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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
5cr.define('options', function() {
6  /////////////////////////////////////////////////////////////////////////////
7  // OptionsPage class:
8
9  /**
10   * Base class for options page.
11   * @constructor
12   * @param {string} name Options page name, also defines id of the div element
13   *     containing the options view and the name of options page navigation bar
14   *     item as name+'PageNav'.
15   * @param {string} title Options page title, used for navigation bar
16   * @extends {EventTarget}
17   */
18  function OptionsPage(name, title, pageDivName) {
19    this.name = name;
20    this.title = title;
21    this.pageDivName = pageDivName;
22    this.pageDiv = $(this.pageDivName);
23    this.tab = null;
24    this.managed = false;
25  }
26
27  OptionsPage.registeredPages_ = {};
28
29  /**
30   * Pages which are meant to have an entry in the nav, but
31   * not have a permanent entry.
32   */
33  OptionsPage.registeredSubPages_ = {};
34
35  /**
36   * Pages which are meant to behave like model dialogs.
37   */
38  OptionsPage.registeredOverlayPages_ = {};
39
40  /**
41   * Shows a registered page.
42   * @param {string} pageName Page name.
43   */
44  OptionsPage.showPageByName = function(pageName) {
45    for (var name in OptionsPage.registeredPages_) {
46      var page = OptionsPage.registeredPages_[name];
47      page.visible = name == pageName;
48    }
49  };
50
51  /**
52   * Called on load. Dispatch the URL hash to the given page's handleHash
53   * function.
54   * @param {string} pageName The string name of the (registered) options page.
55   * @param {string} hash The value of the hash component of the URL.
56   */
57  OptionsPage.handleHashForPage = function(pageName, hash) {
58    OptionsPage.registeredPages_[pageName].handleHash(hash);
59  };
60
61  /**
62   * Shows a registered Overlay page.
63   * @param {string} overlayName Page name.
64   */
65  OptionsPage.showOverlay = function(overlayName) {
66    if (OptionsPage.registeredOverlayPages_[overlayName]) {
67      OptionsPage.registeredOverlayPages_[overlayName].visible = true;
68    }
69  };
70
71  OptionsPage.clearOverlays = function() {
72     for (var name in OptionsPage.registeredOverlayPages_) {
73       var page = OptionsPage.registeredOverlayPages_[name];
74       page.visible = false;
75     }
76  };
77
78  /**
79  * Shows the tab contents for the given navigation tab.
80  * @param {!Element} tab The tab that the user clicked.
81  */
82  OptionsPage.showTab = function(tab) {
83    if (!tab.classList.contains('inactive-tab'))
84      return;
85
86    if (this.activeNavTab != null) {
87      this.activeNavTab.classList.remove('active-tab');
88      $(this.activeNavTab.getAttribute('tab-contents')).classList.
89          remove('active-tab-contents');
90    }
91
92    tab.classList.add('active-tab');
93    $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents');
94    this.activeNavTab = tab;
95  }
96
97  /**
98   * Registers new options page.
99   * @param {OptionsPage} page Page to register.
100   */
101  OptionsPage.register = function(page) {
102    OptionsPage.registeredPages_[page.name] = page;
103    // Create and add new page <li> element to navbar.
104    var pageNav = document.createElement('li');
105    pageNav.id = page.name + 'PageNav';
106    pageNav.className = 'navbar-item';
107    pageNav.setAttribute('pageName', page.name);
108    pageNav.textContent = page.title;
109    pageNav.tabIndex = 0;
110    pageNav.onclick = function(event) {
111      OptionsPage.showPageByName(this.getAttribute('pageName'));
112    };
113    pageNav.onkeypress = function(event) {
114      // Enter or space
115      if (event.keyCode == 13 || event.keyCode == 32) {
116        OptionsPage.showPageByName(this.getAttribute('pageName'));
117      }
118    };
119    var navbar = $('navbar');
120    navbar.appendChild(pageNav);
121    page.tab = pageNav;
122    page.initializePage();
123  };
124
125  /**
126   * Registers a new Sub tab page.
127   * @param {OptionsPage} page Page to register.
128   */
129  OptionsPage.registerSubPage = function(page) {
130    OptionsPage.registeredPages_[page.name] = page;
131    var pageNav = document.createElement('li');
132    pageNav.id = page.name + 'PageNav';
133    pageNav.className = 'navbar-item hidden';
134    pageNav.setAttribute('pageName', page.name);
135    pageNav.textContent = page.title;
136    var subpagesnav = $('subpagesnav');
137    subpagesnav.appendChild(pageNav);
138    page.tab = pageNav;
139    page.initializePage();
140  };
141
142  /**
143   * Registers a new Overlay page.
144   * @param {OptionsPage} page Page to register, must be a class derived from
145   * OptionsPage.
146   */
147  OptionsPage.registerOverlay = function(page) {
148    OptionsPage.registeredOverlayPages_[page.name] = page;
149    page.tab = undefined;
150    page.isOverlay = true;
151    page.initializePage();
152  };
153
154  /**
155   * Callback for window.onpopstate.
156   * @param {Object} data State data pushed into history.
157   */
158  OptionsPage.setState = function(data) {
159    if (data && data.pageName) {
160      OptionsPage.showPageByName(data.pageName);
161    }
162  };
163
164  /**
165   * Initializes the complete options page.  This will cause
166   * all C++ handlers to be invoked to do final setup.
167   */
168  OptionsPage.initialize = function() {
169    chrome.send('coreOptionsInitialize');
170  };
171
172  OptionsPage.prototype = {
173    __proto__: cr.EventTarget.prototype,
174
175    /**
176     * Initializes page content.
177     */
178    initializePage: function() {},
179
180    /**
181     * Sets managed banner visibility state.
182     */
183    setManagedBannerVisibility: function(visible) {
184      this.managed = visible;
185      if (this.visible) {
186        $('managed-prefs-banner').style.display = visible ? 'block' : 'none';
187      }
188    },
189
190    /**
191     * Gets page visibility state.
192     */
193    get visible() {
194      var page = $(this.pageDivName);
195      return page && page.ownerDocument.defaultView.getComputedStyle(
196          page).display == 'block';
197    },
198
199    /**
200     * Sets page visibility.
201     */
202    set visible(visible) {
203      if ((this.visible && visible) || (!this.visible && !visible))
204        return;
205
206      if (visible) {
207        this.pageDiv.style.display = 'block';
208        if (this.isOverlay) {
209          var overlay = $('overlay');
210          overlay.classList.remove('hidden');
211        } else {
212          var banner = $('managed-prefs-banner');
213          banner.style.display = this.managed ? 'block' : 'none';
214
215          // Recent webkit change no longer allows url change from "chrome://".
216          window.history.pushState({pageName: this.name},
217                                   this.title);
218        }
219        if (this.tab) {
220          this.tab.classList.add('navbar-item-selected');
221          if (this.tab.parentNode && this.tab.parentNode.id == 'subpagesnav')
222            this.tab.classList.remove('hidden');
223        }
224      } else {
225        if (this.isOverlay) {
226          var overlay = $('overlay');
227          overlay.classList.add('hidden');
228        }
229        this.pageDiv.style.display = 'none';
230        if (this.tab) {
231          this.tab.classList.remove('navbar-item-selected');
232          if (this.tab.parentNode && this.tab.parentNode.id == 'subpagesnav')
233            this.tab.classList.add('hidden');
234        }
235      }
236
237      cr.dispatchPropertyChange(this, 'visible', visible, !visible);
238    },
239
240    /**
241     * Handles a hash value in the URL (such as bar in
242     * chrome://options/foo#bar). Called on page load. By default, this shows
243     * an overlay that matches the hash name, but can be overriden by individual
244     * OptionsPage subclasses to get other behavior.
245     * @param {string} hash The hash value.
246     */
247    handleHash: function(hash) {
248      OptionsPage.showOverlay(hash);
249    },
250  };
251
252  // Export
253  return {
254    OptionsPage: OptionsPage
255  };
256
257});
258