jupyterlab-emrys
Version:
A computational environment for Jupyter. Powered by Emrys
238 lines (237 loc) • 6.85 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
;
/**
* The class name added to dialog instances.
*/
var DIALOG_CLASS = 'jp-Dialog';
/**
* The class name added to dialog content node.
*/
var CONTENT_CLASS = 'jp-Dialog-content';
/**
* The class name added to dialog header node.
*/
var HEADER_CLASS = 'jp-Dialog-header';
/**
* The class name added to dialog title node.
*/
var TITLE_CLASS = 'jp-Dialog-title';
/**
* The class name added to dialog body node.
*/
var BODY_CLASS = 'jp-Dialog-body';
/**
* The class name added to a dialog body content node.
*/
var BODY_CONTENT_CLASS = 'jp-Dialog-bodyContent';
/**
* The class name added to a dialog content node.
*/
var FOOTER_CLASS = 'jp-Dialog-footer';
/**
* The class name added to a dialog button node.
*/
var BUTTON_CLASS = 'jp-Dialog-button';
/**
* The class name added to a dialog button icon node.
*/
var BUTTON_ICON_CLASS = 'jp-Dialog-buttonIcon';
/**
* The class name added to a dialog button text node.
*/
var BUTTON_TEXT_CLASS = 'jp-Dialog-buttonText';
/*
* The class name added to dialog Confirm buttons.
*/
var OK_BUTTON_CLASS = 'jp-Dialog-okButton';
/**
* The class name added to dialog Cancel buttons.
*/
var CANCEL_BUTTON_CLASS = 'jp-Dialog-cancelButton';
/**
* The class name added to dialog input field wrappers.
*/
var INPUT_WRAPPER_CLASS = 'jp-Dialog-inputWrapper';
/**
* The class name added to dialog input fields.
*/
var INPUT_CLASS = 'jp-Dialog-input';
/**
* The class name added to dialog select wrappers.
*/
var SELECT_WRAPPER_CLASS = 'jp-Dialog-selectWrapper';
/**
* The class name added to dialog select nodes.
*/
var SELECT_CLASS = 'jp-Dialog-select';
/**
* A default confirmation button.
*/
exports.okButton = {
text: 'OK',
className: OK_BUTTON_CLASS
};
/**
* A default cancel button.
*/
exports.cancelButton = {
text: 'CANCEL',
className: CANCEL_BUTTON_CLASS
};
/**
* Create a dialog and show it.
*
* @param options - The dialog setup options.
*
* @returns The button item that was selected.
*/
function showDialog(options) {
options = options || {};
var host = options.host || document.body;
options.host = host;
options.body = options.body || '';
exports.okButton.text = options.okText ? options.okText : 'OK';
var buttons = options.buttons || [exports.cancelButton, exports.okButton];
var buttonNodes = buttons.map(createButton);
var dialog = createDialog(options, buttonNodes);
host.appendChild(dialog);
// Focus the ok button if given.
var index = buttons.indexOf(exports.okButton);
if (index !== -1) {
buttonNodes[index].focus();
}
return new Promise(function (resolve, reject) {
buttonNodes.map(function (node) {
node.addEventListener('click', function (evt) {
if (node.contains(evt.target)) {
host.removeChild(dialog);
var button = buttons[buttonNodes.indexOf(node)];
resolve(button);
}
});
});
dialog.addEventListener('keydown', function (evt) {
// Check for escape key
if (evt.keyCode === 27) {
host.removeChild(dialog);
resolve(exports.cancelButton);
}
}, true);
dialog.addEventListener('contextmenu', function (evt) {
evt.preventDefault();
evt.stopPropagation();
}, true);
});
}
exports.showDialog = showDialog;
/**
* Create the dialog node.
*/
function createDialog(options, buttonNodes) {
// Create the dialog nodes (except for the buttons).
var node = document.createElement('div');
var content = document.createElement('div');
var header = document.createElement('div');
var body = document.createElement('div');
var footer = document.createElement('div');
var title = document.createElement('span');
node.className = DIALOG_CLASS;
content.className = CONTENT_CLASS;
header.className = HEADER_CLASS;
body.className = BODY_CLASS;
footer.className = FOOTER_CLASS;
title.className = TITLE_CLASS;
node.appendChild(content);
content.appendChild(header);
content.appendChild(body);
content.appendChild(footer);
header.appendChild(title);
// Populate the nodes.
title.textContent = options.title || '';
var child;
if (typeof options.body === 'string') {
child = document.createElement('span');
child.innerHTML = options.body;
}
else if (options.body) {
child = options.body;
switch (child.tagName) {
case 'INPUT':
child = wrapInput(child);
break;
case 'SELECT':
child = wrapSelect(child);
break;
default:
child = styleElements(child);
break;
}
}
child.classList.add(BODY_CONTENT_CLASS);
body.appendChild(child);
buttonNodes.map(function (buttonNode) { footer.appendChild(buttonNode); });
return node;
}
/**
* Style the child elements of a parent element.
*/
function styleElements(element) {
for (var i = 0; i < element.children.length; i++) {
var child = element.children[i];
var next = child.nextSibling;
switch (child.tagName) {
case 'INPUT':
child = wrapInput(child);
element.insertBefore(child, next);
break;
case 'SELECT':
child = wrapSelect(child);
element.insertBefore(child, next);
break;
}
}
return element;
}
/**
* Create a node for a button item.
*/
function createButton(item) {
var button = document.createElement('button');
button.className = BUTTON_CLASS;
button.tabIndex = -1;
if (item.className) {
button.classList.add(item.className);
}
var icon = document.createElement('span');
icon.className = BUTTON_ICON_CLASS;
if (item.icon) {
icon.classList.add(item.icon);
}
var text = document.createElement('span');
text.className = BUTTON_TEXT_CLASS;
text.textContent = item.text;
button.appendChild(icon);
button.appendChild(text);
return button;
}
/**
* Wrap and style an input node.
*/
function wrapInput(input) {
var wrapper = document.createElement('div');
wrapper.className = INPUT_WRAPPER_CLASS;
wrapper.appendChild(input);
input.classList.add(INPUT_CLASS);
return wrapper;
}
/**
* Wrap and style a select node.
*/
function wrapSelect(select) {
var wrapper = document.createElement('div');
wrapper.className = SELECT_WRAPPER_CLASS;
wrapper.appendChild(select);
select.classList.add(SELECT_CLASS);
return wrapper;
}