##// END OF EJS Templates
Adding new logic to cells.
Brian E. Granger -
Show More
@@ -39,7 +39,8 b' var IPython = (function (IPython) {'
39 this.placeholder = options.placeholder || '';
39 this.placeholder = options.placeholder || '';
40 this.read_only = options.cm_config.readOnly;
40 this.read_only = options.cm_config.readOnly;
41 this.selected = false;
41 this.selected = false;
42 this.focused = false;
42 this.rendered = false;
43 this.mode = 'command';
43 this.metadata = {};
44 this.metadata = {};
44 // load this from metadata later ?
45 // load this from metadata later ?
45 this.user_highlight = 'auto';
46 this.user_highlight = 'auto';
@@ -130,49 +131,126 b' var IPython = (function (IPython) {'
130 * @method typeset
131 * @method typeset
131 */
132 */
132 Cell.prototype.typeset = function () {
133 Cell.prototype.typeset = function () {
133 if (window.MathJax){
134 if (window.MathJax) {
134 var cell_math = this.element.get(0);
135 var cell_math = this.element.get(0);
135 MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]);
136 MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]);
136 }
137 };
137 };
138 };
138
139
139 /**
140 /**
140 * handle cell level logic when a cell is selected
141 * handle cell level logic when a cell is selected
141 * @method select
142 * @method select
143 * @return is the action being taken
142 */
144 */
143 Cell.prototype.select = function () {
145 Cell.prototype.select = function () {
144 this.element.addClass('selected');
146 if (!this.selected) {
145 this.selected = true;
147 this.element.addClass('selected');
148 this.element.removeClass('unselected');
149 this.selected = true;
150 return true;
151 } else {
152 return false;
153 };
146 };
154 };
147
155
148 /**
156 /**
149 * handle cell level logic when a cell is unselected
157 * handle cell level logic when a cell is unselected
150 * @method unselect
158 * @method unselect
159 * @return is the action being taken
151 */
160 */
152 Cell.prototype.unselect = function () {
161 Cell.prototype.unselect = function () {
153 this.element.removeClass('selected');
162 if (this.selected) {
154 this.selected = false;
163 this.element.addClass('unselected');
164 this.element.removeClass('selected');
165 this.selected = false;
166 return true;
167 } else {
168 return false;
169 };
155 };
170 };
156
171
157 /**
172 /**
158 * handle cell level logic when a cell is focused
173 * handle cell level logic when a cell is rendered
159 * @method focus
174 * @method render
175 * @return is the action being taken
160 */
176 */
161 Cell.prototype.focus = function () {
177 Cell.prototype.render = function () {
162 this.element.addClass('focused');
178 if (!this.rendered) {
163 this.focused = true;
179 this.element.addClass('rendered');
180 this.element.removeClass('unrendered');
181 this.rendered = true;
182 return true;
183 } else {
184 return false;
185 };
164 };
186 };
165
187
166 /**
188 /**
167 * handle cell level logic when a cell is unfocused
189 * handle cell level logic when a cell is unrendered
168 * @method unfocus
190 * @method unrender
191 * @return is the action being taken
169 */
192 */
170 Cell.prototype.unfocus = function () {
193 Cell.prototype.unrender = function () {
171 this.element.removeClass('focused');
194 if (this.rendered) {
172 this.focused = false;
195 this.element.addClass('unrendered');
196 this.element.removeClass('rendered');
197 this.rendered = false;
198 return true;
199 } else {
200 return false;
201 };
173 };
202 };
174
203
175 /**
204 /**
205 * enter the command mode for the cell
206 * @method command_mode
207 * @return is the action being taken
208 */
209 Cell.prototype.command_mode = function () {
210 if (this.mode !== 'command') {
211 this.element.addClass('command_mode');
212 this.element.removeClass('edit_mode');
213 this.mode = 'command';
214 return true;
215 } else {
216 return false;
217 };
218 };
219
220 /**
221 * enter the edit mode for the cell
222 * @method command_mode
223 * @return is the action being taken
224 */
225 Cell.prototype.edit_mode = function () {
226 if (this.mode !== 'edit') {
227 this.element.addClass('edit_mode');
228 this.element.removeClass('command_mode');
229 this.mode = 'edit';
230 return true;
231 } else {
232 return false;
233 };
234 }
235
236 /**
237 * Focus the cell in the DOM sense
238 * @method focus_cell
239 */
240 Cell.prototype.focus_cell = function () {
241 this.element.focus();
242 }
243
244 /**
245 * Focus the editor area so a user can type
246 * @method focus_editor
247 */
248 Cell.prototype.focus_editor = function () {
249 this.code_mirror.refresh();
250 this.code_mirror.focus();
251 }
252
253 /**
176 * should be overritten by subclass
254 * should be overritten by subclass
177 * @method get_text
255 * @method get_text
178 */
256 */
@@ -149,53 +149,60 b' var IPython = (function (IPython) {'
149 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
149 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
150
150
151 var that = this;
151 var that = this;
152 // whatever key is pressed, first, cancel the tooltip request before
153 // they are sent, and remove tooltip if any, except for tab again
154 if (event.type === 'keydown' && event.which != key.TAB ) {
155 IPython.tooltip.remove_and_cancel_tooltip();
156 }
157
152
158 var cur = editor.getCursor();
153 if (this.mode === 'command') {
159 if (event.keyCode === key.ENTER){
154 return false
160 this.auto_highlight();
155 } else if (this.mode === 'edit') {
161 }
156 // whatever key is pressed, first, cancel the tooltip request before
157 // they are sent, and remove tooltip if any, except for tab again
158 if (event.type === 'keydown' && event.which != key.TAB ) {
159 IPython.tooltip.remove_and_cancel_tooltip();
160 };
161
162 var cur = editor.getCursor();
163 if (event.keyCode === key.ENTER){
164 this.auto_highlight();
165 }
162
166
163 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
167 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
164 // Always ignore shift-enter in CodeMirror as we handle it.
168 // Always ignore shift-enter in CodeMirror as we handle it.
165 return true;
166 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
167 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
168 // browser and keyboard layout !
169 // Pressing '(' , request tooltip, don't forget to reappend it
170 // The second argument says to hide the tooltip if the docstring
171 // is actually empty
172 IPython.tooltip.pending(that, true);
173 } else if (event.which === key.UPARROW && event.type === 'keydown') {
174 // If we are not at the top, let CM handle the up arrow and
175 // prevent the global keydown handler from handling it.
176 if (!that.at_top()) {
177 event.stop();
178 return false;
179 } else {
180 return true;
169 return true;
181 }
170
182 } else if (event.which === key.ESC) {
171 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
183 return IPython.tooltip.remove_and_cancel_tooltip(true);
172 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
184 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
173 // browser and keyboard layout !
185 // If we are not at the bottom, let CM handle the down arrow and
174 // Pressing '(' , request tooltip, don't forget to reappend it
186 // prevent the global keydown handler from handling it.
175 // The second argument says to hide the tooltip if the docstring
187 if (!that.at_bottom()) {
176 // is actually empty
188 event.stop();
177 IPython.tooltip.pending(that, true);
189 return false;
178 } else if (event.which === key.UPARROW && event.type === 'keydown') {
190 } else {
179 // If we are not at the top, let CM handle the up arrow and
180 // prevent the global keydown handler from handling it.
181 if (!that.at_top()) {
182 event.stop();
183 return false;
184 } else {
185 return true;
186 };
187 } else if (event.which === key.ESC) {
188 IPython.tooltip.remove_and_cancel_tooltip(true);
191 return true;
189 return true;
192 }
190 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
193 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
191 // If we are not at the bottom, let CM handle the down arrow and
194 if (editor.somethingSelected()){
192 // prevent the global keydown handler from handling it.
195 var anchor = editor.getCursor("anchor");
193 if (!that.at_bottom()) {
196 var head = editor.getCursor("head");
194 event.stop();
197 if( anchor.line != head.line){
195 return false;
198 return false;
196 } else {
197 return true;
198 };
199 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
200 if (editor.somethingSelected()){
201 var anchor = editor.getCursor("anchor");
202 var head = editor.getCursor("head");
203 if( anchor.line != head.line){
204 return false;
205 }
199 }
206 }
200 }
207 }
201 IPython.tooltip.request(that);
208 IPython.tooltip.request(that);
@@ -213,13 +220,10 b' var IPython = (function (IPython) {'
213 // is empty. In this case, let CodeMirror handle indentation.
220 // is empty. In this case, let CodeMirror handle indentation.
214 return false;
221 return false;
215 } else {
222 } else {
216 event.stop();
223 // keypress/keyup also trigger on TAB press, and we don't want to
217 this.completer.startCompletion();
224 // use those to disable tab completion.
218 return true;
225 return false;
219 }
226 };
220 } else {
221 // keypress/keyup also trigger on TAB press, and we don't want to
222 // use those to disable tab completion.
223 return false;
227 return false;
224 }
228 }
225 return false;
229 return false;
@@ -304,21 +308,46 b' var IPython = (function (IPython) {'
304 // Basic cell manipulation.
308 // Basic cell manipulation.
305
309
306 CodeCell.prototype.select = function () {
310 CodeCell.prototype.select = function () {
307 IPython.Cell.prototype.select.apply(this);
311 var continue = IPython.Cell.prototype.select.apply(this);
308 this.code_mirror.refresh();
312 if (continue) {
309 this.auto_highlight();
313 this.code_mirror.refresh();
314 this.auto_highlight();
315 };
316 return continue;
310 };
317 };
311
318
312 CodeCell.prototype.focus = function () {
319 CodeCell.prototype.render = function () {
313 IPython.Cell.prototype.focus.apply(this);
320 var continue = IPython.Cell.prototype.render.apply(this);
314 this.code_mirror.focus();
321 if (continue) {
322 this.execute();
323 };
324 return continue;
315 };
325 };
316
326
317 CodeCell.prototype.unfocus = function () {
327 CodeCell.prototype.unrender = function () {
318 IPython.Cell.prototype.focus.apply(this);
328 var continue = IPython.Cell.prototype.unrender.apply(this);
319 this.code_mirror.blur();
329 if (continue) {
330 this.clear_output(true, true, true);
331 };
332 return continue;
320 };
333 };
321
334
335 CodeCell.prototype.command_mode = function () {
336 var continue = IPython.Cell.prototype.command_mode.apply(this);
337 if (continue) {
338 this.focus_cell();
339 };
340 return continue;
341 }
342
343 CodeCell.prototype.edit_mode = function () {
344 var continue = IPython.Cell.prototype.edit_mode.apply(this);
345 if (continue) {
346 this.focus_editor();
347 };
348 return continue;
349 }
350
322 CodeCell.prototype.select_all = function () {
351 CodeCell.prototype.select_all = function () {
323 var start = {line: 0, ch: 0};
352 var start = {line: 0, ch: 0};
324 var nlines = this.code_mirror.lineCount();
353 var nlines = this.code_mirror.lineCount();
@@ -946,7 +946,7 b' var IPython = (function (IPython) {'
946 text = '';
946 text = '';
947 };
947 };
948 // The edit must come before the set_text.
948 // The edit must come before the set_text.
949 target_cell.edit();
949 target_cell.unrender();
950 target_cell.set_text(text);
950 target_cell.set_text(text);
951 // make this value the starting point, so that we can only undo
951 // make this value the starting point, so that we can only undo
952 // to this state, instead of a blank cell
952 // to this state, instead of a blank cell
@@ -976,7 +976,7 b' var IPython = (function (IPython) {'
976 text = '';
976 text = '';
977 };
977 };
978 // The edit must come before the set_text.
978 // The edit must come before the set_text.
979 target_cell.edit();
979 target_cell.unrender();
980 target_cell.set_text(text);
980 target_cell.set_text(text);
981 // make this value the starting point, so that we can only undo
981 // make this value the starting point, so that we can only undo
982 // to this state, instead of a blank cell
982 // to this state, instead of a blank cell
@@ -1011,7 +1011,7 b' var IPython = (function (IPython) {'
1011 };
1011 };
1012 // The edit must come before the set_text.
1012 // The edit must come before the set_text.
1013 target_cell.set_level(level);
1013 target_cell.set_level(level);
1014 target_cell.edit();
1014 target_cell.unrender();
1015 target_cell.set_text(text);
1015 target_cell.set_text(text);
1016 // make this value the starting point, so that we can only undo
1016 // make this value the starting point, so that we can only undo
1017 // to this state, instead of a blank cell
1017 // to this state, instead of a blank cell
@@ -1179,7 +1179,7 b' var IPython = (function (IPython) {'
1179 cell.set_text(textb);
1179 cell.set_text(textb);
1180 cell.render();
1180 cell.render();
1181 var new_cell = this.insert_cell_above('markdown');
1181 var new_cell = this.insert_cell_above('markdown');
1182 new_cell.edit(); // editor must be visible to call set_text
1182 new_cell.unrender(); // editor must be visible to call set_text
1183 new_cell.set_text(texta);
1183 new_cell.set_text(texta);
1184 new_cell.render();
1184 new_cell.render();
1185 this.select_next();
1185 this.select_next();
@@ -1208,7 +1208,7 b' var IPython = (function (IPython) {'
1208 if (cell instanceof IPython.CodeCell) {
1208 if (cell instanceof IPython.CodeCell) {
1209 cell.set_text(upper_text+'\n'+text);
1209 cell.set_text(upper_text+'\n'+text);
1210 } else if (cell instanceof IPython.MarkdownCell) {
1210 } else if (cell instanceof IPython.MarkdownCell) {
1211 cell.edit();
1211 cell.unrender();
1212 cell.set_text(upper_text+'\n'+text);
1212 cell.set_text(upper_text+'\n'+text);
1213 cell.render();
1213 cell.render();
1214 };
1214 };
@@ -1238,7 +1238,7 b' var IPython = (function (IPython) {'
1238 if (cell instanceof IPython.CodeCell) {
1238 if (cell instanceof IPython.CodeCell) {
1239 cell.set_text(text+'\n'+lower_text);
1239 cell.set_text(text+'\n'+lower_text);
1240 } else if (cell instanceof IPython.MarkdownCell) {
1240 } else if (cell instanceof IPython.MarkdownCell) {
1241 cell.edit();
1241 cell.unrender();
1242 cell.set_text(text+'\n'+lower_text);
1242 cell.set_text(text+'\n'+lower_text);
1243 cell.render();
1243 cell.render();
1244 };
1244 };
@@ -104,13 +104,13 b' var IPython = (function (IPython) {'
104 this.element.keydown(function (event) {
104 this.element.keydown(function (event) {
105 if (event.which === 13 && !event.shiftKey) {
105 if (event.which === 13 && !event.shiftKey) {
106 if (that.rendered) {
106 if (that.rendered) {
107 that.edit();
107 that.unrender();
108 return false;
108 return false;
109 };
109 };
110 };
110 };
111 });
111 });
112 this.element.dblclick(function () {
112 this.element.dblclick(function () {
113 that.edit();
113 that.unrender();
114 });
114 });
115 };
115 };
116
116
@@ -134,57 +134,59 b' var IPython = (function (IPython) {'
134 return false;
134 return false;
135 };
135 };
136
136
137 /**
137 // Cell level actions
138 * Select the current cell and trigger 'focus'
138
139 * @method select
140 */
141 TextCell.prototype.select = function () {
139 TextCell.prototype.select = function () {
142 IPython.Cell.prototype.select.apply(this);
140 var continue = IPython.Cell.prototype.select.apply(this);
143 var output = this.element.find("div.text_cell_render");
141 if (continue) {
144 output.trigger('focus');
142 if (this.mode === 'edit') {
143 this.code_mirror.refresh();
144 }
145 };
146 return continue;
145 };
147 };
146
148
147 /**
149 TextCell.prototype.render = function () {
148 * unselect the current cell and `render` it
150 var continue = IPython.Cell.prototype.render.apply(this);
149 * @method unselect
151 if (continue) {
150 */
152 this.execute();
151 TextCell.prototype.unselect = function() {
153 };
152 // render on selection of another cell
154 return continue;
153 this.render();
154 IPython.Cell.prototype.unselect.apply(this);
155 };
155 };
156
156
157 /**
157 TextCell.prototype.unrender = function () {
158 *
158 if (this.read_only) return;
159 * put the current cell in edition mode
159 var continue = IPython.Cell.prototype.unrender.apply(this);
160 * @method edit
160 if (continue) {
161 */
162 TextCell.prototype.edit = function () {
163 if (this.rendered === true) {
164 var text_cell = this.element;
161 var text_cell = this.element;
165 var output = text_cell.find("div.text_cell_render");
162 var output = text_cell.find("div.text_cell_render");
166 output.hide();
163 output.hide();
167 text_cell.find('div.text_cell_input').show();
164 text_cell.find('div.text_cell_input').show();
168 this.code_mirror.refresh();
165 this.focus_editor();
169 this.code_mirror.focus();
170 // We used to need an additional refresh() after the focus, but
171 // it appears that this has been fixed in CM. This bug would show
172 // up on FF when a newly loaded markdown cell was edited.
173 this.rendered = false;
174 if (this.get_text() === this.placeholder) {
166 if (this.get_text() === this.placeholder) {
175 this.set_text('');
167 this.set_text('');
176 this.refresh();
168 this.refresh();
177 }
169 }
178 }
179 };
180
170
171 };
172 return continue;
173 };
181
174
182 /**
175 TextCell.prototype.command_mode = function () {
183 * Empty, Subclasses must define render.
176 var continue = IPython.Cell.prototype.command_mode.apply(this);
184 * @method render
177 if (continue) {
185 */
178 this.focus_cell();
186 TextCell.prototype.render = function () {};
179 };
180 return continue;
181 }
187
182
183 TextCell.prototype.edit_mode = function () {
184 var continue = IPython.Cell.prototype.edit_mode.apply(this);
185 if (continue) {
186 this.focus_editor();
187 };
188 return continue;
189 }
188
190
189 /**
191 /**
190 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
192 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
@@ -382,11 +384,12 b' var IPython = (function (IPython) {'
382
384
383 /** @method render **/
385 /** @method render **/
384 RawCell.prototype.render = function () {
386 RawCell.prototype.render = function () {
387
385 this.rendered = true;
388 this.rendered = true;
386 var text = this.get_text();
389 var text = this.get_text();
387 if (text === "") { text = this.placeholder; }
390 if (text === "") { text = this.placeholder; }
388 console.log('rendering', text);
389 this.set_text(text);
391 this.set_text(text);
392 this.unrender();
390 };
393 };
391
394
392
395
General Comments 0
You need to be logged in to leave comments. Login now