##// END OF EJS Templates
sanitize only of text and not explicitely asked not to....
Bussonnier Matthias -
Show More
@@ -1,183 +1,212 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define(function(require) {
4 define(function(require) {
5 "use strict";
5 "use strict";
6
6
7 var CodeMirror = require('codemirror/lib/codemirror');
7 var CodeMirror = require('codemirror/lib/codemirror');
8 var IPython = require('base/js/namespace');
8 var IPython = require('base/js/namespace');
9 var $ = require('jquery');
9 var $ = require('jquery');
10
10
11 /**
12 * A wrapper around bootstrap modal for easier use
13 * Pass it an option dictionary with the following properties:
14 *
15 * - body : <string> or <DOM node>, main content of the dialog
16 * if pass a <string> it will be wrapped in a p tag and
17 * html element escaped, unless you specify sanitize=false
18 * option.
19 * - title : Dialog title, default to empty string.
20 * - buttons : dict of btn_options who keys are button label.
21 * see btn_options below for description
22 * - open : callback to trigger on dialog open.
23 * - destroy:
24 * - notebook : notebook instance
25 * - keyboard_manager: keyboard manager instance.
26 *
27 * Unlike bootstrap modals, the backdrop options is set by default
28 * to 'static'.
29 *
30 * The rest of the options are passed as is to bootstrap modals.
31 *
32 * btn_options: dict with the following property:
33 *
34 * - click : callback to trigger on click
35 * - class : css classes to add to button.
36 *
37 *
38 *
39 **/
11 var modal = function (options) {
40 var modal = function (options) {
12
41
13 var modal = $("<div/>")
42 var modal = $("<div/>")
14 .addClass("modal")
43 .addClass("modal")
15 .addClass("fade")
44 .addClass("fade")
16 .attr("role", "dialog");
45 .attr("role", "dialog");
17 var dialog = $("<div/>")
46 var dialog = $("<div/>")
18 .addClass("modal-dialog")
47 .addClass("modal-dialog")
19 .appendTo(modal);
48 .appendTo(modal);
20 var dialog_content = $("<div/>")
49 var dialog_content = $("<div/>")
21 .addClass("modal-content")
50 .addClass("modal-content")
22 .appendTo(dialog);
51 .appendTo(dialog);
23 if(typeof(options.body) === 'string'){
52 if(typeof(options.body) === 'string' && options.sanitize !== false){
24 options.body = $("<p/>").text(options.body)
53 options.body = $("<p/>").text(options.body)
25 }
54 }
26 dialog_content.append(
55 dialog_content.append(
27 $("<div/>")
56 $("<div/>")
28 .addClass("modal-header")
57 .addClass("modal-header")
29 .append($("<button>")
58 .append($("<button>")
30 .attr("type", "button")
59 .attr("type", "button")
31 .addClass("close")
60 .addClass("close")
32 .attr("data-dismiss", "modal")
61 .attr("data-dismiss", "modal")
33 .attr("aria-hidden", "true")
62 .attr("aria-hidden", "true")
34 .html("&times;")
63 .html("&times;")
35 ).append(
64 ).append(
36 $("<h4/>")
65 $("<h4/>")
37 .addClass('modal-title')
66 .addClass('modal-title')
38 .text(options.title || "No Title")
67 .text(options.title || "")
39 )
68 )
40 ).append(
69 ).append(
41 $("<div/>").addClass("modal-body").append(
70 $("<div/>").addClass("modal-body").append(
42 options.body || $("<p/>")
71 options.body || $("<p/>")
43 )
72 )
44 );
73 );
45
74
46 var footer = $("<div/>").addClass("modal-footer");
75 var footer = $("<div/>").addClass("modal-footer");
47
76
48 for (var label in options.buttons) {
77 for (var label in options.buttons) {
49 var btn_opts = options.buttons[label];
78 var btn_opts = options.buttons[label];
50 var button = $("<button/>")
79 var button = $("<button/>")
51 .addClass("btn btn-default btn-sm")
80 .addClass("btn btn-default btn-sm")
52 .attr("data-dismiss", "modal")
81 .attr("data-dismiss", "modal")
53 .text(label);
82 .text(label);
54 if (btn_opts.click) {
83 if (btn_opts.click) {
55 button.click($.proxy(btn_opts.click, dialog_content));
84 button.click($.proxy(btn_opts.click, dialog_content));
56 }
85 }
57 if (btn_opts.class) {
86 if (btn_opts.class) {
58 button.addClass(btn_opts.class);
87 button.addClass(btn_opts.class);
59 }
88 }
60 footer.append(button);
89 footer.append(button);
61 }
90 }
62 dialog_content.append(footer);
91 dialog_content.append(footer);
63 // hook up on-open event
92 // hook up on-open event
64 modal.on("shown.bs.modal", function() {
93 modal.on("shown.bs.modal", function() {
65 setTimeout(function() {
94 setTimeout(function() {
66 footer.find("button").last().focus();
95 footer.find("button").last().focus();
67 if (options.open) {
96 if (options.open) {
68 $.proxy(options.open, modal)();
97 $.proxy(options.open, modal)();
69 }
98 }
70 }, 0);
99 }, 0);
71 });
100 });
72
101
73 // destroy modal on hide, unless explicitly asked not to
102 // destroy modal on hide, unless explicitly asked not to
74 if (options.destroy === undefined || options.destroy) {
103 if (options.destroy === undefined || options.destroy) {
75 modal.on("hidden.bs.modal", function () {
104 modal.on("hidden.bs.modal", function () {
76 modal.remove();
105 modal.remove();
77 });
106 });
78 }
107 }
79 modal.on("hidden.bs.modal", function () {
108 modal.on("hidden.bs.modal", function () {
80 if (options.notebook) {
109 if (options.notebook) {
81 var cell = options.notebook.get_selected_cell();
110 var cell = options.notebook.get_selected_cell();
82 if (cell) cell.select();
111 if (cell) cell.select();
83 }
112 }
84 if (options.keyboard_manager) {
113 if (options.keyboard_manager) {
85 options.keyboard_manager.enable();
114 options.keyboard_manager.enable();
86 options.keyboard_manager.command_mode();
115 options.keyboard_manager.command_mode();
87 }
116 }
88 });
117 });
89
118
90 if (options.keyboard_manager) {
119 if (options.keyboard_manager) {
91 options.keyboard_manager.disable();
120 options.keyboard_manager.disable();
92 }
121 }
93
122
94 options.backdrop = options.backdrop || 'static';
123 options.backdrop = options.backdrop || 'static';
95
124
96 return modal.modal(options);
125 return modal.modal(options);
97 };
126 };
98
127
99 var kernel_modal = function (options) {
128 var kernel_modal = function (options) {
100 /**
129 /**
101 * only one kernel dialog should be open at a time -- but
130 * only one kernel dialog should be open at a time -- but
102 * other modal dialogs can still be open
131 * other modal dialogs can still be open
103 */
132 */
104 $('.kernel-modal').modal('hide');
133 $('.kernel-modal').modal('hide');
105 var dialog = modal(options);
134 var dialog = modal(options);
106 dialog.addClass('kernel-modal');
135 dialog.addClass('kernel-modal');
107 return dialog;
136 return dialog;
108 };
137 };
109
138
110 var edit_metadata = function (options) {
139 var edit_metadata = function (options) {
111 options.name = options.name || "Cell";
140 options.name = options.name || "Cell";
112 var error_div = $('<div/>').css('color', 'red');
141 var error_div = $('<div/>').css('color', 'red');
113 var message =
142 var message =
114 "Manually edit the JSON below to manipulate the metadata for this " + options.name + "." +
143 "Manually edit the JSON below to manipulate the metadata for this " + options.name + "." +
115 " We recommend putting custom metadata attributes in an appropriately named sub-structure," +
144 " We recommend putting custom metadata attributes in an appropriately named sub-structure," +
116 " so they don't conflict with those of others.";
145 " so they don't conflict with those of others.";
117
146
118 var textarea = $('<textarea/>')
147 var textarea = $('<textarea/>')
119 .attr('rows', '13')
148 .attr('rows', '13')
120 .attr('cols', '80')
149 .attr('cols', '80')
121 .attr('name', 'metadata')
150 .attr('name', 'metadata')
122 .text(JSON.stringify(options.md || {}, null, 2));
151 .text(JSON.stringify(options.md || {}, null, 2));
123
152
124 var dialogform = $('<div/>').attr('title', 'Edit the metadata')
153 var dialogform = $('<div/>').attr('title', 'Edit the metadata')
125 .append(
154 .append(
126 $('<form/>').append(
155 $('<form/>').append(
127 $('<fieldset/>').append(
156 $('<fieldset/>').append(
128 $('<label/>')
157 $('<label/>')
129 .attr('for','metadata')
158 .attr('for','metadata')
130 .text(message)
159 .text(message)
131 )
160 )
132 .append(error_div)
161 .append(error_div)
133 .append($('<br/>'))
162 .append($('<br/>'))
134 .append(textarea)
163 .append(textarea)
135 )
164 )
136 );
165 );
137 var editor = CodeMirror.fromTextArea(textarea[0], {
166 var editor = CodeMirror.fromTextArea(textarea[0], {
138 lineNumbers: true,
167 lineNumbers: true,
139 matchBrackets: true,
168 matchBrackets: true,
140 indentUnit: 2,
169 indentUnit: 2,
141 autoIndent: true,
170 autoIndent: true,
142 mode: 'application/json',
171 mode: 'application/json',
143 });
172 });
144 var modal_obj = modal({
173 var modal_obj = modal({
145 title: "Edit " + options.name + " Metadata",
174 title: "Edit " + options.name + " Metadata",
146 body: dialogform,
175 body: dialogform,
147 buttons: {
176 buttons: {
148 OK: { class : "btn-primary",
177 OK: { class : "btn-primary",
149 click: function() {
178 click: function() {
150 /**
179 /**
151 * validate json and set it
180 * validate json and set it
152 */
181 */
153 var new_md;
182 var new_md;
154 try {
183 try {
155 new_md = JSON.parse(editor.getValue());
184 new_md = JSON.parse(editor.getValue());
156 } catch(e) {
185 } catch(e) {
157 console.log(e);
186 console.log(e);
158 error_div.text('WARNING: Could not save invalid JSON.');
187 error_div.text('WARNING: Could not save invalid JSON.');
159 return false;
188 return false;
160 }
189 }
161 options.callback(new_md);
190 options.callback(new_md);
162 }
191 }
163 },
192 },
164 Cancel: {}
193 Cancel: {}
165 },
194 },
166 notebook: options.notebook,
195 notebook: options.notebook,
167 keyboard_manager: options.keyboard_manager,
196 keyboard_manager: options.keyboard_manager,
168 });
197 });
169
198
170 modal_obj.on('shown.bs.modal', function(){ editor.refresh(); });
199 modal_obj.on('shown.bs.modal', function(){ editor.refresh(); });
171 };
200 };
172
201
173 var dialog = {
202 var dialog = {
174 modal : modal,
203 modal : modal,
175 kernel_modal : kernel_modal,
204 kernel_modal : kernel_modal,
176 edit_metadata : edit_metadata,
205 edit_metadata : edit_metadata,
177 };
206 };
178
207
179 // Backwards compatability.
208 // Backwards compatability.
180 IPython.dialog = dialog;
209 IPython.dialog = dialog;
181
210
182 return dialog;
211 return dialog;
183 });
212 });
General Comments 0
You need to be logged in to leave comments. Login now