UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

238 lines (237 loc) 6.85 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. "use strict"; /** * 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; }