Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/js/list_menu.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/system/js/list_menu.js')
-rw-r--r--apps/system/js/list_menu.js180
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();