##// END OF EJS Templates
Merge pull request #6190 from minrk/bootstrap-shim...
Matthias Bussonnier -
r17314:555f4435 merge
parent child Browse files
Show More
@@ -1,351 +1,351 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([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/utils',
7 'base/js/utils',
8 'notebook/js/tour',
8 'notebook/js/tour',
9 'components/bootstrap/js/bootstrap.min',
9 'bootstrap',
10 ], function(IPython, $, utils, tour) {
10 ], function(IPython, $, utils, tour) {
11 "use strict";
11 "use strict";
12
12
13 var MenuBar = function (selector, options) {
13 var MenuBar = function (selector, options) {
14 // Constructor
14 // Constructor
15 //
15 //
16 // A MenuBar Class to generate the menubar of IPython notebook
16 // A MenuBar Class to generate the menubar of IPython notebook
17 //
17 //
18 // Parameters:
18 // Parameters:
19 // selector: string
19 // selector: string
20 // options: dictionary
20 // options: dictionary
21 // Dictionary of keyword arguments.
21 // Dictionary of keyword arguments.
22 // notebook: Notebook instance
22 // notebook: Notebook instance
23 // layout_manager: LayoutManager instance
23 // layout_manager: LayoutManager instance
24 // events: $(Events) instance
24 // events: $(Events) instance
25 // save_widget: SaveWidget instance
25 // save_widget: SaveWidget instance
26 // quick_help: QuickHelp instance
26 // quick_help: QuickHelp instance
27 // base_url : string
27 // base_url : string
28 // notebook_path : string
28 // notebook_path : string
29 // notebook_name : string
29 // notebook_name : string
30 options = options || {};
30 options = options || {};
31 this.base_url = options.base_url || utils.get_body_data("baseUrl");
31 this.base_url = options.base_url || utils.get_body_data("baseUrl");
32 this.selector = selector;
32 this.selector = selector;
33 this.notebook = options.notebook;
33 this.notebook = options.notebook;
34 this.layout_manager = options.layout_manager;
34 this.layout_manager = options.layout_manager;
35 this.events = options.events;
35 this.events = options.events;
36 this.save_widget = options.save_widget;
36 this.save_widget = options.save_widget;
37 this.quick_help = options.quick_help;
37 this.quick_help = options.quick_help;
38
38
39 try {
39 try {
40 this.tour = new tour.Tour(this.notebook, this.events);
40 this.tour = new tour.Tour(this.notebook, this.events);
41 } catch (e) {
41 } catch (e) {
42 this.tour = undefined;
42 this.tour = undefined;
43 console.log("Failed to instantiate Notebook Tour", e);
43 console.log("Failed to instantiate Notebook Tour", e);
44 }
44 }
45
45
46 if (this.selector !== undefined) {
46 if (this.selector !== undefined) {
47 this.element = $(selector);
47 this.element = $(selector);
48 this.style();
48 this.style();
49 this.bind_events();
49 this.bind_events();
50 }
50 }
51 };
51 };
52
52
53 MenuBar.prototype.style = function () {
53 MenuBar.prototype.style = function () {
54 var that = this;
54 var that = this;
55 this.element.addClass('border-box-sizing');
55 this.element.addClass('border-box-sizing');
56 this.element.find("li").click(function (event, ui) {
56 this.element.find("li").click(function (event, ui) {
57 // The selected cell loses focus when the menu is entered, so we
57 // The selected cell loses focus when the menu is entered, so we
58 // re-select it upon selection.
58 // re-select it upon selection.
59 var i = that.notebook.get_selected_index();
59 var i = that.notebook.get_selected_index();
60 that.notebook.select(i);
60 that.notebook.select(i);
61 }
61 }
62 );
62 );
63 };
63 };
64
64
65 MenuBar.prototype._nbconvert = function (format, download) {
65 MenuBar.prototype._nbconvert = function (format, download) {
66 download = download || false;
66 download = download || false;
67 var notebook_path = this.notebook.notebook_path;
67 var notebook_path = this.notebook.notebook_path;
68 var notebook_name = this.notebook.notebook_name;
68 var notebook_name = this.notebook.notebook_name;
69 if (this.notebook.dirty) {
69 if (this.notebook.dirty) {
70 this.notebook.save_notebook({async : false});
70 this.notebook.save_notebook({async : false});
71 }
71 }
72 var url = utils.url_join_encode(
72 var url = utils.url_join_encode(
73 this.base_url,
73 this.base_url,
74 'nbconvert',
74 'nbconvert',
75 format,
75 format,
76 notebook_path,
76 notebook_path,
77 notebook_name
77 notebook_name
78 ) + "?download=" + download.toString();
78 ) + "?download=" + download.toString();
79
79
80 window.open(url);
80 window.open(url);
81 };
81 };
82
82
83 MenuBar.prototype.bind_events = function () {
83 MenuBar.prototype.bind_events = function () {
84 // File
84 // File
85 var that = this;
85 var that = this;
86 this.element.find('#new_notebook').click(function () {
86 this.element.find('#new_notebook').click(function () {
87 that.notebook.new_notebook();
87 that.notebook.new_notebook();
88 });
88 });
89 this.element.find('#open_notebook').click(function () {
89 this.element.find('#open_notebook').click(function () {
90 window.open(utils.url_join_encode(
90 window.open(utils.url_join_encode(
91 that.notebook.base_url,
91 that.notebook.base_url,
92 'tree',
92 'tree',
93 that.notebook.notebook_path
93 that.notebook.notebook_path
94 ));
94 ));
95 });
95 });
96 this.element.find('#copy_notebook').click(function () {
96 this.element.find('#copy_notebook').click(function () {
97 that.notebook.copy_notebook();
97 that.notebook.copy_notebook();
98 return false;
98 return false;
99 });
99 });
100 this.element.find('#download_ipynb').click(function () {
100 this.element.find('#download_ipynb').click(function () {
101 var base_url = that.notebook.base_url;
101 var base_url = that.notebook.base_url;
102 var notebook_path = that.notebook.notebook_path;
102 var notebook_path = that.notebook.notebook_path;
103 var notebook_name = that.notebook.notebook_name;
103 var notebook_name = that.notebook.notebook_name;
104 if (that.notebook.dirty) {
104 if (that.notebook.dirty) {
105 that.notebook.save_notebook({async : false});
105 that.notebook.save_notebook({async : false});
106 }
106 }
107
107
108 var url = utils.url_join_encode(
108 var url = utils.url_join_encode(
109 base_url,
109 base_url,
110 'files',
110 'files',
111 notebook_path,
111 notebook_path,
112 notebook_name
112 notebook_name
113 );
113 );
114 window.location.assign(url);
114 window.location.assign(url);
115 });
115 });
116
116
117 this.element.find('#print_preview').click(function () {
117 this.element.find('#print_preview').click(function () {
118 that._nbconvert('html', false);
118 that._nbconvert('html', false);
119 });
119 });
120
120
121 this.element.find('#download_py').click(function () {
121 this.element.find('#download_py').click(function () {
122 that._nbconvert('python', true);
122 that._nbconvert('python', true);
123 });
123 });
124
124
125 this.element.find('#download_html').click(function () {
125 this.element.find('#download_html').click(function () {
126 that._nbconvert('html', true);
126 that._nbconvert('html', true);
127 });
127 });
128
128
129 this.element.find('#download_rst').click(function () {
129 this.element.find('#download_rst').click(function () {
130 that._nbconvert('rst', true);
130 that._nbconvert('rst', true);
131 });
131 });
132
132
133 this.element.find('#download_pdf').click(function () {
133 this.element.find('#download_pdf').click(function () {
134 that._nbconvert('pdf', true);
134 that._nbconvert('pdf', true);
135 });
135 });
136
136
137 this.element.find('#rename_notebook').click(function () {
137 this.element.find('#rename_notebook').click(function () {
138 that.save_widget.rename_notebook({notebook: that.notebook});
138 that.save_widget.rename_notebook({notebook: that.notebook});
139 });
139 });
140 this.element.find('#save_checkpoint').click(function () {
140 this.element.find('#save_checkpoint').click(function () {
141 that.notebook.save_checkpoint();
141 that.notebook.save_checkpoint();
142 });
142 });
143 this.element.find('#restore_checkpoint').click(function () {
143 this.element.find('#restore_checkpoint').click(function () {
144 });
144 });
145 this.element.find('#trust_notebook').click(function () {
145 this.element.find('#trust_notebook').click(function () {
146 that.notebook.trust_notebook();
146 that.notebook.trust_notebook();
147 });
147 });
148 this.events.on('trust_changed.Notebook', function (event, trusted) {
148 this.events.on('trust_changed.Notebook', function (event, trusted) {
149 if (trusted) {
149 if (trusted) {
150 that.element.find('#trust_notebook')
150 that.element.find('#trust_notebook')
151 .addClass("disabled")
151 .addClass("disabled")
152 .find("a").text("Trusted Notebook");
152 .find("a").text("Trusted Notebook");
153 } else {
153 } else {
154 that.element.find('#trust_notebook')
154 that.element.find('#trust_notebook')
155 .removeClass("disabled")
155 .removeClass("disabled")
156 .find("a").text("Trust Notebook");
156 .find("a").text("Trust Notebook");
157 }
157 }
158 });
158 });
159 this.element.find('#kill_and_exit').click(function () {
159 this.element.find('#kill_and_exit').click(function () {
160 that.notebook.session.delete();
160 that.notebook.session.delete();
161 setTimeout(function(){
161 setTimeout(function(){
162 // allow closing of new tabs in Chromium, impossible in FF
162 // allow closing of new tabs in Chromium, impossible in FF
163 window.open('', '_self', '');
163 window.open('', '_self', '');
164 window.close();
164 window.close();
165 }, 500);
165 }, 500);
166 });
166 });
167 // Edit
167 // Edit
168 this.element.find('#cut_cell').click(function () {
168 this.element.find('#cut_cell').click(function () {
169 that.notebook.cut_cell();
169 that.notebook.cut_cell();
170 });
170 });
171 this.element.find('#copy_cell').click(function () {
171 this.element.find('#copy_cell').click(function () {
172 that.notebook.copy_cell();
172 that.notebook.copy_cell();
173 });
173 });
174 this.element.find('#delete_cell').click(function () {
174 this.element.find('#delete_cell').click(function () {
175 that.notebook.delete_cell();
175 that.notebook.delete_cell();
176 });
176 });
177 this.element.find('#undelete_cell').click(function () {
177 this.element.find('#undelete_cell').click(function () {
178 that.notebook.undelete_cell();
178 that.notebook.undelete_cell();
179 });
179 });
180 this.element.find('#split_cell').click(function () {
180 this.element.find('#split_cell').click(function () {
181 that.notebook.split_cell();
181 that.notebook.split_cell();
182 });
182 });
183 this.element.find('#merge_cell_above').click(function () {
183 this.element.find('#merge_cell_above').click(function () {
184 that.notebook.merge_cell_above();
184 that.notebook.merge_cell_above();
185 });
185 });
186 this.element.find('#merge_cell_below').click(function () {
186 this.element.find('#merge_cell_below').click(function () {
187 that.notebook.merge_cell_below();
187 that.notebook.merge_cell_below();
188 });
188 });
189 this.element.find('#move_cell_up').click(function () {
189 this.element.find('#move_cell_up').click(function () {
190 that.notebook.move_cell_up();
190 that.notebook.move_cell_up();
191 });
191 });
192 this.element.find('#move_cell_down').click(function () {
192 this.element.find('#move_cell_down').click(function () {
193 that.notebook.move_cell_down();
193 that.notebook.move_cell_down();
194 });
194 });
195 this.element.find('#edit_nb_metadata').click(function () {
195 this.element.find('#edit_nb_metadata').click(function () {
196 that.notebook.edit_metadata({
196 that.notebook.edit_metadata({
197 notebook: that.notebook,
197 notebook: that.notebook,
198 keyboard_manager: that.notebook.keyboard_manager});
198 keyboard_manager: that.notebook.keyboard_manager});
199 });
199 });
200
200
201 // View
201 // View
202 this.element.find('#toggle_header').click(function () {
202 this.element.find('#toggle_header').click(function () {
203 $('div#header').toggle();
203 $('div#header').toggle();
204 that.layout_manager.do_resize();
204 that.layout_manager.do_resize();
205 });
205 });
206 this.element.find('#toggle_toolbar').click(function () {
206 this.element.find('#toggle_toolbar').click(function () {
207 $('div#maintoolbar').toggle();
207 $('div#maintoolbar').toggle();
208 that.layout_manager.do_resize();
208 that.layout_manager.do_resize();
209 });
209 });
210 // Insert
210 // Insert
211 this.element.find('#insert_cell_above').click(function () {
211 this.element.find('#insert_cell_above').click(function () {
212 that.notebook.insert_cell_above('code');
212 that.notebook.insert_cell_above('code');
213 that.notebook.select_prev();
213 that.notebook.select_prev();
214 });
214 });
215 this.element.find('#insert_cell_below').click(function () {
215 this.element.find('#insert_cell_below').click(function () {
216 that.notebook.insert_cell_below('code');
216 that.notebook.insert_cell_below('code');
217 that.notebook.select_next();
217 that.notebook.select_next();
218 });
218 });
219 // Cell
219 // Cell
220 this.element.find('#run_cell').click(function () {
220 this.element.find('#run_cell').click(function () {
221 that.notebook.execute_cell();
221 that.notebook.execute_cell();
222 });
222 });
223 this.element.find('#run_cell_select_below').click(function () {
223 this.element.find('#run_cell_select_below').click(function () {
224 that.notebook.execute_cell_and_select_below();
224 that.notebook.execute_cell_and_select_below();
225 });
225 });
226 this.element.find('#run_cell_insert_below').click(function () {
226 this.element.find('#run_cell_insert_below').click(function () {
227 that.notebook.execute_cell_and_insert_below();
227 that.notebook.execute_cell_and_insert_below();
228 });
228 });
229 this.element.find('#run_all_cells').click(function () {
229 this.element.find('#run_all_cells').click(function () {
230 that.notebook.execute_all_cells();
230 that.notebook.execute_all_cells();
231 });
231 });
232 this.element.find('#run_all_cells_above').click(function () {
232 this.element.find('#run_all_cells_above').click(function () {
233 that.notebook.execute_cells_above();
233 that.notebook.execute_cells_above();
234 });
234 });
235 this.element.find('#run_all_cells_below').click(function () {
235 this.element.find('#run_all_cells_below').click(function () {
236 that.notebook.execute_cells_below();
236 that.notebook.execute_cells_below();
237 });
237 });
238 this.element.find('#to_code').click(function () {
238 this.element.find('#to_code').click(function () {
239 that.notebook.to_code();
239 that.notebook.to_code();
240 });
240 });
241 this.element.find('#to_markdown').click(function () {
241 this.element.find('#to_markdown').click(function () {
242 that.notebook.to_markdown();
242 that.notebook.to_markdown();
243 });
243 });
244 this.element.find('#to_raw').click(function () {
244 this.element.find('#to_raw').click(function () {
245 that.notebook.to_raw();
245 that.notebook.to_raw();
246 });
246 });
247 this.element.find('#to_heading1').click(function () {
247 this.element.find('#to_heading1').click(function () {
248 that.notebook.to_heading(undefined, 1);
248 that.notebook.to_heading(undefined, 1);
249 });
249 });
250 this.element.find('#to_heading2').click(function () {
250 this.element.find('#to_heading2').click(function () {
251 that.notebook.to_heading(undefined, 2);
251 that.notebook.to_heading(undefined, 2);
252 });
252 });
253 this.element.find('#to_heading3').click(function () {
253 this.element.find('#to_heading3').click(function () {
254 that.notebook.to_heading(undefined, 3);
254 that.notebook.to_heading(undefined, 3);
255 });
255 });
256 this.element.find('#to_heading4').click(function () {
256 this.element.find('#to_heading4').click(function () {
257 that.notebook.to_heading(undefined, 4);
257 that.notebook.to_heading(undefined, 4);
258 });
258 });
259 this.element.find('#to_heading5').click(function () {
259 this.element.find('#to_heading5').click(function () {
260 that.notebook.to_heading(undefined, 5);
260 that.notebook.to_heading(undefined, 5);
261 });
261 });
262 this.element.find('#to_heading6').click(function () {
262 this.element.find('#to_heading6').click(function () {
263 that.notebook.to_heading(undefined, 6);
263 that.notebook.to_heading(undefined, 6);
264 });
264 });
265
265
266 this.element.find('#toggle_current_output').click(function () {
266 this.element.find('#toggle_current_output').click(function () {
267 that.notebook.toggle_output();
267 that.notebook.toggle_output();
268 });
268 });
269 this.element.find('#toggle_current_output_scroll').click(function () {
269 this.element.find('#toggle_current_output_scroll').click(function () {
270 that.notebook.toggle_output_scroll();
270 that.notebook.toggle_output_scroll();
271 });
271 });
272 this.element.find('#clear_current_output').click(function () {
272 this.element.find('#clear_current_output').click(function () {
273 that.notebook.clear_output();
273 that.notebook.clear_output();
274 });
274 });
275
275
276 this.element.find('#toggle_all_output').click(function () {
276 this.element.find('#toggle_all_output').click(function () {
277 that.notebook.toggle_all_output();
277 that.notebook.toggle_all_output();
278 });
278 });
279 this.element.find('#toggle_all_output_scroll').click(function () {
279 this.element.find('#toggle_all_output_scroll').click(function () {
280 that.notebook.toggle_all_output_scroll();
280 that.notebook.toggle_all_output_scroll();
281 });
281 });
282 this.element.find('#clear_all_output').click(function () {
282 this.element.find('#clear_all_output').click(function () {
283 that.notebook.clear_all_output();
283 that.notebook.clear_all_output();
284 });
284 });
285
285
286 // Kernel
286 // Kernel
287 this.element.find('#int_kernel').click(function () {
287 this.element.find('#int_kernel').click(function () {
288 that.notebook.session.interrupt_kernel();
288 that.notebook.session.interrupt_kernel();
289 });
289 });
290 this.element.find('#restart_kernel').click(function () {
290 this.element.find('#restart_kernel').click(function () {
291 that.notebook.restart_kernel();
291 that.notebook.restart_kernel();
292 });
292 });
293 // Help
293 // Help
294 if (this.tour) {
294 if (this.tour) {
295 this.element.find('#notebook_tour').click(function () {
295 this.element.find('#notebook_tour').click(function () {
296 that.tour.start();
296 that.tour.start();
297 });
297 });
298 } else {
298 } else {
299 this.element.find('#notebook_tour').addClass("disabled");
299 this.element.find('#notebook_tour').addClass("disabled");
300 }
300 }
301 this.element.find('#keyboard_shortcuts').click(function () {
301 this.element.find('#keyboard_shortcuts').click(function () {
302 that.quick_help.show_keyboard_shortcuts();
302 that.quick_help.show_keyboard_shortcuts();
303 });
303 });
304
304
305 this.update_restore_checkpoint(null);
305 this.update_restore_checkpoint(null);
306
306
307 this.events.on('checkpoints_listed.Notebook', function (event, data) {
307 this.events.on('checkpoints_listed.Notebook', function (event, data) {
308 that.update_restore_checkpoint(that.notebook.checkpoints);
308 that.update_restore_checkpoint(that.notebook.checkpoints);
309 });
309 });
310
310
311 this.events.on('checkpoint_created.Notebook', function (event, data) {
311 this.events.on('checkpoint_created.Notebook', function (event, data) {
312 that.update_restore_checkpoint(that.notebook.checkpoints);
312 that.update_restore_checkpoint(that.notebook.checkpoints);
313 });
313 });
314 };
314 };
315
315
316 MenuBar.prototype.update_restore_checkpoint = function(checkpoints) {
316 MenuBar.prototype.update_restore_checkpoint = function(checkpoints) {
317 var ul = this.element.find("#restore_checkpoint").find("ul");
317 var ul = this.element.find("#restore_checkpoint").find("ul");
318 ul.empty();
318 ul.empty();
319 if (!checkpoints || checkpoints.length === 0) {
319 if (!checkpoints || checkpoints.length === 0) {
320 ul.append(
320 ul.append(
321 $("<li/>")
321 $("<li/>")
322 .addClass("disabled")
322 .addClass("disabled")
323 .append(
323 .append(
324 $("<a/>")
324 $("<a/>")
325 .text("No checkpoints")
325 .text("No checkpoints")
326 )
326 )
327 );
327 );
328 return;
328 return;
329 }
329 }
330
330
331 var that = this;
331 var that = this;
332 checkpoints.map(function (checkpoint) {
332 checkpoints.map(function (checkpoint) {
333 var d = new Date(checkpoint.last_modified);
333 var d = new Date(checkpoint.last_modified);
334 ul.append(
334 ul.append(
335 $("<li/>").append(
335 $("<li/>").append(
336 $("<a/>")
336 $("<a/>")
337 .attr("href", "#")
337 .attr("href", "#")
338 .text(d.format("mmm dd HH:MM:ss"))
338 .text(d.format("mmm dd HH:MM:ss"))
339 .click(function () {
339 .click(function () {
340 that.notebook.restore_checkpoint_dialog(checkpoint);
340 that.notebook.restore_checkpoint_dialog(checkpoint);
341 })
341 })
342 )
342 )
343 );
343 );
344 });
344 });
345 };
345 };
346
346
347 // Backwards compatability.
347 // Backwards compatability.
348 IPython.MenuBar = MenuBar;
348 IPython.MenuBar = MenuBar;
349
349
350 return {'MenuBar': MenuBar};
350 return {'MenuBar': MenuBar};
351 });
351 });
@@ -1,119 +1,119 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 require([
4 require([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/events',
7 'base/js/events',
8 'base/js/page',
8 'base/js/page',
9 'base/js/utils',
9 'base/js/utils',
10 'tree/js/notebooklist',
10 'tree/js/notebooklist',
11 'tree/js/clusterlist',
11 'tree/js/clusterlist',
12 'tree/js/sessionlist',
12 'tree/js/sessionlist',
13 'tree/js/kernellist',
13 'tree/js/kernellist',
14 'auth/js/loginwidget',
14 'auth/js/loginwidget',
15 'components/jquery-ui/ui/minified/jquery-ui.min',
15 'jqueryui',
16 'components/bootstrap/js/bootstrap.min',
16 'bootstrap',
17 ], function(
17 ], function(
18 IPython,
18 IPython,
19 $,
19 $,
20 events,
20 events,
21 page,
21 page,
22 utils,
22 utils,
23 notebooklist,
23 notebooklist,
24 clusterlist,
24 clusterlist,
25 sesssionlist,
25 sesssionlist,
26 kernellist,
26 kernellist,
27 loginwidget){
27 loginwidget){
28
28
29 page = new page.Page();
29 page = new page.Page();
30
30
31 var common_options = {
31 var common_options = {
32 base_url: utils.get_body_data("baseUrl"),
32 base_url: utils.get_body_data("baseUrl"),
33 notebook_path: utils.get_body_data("notebookPath"),
33 notebook_path: utils.get_body_data("notebookPath"),
34 };
34 };
35 events = $([new events.Events()]);
35 events = $([new events.Events()]);
36 session_list = new sesssionlist.SesssionList($.extend({
36 session_list = new sesssionlist.SesssionList($.extend({
37 events: events},
37 events: events},
38 common_options));
38 common_options));
39 notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
39 notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
40 session_list: session_list},
40 session_list: session_list},
41 common_options));
41 common_options));
42 cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
42 cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
43 kernel_list = new kernellist.KernelList('#running_list', $.extend({
43 kernel_list = new kernellist.KernelList('#running_list', $.extend({
44 session_list: session_list},
44 session_list: session_list},
45 common_options));
45 common_options));
46 login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
46 login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
47
47
48 $('#new_notebook').button().click(function (e) {
48 $('#new_notebook').button().click(function (e) {
49 notebook_list.new_notebook();
49 notebook_list.new_notebook();
50 });
50 });
51
51
52 var interval_id=0;
52 var interval_id=0;
53 // auto refresh every xx secondes, no need to be fast,
53 // auto refresh every xx secondes, no need to be fast,
54 // update is done at least when page get focus
54 // update is done at least when page get focus
55 var time_refresh = 60; // in sec
55 var time_refresh = 60; // in sec
56
56
57 var enable_autorefresh = function(){
57 var enable_autorefresh = function(){
58 //refresh immediately , then start interval
58 //refresh immediately , then start interval
59 if($('.upload_button').length === 0)
59 if($('.upload_button').length === 0)
60 {
60 {
61 session_list.load_sessions();
61 session_list.load_sessions();
62 cluster_list.load_list();
62 cluster_list.load_list();
63 }
63 }
64 if (!interval_id){
64 if (!interval_id){
65 interval_id = setInterval(function(){
65 interval_id = setInterval(function(){
66 if($('.upload_button').length === 0)
66 if($('.upload_button').length === 0)
67 {
67 {
68 session_list.load_sessions();
68 session_list.load_sessions();
69 cluster_list.load_list();
69 cluster_list.load_list();
70 }
70 }
71 }, time_refresh*1000);
71 }, time_refresh*1000);
72 }
72 }
73 };
73 };
74
74
75 var disable_autorefresh = function(){
75 var disable_autorefresh = function(){
76 clearInterval(interval_id);
76 clearInterval(interval_id);
77 interval_id = 0;
77 interval_id = 0;
78 };
78 };
79
79
80 // stop autorefresh when page lose focus
80 // stop autorefresh when page lose focus
81 $(window).blur(function() {
81 $(window).blur(function() {
82 disable_autorefresh();
82 disable_autorefresh();
83 });
83 });
84
84
85 //re-enable when page get focus back
85 //re-enable when page get focus back
86 $(window).focus(function() {
86 $(window).focus(function() {
87 enable_autorefresh();
87 enable_autorefresh();
88 });
88 });
89
89
90 // finally start it, it will refresh immediately
90 // finally start it, it will refresh immediately
91 enable_autorefresh();
91 enable_autorefresh();
92
92
93 page.show();
93 page.show();
94 events.trigger('app_initialized.DashboardApp');
94 events.trigger('app_initialized.DashboardApp');
95
95
96 // bound the upload method to the on change of the file select list
96 // bound the upload method to the on change of the file select list
97 $("#alternate_upload").change(function (event){
97 $("#alternate_upload").change(function (event){
98 notebook_list.handleFilesUpload(event,'form');
98 notebook_list.handleFilesUpload(event,'form');
99 });
99 });
100
100
101 // set hash on tab click
101 // set hash on tab click
102 $("#tabs").find("a").click(function() {
102 $("#tabs").find("a").click(function() {
103 window.location.hash = $(this).attr("href");
103 window.location.hash = $(this).attr("href");
104 });
104 });
105
105
106 // load tab if url hash
106 // load tab if url hash
107 if (window.location.hash) {
107 if (window.location.hash) {
108 $("#tabs").find("a[href=" + window.location.hash + "]").click();
108 $("#tabs").find("a[href=" + window.location.hash + "]").click();
109 }
109 }
110
110
111 // For backwards compatability.
111 // For backwards compatability.
112 IPython.page = page;
112 IPython.page = page;
113 IPython.notebook_list = notebook_list;
113 IPython.notebook_list = notebook_list;
114 IPython.cluster_list = cluster_list;
114 IPython.cluster_list = cluster_list;
115 IPython.session_list = session_list;
115 IPython.session_list = session_list;
116 IPython.kernel_list = kernel_list;
116 IPython.kernel_list = kernel_list;
117 IPython.login_widget = login_widget;
117 IPython.login_widget = login_widget;
118 IPython.events = events;
118 IPython.events = events;
119 });
119 });
@@ -1,120 +1,120 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jquery",
6 "jquery",
7 "components/bootstrap/js/bootstrap.min",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var CheckboxView = widget.DOMWidgetView.extend({
10 var CheckboxView = widget.DOMWidgetView.extend({
11 render : function(){
11 render : function(){
12 // Called when view is rendered.
12 // Called when view is rendered.
13 this.$el
13 this.$el
14 .addClass('widget-hbox-single');
14 .addClass('widget-hbox-single');
15 this.$label = $('<div />')
15 this.$label = $('<div />')
16 .addClass('widget-hlabel')
16 .addClass('widget-hlabel')
17 .appendTo(this.$el)
17 .appendTo(this.$el)
18 .hide();
18 .hide();
19 this.$checkbox = $('<input />')
19 this.$checkbox = $('<input />')
20 .attr('type', 'checkbox')
20 .attr('type', 'checkbox')
21 .appendTo(this.$el)
21 .appendTo(this.$el)
22 .click($.proxy(this.handle_click, this));
22 .click($.proxy(this.handle_click, this));
23
23
24 this.$el_to_style = this.$checkbox; // Set default element to style
24 this.$el_to_style = this.$checkbox; // Set default element to style
25 this.update(); // Set defaults.
25 this.update(); // Set defaults.
26 },
26 },
27
27
28 handle_click: function() {
28 handle_click: function() {
29 // Handles when the checkbox is clicked.
29 // Handles when the checkbox is clicked.
30
30
31 // Calling model.set will trigger all of the other views of the
31 // Calling model.set will trigger all of the other views of the
32 // model to update.
32 // model to update.
33 var value = this.model.get('value');
33 var value = this.model.get('value');
34 this.model.set('value', ! value, {updated_view: this});
34 this.model.set('value', ! value, {updated_view: this});
35 this.touch();
35 this.touch();
36 },
36 },
37
37
38 update : function(options){
38 update : function(options){
39 // Update the contents of this view
39 // Update the contents of this view
40 //
40 //
41 // Called when the model is changed. The model may have been
41 // Called when the model is changed. The model may have been
42 // changed by another view or by a state update from the back-end.
42 // changed by another view or by a state update from the back-end.
43 this.$checkbox.prop('checked', this.model.get('value'));
43 this.$checkbox.prop('checked', this.model.get('value'));
44
44
45 if (options === undefined || options.updated_view != this) {
45 if (options === undefined || options.updated_view != this) {
46 var disabled = this.model.get('disabled');
46 var disabled = this.model.get('disabled');
47 this.$checkbox.prop('disabled', disabled);
47 this.$checkbox.prop('disabled', disabled);
48
48
49 var description = this.model.get('description');
49 var description = this.model.get('description');
50 if (description.trim().length === 0) {
50 if (description.trim().length === 0) {
51 this.$label.hide();
51 this.$label.hide();
52 } else {
52 } else {
53 this.$label.text(description);
53 this.$label.text(description);
54 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
54 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
55 this.$label.show();
55 this.$label.show();
56 }
56 }
57 }
57 }
58 return CheckboxView.__super__.update.apply(this);
58 return CheckboxView.__super__.update.apply(this);
59 },
59 },
60
60
61 });
61 });
62
62
63
63
64 var ToggleButtonView = widget.DOMWidgetView.extend({
64 var ToggleButtonView = widget.DOMWidgetView.extend({
65 render : function() {
65 render : function() {
66 // Called when view is rendered.
66 // Called when view is rendered.
67 var that = this;
67 var that = this;
68 this.setElement($('<button />')
68 this.setElement($('<button />')
69 .addClass('btn btn-default')
69 .addClass('btn btn-default')
70 .attr('type', 'button')
70 .attr('type', 'button')
71 .on('click', function (e) {
71 .on('click', function (e) {
72 e.preventDefault();
72 e.preventDefault();
73 that.handle_click();
73 that.handle_click();
74 }));
74 }));
75
75
76 this.update(); // Set defaults.
76 this.update(); // Set defaults.
77 },
77 },
78
78
79 update : function(options){
79 update : function(options){
80 // Update the contents of this view
80 // Update the contents of this view
81 //
81 //
82 // Called when the model is changed. The model may have been
82 // Called when the model is changed. The model may have been
83 // changed by another view or by a state update from the back-end.
83 // changed by another view or by a state update from the back-end.
84 if (this.model.get('value')) {
84 if (this.model.get('value')) {
85 this.$el.addClass('active');
85 this.$el.addClass('active');
86 } else {
86 } else {
87 this.$el.removeClass('active');
87 this.$el.removeClass('active');
88 }
88 }
89
89
90 if (options === undefined || options.updated_view != this) {
90 if (options === undefined || options.updated_view != this) {
91
91
92 var disabled = this.model.get('disabled');
92 var disabled = this.model.get('disabled');
93 this.$el.prop('disabled', disabled);
93 this.$el.prop('disabled', disabled);
94
94
95 var description = this.model.get('description');
95 var description = this.model.get('description');
96 if (description.trim().length === 0) {
96 if (description.trim().length === 0) {
97 this.$el.html("&nbsp;"); // Preserve button height
97 this.$el.html("&nbsp;"); // Preserve button height
98 } else {
98 } else {
99 this.$el.text(description);
99 this.$el.text(description);
100 }
100 }
101 }
101 }
102 return ToggleButtonView.__super__.update.apply(this);
102 return ToggleButtonView.__super__.update.apply(this);
103 },
103 },
104
104
105 handle_click: function(e) {
105 handle_click: function(e) {
106 // Handles and validates user input.
106 // Handles and validates user input.
107
107
108 // Calling model.set will trigger all of the other views of the
108 // Calling model.set will trigger all of the other views of the
109 // model to update.
109 // model to update.
110 var value = this.model.get('value');
110 var value = this.model.get('value');
111 this.model.set('value', ! value, {updated_view: this});
111 this.model.set('value', ! value, {updated_view: this});
112 this.touch();
112 this.touch();
113 },
113 },
114 });
114 });
115
115
116 return {
116 return {
117 'CheckboxView': CheckboxView,
117 'CheckboxView': CheckboxView,
118 'ToggleButtonView': ToggleButtonView,
118 'ToggleButtonView': ToggleButtonView,
119 };
119 };
120 });
120 });
@@ -1,54 +1,54 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jquery",
6 "jquery",
7 "components/bootstrap/js/bootstrap.min",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var ButtonView = widget.DOMWidgetView.extend({
10 var ButtonView = widget.DOMWidgetView.extend({
11 render : function(){
11 render : function(){
12 // Called when view is rendered.
12 // Called when view is rendered.
13 this.setElement($("<button />")
13 this.setElement($("<button />")
14 .addClass('btn btn-default'));
14 .addClass('btn btn-default'));
15
15
16 this.update(); // Set defaults.
16 this.update(); // Set defaults.
17 },
17 },
18
18
19 update : function(){
19 update : function(){
20 // Update the contents of this view
20 // Update the contents of this view
21 //
21 //
22 // Called when the model is changed. The model may have been
22 // Called when the model is changed. The model may have been
23 // changed by another view or by a state update from the back-end.
23 // changed by another view or by a state update from the back-end.
24 var description = this.model.get('description');
24 var description = this.model.get('description');
25 if (description.length === 0) {
25 if (description.length === 0) {
26 this.$el.html("&nbsp;"); // Preserve button height
26 this.$el.html("&nbsp;"); // Preserve button height
27 } else {
27 } else {
28 this.$el.text(description);
28 this.$el.text(description);
29 }
29 }
30
30
31 if (this.model.get('disabled')) {
31 if (this.model.get('disabled')) {
32 this.$el.attr('disabled','disabled');
32 this.$el.attr('disabled','disabled');
33 } else {
33 } else {
34 this.$el.removeAttr('disabled');
34 this.$el.removeAttr('disabled');
35 }
35 }
36
36
37 return ButtonView.__super__.update.apply(this);
37 return ButtonView.__super__.update.apply(this);
38 },
38 },
39
39
40 events: {
40 events: {
41 // Dictionary of events and their handlers.
41 // Dictionary of events and their handlers.
42 'click': '_handle_click',
42 'click': '_handle_click',
43 },
43 },
44
44
45 _handle_click: function(){
45 _handle_click: function(){
46 // Handles when the button is clicked.
46 // Handles when the button is clicked.
47 this.send({event: 'click'});
47 this.send({event: 'click'});
48 },
48 },
49 });
49 });
50
50
51 return {
51 return {
52 'ButtonView': ButtonView,
52 'ButtonView': ButtonView,
53 };
53 };
54 });
54 });
@@ -1,315 +1,315 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jqueryui",
6 "jqueryui",
7 "components/bootstrap/js/bootstrap.min",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var ContainerView = widget.DOMWidgetView.extend({
10 var ContainerView = widget.DOMWidgetView.extend({
11 render: function(){
11 render: function(){
12 // Called when view is rendered.
12 // Called when view is rendered.
13 this.$el.addClass('widget-container')
13 this.$el.addClass('widget-container')
14 .addClass('vbox');
14 .addClass('vbox');
15 this.update_children([], this.model.get('children'));
15 this.update_children([], this.model.get('children'));
16 this.model.on('change:children', function(model, value, options) {
16 this.model.on('change:children', function(model, value, options) {
17 this.update_children(model.previous('children'), value);
17 this.update_children(model.previous('children'), value);
18 }, this);
18 }, this);
19 this.update();
19 this.update();
20
20
21 // Trigger model displayed events for any models that are child to
21 // Trigger model displayed events for any models that are child to
22 // this model when this model is displayed.
22 // this model when this model is displayed.
23 var that = this;
23 var that = this;
24 this.on('displayed', function(){
24 this.on('displayed', function(){
25 that.is_displayed = true;
25 that.is_displayed = true;
26 for (var property in that.child_views) {
26 for (var property in that.child_views) {
27 if (that.child_views.hasOwnProperty(property)) {
27 if (that.child_views.hasOwnProperty(property)) {
28 that.child_views[property].trigger('displayed');
28 that.child_views[property].trigger('displayed');
29 }
29 }
30 }
30 }
31 });
31 });
32 },
32 },
33
33
34 update_children: function(old_list, new_list) {
34 update_children: function(old_list, new_list) {
35 // Called when the children list changes.
35 // Called when the children list changes.
36 this.do_diff(old_list,
36 this.do_diff(old_list,
37 new_list,
37 new_list,
38 $.proxy(this.remove_child_model, this),
38 $.proxy(this.remove_child_model, this),
39 $.proxy(this.add_child_model, this));
39 $.proxy(this.add_child_model, this));
40 },
40 },
41
41
42 remove_child_model: function(model) {
42 remove_child_model: function(model) {
43 // Called when a model is removed from the children list.
43 // Called when a model is removed from the children list.
44 this.pop_child_view(model).remove();
44 this.pop_child_view(model).remove();
45 },
45 },
46
46
47 add_child_model: function(model) {
47 add_child_model: function(model) {
48 // Called when a model is added to the children list.
48 // Called when a model is added to the children list.
49 var view = this.create_child_view(model);
49 var view = this.create_child_view(model);
50 this.$el.append(view.$el);
50 this.$el.append(view.$el);
51
51
52 // Trigger the displayed event if this model is displayed.
52 // Trigger the displayed event if this model is displayed.
53 if (this.is_displayed) {
53 if (this.is_displayed) {
54 view.trigger('displayed');
54 view.trigger('displayed');
55 }
55 }
56 },
56 },
57
57
58 update: function(){
58 update: function(){
59 // Update the contents of this view
59 // Update the contents of this view
60 //
60 //
61 // Called when the model is changed. The model may have been
61 // Called when the model is changed. The model may have been
62 // changed by another view or by a state update from the back-end.
62 // changed by another view or by a state update from the back-end.
63 return ContainerView.__super__.update.apply(this);
63 return ContainerView.__super__.update.apply(this);
64 },
64 },
65 });
65 });
66
66
67
67
68 var PopupView = widget.DOMWidgetView.extend({
68 var PopupView = widget.DOMWidgetView.extend({
69 render: function(){
69 render: function(){
70 // Called when view is rendered.
70 // Called when view is rendered.
71 var that = this;
71 var that = this;
72
72
73 this.$el.on("remove", function(){
73 this.$el.on("remove", function(){
74 that.$backdrop.remove();
74 that.$backdrop.remove();
75 });
75 });
76 this.$backdrop = $('<div />')
76 this.$backdrop = $('<div />')
77 .appendTo($('#notebook-container'))
77 .appendTo($('#notebook-container'))
78 .addClass('modal-dialog')
78 .addClass('modal-dialog')
79 .css('position', 'absolute')
79 .css('position', 'absolute')
80 .css('left', '0px')
80 .css('left', '0px')
81 .css('top', '0px');
81 .css('top', '0px');
82 this.$window = $('<div />')
82 this.$window = $('<div />')
83 .appendTo(this.$backdrop)
83 .appendTo(this.$backdrop)
84 .addClass('modal-content widget-modal')
84 .addClass('modal-content widget-modal')
85 .mousedown(function(){
85 .mousedown(function(){
86 that.bring_to_front();
86 that.bring_to_front();
87 });
87 });
88
88
89 // Set the elements array since the this.$window element is not child
89 // Set the elements array since the this.$window element is not child
90 // of this.$el and the parent widget manager or other widgets may
90 // of this.$el and the parent widget manager or other widgets may
91 // need to know about all of the top-level widgets. The IPython
91 // need to know about all of the top-level widgets. The IPython
92 // widget manager uses this to register the elements with the
92 // widget manager uses this to register the elements with the
93 // keyboard manager.
93 // keyboard manager.
94 this.additional_elements = [this.$window];
94 this.additional_elements = [this.$window];
95
95
96 this.$title_bar = $('<div />')
96 this.$title_bar = $('<div />')
97 .addClass('popover-title')
97 .addClass('popover-title')
98 .appendTo(this.$window)
98 .appendTo(this.$window)
99 .mousedown(function(){
99 .mousedown(function(){
100 that.bring_to_front();
100 that.bring_to_front();
101 });
101 });
102 this.$close = $('<button />')
102 this.$close = $('<button />')
103 .addClass('close icon-remove')
103 .addClass('close icon-remove')
104 .css('margin-left', '5px')
104 .css('margin-left', '5px')
105 .appendTo(this.$title_bar)
105 .appendTo(this.$title_bar)
106 .click(function(){
106 .click(function(){
107 that.hide();
107 that.hide();
108 event.stopPropagation();
108 event.stopPropagation();
109 });
109 });
110 this.$minimize = $('<button />')
110 this.$minimize = $('<button />')
111 .addClass('close icon-arrow-down')
111 .addClass('close icon-arrow-down')
112 .appendTo(this.$title_bar)
112 .appendTo(this.$title_bar)
113 .click(function(){
113 .click(function(){
114 that.popped_out = !that.popped_out;
114 that.popped_out = !that.popped_out;
115 if (!that.popped_out) {
115 if (!that.popped_out) {
116 that.$minimize
116 that.$minimize
117 .removeClass('icon-arrow-down')
117 .removeClass('icon-arrow-down')
118 .addClass('icon-arrow-up');
118 .addClass('icon-arrow-up');
119
119
120 that.$window
120 that.$window
121 .draggable('destroy')
121 .draggable('destroy')
122 .resizable('destroy')
122 .resizable('destroy')
123 .removeClass('widget-modal modal-content')
123 .removeClass('widget-modal modal-content')
124 .addClass('docked-widget-modal')
124 .addClass('docked-widget-modal')
125 .detach()
125 .detach()
126 .insertBefore(that.$show_button);
126 .insertBefore(that.$show_button);
127 that.$show_button.hide();
127 that.$show_button.hide();
128 that.$close.hide();
128 that.$close.hide();
129 } else {
129 } else {
130 that.$minimize
130 that.$minimize
131 .addClass('icon-arrow-down')
131 .addClass('icon-arrow-down')
132 .removeClass('icon-arrow-up');
132 .removeClass('icon-arrow-up');
133
133
134 that.$window
134 that.$window
135 .removeClass('docked-widget-modal')
135 .removeClass('docked-widget-modal')
136 .addClass('widget-modal modal-content')
136 .addClass('widget-modal modal-content')
137 .detach()
137 .detach()
138 .appendTo(that.$backdrop)
138 .appendTo(that.$backdrop)
139 .draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'})
139 .draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'})
140 .resizable()
140 .resizable()
141 .children('.ui-resizable-handle').show();
141 .children('.ui-resizable-handle').show();
142 that.show();
142 that.show();
143 that.$show_button.show();
143 that.$show_button.show();
144 that.$close.show();
144 that.$close.show();
145 }
145 }
146 event.stopPropagation();
146 event.stopPropagation();
147 });
147 });
148 this.$title = $('<div />')
148 this.$title = $('<div />')
149 .addClass('widget-modal-title')
149 .addClass('widget-modal-title')
150 .html("&nbsp;")
150 .html("&nbsp;")
151 .appendTo(this.$title_bar);
151 .appendTo(this.$title_bar);
152 this.$body = $('<div />')
152 this.$body = $('<div />')
153 .addClass('modal-body')
153 .addClass('modal-body')
154 .addClass('widget-modal-body')
154 .addClass('widget-modal-body')
155 .addClass('widget-container')
155 .addClass('widget-container')
156 .addClass('vbox')
156 .addClass('vbox')
157 .appendTo(this.$window);
157 .appendTo(this.$window);
158
158
159 this.$show_button = $('<button />')
159 this.$show_button = $('<button />')
160 .html("&nbsp;")
160 .html("&nbsp;")
161 .addClass('btn btn-info widget-modal-show')
161 .addClass('btn btn-info widget-modal-show')
162 .appendTo(this.$el)
162 .appendTo(this.$el)
163 .click(function(){
163 .click(function(){
164 that.show();
164 that.show();
165 });
165 });
166
166
167 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
167 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
168 this.$window.resizable();
168 this.$window.resizable();
169 this.$window.on('resize', function(){
169 this.$window.on('resize', function(){
170 that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
170 that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
171 });
171 });
172
172
173 this.$el_to_style = this.$body;
173 this.$el_to_style = this.$body;
174 this._shown_once = false;
174 this._shown_once = false;
175 this.popped_out = true;
175 this.popped_out = true;
176
176
177 this.update_children([], this.model.get('children'));
177 this.update_children([], this.model.get('children'));
178 this.model.on('change:children', function(model, value, options) {
178 this.model.on('change:children', function(model, value, options) {
179 this.update_children(model.previous('children'), value);
179 this.update_children(model.previous('children'), value);
180 }, this);
180 }, this);
181 this.update();
181 this.update();
182
182
183 // Trigger model displayed events for any models that are child to
183 // Trigger model displayed events for any models that are child to
184 // this model when this model is displayed.
184 // this model when this model is displayed.
185 this.on('displayed', function(){
185 this.on('displayed', function(){
186 that.is_displayed = true;
186 that.is_displayed = true;
187 for (var property in that.child_views) {
187 for (var property in that.child_views) {
188 if (that.child_views.hasOwnProperty(property)) {
188 if (that.child_views.hasOwnProperty(property)) {
189 that.child_views[property].trigger('displayed');
189 that.child_views[property].trigger('displayed');
190 }
190 }
191 }
191 }
192 });
192 });
193 },
193 },
194
194
195 hide: function() {
195 hide: function() {
196 // Called when the modal hide button is clicked.
196 // Called when the modal hide button is clicked.
197 this.$window.hide();
197 this.$window.hide();
198 this.$show_button.removeClass('btn-info');
198 this.$show_button.removeClass('btn-info');
199 },
199 },
200
200
201 show: function() {
201 show: function() {
202 // Called when the modal show button is clicked.
202 // Called when the modal show button is clicked.
203 this.$show_button.addClass('btn-info');
203 this.$show_button.addClass('btn-info');
204 this.$window.show();
204 this.$window.show();
205 if (this.popped_out) {
205 if (this.popped_out) {
206 this.$window.css("positon", "absolute");
206 this.$window.css("positon", "absolute");
207 this.$window.css("top", "0px");
207 this.$window.css("top", "0px");
208 this.$window.css("left", Math.max(0, (($('body').outerWidth() - this.$window.outerWidth()) / 2) +
208 this.$window.css("left", Math.max(0, (($('body').outerWidth() - this.$window.outerWidth()) / 2) +
209 $(window).scrollLeft()) + "px");
209 $(window).scrollLeft()) + "px");
210 this.bring_to_front();
210 this.bring_to_front();
211 }
211 }
212 },
212 },
213
213
214 bring_to_front: function() {
214 bring_to_front: function() {
215 // Make the modal top-most, z-ordered about the other modals.
215 // Make the modal top-most, z-ordered about the other modals.
216 var $widget_modals = $(".widget-modal");
216 var $widget_modals = $(".widget-modal");
217 var max_zindex = 0;
217 var max_zindex = 0;
218 $widget_modals.each(function (index, el){
218 $widget_modals.each(function (index, el){
219 var zindex = parseInt($(el).css('z-index'));
219 var zindex = parseInt($(el).css('z-index'));
220 if (!isNaN(zindex)) {
220 if (!isNaN(zindex)) {
221 max_zindex = Math.max(max_zindex, zindex);
221 max_zindex = Math.max(max_zindex, zindex);
222 }
222 }
223 });
223 });
224
224
225 // Start z-index of widget modals at 2000
225 // Start z-index of widget modals at 2000
226 max_zindex = Math.max(max_zindex, 2000);
226 max_zindex = Math.max(max_zindex, 2000);
227
227
228 $widget_modals.each(function (index, el){
228 $widget_modals.each(function (index, el){
229 $el = $(el);
229 $el = $(el);
230 if (max_zindex == parseInt($el.css('z-index'))) {
230 if (max_zindex == parseInt($el.css('z-index'))) {
231 $el.css('z-index', max_zindex - 1);
231 $el.css('z-index', max_zindex - 1);
232 }
232 }
233 });
233 });
234 this.$window.css('z-index', max_zindex);
234 this.$window.css('z-index', max_zindex);
235 },
235 },
236
236
237 update_children: function(old_list, new_list) {
237 update_children: function(old_list, new_list) {
238 // Called when the children list is modified.
238 // Called when the children list is modified.
239 this.do_diff(old_list,
239 this.do_diff(old_list,
240 new_list,
240 new_list,
241 $.proxy(this.remove_child_model, this),
241 $.proxy(this.remove_child_model, this),
242 $.proxy(this.add_child_model, this));
242 $.proxy(this.add_child_model, this));
243 },
243 },
244
244
245 remove_child_model: function(model) {
245 remove_child_model: function(model) {
246 // Called when a child is removed from children list.
246 // Called when a child is removed from children list.
247 this.pop_child_view(model).remove();
247 this.pop_child_view(model).remove();
248 },
248 },
249
249
250 add_child_model: function(model) {
250 add_child_model: function(model) {
251 // Called when a child is added to children list.
251 // Called when a child is added to children list.
252 var view = this.create_child_view(model);
252 var view = this.create_child_view(model);
253 this.$body.append(view.$el);
253 this.$body.append(view.$el);
254
254
255 // Trigger the displayed event if this model is displayed.
255 // Trigger the displayed event if this model is displayed.
256 if (this.is_displayed) {
256 if (this.is_displayed) {
257 view.trigger('displayed');
257 view.trigger('displayed');
258 }
258 }
259 },
259 },
260
260
261 update: function(){
261 update: function(){
262 // Update the contents of this view
262 // Update the contents of this view
263 //
263 //
264 // Called when the model is changed. The model may have been
264 // Called when the model is changed. The model may have been
265 // changed by another view or by a state update from the back-end.
265 // changed by another view or by a state update from the back-end.
266 var description = this.model.get('description');
266 var description = this.model.get('description');
267 if (description.trim().length === 0) {
267 if (description.trim().length === 0) {
268 this.$title.html("&nbsp;"); // Preserve title height
268 this.$title.html("&nbsp;"); // Preserve title height
269 } else {
269 } else {
270 this.$title.text(description);
270 this.$title.text(description);
271 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$title.get(0)]);
271 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$title.get(0)]);
272 }
272 }
273
273
274 var button_text = this.model.get('button_text');
274 var button_text = this.model.get('button_text');
275 if (button_text.trim().length === 0) {
275 if (button_text.trim().length === 0) {
276 this.$show_button.html("&nbsp;"); // Preserve button height
276 this.$show_button.html("&nbsp;"); // Preserve button height
277 } else {
277 } else {
278 this.$show_button.text(button_text);
278 this.$show_button.text(button_text);
279 }
279 }
280
280
281 if (!this._shown_once) {
281 if (!this._shown_once) {
282 this._shown_once = true;
282 this._shown_once = true;
283 this.show();
283 this.show();
284 }
284 }
285
285
286 return PopupView.__super__.update.apply(this);
286 return PopupView.__super__.update.apply(this);
287 },
287 },
288
288
289 _get_selector_element: function(selector) {
289 _get_selector_element: function(selector) {
290 // Get an element view a 'special' jquery selector. (see widget.js)
290 // Get an element view a 'special' jquery selector. (see widget.js)
291 //
291 //
292 // Since the modal actually isn't within the $el in the DOM, we need to extend
292 // Since the modal actually isn't within the $el in the DOM, we need to extend
293 // the selector logic to allow the user to set css on the modal if need be.
293 // the selector logic to allow the user to set css on the modal if need be.
294 // The convention used is:
294 // The convention used is:
295 // "modal" - select the modal div
295 // "modal" - select the modal div
296 // "modal [selector]" - select element(s) within the modal div.
296 // "modal [selector]" - select element(s) within the modal div.
297 // "[selector]" - select elements within $el
297 // "[selector]" - select elements within $el
298 // "" - select the $el_to_style
298 // "" - select the $el_to_style
299 if (selector.substring(0, 5) == 'modal') {
299 if (selector.substring(0, 5) == 'modal') {
300 if (selector == 'modal') {
300 if (selector == 'modal') {
301 return this.$window;
301 return this.$window;
302 } else {
302 } else {
303 return this.$window.find(selector.substring(6));
303 return this.$window.find(selector.substring(6));
304 }
304 }
305 } else {
305 } else {
306 return PopupView.__super__._get_selector_element.apply(this, [selector]);
306 return PopupView.__super__._get_selector_element.apply(this, [selector]);
307 }
307 }
308 },
308 },
309 });
309 });
310
310
311 return {
311 return {
312 'ContainerView': ContainerView,
312 'ContainerView': ContainerView,
313 'PopupView': PopupView,
313 'PopupView': PopupView,
314 };
314 };
315 });
315 });
@@ -1,301 +1,301 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jqueryui",
6 "jqueryui",
7 "components/bootstrap/js/bootstrap.min",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var IntSliderView = widget.DOMWidgetView.extend({
10 var IntSliderView = widget.DOMWidgetView.extend({
11 render : function(){
11 render : function(){
12 // Called when view is rendered.
12 // Called when view is rendered.
13 this.$el
13 this.$el
14 .addClass('widget-hbox-single');
14 .addClass('widget-hbox-single');
15 this.$label = $('<div />')
15 this.$label = $('<div />')
16 .appendTo(this.$el)
16 .appendTo(this.$el)
17 .addClass('widget-hlabel')
17 .addClass('widget-hlabel')
18 .hide();
18 .hide();
19
19
20 this.$slider = $('<div />')
20 this.$slider = $('<div />')
21 .slider({})
21 .slider({})
22 .addClass('slider');
22 .addClass('slider');
23 // Put the slider in a container
23 // Put the slider in a container
24 this.$slider_container = $('<div />')
24 this.$slider_container = $('<div />')
25 .addClass('widget-hslider')
25 .addClass('widget-hslider')
26 .append(this.$slider);
26 .append(this.$slider);
27 this.$el_to_style = this.$slider_container; // Set default element to style
27 this.$el_to_style = this.$slider_container; // Set default element to style
28 this.$el.append(this.$slider_container);
28 this.$el.append(this.$slider_container);
29
29
30 this.$readout = $('<div/>')
30 this.$readout = $('<div/>')
31 .appendTo(this.$el)
31 .appendTo(this.$el)
32 .addClass('widget-hreadout')
32 .addClass('widget-hreadout')
33 .hide();
33 .hide();
34
34
35 // Set defaults.
35 // Set defaults.
36 this.update();
36 this.update();
37 },
37 },
38
38
39 update : function(options){
39 update : function(options){
40 // Update the contents of this view
40 // Update the contents of this view
41 //
41 //
42 // Called when the model is changed. The model may have been
42 // Called when the model is changed. The model may have been
43 // changed by another view or by a state update from the back-end.
43 // changed by another view or by a state update from the back-end.
44 if (options === undefined || options.updated_view != this) {
44 if (options === undefined || options.updated_view != this) {
45 // JQuery slider option keys. These keys happen to have a
45 // JQuery slider option keys. These keys happen to have a
46 // one-to-one mapping with the corrosponding keys of the model.
46 // one-to-one mapping with the corrosponding keys of the model.
47 var jquery_slider_keys = ['step', 'max', 'min', 'disabled'];
47 var jquery_slider_keys = ['step', 'max', 'min', 'disabled'];
48 var that = this;
48 var that = this;
49 that.$slider.slider({});
49 that.$slider.slider({});
50 _.each(jquery_slider_keys, function(key, i) {
50 _.each(jquery_slider_keys, function(key, i) {
51 var model_value = that.model.get(key);
51 var model_value = that.model.get(key);
52 if (model_value !== undefined) {
52 if (model_value !== undefined) {
53 that.$slider.slider("option", key, model_value);
53 that.$slider.slider("option", key, model_value);
54 }
54 }
55 });
55 });
56
56
57 // WORKAROUND FOR JQUERY SLIDER BUG.
57 // WORKAROUND FOR JQUERY SLIDER BUG.
58 // The horizontal position of the slider handle
58 // The horizontal position of the slider handle
59 // depends on the value of the slider at the time
59 // depends on the value of the slider at the time
60 // of orientation change. Before applying the new
60 // of orientation change. Before applying the new
61 // workaround, we set the value to the minimum to
61 // workaround, we set the value to the minimum to
62 // make sure that the horizontal placement of the
62 // make sure that the horizontal placement of the
63 // handle in the vertical slider is always
63 // handle in the vertical slider is always
64 // consistent.
64 // consistent.
65 var orientation = this.model.get('orientation');
65 var orientation = this.model.get('orientation');
66 var value = this.model.get('min');
66 var value = this.model.get('min');
67 this.$slider.slider('option', 'value', value);
67 this.$slider.slider('option', 'value', value);
68 this.$slider.slider('option', 'orientation', orientation);
68 this.$slider.slider('option', 'orientation', orientation);
69 value = this.model.get('value');
69 value = this.model.get('value');
70 this.$slider.slider('option', 'value', value);
70 this.$slider.slider('option', 'value', value);
71 this.$readout.text(value);
71 this.$readout.text(value);
72
72
73 // Use the right CSS classes for vertical & horizontal sliders
73 // Use the right CSS classes for vertical & horizontal sliders
74 if (orientation=='vertical') {
74 if (orientation=='vertical') {
75 this.$slider_container
75 this.$slider_container
76 .removeClass('widget-hslider')
76 .removeClass('widget-hslider')
77 .addClass('widget-vslider');
77 .addClass('widget-vslider');
78 this.$el
78 this.$el
79 .removeClass('widget-hbox-single')
79 .removeClass('widget-hbox-single')
80 .addClass('widget-vbox-single');
80 .addClass('widget-vbox-single');
81 this.$label
81 this.$label
82 .removeClass('widget-hlabel')
82 .removeClass('widget-hlabel')
83 .addClass('widget-vlabel');
83 .addClass('widget-vlabel');
84 this.$readout
84 this.$readout
85 .removeClass('widget-hreadout')
85 .removeClass('widget-hreadout')
86 .addClass('widget-vreadout');
86 .addClass('widget-vreadout');
87
87
88 } else {
88 } else {
89 this.$slider_container
89 this.$slider_container
90 .removeClass('widget-vslider')
90 .removeClass('widget-vslider')
91 .addClass('widget-hslider');
91 .addClass('widget-hslider');
92 this.$el
92 this.$el
93 .removeClass('widget-vbox-single')
93 .removeClass('widget-vbox-single')
94 .addClass('widget-hbox-single');
94 .addClass('widget-hbox-single');
95 this.$label
95 this.$label
96 .removeClass('widget-vlabel')
96 .removeClass('widget-vlabel')
97 .addClass('widget-hlabel');
97 .addClass('widget-hlabel');
98 this.$readout
98 this.$readout
99 .removeClass('widget-vreadout')
99 .removeClass('widget-vreadout')
100 .addClass('widget-hreadout');
100 .addClass('widget-hreadout');
101 }
101 }
102
102
103 var description = this.model.get('description');
103 var description = this.model.get('description');
104 if (description.length === 0) {
104 if (description.length === 0) {
105 this.$label.hide();
105 this.$label.hide();
106 } else {
106 } else {
107 this.$label.text(description);
107 this.$label.text(description);
108 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
108 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
109 this.$label.show();
109 this.$label.show();
110 }
110 }
111
111
112 var readout = this.model.get('readout');
112 var readout = this.model.get('readout');
113 if (readout) {
113 if (readout) {
114 this.$readout.show();
114 this.$readout.show();
115 } else {
115 } else {
116 this.$readout.hide();
116 this.$readout.hide();
117 }
117 }
118 }
118 }
119 return IntSliderView.__super__.update.apply(this);
119 return IntSliderView.__super__.update.apply(this);
120 },
120 },
121
121
122 events: {
122 events: {
123 // Dictionary of events and their handlers.
123 // Dictionary of events and their handlers.
124 "slide" : "handleSliderChange"
124 "slide" : "handleSliderChange"
125 },
125 },
126
126
127 handleSliderChange: function(e, ui) {
127 handleSliderChange: function(e, ui) {
128 // Called when the slider value is changed.
128 // Called when the slider value is changed.
129
129
130 // Calling model.set will trigger all of the other views of the
130 // Calling model.set will trigger all of the other views of the
131 // model to update.
131 // model to update.
132 var actual_value = this._validate_slide_value(ui.value);
132 var actual_value = this._validate_slide_value(ui.value);
133 this.model.set('value', actual_value, {updated_view: this});
133 this.model.set('value', actual_value, {updated_view: this});
134 this.$readout.text(actual_value);
134 this.$readout.text(actual_value);
135 this.touch();
135 this.touch();
136 },
136 },
137
137
138 _validate_slide_value: function(x) {
138 _validate_slide_value: function(x) {
139 // Validate the value of the slider before sending it to the back-end
139 // Validate the value of the slider before sending it to the back-end
140 // and applying it to the other views on the page.
140 // and applying it to the other views on the page.
141
141
142 // Double bit-wise not truncates the decimel (int cast).
142 // Double bit-wise not truncates the decimel (int cast).
143 return ~~x;
143 return ~~x;
144 },
144 },
145 });
145 });
146
146
147
147
148 var IntTextView = widget.DOMWidgetView.extend({
148 var IntTextView = widget.DOMWidgetView.extend({
149 render : function(){
149 render : function(){
150 // Called when view is rendered.
150 // Called when view is rendered.
151 this.$el
151 this.$el
152 .addClass('widget-hbox-single');
152 .addClass('widget-hbox-single');
153 this.$label = $('<div />')
153 this.$label = $('<div />')
154 .appendTo(this.$el)
154 .appendTo(this.$el)
155 .addClass('widget-hlabel')
155 .addClass('widget-hlabel')
156 .hide();
156 .hide();
157 this.$textbox = $('<input type="text" />')
157 this.$textbox = $('<input type="text" />')
158 .addClass('form-control')
158 .addClass('form-control')
159 .addClass('widget-numeric-text')
159 .addClass('widget-numeric-text')
160 .appendTo(this.$el);
160 .appendTo(this.$el);
161 this.$el_to_style = this.$textbox; // Set default element to style
161 this.$el_to_style = this.$textbox; // Set default element to style
162 this.update(); // Set defaults.
162 this.update(); // Set defaults.
163 },
163 },
164
164
165 update : function(options){
165 update : function(options){
166 // Update the contents of this view
166 // Update the contents of this view
167 //
167 //
168 // Called when the model is changed. The model may have been
168 // Called when the model is changed. The model may have been
169 // changed by another view or by a state update from the back-end.
169 // changed by another view or by a state update from the back-end.
170 if (options === undefined || options.updated_view != this) {
170 if (options === undefined || options.updated_view != this) {
171 var value = this.model.get('value');
171 var value = this.model.get('value');
172 if (this._parse_value(this.$textbox.val()) != value) {
172 if (this._parse_value(this.$textbox.val()) != value) {
173 this.$textbox.val(value);
173 this.$textbox.val(value);
174 }
174 }
175
175
176 if (this.model.get('disabled')) {
176 if (this.model.get('disabled')) {
177 this.$textbox.attr('disabled','disabled');
177 this.$textbox.attr('disabled','disabled');
178 } else {
178 } else {
179 this.$textbox.removeAttr('disabled');
179 this.$textbox.removeAttr('disabled');
180 }
180 }
181
181
182 var description = this.model.get('description');
182 var description = this.model.get('description');
183 if (description.length === 0) {
183 if (description.length === 0) {
184 this.$label.hide();
184 this.$label.hide();
185 } else {
185 } else {
186 this.$label.text(description);
186 this.$label.text(description);
187 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
187 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
188 this.$label.show();
188 this.$label.show();
189 }
189 }
190 }
190 }
191 return IntTextView.__super__.update.apply(this);
191 return IntTextView.__super__.update.apply(this);
192 },
192 },
193
193
194 events: {
194 events: {
195 // Dictionary of events and their handlers.
195 // Dictionary of events and their handlers.
196 "keyup input" : "handleChanging",
196 "keyup input" : "handleChanging",
197 "paste input" : "handleChanging",
197 "paste input" : "handleChanging",
198 "cut input" : "handleChanging",
198 "cut input" : "handleChanging",
199
199
200 // Fires only when control is validated or looses focus.
200 // Fires only when control is validated or looses focus.
201 "change input" : "handleChanged"
201 "change input" : "handleChanged"
202 },
202 },
203
203
204 handleChanging: function(e) {
204 handleChanging: function(e) {
205 // Handles and validates user input.
205 // Handles and validates user input.
206
206
207 // Try to parse value as a int.
207 // Try to parse value as a int.
208 var numericalValue = 0;
208 var numericalValue = 0;
209 if (e.target.value !== '') {
209 if (e.target.value !== '') {
210 var trimmed = e.target.value.trim();
210 var trimmed = e.target.value.trim();
211 if (!(['-', '-.', '.', '+.', '+'].indexOf(trimmed) >= 0)) {
211 if (!(['-', '-.', '.', '+.', '+'].indexOf(trimmed) >= 0)) {
212 numericalValue = this._parse_value(e.target.value);
212 numericalValue = this._parse_value(e.target.value);
213 }
213 }
214 }
214 }
215
215
216 // If parse failed, reset value to value stored in model.
216 // If parse failed, reset value to value stored in model.
217 if (isNaN(numericalValue)) {
217 if (isNaN(numericalValue)) {
218 e.target.value = this.model.get('value');
218 e.target.value = this.model.get('value');
219 } else if (!isNaN(numericalValue)) {
219 } else if (!isNaN(numericalValue)) {
220 if (this.model.get('max') !== undefined) {
220 if (this.model.get('max') !== undefined) {
221 numericalValue = Math.min(this.model.get('max'), numericalValue);
221 numericalValue = Math.min(this.model.get('max'), numericalValue);
222 }
222 }
223 if (this.model.get('min') !== undefined) {
223 if (this.model.get('min') !== undefined) {
224 numericalValue = Math.max(this.model.get('min'), numericalValue);
224 numericalValue = Math.max(this.model.get('min'), numericalValue);
225 }
225 }
226
226
227 // Apply the value if it has changed.
227 // Apply the value if it has changed.
228 if (numericalValue != this.model.get('value')) {
228 if (numericalValue != this.model.get('value')) {
229
229
230 // Calling model.set will trigger all of the other views of the
230 // Calling model.set will trigger all of the other views of the
231 // model to update.
231 // model to update.
232 this.model.set('value', numericalValue, {updated_view: this});
232 this.model.set('value', numericalValue, {updated_view: this});
233 this.touch();
233 this.touch();
234 }
234 }
235 }
235 }
236 },
236 },
237
237
238 handleChanged: function(e) {
238 handleChanged: function(e) {
239 // Applies validated input.
239 // Applies validated input.
240 if (this.model.get('value') != e.target.value) {
240 if (this.model.get('value') != e.target.value) {
241 e.target.value = this.model.get('value');
241 e.target.value = this.model.get('value');
242 }
242 }
243 },
243 },
244
244
245 _parse_value: function(value) {
245 _parse_value: function(value) {
246 // Parse the value stored in a string.
246 // Parse the value stored in a string.
247 return parseInt(value);
247 return parseInt(value);
248 },
248 },
249 });
249 });
250
250
251
251
252 var ProgressView = widget.DOMWidgetView.extend({
252 var ProgressView = widget.DOMWidgetView.extend({
253 render : function(){
253 render : function(){
254 // Called when view is rendered.
254 // Called when view is rendered.
255 this.$el
255 this.$el
256 .addClass('widget-hbox-single');
256 .addClass('widget-hbox-single');
257 this.$label = $('<div />')
257 this.$label = $('<div />')
258 .appendTo(this.$el)
258 .appendTo(this.$el)
259 .addClass('widget-hlabel')
259 .addClass('widget-hlabel')
260 .hide();
260 .hide();
261 this.$progress = $('<div />')
261 this.$progress = $('<div />')
262 .addClass('progress')
262 .addClass('progress')
263 .addClass('widget-progress')
263 .addClass('widget-progress')
264 .appendTo(this.$el);
264 .appendTo(this.$el);
265 this.$el_to_style = this.$progress; // Set default element to style
265 this.$el_to_style = this.$progress; // Set default element to style
266 this.$bar = $('<div />')
266 this.$bar = $('<div />')
267 .addClass('progress-bar')
267 .addClass('progress-bar')
268 .css('width', '50%')
268 .css('width', '50%')
269 .appendTo(this.$progress);
269 .appendTo(this.$progress);
270 this.update(); // Set defaults.
270 this.update(); // Set defaults.
271 },
271 },
272
272
273 update : function(){
273 update : function(){
274 // Update the contents of this view
274 // Update the contents of this view
275 //
275 //
276 // Called when the model is changed. The model may have been
276 // Called when the model is changed. The model may have been
277 // changed by another view or by a state update from the back-end.
277 // changed by another view or by a state update from the back-end.
278 var value = this.model.get('value');
278 var value = this.model.get('value');
279 var max = this.model.get('max');
279 var max = this.model.get('max');
280 var min = this.model.get('min');
280 var min = this.model.get('min');
281 var percent = 100.0 * (value - min) / (max - min);
281 var percent = 100.0 * (value - min) / (max - min);
282 this.$bar.css('width', percent + '%');
282 this.$bar.css('width', percent + '%');
283
283
284 var description = this.model.get('description');
284 var description = this.model.get('description');
285 if (description.length === 0) {
285 if (description.length === 0) {
286 this.$label.hide();
286 this.$label.hide();
287 } else {
287 } else {
288 this.$label.text(description);
288 this.$label.text(description);
289 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
289 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
290 this.$label.show();
290 this.$label.show();
291 }
291 }
292 return ProgressView.__super__.update.apply(this);
292 return ProgressView.__super__.update.apply(this);
293 },
293 },
294 });
294 });
295
295
296 return {
296 return {
297 'IntSliderView': IntSliderView,
297 'IntSliderView': IntSliderView,
298 'IntTextView': IntTextView,
298 'IntTextView': IntTextView,
299 'ProgressView': ProgressView,
299 'ProgressView': ProgressView,
300 };
300 };
301 });
301 });
@@ -1,380 +1,380 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "base/js/utils",
6 "base/js/utils",
7 "jquery",
7 "jquery",
8 "components/bootstrap/js/bootstrap.min",
8 "bootstrap",
9 ], function(widget, utils, $){
9 ], function(widget, utils, $){
10
10
11 var DropdownView = widget.DOMWidgetView.extend({
11 var DropdownView = widget.DOMWidgetView.extend({
12 render : function(){
12 render : function(){
13 // Called when view is rendered.
13 // Called when view is rendered.
14 this.$el
14 this.$el
15 .addClass('widget-hbox-single');
15 .addClass('widget-hbox-single');
16 this.$label = $('<div />')
16 this.$label = $('<div />')
17 .appendTo(this.$el)
17 .appendTo(this.$el)
18 .addClass('widget-hlabel')
18 .addClass('widget-hlabel')
19 .hide();
19 .hide();
20 this.$buttongroup = $('<div />')
20 this.$buttongroup = $('<div />')
21 .addClass('widget_item')
21 .addClass('widget_item')
22 .addClass('btn-group')
22 .addClass('btn-group')
23 .appendTo(this.$el);
23 .appendTo(this.$el);
24 this.$el_to_style = this.$buttongroup; // Set default element to style
24 this.$el_to_style = this.$buttongroup; // Set default element to style
25 this.$droplabel = $('<button />')
25 this.$droplabel = $('<button />')
26 .addClass('btn btn-default')
26 .addClass('btn btn-default')
27 .addClass('widget-combo-btn')
27 .addClass('widget-combo-btn')
28 .html("&nbsp;")
28 .html("&nbsp;")
29 .appendTo(this.$buttongroup);
29 .appendTo(this.$buttongroup);
30 this.$dropbutton = $('<button />')
30 this.$dropbutton = $('<button />')
31 .addClass('btn btn-default')
31 .addClass('btn btn-default')
32 .addClass('dropdown-toggle')
32 .addClass('dropdown-toggle')
33 .addClass('widget-combo-carrot-btn')
33 .addClass('widget-combo-carrot-btn')
34 .attr('data-toggle', 'dropdown')
34 .attr('data-toggle', 'dropdown')
35 .append($('<span />').addClass("caret"))
35 .append($('<span />').addClass("caret"))
36 .appendTo(this.$buttongroup);
36 .appendTo(this.$buttongroup);
37 this.$droplist = $('<ul />')
37 this.$droplist = $('<ul />')
38 .addClass('dropdown-menu')
38 .addClass('dropdown-menu')
39 .appendTo(this.$buttongroup);
39 .appendTo(this.$buttongroup);
40
40
41 // Set defaults.
41 // Set defaults.
42 this.update();
42 this.update();
43 },
43 },
44
44
45 update : function(options){
45 update : function(options){
46 // Update the contents of this view
46 // Update the contents of this view
47 //
47 //
48 // Called when the model is changed. The model may have been
48 // Called when the model is changed. The model may have been
49 // changed by another view or by a state update from the back-end.
49 // changed by another view or by a state update from the back-end.
50
50
51 if (options === undefined || options.updated_view != this) {
51 if (options === undefined || options.updated_view != this) {
52 var selected_item_text = this.model.get('value_name');
52 var selected_item_text = this.model.get('value_name');
53 if (selected_item_text.trim().length === 0) {
53 if (selected_item_text.trim().length === 0) {
54 this.$droplabel.html("&nbsp;");
54 this.$droplabel.html("&nbsp;");
55 } else {
55 } else {
56 this.$droplabel.text(selected_item_text);
56 this.$droplabel.text(selected_item_text);
57 }
57 }
58
58
59 var items = this.model.get('value_names');
59 var items = this.model.get('value_names');
60 var $replace_droplist = $('<ul />')
60 var $replace_droplist = $('<ul />')
61 .addClass('dropdown-menu');
61 .addClass('dropdown-menu');
62 var that = this;
62 var that = this;
63 _.each(items, function(item, i) {
63 _.each(items, function(item, i) {
64 var item_button = $('<a href="#"/>')
64 var item_button = $('<a href="#"/>')
65 .text(item)
65 .text(item)
66 .on('click', $.proxy(that.handle_click, that));
66 .on('click', $.proxy(that.handle_click, that));
67 $replace_droplist.append($('<li />').append(item_button));
67 $replace_droplist.append($('<li />').append(item_button));
68 });
68 });
69
69
70 this.$droplist.replaceWith($replace_droplist);
70 this.$droplist.replaceWith($replace_droplist);
71 this.$droplist.remove();
71 this.$droplist.remove();
72 this.$droplist = $replace_droplist;
72 this.$droplist = $replace_droplist;
73
73
74 if (this.model.get('disabled')) {
74 if (this.model.get('disabled')) {
75 this.$buttongroup.attr('disabled','disabled');
75 this.$buttongroup.attr('disabled','disabled');
76 this.$droplabel.attr('disabled','disabled');
76 this.$droplabel.attr('disabled','disabled');
77 this.$dropbutton.attr('disabled','disabled');
77 this.$dropbutton.attr('disabled','disabled');
78 this.$droplist.attr('disabled','disabled');
78 this.$droplist.attr('disabled','disabled');
79 } else {
79 } else {
80 this.$buttongroup.removeAttr('disabled');
80 this.$buttongroup.removeAttr('disabled');
81 this.$droplabel.removeAttr('disabled');
81 this.$droplabel.removeAttr('disabled');
82 this.$dropbutton.removeAttr('disabled');
82 this.$dropbutton.removeAttr('disabled');
83 this.$droplist.removeAttr('disabled');
83 this.$droplist.removeAttr('disabled');
84 }
84 }
85
85
86 var description = this.model.get('description');
86 var description = this.model.get('description');
87 if (description.length === 0) {
87 if (description.length === 0) {
88 this.$label.hide();
88 this.$label.hide();
89 } else {
89 } else {
90 this.$label.text(description);
90 this.$label.text(description);
91 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
91 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
92 this.$label.show();
92 this.$label.show();
93 }
93 }
94 }
94 }
95 return DropdownView.__super__.update.apply(this);
95 return DropdownView.__super__.update.apply(this);
96 },
96 },
97
97
98 handle_click: function (e) {
98 handle_click: function (e) {
99 // Handle when a value is clicked.
99 // Handle when a value is clicked.
100
100
101 // Calling model.set will trigger all of the other views of the
101 // Calling model.set will trigger all of the other views of the
102 // model to update.
102 // model to update.
103 this.model.set('value_name', $(e.target).text(), {updated_view: this});
103 this.model.set('value_name', $(e.target).text(), {updated_view: this});
104 this.touch();
104 this.touch();
105 },
105 },
106
106
107 });
107 });
108
108
109
109
110 var RadioButtonsView = widget.DOMWidgetView.extend({
110 var RadioButtonsView = widget.DOMWidgetView.extend({
111 render : function(){
111 render : function(){
112 // Called when view is rendered.
112 // Called when view is rendered.
113 this.$el
113 this.$el
114 .addClass('widget-hbox');
114 .addClass('widget-hbox');
115 this.$label = $('<div />')
115 this.$label = $('<div />')
116 .appendTo(this.$el)
116 .appendTo(this.$el)
117 .addClass('widget-hlabel')
117 .addClass('widget-hlabel')
118 .hide();
118 .hide();
119 this.$container = $('<div />')
119 this.$container = $('<div />')
120 .appendTo(this.$el)
120 .appendTo(this.$el)
121 .addClass('widget-radio-box');
121 .addClass('widget-radio-box');
122 this.$el_to_style = this.$container; // Set default element to style
122 this.$el_to_style = this.$container; // Set default element to style
123 this.update();
123 this.update();
124 },
124 },
125
125
126 update : function(options){
126 update : function(options){
127 // Update the contents of this view
127 // Update the contents of this view
128 //
128 //
129 // Called when the model is changed. The model may have been
129 // Called when the model is changed. The model may have been
130 // changed by another view or by a state update from the back-end.
130 // changed by another view or by a state update from the back-end.
131 if (options === undefined || options.updated_view != this) {
131 if (options === undefined || options.updated_view != this) {
132 // Add missing items to the DOM.
132 // Add missing items to the DOM.
133 var items = this.model.get('value_names');
133 var items = this.model.get('value_names');
134 var disabled = this.model.get('disabled');
134 var disabled = this.model.get('disabled');
135 var that = this;
135 var that = this;
136 _.each(items, function(item, index) {
136 _.each(items, function(item, index) {
137 var item_query = ' :input[value="' + item + '"]';
137 var item_query = ' :input[value="' + item + '"]';
138 if (that.$el.find(item_query).length === 0) {
138 if (that.$el.find(item_query).length === 0) {
139 var $label = $('<label />')
139 var $label = $('<label />')
140 .addClass('radio')
140 .addClass('radio')
141 .text(item)
141 .text(item)
142 .appendTo(that.$container);
142 .appendTo(that.$container);
143
143
144 $('<input />')
144 $('<input />')
145 .attr('type', 'radio')
145 .attr('type', 'radio')
146 .addClass(that.model)
146 .addClass(that.model)
147 .val(item)
147 .val(item)
148 .prependTo($label)
148 .prependTo($label)
149 .on('click', $.proxy(that.handle_click, that));
149 .on('click', $.proxy(that.handle_click, that));
150 }
150 }
151
151
152 var $item_element = that.$container.find(item_query);
152 var $item_element = that.$container.find(item_query);
153 if (that.model.get('value_name') == item) {
153 if (that.model.get('value_name') == item) {
154 $item_element.prop('checked', true);
154 $item_element.prop('checked', true);
155 } else {
155 } else {
156 $item_element.prop('checked', false);
156 $item_element.prop('checked', false);
157 }
157 }
158 $item_element.prop('disabled', disabled);
158 $item_element.prop('disabled', disabled);
159 });
159 });
160
160
161 // Remove items that no longer exist.
161 // Remove items that no longer exist.
162 this.$container.find('input').each(function(i, obj) {
162 this.$container.find('input').each(function(i, obj) {
163 var value = $(obj).val();
163 var value = $(obj).val();
164 var found = false;
164 var found = false;
165 _.each(items, function(item, index) {
165 _.each(items, function(item, index) {
166 if (item == value) {
166 if (item == value) {
167 found = true;
167 found = true;
168 return false;
168 return false;
169 }
169 }
170 });
170 });
171
171
172 if (!found) {
172 if (!found) {
173 $(obj).parent().remove();
173 $(obj).parent().remove();
174 }
174 }
175 });
175 });
176
176
177 var description = this.model.get('description');
177 var description = this.model.get('description');
178 if (description.length === 0) {
178 if (description.length === 0) {
179 this.$label.hide();
179 this.$label.hide();
180 } else {
180 } else {
181 this.$label.text(description);
181 this.$label.text(description);
182 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
182 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
183 this.$label.show();
183 this.$label.show();
184 }
184 }
185 }
185 }
186 return RadioButtonsView.__super__.update.apply(this);
186 return RadioButtonsView.__super__.update.apply(this);
187 },
187 },
188
188
189 handle_click: function (e) {
189 handle_click: function (e) {
190 // Handle when a value is clicked.
190 // Handle when a value is clicked.
191
191
192 // Calling model.set will trigger all of the other views of the
192 // Calling model.set will trigger all of the other views of the
193 // model to update.
193 // model to update.
194 this.model.set('value_name', $(e.target).val(), {updated_view: this});
194 this.model.set('value_name', $(e.target).val(), {updated_view: this});
195 this.touch();
195 this.touch();
196 },
196 },
197 });
197 });
198
198
199
199
200 var ToggleButtonsView = widget.DOMWidgetView.extend({
200 var ToggleButtonsView = widget.DOMWidgetView.extend({
201 render : function(){
201 render : function(){
202 // Called when view is rendered.
202 // Called when view is rendered.
203 this.$el
203 this.$el
204 .addClass('widget-hbox-single');
204 .addClass('widget-hbox-single');
205 this.$label = $('<div />')
205 this.$label = $('<div />')
206 .appendTo(this.$el)
206 .appendTo(this.$el)
207 .addClass('widget-hlabel')
207 .addClass('widget-hlabel')
208 .hide();
208 .hide();
209 this.$buttongroup = $('<div />')
209 this.$buttongroup = $('<div />')
210 .addClass('btn-group')
210 .addClass('btn-group')
211 .attr('data-toggle', 'buttons-radio')
211 .attr('data-toggle', 'buttons-radio')
212 .appendTo(this.$el);
212 .appendTo(this.$el);
213 this.$el_to_style = this.$buttongroup; // Set default element to style
213 this.$el_to_style = this.$buttongroup; // Set default element to style
214 this.update();
214 this.update();
215 },
215 },
216
216
217 update : function(options){
217 update : function(options){
218 // Update the contents of this view
218 // Update the contents of this view
219 //
219 //
220 // Called when the model is changed. The model may have been
220 // Called when the model is changed. The model may have been
221 // changed by another view or by a state update from the back-end.
221 // changed by another view or by a state update from the back-end.
222 if (options === undefined || options.updated_view != this) {
222 if (options === undefined || options.updated_view != this) {
223 // Add missing items to the DOM.
223 // Add missing items to the DOM.
224 var items = this.model.get('value_names');
224 var items = this.model.get('value_names');
225 var disabled = this.model.get('disabled');
225 var disabled = this.model.get('disabled');
226 var that = this;
226 var that = this;
227 var item_html;
227 var item_html;
228 _.each(items, function(item, index) {
228 _.each(items, function(item, index) {
229 if (item.trim().length == 0) {
229 if (item.trim().length == 0) {
230 item_html = "&nbsp;";
230 item_html = "&nbsp;";
231 } else {
231 } else {
232 item_html = utils.escape_html(item);
232 item_html = utils.escape_html(item);
233 }
233 }
234 var item_query = '[data-value="' + item + '"]';
234 var item_query = '[data-value="' + item + '"]';
235 var $item_element = that.$buttongroup.find(item_query);
235 var $item_element = that.$buttongroup.find(item_query);
236 if (!$item_element.length) {
236 if (!$item_element.length) {
237 $item_element = $('<button/>')
237 $item_element = $('<button/>')
238 .attr('type', 'button')
238 .attr('type', 'button')
239 .addClass('btn btn-default')
239 .addClass('btn btn-default')
240 .html(item_html)
240 .html(item_html)
241 .appendTo(that.$buttongroup)
241 .appendTo(that.$buttongroup)
242 .attr('data-value', item)
242 .attr('data-value', item)
243 .on('click', $.proxy(that.handle_click, that));
243 .on('click', $.proxy(that.handle_click, that));
244 }
244 }
245 if (that.model.get('value_name') == item) {
245 if (that.model.get('value_name') == item) {
246 $item_element.addClass('active');
246 $item_element.addClass('active');
247 } else {
247 } else {
248 $item_element.removeClass('active');
248 $item_element.removeClass('active');
249 }
249 }
250 $item_element.prop('disabled', disabled);
250 $item_element.prop('disabled', disabled);
251 });
251 });
252
252
253 // Remove items that no longer exist.
253 // Remove items that no longer exist.
254 this.$buttongroup.find('button').each(function(i, obj) {
254 this.$buttongroup.find('button').each(function(i, obj) {
255 var value = $(obj).data('value');
255 var value = $(obj).data('value');
256 var found = false;
256 var found = false;
257 _.each(items, function(item, index) {
257 _.each(items, function(item, index) {
258 if (item == value) {
258 if (item == value) {
259 found = true;
259 found = true;
260 return false;
260 return false;
261 }
261 }
262 });
262 });
263
263
264 if (!found) {
264 if (!found) {
265 $(obj).remove();
265 $(obj).remove();
266 }
266 }
267 });
267 });
268
268
269 var description = this.model.get('description');
269 var description = this.model.get('description');
270 if (description.length === 0) {
270 if (description.length === 0) {
271 this.$label.hide();
271 this.$label.hide();
272 } else {
272 } else {
273 this.$label.text(description);
273 this.$label.text(description);
274 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
274 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
275 this.$label.show();
275 this.$label.show();
276 }
276 }
277 }
277 }
278 return ToggleButtonsView.__super__.update.apply(this);
278 return ToggleButtonsView.__super__.update.apply(this);
279 },
279 },
280
280
281 handle_click: function (e) {
281 handle_click: function (e) {
282 // Handle when a value is clicked.
282 // Handle when a value is clicked.
283
283
284 // Calling model.set will trigger all of the other views of the
284 // Calling model.set will trigger all of the other views of the
285 // model to update.
285 // model to update.
286 this.model.set('value_name', $(e.target).data('value'), {updated_view: this});
286 this.model.set('value_name', $(e.target).data('value'), {updated_view: this});
287 this.touch();
287 this.touch();
288 },
288 },
289 });
289 });
290
290
291
291
292 var SelectView = widget.DOMWidgetView.extend({
292 var SelectView = widget.DOMWidgetView.extend({
293 render : function(){
293 render : function(){
294 // Called when view is rendered.
294 // Called when view is rendered.
295 this.$el
295 this.$el
296 .addClass('widget-hbox');
296 .addClass('widget-hbox');
297 this.$label = $('<div />')
297 this.$label = $('<div />')
298 .appendTo(this.$el)
298 .appendTo(this.$el)
299 .addClass('widget-hlabel')
299 .addClass('widget-hlabel')
300 .hide();
300 .hide();
301 this.$listbox = $('<select />')
301 this.$listbox = $('<select />')
302 .addClass('widget-listbox form-control')
302 .addClass('widget-listbox form-control')
303 .attr('size', 6)
303 .attr('size', 6)
304 .appendTo(this.$el);
304 .appendTo(this.$el);
305 this.$el_to_style = this.$listbox; // Set default element to style
305 this.$el_to_style = this.$listbox; // Set default element to style
306 this.update();
306 this.update();
307 },
307 },
308
308
309 update : function(options){
309 update : function(options){
310 // Update the contents of this view
310 // Update the contents of this view
311 //
311 //
312 // Called when the model is changed. The model may have been
312 // Called when the model is changed. The model may have been
313 // changed by another view or by a state update from the back-end.
313 // changed by another view or by a state update from the back-end.
314 if (options === undefined || options.updated_view != this) {
314 if (options === undefined || options.updated_view != this) {
315 // Add missing items to the DOM.
315 // Add missing items to the DOM.
316 var items = this.model.get('value_names');
316 var items = this.model.get('value_names');
317 var that = this;
317 var that = this;
318 _.each(items, function(item, index) {
318 _.each(items, function(item, index) {
319 var item_query = ' :contains("' + item + '")';
319 var item_query = ' :contains("' + item + '")';
320 if (that.$listbox.find(item_query).length === 0) {
320 if (that.$listbox.find(item_query).length === 0) {
321 $('<option />')
321 $('<option />')
322 .text(item)
322 .text(item)
323 .attr('value_name', item)
323 .attr('value_name', item)
324 .appendTo(that.$listbox)
324 .appendTo(that.$listbox)
325 .on('click', $.proxy(that.handle_click, that));
325 .on('click', $.proxy(that.handle_click, that));
326 }
326 }
327 });
327 });
328
328
329 // Select the correct element
329 // Select the correct element
330 this.$listbox.val(this.model.get('value_name'));
330 this.$listbox.val(this.model.get('value_name'));
331
331
332 // Disable listbox if needed
332 // Disable listbox if needed
333 var disabled = this.model.get('disabled');
333 var disabled = this.model.get('disabled');
334 this.$listbox.prop('disabled', disabled);
334 this.$listbox.prop('disabled', disabled);
335
335
336 // Remove items that no longer exist.
336 // Remove items that no longer exist.
337 this.$listbox.find('option').each(function(i, obj) {
337 this.$listbox.find('option').each(function(i, obj) {
338 var value = $(obj).text();
338 var value = $(obj).text();
339 var found = false;
339 var found = false;
340 _.each(items, function(item, index) {
340 _.each(items, function(item, index) {
341 if (item == value) {
341 if (item == value) {
342 found = true;
342 found = true;
343 return false;
343 return false;
344 }
344 }
345 });
345 });
346
346
347 if (!found) {
347 if (!found) {
348 $(obj).remove();
348 $(obj).remove();
349 }
349 }
350 });
350 });
351
351
352 var description = this.model.get('description');
352 var description = this.model.get('description');
353 if (description.length === 0) {
353 if (description.length === 0) {
354 this.$label.hide();
354 this.$label.hide();
355 } else {
355 } else {
356 this.$label.text(description);
356 this.$label.text(description);
357 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
357 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
358 this.$label.show();
358 this.$label.show();
359 }
359 }
360 }
360 }
361 return SelectView.__super__.update.apply(this);
361 return SelectView.__super__.update.apply(this);
362 },
362 },
363
363
364 handle_click: function (e) {
364 handle_click: function (e) {
365 // Handle when a value is clicked.
365 // Handle when a value is clicked.
366
366
367 // Calling model.set will trigger all of the other views of the
367 // Calling model.set will trigger all of the other views of the
368 // model to update.
368 // model to update.
369 this.model.set('value_name', $(e.target).text(), {updated_view: this});
369 this.model.set('value_name', $(e.target).text(), {updated_view: this});
370 this.touch();
370 this.touch();
371 },
371 },
372 });
372 });
373
373
374 return {
374 return {
375 'DropdownView': DropdownView,
375 'DropdownView': DropdownView,
376 'RadioButtonsView': RadioButtonsView,
376 'RadioButtonsView': RadioButtonsView,
377 'ToggleButtonsView': ToggleButtonsView,
377 'ToggleButtonsView': ToggleButtonsView,
378 'SelectView': SelectView,
378 'SelectView': SelectView,
379 };
379 };
380 });
380 });
@@ -1,267 +1,267 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "base/js/utils",
6 "base/js/utils",
7 "jquery",
7 "jquery",
8 "components/bootstrap/js/bootstrap.min",
8 "bootstrap",
9 ], function(widget, utils, $){
9 ], function(widget, utils, $){
10
10
11 var AccordionView = widget.DOMWidgetView.extend({
11 var AccordionView = widget.DOMWidgetView.extend({
12 render: function(){
12 render: function(){
13 // Called when view is rendered.
13 // Called when view is rendered.
14 var guid = 'panel-group' + utils.uuid();
14 var guid = 'panel-group' + utils.uuid();
15 this.$el
15 this.$el
16 .attr('id', guid)
16 .attr('id', guid)
17 .addClass('panel-group');
17 .addClass('panel-group');
18 this.containers = [];
18 this.containers = [];
19 this.model_containers = {};
19 this.model_containers = {};
20 this.update_children([], this.model.get('children'));
20 this.update_children([], this.model.get('children'));
21 this.model.on('change:children', function(model, value, options) {
21 this.model.on('change:children', function(model, value, options) {
22 this.update_children(model.previous('children'), value);
22 this.update_children(model.previous('children'), value);
23 }, this);
23 }, this);
24 this.model.on('change:selected_index', function(model, value, options) {
24 this.model.on('change:selected_index', function(model, value, options) {
25 this.update_selected_index(model.previous('selected_index'), value, options);
25 this.update_selected_index(model.previous('selected_index'), value, options);
26 }, this);
26 }, this);
27 this.model.on('change:_titles', function(model, value, options) {
27 this.model.on('change:_titles', function(model, value, options) {
28 this.update_titles(value);
28 this.update_titles(value);
29 }, this);
29 }, this);
30 var that = this;
30 var that = this;
31 this.on('displayed', function() {
31 this.on('displayed', function() {
32 this.update_titles();
32 this.update_titles();
33 // Trigger model displayed events for any models that are child to
33 // Trigger model displayed events for any models that are child to
34 // this model when this model is displayed.
34 // this model when this model is displayed.
35 that.is_displayed = true;
35 that.is_displayed = true;
36 for (var property in that.child_views) {
36 for (var property in that.child_views) {
37 if (that.child_views.hasOwnProperty(property)) {
37 if (that.child_views.hasOwnProperty(property)) {
38 that.child_views[property].trigger('displayed');
38 that.child_views[property].trigger('displayed');
39 }
39 }
40 }
40 }
41 }, this);
41 }, this);
42 },
42 },
43
43
44 update_titles: function(titles) {
44 update_titles: function(titles) {
45 // Set tab titles
45 // Set tab titles
46 if (!titles) {
46 if (!titles) {
47 titles = this.model.get('_titles');
47 titles = this.model.get('_titles');
48 }
48 }
49
49
50 var that = this;
50 var that = this;
51 _.each(titles, function(title, page_index) {
51 _.each(titles, function(title, page_index) {
52 var accordian = that.containers[page_index];
52 var accordian = that.containers[page_index];
53 if (accordian !== undefined) {
53 if (accordian !== undefined) {
54 accordian
54 accordian
55 .find('.panel-heading')
55 .find('.panel-heading')
56 .find('.accordion-toggle')
56 .find('.accordion-toggle')
57 .text(title);
57 .text(title);
58 }
58 }
59 });
59 });
60 },
60 },
61
61
62 update_selected_index: function(old_index, new_index, options) {
62 update_selected_index: function(old_index, new_index, options) {
63 // Only update the selection if the selection wasn't triggered
63 // Only update the selection if the selection wasn't triggered
64 // by the front-end. It must be triggered by the back-end.
64 // by the front-end. It must be triggered by the back-end.
65 if (options === undefined || options.updated_view != this) {
65 if (options === undefined || options.updated_view != this) {
66 this.containers[old_index].find('.panel-collapse').collapse('hide');
66 this.containers[old_index].find('.panel-collapse').collapse('hide');
67 if (0 <= new_index && new_index < this.containers.length) {
67 if (0 <= new_index && new_index < this.containers.length) {
68 this.containers[new_index].find('.panel-collapse').collapse('show');
68 this.containers[new_index].find('.panel-collapse').collapse('show');
69 }
69 }
70 }
70 }
71 },
71 },
72
72
73 update_children: function(old_list, new_list) {
73 update_children: function(old_list, new_list) {
74 // Called when the children list is modified.
74 // Called when the children list is modified.
75 this.do_diff(old_list,
75 this.do_diff(old_list,
76 new_list,
76 new_list,
77 $.proxy(this.remove_child_model, this),
77 $.proxy(this.remove_child_model, this),
78 $.proxy(this.add_child_model, this));
78 $.proxy(this.add_child_model, this));
79 },
79 },
80
80
81 remove_child_model: function(model) {
81 remove_child_model: function(model) {
82 // Called when a child is removed from children list.
82 // Called when a child is removed from children list.
83 var accordion_group = this.model_containers[model.id];
83 var accordion_group = this.model_containers[model.id];
84 this.containers.splice(accordion_group.container_index, 1);
84 this.containers.splice(accordion_group.container_index, 1);
85 delete this.model_containers[model.id];
85 delete this.model_containers[model.id];
86 accordion_group.remove();
86 accordion_group.remove();
87 this.pop_child_view(model);
87 this.pop_child_view(model);
88 },
88 },
89
89
90 add_child_model: function(model) {
90 add_child_model: function(model) {
91 // Called when a child is added to children list.
91 // Called when a child is added to children list.
92 var view = this.create_child_view(model);
92 var view = this.create_child_view(model);
93 var index = this.containers.length;
93 var index = this.containers.length;
94 var uuid = utils.uuid();
94 var uuid = utils.uuid();
95 var accordion_group = $('<div />')
95 var accordion_group = $('<div />')
96 .addClass('panel panel-default')
96 .addClass('panel panel-default')
97 .appendTo(this.$el);
97 .appendTo(this.$el);
98 var accordion_heading = $('<div />')
98 var accordion_heading = $('<div />')
99 .addClass('panel-heading')
99 .addClass('panel-heading')
100 .appendTo(accordion_group);
100 .appendTo(accordion_group);
101 var that = this;
101 var that = this;
102 var accordion_toggle = $('<a />')
102 var accordion_toggle = $('<a />')
103 .addClass('accordion-toggle')
103 .addClass('accordion-toggle')
104 .attr('data-toggle', 'collapse')
104 .attr('data-toggle', 'collapse')
105 .attr('data-parent', '#' + this.$el.attr('id'))
105 .attr('data-parent', '#' + this.$el.attr('id'))
106 .attr('href', '#' + uuid)
106 .attr('href', '#' + uuid)
107 .click(function(evt){
107 .click(function(evt){
108
108
109 // Calling model.set will trigger all of the other views of the
109 // Calling model.set will trigger all of the other views of the
110 // model to update.
110 // model to update.
111 that.model.set("selected_index", index, {updated_view: that});
111 that.model.set("selected_index", index, {updated_view: that});
112 that.touch();
112 that.touch();
113 })
113 })
114 .text('Page ' + index)
114 .text('Page ' + index)
115 .appendTo(accordion_heading);
115 .appendTo(accordion_heading);
116 var accordion_body = $('<div />', {id: uuid})
116 var accordion_body = $('<div />', {id: uuid})
117 .addClass('panel-collapse collapse')
117 .addClass('panel-collapse collapse')
118 .appendTo(accordion_group);
118 .appendTo(accordion_group);
119 var accordion_inner = $('<div />')
119 var accordion_inner = $('<div />')
120 .addClass('panel-body')
120 .addClass('panel-body')
121 .appendTo(accordion_body);
121 .appendTo(accordion_body);
122 var container_index = this.containers.push(accordion_group) - 1;
122 var container_index = this.containers.push(accordion_group) - 1;
123 accordion_group.container_index = container_index;
123 accordion_group.container_index = container_index;
124 this.model_containers[model.id] = accordion_group;
124 this.model_containers[model.id] = accordion_group;
125 accordion_inner.append(view.$el);
125 accordion_inner.append(view.$el);
126
126
127 this.update();
127 this.update();
128 this.update_titles();
128 this.update_titles();
129
129
130 // Trigger the displayed event if this model is displayed.
130 // Trigger the displayed event if this model is displayed.
131 if (this.is_displayed) {
131 if (this.is_displayed) {
132 view.trigger('displayed');
132 view.trigger('displayed');
133 }
133 }
134 },
134 },
135 });
135 });
136
136
137
137
138 var TabView = widget.DOMWidgetView.extend({
138 var TabView = widget.DOMWidgetView.extend({
139 initialize: function() {
139 initialize: function() {
140 // Public constructor.
140 // Public constructor.
141 this.containers = [];
141 this.containers = [];
142 TabView.__super__.initialize.apply(this, arguments);
142 TabView.__super__.initialize.apply(this, arguments);
143 },
143 },
144
144
145 render: function(){
145 render: function(){
146 // Called when view is rendered.
146 // Called when view is rendered.
147 var uuid = 'tabs'+utils.uuid();
147 var uuid = 'tabs'+utils.uuid();
148 var that = this;
148 var that = this;
149 this.$tabs = $('<div />', {id: uuid})
149 this.$tabs = $('<div />', {id: uuid})
150 .addClass('nav')
150 .addClass('nav')
151 .addClass('nav-tabs')
151 .addClass('nav-tabs')
152 .appendTo(this.$el);
152 .appendTo(this.$el);
153 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
153 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
154 .addClass('tab-content')
154 .addClass('tab-content')
155 .appendTo(this.$el);
155 .appendTo(this.$el);
156 this.containers = [];
156 this.containers = [];
157 this.update_children([], this.model.get('children'));
157 this.update_children([], this.model.get('children'));
158 this.model.on('change:children', function(model, value, options) {
158 this.model.on('change:children', function(model, value, options) {
159 this.update_children(model.previous('children'), value);
159 this.update_children(model.previous('children'), value);
160 }, this);
160 }, this);
161
161
162 // Trigger model displayed events for any models that are child to
162 // Trigger model displayed events for any models that are child to
163 // this model when this model is displayed.
163 // this model when this model is displayed.
164 this.on('displayed', function(){
164 this.on('displayed', function(){
165 that.is_displayed = true;
165 that.is_displayed = true;
166 for (var property in that.child_views) {
166 for (var property in that.child_views) {
167 if (that.child_views.hasOwnProperty(property)) {
167 if (that.child_views.hasOwnProperty(property)) {
168 that.child_views[property].trigger('displayed');
168 that.child_views[property].trigger('displayed');
169 }
169 }
170 }
170 }
171 });
171 });
172 },
172 },
173
173
174 update_children: function(old_list, new_list) {
174 update_children: function(old_list, new_list) {
175 // Called when the children list is modified.
175 // Called when the children list is modified.
176 this.do_diff(old_list,
176 this.do_diff(old_list,
177 new_list,
177 new_list,
178 $.proxy(this.remove_child_model, this),
178 $.proxy(this.remove_child_model, this),
179 $.proxy(this.add_child_model, this));
179 $.proxy(this.add_child_model, this));
180 },
180 },
181
181
182 remove_child_model: function(model) {
182 remove_child_model: function(model) {
183 // Called when a child is removed from children list.
183 // Called when a child is removed from children list.
184 var view = this.pop_child_view(model);
184 var view = this.pop_child_view(model);
185 this.containers.splice(view.parent_tab.tab_text_index, 1);
185 this.containers.splice(view.parent_tab.tab_text_index, 1);
186 view.parent_tab.remove();
186 view.parent_tab.remove();
187 view.parent_container.remove();
187 view.parent_container.remove();
188 view.remove();
188 view.remove();
189 },
189 },
190
190
191 add_child_model: function(model) {
191 add_child_model: function(model) {
192 // Called when a child is added to children list.
192 // Called when a child is added to children list.
193 var view = this.create_child_view(model);
193 var view = this.create_child_view(model);
194 var index = this.containers.length;
194 var index = this.containers.length;
195 var uuid = utils.uuid();
195 var uuid = utils.uuid();
196
196
197 var that = this;
197 var that = this;
198 var tab = $('<li />')
198 var tab = $('<li />')
199 .css('list-style-type', 'none')
199 .css('list-style-type', 'none')
200 .appendTo(this.$tabs);
200 .appendTo(this.$tabs);
201 view.parent_tab = tab;
201 view.parent_tab = tab;
202
202
203 var tab_text = $('<a />')
203 var tab_text = $('<a />')
204 .attr('href', '#' + uuid)
204 .attr('href', '#' + uuid)
205 .attr('data-toggle', 'tab')
205 .attr('data-toggle', 'tab')
206 .text('Page ' + index)
206 .text('Page ' + index)
207 .appendTo(tab)
207 .appendTo(tab)
208 .click(function (e) {
208 .click(function (e) {
209
209
210 // Calling model.set will trigger all of the other views of the
210 // Calling model.set will trigger all of the other views of the
211 // model to update.
211 // model to update.
212 that.model.set("selected_index", index, {updated_view: this});
212 that.model.set("selected_index", index, {updated_view: this});
213 that.touch();
213 that.touch();
214 that.select_page(index);
214 that.select_page(index);
215 });
215 });
216 tab.tab_text_index = this.containers.push(tab_text) - 1;
216 tab.tab_text_index = this.containers.push(tab_text) - 1;
217
217
218 var contents_div = $('<div />', {id: uuid})
218 var contents_div = $('<div />', {id: uuid})
219 .addClass('tab-pane')
219 .addClass('tab-pane')
220 .addClass('fade')
220 .addClass('fade')
221 .append(view.$el)
221 .append(view.$el)
222 .appendTo(this.$tab_contents);
222 .appendTo(this.$tab_contents);
223 view.parent_container = contents_div;
223 view.parent_container = contents_div;
224
224
225 // Trigger the displayed event if this model is displayed.
225 // Trigger the displayed event if this model is displayed.
226 if (this.is_displayed) {
226 if (this.is_displayed) {
227 view.trigger('displayed');
227 view.trigger('displayed');
228 }
228 }
229 },
229 },
230
230
231 update: function(options) {
231 update: function(options) {
232 // Update the contents of this view
232 // Update the contents of this view
233 //
233 //
234 // Called when the model is changed. The model may have been
234 // Called when the model is changed. The model may have been
235 // changed by another view or by a state update from the back-end.
235 // changed by another view or by a state update from the back-end.
236 if (options === undefined || options.updated_view != this) {
236 if (options === undefined || options.updated_view != this) {
237 // Set tab titles
237 // Set tab titles
238 var titles = this.model.get('_titles');
238 var titles = this.model.get('_titles');
239 var that = this;
239 var that = this;
240 _.each(titles, function(title, page_index) {
240 _.each(titles, function(title, page_index) {
241 var tab_text = that.containers[page_index];
241 var tab_text = that.containers[page_index];
242 if (tab_text !== undefined) {
242 if (tab_text !== undefined) {
243 tab_text.text(title);
243 tab_text.text(title);
244 }
244 }
245 });
245 });
246
246
247 var selected_index = this.model.get('selected_index');
247 var selected_index = this.model.get('selected_index');
248 if (0 <= selected_index && selected_index < this.containers.length) {
248 if (0 <= selected_index && selected_index < this.containers.length) {
249 this.select_page(selected_index);
249 this.select_page(selected_index);
250 }
250 }
251 }
251 }
252 return TabView.__super__.update.apply(this);
252 return TabView.__super__.update.apply(this);
253 },
253 },
254
254
255 select_page: function(index) {
255 select_page: function(index) {
256 // Select a page.
256 // Select a page.
257 this.$tabs.find('li')
257 this.$tabs.find('li')
258 .removeClass('active');
258 .removeClass('active');
259 this.containers[index].tab('show');
259 this.containers[index].tab('show');
260 },
260 },
261 });
261 });
262
262
263 return {
263 return {
264 'AccordionView': AccordionView,
264 'AccordionView': AccordionView,
265 'TabView': TabView,
265 'TabView': TabView,
266 };
266 };
267 });
267 });
@@ -1,242 +1,242 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([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jquery",
6 "jquery",
7 "components/bootstrap/js/bootstrap.min",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var HTMLView = widget.DOMWidgetView.extend({
10 var HTMLView = widget.DOMWidgetView.extend({
11 render : function(){
11 render : function(){
12 // Called when view is rendered.
12 // Called when view is rendered.
13 this.update(); // Set defaults.
13 this.update(); // Set defaults.
14 },
14 },
15
15
16 update : function(){
16 update : function(){
17 // Update the contents of this view
17 // Update the contents of this view
18 //
18 //
19 // Called when the model is changed. The model may have been
19 // Called when the model is changed. The model may have been
20 // changed by another view or by a state update from the back-end.
20 // changed by another view or by a state update from the back-end.
21 this.$el.html(this.model.get('value')); // CAUTION! .html(...) CALL MANDITORY!!!
21 this.$el.html(this.model.get('value')); // CAUTION! .html(...) CALL MANDITORY!!!
22 return HTMLView.__super__.update.apply(this);
22 return HTMLView.__super__.update.apply(this);
23 },
23 },
24 });
24 });
25
25
26
26
27 var LatexView = widget.DOMWidgetView.extend({
27 var LatexView = widget.DOMWidgetView.extend({
28 render : function(){
28 render : function(){
29 // Called when view is rendered.
29 // Called when view is rendered.
30 this.update(); // Set defaults.
30 this.update(); // Set defaults.
31 },
31 },
32
32
33 update : function(){
33 update : function(){
34 // Update the contents of this view
34 // Update the contents of this view
35 //
35 //
36 // Called when the model is changed. The model may have been
36 // Called when the model is changed. The model may have been
37 // changed by another view or by a state update from the back-end.
37 // changed by another view or by a state update from the back-end.
38 this.$el.text(this.model.get('value'));
38 this.$el.text(this.model.get('value'));
39 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$el.get(0)]);
39 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$el.get(0)]);
40
40
41 return LatexView.__super__.update.apply(this);
41 return LatexView.__super__.update.apply(this);
42 },
42 },
43 });
43 });
44
44
45
45
46 var TextareaView = widget.DOMWidgetView.extend({
46 var TextareaView = widget.DOMWidgetView.extend({
47 render: function(){
47 render: function(){
48 // Called when view is rendered.
48 // Called when view is rendered.
49 this.$el
49 this.$el
50 .addClass('widget-hbox');
50 .addClass('widget-hbox');
51 this.$label = $('<div />')
51 this.$label = $('<div />')
52 .appendTo(this.$el)
52 .appendTo(this.$el)
53 .addClass('widget-hlabel')
53 .addClass('widget-hlabel')
54 .hide();
54 .hide();
55 this.$textbox = $('<textarea />')
55 this.$textbox = $('<textarea />')
56 .attr('rows', 5)
56 .attr('rows', 5)
57 .addClass('widget-text form-control')
57 .addClass('widget-text form-control')
58 .appendTo(this.$el);
58 .appendTo(this.$el);
59 this.$el_to_style = this.$textbox; // Set default element to style
59 this.$el_to_style = this.$textbox; // Set default element to style
60 this.update(); // Set defaults.
60 this.update(); // Set defaults.
61
61
62 this.model.on('msg:custom', $.proxy(this._handle_textarea_msg, this));
62 this.model.on('msg:custom', $.proxy(this._handle_textarea_msg, this));
63 this.model.on('change:placeholder', function(model, value, options) {
63 this.model.on('change:placeholder', function(model, value, options) {
64 this.update_placeholder(value);
64 this.update_placeholder(value);
65 }, this);
65 }, this);
66
66
67 this.update_placeholder();
67 this.update_placeholder();
68 },
68 },
69
69
70 _handle_textarea_msg: function (content){
70 _handle_textarea_msg: function (content){
71 // Handle when a custom msg is recieved from the back-end.
71 // Handle when a custom msg is recieved from the back-end.
72 if (content.method == "scroll_to_bottom") {
72 if (content.method == "scroll_to_bottom") {
73 this.scroll_to_bottom();
73 this.scroll_to_bottom();
74 }
74 }
75 },
75 },
76
76
77 update_placeholder: function(value) {
77 update_placeholder: function(value) {
78 if (!value) {
78 if (!value) {
79 value = this.model.get('placeholder');
79 value = this.model.get('placeholder');
80 }
80 }
81 this.$textbox.attr('placeholder', value);
81 this.$textbox.attr('placeholder', value);
82 },
82 },
83
83
84 scroll_to_bottom: function (){
84 scroll_to_bottom: function (){
85 // Scroll the text-area view to the bottom.
85 // Scroll the text-area view to the bottom.
86 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
86 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
87 },
87 },
88
88
89 update: function(options){
89 update: function(options){
90 // Update the contents of this view
90 // Update the contents of this view
91 //
91 //
92 // Called when the model is changed. The model may have been
92 // Called when the model is changed. The model may have been
93 // changed by another view or by a state update from the back-end.
93 // changed by another view or by a state update from the back-end.
94 if (options === undefined || options.updated_view != this) {
94 if (options === undefined || options.updated_view != this) {
95 this.$textbox.val(this.model.get('value'));
95 this.$textbox.val(this.model.get('value'));
96
96
97 var disabled = this.model.get('disabled');
97 var disabled = this.model.get('disabled');
98 this.$textbox.prop('disabled', disabled);
98 this.$textbox.prop('disabled', disabled);
99
99
100 var description = this.model.get('description');
100 var description = this.model.get('description');
101 if (description.length === 0) {
101 if (description.length === 0) {
102 this.$label.hide();
102 this.$label.hide();
103 } else {
103 } else {
104 this.$label.text(description);
104 this.$label.text(description);
105 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
105 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
106 this.$label.show();
106 this.$label.show();
107 }
107 }
108 }
108 }
109 return TextareaView.__super__.update.apply(this);
109 return TextareaView.__super__.update.apply(this);
110 },
110 },
111
111
112 events: {
112 events: {
113 // Dictionary of events and their handlers.
113 // Dictionary of events and their handlers.
114 "keyup textarea" : "handleChanging",
114 "keyup textarea" : "handleChanging",
115 "paste textarea" : "handleChanging",
115 "paste textarea" : "handleChanging",
116 "cut textarea" : "handleChanging"
116 "cut textarea" : "handleChanging"
117 },
117 },
118
118
119 handleChanging: function(e) {
119 handleChanging: function(e) {
120 // Handles and validates user input.
120 // Handles and validates user input.
121
121
122 // Calling model.set will trigger all of the other views of the
122 // Calling model.set will trigger all of the other views of the
123 // model to update.
123 // model to update.
124 this.model.set('value', e.target.value, {updated_view: this});
124 this.model.set('value', e.target.value, {updated_view: this});
125 this.touch();
125 this.touch();
126 },
126 },
127 });
127 });
128
128
129
129
130 var TextView = widget.DOMWidgetView.extend({
130 var TextView = widget.DOMWidgetView.extend({
131 render: function(){
131 render: function(){
132 // Called when view is rendered.
132 // Called when view is rendered.
133 this.$el
133 this.$el
134 .addClass('widget-hbox-single');
134 .addClass('widget-hbox-single');
135 this.$label = $('<div />')
135 this.$label = $('<div />')
136 .addClass('widget-hlabel')
136 .addClass('widget-hlabel')
137 .appendTo(this.$el)
137 .appendTo(this.$el)
138 .hide();
138 .hide();
139 this.$textbox = $('<input type="text" />')
139 this.$textbox = $('<input type="text" />')
140 .addClass('input')
140 .addClass('input')
141 .addClass('widget-text form-control')
141 .addClass('widget-text form-control')
142 .appendTo(this.$el);
142 .appendTo(this.$el);
143 this.$el_to_style = this.$textbox; // Set default element to style
143 this.$el_to_style = this.$textbox; // Set default element to style
144 this.update(); // Set defaults.
144 this.update(); // Set defaults.
145 this.model.on('change:placeholder', function(model, value, options) {
145 this.model.on('change:placeholder', function(model, value, options) {
146 this.update_placeholder(value);
146 this.update_placeholder(value);
147 }, this);
147 }, this);
148
148
149 this.update_placeholder();
149 this.update_placeholder();
150 },
150 },
151
151
152 update_placeholder: function(value) {
152 update_placeholder: function(value) {
153 if (!value) {
153 if (!value) {
154 value = this.model.get('placeholder');
154 value = this.model.get('placeholder');
155 }
155 }
156 this.$textbox.attr('placeholder', value);
156 this.$textbox.attr('placeholder', value);
157 },
157 },
158
158
159 update: function(options){
159 update: function(options){
160 // Update the contents of this view
160 // Update the contents of this view
161 //
161 //
162 // Called when the model is changed. The model may have been
162 // Called when the model is changed. The model may have been
163 // changed by another view or by a state update from the back-end.
163 // changed by another view or by a state update from the back-end.
164 if (options === undefined || options.updated_view != this) {
164 if (options === undefined || options.updated_view != this) {
165 if (this.$textbox.val() != this.model.get('value')) {
165 if (this.$textbox.val() != this.model.get('value')) {
166 this.$textbox.val(this.model.get('value'));
166 this.$textbox.val(this.model.get('value'));
167 }
167 }
168
168
169 var disabled = this.model.get('disabled');
169 var disabled = this.model.get('disabled');
170 this.$textbox.prop('disabled', disabled);
170 this.$textbox.prop('disabled', disabled);
171
171
172 var description = this.model.get('description');
172 var description = this.model.get('description');
173 if (description.length === 0) {
173 if (description.length === 0) {
174 this.$label.hide();
174 this.$label.hide();
175 } else {
175 } else {
176 this.$label.text(description);
176 this.$label.text(description);
177 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
177 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
178 this.$label.show();
178 this.$label.show();
179 }
179 }
180 }
180 }
181 return TextView.__super__.update.apply(this);
181 return TextView.__super__.update.apply(this);
182 },
182 },
183
183
184 events: {
184 events: {
185 // Dictionary of events and their handlers.
185 // Dictionary of events and their handlers.
186 "keyup input" : "handleChanging",
186 "keyup input" : "handleChanging",
187 "paste input" : "handleChanging",
187 "paste input" : "handleChanging",
188 "cut input" : "handleChanging",
188 "cut input" : "handleChanging",
189 "keypress input" : "handleKeypress",
189 "keypress input" : "handleKeypress",
190 "blur input" : "handleBlur",
190 "blur input" : "handleBlur",
191 "focusout input" : "handleFocusOut"
191 "focusout input" : "handleFocusOut"
192 },
192 },
193
193
194 handleChanging: function(e) {
194 handleChanging: function(e) {
195 // Handles user input.
195 // Handles user input.
196
196
197 // Calling model.set will trigger all of the other views of the
197 // Calling model.set will trigger all of the other views of the
198 // model to update.
198 // model to update.
199 this.model.set('value', e.target.value, {updated_view: this});
199 this.model.set('value', e.target.value, {updated_view: this});
200 this.touch();
200 this.touch();
201 },
201 },
202
202
203 handleKeypress: function(e) {
203 handleKeypress: function(e) {
204 // Handles text submition
204 // Handles text submition
205 if (e.keyCode == 13) { // Return key
205 if (e.keyCode == 13) { // Return key
206 this.send({event: 'submit'});
206 this.send({event: 'submit'});
207 event.stopPropagation();
207 event.stopPropagation();
208 event.preventDefault();
208 event.preventDefault();
209 return false;
209 return false;
210 }
210 }
211 },
211 },
212
212
213 handleBlur: function(e) {
213 handleBlur: function(e) {
214 // Prevent a blur from firing if the blur was not user intended.
214 // Prevent a blur from firing if the blur was not user intended.
215 // This is a workaround for the return-key focus loss bug.
215 // This is a workaround for the return-key focus loss bug.
216 // TODO: Is the original bug actually a fault of the keyboard
216 // TODO: Is the original bug actually a fault of the keyboard
217 // manager?
217 // manager?
218 if (e.relatedTarget === null) {
218 if (e.relatedTarget === null) {
219 event.stopPropagation();
219 event.stopPropagation();
220 event.preventDefault();
220 event.preventDefault();
221 return false;
221 return false;
222 }
222 }
223 },
223 },
224
224
225 handleFocusOut: function(e) {
225 handleFocusOut: function(e) {
226 // Prevent a blur from firing if the blur was not user intended.
226 // Prevent a blur from firing if the blur was not user intended.
227 // This is a workaround for the return-key focus loss bug.
227 // This is a workaround for the return-key focus loss bug.
228 if (e.relatedTarget === null) {
228 if (e.relatedTarget === null) {
229 event.stopPropagation();
229 event.stopPropagation();
230 event.preventDefault();
230 event.preventDefault();
231 return false;
231 return false;
232 }
232 }
233 },
233 },
234 });
234 });
235
235
236 return {
236 return {
237 'HTMLView': HTMLView,
237 'HTMLView': HTMLView,
238 'LatexView': LatexView,
238 'LatexView': LatexView,
239 'TextareaView': TextareaView,
239 'TextareaView': TextareaView,
240 'TextView': TextView,
240 'TextView': TextView,
241 };
241 };
242 });
242 });
@@ -1,99 +1,105 b''
1 <!DOCTYPE HTML>
1 <!DOCTYPE HTML>
2 <html>
2 <html>
3
3
4 <head>
4 <head>
5 <meta charset="utf-8">
5 <meta charset="utf-8">
6
6
7 <title>{% block title %}IPython Notebook{% endblock %}</title>
7 <title>{% block title %}IPython Notebook{% endblock %}</title>
8 <link rel="shortcut icon" type="image/x-icon" href="{{static_url("base/images/favicon.ico") }}">
8 <link rel="shortcut icon" type="image/x-icon" href="{{static_url("base/images/favicon.ico") }}">
9 <meta http-equiv="X-UA-Compatible" content="chrome=1">
9 <meta http-equiv="X-UA-Compatible" content="chrome=1">
10 <link rel="stylesheet" href="{{static_url("components/jquery-ui/themes/smoothness/jquery-ui.min.css") }}" type="text/css" />
10 <link rel="stylesheet" href="{{static_url("components/jquery-ui/themes/smoothness/jquery-ui.min.css") }}" type="text/css" />
11 <meta name="viewport" content="width=device-width, initial-scale=1.0">
11 <meta name="viewport" content="width=device-width, initial-scale=1.0">
12
12
13 {% block stylesheet %}
13 {% block stylesheet %}
14 <link rel="stylesheet" href="{{ static_url("style/style.min.css") }}" type="text/css"/>
14 <link rel="stylesheet" href="{{ static_url("style/style.min.css") }}" type="text/css"/>
15 {% endblock %}
15 {% endblock %}
16 <link rel="stylesheet" href="{{ static_url("custom/custom.css") }}" type="text/css" />
16 <link rel="stylesheet" href="{{ static_url("custom/custom.css") }}" type="text/css" />
17 <script src="{{static_url("components/requirejs/require.js") }}" type="text/javascript" charset="utf-8"></script>
17 <script src="{{static_url("components/requirejs/require.js") }}" type="text/javascript" charset="utf-8"></script>
18 <script>
18 <script>
19 require.config({
19 require.config({
20 baseUrl: '{{static_url("", include_version=False)}}',
20 baseUrl: '{{static_url("", include_version=False)}}',
21 paths: {
21 paths: {
22 nbextensions : '{{ base_url }}nbextensions',
22 nbextensions : '{{ base_url }}nbextensions',
23 underscore : 'components/underscore/underscore-min',
23 underscore : 'components/underscore/underscore-min',
24 backbone : 'components/backbone/backbone-min',
24 backbone : 'components/backbone/backbone-min',
25 jquery: 'components/jquery/jquery.min',
25 jquery: 'components/jquery/jquery.min',
26 bootstrap: 'components/bootstrap/js/bootstrap.min',
26 bootstraptour: 'components/bootstrap-tour/build/js/bootstrap-tour.min',
27 bootstraptour: 'components/bootstrap-tour/build/js/bootstrap-tour.min',
27 dateformat: 'dateformat/date.format',
28 dateformat: 'dateformat/date.format',
28 jqueryui: 'components/jquery-ui/ui/minified/jquery-ui.min',
29 jqueryui: 'components/jquery-ui/ui/minified/jquery-ui.min',
29 },
30 },
30 shim: {
31 shim: {
31 underscore: {
32 underscore: {
32 exports: '_'
33 exports: '_'
33 },
34 },
34 backbone: {
35 backbone: {
35 deps: ["underscore", "jquery"],
36 deps: ["underscore", "jquery"],
36 exports: "Backbone"
37 exports: "Backbone"
37 },
38 },
39 bootstrap: {
40 deps: ["jquery"],
41 exports: "bootstrap"
42 },
38 bootstraptour: {
43 bootstraptour: {
44 deps: ["bootstrap"],
39 exports: "Tour"
45 exports: "Tour"
40 },
46 },
41 dateformat: {
47 dateformat: {
42 exports: "dateFormat"
48 exports: "dateFormat"
43 },
49 },
44 jqueryui: {
50 jqueryui: {
45 deps: ["jquery"],
51 deps: ["jquery"],
46 exports: "$"
52 exports: "$"
47 }
53 }
48 }
54 }
49 });
55 });
50 </script>
56 </script>
51
57
52 {% block meta %}
58 {% block meta %}
53 {% endblock %}
59 {% endblock %}
54
60
55 </head>
61 </head>
56
62
57 <body {% block params %}{% endblock %}>
63 <body {% block params %}{% endblock %}>
58
64
59 <noscript>
65 <noscript>
60 <div id='noscript'>
66 <div id='noscript'>
61 IPython Notebook requires JavaScript.<br>
67 IPython Notebook requires JavaScript.<br>
62 Please enable it to proceed.
68 Please enable it to proceed.
63 </div>
69 </div>
64 </noscript>
70 </noscript>
65
71
66 <div id="header" class="navbar navbar-static-top">
72 <div id="header" class="navbar navbar-static-top">
67 <div class="container">
73 <div class="container">
68 <div id="ipython_notebook" class="nav navbar-brand pull-left"><a href="{{base_url}}tree/{{notebook_path}}" alt='dashboard'><img src='{{static_url("base/images/ipynblogo.png") }}' alt='IPython Notebook'/></a></div>
74 <div id="ipython_notebook" class="nav navbar-brand pull-left"><a href="{{base_url}}tree/{{notebook_path}}" alt='dashboard'><img src='{{static_url("base/images/ipynblogo.png") }}' alt='IPython Notebook'/></a></div>
69
75
70 {% block login_widget %}
76 {% block login_widget %}
71
77
72 <span id="login_widget">
78 <span id="login_widget">
73 {% if logged_in %}
79 {% if logged_in %}
74 <button id="logout">Logout</button>
80 <button id="logout">Logout</button>
75 {% elif login_available and not logged_in %}
81 {% elif login_available and not logged_in %}
76 <button id="login">Login</button>
82 <button id="login">Login</button>
77 {% endif %}
83 {% endif %}
78 </span>
84 </span>
79
85
80 {% endblock %}
86 {% endblock %}
81
87
82 {% block header %}
88 {% block header %}
83 {% endblock %}
89 {% endblock %}
84 </div>
90 </div>
85 </div>
91 </div>
86
92
87 <div id="site">
93 <div id="site">
88 {% block site %}
94 {% block site %}
89 {% endblock %}
95 {% endblock %}
90 </div>
96 </div>
91
97
92 {% block script %}
98 {% block script %}
93 {% endblock %}
99 {% endblock %}
94
100
95 <script src="{{static_url("custom/custom.js") }}" type="text/javascript" charset="utf-8"></script>
101 <script src="{{static_url("custom/custom.js") }}" type="text/javascript" charset="utf-8"></script>
96
102
97 </body>
103 </body>
98
104
99 </html>
105 </html>
General Comments 0
You need to be logged in to leave comments. Login now