Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
156 lines
4.7 KiB
JavaScript
Executable file
156 lines
4.7 KiB
JavaScript
Executable file
/* exported ContextMenuView */
|
|
/* global BaseUI, Service, eventSafety */
|
|
(function(exports) {
|
|
'use strict';
|
|
|
|
var _id = 0;
|
|
/**
|
|
* The ContextMenu UI for BrowserContextMenu.
|
|
*
|
|
* @class ContextMenuView
|
|
* @param {BaseModule} parentModule The BrowserContextMenu instance
|
|
* where this dialog should popup.
|
|
* @extends BaseUI
|
|
*/
|
|
function ContextMenuView(parentModule) {
|
|
this.parentModule = parentModule;
|
|
this.containerElement = parentModule.containerElement;
|
|
this.instanceID = _id++;
|
|
this._injected = false;
|
|
}
|
|
|
|
ContextMenuView.prototype = Object.create(BaseUI.prototype);
|
|
|
|
|
|
ContextMenuView.prototype.CLASS_NAME = 'BrowserContextMenu';
|
|
|
|
ContextMenuView.prototype.ELEMENT_PREFIX = 'contextmenu-';
|
|
|
|
ContextMenuView.prototype.TRANSITION_TIMEOUT = 350;
|
|
|
|
ContextMenuView.prototype.customID = function am_customID() {
|
|
return 'context-menu';
|
|
};
|
|
|
|
ContextMenuView.prototype._fetchElements = function bcm__fetchElements() {
|
|
this.element = this.containerElement.querySelector('#' + this.CLASS_NAME +
|
|
this.instanceID);
|
|
this.elements = {};
|
|
|
|
var toCamelCase = function toCamelCase(str) {
|
|
return str.replace(/\-(.)/g, function replacer(str, p1) {
|
|
return p1.toUpperCase();
|
|
});
|
|
};
|
|
|
|
this.elementClasses = ['header', 'list'];
|
|
|
|
// Loop and add element with camel style name to Modal Dialog attribute.
|
|
this.elementClasses.forEach(function createElementRef(name) {
|
|
this.elements[toCamelCase(name)] =
|
|
this.element.querySelector('.' + this.ELEMENT_PREFIX + name);
|
|
}, this);
|
|
var cancel = document.createElement('button');
|
|
cancel.id = 'ctx-cancel-button';
|
|
cancel.dataset.action = 'cancel';
|
|
cancel.setAttribute('data-l10n-id', 'cancel');
|
|
this.elements.cancel = cancel;
|
|
};
|
|
|
|
ContextMenuView.prototype._registerEvents = function() {
|
|
this.elements.cancel.addEventListener('click', this.hide.bind(this));
|
|
};
|
|
|
|
ContextMenuView.prototype.view = function() {
|
|
var id = this.CLASS_NAME + this.instanceID;
|
|
var content = `<form class="contextmenu" role="dialog" tabindex="-1"
|
|
data-type="action" id="${id}">
|
|
<header class="contextmenu-header"></header>
|
|
<menu class="contextmenu-list"></menu>
|
|
</form>`;
|
|
return content;
|
|
};
|
|
|
|
ContextMenuView.prototype.kill = function() {
|
|
this.containerElement.removeChild(this.element);
|
|
};
|
|
|
|
ContextMenuView.prototype.show = function(menu) {
|
|
if (!this._injected) {
|
|
this.render();
|
|
this._injected = true;
|
|
}
|
|
|
|
this.buildMenu(menu);
|
|
this.element.classList.add('visible');
|
|
this._requestFocus();
|
|
};
|
|
|
|
ContextMenuView.prototype.hide = function(evt) {
|
|
if (!this.element) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
if (evt) {
|
|
evt.preventDefault();
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.element.classList.remove('visible');
|
|
this._requestFocus();
|
|
eventSafety(this.element, 'transitionend', resolve, 400);
|
|
});
|
|
};
|
|
|
|
ContextMenuView.prototype.buildMenu = function(items) {
|
|
this.elements.list.innerHTML = '';
|
|
items.forEach(function traveseItems(item) {
|
|
var action = document.createElement('button');
|
|
action.dataset.id = item.id;
|
|
action.dataset.value = item.value;
|
|
action.textContent = item.label;
|
|
|
|
if (item.icon) {
|
|
action.classList.add(item.iconClass || 'icon');
|
|
action.style.backgroundImage = 'url(' + item.icon + ')';
|
|
}
|
|
|
|
action.addEventListener('click', function(evt) {
|
|
this.hide(evt).then(() => {
|
|
item.callback();
|
|
});
|
|
}.bind(this));
|
|
|
|
this.elements.list.appendChild(action);
|
|
}, this);
|
|
|
|
var lastButtonWrapper = document.createElement('span');
|
|
lastButtonWrapper.className = 'last-button-container';
|
|
this.elements.list.appendChild(lastButtonWrapper);
|
|
lastButtonWrapper.appendChild(this.elements.cancel);
|
|
};
|
|
|
|
ContextMenuView.prototype.focus = function() {
|
|
document.activeElement.blur();
|
|
this.elements.cancel.focus();
|
|
};
|
|
|
|
ContextMenuView.prototype._requestFocus = function() {
|
|
var transited = function() {
|
|
this.element.removeEventListener('transitionend', transited);
|
|
if (this.transitionTimeout) {
|
|
clearTimeout(this.transitionTimeout);
|
|
this.transitionTimeout = null;
|
|
}
|
|
// The focus switch should be after this module is already shown and
|
|
// transited.
|
|
Service.request('focus');
|
|
}.bind(this);
|
|
|
|
this.element.addEventListener('transitionend', transited);
|
|
this.transitionTimeout = setTimeout(transited, this.TRANSITION_TIMEOUT);
|
|
};
|
|
|
|
exports.ContextMenuView = ContextMenuView;
|
|
|
|
})(window);
|