diff options
Diffstat (limited to 'apps/system/js/list_menu.js')
-rw-r--r-- | apps/system/js/list_menu.js | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/apps/system/js/list_menu.js b/apps/system/js/list_menu.js new file mode 100644 index 0000000..303fafe --- /dev/null +++ b/apps/system/js/list_menu.js @@ -0,0 +1,180 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +'use strict'; + +var ListMenu = { + get element() { + delete this.element; + return this.element = document.getElementById('listmenu'); + }, + + get container() { + delete this.container; + return this.container = document.querySelector('#listmenu menu'); + }, + + get visible() { + return this.element.classList.contains('visible'); + }, + + // Listen to click event only + init: function lm_init() { + window.addEventListener('click', this, true); + window.addEventListener('screenchange', this, true); + window.addEventListener('home', this); + window.addEventListener('holdhome', this); + }, + + // Pass an array of list items and handler for clicking on the items + // Modified to fit contextmenu use case, loop into the menu items + request: function lm_request(listItems, title, successCb, errorCb) { + this.container.innerHTML = ''; + this.currentLevel = 0; + this.internalList = []; + this.setTitle(title); + this.buildMenu(listItems); + this.internalList.forEach(function render_item(item) { + this.container.appendChild(item); + }, this); + + this.onreturn = successCb || function() {}; + this.oncancel = errorCb || function() {}; + + this.show(); + }, + + buildMenu: function lm_buildMenu(items) { + var containerDiv = document.createElement('ul'); + var _ = navigator.mozL10n.get; + + if (this.currentLevel === 0) { + containerDiv.classList.add('list-menu-root'); + containerDiv.id = 'list-menu-root'; + } else { + containerDiv.id = 'list-menu-' + this.internalList.length; + } + this.internalList.push(containerDiv); + + items.forEach(function traveseItems(item) { + var item_div = document.createElement('li'); + var button = document.createElement('a'); + button.setAttribute('role', 'button'); + if (item.type && item.type == 'menu') { + // XXX: We disallow multi-level menu at this moment + // See https://bugzilla.mozilla.org/show_bug.cgi?id=824928 + // for UX design and dev implementation tracking + return; + } else if (item.type && item.type == 'menuitem') { + button.dataset.value = item.id; + button.textContent = item.label; + } else { + button.dataset.value = item.value; + button.textContent = item.label; + } + + item_div.appendChild(button); + if (item.icon) { + button.style.backgroundImage = 'url(' + item.icon + ')'; + button.classList.add('icon'); + } + containerDiv.appendChild(item_div); + }, this); + + if (this.currentLevel > 0) { + var back = document.createElement('li'); + var button = document.createElement('a'); + button.setAttribute('role', 'button'); + button.textContent = _('back'); + button.href = '#' + this.currentParent; + back.classList.add('back'); + back.appendChild(button); + containerDiv.appendChild(back); + } else { + var cancel = document.createElement('li'); + var button = document.createElement('button'); + button.textContent = _('cancel'); + button.dataset.action = 'cancel'; + cancel.appendChild(button); + containerDiv.appendChild(cancel); + } + + containerDiv.dataset.level = this.currentLevel; + this.currentChild = containerDiv.id; + }, + + setTitle: function lm_setTitle(title) { + if (!title) + return; + + var titleElement = document.createElement('h3'); + titleElement.textContent = title; + this.container.appendChild(titleElement); + }, + + show: function lm_show() { + if (this.visible) + return; + + this.container.classList.remove('slidedown'); + this.element.classList.add('visible'); + }, + + hide: function lm_hide() { + if (!this.visible) + return; + + var self = this; + var container = this.container; + container.addEventListener('transitionend', function list_hide() { + container.removeEventListener('transitionend', list_hide); + self.element.classList.remove('visible'); + }); + + setTimeout(function() { + container.classList.add('slidedown'); + }); + }, + + handleEvent: function lm_handleEvent(evt) { + switch (evt.type) { + case 'screenchange': + if (!evt.detail.screenEnabled) { + this.hide(); + this.oncancel(); + } + break; + + case 'click': + if (!this.visible) + return; + + var cancel = evt.target.dataset.action; + if (cancel && cancel == 'cancel') { + this.hide(); + this.oncancel(); + return; + } + + var value = evt.target.dataset.value; + if (!value) { + return; + } + + this.hide(); + this.onreturn(value); + break; + + case 'home': + case 'holdhome': + if (!this.visible) + return; + + this.hide(); + this.oncancel(); + break; + } + } +}; + +ListMenu.init(); |