##// END OF EJS Templates
disable CodeMirror drag/drop on Safari...
MinRK -
Show More
@@ -1,322 +1,330 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 * @param {object|undefined} [options]
30 * @param {object|undefined} [options]
31 * @param [options.cm_config] {object} config to pass to CodeMirror, will extend default parameters
31 * @param [options.cm_config] {object} config to pass to CodeMirror, will extend default parameters
32 */
32 */
33 var Cell = function (options) {
33 var Cell = function (options) {
34
34
35 options = this.mergeopt(Cell, options)
35 options = this.mergeopt(Cell, options)
36 // superclass default overwrite our default
36 // superclass default overwrite our default
37
37
38 this.placeholder = options.placeholder || '';
38 this.placeholder = options.placeholder || '';
39 this.read_only = options.cm_config.readOnly;
39 this.read_only = options.cm_config.readOnly;
40 this.selected = false;
40 this.selected = false;
41 this.element = null;
41 this.element = null;
42 this.metadata = {};
42 this.metadata = {};
43 // load this from metadata later ?
43 // load this from metadata later ?
44 this.user_highlight = 'auto';
44 this.user_highlight = 'auto';
45 this.cm_config = options.cm_config;
45 this.cm_config = options.cm_config;
46 this.create_element();
46 this.create_element();
47 if (this.element !== null) {
47 if (this.element !== null) {
48 this.element.data("cell", this);
48 this.element.data("cell", this);
49 this.bind_events();
49 this.bind_events();
50 }
50 }
51 this.cell_id = utils.uuid();
51 this.cell_id = utils.uuid();
52 this._options = options;
52 this._options = options;
53 };
53 };
54
54
55 Cell.options_default = {
55 Cell.options_default = {
56 cm_config : {
56 cm_config : {
57 indentUnit : 4,
57 indentUnit : 4,
58 readOnly: false,
58 readOnly: false,
59 theme: "default"
59 theme: "default"
60 }
60 }
61 };
61 };
62
63 // FIXME: Workaround CM Bug #332 (Safari segfault on drag)
64 // by disabling drag/drop altogether on Safari
65 // https://github.com/marijnh/CodeMirror/issues/332
66
67 if (utils.browser[0] == "Safari") {
68 Cell.options_default.cm_config.dragDrop = false;
69 }
62
70
63 Cell.prototype.mergeopt = function(_class, options, overwrite){
71 Cell.prototype.mergeopt = function(_class, options, overwrite){
64 overwrite = overwrite ||Β {};
72 overwrite = overwrite || {};
65 return $.extend(true, {}, _class.options_default, options, overwrite)
73 return $.extend(true, {}, _class.options_default, options, overwrite)
66
74
67 }
75 }
68
76
69
77
70
78
71 /**
79 /**
72 * Empty. Subclasses must implement create_element.
80 * Empty. Subclasses must implement create_element.
73 * This should contain all the code to create the DOM element in notebook
81 * This should contain all the code to create the DOM element in notebook
74 * and will be called by Base Class constructor.
82 * and will be called by Base Class constructor.
75 * @method create_element
83 * @method create_element
76 */
84 */
77 Cell.prototype.create_element = function () {
85 Cell.prototype.create_element = function () {
78 };
86 };
79
87
80
88
81 /**
89 /**
82 * Subclasses can implement override bind_events.
90 * Subclasses can implement override bind_events.
83 * Be carefull to call the parent method when overwriting as it fires event.
91 * Be carefull to call the parent method when overwriting as it fires event.
84 * this will be triggerd after create_element in constructor.
92 * this will be triggerd after create_element in constructor.
85 * @method bind_events
93 * @method bind_events
86 */
94 */
87 Cell.prototype.bind_events = function () {
95 Cell.prototype.bind_events = function () {
88 var that = this;
96 var that = this;
89 // We trigger events so that Cell doesn't have to depend on Notebook.
97 // We trigger events so that Cell doesn't have to depend on Notebook.
90 that.element.click(function (event) {
98 that.element.click(function (event) {
91 if (that.selected === false) {
99 if (that.selected === false) {
92 $([IPython.events]).trigger('select.Cell', {'cell':that});
100 $([IPython.events]).trigger('select.Cell', {'cell':that});
93 }
101 }
94 });
102 });
95 that.element.focusin(function (event) {
103 that.element.focusin(function (event) {
96 if (that.selected === false) {
104 if (that.selected === false) {
97 $([IPython.events]).trigger('select.Cell', {'cell':that});
105 $([IPython.events]).trigger('select.Cell', {'cell':that});
98 }
106 }
99 });
107 });
100 };
108 };
101
109
102 /**
110 /**
103 * Triger typsetting of math by mathjax on current cell element
111 * Triger typsetting of math by mathjax on current cell element
104 * @method typeset
112 * @method typeset
105 */
113 */
106 Cell.prototype.typeset = function () {
114 Cell.prototype.typeset = function () {
107 if (window.MathJax){
115 if (window.MathJax){
108 var cell_math = this.element.get(0);
116 var cell_math = this.element.get(0);
109 MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]);
117 MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]);
110 }
118 }
111 };
119 };
112
120
113 /**
121 /**
114 * should be triggerd when cell is selected
122 * should be triggerd when cell is selected
115 * @method select
123 * @method select
116 */
124 */
117 Cell.prototype.select = function () {
125 Cell.prototype.select = function () {
118 this.element.addClass('selected');
126 this.element.addClass('selected');
119 this.selected = true;
127 this.selected = true;
120 };
128 };
121
129
122
130
123 /**
131 /**
124 * should be triggerd when cell is unselected
132 * should be triggerd when cell is unselected
125 * @method unselect
133 * @method unselect
126 */
134 */
127 Cell.prototype.unselect = function () {
135 Cell.prototype.unselect = function () {
128 this.element.removeClass('selected');
136 this.element.removeClass('selected');
129 this.selected = false;
137 this.selected = false;
130 };
138 };
131
139
132 /**
140 /**
133 * should be overritten by subclass
141 * should be overritten by subclass
134 * @method get_text
142 * @method get_text
135 */
143 */
136 Cell.prototype.get_text = function () {
144 Cell.prototype.get_text = function () {
137 };
145 };
138
146
139 /**
147 /**
140 * should be overritten by subclass
148 * should be overritten by subclass
141 * @method set_text
149 * @method set_text
142 * @param {string} text
150 * @param {string} text
143 */
151 */
144 Cell.prototype.set_text = function (text) {
152 Cell.prototype.set_text = function (text) {
145 };
153 };
146
154
147 /**
155 /**
148 * Refresh codemirror instance
156 * Refresh codemirror instance
149 * @method refresh
157 * @method refresh
150 */
158 */
151 Cell.prototype.refresh = function () {
159 Cell.prototype.refresh = function () {
152 this.code_mirror.refresh();
160 this.code_mirror.refresh();
153 };
161 };
154
162
155
163
156 /**
164 /**
157 * should be overritten by subclass
165 * should be overritten by subclass
158 * @method edit
166 * @method edit
159 **/
167 **/
160 Cell.prototype.edit = function () {
168 Cell.prototype.edit = function () {
161 };
169 };
162
170
163
171
164 /**
172 /**
165 * should be overritten by subclass
173 * should be overritten by subclass
166 * @method render
174 * @method render
167 **/
175 **/
168 Cell.prototype.render = function () {
176 Cell.prototype.render = function () {
169 };
177 };
170
178
171 /**
179 /**
172 * should be overritten by subclass
180 * should be overritten by subclass
173 * serialise cell to json.
181 * serialise cell to json.
174 * @method toJSON
182 * @method toJSON
175 **/
183 **/
176 Cell.prototype.toJSON = function () {
184 Cell.prototype.toJSON = function () {
177 var data = {};
185 var data = {};
178 data.metadata = this.metadata;
186 data.metadata = this.metadata;
179 return data;
187 return data;
180 };
188 };
181
189
182
190
183 /**
191 /**
184 * should be overritten by subclass
192 * should be overritten by subclass
185 * @method fromJSON
193 * @method fromJSON
186 **/
194 **/
187 Cell.prototype.fromJSON = function (data) {
195 Cell.prototype.fromJSON = function (data) {
188 if (data.metadata !== undefined) {
196 if (data.metadata !== undefined) {
189 this.metadata = data.metadata;
197 this.metadata = data.metadata;
190 }
198 }
191 this.celltoolbar.rebuild();
199 this.celltoolbar.rebuild();
192 };
200 };
193
201
194
202
195 /**
203 /**
196 * can the cell be splitted in 2 cells.
204 * can the cell be splitted in 2 cells.
197 * @method is_splittable
205 * @method is_splittable
198 **/
206 **/
199 Cell.prototype.is_splittable = function () {
207 Cell.prototype.is_splittable = function () {
200 return true;
208 return true;
201 };
209 };
202
210
203
211
204 /**
212 /**
205 * @return {String} - the text before the cursor
213 * @return {String} - the text before the cursor
206 * @method get_pre_cursor
214 * @method get_pre_cursor
207 **/
215 **/
208 Cell.prototype.get_pre_cursor = function () {
216 Cell.prototype.get_pre_cursor = function () {
209 var cursor = this.code_mirror.getCursor();
217 var cursor = this.code_mirror.getCursor();
210 var text = this.code_mirror.getRange({line:0, ch:0}, cursor);
218 var text = this.code_mirror.getRange({line:0, ch:0}, cursor);
211 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
219 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
212 return text;
220 return text;
213 }
221 }
214
222
215
223
216 /**
224 /**
217 * @return {String} - the text after the cursor
225 * @return {String} - the text after the cursor
218 * @method get_post_cursor
226 * @method get_post_cursor
219 **/
227 **/
220 Cell.prototype.get_post_cursor = function () {
228 Cell.prototype.get_post_cursor = function () {
221 var cursor = this.code_mirror.getCursor();
229 var cursor = this.code_mirror.getCursor();
222 var last_line_num = this.code_mirror.lineCount()-1;
230 var last_line_num = this.code_mirror.lineCount()-1;
223 var last_line_len = this.code_mirror.getLine(last_line_num).length;
231 var last_line_len = this.code_mirror.getLine(last_line_num).length;
224 var end = {line:last_line_num, ch:last_line_len}
232 var end = {line:last_line_num, ch:last_line_len}
225 var text = this.code_mirror.getRange(cursor, end);
233 var text = this.code_mirror.getRange(cursor, end);
226 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
234 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
227 return text;
235 return text;
228 };
236 };
229
237
230 /**
238 /**
231 * Show/Hide CodeMirror LineNumber
239 * Show/Hide CodeMirror LineNumber
232 * @method show_line_numbers
240 * @method show_line_numbers
233 *
241 *
234 * @param value {Bool} show (true), or hide (false) the line number in CodeMirror
242 * @param value {Bool} show (true), or hide (false) the line number in CodeMirror
235 **/
243 **/
236 Cell.prototype.show_line_numbers = function (value) {
244 Cell.prototype.show_line_numbers = function (value) {
237 this.code_mirror.setOption('lineNumbers', value);
245 this.code_mirror.setOption('lineNumbers', value);
238 this.code_mirror.refresh();
246 this.code_mirror.refresh();
239 };
247 };
240
248
241 /**
249 /**
242 * Toggle CodeMirror LineNumber
250 * Toggle CodeMirror LineNumber
243 * @method toggle_line_numbers
251 * @method toggle_line_numbers
244 **/
252 **/
245 Cell.prototype.toggle_line_numbers = function () {
253 Cell.prototype.toggle_line_numbers = function () {
246 var val = this.code_mirror.getOption('lineNumbers');
254 var val = this.code_mirror.getOption('lineNumbers');
247 this.show_line_numbers(!val);
255 this.show_line_numbers(!val);
248 };
256 };
249
257
250 /**
258 /**
251 * Force codemirror highlight mode
259 * Force codemirror highlight mode
252 * @method force_highlight
260 * @method force_highlight
253 * @param {object} - CodeMirror mode
261 * @param {object} - CodeMirror mode
254 **/
262 **/
255 Cell.prototype.force_highlight = function(mode) {
263 Cell.prototype.force_highlight = function(mode) {
256 this.user_highlight = mode;
264 this.user_highlight = mode;
257 this.auto_highlight();
265 this.auto_highlight();
258 };
266 };
259
267
260 /**
268 /**
261 * Try to autodetect cell highlight mode, or use selected mode
269 * Try to autodetect cell highlight mode, or use selected mode
262 * @methods _auto_highlight
270 * @methods _auto_highlight
263 * @private
271 * @private
264 * @param {String|object|undefined} - CodeMirror mode | 'auto'
272 * @param {String|object|undefined} - CodeMirror mode | 'auto'
265 **/
273 **/
266 Cell.prototype._auto_highlight = function (modes) {
274 Cell.prototype._auto_highlight = function (modes) {
267 //Here we handle manually selected modes
275 //Here we handle manually selected modes
268 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
276 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
269 {
277 {
270 var mode = this.user_highlight;
278 var mode = this.user_highlight;
271 CodeMirror.autoLoadMode(this.code_mirror, mode);
279 CodeMirror.autoLoadMode(this.code_mirror, mode);
272 this.code_mirror.setOption('mode', mode);
280 this.code_mirror.setOption('mode', mode);
273 return;
281 return;
274 }
282 }
275 var first_line = this.code_mirror.getLine(0);
283 var first_line = this.code_mirror.getLine(0);
276 // loop on every pairs
284 // loop on every pairs
277 for( var mode in modes) {
285 for( var mode in modes) {
278 var regs = modes[mode]['reg'];
286 var regs = modes[mode]['reg'];
279 // only one key every time but regexp can't be keys...
287 // only one key every time but regexp can't be keys...
280 for(var reg in regs ) {
288 for(var reg in regs ) {
281 // here we handle non magic_modes
289 // here we handle non magic_modes
282 if(first_line.match(regs[reg]) != null) {
290 if(first_line.match(regs[reg]) != null) {
283 if (mode.search('magic_') != 0) {
291 if (mode.search('magic_') != 0) {
284 this.code_mirror.setOption('mode', mode);
292 this.code_mirror.setOption('mode', mode);
285 CodeMirror.autoLoadMode(this.code_mirror, mode);
293 CodeMirror.autoLoadMode(this.code_mirror, mode);
286 return;
294 return;
287 }
295 }
288 var open = modes[mode]['open']|| "%%";
296 var open = modes[mode]['open']|| "%%";
289 var close = modes[mode]['close']|| "%%end";
297 var close = modes[mode]['close']|| "%%end";
290 var mmode = mode;
298 var mmode = mode;
291 mode = mmode.substr(6);
299 mode = mmode.substr(6);
292 CodeMirror.autoLoadMode(this.code_mirror, mode);
300 CodeMirror.autoLoadMode(this.code_mirror, mode);
293 // create on the fly a mode that swhitch between
301 // create on the fly a mode that swhitch between
294 // plain/text and smth else otherwise `%%` is
302 // plain/text and smth else otherwise `%%` is
295 // source of some highlight issues.
303 // source of some highlight issues.
296 // we use patchedGetMode to circumvent a bug in CM
304 // we use patchedGetMode to circumvent a bug in CM
297 CodeMirror.defineMode(mmode , function(config) {
305 CodeMirror.defineMode(mmode , function(config) {
298 return CodeMirror.multiplexingMode(
306 return CodeMirror.multiplexingMode(
299 CodeMirror.patchedGetMode(config, 'text/plain'),
307 CodeMirror.patchedGetMode(config, 'text/plain'),
300 // always set someting on close
308 // always set someting on close
301 {open: open, close: close,
309 {open: open, close: close,
302 mode: CodeMirror.patchedGetMode(config, mode),
310 mode: CodeMirror.patchedGetMode(config, mode),
303 delimStyle: "delimit"
311 delimStyle: "delimit"
304 }
312 }
305 );
313 );
306 });
314 });
307 this.code_mirror.setOption('mode', mmode);
315 this.code_mirror.setOption('mode', mmode);
308 return;
316 return;
309 }
317 }
310 }
318 }
311 }
319 }
312 // fallback on default (python)
320 // fallback on default (python)
313 var default_mode = this.default_mode || 'text/plain';
321 var default_mode = this.default_mode || 'text/plain';
314 this.code_mirror.setOption('mode', default_mode);
322 this.code_mirror.setOption('mode', default_mode);
315 };
323 };
316
324
317 IPython.Cell = Cell;
325 IPython.Cell = Cell;
318
326
319 return IPython;
327 return IPython;
320
328
321 }(IPython));
329 }(IPython));
322
330
General Comments 0
You need to be logged in to leave comments. Login now