|
|
// Copyright (c) IPython Development Team.
|
|
|
// Distributed under the terms of the Modified BSD License.
|
|
|
|
|
|
define([
|
|
|
'base/js/namespace',
|
|
|
'jquery',
|
|
|
'codemirror/lib/codemirror',
|
|
|
], function(IPython, $, CodeMirror) {
|
|
|
"use strict";
|
|
|
|
|
|
var modal = function (options) {
|
|
|
|
|
|
var modal = $("<div/>")
|
|
|
.addClass("modal")
|
|
|
.addClass("fade")
|
|
|
.attr("role", "dialog");
|
|
|
var dialog = $("<div/>")
|
|
|
.addClass("modal-dialog")
|
|
|
.appendTo(modal);
|
|
|
var dialog_content = $("<div/>")
|
|
|
.addClass("modal-content")
|
|
|
.appendTo(dialog);
|
|
|
dialog_content.append(
|
|
|
$("<div/>")
|
|
|
.addClass("modal-header")
|
|
|
.append($("<button>")
|
|
|
.attr("type", "button")
|
|
|
.addClass("close")
|
|
|
.attr("data-dismiss", "modal")
|
|
|
.attr("aria-hidden", "true")
|
|
|
.html("×")
|
|
|
).append(
|
|
|
$("<h4/>")
|
|
|
.addClass('modal-title')
|
|
|
.text(options.title || "")
|
|
|
)
|
|
|
).append(
|
|
|
$("<div/>").addClass("modal-body").append(
|
|
|
options.body || $("<p/>")
|
|
|
)
|
|
|
);
|
|
|
|
|
|
var footer = $("<div/>").addClass("modal-footer");
|
|
|
|
|
|
for (var label in options.buttons) {
|
|
|
var btn_opts = options.buttons[label];
|
|
|
var button = $("<button/>")
|
|
|
.addClass("btn btn-default btn-sm")
|
|
|
.attr("data-dismiss", "modal")
|
|
|
.text(label);
|
|
|
if (btn_opts.click) {
|
|
|
button.click($.proxy(btn_opts.click, dialog_content));
|
|
|
}
|
|
|
if (btn_opts.class) {
|
|
|
button.addClass(btn_opts.class);
|
|
|
}
|
|
|
footer.append(button);
|
|
|
}
|
|
|
dialog_content.append(footer);
|
|
|
// hook up on-open event
|
|
|
modal.on("shown.bs.modal", function() {
|
|
|
setTimeout(function() {
|
|
|
footer.find("button").last().focus();
|
|
|
if (options.open) {
|
|
|
$.proxy(options.open, modal)();
|
|
|
}
|
|
|
}, 0);
|
|
|
});
|
|
|
|
|
|
// destroy modal on hide, unless explicitly asked not to
|
|
|
if (options.destroy === undefined || options.destroy) {
|
|
|
modal.on("hidden.bs.modal", function () {
|
|
|
modal.remove();
|
|
|
});
|
|
|
}
|
|
|
modal.on("hidden.bs.modal", function () {
|
|
|
if (options.notebook) {
|
|
|
var cell = options.notebook.get_selected_cell();
|
|
|
if (cell) cell.select();
|
|
|
}
|
|
|
if (options.keyboard_manager) {
|
|
|
options.keyboard_manager.enable();
|
|
|
options.keyboard_manager.command_mode();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
if (options.keyboard_manager) {
|
|
|
options.keyboard_manager.disable();
|
|
|
}
|
|
|
|
|
|
return modal.modal(options);
|
|
|
};
|
|
|
|
|
|
var kernel_modal = function (options) {
|
|
|
/**
|
|
|
* only one kernel dialog should be open at a time -- but
|
|
|
* other modal dialogs can still be open
|
|
|
*/
|
|
|
$('.kernel-modal').modal('hide');
|
|
|
var dialog = modal(options);
|
|
|
dialog.addClass('kernel-modal');
|
|
|
return dialog;
|
|
|
};
|
|
|
|
|
|
var edit_metadata = function (options) {
|
|
|
options.name = options.name || "Cell";
|
|
|
var error_div = $('<div/>').css('color', 'red');
|
|
|
var message =
|
|
|
"Manually edit the JSON below to manipulate the metadata for this " + options.name + "." +
|
|
|
" We recommend putting custom metadata attributes in an appropriately named sub-structure," +
|
|
|
" so they don't conflict with those of others.";
|
|
|
|
|
|
var textarea = $('<textarea/>')
|
|
|
.attr('rows', '13')
|
|
|
.attr('cols', '80')
|
|
|
.attr('name', 'metadata')
|
|
|
.text(JSON.stringify(options.md || {}, null, 2));
|
|
|
|
|
|
var dialogform = $('<div/>').attr('title', 'Edit the metadata')
|
|
|
.append(
|
|
|
$('<form/>').append(
|
|
|
$('<fieldset/>').append(
|
|
|
$('<label/>')
|
|
|
.attr('for','metadata')
|
|
|
.text(message)
|
|
|
)
|
|
|
.append(error_div)
|
|
|
.append($('<br/>'))
|
|
|
.append(textarea)
|
|
|
)
|
|
|
);
|
|
|
var editor = CodeMirror.fromTextArea(textarea[0], {
|
|
|
lineNumbers: true,
|
|
|
matchBrackets: true,
|
|
|
indentUnit: 2,
|
|
|
autoIndent: true,
|
|
|
mode: 'application/json',
|
|
|
});
|
|
|
var modal_obj = modal({
|
|
|
title: "Edit " + options.name + " Metadata",
|
|
|
body: dialogform,
|
|
|
buttons: {
|
|
|
OK: { class : "btn-primary",
|
|
|
click: function() {
|
|
|
/**
|
|
|
* validate json and set it
|
|
|
*/
|
|
|
var new_md;
|
|
|
try {
|
|
|
new_md = JSON.parse(editor.getValue());
|
|
|
} catch(e) {
|
|
|
console.log(e);
|
|
|
error_div.text('WARNING: Could not save invalid JSON.');
|
|
|
return false;
|
|
|
}
|
|
|
options.callback(new_md);
|
|
|
}
|
|
|
},
|
|
|
Cancel: {}
|
|
|
},
|
|
|
notebook: options.notebook,
|
|
|
keyboard_manager: options.keyboard_manager,
|
|
|
});
|
|
|
|
|
|
modal_obj.on('shown.bs.modal', function(){ editor.refresh(); });
|
|
|
};
|
|
|
|
|
|
var dialog = {
|
|
|
modal : modal,
|
|
|
kernel_modal : kernel_modal,
|
|
|
edit_metadata : edit_metadata,
|
|
|
};
|
|
|
|
|
|
// Backwards compatability.
|
|
|
IPython.dialog = dialog;
|
|
|
|
|
|
return dialog;
|
|
|
});
|
|
|
|