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