Show More
@@ -0,0 +1,53 b'' | |||
|
1 | /*Css for the metadata edit area*/ | |
|
2 | ||
|
3 | .celltoolbar{ | |
|
4 | border:thin solid #DDD; | |
|
5 | margin-left:81px; | |
|
6 | border-bottom:none; | |
|
7 | background : #EEE; | |
|
8 | border-top-right-radius: 3px; | |
|
9 | border-top-left-radius: 3px; | |
|
10 | display:none; | |
|
11 | } | |
|
12 | ||
|
13 | .code_cell .celltoolbar{ | |
|
14 | margin-left:81px; | |
|
15 | } | |
|
16 | ||
|
17 | .text_cell .celltoolbar{ | |
|
18 | margin-left:0px; | |
|
19 | } | |
|
20 | ||
|
21 | .celltoolbar-on div.input_area , .celltoolbar-on div.text_cell_input{ | |
|
22 | border-top-right-radius: 0px; | |
|
23 | border-top-left-radius: 0px; | |
|
24 | } | |
|
25 | ||
|
26 | .celltoolbar-on .celltoolbar { | |
|
27 | display:block; | |
|
28 | } | |
|
29 | ||
|
30 | .celltoolbar ui-button { | |
|
31 | border :none; | |
|
32 | } | |
|
33 | ||
|
34 | .button_container { | |
|
35 | float:right; | |
|
36 | } | |
|
37 | ||
|
38 | .button_container .ui-state-default, .button_container .ui-state-hover, .button_container .ui-state-hover span{ | |
|
39 | border-radius : 0 0 0 0; | |
|
40 | border : none; | |
|
41 | } | |
|
42 | ||
|
43 | .celltoolbar select { | |
|
44 | margin:10px; | |
|
45 | margin-top:0px; | |
|
46 | margin-bottom:0px; | |
|
47 | } | |
|
48 | ||
|
49 | .celltoolbar input[type=checkbox] { | |
|
50 | margin-bottom:1px; | |
|
51 | ||
|
52 | } | |
|
53 |
@@ -0,0 +1,358 b'' | |||
|
1 | //---------------------------------------------------------------------------- | |
|
2 | // Copyright (C) 2012 The IPython Development Team | |
|
3 | // | |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
|
5 | // the file COPYING, distributed as part of this software. | |
|
6 | //---------------------------------------------------------------------------- | |
|
7 | ||
|
8 | //============================================================================ | |
|
9 | // CellToolbar | |
|
10 | //============================================================================ | |
|
11 | ||
|
12 | ||
|
13 | /** | |
|
14 | * A Module to control the per-cell toolbar. | |
|
15 | * @module IPython | |
|
16 | * @namespace IPython | |
|
17 | * @submodule CellToolbar | |
|
18 | */ | |
|
19 | var IPython = (function (IPython) { | |
|
20 | "use strict"; | |
|
21 | ||
|
22 | ||
|
23 | /** | |
|
24 | * @constructor | |
|
25 | * @class CellToolbar | |
|
26 | * @param {The cell to attach the metadata UI to} cell | |
|
27 | */ | |
|
28 | var CellToolbar = function (cell) { | |
|
29 | CellToolbar._instances.push(this); | |
|
30 | this.inner_element = $('<div/>'); | |
|
31 | this.cell = cell; | |
|
32 | this.element = $('<div/>').addClass('celltoolbar') | |
|
33 | .append(this.inner_element) | |
|
34 | this.rebuild(); | |
|
35 | return this; | |
|
36 | }; | |
|
37 | ||
|
38 | CellToolbar.dropdown_preset_element = $('<select/>') | |
|
39 | .addClass('ui-widget ui-widget-content') | |
|
40 | .attr('id', 'celltoolbar_selector') | |
|
41 | .append($('<option/>').attr('value', '').text('None')) | |
|
42 | ||
|
43 | CellToolbar.dropdown_preset_element.change(function(){ | |
|
44 | var val = CellToolbar.dropdown_preset_element.val() | |
|
45 | if(val ==''){ | |
|
46 | $('body').removeClass('celltoolbar-on') | |
|
47 | } else { | |
|
48 | $('body').addClass('celltoolbar-on') | |
|
49 | CellToolbar.activate_preset(val) | |
|
50 | } | |
|
51 | }) | |
|
52 | ||
|
53 | ||
|
54 | ||
|
55 | /** | |
|
56 | * Class variable that should contain a dict of all availlable callback | |
|
57 | * we need to think of wether or not we allow nested namespace | |
|
58 | * @property _callback_dict | |
|
59 | * @private | |
|
60 | * @static | |
|
61 | * @type Dict | |
|
62 | */ | |
|
63 | CellToolbar._callback_dict = {}; | |
|
64 | ||
|
65 | /** | |
|
66 | * Class variable that should contain the reverse order list of the button | |
|
67 | * to add to the toolbar of each cell | |
|
68 | * @property _ui_controls_list | |
|
69 | * @private | |
|
70 | * @static | |
|
71 | * @type List | |
|
72 | */ | |
|
73 | CellToolbar._ui_controls_list = []; | |
|
74 | ||
|
75 | /** | |
|
76 | * Class variable that should contains the CellToolbar instances for each | |
|
77 | * cell of the notebook | |
|
78 | * | |
|
79 | * @private | |
|
80 | * @property _instances | |
|
81 | * @static | |
|
82 | * @type List | |
|
83 | */ | |
|
84 | CellToolbar._instances =[] | |
|
85 | ||
|
86 | /** | |
|
87 | * keep a list of all the availlabel presets for the toolbar | |
|
88 | * @private | |
|
89 | * @property _presets | |
|
90 | * @static | |
|
91 | * @type Dict | |
|
92 | */ | |
|
93 | CellToolbar._presets ={} | |
|
94 | ||
|
95 | // this is by design not a prototype. | |
|
96 | /** | |
|
97 | * Register a callback to create an UI element in a cell toolbar. | |
|
98 | * @method register_callback | |
|
99 | * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name | |
|
100 | * for easier sorting and avoid collision | |
|
101 | * @param callback {function(div, cell)} callback that will be called to generate the ui element | |
|
102 | * | |
|
103 | * | |
|
104 | * The callback will receive the following element : | |
|
105 | * | |
|
106 | * * a div in which to add element. | |
|
107 | * * the cell it is responsible from | |
|
108 | * | |
|
109 | * @example | |
|
110 | * | |
|
111 | * Example that create callback for a button that toggle between `true` and `false` label, | |
|
112 | * with the metadata under the key 'foo' to reflect the status of the button. | |
|
113 | * | |
|
114 | * // first param reference to a DOM div | |
|
115 | * // second param reference to the cell. | |
|
116 | * var toggle = function(div, cell) { | |
|
117 | * var button_container = $(div) | |
|
118 | * | |
|
119 | * // let's create a button that show the current value of the metadata | |
|
120 | * var button = $('<div/>').button({label:String(cell.metadata.foo)}); | |
|
121 | * | |
|
122 | * // On click, change the metadata value and update the button label | |
|
123 | * button.click(function(){ | |
|
124 | * var v = cell.metadata.foo; | |
|
125 | * cell.metadata.foo = !v; | |
|
126 | * button.button("option", "label", String(!v)); | |
|
127 | * }) | |
|
128 | * | |
|
129 | * // add the button to the DOM div. | |
|
130 | * button_container.append(button); | |
|
131 | * } | |
|
132 | * | |
|
133 | * // now we register the callback under the name `foo` to give the | |
|
134 | * // user the ability to use it later | |
|
135 | * CellToolbar.register_callback('foo', toggle); | |
|
136 | */ | |
|
137 | CellToolbar.register_callback = function(name, callback){ | |
|
138 | // Overwrite if it already exists. | |
|
139 | CellToolbar._callback_dict[name] = callback; | |
|
140 | }; | |
|
141 | ||
|
142 | /** | |
|
143 | * Register a preset of UI element in a cell toolbar. | |
|
144 | * Not supported Yet. | |
|
145 | * @method register_preset | |
|
146 | * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name | |
|
147 | * for easier sorting and avoid collision | |
|
148 | * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list | |
|
149 | * should correspond to a name of a registerd callback. | |
|
150 | * | |
|
151 | * @private | |
|
152 | * @example | |
|
153 | * | |
|
154 | * CellToolbar.register_callback('foo.c1', function(div, cell){...}); | |
|
155 | * CellToolbar.register_callback('foo.c2', function(div, cell){...}); | |
|
156 | * CellToolbar.register_callback('foo.c3', function(div, cell){...}); | |
|
157 | * CellToolbar.register_callback('foo.c4', function(div, cell){...}); | |
|
158 | * CellToolbar.register_callback('foo.c5', function(div, cell){...}); | |
|
159 | * | |
|
160 | * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5']) | |
|
161 | * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5']) | |
|
162 | */ | |
|
163 | CellToolbar.register_preset = function(name, preset_list){ | |
|
164 | CellToolbar._presets[name] = preset_list | |
|
165 | CellToolbar.dropdown_preset_element.append( | |
|
166 | $('<option/>').attr('value', name).text(name) | |
|
167 | ) | |
|
168 | } | |
|
169 | /** | |
|
170 | * Activate an UI preset from `register_preset` | |
|
171 | * | |
|
172 | * This does not update the selection UI. | |
|
173 | * | |
|
174 | * @method activate_preset | |
|
175 | * @param preset_name {String} string corresponding to the preset name | |
|
176 | * | |
|
177 | * @static | |
|
178 | * @private | |
|
179 | * @example | |
|
180 | * | |
|
181 | * CellToolbar.activate_preset('foo.foo_preset1'); | |
|
182 | */ | |
|
183 | CellToolbar.activate_preset= function(preset_name){ | |
|
184 | var preset = CellToolbar._presets[preset_name]; | |
|
185 | ||
|
186 | if(preset != undefined){ | |
|
187 | CellToolbar._ui_controls_list = preset; | |
|
188 | CellToolbar.rebuild_all(); | |
|
189 | } | |
|
190 | } | |
|
191 | ||
|
192 | ||
|
193 | // this is by design not a prototype. | |
|
194 | /** | |
|
195 | * This should be called on the class and not on a instance as it will trigger | |
|
196 | * rebuild of all the instances. | |
|
197 | * @method rebuild_all | |
|
198 | * @static | |
|
199 | * | |
|
200 | */ | |
|
201 | CellToolbar.rebuild_all = function(){ | |
|
202 | for(var i in CellToolbar._instances){ | |
|
203 | CellToolbar._instances[i].rebuild(); | |
|
204 | } | |
|
205 | } | |
|
206 | ||
|
207 | /** | |
|
208 | * Rebuild all the button on the toolbar to update it's state. | |
|
209 | * @method rebuild | |
|
210 | */ | |
|
211 | CellToolbar.prototype.rebuild = function(){ | |
|
212 | // strip evrything from the div | |
|
213 | // which is probabli metainner. | |
|
214 | // or this.element. | |
|
215 | this.inner_element.empty(); | |
|
216 | ||
|
217 | var cdict = CellToolbar._callback_dict; | |
|
218 | var preset = CellToolbar._ui_controls_list; | |
|
219 | // Yes we iterate on the class varaible, not the instance one. | |
|
220 | for ( var index in CellToolbar._ui_controls_list){ | |
|
221 | var local_div = $('<div/>').addClass('button_container'); | |
|
222 | // Note, | |
|
223 | // do this the other way, wrap in try/catch and don't append if any errors. | |
|
224 | this.inner_element.append(local_div) | |
|
225 | cdict[preset[index]](local_div, this.cell) | |
|
226 | } | |
|
227 | ||
|
228 | } | |
|
229 | ||
|
230 | ||
|
231 | /** | |
|
232 | */ | |
|
233 | CellToolbar.utils = {}; | |
|
234 | ||
|
235 | /** | |
|
236 | * A utility function to generate bindings between a checkbox and cell/metadata | |
|
237 | * @method utils.checkbox_ui_generator | |
|
238 | * @static | |
|
239 | * | |
|
240 | * @param name {string} Label in front of the checkbox | |
|
241 | * @param setter {function( cell, newValue )} | |
|
242 | * A setter method to set the newValue | |
|
243 | * @param getter {function( cell )} | |
|
244 | * A getter methods which return the current value. | |
|
245 | * | |
|
246 | * @return callback {function( div, cell )} Callback to be passed to `register_callback` | |
|
247 | * | |
|
248 | * @example | |
|
249 | * | |
|
250 | * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label | |
|
251 | * | |
|
252 | * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide', | |
|
253 | * // setter | |
|
254 | * function(cell, value){ | |
|
255 | * // we check that the slideshow namespace exist and create it if needed | |
|
256 | * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}} | |
|
257 | * // set the value | |
|
258 | * cell.metadata.slideshow.isSectionStart = value | |
|
259 | * }, | |
|
260 | * //geter | |
|
261 | * function(cell){ var ns = cell.metadata.slideshow; | |
|
262 | * // if the slideshow namespace does not exist return `undefined` | |
|
263 | * // (will be interpreted as `false` by checkbox) otherwise | |
|
264 | * // return the value | |
|
265 | * return (ns == undefined)? undefined: ns.isSectionStart | |
|
266 | * } | |
|
267 | * ); | |
|
268 | * | |
|
269 | * CellToolbar.register_callback('newSlide', newSlide); | |
|
270 | * | |
|
271 | */ | |
|
272 | CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){ | |
|
273 | return function(div, cell) { | |
|
274 | var button_container = $(div) | |
|
275 | ||
|
276 | var chkb = $('<input/>').attr('type', 'checkbox'); | |
|
277 | var lbl = $('<label/>').append($('<span/>').text(name).css('font-size', '77%')); | |
|
278 | lbl.append(chkb); | |
|
279 | chkb.attr("checked", getter(cell)); | |
|
280 | ||
|
281 | chkb.click(function(){ | |
|
282 | var v = getter(cell); | |
|
283 | setter(cell, !v); | |
|
284 | chkb.attr("checked", !v); | |
|
285 | }) | |
|
286 | button_container.append($('<div/>').append(lbl)); | |
|
287 | ||
|
288 | } | |
|
289 | } | |
|
290 | ||
|
291 | /** | |
|
292 | * A utility function to generate bindings between a dropdown list cell | |
|
293 | * @method utils.select_ui_generator | |
|
294 | * @static | |
|
295 | * | |
|
296 | * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list. | |
|
297 | * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list, | |
|
298 | * and second the corresponding value to be passed to setter/return by getter. | |
|
299 | * @param setter {function( cell, newValue )} | |
|
300 | * A setter method to set the newValue | |
|
301 | * @param getter {function( cell )} | |
|
302 | * A getter methods which return the current value of the metadata. | |
|
303 | * @param [label=""] {String} optionnal label for the dropdown menu | |
|
304 | * | |
|
305 | * @return callback {function( div, cell )} Callback to be passed to `register_callback` | |
|
306 | * | |
|
307 | * @example | |
|
308 | * | |
|
309 | * var select_type = CellToolbar.utils.select_ui_generator([ | |
|
310 | * ["<None>" , undefined ], | |
|
311 | * ["Header Slide" , "header_slide" ], | |
|
312 | * ["Slide" , "slide" ], | |
|
313 | * ["Fragment" , "fragment" ], | |
|
314 | * ["Skip" , "skip" ], | |
|
315 | * ], | |
|
316 | * // setter | |
|
317 | * function(cell, value){ | |
|
318 | * // we check that the slideshow namespace exist and create it if needed | |
|
319 | * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}} | |
|
320 | * // set the value | |
|
321 | * cell.metadata.slideshow.slide_type = value | |
|
322 | * }, | |
|
323 | * //geter | |
|
324 | * function(cell){ var ns = cell.metadata.slideshow; | |
|
325 | * // if the slideshow namespace does not exist return `undefined` | |
|
326 | * // (will be interpreted as `false` by checkbox) otherwise | |
|
327 | * // return the value | |
|
328 | * return (ns == undefined)? undefined: ns.slide_type | |
|
329 | * } | |
|
330 | * CellToolbar.register_callback('slideshow.select', select_type); | |
|
331 | * | |
|
332 | */ | |
|
333 | CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){ | |
|
334 | label= label? label: ""; | |
|
335 | return function(div, cell) { | |
|
336 | var button_container = $(div) | |
|
337 | var lbl = $("<label/>").append($('<span/>').text(label).css('font-size', '77%')); | |
|
338 | var select = $('<select/>'); | |
|
339 | for(var itemn in list_list){ | |
|
340 | var opt = $('<option/>'); | |
|
341 | opt.attr('value', list_list[itemn][1]) | |
|
342 | opt.text(list_list[itemn][0]) | |
|
343 | select.append(opt); | |
|
344 | } | |
|
345 | select.val(getter(cell)); | |
|
346 | select.change(function(){ | |
|
347 | setter(cell, select.val()); | |
|
348 | }); | |
|
349 | button_container.append($('<div/>').append(lbl).append(select)); | |
|
350 | ||
|
351 | } | |
|
352 | }; | |
|
353 | ||
|
354 | ||
|
355 | IPython.CellToolbar = CellToolbar; | |
|
356 | ||
|
357 | return IPython; | |
|
358 | }(IPython)); |
@@ -0,0 +1,94 b'' | |||
|
1 | //---------------------------------------------------------------------------- | |
|
2 | // Copyright (C) 2012 The IPython Development Team | |
|
3 | // | |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
|
5 | // the file COPYING, distributed as part of this software. | |
|
6 | //---------------------------------------------------------------------------- | |
|
7 | ||
|
8 | //============================================================================ | |
|
9 | // CellToolbar Default | |
|
10 | //============================================================================ | |
|
11 | ||
|
12 | /** | |
|
13 | * Example Use for the CellToolbar library | |
|
14 | */ | |
|
15 | // IIFE without asignement, we don't modifiy the IPython namespace | |
|
16 | (function (IPython) { | |
|
17 | "use strict"; | |
|
18 | ||
|
19 | var CellToolbar = IPython.CellToolbar; | |
|
20 | ||
|
21 | var raw_edit = function(cell){ | |
|
22 | ||
|
23 | var md = cell.metadata | |
|
24 | var error_div = $('<div/>').css('color','red') | |
|
25 | ||
|
26 | var textarea = $('<textarea/>') | |
|
27 | .attr('rows','13') | |
|
28 | .attr('cols','75') | |
|
29 | .attr('name','metadata') | |
|
30 | .text(JSON.stringify(md, null,4)||''); | |
|
31 | var dialogform = $('<div/>').attr('title','Edit the metadata') | |
|
32 | .append( | |
|
33 | $('<form/>').append( | |
|
34 | $('<fieldset/>').append( | |
|
35 | $('<label/>') | |
|
36 | .attr('for','metadata') | |
|
37 | .text("Manually edit the JSON below to manipulate the metadata for this cell. This assumes you know what you are doing and won't complain if it breaks your notebook. We also recommend putting your metadata attributes in an appropriately named sub-structure, so they don't conflict with those of others.") | |
|
38 | ) | |
|
39 | .append(error_div) | |
|
40 | .append($('<br/>')) | |
|
41 | .append( | |
|
42 | textarea | |
|
43 | ) | |
|
44 | ) | |
|
45 | ); | |
|
46 | var editor = CodeMirror.fromTextArea(textarea[0], { | |
|
47 | lineNumbers: true, | |
|
48 | matchBrackets: true, | |
|
49 | }); | |
|
50 | $(dialogform).dialog({ | |
|
51 | autoOpen: true, | |
|
52 | height: 300, | |
|
53 | width: 650, | |
|
54 | modal: true, | |
|
55 | buttons: { | |
|
56 | "Ok": function() { | |
|
57 | //validate json and set it | |
|
58 | try { | |
|
59 | var json = JSON.parse(editor.getValue()); | |
|
60 | cell.metadata = json; | |
|
61 | $( this ).dialog( "close" ); | |
|
62 | } | |
|
63 | catch(e) | |
|
64 | { | |
|
65 | error_div.text('Warning, invalid json, not saved'); | |
|
66 | } | |
|
67 | }, | |
|
68 | Cancel: function() { | |
|
69 | $( this ).dialog( "close" ); | |
|
70 | } | |
|
71 | }, | |
|
72 | close: function() { | |
|
73 | //cleanup on close | |
|
74 | $(this).remove(); | |
|
75 | } | |
|
76 | }); | |
|
77 | editor.refresh(); | |
|
78 | } | |
|
79 | ||
|
80 | var add_raw_edit_button = function(div, cell) { | |
|
81 | var button_container = div | |
|
82 | var button = $('<div/>').button({label:'Raw Edit'}) | |
|
83 | .click(function(){raw_edit(cell); return false;}) | |
|
84 | button_container.append(button); | |
|
85 | } | |
|
86 | ||
|
87 | CellToolbar.register_callback('default.rawedit',add_raw_edit_button); | |
|
88 | var example_preset = [] | |
|
89 | example_preset.push('default.rawedit'); | |
|
90 | ||
|
91 | CellToolbar.register_preset('Default',example_preset); | |
|
92 | console.log('Default extension for metadata editting loaded.'); | |
|
93 | ||
|
94 | }(IPython)); |
@@ -0,0 +1,154 b'' | |||
|
1 | //---------------------------------------------------------------------------- | |
|
2 | // Copyright (C) 2012 The IPython Development Team | |
|
3 | // | |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
|
5 | // the file COPYING, distributed as part of this software. | |
|
6 | //---------------------------------------------------------------------------- | |
|
7 | ||
|
8 | //============================================================================ | |
|
9 | // CellToolbar Example | |
|
10 | //============================================================================ | |
|
11 | ||
|
12 | /** | |
|
13 | * Example Use for the CellToolbar library | |
|
14 | * add the following to your custom.js to load | |
|
15 | * Celltoolbar UI for slideshow | |
|
16 | * | |
|
17 | * ``` | |
|
18 | * $.getScript('/static/js/celltoolbarpresets/example.js'); | |
|
19 | * ``` | |
|
20 | */ | |
|
21 | // IIFE without asignement, we don't modifiy the IPython namespace | |
|
22 | (function (IPython) { | |
|
23 | "use strict"; | |
|
24 | ||
|
25 | var CellToolbar = IPython.CellToolbar; | |
|
26 | ||
|
27 | var example_preset = []; | |
|
28 | ||
|
29 | var simple_button = function(div, cell) { | |
|
30 | var button_container = $(div); | |
|
31 | var button = $('<div/>').button({icons:{primary:'ui-icon-locked'}}); | |
|
32 | var fun = function(value){ | |
|
33 | try{ | |
|
34 | if(value){ | |
|
35 | cell.code_mirror.setOption('readOnly','nocursor') | |
|
36 | button.button('option','icons',{primary:'ui-icon-locked'}) | |
|
37 | } else { | |
|
38 | cell.code_mirror.setOption('readOnly',false) | |
|
39 | button.button('option','icons',{primary:'ui-icon-unlocked'}) | |
|
40 | } | |
|
41 | } catch(e){} | |
|
42 | ||
|
43 | } | |
|
44 | fun(cell.metadata.ro) | |
|
45 | button.click(function(){ | |
|
46 | var v = cell.metadata.ro; | |
|
47 | var locked = !v; | |
|
48 | cell.metadata.ro = locked; | |
|
49 | fun(locked) | |
|
50 | }) | |
|
51 | .css('height','16px') | |
|
52 | .css('width','35px'); | |
|
53 | button_container.append(button); | |
|
54 | } | |
|
55 | ||
|
56 | CellToolbar.register_callback('example.lock',simple_button); | |
|
57 | example_preset.push('example.lock'); | |
|
58 | ||
|
59 | var toggle_test = function(div, cell) { | |
|
60 | var button_container = $(div) | |
|
61 | var button = $('<div/>') | |
|
62 | .button({label:String(cell.metadata.foo)}). | |
|
63 | css('width','65px'); | |
|
64 | button.click(function(){ | |
|
65 | var v = cell.metadata.foo; | |
|
66 | cell.metadata.foo = !v; | |
|
67 | button.button("option","label",String(!v)); | |
|
68 | }) | |
|
69 | button_container.append(button); | |
|
70 | } | |
|
71 | ||
|
72 | CellToolbar.register_callback('example.toggle',toggle_test); | |
|
73 | example_preset.push('example.toggle'); | |
|
74 | ||
|
75 | var checkbox_test = CellToolbar.utils.checkbox_ui_generator('Yes/No', | |
|
76 | // setter | |
|
77 | function(cell, value){ | |
|
78 | // we check that the slideshow namespace exist and create it if needed | |
|
79 | if (cell.metadata.yn_test == undefined){cell.metadata.yn_test = {}} | |
|
80 | // set the value | |
|
81 | cell.metadata.yn_test.value = value | |
|
82 | }, | |
|
83 | //geter | |
|
84 | function(cell){ var ns = cell.metadata.yn_test; | |
|
85 | // if the slideshow namespace does not exist return `undefined` | |
|
86 | // (will be interpreted as `false` by checkbox) otherwise | |
|
87 | // return the value | |
|
88 | return (ns == undefined)? undefined: ns.value | |
|
89 | } | |
|
90 | ); | |
|
91 | ||
|
92 | ||
|
93 | CellToolbar.register_callback('example.checkbox',checkbox_test); | |
|
94 | example_preset.push('example.checkbox'); | |
|
95 | ||
|
96 | var select_test = CellToolbar.utils.select_ui_generator([ | |
|
97 | ["-" ,undefined ], | |
|
98 | ["Header Slide" ,"header_slide" ], | |
|
99 | ["Slide" ,"slide" ], | |
|
100 | ["Fragment" ,"fragment" ], | |
|
101 | ["Skip" ,"skip" ], | |
|
102 | ], | |
|
103 | // setter | |
|
104 | function(cell,value){ | |
|
105 | // we check that the slideshow namespace exist and create it if needed | |
|
106 | if (cell.metadata.test == undefined){cell.metadata.test = {}} | |
|
107 | // set the value | |
|
108 | cell.metadata.test.slide_type = value | |
|
109 | }, | |
|
110 | //geter | |
|
111 | function(cell){ var ns = cell.metadata.test; | |
|
112 | // if the slideshow namespace does not exist return `undefined` | |
|
113 | // (will be interpreted as `false` by checkbox) otherwise | |
|
114 | // return the value | |
|
115 | return (ns == undefined)? undefined: ns.slide_type | |
|
116 | }); | |
|
117 | ||
|
118 | CellToolbar.register_callback('example.select',select_test); | |
|
119 | example_preset.push('example.select'); | |
|
120 | ||
|
121 | var simple_dialog = function(title,text){ | |
|
122 | var dlg = $('<div/>').attr('title',title) | |
|
123 | .append($('<p/>').text(text)) | |
|
124 | $(dlg).dialog({ | |
|
125 | autoOpen: true, | |
|
126 | height: 300, | |
|
127 | width: 650, | |
|
128 | modal: true, | |
|
129 | close: function() { | |
|
130 | //cleanup on close | |
|
131 | $(this).remove(); | |
|
132 | } | |
|
133 | }); | |
|
134 | } | |
|
135 | ||
|
136 | var add_simple_dialog_button = function(div, cell) { | |
|
137 | var help_text = ["This is the Metadata editting UI.", | |
|
138 | "It heavily rely on plugin to work ", | |
|
139 | "and is still under developpement. You shouldn't wait too long before", | |
|
140 | " seeing some customisable buttons in those toolbar." | |
|
141 | ].join('\n') | |
|
142 | var button_container = $(div) | |
|
143 | var button = $('<div/>').button({label:'?'}) | |
|
144 | .click(function(){simple_dialog('help',help_text); return false;}) | |
|
145 | button_container.append(button); | |
|
146 | } | |
|
147 | ||
|
148 | CellToolbar.register_callback('example.help',add_simple_dialog_button) | |
|
149 | example_preset.push('example.help') | |
|
150 | ||
|
151 | CellToolbar.register_preset('Example',example_preset); | |
|
152 | console.log('Example extension for metadata editting loaded.'); | |
|
153 | ||
|
154 | }(IPython)); |
@@ -1,414 +1,418 b'' | |||
|
1 | 1 | /** |
|
2 | 2 | * Primary styles |
|
3 | 3 | * |
|
4 | 4 | * Author: IPython Development Team |
|
5 | 5 | */ |
|
6 | 6 | |
|
7 | 7 | |
|
8 | 8 | body { |
|
9 | 9 | overflow: hidden; |
|
10 | 10 | } |
|
11 | 11 | |
|
12 | 12 | blockquote { |
|
13 | 13 | border-left: 4px solid #DDD; |
|
14 | 14 | padding: 0 15px; |
|
15 | 15 | color: #777; |
|
16 | 16 | } |
|
17 | 17 | |
|
18 | 18 | span#save_widget { |
|
19 | 19 | padding: 5px; |
|
20 | 20 | margin: 0px 0px 0px 300px; |
|
21 | 21 | display:inline-block; |
|
22 | 22 | } |
|
23 | 23 | |
|
24 | 24 | span#notebook_name { |
|
25 | 25 | height: 1em; |
|
26 | 26 | line-height: 1em; |
|
27 | 27 | padding: 3px; |
|
28 | 28 | border: none; |
|
29 | 29 | font-size: 146.5%; |
|
30 | 30 | } |
|
31 | 31 | |
|
32 | ||
|
32 | 33 | .ui-menubar-item .ui-button .ui-button-text { |
|
33 | 34 | padding: 0.4em 1.0em; |
|
34 | 35 | font-size: 100%; |
|
35 | 36 | } |
|
36 | 37 | |
|
37 | 38 | .ui-menu { |
|
38 | 39 | -moz-box-shadow: 0px 6px 10px -1px #adadad; |
|
39 | 40 | -webkit-box-shadow: 0px 6px 10px -1px #adadad; |
|
40 | 41 | box-shadow: 0px 6px 10px -1px #adadad; |
|
41 | 42 | } |
|
42 | 43 | |
|
43 | 44 | .ui-menu .ui-menu-item a { |
|
44 | 45 | border: 1px solid transparent; |
|
45 | 46 | padding: 2px 1.6em; |
|
46 | 47 | } |
|
47 | 48 | |
|
48 | 49 | .ui-menu .ui-menu-item a.ui-state-focus { |
|
49 | 50 | margin: 0; |
|
50 | 51 | } |
|
51 | 52 | |
|
52 | 53 | .ui-menu hr { |
|
53 | 54 | margin: 0.3em 0; |
|
54 | 55 | } |
|
55 | 56 | |
|
56 | 57 | #menubar_container { |
|
57 | 58 | position: relative; |
|
58 | 59 | } |
|
59 | 60 | |
|
60 | 61 | #notification_area { |
|
61 | 62 | position: absolute; |
|
62 | 63 | right: 0px; |
|
63 | 64 | top: 0px; |
|
64 | 65 | height: 25px; |
|
65 | 66 | padding: 3px 0px; |
|
66 | 67 | padding-right: 3px; |
|
67 | 68 | z-index: 10; |
|
68 | 69 | } |
|
69 | 70 | |
|
70 | 71 | .notification_widget{ |
|
71 | 72 | float : right; |
|
72 | 73 | right: 0px; |
|
73 | 74 | top: 1px; |
|
74 | 75 | height: 25px; |
|
75 | 76 | padding: 3px 6px; |
|
76 | 77 | z-index: 10; |
|
77 | 78 | } |
|
78 | 79 | |
|
79 | 80 | .toolbar { |
|
80 | 81 | padding: 3px 15px; |
|
81 | 82 | } |
|
82 | 83 | |
|
83 | #cell_type { | |
|
84 | #maintoolbar > select, #maintoolbar label { | |
|
84 | 85 | font-size: 85%; |
|
86 | margin-left:0.3em; | |
|
87 | margin-right:0.3em; | |
|
88 | ||
|
85 | 89 | } |
|
86 | 90 | |
|
87 | 91 | |
|
88 | 92 | div#main_app { |
|
89 | 93 | width: 100%; |
|
90 | 94 | position: relative; |
|
91 | 95 | } |
|
92 | 96 | |
|
93 | 97 | span#quick_help_area { |
|
94 | 98 | position: static; |
|
95 | 99 | padding: 5px 0px; |
|
96 | 100 | margin: 0px 0px 0px 0px; |
|
97 | 101 | } |
|
98 | 102 | |
|
99 | 103 | .help_string { |
|
100 | 104 | float: right; |
|
101 | 105 | width: 170px; |
|
102 | 106 | padding: 0px 5px; |
|
103 | 107 | text-align: left; |
|
104 | 108 | font-size: 85%; |
|
105 | 109 | } |
|
106 | 110 | |
|
107 | 111 | .help_string_label { |
|
108 | 112 | float: right; |
|
109 | 113 | font-size: 85%; |
|
110 | 114 | } |
|
111 | 115 | |
|
112 | 116 | div#notebook_panel { |
|
113 | 117 | margin: 0px 0px 0px 0px; |
|
114 | 118 | padding: 0px; |
|
115 | 119 | } |
|
116 | 120 | |
|
117 | 121 | div#notebook { |
|
118 | 122 | overflow-y: scroll; |
|
119 | 123 | overflow-x: auto; |
|
120 | 124 | width: 100%; |
|
121 | 125 | /* This spaces the cell away from the edge of the notebook area */ |
|
122 | 126 | padding: 5px 5px 15px 5px; |
|
123 | 127 | margin: 0px; |
|
124 | 128 | background-color: white; |
|
125 | 129 | } |
|
126 | 130 | |
|
127 | 131 | div#pager_splitter { |
|
128 | 132 | height: 8px; |
|
129 | 133 | } |
|
130 | 134 | |
|
131 | 135 | #pager_container { |
|
132 | 136 | position : relative; |
|
133 | 137 | } |
|
134 | 138 | |
|
135 | 139 | div#pager { |
|
136 | 140 | padding: 15px; |
|
137 | 141 | overflow: auto; |
|
138 | 142 | display: none; |
|
139 | 143 | } |
|
140 | 144 | |
|
141 | 145 | div.ui-widget-content { |
|
142 | 146 | border: 1px solid #aaa; |
|
143 | 147 | outline: none; |
|
144 | 148 | } |
|
145 | 149 | |
|
146 | 150 | .cell { |
|
147 | 151 | border: 1px solid transparent; |
|
148 | 152 | } |
|
149 | 153 | |
|
150 | 154 | div.cell { |
|
151 | 155 | width: 100%; |
|
152 | 156 | padding: 5px 5px 5px 0px; |
|
153 | 157 | /* This acts as a spacer between cells, that is outside the border */ |
|
154 | 158 | margin: 2px 0px 2px 0px; |
|
155 | 159 | } |
|
156 | 160 | |
|
157 | 161 | div.code_cell { |
|
158 | 162 | background-color: white; |
|
159 | 163 | } |
|
160 | 164 | |
|
161 | 165 | /* any special styling for code cells that are currently running goes here */ |
|
162 | 166 | div.code_cell.running { |
|
163 | 167 | } |
|
164 | 168 | |
|
165 | 169 | div.prompt { |
|
166 | 170 | /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */ |
|
167 | 171 | width: 11ex; |
|
168 | 172 | /* This 0.4em is tuned to match the padding on the CodeMirror editor. */ |
|
169 | 173 | padding: 0.4em; |
|
170 | 174 | margin: 0px; |
|
171 | 175 | font-family: monospace; |
|
172 | 176 | text-align:right; |
|
173 | 177 | } |
|
174 | 178 | |
|
175 | 179 | div.input { |
|
176 | 180 | page-break-inside: avoid; |
|
177 | 181 | } |
|
178 | 182 | |
|
179 | 183 | /* input_area and input_prompt must match in top border and margin for alignment */ |
|
180 | 184 | div.input_area { |
|
181 | 185 | color: black; |
|
182 | 186 | border: 1px solid #ddd; |
|
183 | 187 | border-radius: 3px; |
|
184 | 188 | background: #f7f7f7; |
|
185 | 189 | } |
|
186 | 190 | |
|
187 | 191 | div.input_prompt { |
|
188 | 192 | color: navy; |
|
189 | 193 | border-top: 1px solid transparent; |
|
190 | 194 | } |
|
191 | 195 | |
|
192 | 196 | div.output_wrapper { |
|
193 | 197 | /* This is a spacer between the input and output of each cell */ |
|
194 | 198 | margin-top: 5px; |
|
195 | 199 | margin-left: 5px; |
|
196 | 200 | /* FF needs explicit width to stretch */ |
|
197 | 201 | width: 100%; |
|
198 | 202 | /* this position must be relative to enable descendents to be absolute within it */ |
|
199 | 203 | position: relative; |
|
200 | 204 | } |
|
201 | 205 | |
|
202 | 206 | /* class for the output area when it should be height-limited */ |
|
203 | 207 | div.output_scroll { |
|
204 | 208 | /* ideally, this would be max-height, but FF barfs all over that */ |
|
205 | 209 | height: 24em; |
|
206 | 210 | /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */ |
|
207 | 211 | width: 100%; |
|
208 | 212 | |
|
209 | 213 | overflow: auto; |
|
210 | 214 | border-radius: 3px; |
|
211 | 215 | box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8); |
|
212 | 216 | } |
|
213 | 217 | |
|
214 | 218 | /* output div while it is collapsed */ |
|
215 | 219 | div.output_collapsed { |
|
216 | 220 | margin-right: 5px; |
|
217 | 221 | } |
|
218 | 222 | |
|
219 | 223 | div.out_prompt_overlay { |
|
220 | 224 | height: 100%; |
|
221 | 225 | padding: 0px; |
|
222 | 226 | position: absolute; |
|
223 | 227 | border-radius: 3px; |
|
224 | 228 | } |
|
225 | 229 | |
|
226 | 230 | div.out_prompt_overlay:hover { |
|
227 | 231 | /* use inner shadow to get border that is computed the same on WebKit/FF */ |
|
228 | 232 | box-shadow: inset 0 0 1px #000; |
|
229 | 233 | background: rgba(240, 240, 240, 0.5); |
|
230 | 234 | } |
|
231 | 235 | |
|
232 | 236 | div.output_prompt { |
|
233 | 237 | color: darkred; |
|
234 | 238 | /* 5px right shift to account for margin in parent container */ |
|
235 | 239 | margin: 0 5px 0 -5px; |
|
236 | 240 | } |
|
237 | 241 | |
|
238 | 242 | /* This class is the outer container of all output sections. */ |
|
239 | 243 | div.output_area { |
|
240 | 244 | padding: 0px; |
|
241 | 245 | page-break-inside: avoid; |
|
242 | 246 | } |
|
243 | 247 | |
|
244 | 248 | /* This class is for the output subarea inside the output_area and after |
|
245 | 249 | the prompt div. */ |
|
246 | 250 | div.output_subarea { |
|
247 | 251 | padding: 0.44em 0.4em 0.4em 1px; |
|
248 | 252 | } |
|
249 | 253 | |
|
250 | 254 | /* The rest of the output_* classes are for special styling of the different |
|
251 | 255 | output types */ |
|
252 | 256 | |
|
253 | 257 | /* all text output has this class: */ |
|
254 | 258 | div.output_text { |
|
255 | 259 | text-align: left; |
|
256 | 260 | color: black; |
|
257 | 261 | font-family: monospace; |
|
258 | 262 | } |
|
259 | 263 | |
|
260 | 264 | /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */ |
|
261 | 265 | div.output_stream { |
|
262 | 266 | padding-top: 0.0em; |
|
263 | 267 | padding-bottom: 0.0em; |
|
264 | 268 | } |
|
265 | 269 | div.output_stdout { |
|
266 | 270 | } |
|
267 | 271 | div.output_stderr { |
|
268 | 272 | background: #fdd; /* very light red background for stderr */ |
|
269 | 273 | } |
|
270 | 274 | |
|
271 | 275 | div.output_latex { |
|
272 | 276 | text-align: left; |
|
273 | 277 | color: black; |
|
274 | 278 | } |
|
275 | 279 | |
|
276 | 280 | div.output_html { |
|
277 | 281 | } |
|
278 | 282 | |
|
279 | 283 | div.output_png { |
|
280 | 284 | } |
|
281 | 285 | |
|
282 | 286 | div.output_jpeg { |
|
283 | 287 | } |
|
284 | 288 | |
|
285 | 289 | div.text_cell { |
|
286 | 290 | background-color: white; |
|
287 | 291 | padding: 5px 5px 5px 5px; |
|
288 | 292 | } |
|
289 | 293 | |
|
290 | 294 | div.text_cell_input { |
|
291 | 295 | color: black; |
|
292 | 296 | border: 1px solid #ddd; |
|
293 | 297 | border-radius: 3px; |
|
294 | 298 | background: #f7f7f7; |
|
295 | 299 | } |
|
296 | 300 | |
|
297 | 301 | div.text_cell_render { |
|
298 | 302 | font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; |
|
299 | 303 | outline: none; |
|
300 | 304 | resize: none; |
|
301 | 305 | width: inherit; |
|
302 | 306 | border-style: none; |
|
303 | 307 | padding: 5px; |
|
304 | 308 | color: black; |
|
305 | 309 | } |
|
306 | 310 | |
|
307 | 311 | /* The following gets added to the <head> if it is detected that the user has a |
|
308 | 312 | * monospace font with inconsistent normal/bold/italic height. See |
|
309 | 313 | * notebookmain.js. Such fonts will have keywords vertically offset with |
|
310 | 314 | * respect to the rest of the text. The user should select a better font. |
|
311 | 315 | * See: https://github.com/ipython/ipython/issues/1503 |
|
312 | 316 | * |
|
313 | 317 | * .CodeMirror span { |
|
314 | 318 | * vertical-align: bottom; |
|
315 | 319 | * } |
|
316 | 320 | */ |
|
317 | 321 | |
|
318 | 322 | .CodeMirror { |
|
319 | 323 | line-height: 1.231; /* Changed from 1em to our global default */ |
|
320 | 324 | } |
|
321 | 325 | |
|
322 | 326 | .CodeMirror-scroll { |
|
323 | 327 | height: auto; /* Changed to auto to autogrow */ |
|
324 | 328 | /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/ |
|
325 | 329 | /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/ |
|
326 | 330 | overflow-y: hidden; |
|
327 | 331 | overflow-x: auto; /* Changed from auto to remove scrollbar */ |
|
328 | 332 | } |
|
329 | 333 | |
|
330 | 334 | /* CSS font colors for translated ANSI colors. */ |
|
331 | 335 | |
|
332 | 336 | |
|
333 | 337 | .ansiblack {color: black;} |
|
334 | 338 | .ansired {color: darkred;} |
|
335 | 339 | .ansigreen {color: darkgreen;} |
|
336 | 340 | .ansiyellow {color: brown;} |
|
337 | 341 | .ansiblue {color: darkblue;} |
|
338 | 342 | .ansipurple {color: darkviolet;} |
|
339 | 343 | .ansicyan {color: steelblue;} |
|
340 | 344 | .ansigrey {color: grey;} |
|
341 | 345 | .ansibold {font-weight: bold;} |
|
342 | 346 | |
|
343 | 347 | .completions { |
|
344 | 348 | position: absolute; |
|
345 | 349 | z-index: 10; |
|
346 | 350 | overflow: hidden; |
|
347 | 351 | border: 1px solid grey; |
|
348 | 352 | } |
|
349 | 353 | |
|
350 | 354 | .completions select { |
|
351 | 355 | background: white; |
|
352 | 356 | outline: none; |
|
353 | 357 | border: none; |
|
354 | 358 | padding: 0px; |
|
355 | 359 | margin: 0px; |
|
356 | 360 | overflow: auto; |
|
357 | 361 | font-family: monospace; |
|
358 | 362 | } |
|
359 | 363 | |
|
360 | 364 | option.context { |
|
361 | 365 | background-color: #DEF7FF; |
|
362 | 366 | } |
|
363 | 367 | option.introspection { |
|
364 | 368 | background-color: #EBF4EB; |
|
365 | 369 | } |
|
366 | 370 | |
|
367 | 371 | /*fixed part of the completion*/ |
|
368 | 372 | .completions p b { |
|
369 | 373 | font-weight:bold; |
|
370 | 374 | } |
|
371 | 375 | |
|
372 | 376 | .completions p { |
|
373 | 377 | background: #DDF; |
|
374 | 378 | /*outline: none; |
|
375 | 379 | padding: 0px;*/ |
|
376 | 380 | border-bottom: black solid 1px; |
|
377 | 381 | padding: 1px; |
|
378 | 382 | font-family: monospace; |
|
379 | 383 | } |
|
380 | 384 | |
|
381 | 385 | pre.dialog { |
|
382 | 386 | background-color: #f7f7f7; |
|
383 | 387 | border: 1px solid #ddd; |
|
384 | 388 | border-radius: 3px; |
|
385 | 389 | padding: 0.4em; |
|
386 | 390 | padding-left: 2em; |
|
387 | 391 | } |
|
388 | 392 | |
|
389 | 393 | p.dialog { |
|
390 | 394 | padding : 0.2em; |
|
391 | 395 | } |
|
392 | 396 | |
|
393 | 397 | .shortcut_key { |
|
394 | 398 | display: inline-block; |
|
395 | 399 | width: 15ex; |
|
396 | 400 | text-align: right; |
|
397 | 401 | font-family: monospace; |
|
398 | 402 | } |
|
399 | 403 | |
|
400 | 404 | .shortcut_descr { |
|
401 | 405 | } |
|
402 | 406 | |
|
403 | 407 | /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems |
|
404 | 408 | to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do. |
|
405 | 409 | */ |
|
406 | 410 | pre, code, kbd, samp { white-space: pre-wrap; } |
|
407 | 411 | |
|
408 | 412 | #fonttest { |
|
409 | 413 | font-family: monospace; |
|
410 | 414 | } |
|
411 | 415 | |
|
412 | 416 | .js-error { |
|
413 | 417 | color: darkred; |
|
414 | 418 | } |
@@ -1,312 +1,315 b'' | |||
|
1 | 1 | //---------------------------------------------------------------------------- |
|
2 | 2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
3 | 3 | // |
|
4 | 4 | // Distributed under the terms of the BSD License. The full license is in |
|
5 | 5 | // the file COPYING, distributed as part of this software. |
|
6 | 6 | //---------------------------------------------------------------------------- |
|
7 | 7 | |
|
8 | 8 | //============================================================================ |
|
9 | 9 | // Cell |
|
10 | 10 | //============================================================================ |
|
11 | 11 | /** |
|
12 | 12 | * An extendable module that provide base functionnality to create cell for notebook. |
|
13 | 13 | * @module IPython |
|
14 | 14 | * @namespace IPython |
|
15 | 15 | * @submodule Cell |
|
16 | 16 | */ |
|
17 | 17 | |
|
18 | 18 | var IPython = (function (IPython) { |
|
19 | 19 | |
|
20 | 20 | var utils = IPython.utils; |
|
21 | 21 | |
|
22 | 22 | /** |
|
23 | 23 | * The Base `Cell` class from which to inherit |
|
24 | 24 | * @class Cell |
|
25 | 25 | */ |
|
26 | 26 | |
|
27 | 27 | /* |
|
28 | 28 | * @constructor |
|
29 | 29 | */ |
|
30 | 30 | var Cell = function () { |
|
31 | 31 | this.placeholder = this.placeholder || ''; |
|
32 | 32 | this.read_only = false; |
|
33 | 33 | this.selected = false; |
|
34 | 34 | this.element = null; |
|
35 | 35 | this.metadata = {}; |
|
36 | 36 | // load this from metadata later ? |
|
37 | 37 | this.user_highlight = 'auto'; |
|
38 | 38 | this.create_element(); |
|
39 | 39 | if (this.element !== null) { |
|
40 | 40 | this.element.data("cell", this); |
|
41 | 41 | this.bind_events(); |
|
42 | 42 | } |
|
43 | 43 | this.cell_id = utils.uuid(); |
|
44 | 44 | }; |
|
45 | 45 | |
|
46 | 46 | |
|
47 | 47 | /** |
|
48 | 48 | * Empty. Subclasses must implement create_element. |
|
49 | 49 | * This should contain all the code to create the DOM element in notebook |
|
50 | 50 | * and will be called by Base Class constructor. |
|
51 | 51 | * @method create_element |
|
52 | 52 | */ |
|
53 |
Cell.prototype.create_element = function () { |
|
|
53 | Cell.prototype.create_element = function () { | |
|
54 | this.celltoolbar = new IPython.CellToolbar(this); | |
|
55 | }; | |
|
54 | 56 | |
|
55 | 57 | |
|
56 | 58 | /** |
|
57 | 59 | * Subclasses can implement override bind_events. |
|
58 | 60 | * Be carefull to call the parent method when overwriting as it fires event. |
|
59 | 61 | * this will be triggerd after create_element in constructor. |
|
60 | 62 | * @method bind_events |
|
61 | 63 | */ |
|
62 | 64 | Cell.prototype.bind_events = function () { |
|
63 | 65 | var that = this; |
|
64 | 66 | // We trigger events so that Cell doesn't have to depend on Notebook. |
|
65 | 67 | that.element.click(function (event) { |
|
66 | 68 | if (that.selected === false) { |
|
67 | 69 | $([IPython.events]).trigger('select.Cell', {'cell':that}); |
|
68 | 70 | } |
|
69 | 71 | }); |
|
70 | 72 | that.element.focusin(function (event) { |
|
71 | 73 | if (that.selected === false) { |
|
72 | 74 | $([IPython.events]).trigger('select.Cell', {'cell':that}); |
|
73 | 75 | } |
|
74 | 76 | }); |
|
75 | 77 | }; |
|
76 | 78 | |
|
77 | 79 | /** |
|
78 | 80 | * Triger typsetting of math by mathjax on current cell element |
|
79 | 81 | * @method typeset |
|
80 | 82 | */ |
|
81 | 83 | Cell.prototype.typeset = function () { |
|
82 | 84 | if (window.MathJax){ |
|
83 | 85 | var cell_math = this.element.get(0); |
|
84 | 86 | MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]); |
|
85 | 87 | } |
|
86 | 88 | }; |
|
87 | 89 | |
|
88 | 90 | /** |
|
89 | 91 | * should be triggerd when cell is selected |
|
90 | 92 | * @method select |
|
91 | 93 | */ |
|
92 | 94 | Cell.prototype.select = function () { |
|
93 | 95 | this.element.addClass('ui-widget-content ui-corner-all'); |
|
94 | 96 | this.selected = true; |
|
95 | 97 | }; |
|
96 | 98 | |
|
97 | 99 | |
|
98 | 100 | /** |
|
99 | 101 | * should be triggerd when cell is unselected |
|
100 | 102 | * @method unselect |
|
101 | 103 | */ |
|
102 | 104 | Cell.prototype.unselect = function () { |
|
103 | 105 | this.element.removeClass('ui-widget-content ui-corner-all'); |
|
104 | 106 | this.selected = false; |
|
105 | 107 | }; |
|
106 | 108 | |
|
107 | 109 | /** |
|
108 | 110 | * should be overritten by subclass |
|
109 | 111 | * @method get_text |
|
110 | 112 | */ |
|
111 | 113 | Cell.prototype.get_text = function () { |
|
112 | 114 | }; |
|
113 | 115 | |
|
114 | 116 | /** |
|
115 | 117 | * should be overritten by subclass |
|
116 | 118 | * @method set_text |
|
117 | 119 | * @param {string} text |
|
118 | 120 | */ |
|
119 | 121 | Cell.prototype.set_text = function (text) { |
|
120 | 122 | }; |
|
121 | 123 | |
|
122 | 124 | /** |
|
123 | 125 | * Refresh codemirror instance |
|
124 | 126 | * @method refresh |
|
125 | 127 | */ |
|
126 | 128 | Cell.prototype.refresh = function () { |
|
127 | 129 | this.code_mirror.refresh(); |
|
128 | 130 | }; |
|
129 | 131 | |
|
130 | 132 | |
|
131 | 133 | /** |
|
132 | 134 | * should be overritten by subclass |
|
133 | 135 | * @method edit |
|
134 | 136 | **/ |
|
135 | 137 | Cell.prototype.edit = function () { |
|
136 | 138 | }; |
|
137 | 139 | |
|
138 | 140 | |
|
139 | 141 | /** |
|
140 | 142 | * should be overritten by subclass |
|
141 | 143 | * @method render |
|
142 | 144 | **/ |
|
143 | 145 | Cell.prototype.render = function () { |
|
144 | 146 | }; |
|
145 | 147 | |
|
146 | 148 | /** |
|
147 | 149 | * should be overritten by subclass |
|
148 | 150 | * serialise cell to json. |
|
149 | 151 | * @method toJSON |
|
150 | 152 | **/ |
|
151 | 153 | Cell.prototype.toJSON = function () { |
|
152 | 154 | var data = {}; |
|
153 | 155 | data.metadata = this.metadata; |
|
154 | 156 | return data; |
|
155 | 157 | }; |
|
156 | 158 | |
|
157 | 159 | |
|
158 | 160 | /** |
|
159 | 161 | * should be overritten by subclass |
|
160 | 162 | * @method fromJSON |
|
161 | 163 | **/ |
|
162 | 164 | Cell.prototype.fromJSON = function (data) { |
|
163 | 165 | if (data.metadata !== undefined) { |
|
164 | 166 | this.metadata = data.metadata; |
|
165 | 167 | } |
|
168 | this.celltoolbar.rebuild(); | |
|
166 | 169 | }; |
|
167 | 170 | |
|
168 | 171 | |
|
169 | 172 | /** |
|
170 | 173 | * can the cell be splitted in 2 cells. |
|
171 | 174 | * @method is_splittable |
|
172 | 175 | **/ |
|
173 | 176 | Cell.prototype.is_splittable = function () { |
|
174 | 177 | return true; |
|
175 | 178 | }; |
|
176 | 179 | |
|
177 | 180 | |
|
178 | 181 | /** |
|
179 | 182 | * @return {String} - the text before the cursor |
|
180 | 183 | * @method get_pre_cursor |
|
181 | 184 | **/ |
|
182 | 185 | Cell.prototype.get_pre_cursor = function () { |
|
183 | 186 | var cursor = this.code_mirror.getCursor(); |
|
184 | 187 | var text = this.code_mirror.getRange({line:0,ch:0}, cursor); |
|
185 | 188 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); |
|
186 | 189 | return text; |
|
187 | 190 | } |
|
188 | 191 | |
|
189 | 192 | |
|
190 | 193 | /** |
|
191 | 194 | * @return {String} - the text after the cursor |
|
192 | 195 | * @method get_post_cursor |
|
193 | 196 | **/ |
|
194 | 197 | Cell.prototype.get_post_cursor = function () { |
|
195 | 198 | var cursor = this.code_mirror.getCursor(); |
|
196 | 199 | var last_line_num = this.code_mirror.lineCount()-1; |
|
197 | 200 | var last_line_len = this.code_mirror.getLine(last_line_num).length; |
|
198 | 201 | var end = {line:last_line_num, ch:last_line_len} |
|
199 | 202 | var text = this.code_mirror.getRange(cursor, end); |
|
200 | 203 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); |
|
201 | 204 | return text; |
|
202 | 205 | }; |
|
203 | 206 | |
|
204 | 207 | |
|
205 | 208 | /** Grow the cell by hand. This is used upon reloading from JSON, when the |
|
206 | 209 | * autogrow handler is not called. |
|
207 | 210 | * |
|
208 | 211 | * could be made static |
|
209 | 212 | * |
|
210 | 213 | * @param {Dom element} - element |
|
211 | 214 | * @method grow |
|
212 | 215 | **/ |
|
213 | 216 | Cell.prototype.grow = function(element) { |
|
214 | 217 | var dom = element.get(0); |
|
215 | 218 | var lines_count = 0; |
|
216 | 219 | // modified split rule from |
|
217 | 220 | // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424 |
|
218 | 221 | var lines = dom.value.split(/\r|\r\n|\n/); |
|
219 | 222 | lines_count = lines.length; |
|
220 | 223 | if (lines_count >= 1) { |
|
221 | 224 | dom.rows = lines_count; |
|
222 | 225 | } else { |
|
223 | 226 | dom.rows = 1; |
|
224 | 227 | } |
|
225 | 228 | }; |
|
226 | 229 | |
|
227 | 230 | /** |
|
228 | 231 | * Toggle CodeMirror LineNumber |
|
229 | 232 | * @method toggle_line_numbers |
|
230 | 233 | **/ |
|
231 | 234 | Cell.prototype.toggle_line_numbers = function () { |
|
232 | 235 | if (this.code_mirror.getOption('lineNumbers') == false) { |
|
233 | 236 | this.code_mirror.setOption('lineNumbers', true); |
|
234 | 237 | } else { |
|
235 | 238 | this.code_mirror.setOption('lineNumbers', false); |
|
236 | 239 | } |
|
237 | 240 | this.code_mirror.refresh(); |
|
238 | 241 | }; |
|
239 | 242 | |
|
240 | 243 | /** |
|
241 | 244 | * force codemirror highlight mode |
|
242 | 245 | * @method force_highlight |
|
243 | 246 | * @param {object} - CodeMirror mode |
|
244 | 247 | **/ |
|
245 | 248 | Cell.prototype.force_highlight = function(mode) { |
|
246 | 249 | this.user_highlight = mode; |
|
247 | 250 | this.auto_highlight(); |
|
248 | 251 | }; |
|
249 | 252 | |
|
250 | 253 | /** |
|
251 | 254 | * Try to autodetect cell highlight mode, or use selected mode |
|
252 | 255 | * @methods _auto_highlight |
|
253 | 256 | * @private |
|
254 | 257 | * @param {String|object|undefined} - CodeMirror mode | 'auto' |
|
255 | 258 | **/ |
|
256 | 259 | Cell.prototype._auto_highlight = function (modes) { |
|
257 | 260 | //Here we handle manually selected modes |
|
258 | 261 | if( this.user_highlight != undefined && this.user_highlight != 'auto' ) |
|
259 | 262 | { |
|
260 | 263 | var mode = this.user_highlight; |
|
261 | 264 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
262 | 265 | this.code_mirror.setOption('mode', mode); |
|
263 | 266 | return; |
|
264 | 267 | } |
|
265 | 268 | var first_line = this.code_mirror.getLine(0); |
|
266 | 269 | // loop on every pairs |
|
267 | 270 | for( var mode in modes) { |
|
268 | 271 | var regs = modes[mode]['reg']; |
|
269 | 272 | // only one key every time but regexp can't be keys... |
|
270 | 273 | for(var reg in regs ) { |
|
271 | 274 | // here we handle non magic_modes |
|
272 | 275 | if(first_line.match(regs[reg]) != null) { |
|
273 | 276 | if (mode.search('magic_') != 0) { |
|
274 | 277 | this.code_mirror.setOption('mode',mode); |
|
275 | 278 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
276 | 279 | return; |
|
277 | 280 | } |
|
278 | 281 | var open = modes[mode]['open']|| "%%"; |
|
279 | 282 | var close = modes[mode]['close']|| "%%end"; |
|
280 | 283 | var mmode = mode; |
|
281 | 284 | mode = mmode.substr(6); |
|
282 | 285 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
283 | 286 | // create on the fly a mode that swhitch between |
|
284 | 287 | // plain/text and smth else otherwise `%%` is |
|
285 | 288 | // source of some highlight issues. |
|
286 | 289 | // we use patchedGetMode to circumvent a bug in CM |
|
287 | 290 | CodeMirror.defineMode(mmode , function(config) { |
|
288 | 291 | return CodeMirror.multiplexingMode( |
|
289 | 292 | CodeMirror.patchedGetMode(config, 'text/plain'), |
|
290 | 293 | // always set someting on close |
|
291 | 294 | {open: open, close: close, |
|
292 | 295 | mode: CodeMirror.patchedGetMode(config, mode), |
|
293 | 296 | delimStyle: "delimit" |
|
294 | 297 | } |
|
295 | 298 | ); |
|
296 | 299 | }); |
|
297 | 300 | this.code_mirror.setOption('mode', mmode); |
|
298 | 301 | return; |
|
299 | 302 | } |
|
300 | 303 | } |
|
301 | 304 | } |
|
302 | 305 | // fallback on default (python) |
|
303 | 306 | var default_mode = this.default_mode || 'text/plain'; |
|
304 | 307 | this.code_mirror.setOption('mode', default_mode); |
|
305 | 308 | }; |
|
306 | 309 | |
|
307 | 310 | IPython.Cell = Cell; |
|
308 | 311 | |
|
309 | 312 | return IPython; |
|
310 | 313 | |
|
311 | 314 | }(IPython)); |
|
312 | 315 |
@@ -1,378 +1,381 b'' | |||
|
1 | 1 | //---------------------------------------------------------------------------- |
|
2 | 2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
3 | 3 | // |
|
4 | 4 | // Distributed under the terms of the BSD License. The full license is in |
|
5 | 5 | // the file COPYING, distributed as part of this software. |
|
6 | 6 | //---------------------------------------------------------------------------- |
|
7 | 7 | |
|
8 | 8 | //============================================================================ |
|
9 | 9 | // CodeCell |
|
10 | 10 | //============================================================================ |
|
11 | 11 | /** |
|
12 | 12 | * An extendable module that provide base functionnality to create cell for notebook. |
|
13 | 13 | * @module IPython |
|
14 | 14 | * @namespace IPython |
|
15 | 15 | * @submodule CodeCell |
|
16 | 16 | */ |
|
17 | 17 | |
|
18 | 18 | var IPython = (function (IPython) { |
|
19 | 19 | "use strict"; |
|
20 | 20 | |
|
21 | 21 | var utils = IPython.utils; |
|
22 | 22 | var key = IPython.utils.keycodes; |
|
23 | 23 | CodeMirror.modeURL = "/static/codemirror/mode/%N/%N.js"; |
|
24 | 24 | |
|
25 | 25 | /** |
|
26 | 26 | * A Cell conceived to write code. |
|
27 | 27 | * |
|
28 | 28 | * The kernel doesn't have to be set at creation time, in that case |
|
29 | 29 | * it will be null and set_kernel has to be called later. |
|
30 | 30 | * @class CodeCell |
|
31 | 31 | * @extends IPython.Cell |
|
32 | 32 | * |
|
33 | 33 | * @constructor |
|
34 | 34 | * @param {Object|null} kernel |
|
35 | 35 | */ |
|
36 | 36 | var CodeCell = function (kernel) { |
|
37 | 37 | this.kernel = kernel || null; |
|
38 | 38 | this.code_mirror = null; |
|
39 | 39 | this.input_prompt_number = null; |
|
40 | 40 | this.collapsed = false; |
|
41 | 41 | this.default_mode = 'python'; |
|
42 | 42 | IPython.Cell.apply(this, arguments); |
|
43 | 43 | |
|
44 | 44 | var that = this; |
|
45 | 45 | this.element.focusout( |
|
46 | 46 | function() { that.auto_highlight(); } |
|
47 | 47 | ); |
|
48 | 48 | }; |
|
49 | 49 | |
|
50 | 50 | CodeCell.prototype = new IPython.Cell(); |
|
51 | 51 | |
|
52 | 52 | /** |
|
53 | 53 | * @method auto_highlight |
|
54 | 54 | */ |
|
55 | 55 | CodeCell.prototype.auto_highlight = function () { |
|
56 | 56 | this._auto_highlight(IPython.config.cell_magic_highlight) |
|
57 | 57 | }; |
|
58 | 58 | |
|
59 | 59 | /** @method create_element */ |
|
60 | 60 | CodeCell.prototype.create_element = function () { |
|
61 | IPython.Cell.prototype.create_element.apply(this, arguments); | |
|
62 | ||
|
61 | 63 | var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox'); |
|
64 | cell.append(this.celltoolbar.element); | |
|
62 | 65 | cell.attr('tabindex','2'); |
|
63 | 66 | var input = $('<div></div>').addClass('input hbox'); |
|
64 | 67 | input.append($('<div/>').addClass('prompt input_prompt')); |
|
65 | 68 | var input_area = $('<div/>').addClass('input_area box-flex1'); |
|
66 | 69 | this.code_mirror = CodeMirror(input_area.get(0), { |
|
67 | 70 | indentUnit : 4, |
|
68 | 71 | mode: 'python', |
|
69 | 72 | theme: 'ipython', |
|
70 | 73 | readOnly: this.read_only, |
|
71 | 74 | extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"}, |
|
72 | 75 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this), |
|
73 | 76 | matchBrackets: true |
|
74 | 77 | }); |
|
75 | 78 | input.append(input_area); |
|
76 | 79 | var output = $('<div></div>'); |
|
77 | 80 | cell.append(input).append(output); |
|
78 | 81 | this.element = cell; |
|
79 | 82 | this.output_area = new IPython.OutputArea(output, true); |
|
80 | 83 | |
|
81 | 84 | // construct a completer only if class exist |
|
82 | 85 | // otherwise no print view |
|
83 | 86 | if (IPython.Completer !== undefined) |
|
84 | 87 | { |
|
85 | 88 | this.completer = new IPython.Completer(this); |
|
86 | 89 | } |
|
87 | 90 | }; |
|
88 | 91 | |
|
89 | 92 | /** |
|
90 | 93 | * This method gets called in CodeMirror's onKeyDown/onKeyPress |
|
91 | 94 | * handlers and is used to provide custom key handling. Its return |
|
92 | 95 | * value is used to determine if CodeMirror should ignore the event: |
|
93 | 96 | * true = ignore, false = don't ignore. |
|
94 | 97 | * @method handle_codemirror_keyevent |
|
95 | 98 | */ |
|
96 | 99 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
97 | 100 | |
|
98 | 101 | if (this.read_only){ |
|
99 | 102 | return false; |
|
100 | 103 | } |
|
101 | 104 | |
|
102 | 105 | var that = this; |
|
103 | 106 | // whatever key is pressed, first, cancel the tooltip request before |
|
104 | 107 | // they are sent, and remove tooltip if any, except for tab again |
|
105 | 108 | if (event.type === 'keydown' && event.which != key.TAB ) { |
|
106 | 109 | IPython.tooltip.remove_and_cancel_tooltip(); |
|
107 | 110 | }; |
|
108 | 111 | |
|
109 | 112 | var cur = editor.getCursor(); |
|
110 | 113 | if (event.keyCode === key.ENTER){ |
|
111 | 114 | this.auto_highlight(); |
|
112 | 115 | } |
|
113 | 116 | |
|
114 | 117 | if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) { |
|
115 | 118 | // Always ignore shift-enter in CodeMirror as we handle it. |
|
116 | 119 | return true; |
|
117 | 120 | } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { |
|
118 | 121 | // triger on keypress (!) otherwise inconsistent event.which depending on plateform |
|
119 | 122 | // browser and keyboard layout ! |
|
120 | 123 | // Pressing '(' , request tooltip, don't forget to reappend it |
|
121 | 124 | IPython.tooltip.pending(that); |
|
122 | 125 | } else if (event.which === key.UPARROW && event.type === 'keydown') { |
|
123 | 126 | // If we are not at the top, let CM handle the up arrow and |
|
124 | 127 | // prevent the global keydown handler from handling it. |
|
125 | 128 | if (!that.at_top()) { |
|
126 | 129 | event.stop(); |
|
127 | 130 | return false; |
|
128 | 131 | } else { |
|
129 | 132 | return true; |
|
130 | 133 | }; |
|
131 | 134 | } else if (event.which === key.ESC) { |
|
132 | 135 | IPython.tooltip.remove_and_cancel_tooltip(true); |
|
133 | 136 | return true; |
|
134 | 137 | } else if (event.which === key.DOWNARROW && event.type === 'keydown') { |
|
135 | 138 | // If we are not at the bottom, let CM handle the down arrow and |
|
136 | 139 | // prevent the global keydown handler from handling it. |
|
137 | 140 | if (!that.at_bottom()) { |
|
138 | 141 | event.stop(); |
|
139 | 142 | return false; |
|
140 | 143 | } else { |
|
141 | 144 | return true; |
|
142 | 145 | }; |
|
143 | 146 | } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) { |
|
144 | 147 | if (editor.somethingSelected()){ |
|
145 | 148 | var anchor = editor.getCursor("anchor"); |
|
146 | 149 | var head = editor.getCursor("head"); |
|
147 | 150 | if( anchor.line != head.line){ |
|
148 | 151 | return false; |
|
149 | 152 | } |
|
150 | 153 | } |
|
151 | 154 | IPython.tooltip.request(that); |
|
152 | 155 | event.stop(); |
|
153 | 156 | return true; |
|
154 | 157 | } else if (event.keyCode === key.TAB && event.type == 'keydown') { |
|
155 | 158 | // Tab completion. |
|
156 | 159 | //Do not trim here because of tooltip |
|
157 | 160 | if (editor.somethingSelected()){return false} |
|
158 | 161 | var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); |
|
159 | 162 | if (pre_cursor.trim() === "") { |
|
160 | 163 | // Don't autocomplete if the part of the line before the cursor |
|
161 | 164 | // is empty. In this case, let CodeMirror handle indentation. |
|
162 | 165 | return false; |
|
163 | 166 | } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) { |
|
164 | 167 | IPython.tooltip.request(that); |
|
165 | 168 | // Prevent the event from bubbling up. |
|
166 | 169 | event.stop(); |
|
167 | 170 | // Prevent CodeMirror from handling the tab. |
|
168 | 171 | return true; |
|
169 | 172 | } else { |
|
170 | 173 | event.stop(); |
|
171 | 174 | this.completer.startCompletion(); |
|
172 | 175 | return true; |
|
173 | 176 | }; |
|
174 | 177 | } else { |
|
175 | 178 | // keypress/keyup also trigger on TAB press, and we don't want to |
|
176 | 179 | // use those to disable tab completion. |
|
177 | 180 | return false; |
|
178 | 181 | }; |
|
179 | 182 | return false; |
|
180 | 183 | }; |
|
181 | 184 | |
|
182 | 185 | |
|
183 | 186 | // Kernel related calls. |
|
184 | 187 | |
|
185 | 188 | CodeCell.prototype.set_kernel = function (kernel) { |
|
186 | 189 | this.kernel = kernel; |
|
187 | 190 | } |
|
188 | 191 | |
|
189 | 192 | /** |
|
190 | 193 | * Execute current code cell to the kernel |
|
191 | 194 | * @method execute |
|
192 | 195 | */ |
|
193 | 196 | CodeCell.prototype.execute = function () { |
|
194 | 197 | this.output_area.clear_output(true, true, true); |
|
195 | 198 | this.set_input_prompt('*'); |
|
196 | 199 | this.element.addClass("running"); |
|
197 | 200 | var callbacks = { |
|
198 | 201 | 'execute_reply': $.proxy(this._handle_execute_reply, this), |
|
199 | 202 | 'output': $.proxy(this.output_area.handle_output, this.output_area), |
|
200 | 203 | 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area), |
|
201 | 204 | 'set_next_input': $.proxy(this._handle_set_next_input, this) |
|
202 | 205 | }; |
|
203 | 206 | var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false}); |
|
204 | 207 | }; |
|
205 | 208 | |
|
206 | 209 | /** |
|
207 | 210 | * @method _handle_execute_reply |
|
208 | 211 | * @private |
|
209 | 212 | */ |
|
210 | 213 | CodeCell.prototype._handle_execute_reply = function (content) { |
|
211 | 214 | this.set_input_prompt(content.execution_count); |
|
212 | 215 | this.element.removeClass("running"); |
|
213 | 216 | $([IPython.events]).trigger('set_dirty.Notebook', {'value': true}); |
|
214 | 217 | } |
|
215 | 218 | |
|
216 | 219 | CodeCell.prototype._handle_set_next_input = function (text) { |
|
217 | 220 | var data = {'cell': this, 'text': text} |
|
218 | 221 | $([IPython.events]).trigger('set_next_input.Notebook', data); |
|
219 | 222 | } |
|
220 | 223 | |
|
221 | 224 | // Basic cell manipulation. |
|
222 | 225 | |
|
223 | 226 | CodeCell.prototype.select = function () { |
|
224 | 227 | IPython.Cell.prototype.select.apply(this); |
|
225 | 228 | this.code_mirror.refresh(); |
|
226 | 229 | this.code_mirror.focus(); |
|
227 | 230 | this.auto_highlight(); |
|
228 | 231 | // We used to need an additional refresh() after the focus, but |
|
229 | 232 | // it appears that this has been fixed in CM. This bug would show |
|
230 | 233 | // up on FF when a newly loaded markdown cell was edited. |
|
231 | 234 | }; |
|
232 | 235 | |
|
233 | 236 | |
|
234 | 237 | CodeCell.prototype.select_all = function () { |
|
235 | 238 | var start = {line: 0, ch: 0}; |
|
236 | 239 | var nlines = this.code_mirror.lineCount(); |
|
237 | 240 | var last_line = this.code_mirror.getLine(nlines-1); |
|
238 | 241 | var end = {line: nlines-1, ch: last_line.length}; |
|
239 | 242 | this.code_mirror.setSelection(start, end); |
|
240 | 243 | }; |
|
241 | 244 | |
|
242 | 245 | |
|
243 | 246 | CodeCell.prototype.collapse = function () { |
|
244 | 247 | this.collapsed = true; |
|
245 | 248 | this.output_area.collapse(); |
|
246 | 249 | }; |
|
247 | 250 | |
|
248 | 251 | |
|
249 | 252 | CodeCell.prototype.expand = function () { |
|
250 | 253 | this.collapsed = false; |
|
251 | 254 | this.output_area.expand(); |
|
252 | 255 | }; |
|
253 | 256 | |
|
254 | 257 | |
|
255 | 258 | CodeCell.prototype.toggle_output = function () { |
|
256 | 259 | this.collapsed = Boolean(1 - this.collapsed); |
|
257 | 260 | this.output_area.toggle_output(); |
|
258 | 261 | }; |
|
259 | 262 | |
|
260 | 263 | |
|
261 | 264 | CodeCell.prototype.toggle_output_scroll = function () { |
|
262 | 265 | this.output_area.toggle_scroll(); |
|
263 | 266 | }; |
|
264 | 267 | |
|
265 | 268 | |
|
266 | 269 | CodeCell.input_prompt_classical = function (prompt_value, lines_number) { |
|
267 | 270 | var ns = prompt_value || " "; |
|
268 | 271 | return 'In [' + ns + ']:' |
|
269 | 272 | }; |
|
270 | 273 | |
|
271 | 274 | CodeCell.input_prompt_continuation = function (prompt_value, lines_number) { |
|
272 | 275 | var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)]; |
|
273 | 276 | for(var i=1; i < lines_number; i++){html.push(['...:'])}; |
|
274 | 277 | return html.join('</br>') |
|
275 | 278 | }; |
|
276 | 279 | |
|
277 | 280 | CodeCell.input_prompt_function = CodeCell.input_prompt_classical; |
|
278 | 281 | |
|
279 | 282 | |
|
280 | 283 | CodeCell.prototype.set_input_prompt = function (number) { |
|
281 | 284 | var nline = 1 |
|
282 | 285 | if( this.code_mirror != undefined) { |
|
283 | 286 | nline = this.code_mirror.lineCount(); |
|
284 | 287 | } |
|
285 | 288 | this.input_prompt_number = number; |
|
286 | 289 | var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline); |
|
287 | 290 | this.element.find('div.input_prompt').html(prompt_html); |
|
288 | 291 | }; |
|
289 | 292 | |
|
290 | 293 | |
|
291 | 294 | CodeCell.prototype.clear_input = function () { |
|
292 | 295 | this.code_mirror.setValue(''); |
|
293 | 296 | }; |
|
294 | 297 | |
|
295 | 298 | |
|
296 | 299 | CodeCell.prototype.get_text = function () { |
|
297 | 300 | return this.code_mirror.getValue(); |
|
298 | 301 | }; |
|
299 | 302 | |
|
300 | 303 | |
|
301 | 304 | CodeCell.prototype.set_text = function (code) { |
|
302 | 305 | return this.code_mirror.setValue(code); |
|
303 | 306 | }; |
|
304 | 307 | |
|
305 | 308 | |
|
306 | 309 | CodeCell.prototype.at_top = function () { |
|
307 | 310 | var cursor = this.code_mirror.getCursor(); |
|
308 | 311 | if (cursor.line === 0 && cursor.ch === 0) { |
|
309 | 312 | return true; |
|
310 | 313 | } else { |
|
311 | 314 | return false; |
|
312 | 315 | } |
|
313 | 316 | }; |
|
314 | 317 | |
|
315 | 318 | |
|
316 | 319 | CodeCell.prototype.at_bottom = function () { |
|
317 | 320 | var cursor = this.code_mirror.getCursor(); |
|
318 | 321 | if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) { |
|
319 | 322 | return true; |
|
320 | 323 | } else { |
|
321 | 324 | return false; |
|
322 | 325 | } |
|
323 | 326 | }; |
|
324 | 327 | |
|
325 | 328 | |
|
326 | 329 | CodeCell.prototype.clear_output = function (stdout, stderr, other) { |
|
327 | 330 | this.output_area.clear_output(stdout, stderr, other); |
|
328 | 331 | }; |
|
329 | 332 | |
|
330 | 333 | |
|
331 | 334 | // JSON serialization |
|
332 | 335 | |
|
333 | 336 | CodeCell.prototype.fromJSON = function (data) { |
|
334 | 337 | IPython.Cell.prototype.fromJSON.apply(this, arguments); |
|
335 | 338 | if (data.cell_type === 'code') { |
|
336 | 339 | if (data.input !== undefined) { |
|
337 | 340 | this.set_text(data.input); |
|
338 | 341 | // make this value the starting point, so that we can only undo |
|
339 | 342 | // to this state, instead of a blank cell |
|
340 | 343 | this.code_mirror.clearHistory(); |
|
341 | 344 | this.auto_highlight(); |
|
342 | 345 | } |
|
343 | 346 | if (data.prompt_number !== undefined) { |
|
344 | 347 | this.set_input_prompt(data.prompt_number); |
|
345 | 348 | } else { |
|
346 | 349 | this.set_input_prompt(); |
|
347 | 350 | }; |
|
348 | 351 | this.output_area.fromJSON(data.outputs); |
|
349 | 352 | if (data.collapsed !== undefined) { |
|
350 | 353 | if (data.collapsed) { |
|
351 | 354 | this.collapse(); |
|
352 | 355 | } else { |
|
353 | 356 | this.expand(); |
|
354 | 357 | }; |
|
355 | 358 | }; |
|
356 | 359 | }; |
|
357 | 360 | }; |
|
358 | 361 | |
|
359 | 362 | |
|
360 | 363 | CodeCell.prototype.toJSON = function () { |
|
361 | 364 | var data = IPython.Cell.prototype.toJSON.apply(this); |
|
362 | 365 | data.input = this.get_text(); |
|
363 | 366 | data.cell_type = 'code'; |
|
364 | 367 | if (this.input_prompt_number) { |
|
365 | 368 | data.prompt_number = this.input_prompt_number; |
|
366 | 369 | }; |
|
367 | 370 | var outputs = this.output_area.toJSON(); |
|
368 | 371 | data.outputs = outputs; |
|
369 | 372 | data.language = 'python'; |
|
370 | 373 | data.collapsed = this.collapsed; |
|
371 | 374 | return data; |
|
372 | 375 | }; |
|
373 | 376 | |
|
374 | 377 | |
|
375 | 378 | IPython.CodeCell = CodeCell; |
|
376 | 379 | |
|
377 | 380 | return IPython; |
|
378 | 381 | }(IPython)); |
@@ -1,35 +1,47 b'' | |||
|
1 | 1 | // leave at least 2 line with only a star on it below, or doc generation fails |
|
2 | 2 | /** |
|
3 | 3 | * |
|
4 | 4 | * |
|
5 | 5 | * Placeholder for custom user javascript |
|
6 | 6 | * mainly to be overridden in profile/static/js/custom.js |
|
7 | 7 | * This will always be an empty file in IPython |
|
8 | 8 | * |
|
9 | 9 | * User could add any javascript in the `profile/static/js/custom.js` file |
|
10 | 10 | * (and should create it if it does not exist). |
|
11 | 11 | * It will be executed by the ipython notebook at load time. |
|
12 | 12 | * |
|
13 | 13 | * Same thing with `profile/static/css/custom.css` to inject custom css into the notebook. |
|
14 | 14 | * |
|
15 | 15 | * Example : |
|
16 | 16 | * |
|
17 | 17 | * Create a custom button in toolbar that execute `%qtconsole` in kernel |
|
18 | 18 | * and hence open a qtconsole attached to the same kernel as the current notebook |
|
19 | 19 | * |
|
20 | 20 | * $([IPython.events]).on('notebook_loaded.Notebook', function(){ |
|
21 | 21 | * IPython.toolbar.add_buttons_group([ |
|
22 | 22 | * { |
|
23 | 23 | * 'label' : 'run qtconsole', |
|
24 | 24 | * 'icon' : 'ui-icon-calculator', // select your icon from http://jqueryui.com/themeroller/ |
|
25 | 25 | * 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')} |
|
26 | 26 | * } |
|
27 | 27 | * // add more button here if needed. |
|
28 | 28 | * ]); |
|
29 | 29 | * }); |
|
30 | 30 | * |
|
31 | * Example : | |
|
32 | * | |
|
33 | * Use `jQuery.getScript(url [, success(script, textStatus, jqXHR)] );` | |
|
34 | * to load custom script into the notebook. | |
|
35 | * | |
|
36 | * // to load the metadata ui extension example. | |
|
37 | * $.getScript('/static/js/celltoolbarpresets/example.js'); | |
|
38 | * // or | |
|
39 | * // to load the metadata ui extension to control slideshow mode / reveal js for nbconvert | |
|
40 | * $.getScript('/static/js/celltoolbarpresets/slideshow.js'); | |
|
41 | * | |
|
42 | * | |
|
31 | 43 | * @module IPython |
|
32 | 44 | * @namespace IPython |
|
33 | 45 | * @class customjs |
|
34 | 46 | * @static |
|
35 | 47 | */ |
@@ -1,177 +1,178 b'' | |||
|
1 | 1 | //---------------------------------------------------------------------------- |
|
2 | 2 | // Copyright (C) 2011 The IPython Development Team |
|
3 | 3 | // |
|
4 | 4 | // Distributed under the terms of the BSD License. The full license is in |
|
5 | 5 | // the file COPYING, distributed as part of this software. |
|
6 | 6 | //---------------------------------------------------------------------------- |
|
7 | 7 | |
|
8 | 8 | //============================================================================ |
|
9 | 9 | // ToolBar |
|
10 | 10 | //============================================================================ |
|
11 | 11 | |
|
12 | 12 | var IPython = (function (IPython) { |
|
13 | 13 | |
|
14 | 14 | var MainToolBar = function (selector) { |
|
15 | 15 | this.selector = selector; |
|
16 | 16 | IPython.ToolBar.apply(this, arguments); |
|
17 | 17 | this.construct(); |
|
18 | 18 | this.add_drop_down_list(); |
|
19 | 19 | this.bind_events(); |
|
20 | $(this.selector) | |
|
21 | .append($('<label/>').text('Cell Toolbar:')) | |
|
22 | .append(IPython.CellToolbar.dropdown_preset_element) | |
|
20 | 23 | }; |
|
21 | 24 | |
|
22 | 25 | MainToolBar.prototype = new IPython.ToolBar(); |
|
23 | 26 | |
|
24 | 27 | MainToolBar.prototype.construct = function () { |
|
25 | 28 | this.add_buttons_group([ |
|
26 | 29 | { |
|
27 | 30 | id : 'save_b', |
|
28 | 31 | label : 'Save', |
|
29 | 32 | icon : 'ui-icon-disk', |
|
30 | 33 | callback : function () { |
|
31 | 34 | IPython.notebook.save_notebook(); |
|
32 | 35 | } |
|
33 | 36 | } |
|
34 | 37 | ]); |
|
35 | 38 | this.add_buttons_group([ |
|
36 | 39 | { |
|
37 | 40 | id : 'cut_b', |
|
38 | 41 | label : 'Cut Cell', |
|
39 | 42 | icon : 'ui-icon-scissors', |
|
40 | 43 | callback : function () { |
|
41 | 44 | IPython.notebook.cut_cell(); |
|
42 | 45 | } |
|
43 | 46 | }, |
|
44 | 47 | { |
|
45 | 48 | id : 'copy_b', |
|
46 | 49 | label : 'Copy Cell', |
|
47 | 50 | icon : 'ui-icon-copy', |
|
48 | 51 | callback : function () { |
|
49 | 52 | IPython.notebook.copy_cell(); |
|
50 | 53 | } |
|
51 | 54 | }, |
|
52 | 55 | { |
|
53 | 56 | id : 'paste_b', |
|
54 | 57 | label : 'Paste Cell Below', |
|
55 | 58 | icon : 'ui-icon-clipboard', |
|
56 | 59 | callback : function () { |
|
57 | 60 | IPython.notebook.paste_cell_below(); |
|
58 | 61 | } |
|
59 | 62 | } |
|
60 | 63 | ],'cut_copy_paste'); |
|
61 | 64 | |
|
62 | 65 | this.add_buttons_group([ |
|
63 | 66 | { |
|
64 | 67 | id : 'move_up_b', |
|
65 | 68 | label : 'Move Cell Up', |
|
66 | 69 | icon : 'ui-icon-arrowthick-1-n', |
|
67 | 70 | callback : function () { |
|
68 | 71 | IPython.notebook.move_cell_up(); |
|
69 | 72 | } |
|
70 | 73 | }, |
|
71 | 74 | { |
|
72 | 75 | id : 'move_down_b', |
|
73 | 76 | label : 'Move Cell Down', |
|
74 | 77 | icon : 'ui-icon-arrowthick-1-s', |
|
75 | 78 | callback : function () { |
|
76 | 79 | IPython.notebook.move_cell_down(); |
|
77 | 80 | } |
|
78 | 81 | } |
|
79 | 82 | ],'move_up_down'); |
|
80 | 83 | |
|
81 | 84 | this.add_buttons_group([ |
|
82 | 85 | { |
|
83 | 86 | id : 'insert_above_b', |
|
84 | 87 | label : 'Insert Cell Above', |
|
85 | 88 | icon : 'ui-icon-arrowthickstop-1-n', |
|
86 | 89 | callback : function () { |
|
87 | 90 | IPython.notebook.insert_cell_above('code'); |
|
88 | 91 | } |
|
89 | 92 | }, |
|
90 | 93 | { |
|
91 | 94 | id : 'insert_below_b', |
|
92 | 95 | label : 'Insert Cell Below', |
|
93 | 96 | icon : 'ui-icon-arrowthickstop-1-s', |
|
94 | 97 | callback : function () { |
|
95 | 98 | IPython.notebook.insert_cell_below('code'); |
|
96 | 99 | } |
|
97 | 100 | } |
|
98 | 101 | ],'insert_above_below'); |
|
99 | 102 | |
|
100 | 103 | this.add_buttons_group([ |
|
101 | 104 | { |
|
102 | 105 | id : 'run_b', |
|
103 | 106 | label : 'Run Cell', |
|
104 | 107 | icon : 'ui-icon-play', |
|
105 | 108 | callback : function () { |
|
106 | 109 | IPython.notebook.execute_selected_cell(); |
|
107 | 110 | } |
|
108 | 111 | }, |
|
109 | 112 | { |
|
110 | 113 | id : 'interrupt_b', |
|
111 | 114 | label : 'Interrupt', |
|
112 | 115 | icon : 'ui-icon-stop', |
|
113 | 116 | callback : function () { |
|
114 | 117 | IPython.notebook.kernel.interrupt(); |
|
115 | 118 | } |
|
116 | 119 | } |
|
117 | 120 | ],'run_int'); |
|
118 | ||
|
119 | ||
|
120 | 121 | }; |
|
121 | 122 | |
|
122 | 123 | MainToolBar.prototype.add_drop_down_list = function () { |
|
123 | 124 | var select = $(this.selector) |
|
124 | 125 | .append($('<select/>') |
|
125 | 126 | .attr('id','cell_type') |
|
126 | 127 | .addClass('ui-widget ui-widget-content') |
|
127 | 128 | .append($('<option/>').attr('value','code').text('Code')) |
|
128 | 129 | .append($('<option/>').attr('value','markdown').text('Markdown')) |
|
129 | 130 | .append($('<option/>').attr('value','raw').text('Raw Text')) |
|
130 | 131 | .append($('<option/>').attr('value','heading1').text('Heading 1')) |
|
131 | 132 | .append($('<option/>').attr('value','heading2').text('Heading 2')) |
|
132 | 133 | .append($('<option/>').attr('value','heading3').text('Heading 3')) |
|
133 | 134 | .append($('<option/>').attr('value','heading4').text('Heading 4')) |
|
134 | 135 | .append($('<option/>').attr('value','heading5').text('Heading 5')) |
|
135 | 136 | .append($('<option/>').attr('value','heading6').text('Heading 6')) |
|
136 | 137 | ); |
|
137 | 138 | }; |
|
138 | 139 | |
|
139 | 140 | MainToolBar.prototype.bind_events = function () { |
|
140 | 141 | var that = this; |
|
141 | 142 | |
|
142 | 143 | this.element.find('#cell_type').change(function () { |
|
143 | 144 | var cell_type = $(this).val(); |
|
144 | 145 | if (cell_type === 'code') { |
|
145 | 146 | IPython.notebook.to_code(); |
|
146 | 147 | } else if (cell_type === 'markdown') { |
|
147 | 148 | IPython.notebook.to_markdown(); |
|
148 | 149 | } else if (cell_type === 'raw') { |
|
149 | 150 | IPython.notebook.to_raw(); |
|
150 | 151 | } else if (cell_type === 'heading1') { |
|
151 | 152 | IPython.notebook.to_heading(undefined, 1); |
|
152 | 153 | } else if (cell_type === 'heading2') { |
|
153 | 154 | IPython.notebook.to_heading(undefined, 2); |
|
154 | 155 | } else if (cell_type === 'heading3') { |
|
155 | 156 | IPython.notebook.to_heading(undefined, 3); |
|
156 | 157 | } else if (cell_type === 'heading4') { |
|
157 | 158 | IPython.notebook.to_heading(undefined, 4); |
|
158 | 159 | } else if (cell_type === 'heading5') { |
|
159 | 160 | IPython.notebook.to_heading(undefined, 5); |
|
160 | 161 | } else if (cell_type === 'heading6') { |
|
161 | 162 | IPython.notebook.to_heading(undefined, 6); |
|
162 | 163 | } |
|
163 | 164 | }); |
|
164 | 165 | $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) { |
|
165 | 166 | if (data.cell_type === 'heading') { |
|
166 | 167 | that.element.find('#cell_type').val(data.cell_type+data.level); |
|
167 | 168 | } else { |
|
168 | 169 | that.element.find('#cell_type').val(data.cell_type); |
|
169 | 170 | } |
|
170 | 171 | }); |
|
171 | 172 | }; |
|
172 | 173 | |
|
173 | 174 | IPython.MainToolBar = MainToolBar; |
|
174 | 175 | |
|
175 | 176 | return IPython; |
|
176 | 177 | |
|
177 | 178 | }(IPython)); |
@@ -1,531 +1,533 b'' | |||
|
1 | 1 | //---------------------------------------------------------------------------- |
|
2 | 2 | // Copyright (C) 2008-2012 The IPython Development Team |
|
3 | 3 | // |
|
4 | 4 | // Distributed under the terms of the BSD License. The full license is in |
|
5 | 5 | // the file COPYING, distributed as part of this software. |
|
6 | 6 | //---------------------------------------------------------------------------- |
|
7 | 7 | |
|
8 | 8 | //============================================================================ |
|
9 | 9 | // TextCell |
|
10 | 10 | //============================================================================ |
|
11 | 11 | |
|
12 | 12 | /** |
|
13 | 13 | A module that allow to create different type of Text Cell |
|
14 | 14 | @module IPython |
|
15 | 15 | @namespace IPython |
|
16 | 16 | */ |
|
17 | 17 | var IPython = (function (IPython) { |
|
18 | 18 | |
|
19 | 19 | // TextCell base class |
|
20 | 20 | var key = IPython.utils.keycodes; |
|
21 | 21 | |
|
22 | 22 | /** |
|
23 | 23 | * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text' |
|
24 | 24 | * cell start as not redered. |
|
25 | 25 | * |
|
26 | 26 | * @class TextCell |
|
27 | 27 | * @constructor TextCell |
|
28 | 28 | * @extend Ipython.Cell |
|
29 | 29 | */ |
|
30 | 30 | var TextCell = function () { |
|
31 | 31 | this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed'; |
|
32 | 32 | IPython.Cell.apply(this, arguments); |
|
33 | 33 | this.rendered = false; |
|
34 | 34 | this.cell_type = this.cell_type || 'text'; |
|
35 | 35 | }; |
|
36 | 36 | |
|
37 | 37 | TextCell.prototype = new IPython.Cell(); |
|
38 | 38 | |
|
39 | 39 | /** |
|
40 | 40 | * Create the DOM element of the TextCell |
|
41 | 41 | * @method create_element |
|
42 | 42 | * @private |
|
43 | 43 | */ |
|
44 | 44 | TextCell.prototype.create_element = function () { |
|
45 | var cell = $("<div>").addClass('cell text_cell border-box-sizing'); | |
|
45 | IPython.Cell.prototype.create_element.apply(this, arguments); | |
|
46 | var cell = $("<div>").addClass('cell text_cell border-box-sizing vbox'); | |
|
47 | cell.append(this.celltoolbar.element); | |
|
46 | 48 | cell.attr('tabindex','2'); |
|
47 | 49 | var input_area = $('<div/>').addClass('text_cell_input border-box-sizing'); |
|
48 | 50 | this.code_mirror = CodeMirror(input_area.get(0), { |
|
49 | 51 | indentUnit : 4, |
|
50 | 52 | mode: this.code_mirror_mode, |
|
51 | 53 | theme: 'default', |
|
52 | 54 | value: this.placeholder, |
|
53 | 55 | readOnly: this.read_only, |
|
54 | 56 | lineWrapping : true, |
|
55 | 57 | extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"}, |
|
56 | 58 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) |
|
57 | 59 | }); |
|
58 | 60 | // The tabindex=-1 makes this div focusable. |
|
59 | 61 | var render_area = $('<div/>').addClass('text_cell_render border-box-sizing'). |
|
60 | 62 | addClass('rendered_html').attr('tabindex','-1'); |
|
61 | 63 | cell.append(input_area).append(render_area); |
|
62 | 64 | this.element = cell; |
|
63 | 65 | }; |
|
64 | 66 | |
|
65 | 67 | |
|
66 | 68 | /** |
|
67 | 69 | * Bind the DOM evet to cell actions |
|
68 | 70 | * Need to be called after TextCell.create_element |
|
69 | 71 | * @private |
|
70 | 72 | * @method bind_event |
|
71 | 73 | */ |
|
72 | 74 | TextCell.prototype.bind_events = function () { |
|
73 | 75 | IPython.Cell.prototype.bind_events.apply(this); |
|
74 | 76 | var that = this; |
|
75 | 77 | this.element.keydown(function (event) { |
|
76 | 78 | if (event.which === 13 && !event.shiftKey) { |
|
77 | 79 | if (that.rendered) { |
|
78 | 80 | that.edit(); |
|
79 | 81 | return false; |
|
80 | 82 | }; |
|
81 | 83 | }; |
|
82 | 84 | }); |
|
83 | 85 | this.element.dblclick(function () { |
|
84 | 86 | that.edit(); |
|
85 | 87 | }); |
|
86 | 88 | }; |
|
87 | 89 | |
|
88 | 90 | /** |
|
89 | 91 | * This method gets called in CodeMirror's onKeyDown/onKeyPress |
|
90 | 92 | * handlers and is used to provide custom key handling. |
|
91 | 93 | * |
|
92 | 94 | * Subclass should override this method to have custom handeling |
|
93 | 95 | * |
|
94 | 96 | * @method handle_codemirror_keyevent |
|
95 | 97 | * @param {CodeMirror} editor - The codemirror instance bound to the cell |
|
96 | 98 | * @param {event} event - |
|
97 | 99 | * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise |
|
98 | 100 | */ |
|
99 | 101 | TextCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
100 | 102 | |
|
101 | 103 | if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) { |
|
102 | 104 | // Always ignore shift-enter in CodeMirror as we handle it. |
|
103 | 105 | return true; |
|
104 | 106 | } |
|
105 | 107 | return false; |
|
106 | 108 | }; |
|
107 | 109 | |
|
108 | 110 | /** |
|
109 | 111 | * Select the current cell and trigger 'focus' |
|
110 | 112 | * @method select |
|
111 | 113 | */ |
|
112 | 114 | TextCell.prototype.select = function () { |
|
113 | 115 | IPython.Cell.prototype.select.apply(this); |
|
114 | 116 | var output = this.element.find("div.text_cell_render"); |
|
115 | 117 | output.trigger('focus'); |
|
116 | 118 | }; |
|
117 | 119 | |
|
118 | 120 | /** |
|
119 | 121 | * unselect the current cell and `render` it |
|
120 | 122 | * @method unselect |
|
121 | 123 | */ |
|
122 | 124 | TextCell.prototype.unselect = function() { |
|
123 | 125 | // render on selection of another cell |
|
124 | 126 | this.render(); |
|
125 | 127 | IPython.Cell.prototype.unselect.apply(this); |
|
126 | 128 | }; |
|
127 | 129 | |
|
128 | 130 | /** |
|
129 | 131 | * |
|
130 | 132 | * put the current cell in edition mode |
|
131 | 133 | * @method edit |
|
132 | 134 | */ |
|
133 | 135 | TextCell.prototype.edit = function () { |
|
134 | 136 | if ( this.read_only ) return; |
|
135 | 137 | if (this.rendered === true) { |
|
136 | 138 | var text_cell = this.element; |
|
137 | 139 | var output = text_cell.find("div.text_cell_render"); |
|
138 | 140 | output.hide(); |
|
139 | 141 | text_cell.find('div.text_cell_input').show(); |
|
140 | 142 | this.code_mirror.refresh(); |
|
141 | 143 | this.code_mirror.focus(); |
|
142 | 144 | // We used to need an additional refresh() after the focus, but |
|
143 | 145 | // it appears that this has been fixed in CM. This bug would show |
|
144 | 146 | // up on FF when a newly loaded markdown cell was edited. |
|
145 | 147 | this.rendered = false; |
|
146 | 148 | if (this.get_text() === this.placeholder) { |
|
147 | 149 | this.set_text(''); |
|
148 | 150 | this.refresh(); |
|
149 | 151 | } |
|
150 | 152 | } |
|
151 | 153 | }; |
|
152 | 154 | |
|
153 | 155 | |
|
154 | 156 | /** |
|
155 | 157 | * Empty, Subclasses must define render. |
|
156 | 158 | * @method render |
|
157 | 159 | */ |
|
158 | 160 | TextCell.prototype.render = function () {}; |
|
159 | 161 | |
|
160 | 162 | |
|
161 | 163 | /** |
|
162 | 164 | * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}} |
|
163 | 165 | * @method get_text |
|
164 | 166 | * @retrun {string} CodeMirror current text value |
|
165 | 167 | */ |
|
166 | 168 | TextCell.prototype.get_text = function() { |
|
167 | 169 | return this.code_mirror.getValue(); |
|
168 | 170 | }; |
|
169 | 171 | |
|
170 | 172 | /** |
|
171 | 173 | * @param {string} text - Codemiror text value |
|
172 | 174 | * @see TextCell#get_text |
|
173 | 175 | * @method set_text |
|
174 | 176 | * */ |
|
175 | 177 | TextCell.prototype.set_text = function(text) { |
|
176 | 178 | this.code_mirror.setValue(text); |
|
177 | 179 | this.code_mirror.refresh(); |
|
178 | 180 | }; |
|
179 | 181 | |
|
180 | 182 | /** |
|
181 | 183 | * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}} |
|
182 | 184 | * @method get_rendered |
|
183 | 185 | * @return {html} html of rendered element |
|
184 | 186 | * */ |
|
185 | 187 | TextCell.prototype.get_rendered = function() { |
|
186 | 188 | return this.element.find('div.text_cell_render').html(); |
|
187 | 189 | }; |
|
188 | 190 | |
|
189 | 191 | /** |
|
190 | 192 | * @method set_rendered |
|
191 | 193 | */ |
|
192 | 194 | TextCell.prototype.set_rendered = function(text) { |
|
193 | 195 | this.element.find('div.text_cell_render').html(text); |
|
194 | 196 | }; |
|
195 | 197 | |
|
196 | 198 | /** |
|
197 | 199 | * not deprecated, but implementation wrong |
|
198 | 200 | * @method at_top |
|
199 | 201 | * @deprecated |
|
200 | 202 | * @return {Boolean} true is cell rendered, false otherwise |
|
201 | 203 | * I doubt this is what it is supposed to do |
|
202 | 204 | * this implementation is completly false |
|
203 | 205 | */ |
|
204 | 206 | TextCell.prototype.at_top = function () { |
|
205 | 207 | if (this.rendered) { |
|
206 | 208 | return true; |
|
207 | 209 | } else { |
|
208 | 210 | return false; |
|
209 | 211 | } |
|
210 | 212 | }; |
|
211 | 213 | |
|
212 | 214 | |
|
213 | 215 | /** |
|
214 | 216 | * not deprecated, but implementation wrong |
|
215 | 217 | * @method at_bottom |
|
216 | 218 | * @deprecated |
|
217 | 219 | * @return {Boolean} true is cell rendered, false otherwise |
|
218 | 220 | * I doubt this is what it is supposed to do |
|
219 | 221 | * this implementation is completly false |
|
220 | 222 | * */ |
|
221 | 223 | TextCell.prototype.at_bottom = function () { |
|
222 | 224 | if (this.rendered) { |
|
223 | 225 | return true; |
|
224 | 226 | } else { |
|
225 | 227 | return false; |
|
226 | 228 | } |
|
227 | 229 | }; |
|
228 | 230 | |
|
229 | 231 | /** |
|
230 | 232 | * Create Text cell from JSON |
|
231 | 233 | * @param {json} data - JSON serialized text-cell |
|
232 | 234 | * @method fromJSON |
|
233 | 235 | */ |
|
234 | 236 | TextCell.prototype.fromJSON = function (data) { |
|
235 | 237 | IPython.Cell.prototype.fromJSON.apply(this, arguments); |
|
236 | 238 | if (data.cell_type === this.cell_type) { |
|
237 | 239 | if (data.source !== undefined) { |
|
238 | 240 | this.set_text(data.source); |
|
239 | 241 | // make this value the starting point, so that we can only undo |
|
240 | 242 | // to this state, instead of a blank cell |
|
241 | 243 | this.code_mirror.clearHistory(); |
|
242 | 244 | this.set_rendered(data.rendered || ''); |
|
243 | 245 | this.rendered = false; |
|
244 | 246 | this.render(); |
|
245 | 247 | } |
|
246 | 248 | } |
|
247 | 249 | }; |
|
248 | 250 | |
|
249 | 251 | /** Generate JSON from cell |
|
250 | 252 | * @return {object} cell data serialised to json |
|
251 | 253 | */ |
|
252 | 254 | TextCell.prototype.toJSON = function () { |
|
253 | 255 | var data = IPython.Cell.prototype.toJSON.apply(this); |
|
254 | 256 | data.cell_type = this.cell_type; |
|
255 | 257 | data.source = this.get_text(); |
|
256 | 258 | return data; |
|
257 | 259 | }; |
|
258 | 260 | |
|
259 | 261 | |
|
260 | 262 | /** |
|
261 | 263 | * @constructor HtmlCell |
|
262 | 264 | * @class HtmlCell |
|
263 | 265 | * @extends Ipython.TextCell |
|
264 | 266 | */ |
|
265 | 267 | var HTMLCell = function () { |
|
266 | 268 | this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$"; |
|
267 | 269 | IPython.TextCell.apply(this, arguments); |
|
268 | 270 | this.cell_type = 'html'; |
|
269 | 271 | }; |
|
270 | 272 | |
|
271 | 273 | |
|
272 | 274 | HTMLCell.prototype = new TextCell(); |
|
273 | 275 | |
|
274 | 276 | /** |
|
275 | 277 | * @method render |
|
276 | 278 | */ |
|
277 | 279 | HTMLCell.prototype.render = function () { |
|
278 | 280 | if (this.rendered === false) { |
|
279 | 281 | var text = this.get_text(); |
|
280 | 282 | if (text === "") { text = this.placeholder; } |
|
281 | 283 | this.set_rendered(text); |
|
282 | 284 | this.typeset(); |
|
283 | 285 | this.element.find('div.text_cell_input').hide(); |
|
284 | 286 | this.element.find("div.text_cell_render").show(); |
|
285 | 287 | this.rendered = true; |
|
286 | 288 | } |
|
287 | 289 | }; |
|
288 | 290 | |
|
289 | 291 | |
|
290 | 292 | /** |
|
291 | 293 | * @class MarkdownCell |
|
292 | 294 | * @constructor MarkdownCell |
|
293 | 295 | * @extends Ipython.HtmlCell |
|
294 | 296 | */ |
|
295 | 297 | var MarkdownCell = function () { |
|
296 | 298 | this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$"; |
|
297 | 299 | IPython.TextCell.apply(this, arguments); |
|
298 | 300 | this.cell_type = 'markdown'; |
|
299 | 301 | }; |
|
300 | 302 | |
|
301 | 303 | |
|
302 | 304 | MarkdownCell.prototype = new TextCell(); |
|
303 | 305 | |
|
304 | 306 | /** |
|
305 | 307 | * @method render |
|
306 | 308 | */ |
|
307 | 309 | MarkdownCell.prototype.render = function () { |
|
308 | 310 | if (this.rendered === false) { |
|
309 | 311 | var text = this.get_text(); |
|
310 | 312 | if (text === "") { text = this.placeholder; } |
|
311 | 313 | text = IPython.mathjaxutils.remove_math(text) |
|
312 | 314 | var html = IPython.markdown_converter.makeHtml(text); |
|
313 | 315 | html = IPython.mathjaxutils.replace_math(html) |
|
314 | 316 | try { |
|
315 | 317 | this.set_rendered(html); |
|
316 | 318 | } catch (e) { |
|
317 | 319 | console.log("Error running Javascript in Markdown:"); |
|
318 | 320 | console.log(e); |
|
319 | 321 | this.set_rendered($("<div/>").addClass("js-error").html( |
|
320 | 322 | "Error rendering Markdown!<br/>" + e.toString()) |
|
321 | 323 | ); |
|
322 | 324 | } |
|
323 | 325 | this.element.find('div.text_cell_input').hide(); |
|
324 | 326 | this.element.find("div.text_cell_render").show(); |
|
325 | 327 | var code_snippets = this.element.find("pre > code"); |
|
326 | 328 | code_snippets.replaceWith(function () { |
|
327 | 329 | var code = $(this).html(); |
|
328 | 330 | /* Substitute br for newlines and for spaces |
|
329 | 331 | before highlighting, since prettify doesn't |
|
330 | 332 | preserve those on all browsers */ |
|
331 | 333 | code = code.replace(/(\r\n|\n|\r)/gm, "<br/>"); |
|
332 | 334 | code = code.replace(/ /gm, ' '); |
|
333 | 335 | code = prettyPrintOne(code); |
|
334 | 336 | |
|
335 | 337 | return '<code class="prettyprint">' + code + '</code>'; |
|
336 | 338 | }); |
|
337 | 339 | this.typeset() |
|
338 | 340 | this.rendered = true; |
|
339 | 341 | } |
|
340 | 342 | }; |
|
341 | 343 | |
|
342 | 344 | |
|
343 | 345 | // RawCell |
|
344 | 346 | |
|
345 | 347 | /** |
|
346 | 348 | * @class RawCell |
|
347 | 349 | * @constructor RawCell |
|
348 | 350 | * @extends Ipython.TextCell |
|
349 | 351 | */ |
|
350 | 352 | var RawCell = function () { |
|
351 | 353 | this.placeholder = "Type plain text and LaTeX: $\\alpha^2$"; |
|
352 | 354 | this.code_mirror_mode = 'rst'; |
|
353 | 355 | IPython.TextCell.apply(this, arguments); |
|
354 | 356 | this.cell_type = 'raw'; |
|
355 | 357 | var that = this |
|
356 | 358 | |
|
357 | 359 | this.element.focusout( |
|
358 | 360 | function() { that.auto_highlight(); } |
|
359 | 361 | ); |
|
360 | 362 | }; |
|
361 | 363 | |
|
362 | 364 | |
|
363 | 365 | RawCell.prototype = new TextCell(); |
|
364 | 366 | |
|
365 | 367 | /** |
|
366 | 368 | * Trigger autodetection of highlight scheme for current cell |
|
367 | 369 | * @method auto_highlight |
|
368 | 370 | */ |
|
369 | 371 | RawCell.prototype.auto_highlight = function () { |
|
370 | 372 | this._auto_highlight(IPython.config.raw_cell_highlight); |
|
371 | 373 | }; |
|
372 | 374 | |
|
373 | 375 | /** @method render **/ |
|
374 | 376 | RawCell.prototype.render = function () { |
|
375 | 377 | this.rendered = true; |
|
376 | 378 | this.edit(); |
|
377 | 379 | }; |
|
378 | 380 | |
|
379 | 381 | |
|
380 | 382 | /** @method handle_codemirror_keyevent **/ |
|
381 | 383 | RawCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
382 | 384 | |
|
383 | 385 | var that = this; |
|
384 | 386 | if (event.which === key.UPARROW && event.type === 'keydown') { |
|
385 | 387 | // If we are not at the top, let CM handle the up arrow and |
|
386 | 388 | // prevent the global keydown handler from handling it. |
|
387 | 389 | if (!that.at_top()) { |
|
388 | 390 | event.stop(); |
|
389 | 391 | return false; |
|
390 | 392 | } else { |
|
391 | 393 | return true; |
|
392 | 394 | }; |
|
393 | 395 | } else if (event.which === key.DOWNARROW && event.type === 'keydown') { |
|
394 | 396 | // If we are not at the bottom, let CM handle the down arrow and |
|
395 | 397 | // prevent the global keydown handler from handling it. |
|
396 | 398 | if (!that.at_bottom()) { |
|
397 | 399 | event.stop(); |
|
398 | 400 | return false; |
|
399 | 401 | } else { |
|
400 | 402 | return true; |
|
401 | 403 | }; |
|
402 | 404 | }; |
|
403 | 405 | return false; |
|
404 | 406 | }; |
|
405 | 407 | |
|
406 | 408 | /** @method select **/ |
|
407 | 409 | RawCell.prototype.select = function () { |
|
408 | 410 | IPython.Cell.prototype.select.apply(this); |
|
409 | 411 | this.code_mirror.refresh(); |
|
410 | 412 | this.code_mirror.focus(); |
|
411 | 413 | }; |
|
412 | 414 | |
|
413 | 415 | /** @method at_top **/ |
|
414 | 416 | RawCell.prototype.at_top = function () { |
|
415 | 417 | var cursor = this.code_mirror.getCursor(); |
|
416 | 418 | if (cursor.line === 0 && cursor.ch === 0) { |
|
417 | 419 | return true; |
|
418 | 420 | } else { |
|
419 | 421 | return false; |
|
420 | 422 | } |
|
421 | 423 | }; |
|
422 | 424 | |
|
423 | 425 | |
|
424 | 426 | /** @method at_bottom **/ |
|
425 | 427 | RawCell.prototype.at_bottom = function () { |
|
426 | 428 | var cursor = this.code_mirror.getCursor(); |
|
427 | 429 | if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) { |
|
428 | 430 | return true; |
|
429 | 431 | } else { |
|
430 | 432 | return false; |
|
431 | 433 | } |
|
432 | 434 | }; |
|
433 | 435 | |
|
434 | 436 | |
|
435 | 437 | /** |
|
436 | 438 | * @class HeadingCell |
|
437 | 439 | * @extends Ipython.TextCell |
|
438 | 440 | */ |
|
439 | 441 | |
|
440 | 442 | /** |
|
441 | 443 | * @constructor HeadingCell |
|
442 | 444 | * @extends Ipython.TextCell |
|
443 | 445 | */ |
|
444 | 446 | var HeadingCell = function () { |
|
445 | 447 | this.placeholder = "Type Heading Here"; |
|
446 | 448 | IPython.TextCell.apply(this, arguments); |
|
447 | 449 | /** |
|
448 | 450 | * heading level of the cell, use getter and setter to access |
|
449 | 451 | * @property level |
|
450 | 452 | */ |
|
451 | 453 | this.level = 1; |
|
452 | 454 | this.cell_type = 'heading'; |
|
453 | 455 | }; |
|
454 | 456 | |
|
455 | 457 | |
|
456 | 458 | HeadingCell.prototype = new TextCell(); |
|
457 | 459 | |
|
458 | 460 | /** @method fromJSON */ |
|
459 | 461 | HeadingCell.prototype.fromJSON = function (data) { |
|
460 | 462 | if (data.level != undefined){ |
|
461 | 463 | this.level = data.level; |
|
462 | 464 | } |
|
463 | 465 | IPython.TextCell.prototype.fromJSON.apply(this, arguments); |
|
464 | 466 | }; |
|
465 | 467 | |
|
466 | 468 | |
|
467 | 469 | /** @method toJSON */ |
|
468 | 470 | HeadingCell.prototype.toJSON = function () { |
|
469 | 471 | var data = IPython.TextCell.prototype.toJSON.apply(this); |
|
470 | 472 | data.level = this.get_level(); |
|
471 | 473 | return data; |
|
472 | 474 | }; |
|
473 | 475 | |
|
474 | 476 | |
|
475 | 477 | /** |
|
476 | 478 | * Change heading level of cell, and re-render |
|
477 | 479 | * @method set_level |
|
478 | 480 | */ |
|
479 | 481 | HeadingCell.prototype.set_level = function (level) { |
|
480 | 482 | this.level = level; |
|
481 | 483 | if (this.rendered) { |
|
482 | 484 | this.rendered = false; |
|
483 | 485 | this.render(); |
|
484 | 486 | }; |
|
485 | 487 | }; |
|
486 | 488 | |
|
487 | 489 | /** The depth of header cell, based on html (h1 to h6) |
|
488 | 490 | * @method get_level |
|
489 | 491 | * @return {integer} level - for 1 to 6 |
|
490 | 492 | */ |
|
491 | 493 | HeadingCell.prototype.get_level = function () { |
|
492 | 494 | return this.level; |
|
493 | 495 | }; |
|
494 | 496 | |
|
495 | 497 | |
|
496 | 498 | HeadingCell.prototype.set_rendered = function (text) { |
|
497 | 499 | var r = this.element.find("div.text_cell_render"); |
|
498 | 500 | r.empty(); |
|
499 | 501 | r.append($('<h'+this.level+'/>').html(text)); |
|
500 | 502 | }; |
|
501 | 503 | |
|
502 | 504 | |
|
503 | 505 | HeadingCell.prototype.get_rendered = function () { |
|
504 | 506 | var r = this.element.find("div.text_cell_render"); |
|
505 | 507 | return r.children().first().html(); |
|
506 | 508 | }; |
|
507 | 509 | |
|
508 | 510 | |
|
509 | 511 | HeadingCell.prototype.render = function () { |
|
510 | 512 | if (this.rendered === false) { |
|
511 | 513 | var text = this.get_text(); |
|
512 | 514 | if (text === "") { text = this.placeholder; } |
|
513 | 515 | this.set_rendered(text); |
|
514 | 516 | this.typeset(); |
|
515 | 517 | this.element.find('div.text_cell_input').hide(); |
|
516 | 518 | this.element.find("div.text_cell_render").show(); |
|
517 | 519 | this.rendered = true; |
|
518 | 520 | }; |
|
519 | 521 | }; |
|
520 | 522 | |
|
521 | 523 | IPython.TextCell = TextCell; |
|
522 | 524 | IPython.HTMLCell = HTMLCell; |
|
523 | 525 | IPython.MarkdownCell = MarkdownCell; |
|
524 | 526 | IPython.RawCell = RawCell; |
|
525 | 527 | IPython.HeadingCell = HeadingCell; |
|
526 | 528 | |
|
527 | 529 | |
|
528 | 530 | return IPython; |
|
529 | 531 | |
|
530 | 532 | }(IPython)); |
|
531 | 533 |
@@ -1,111 +1,111 b'' | |||
|
1 | 1 | //---------------------------------------------------------------------------- |
|
2 | 2 | // Copyright (C) 2008 The IPython Development Team |
|
3 | 3 | // |
|
4 | 4 | // Distributed under the terms of the BSD License. The full license is in |
|
5 | 5 | // the file COPYING, distributed as part of this software. |
|
6 | 6 | //---------------------------------------------------------------------------- |
|
7 | 7 | |
|
8 | 8 | //============================================================================ |
|
9 | 9 | // ToolBar |
|
10 | 10 | //============================================================================ |
|
11 | 11 | /** |
|
12 | 12 | * @module IPython |
|
13 | 13 | * @namespace IPython |
|
14 | 14 | * @submodule ToolBar |
|
15 | 15 | */ |
|
16 | 16 | |
|
17 | 17 | var IPython = (function (IPython) { |
|
18 | 18 | |
|
19 | 19 | /** |
|
20 | 20 | * A generic toolbar on which one can add button |
|
21 | 21 | * @class ToolBar |
|
22 | 22 | * @constructor |
|
23 | 23 | * @param {Dom object} selector |
|
24 | 24 | */ |
|
25 | 25 | var ToolBar = function (selector) { |
|
26 | 26 | this.selector = selector; |
|
27 | 27 | if (this.selector !== undefined) { |
|
28 | 28 | this.element = $(selector); |
|
29 | 29 | this.style(); |
|
30 | 30 | } |
|
31 | 31 | }; |
|
32 | 32 | |
|
33 | 33 | /** |
|
34 | 34 | * add a group of button into the current toolbar. |
|
35 | 35 | * |
|
36 | 36 | * |
|
37 | 37 | * @example |
|
38 | 38 | * |
|
39 | * IPython.toolbar.add_button_group([ | |
|
39 | * IPython.toolbar.add_buttons_group([ | |
|
40 | 40 | * { |
|
41 | 41 | * label:'my button', |
|
42 | 42 | * icon:'ui-icon-disk', |
|
43 | 43 | * callback:function(){alert('hoho'), |
|
44 | 44 | * id : 'my_button_id', // this is optional |
|
45 | 45 | * }, |
|
46 | 46 | * { |
|
47 | 47 | * label:'my second button', |
|
48 | 48 | * icon:'ui-icon-scissors', |
|
49 | 49 | * callback:function(){alert('be carefull I cut')} |
|
50 | 50 | * } |
|
51 | 51 | * ], |
|
52 | 52 | * "my_button_group_id" |
|
53 | 53 | * ) |
|
54 | 54 | * |
|
55 | 55 | * @method add_buttons_group |
|
56 | 56 | * @param list {List} |
|
57 | 57 | * List of button of the group, with the following paramter for each : |
|
58 | 58 | * @param list.label {string} text to show on button hover |
|
59 | 59 | * @param list.icon {string} icon to choose from [jQuery ThemeRoller](http://jqueryui.com/themeroller/) |
|
60 | 60 | * @param list.callback {function} function to be called on button click |
|
61 | 61 | * @param [list.id] {String} id to give to the button |
|
62 | 62 | * @param [group_id] {String} optionnal id to give to the group |
|
63 | 63 | * |
|
64 | 64 | */ |
|
65 | 65 | ToolBar.prototype.add_buttons_group = function (list, group_id) { |
|
66 | 66 | var span_group = $('<span/>'); |
|
67 | 67 | if( group_id != undefined ) { |
|
68 | 68 | span_group.attr('id',group_id); |
|
69 | 69 | } |
|
70 | 70 | for(var el in list) { |
|
71 | 71 | var button = $('<button/>').button({ |
|
72 | 72 | icons : {primary : list[el].icon}, |
|
73 | 73 | text : false, |
|
74 | 74 | label : list[el].label |
|
75 | 75 | }); |
|
76 | 76 | var id = list[el].id; |
|
77 | 77 | if( id != undefined ) |
|
78 | 78 | button.attr('id',id); |
|
79 | 79 | var fun = list[el].callback; |
|
80 | 80 | button.click(fun); |
|
81 | 81 | span_group.append(button); |
|
82 | 82 | } |
|
83 | 83 | span_group.buttonset(); |
|
84 | 84 | $(this.selector).append(span_group); |
|
85 | 85 | }; |
|
86 | 86 | |
|
87 | 87 | ToolBar.prototype.style = function () { |
|
88 | 88 | this.element.addClass('border-box-sizing'). |
|
89 | 89 | addClass('ui-widget ui-widget-content toolbar'). |
|
90 | 90 | css('border-top-style','none'). |
|
91 | 91 | css('border-left-style','none'). |
|
92 | 92 | css('border-right-style','none'); |
|
93 | 93 | }; |
|
94 | 94 | |
|
95 | 95 | /** |
|
96 | 96 | * Show and hide toolbar |
|
97 | 97 | * @method toggle |
|
98 | 98 | */ |
|
99 | 99 | ToolBar.prototype.toggle = function () { |
|
100 | 100 | this.element.toggle(); |
|
101 | 101 | if (IPython.layout_manager != undefined) { |
|
102 | 102 | IPython.layout_manager.do_resize(); |
|
103 | 103 | } |
|
104 | 104 | }; |
|
105 | 105 | |
|
106 | 106 | |
|
107 | 107 | IPython.ToolBar = ToolBar; |
|
108 | 108 | |
|
109 | 109 | return IPython; |
|
110 | 110 | |
|
111 | 111 | }(IPython)); |
@@ -1,227 +1,229 b'' | |||
|
1 | 1 | {% extends "page.html" %} |
|
2 | 2 | |
|
3 | 3 | {% block stylesheet %} |
|
4 | 4 | |
|
5 | 5 | {% if mathjax_url %} |
|
6 | 6 | <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script> |
|
7 | 7 | {% endif %} |
|
8 | 8 | <script type="text/javascript"> |
|
9 | 9 | // MathJax disabled, set as null to distingish from *missing* MathJax, |
|
10 | 10 | // where it will be undefined, and should prompt a dialog later. |
|
11 | 11 | window.mathjax_url = "{{mathjax_url}}"; |
|
12 | 12 | </script> |
|
13 | 13 | |
|
14 | 14 | <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}"> |
|
15 | 15 | <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}"> |
|
16 | 16 | |
|
17 | 17 | <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/> |
|
18 | 18 | |
|
19 | 19 | <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" /> |
|
20 | <link rel="stylesheet" href="{{ static_url("css/celltoolbar.css") }}" type="text/css" /> | |
|
20 | 21 | <link rel="stylesheet" href="{{ static_url("css/tooltip.css") }}" type="text/css" /> |
|
21 | 22 | <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" /> |
|
22 | 23 | |
|
23 | 24 | <link rel="stylesheet" href="{{ static_url("css/printnotebook.css") }}" type="text/css" media="print"/> |
|
24 | 25 | {% endblock %} |
|
25 | 26 | |
|
26 | 27 | {% block params %} |
|
27 | 28 | |
|
28 | 29 | data-project={{project}} |
|
29 | 30 | data-base-project-url={{base_project_url}} |
|
30 | 31 | data-base-kernel-url={{base_kernel_url}} |
|
31 | 32 | data-read-only={{read_only and not logged_in}} |
|
32 | 33 | data-notebook-id={{notebook_id}} |
|
33 | 34 | |
|
34 | 35 | {% endblock %} |
|
35 | 36 | |
|
36 | 37 | |
|
37 | 38 | {% block header %} |
|
38 | 39 | |
|
39 | 40 | <span id="save_widget"> |
|
40 | 41 | <span id="notebook_name"></span> |
|
41 | 42 | <span id="save_status"></span> |
|
42 | 43 | </span> |
|
43 | 44 | |
|
44 | 45 | {% endblock %} |
|
45 | 46 | |
|
46 | 47 | |
|
47 | 48 | {% block site %} |
|
48 | 49 | |
|
49 | 50 | <div id="menubar_container"> |
|
50 | 51 | <div id="menubar"> |
|
51 | 52 | <ul id="menus"> |
|
52 | 53 | <li><a href="#">File</a> |
|
53 | 54 | <ul> |
|
54 | 55 | <li id="new_notebook"><a href="#">New</a></li> |
|
55 | 56 | <li id="open_notebook"><a href="#">Open...</a></li> |
|
56 | 57 | <hr/> |
|
57 | 58 | <li id="copy_notebook"><a href="#">Make a Copy...</a></li> |
|
58 | 59 | <li id="rename_notebook"><a href="#">Rename...</a></li> |
|
59 | 60 | <li id="save_notebook"><a href="#">Save</a></li> |
|
60 | 61 | <hr/> |
|
61 | 62 | <li><a href="#">Download as</a> |
|
62 | 63 | <ul> |
|
63 | 64 | <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li> |
|
64 | 65 | <li id="download_py"><a href="#">Python (.py)</a></li> |
|
65 | 66 | </ul> |
|
66 | 67 | </li> |
|
67 | 68 | <hr/> |
|
68 | 69 | <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li> |
|
69 | 70 | <hr/> |
|
70 | 71 | <li id="kill_and_exit"><a href="#" >Close and halt</a></li> |
|
71 | 72 | </ul> |
|
72 | 73 | </li> |
|
73 | 74 | <li><a href="#">Edit</a> |
|
74 | 75 | <ul> |
|
75 | 76 | <li id="cut_cell"><a href="#">Cut Cell</a></li> |
|
76 | 77 | <li id="copy_cell"><a href="#">Copy Cell</a></li> |
|
77 | 78 | <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li> |
|
78 | 79 | <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li> |
|
79 | 80 | <li id="paste_cell_replace" class="ui-state-disabled"><a href="#">Paste Cell & Replace</a></li> |
|
80 | 81 | <li id="delete_cell"><a href="#">Delete</a></li> |
|
81 | 82 | <hr/> |
|
82 | 83 | <li id="split_cell"><a href="#">Split Cell</a></li> |
|
83 | 84 | <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li> |
|
84 | 85 | <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li> |
|
85 | 86 | <hr/> |
|
86 | 87 | <li id="move_cell_up"><a href="#">Move Cell Up</a></li> |
|
87 | 88 | <li id="move_cell_down"><a href="#">Move Cell Down</a></li> |
|
88 | 89 | <hr/> |
|
89 | 90 | <li id="select_previous"><a href="#">Select Previous Cell</a></li> |
|
90 | 91 | <li id="select_next"><a href="#">Select Next Cell</a></li> |
|
91 | 92 | </ul> |
|
92 | 93 | </li> |
|
93 | 94 | <li><a href="#">View</a> |
|
94 | 95 | <ul> |
|
95 | 96 | <li id="toggle_header"><a href="#">Toggle Header</a></li> |
|
96 | 97 | <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li> |
|
97 | 98 | </ul> |
|
98 | 99 | </li> |
|
99 | 100 | <li><a href="#">Insert</a> |
|
100 | 101 | <ul> |
|
101 | 102 | <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li> |
|
102 | 103 | <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li> |
|
103 | 104 | </ul> |
|
104 | 105 | </li> |
|
105 | 106 | <li><a href="#">Cell</a> |
|
106 | 107 | <ul> |
|
107 | 108 | <li id="run_cell"><a href="#">Run</a></li> |
|
108 | 109 | <li id="run_cell_in_place"><a href="#">Run in Place</a></li> |
|
109 | 110 | <li id="run_all_cells"><a href="#">Run All</a></li> |
|
110 | 111 | <li id="run_all_cells_above"><a href="#">Run All Above</a></li> |
|
111 | 112 | <li id="run_all_cells_below"><a href="#">Run All Below</a></li> |
|
112 | 113 | <hr/> |
|
113 | 114 | <li id="to_code"><a href="#">Code</a></li> |
|
114 | 115 | <li id="to_markdown"><a href="#">Markdown </a></li> |
|
115 | 116 | <li id="to_raw"><a href="#">Raw Text</a></li> |
|
116 | 117 | <li id="to_heading1"><a href="#">Heading 1</a></li> |
|
117 | 118 | <li id="to_heading2"><a href="#">Heading 2</a></li> |
|
118 | 119 | <li id="to_heading3"><a href="#">Heading 3</a></li> |
|
119 | 120 | <li id="to_heading4"><a href="#">Heading 4</a></li> |
|
120 | 121 | <li id="to_heading5"><a href="#">Heading 5</a></li> |
|
121 | 122 | <li id="to_heading6"><a href="#">Heading 6</a></li> |
|
122 | 123 | <hr/> |
|
123 | 124 | <li id="toggle_output"><a href="#">Toggle Current Output</a></li> |
|
124 | 125 | <li id="all_outputs"><a href="#">All Output</a> |
|
125 | 126 | <ul> |
|
126 | 127 | <li id="expand_all_output"><a href="#">Expand</a></li> |
|
127 | 128 | <li id="scroll_all_output"><a href="#">Scroll Long</a></li> |
|
128 | 129 | <li id="collapse_all_output"><a href="#">Collapse</a></li> |
|
129 | 130 | <li id="clear_all_output"><a href="#">Clear</a></li> |
|
130 | 131 | </ul> |
|
131 | 132 | </li> |
|
132 | 133 | </ul> |
|
133 | 134 | </li> |
|
134 | 135 | <li><a href="#">Kernel</a> |
|
135 | 136 | <ul> |
|
136 | 137 | <li id="int_kernel"><a href="#">Interrupt</a></li> |
|
137 | 138 | <li id="restart_kernel"><a href="#">Restart</a></li> |
|
138 | 139 | </ul> |
|
139 | 140 | </li> |
|
140 | 141 | <li><a href="#">Help</a> |
|
141 | 142 | <ul> |
|
142 | 143 | <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li> |
|
143 | 144 | <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li> |
|
144 | 145 | <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li> |
|
145 | 146 | <hr/> |
|
146 | 147 | <li><a href="http://docs.python.org" target="_blank">Python</a></li> |
|
147 | 148 | <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li> |
|
148 | 149 | <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li> |
|
149 | 150 | <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li> |
|
150 | 151 | <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li> |
|
151 | 152 | </ul> |
|
152 | 153 | </li> |
|
153 | 154 | </ul> |
|
154 | 155 | |
|
155 | 156 | </div> |
|
156 | 157 | <div id="notification_area"> |
|
157 | 158 | </div> |
|
158 | 159 | </div> |
|
159 | 160 | |
|
160 | 161 | |
|
161 | 162 | <div id="maintoolbar"></div> |
|
162 | 163 | |
|
163 | 164 | <div id="main_app"> |
|
164 | 165 | |
|
165 | 166 | <div id="notebook_panel"> |
|
166 | 167 | <div id="notebook"></div> |
|
167 | 168 | <div id="pager_splitter"></div> |
|
168 | 169 | <div id="pager_container"> |
|
169 | 170 | <div id='pager_button_area'> |
|
170 | 171 | </div> |
|
171 | 172 | <div id="pager"></div> |
|
172 | 173 | </div> |
|
173 | 174 | </div> |
|
174 | 175 | |
|
175 | 176 | </div> |
|
176 | 177 | <div id='tooltip' class='ipython_tooltip ui-corner-all' style='display:none'></div> |
|
177 | 178 | |
|
178 | 179 | |
|
179 | 180 | {% endblock %} |
|
180 | 181 | |
|
181 | 182 | |
|
182 | 183 | {% block script %} |
|
183 | 184 | |
|
184 | 185 | <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script> |
|
185 | 186 | <script src="{{ static_url("codemirror/lib/util/loadmode.js") }}" charset="utf-8"></script> |
|
186 | 187 | <script src="{{ static_url("codemirror/lib/util/multiplex.js") }}" charset="utf-8"></script> |
|
187 | 188 | <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script> |
|
188 | 189 | <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script> |
|
189 | 190 | <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script> |
|
190 | 191 | <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script> |
|
191 | 192 | <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script> |
|
192 | 193 | <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script> |
|
193 | 194 | <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script> |
|
194 | 195 | |
|
195 | 196 | <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script> |
|
196 | 197 | |
|
197 | 198 | <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script> |
|
198 | 199 | <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script> |
|
199 | 200 | |
|
200 | 201 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> |
|
201 | 202 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
202 | 203 | <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
203 | 204 | <script src="{{ static_url("js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
204 | 205 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
205 | 206 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
207 | <script src="{{ static_url("js/celltoolbar.js") }}" type="text/javascript" charset="utf-8"></script> | |
|
206 | 208 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
207 | 209 | <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script> |
|
208 | 210 | <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
209 | 211 | <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script> |
|
210 | 212 | <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script> |
|
211 | 213 | <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script> |
|
212 | 214 | <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
213 | 215 | <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
214 | 216 | <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
215 | 217 | <script src="{{ static_url("js/maintoolbar.js") }}" type="text/javascript" charset="utf-8"></script> |
|
216 | 218 | <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script> |
|
217 | 219 | <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script> |
|
218 | 220 | <script src="{{ static_url("js/notificationarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
219 | 221 | <script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script> |
|
220 | 222 | <script src="{{ static_url("js/config.js") }}" type="text/javascript" charset="utf-8"></script> |
|
221 | 223 | <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script> |
|
222 | 224 | |
|
223 | 225 | <script src="{{ static_url("js/contexthint.js") }}" charset="utf-8"></script> |
|
224 | {% endblock %} | |
|
225 | ||
|
226 | 226 | |
|
227 | <script src="{{ static_url("js/celltoolbarpresets/default.js") }}" type="text/javascript" charset="utf-8"></script> | |
|
227 | 228 | |
|
229 | {% endblock %} |
General Comments 0
You need to be logged in to leave comments.
Login now