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