diff options
Diffstat (limited to 'chromium/chrome/browser/resources/chromeos/menu.js')
-rw-r--r-- | chromium/chrome/browser/resources/chromeos/menu.js | 670 |
1 files changed, 0 insertions, 670 deletions
diff --git a/chromium/chrome/browser/resources/chromeos/menu.js b/chromium/chrome/browser/resources/chromeos/menu.js deleted file mode 100644 index 598e58bfdc3..00000000000 --- a/chromium/chrome/browser/resources/chromeos/menu.js +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// How long to wait to open submenu when mouse hovers. -var SUBMENU_OPEN_DELAY_MS = 200; -// How long to wait to close submenu when mouse left. -var SUBMENU_CLOSE_DELAY_MS = 500; -// Scroll repeat interval. -var SCROLL_INTERVAL_MS = 20; -// Scrolling amount in pixel. -var SCROLL_TICK_PX = 4; -// Regular expression to match/find mnemonic key. -var MNEMONIC_REGEXP = /([^&]*)&(.)(.*)/; - -var localStrings = new LocalStrings(); - -/** - * Sends 'activate' WebUI message. - * @param {number} index The index of menu item to activate in menu model. - * @param {string} mode The activation mode, one of 'close_and_activate', or - * 'activate_no_close'. - * TODO(oshima): change these string to enum numbers once it becomes possible - * to pass number to C++. - */ -function sendActivate(index, mode) { - chrome.send('activate', [String(index), mode]); -} - -/** - * MenuItem class. - */ -var MenuItem = cr.ui.define('div'); - -MenuItem.prototype = { - __proto__: HTMLDivElement.prototype, - - /** - * Decorates the menu item element. - */ - decorate: function() { - this.className = 'menu-item'; - }, - - /** - * Initialize the MenuItem. - * @param {Menu} menu A {@code Menu} object to which this menu item - * will be added to. - * @param {Object} attrs JSON object that represents this menu items - * properties. This is created from menu model in C code. See - * chromeos/views/native_menu_webui.cc. - * @param {Object} model The model object. - */ - init: function(menu, attrs, model) { - // The left icon's width. 0 if no icon. - var leftIconWidth = model.maxIconWidth; - this.menu_ = menu; - this.attrs = attrs; - var attrs = this.attrs; - if (attrs.type == 'separator') { - this.className = 'separator'; - } else if (attrs.type == 'command' || - attrs.type == 'submenu' || - attrs.type == 'check' || - attrs.type == 'radio') { - this.initMenuItem_(); - this.initPadding_(leftIconWidth); - } else { - // This should not happend. - this.classList.add('disabled'); - this.textContent = 'unknown'; - } - - menu.appendChild(this); - if (!attrs.visible) { - this.classList.add('hidden'); - } - }, - - /** - * Changes the selection state of the menu item. - * @param {boolean} selected True to set the selection, or false - * otherwise. - */ - set selected(selected) { - if (selected) { - this.classList.add('selected'); - this.menu_.selectedItem = this; - } else { - this.classList.remove('selected'); - } - }, - - /** - * Activate the menu item. - */ - activate: function() { - if (this.attrs.type == 'submenu') { - this.menu_.openSubmenu(this); - } else if (this.attrs.type != 'separator' && - this.className.indexOf('selected') >= 0) { - sendActivate(this.menu_.getMenuItemIndexOf(this), - 'close_and_activate'); - } - }, - - /** - * Sends open_submenu WebUI message. - */ - sendOpenSubmenuCommand: function() { - chrome.send('open_submenu', - [String(this.menu_.getMenuItemIndexOf(this)), - String(this.getBoundingClientRect().top)]); - }, - - /** - * Internal method to initiailze the MenuItem. - * @private - */ - initMenuItem_: function() { - var attrs = this.attrs; - this.className = 'menu-item ' + attrs.type; - this.menu_.addHandlers(this, this); - var label = document.createElement('div'); - - label.className = 'menu-label'; - this.menu_.addLabelTo(this, attrs.label, label, - true /* enable mnemonic */); - - if (attrs.font) { - label.style.font = attrs.font; - } - this.appendChild(label); - - - if (attrs.accel) { - var accel = document.createElement('div'); - accel.className = 'accelerator'; - accel.textContent = attrs.accel; - accel.style.font = attrs.font; - this.appendChild(accel); - } - - if (attrs.type == 'submenu') { - // This overrides left-icon's position, but it's OK as submenu - // shoudln't have left-icon. - this.classList.add('right-icon'); - this.style.backgroundImage = 'url(' + this.menu_.config_.arrowUrl + ')'; - } - }, - - initPadding_: function(leftIconWidth) { - if (leftIconWidth <= 0) { - this.classList.add('no-icon'); - return; - } - this.classList.add('left-icon'); - - var url; - var attrs = this.attrs; - if (attrs.type == 'radio') { - url = attrs.checked ? - this.menu_.config_.radioOnUrl : - this.menu_.config_.radioOffUrl; - } else if (attrs.icon) { - url = attrs.icon; - } else if (attrs.type == 'check' && attrs.checked) { - url = this.menu_.config_.checkUrl; - } - if (url) { - this.style.backgroundImage = 'url(' + url + ')'; - } - // TODO(oshima): figure out how to update left padding in rule. - // 4 is the padding on left side of icon. - var padding = - 4 + leftIconWidth + this.menu_.config_.icon_to_label_padding; - this.style.WebkitPaddingStart = padding + 'px'; - }, -}; - -/** - * Menu class. - */ -var Menu = cr.ui.define('div'); - -Menu.prototype = { - __proto__: HTMLDivElement.prototype, - - /** - * Configuration object. - * @type {Object} - */ - config_: null, - - /** - * Currently selected menu item. - * @type {MenuItem} - */ - current_: null, - - /** - * Timers for opening/closing submenu. - * @type {number} - */ - openSubmenuTimer_: 0, - closeSubmenuTimer_: 0, - - /** - * Auto scroll timer. - * @type {number} - */ - scrollTimer_: 0, - - /** - * Pointer to a submenu currently shown, if any. - * @type {MenuItem} - */ - submenuShown_: null, - - /** - * True if this menu is root. - * @type {boolean} - */ - isRoot_: false, - - /** - * Total hight of scroll buttons. Used to adjust the height of - * viewport in order to show scroll bottons without scrollbar. - * @type {number} - */ - buttonHeight_: 0, - - /** - * True to enable scroll button. - * @type {boolean} - */ - scrollEnabled: false, - - /** - * Decorates the menu element. - */ - decorate: function() { - this.id = 'viewport'; - }, - - /** - * Initialize the menu. - * @param {Object} config Configuration parameters in JSON format. - * See chromeos/views/native_menu_webui.cc for details. - */ - init: function(config) { - // List of menu items - this.items_ = []; - // Map from mnemonic character to item to activate - this.mnemonics_ = {}; - - this.config_ = config; - this.addEventListener('mouseout', this.onMouseout_.bind(this)); - - document.addEventListener('keydown', this.onKeydown_.bind(this)); - document.addEventListener('keypress', this.onKeypress_.bind(this)); - document.addEventListener('mousewheel', this.onMouseWheel_.bind(this)); - window.addEventListener('resize', this.onResize_.bind(this)); - - // Setup scroll events. - var up = $('scroll-up'); - var down = $('scroll-down'); - up.addEventListener('mouseout', this.stopScroll_.bind(this)); - down.addEventListener('mouseout', this.stopScroll_.bind(this)); - var menu = this; - up.addEventListener('mouseover', - function() { - menu.autoScroll_(-SCROLL_TICK_PX); - }); - down.addEventListener('mouseover', - function() { - menu.autoScroll_(SCROLL_TICK_PX); - }); - - this.buttonHeight_ = - up.getBoundingClientRect().height + - down.getBoundingClientRect().height; - }, - - /** - * Adds a label to {@code targetDiv}. A label may contain - * mnemonic key, preceded by '&'. - * @param {MenuItem} item The menu item to be activated by mnemonic - * key. - * @param {string} label The label string to be added to - * {@code targetDiv}. - * @param {HTMLElement} div The div element the label is added to. - * @param {boolean} enableMnemonic True to enable mnemonic, or false - * to not to interprete mnemonic key. The function removes '&' - * from the label in both cases. - */ - addLabelTo: function(item, label, targetDiv, enableMnemonic) { - var mnemonic = MNEMONIC_REGEXP.exec(label); - if (mnemonic && enableMnemonic) { - var c = mnemonic[2].toLowerCase(); - this.mnemonics_[c] = item; - } - if (!mnemonic) { - targetDiv.textContent = label; - } else if (enableMnemonic) { - targetDiv.appendChild(document.createTextNode(mnemonic[1])); - targetDiv.appendChild(document.createElement('span')); - targetDiv.appendChild(document.createTextNode(mnemonic[3])); - targetDiv.childNodes[1].className = 'mnemonic'; - targetDiv.childNodes[1].textContent = mnemonic[2]; - } else { - targetDiv.textContent = mnemonic.splice(1, 3).join(''); - } - }, - - /** - * @return {number} The index of the {@code item}. - */ - getMenuItemIndexOf: function(item) { - return this.items_.indexOf(item); - }, - - /** - * A template method to create an item object. It can be a subclass - * of MenuItem, or any HTMLElement that implements {@code init}, - * {@code activate} methods as well as {@code selected} attribute. - * @param {Object} attrs The menu item's properties passed from C++. - * @return {MenuItem} The created menu item. - */ - createMenuItem: function(attrs) { - return new MenuItem(); - }, - - /** - * Update and display the new model. - */ - updateModel: function(model) { - this.isRoot = model.isRoot; - this.current_ = null; - this.items_ = []; - this.mnemonics_ = {}; - this.innerHTML = ''; // remove menu items - - for (var i = 0; i < model.items.length; i++) { - var attrs = model.items[i]; - var item = this.createMenuItem(attrs); - item.init(this, attrs, model); - this.items_.push(item); - } - this.onResize_(); - }, - - /** - * Highlights the currently selected item, or - * select the 1st selectable item if none is selected. - */ - showSelection: function() { - if (this.current_) { - this.current_.selected = true; - } else { - this.findNextEnabled_(1).selected = true; - } - }, - - /** - * Add event handlers for the item. - */ - addHandlers: function(item, target) { - var menu = this; - target.addEventListener('mouseover', function(event) { - menu.onMouseover_(event, item); - }); - if (item.attrs.enabled) { - target.addEventListener('mouseup', function(event) { - menu.onClick_(event, item); - }); - } else { - target.classList.add('disabled'); - } - }, - - /** - * Set the selected item. This controls timers to open/close submenus. - * 1) If the selected menu is submenu, and that submenu is not yet opeend, - * start timer to open. This will not cancel close timer, so - * if there is a submenu opened, it will be closed before new submenu is - * open. - * 2) If the selected menu is submenu, and that submenu is already opened, - * cancel both open/close timer. - * 3) If the selected menu is not submenu, cancel all timers and start - * timer to close submenu. - * This prevents from opening/closing menus while you're actively - * navigating menus. To open submenu, you need to wait a bit, or click - * submenu. - * - * @param {MenuItem} item The selected item. - */ - set selectedItem(item) { - if (this.current_ != item) { - if (this.current_ != null) - this.current_.selected = false; - this.current_ = item; - this.makeSelectedItemVisible_(); - } - - var menu = this; - if (item.attrs.type == 'submenu') { - if (this.submenuShown_ != item) { - this.openSubmenuTimer_ = - setTimeout( - function() { - menu.openSubmenu(item); - }, - SUBMENU_OPEN_DELAY_MS); - } else { - this.cancelSubmenuTimer_(); - } - } else if (this.submenuShown_) { - this.cancelSubmenuTimer_(); - this.closeSubmenuTimer_ = - setTimeout( - function() { - menu.closeSubmenu_(item); - }, - SUBMENU_CLOSE_DELAY_MS); - } - }, - - /** - * Open submenu {@code item}. It does nothing if the submenu is - * already opened. - * @param {MenuItem} item The submenu item to open. - */ - openSubmenu: function(item) { - this.cancelSubmenuTimer_(); - if (this.submenuShown_ != item) { - this.submenuShown_ = item; - item.sendOpenSubmenuCommand(); - } - }, - - /** - * Handle keyboard navigation and activation. - * @private - */ - onKeydown_: function(event) { - switch (event.keyIdentifier) { - case 'Left': - this.moveToParent_(); - break; - case 'Right': - this.moveToSubmenu_(); - break; - case 'Up': - this.classList.add('mnemonic-enabled'); - this.findNextEnabled_(-1).selected = true; - break; - case 'Down': - this.classList.add('mnemonic-enabled'); - this.findNextEnabled_(1).selected = true; - break; - case 'U+0009': // tab - break; - case 'U+001B': // escape - chrome.send('close_all'); - break; - case 'Enter': - case 'U+0020': // space - if (this.current_) { - this.current_.activate(); - } - break; - } - }, - - /** - * Handle mnemonic keys. - * @private - */ - onKeypress_: function(event) { - // Handles mnemonic. - var c = String.fromCharCode(event.keyCode); - var item = this.mnemonics_[c.toLowerCase()]; - if (item) { - item.selected = true; - item.activate(); - } - }, - - // Mouse Event handlers - onClick_: function(event, item) { - item.activate(); - }, - - onMouseover_: function(event, item) { - this.cancelSubmenuTimer_(); - // Ignore false mouseover event at (0,0) which is - // emitted when opening submenu. - if (item.attrs.enabled && event.clientX != 0 && event.clientY != 0) { - item.selected = true; - } - }, - - onMouseout_: function(event) { - if (this.current_) { - this.current_.selected = false; - } - }, - - onResize_: function() { - var up = $('scroll-up'); - var down = $('scroll-down'); - // this needs to be < 2 as empty page has height of 1. - if (window.innerHeight < 2) { - // menu window is not visible yet. just hide buttons. - up.classList.add('hidden'); - down.classList.add('hidden'); - return; - } - // Do not use screen width to determin if we need scroll buttons - // as the max renderer hight can be shorter than actual screen size. - // TODO(oshima): Fix this when we implement transparent renderer. - if (this.scrollHeight > window.innerHeight && this.scrollEnabled) { - this.style.height = (window.innerHeight - this.buttonHeight_) + 'px'; - up.classList.remove('hidden'); - down.classList.remove('hidden'); - } else { - this.style.height = ''; - up.classList.add('hidden'); - down.classList.add('hidden'); - } - }, - - onMouseWheel_: function(event) { - var delta = event.wheelDelta / 5; - this.scrollTop -= delta; - }, - - /** - * Closes the submenu. - * a submenu. - * @private - */ - closeSubmenu_: function(item) { - this.submenuShown_ = null; - this.cancelSubmenuTimer_(); - chrome.send('close_submenu'); - }, - - /** - * Move the selection to parent menu if the current menu is - * a submenu. - * @private - */ - moveToParent_: function() { - if (!this.isRoot) { - if (this.current_) { - this.current_.selected = false; - } - chrome.send('move_to_parent'); - } - }, - - /** - * Move the selection to submenu if the currently selected - * menu is a submenu. - * @private - */ - moveToSubmenu_: function() { - var current = this.current_; - if (current && current.attrs.type == 'submenu') { - this.openSubmenu(current); - chrome.send('move_to_submenu'); - } - }, - - /** - * Finds the next selectable item. If nothing is selected, the first - * selectable item will be chosen. Returns null if nothing is selectable. - * @param {number} incr Specifies the direction to search, 1 to - * downwards and -1 for upwards. - * @private - * @return {MenuItem} The next selectable item. - */ - findNextEnabled_: function(incr) { - var len = this.items_.length; - var index; - if (this.current_) { - index = this.getMenuItemIndexOf(this.current_); - } else { - index = incr > 0 ? -1 : len; - } - for (var i = 0; i < len; i++) { - index = (index + incr + len) % len; - var item = this.items_[index]; - if (item.attrs.enabled && item.attrs.type != 'separator' && - !item.classList.contains('hidden')) - return item; - } - return null; - }, - - /** - * Cancels timers to open/close submenus. - * @private - */ - cancelSubmenuTimer_: function() { - clearTimeout(this.openSubmenuTimer_); - this.openSubmenuTimer_ = 0; - clearTimeout(this.closeSubmenuTimer_); - this.closeSubmenuTimer_ = 0; - }, - - /** - * Starts auto scroll. - * @param {number} tick The number of pixels to scroll. - * @private - */ - autoScroll_: function(tick) { - var previous = this.scrollTop; - this.scrollTop += tick; - var menu = this; - this.scrollTimer_ = setTimeout( - function() { - menu.autoScroll_(tick); - }, - SCROLL_INTERVAL_MS); - }, - - /** - * Stops auto scroll. - * @private - */ - stopScroll_: function() { - clearTimeout(this.scrollTimer_); - this.scrollTimer_ = 0; - }, - - /** - * Scrolls the viewport to make the selected item visible. - * @private - */ - makeSelectedItemVisible_: function() { - this.current_.scrollIntoViewIfNeeded(false); - }, -}; - -/** - * functions to be called from C++. - * @param {Object} config The viewport configuration. - */ -function init(config) { - $('viewport').init(config); -} - -function selectItem() { - $('viewport').showSelection(); -} - -function updateModel(model) { - $('viewport').updateModel(model); -} - -function modelUpdated() { - chrome.send('model_updated'); -} - -function enableScroll(enabled) { - $('viewport').scrollEnabled = enabled; -} |