##// END OF EJS Templates
Removing old autogrow JS code.
Brian E. Granger -
Show More
@@ -1,345 +1,322 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Cell
10 10 //============================================================================
11 11 /**
12 12 * An extendable module that provide base functionnality to create cell for notebook.
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule Cell
16 16 */
17 17
18 18 var IPython = (function (IPython) {
19 19
20 20 var utils = IPython.utils;
21 21
22 22 /**
23 23 * The Base `Cell` class from which to inherit
24 24 * @class Cell
25 25 **/
26 26
27 27 /*
28 28 * @constructor
29 29 *
30 30 * @param {object|undefined} [options]
31 31 * @param [options.cm_config] {object} config to pass to CodeMirror, will extend default parameters
32 32 */
33 33 var Cell = function (options) {
34 34
35 35 options = this.mergeopt(Cell, options)
36 36 // superclass default overwrite our default
37 37
38 38 this.placeholder = options.placeholder || '';
39 39 this.read_only = options.cm_config.readOnly;
40 40 this.selected = false;
41 41 this.element = null;
42 42 this.metadata = {};
43 43 // load this from metadata later ?
44 44 this.user_highlight = 'auto';
45 45 this.cm_config = options.cm_config;
46 46 this.create_element();
47 47 if (this.element !== null) {
48 48 this.element.data("cell", this);
49 49 this.bind_events();
50 50 }
51 51 this.cell_id = utils.uuid();
52 52 this._options = options;
53 53 };
54 54
55 55 Cell.options_default = {
56 56 cm_config : {
57 57 indentUnit : 4,
58 58 readOnly: false,
59 59 theme: "default"
60 60 }
61 61 };
62 62
63 63 Cell.prototype.mergeopt = function(_class, options, overwrite){
64 64 overwrite = overwrite ||Β {};
65 65 return $.extend(true, {}, _class.options_default, options, overwrite)
66 66
67 67 }
68 68
69 69
70 70
71 71 /**
72 72 * Empty. Subclasses must implement create_element.
73 73 * This should contain all the code to create the DOM element in notebook
74 74 * and will be called by Base Class constructor.
75 75 * @method create_element
76 76 */
77 77 Cell.prototype.create_element = function () {
78 78 };
79 79
80 80
81 81 /**
82 82 * Subclasses can implement override bind_events.
83 83 * Be carefull to call the parent method when overwriting as it fires event.
84 84 * this will be triggerd after create_element in constructor.
85 85 * @method bind_events
86 86 */
87 87 Cell.prototype.bind_events = function () {
88 88 var that = this;
89 89 // We trigger events so that Cell doesn't have to depend on Notebook.
90 90 that.element.click(function (event) {
91 91 if (that.selected === false) {
92 92 $([IPython.events]).trigger('select.Cell', {'cell':that});
93 93 }
94 94 });
95 95 that.element.focusin(function (event) {
96 96 if (that.selected === false) {
97 97 $([IPython.events]).trigger('select.Cell', {'cell':that});
98 98 }
99 99 });
100 100 };
101 101
102 102 /**
103 103 * Triger typsetting of math by mathjax on current cell element
104 104 * @method typeset
105 105 */
106 106 Cell.prototype.typeset = function () {
107 107 if (window.MathJax){
108 108 var cell_math = this.element.get(0);
109 109 MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]);
110 110 }
111 111 };
112 112
113 113 /**
114 114 * should be triggerd when cell is selected
115 115 * @method select
116 116 */
117 117 Cell.prototype.select = function () {
118 118 this.element.addClass('selected');
119 119 this.selected = true;
120 120 };
121 121
122 122
123 123 /**
124 124 * should be triggerd when cell is unselected
125 125 * @method unselect
126 126 */
127 127 Cell.prototype.unselect = function () {
128 128 this.element.removeClass('selected');
129 129 this.selected = false;
130 130 };
131 131
132 132 /**
133 133 * should be overritten by subclass
134 134 * @method get_text
135 135 */
136 136 Cell.prototype.get_text = function () {
137 137 };
138 138
139 139 /**
140 140 * should be overritten by subclass
141 141 * @method set_text
142 142 * @param {string} text
143 143 */
144 144 Cell.prototype.set_text = function (text) {
145 145 };
146 146
147 147 /**
148 148 * Refresh codemirror instance
149 149 * @method refresh
150 150 */
151 151 Cell.prototype.refresh = function () {
152 152 this.code_mirror.refresh();
153 153 };
154 154
155 155
156 156 /**
157 157 * should be overritten by subclass
158 158 * @method edit
159 159 **/
160 160 Cell.prototype.edit = function () {
161 161 };
162 162
163 163
164 164 /**
165 165 * should be overritten by subclass
166 166 * @method render
167 167 **/
168 168 Cell.prototype.render = function () {
169 169 };
170 170
171 171 /**
172 172 * should be overritten by subclass
173 173 * serialise cell to json.
174 174 * @method toJSON
175 175 **/
176 176 Cell.prototype.toJSON = function () {
177 177 var data = {};
178 178 data.metadata = this.metadata;
179 179 return data;
180 180 };
181 181
182 182
183 183 /**
184 184 * should be overritten by subclass
185 185 * @method fromJSON
186 186 **/
187 187 Cell.prototype.fromJSON = function (data) {
188 188 if (data.metadata !== undefined) {
189 189 this.metadata = data.metadata;
190 190 }
191 191 this.celltoolbar.rebuild();
192 192 };
193 193
194 194
195 195 /**
196 196 * can the cell be splitted in 2 cells.
197 197 * @method is_splittable
198 198 **/
199 199 Cell.prototype.is_splittable = function () {
200 200 return true;
201 201 };
202 202
203 203
204 204 /**
205 205 * @return {String} - the text before the cursor
206 206 * @method get_pre_cursor
207 207 **/
208 208 Cell.prototype.get_pre_cursor = function () {
209 209 var cursor = this.code_mirror.getCursor();
210 210 var text = this.code_mirror.getRange({line:0, ch:0}, cursor);
211 211 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
212 212 return text;
213 213 }
214 214
215 215
216 216 /**
217 217 * @return {String} - the text after the cursor
218 218 * @method get_post_cursor
219 219 **/
220 220 Cell.prototype.get_post_cursor = function () {
221 221 var cursor = this.code_mirror.getCursor();
222 222 var last_line_num = this.code_mirror.lineCount()-1;
223 223 var last_line_len = this.code_mirror.getLine(last_line_num).length;
224 224 var end = {line:last_line_num, ch:last_line_len}
225 225 var text = this.code_mirror.getRange(cursor, end);
226 226 text = text.replace(/^\n+/, '').replace(/\n+$/, '');
227 227 return text;
228 228 };
229 229
230
231 /** Grow the cell by hand. This is used upon reloading from JSON, when the
232 * autogrow handler is not called.
233 *
234 * could be made static
235 *
236 * @param {Dom element} - element
237 * @method grow
238 **/
239 Cell.prototype.grow = function(element) {
240 var dom = element.get(0);
241 var lines_count = 0;
242 // modified split rule from
243 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
244 var lines = dom.value.split(/\r|\r\n|\n/);
245 lines_count = lines.length;
246 if (lines_count >= 1) {
247 dom.rows = lines_count;
248 } else {
249 dom.rows = 1;
250 }
251 };
252
253 230 /**
254 231 * Show/Hide CodeMirror LineNumber
255 232 * @method show_line_numbers
256 233 *
257 234 * @param value {Bool} show (true), or hide (false) the line number in CodeMirror
258 235 **/
259 236 Cell.prototype.show_line_numbers = function (value) {
260 237 this.code_mirror.setOption('lineNumbers', value);
261 238 this.code_mirror.refresh();
262 239 };
263 240
264 241 /**
265 242 * Toggle CodeMirror LineNumber
266 243 * @method toggle_line_numbers
267 244 **/
268 245 Cell.prototype.toggle_line_numbers = function () {
269 246 var val = this.code_mirror.getOption('lineNumbers');
270 247 this.show_line_numbers(!val);
271 248 };
272 249
273 250 /**
274 251 * Force codemirror highlight mode
275 252 * @method force_highlight
276 253 * @param {object} - CodeMirror mode
277 254 **/
278 255 Cell.prototype.force_highlight = function(mode) {
279 256 this.user_highlight = mode;
280 257 this.auto_highlight();
281 258 };
282 259
283 260 /**
284 261 * Try to autodetect cell highlight mode, or use selected mode
285 262 * @methods _auto_highlight
286 263 * @private
287 264 * @param {String|object|undefined} - CodeMirror mode | 'auto'
288 265 **/
289 266 Cell.prototype._auto_highlight = function (modes) {
290 267 //Here we handle manually selected modes
291 268 if( this.user_highlight != undefined && this.user_highlight != 'auto' )
292 269 {
293 270 var mode = this.user_highlight;
294 271 CodeMirror.autoLoadMode(this.code_mirror, mode);
295 272 this.code_mirror.setOption('mode', mode);
296 273 return;
297 274 }
298 275 var first_line = this.code_mirror.getLine(0);
299 276 // loop on every pairs
300 277 for( var mode in modes) {
301 278 var regs = modes[mode]['reg'];
302 279 // only one key every time but regexp can't be keys...
303 280 for(var reg in regs ) {
304 281 // here we handle non magic_modes
305 282 if(first_line.match(regs[reg]) != null) {
306 283 if (mode.search('magic_') != 0) {
307 284 this.code_mirror.setOption('mode', mode);
308 285 CodeMirror.autoLoadMode(this.code_mirror, mode);
309 286 return;
310 287 }
311 288 var open = modes[mode]['open']|| "%%";
312 289 var close = modes[mode]['close']|| "%%end";
313 290 var mmode = mode;
314 291 mode = mmode.substr(6);
315 292 CodeMirror.autoLoadMode(this.code_mirror, mode);
316 293 // create on the fly a mode that swhitch between
317 294 // plain/text and smth else otherwise `%%` is
318 295 // source of some highlight issues.
319 296 // we use patchedGetMode to circumvent a bug in CM
320 297 CodeMirror.defineMode(mmode , function(config) {
321 298 return CodeMirror.multiplexingMode(
322 299 CodeMirror.patchedGetMode(config, 'text/plain'),
323 300 // always set someting on close
324 301 {open: open, close: close,
325 302 mode: CodeMirror.patchedGetMode(config, mode),
326 303 delimStyle: "delimit"
327 304 }
328 305 );
329 306 });
330 307 this.code_mirror.setOption('mode', mmode);
331 308 return;
332 309 }
333 310 }
334 311 }
335 312 // fallback on default (python)
336 313 var default_mode = this.default_mode || 'text/plain';
337 314 this.code_mirror.setOption('mode', default_mode);
338 315 };
339 316
340 317 IPython.Cell = Cell;
341 318
342 319 return IPython;
343 320
344 321 }(IPython));
345 322
@@ -1,308 +1,291 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2012 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Utilities
10 10 //============================================================================
11 11
12 12 IPython.namespace('IPython.utils');
13 13
14 14 IPython.utils = (function (IPython) {
15 15
16 16 //============================================================================
17 17 // Cross-browser RegEx Split
18 18 //============================================================================
19 19
20 20 // This code has been MODIFIED from the code licensed below to not replace the
21 21 // default browser split. The license is reproduced here.
22 22
23 23 // see http://blog.stevenlevithan.com/archives/cross-browser-split for more info:
24 24 /*!
25 25 * Cross-Browser Split 1.1.1
26 26 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
27 27 * Available under the MIT License
28 28 * ECMAScript compliant, uniform cross-browser split method
29 29 */
30 30
31 31 /**
32 32 * Splits a string into an array of strings using a regex or string
33 33 * separator. Matches of the separator are not included in the result array.
34 34 * However, if `separator` is a regex that contains capturing groups,
35 35 * backreferences are spliced into the result each time `separator` is
36 36 * matched. Fixes browser bugs compared to the native
37 37 * `String.prototype.split` and can be used reliably cross-browser.
38 38 * @param {String} str String to split.
39 39 * @param {RegExp|String} separator Regex or string to use for separating
40 40 * the string.
41 41 * @param {Number} [limit] Maximum number of items to include in the result
42 42 * array.
43 43 * @returns {Array} Array of substrings.
44 44 * @example
45 45 *
46 46 * // Basic use
47 47 * regex_split('a b c d', ' ');
48 48 * // -> ['a', 'b', 'c', 'd']
49 49 *
50 50 * // With limit
51 51 * regex_split('a b c d', ' ', 2);
52 52 * // -> ['a', 'b']
53 53 *
54 54 * // Backreferences in result array
55 55 * regex_split('..word1 word2..', /([a-z]+)(\d+)/i);
56 56 * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
57 57 */
58 58 var regex_split = function (str, separator, limit) {
59 59 // If `separator` is not a regex, use `split`
60 60 if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
61 61 return split.call(str, separator, limit);
62 62 }
63 63 var output = [],
64 64 flags = (separator.ignoreCase ? "i" : "") +
65 65 (separator.multiline ? "m" : "") +
66 66 (separator.extended ? "x" : "") + // Proposed for ES6
67 67 (separator.sticky ? "y" : ""), // Firefox 3+
68 68 lastLastIndex = 0,
69 69 // Make `global` and avoid `lastIndex` issues by working with a copy
70 70 separator = new RegExp(separator.source, flags + "g"),
71 71 separator2, match, lastIndex, lastLength;
72 72 str += ""; // Type-convert
73 73
74 74 var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined"
75 75 if (!compliantExecNpcg) {
76 76 // Doesn't need flags gy, but they don't hurt
77 77 separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
78 78 }
79 79 /* Values for `limit`, per the spec:
80 80 * If undefined: 4294967295 // Math.pow(2, 32) - 1
81 81 * If 0, Infinity, or NaN: 0
82 82 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
83 83 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
84 84 * If other: Type-convert, then use the above rules
85 85 */
86 86 limit = typeof(limit) === "undefined" ?
87 87 -1 >>> 0 : // Math.pow(2, 32) - 1
88 88 limit >>> 0; // ToUint32(limit)
89 89 while (match = separator.exec(str)) {
90 90 // `separator.lastIndex` is not reliable cross-browser
91 91 lastIndex = match.index + match[0].length;
92 92 if (lastIndex > lastLastIndex) {
93 93 output.push(str.slice(lastLastIndex, match.index));
94 94 // Fix browsers whose `exec` methods don't consistently return `undefined` for
95 95 // nonparticipating capturing groups
96 96 if (!compliantExecNpcg && match.length > 1) {
97 97 match[0].replace(separator2, function () {
98 98 for (var i = 1; i < arguments.length - 2; i++) {
99 99 if (typeof(arguments[i]) === "undefined") {
100 100 match[i] = undefined;
101 101 }
102 102 }
103 103 });
104 104 }
105 105 if (match.length > 1 && match.index < str.length) {
106 106 Array.prototype.push.apply(output, match.slice(1));
107 107 }
108 108 lastLength = match[0].length;
109 109 lastLastIndex = lastIndex;
110 110 if (output.length >= limit) {
111 111 break;
112 112 }
113 113 }
114 114 if (separator.lastIndex === match.index) {
115 115 separator.lastIndex++; // Avoid an infinite loop
116 116 }
117 117 }
118 118 if (lastLastIndex === str.length) {
119 119 if (lastLength || !separator.test("")) {
120 120 output.push("");
121 121 }
122 122 } else {
123 123 output.push(str.slice(lastLastIndex));
124 124 }
125 125 return output.length > limit ? output.slice(0, limit) : output;
126 126 };
127 127
128 128 //============================================================================
129 129 // End contributed Cross-browser RegEx Split
130 130 //============================================================================
131 131
132 132
133 133 var uuid = function () {
134 134 // http://www.ietf.org/rfc/rfc4122.txt
135 135 var s = [];
136 136 var hexDigits = "0123456789ABCDEF";
137 137 for (var i = 0; i < 32; i++) {
138 138 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
139 139 }
140 140 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
141 141 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
142 142
143 143 var uuid = s.join("");
144 144 return uuid;
145 145 };
146 146
147 147
148 148 //Fix raw text to parse correctly in crazy XML
149 149 function xmlencode(string) {
150 150 return string.replace(/\&/g,'&'+'amp;')
151 151 .replace(/</g,'&'+'lt;')
152 152 .replace(/>/g,'&'+'gt;')
153 153 .replace(/\'/g,'&'+'apos;')
154 154 .replace(/\"/g,'&'+'quot;')
155 155 .replace(/`/g,'&'+'#96;');
156 156 }
157 157
158 158
159 159 //Map from terminal commands to CSS classes
160 160 var ansi_colormap = {
161 161 "01":"ansibold",
162 162 "30":"ansiblack",
163 163 "31":"ansired",
164 164 "32":"ansigreen",
165 165 "33":"ansiyellow",
166 166 "34":"ansiblue",
167 167 "35":"ansipurple",
168 168 "36":"ansicyan",
169 169 "37":"ansigrey"
170 170 };
171 171
172 172 function ansispan(str) {
173 173 // ansispan function adapted from github.com/mmalecki/ansispan (MIT License)
174 174 Object.keys(ansi_colormap).forEach(function(ansi) {
175 175 var span = '<span class="' + ansi_colormap[ansi] + '">';
176 176
177 177 //
178 178 // `\033[Xm` == `\033[0;Xm` sets foreground color to `X`.
179 179 //
180 180 str = str.replace(
181 181 new RegExp('\033\\[([01];)?' + ansi + 'm', 'g'), span
182 182 );
183 183 });
184 184
185 185 str = str.replace(/\033\[([01]|39|22)?m/g, '</span>');
186 186 return str;
187 187 };
188 188
189 189 // Transform ANSI color escape codes into HTML <span> tags with css
190 190 // classes listed in the above ansi_colormap object. The actual color used
191 191 // are set in the css file.
192 192 function fixConsole(txt) {
193 193 txt = xmlencode(txt);
194 194 var re = /\033\[([\dA-Fa-f;]*?)m/;
195 195 var opened = false;
196 196 var cmds = [];
197 197 var opener = "";
198 198 var closer = "";
199 199
200 200 // Strip all ANSI codes that are not color related. Matches
201 201 // all ANSI codes that do not end with "m".
202 202 var ignored_re = /(?=(\033\[[\d;=]*[a-ln-zA-Z]{1}))\1(?!m)/g;
203 203 txt = txt.replace(ignored_re, "");
204 204
205 205 // color ansi codes
206 206 txt = ansispan(txt);
207 207 return txt;
208 208 }
209 209
210 210 // Remove chunks that should be overridden by the effect of
211 211 // carriage return characters
212 212 function fixCarriageReturn(txt) {
213 213 var tmp = txt;
214 214 do {
215 215 txt = tmp;
216 216 tmp = txt.replace(/\r+\n/gm, '\n'); // \r followed by \n --> newline
217 217 tmp = tmp.replace(/^.*\r+/gm, ''); // Other \r --> clear line
218 218 } while (tmp.length < txt.length);
219 219 return txt;
220 220 }
221 221
222 222 // Locate any URLs and convert them to a anchor tag
223 223 function autoLinkUrls(txt) {
224 224 return txt.replace(/(^|\s)(https?|ftp)(:[^'">\s]+)/gi,
225 225 "$1<a target=\"_blank\" href=\"$2$3\">$2$3</a>");
226 226 }
227 227
228 grow = function(element) {
229 // Grow the cell by hand. This is used upon reloading from JSON, when the
230 // autogrow handler is not called.
231 var dom = element.get(0);
232 var lines_count = 0;
233 // modified split rule from
234 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
235 var lines = dom.value.split(/\r|\r\n|\n/);
236 lines_count = lines.length;
237 if (lines_count >= 1) {
238 dom.rows = lines_count;
239 } else {
240 dom.rows = 1;
241 }
242 };
243
244 228 // some keycodes that seem to be platform/browser independant
245 229 var keycodes ={
246 230 BACKSPACE: 8,
247 231 TAB : 9,
248 232 ENTER : 13,
249 233 SHIFT : 16,
250 234 CTRL : 17,
251 235 CONTROL : 17,
252 236 ALT : 18,
253 237 CAPS_LOCK: 20,
254 238 ESC : 27,
255 239 SPACE : 32,
256 240 PGUP : 33,
257 241 PGDOWN : 34,
258 242 END : 35,
259 243 HOME : 36,
260 244 LEFT_ARROW: 37,
261 245 LEFTARROW: 37,
262 246 LEFT : 37,
263 247 UP_ARROW : 38,
264 248 UPARROW : 38,
265 249 UP : 38,
266 250 RIGHT_ARROW:39,
267 251 RIGHTARROW:39,
268 252 RIGHT : 39,
269 253 DOWN_ARROW: 40,
270 254 DOWNARROW: 40,
271 255 DOWN : 40,
272 256 COMMAND : 91,
273 257 };
274 258
275 259
276 260 var points_to_pixels = function (points) {
277 261 // A reasonably good way of converting between points and pixels.
278 262 var test = $('<div style="display: none; width: 10000pt; padding:0; border:0;"></div>');
279 263 $(body).append(test);
280 264 var pixel_per_point = test.width()/10000;
281 265 test.remove();
282 266 return Math.floor(points*pixel_per_point);
283 267 };
284 268
285 269 // http://stackoverflow.com/questions/2400935/browser-detection-in-javascript
286 270 browser = (function() {
287 271 var N= navigator.appName, ua= navigator.userAgent, tem;
288 272 var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
289 273 if (M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
290 274 M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
291 275 return M;
292 276 })();
293 277
294 278
295 279 return {
296 280 regex_split : regex_split,
297 281 uuid : uuid,
298 282 fixConsole : fixConsole,
299 283 keycodes : keycodes,
300 grow : grow,
301 284 fixCarriageReturn : fixCarriageReturn,
302 285 autoLinkUrls : autoLinkUrls,
303 286 points_to_pixels : points_to_pixels,
304 287 browser : browser
305 288 };
306 289
307 290 }(IPython));
308 291
General Comments 0
You need to be logged in to leave comments. Login now