From a11c3dfdeead62a44824f9003179c7ba74f8346a 2014-01-07 22:42:34 From: Brian E. Granger Date: 2014-01-07 22:42:34 Subject: [PATCH] Adding new logic to cells. --- diff --git a/IPython/html/static/notebook/js/cell.js b/IPython/html/static/notebook/js/cell.js index 2a65e4f..7d8506a 100644 --- a/IPython/html/static/notebook/js/cell.js +++ b/IPython/html/static/notebook/js/cell.js @@ -39,7 +39,8 @@ var IPython = (function (IPython) { this.placeholder = options.placeholder || ''; this.read_only = options.cm_config.readOnly; this.selected = false; - this.focused = false; + this.rendered = false; + this.mode = 'command'; this.metadata = {}; // load this from metadata later ? this.user_highlight = 'auto'; @@ -130,49 +131,126 @@ var IPython = (function (IPython) { * @method typeset */ Cell.prototype.typeset = function () { - if (window.MathJax){ + if (window.MathJax) { var cell_math = this.element.get(0); MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]); - } + }; }; /** * handle cell level logic when a cell is selected * @method select + * @return is the action being taken */ Cell.prototype.select = function () { - this.element.addClass('selected'); - this.selected = true; + if (!this.selected) { + this.element.addClass('selected'); + this.element.removeClass('unselected'); + this.selected = true; + return true; + } else { + return false; + }; }; /** * handle cell level logic when a cell is unselected * @method unselect + * @return is the action being taken */ Cell.prototype.unselect = function () { - this.element.removeClass('selected'); - this.selected = false; + if (this.selected) { + this.element.addClass('unselected'); + this.element.removeClass('selected'); + this.selected = false; + return true; + } else { + return false; + }; }; /** - * handle cell level logic when a cell is focused - * @method focus + * handle cell level logic when a cell is rendered + * @method render + * @return is the action being taken */ - Cell.prototype.focus = function () { - this.element.addClass('focused'); - this.focused = true; + Cell.prototype.render = function () { + if (!this.rendered) { + this.element.addClass('rendered'); + this.element.removeClass('unrendered'); + this.rendered = true; + return true; + } else { + return false; + }; }; /** - * handle cell level logic when a cell is unfocused - * @method unfocus + * handle cell level logic when a cell is unrendered + * @method unrender + * @return is the action being taken */ - Cell.prototype.unfocus = function () { - this.element.removeClass('focused'); - this.focused = false; + Cell.prototype.unrender = function () { + if (this.rendered) { + this.element.addClass('unrendered'); + this.element.removeClass('rendered'); + this.rendered = false; + return true; + } else { + return false; + }; }; /** + * enter the command mode for the cell + * @method command_mode + * @return is the action being taken + */ + Cell.prototype.command_mode = function () { + if (this.mode !== 'command') { + this.element.addClass('command_mode'); + this.element.removeClass('edit_mode'); + this.mode = 'command'; + return true; + } else { + return false; + }; + }; + + /** + * enter the edit mode for the cell + * @method command_mode + * @return is the action being taken + */ + Cell.prototype.edit_mode = function () { + if (this.mode !== 'edit') { + this.element.addClass('edit_mode'); + this.element.removeClass('command_mode'); + this.mode = 'edit'; + return true; + } else { + return false; + }; + } + + /** + * Focus the cell in the DOM sense + * @method focus_cell + */ + Cell.prototype.focus_cell = function () { + this.element.focus(); + } + + /** + * Focus the editor area so a user can type + * @method focus_editor + */ + Cell.prototype.focus_editor = function () { + this.code_mirror.refresh(); + this.code_mirror.focus(); + } + + /** * should be overritten by subclass * @method get_text */ diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js index bd5c711..9069279 100644 --- a/IPython/html/static/notebook/js/codecell.js +++ b/IPython/html/static/notebook/js/codecell.js @@ -149,53 +149,60 @@ var IPython = (function (IPython) { CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { var that = this; - // whatever key is pressed, first, cancel the tooltip request before - // they are sent, and remove tooltip if any, except for tab again - if (event.type === 'keydown' && event.which != key.TAB ) { - IPython.tooltip.remove_and_cancel_tooltip(); - } - var cur = editor.getCursor(); - if (event.keyCode === key.ENTER){ - this.auto_highlight(); - } + if (this.mode === 'command') { + return false + } else if (this.mode === 'edit') { + // whatever key is pressed, first, cancel the tooltip request before + // they are sent, and remove tooltip if any, except for tab again + if (event.type === 'keydown' && event.which != key.TAB ) { + IPython.tooltip.remove_and_cancel_tooltip(); + }; + + var cur = editor.getCursor(); + if (event.keyCode === key.ENTER){ + this.auto_highlight(); + } - if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) { - // Always ignore shift-enter in CodeMirror as we handle it. - return true; - } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { - // triger on keypress (!) otherwise inconsistent event.which depending on plateform - // browser and keyboard layout ! - // Pressing '(' , request tooltip, don't forget to reappend it - // The second argument says to hide the tooltip if the docstring - // is actually empty - IPython.tooltip.pending(that, true); - } else if (event.which === key.UPARROW && event.type === 'keydown') { - // If we are not at the top, let CM handle the up arrow and - // prevent the global keydown handler from handling it. - if (!that.at_top()) { - event.stop(); - return false; - } else { + if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) { + // Always ignore shift-enter in CodeMirror as we handle it. return true; - } - } else if (event.which === key.ESC) { - return IPython.tooltip.remove_and_cancel_tooltip(true); - } else if (event.which === key.DOWNARROW && event.type === 'keydown') { - // If we are not at the bottom, let CM handle the down arrow and - // prevent the global keydown handler from handling it. - if (!that.at_bottom()) { - event.stop(); - return false; - } else { + + } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { + // triger on keypress (!) otherwise inconsistent event.which depending on plateform + // browser and keyboard layout ! + // Pressing '(' , request tooltip, don't forget to reappend it + // The second argument says to hide the tooltip if the docstring + // is actually empty + IPython.tooltip.pending(that, true); + } else if (event.which === key.UPARROW && event.type === 'keydown') { + // If we are not at the top, let CM handle the up arrow and + // prevent the global keydown handler from handling it. + if (!that.at_top()) { + event.stop(); + return false; + } else { + return true; + }; + } else if (event.which === key.ESC) { + IPython.tooltip.remove_and_cancel_tooltip(true); return true; - } - } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) { - if (editor.somethingSelected()){ - var anchor = editor.getCursor("anchor"); - var head = editor.getCursor("head"); - if( anchor.line != head.line){ - return false; + } else if (event.which === key.DOWNARROW && event.type === 'keydown') { + // If we are not at the bottom, let CM handle the down arrow and + // prevent the global keydown handler from handling it. + if (!that.at_bottom()) { + event.stop(); + return false; + } else { + return true; + }; + } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) { + if (editor.somethingSelected()){ + var anchor = editor.getCursor("anchor"); + var head = editor.getCursor("head"); + if( anchor.line != head.line){ + return false; + } } } IPython.tooltip.request(that); @@ -213,13 +220,10 @@ var IPython = (function (IPython) { // is empty. In this case, let CodeMirror handle indentation. return false; } else { - event.stop(); - this.completer.startCompletion(); - return true; - } - } else { - // keypress/keyup also trigger on TAB press, and we don't want to - // use those to disable tab completion. + // keypress/keyup also trigger on TAB press, and we don't want to + // use those to disable tab completion. + return false; + }; return false; } return false; @@ -304,21 +308,46 @@ var IPython = (function (IPython) { // Basic cell manipulation. CodeCell.prototype.select = function () { - IPython.Cell.prototype.select.apply(this); - this.code_mirror.refresh(); - this.auto_highlight(); + var continue = IPython.Cell.prototype.select.apply(this); + if (continue) { + this.code_mirror.refresh(); + this.auto_highlight(); + }; + return continue; }; - CodeCell.prototype.focus = function () { - IPython.Cell.prototype.focus.apply(this); - this.code_mirror.focus(); + CodeCell.prototype.render = function () { + var continue = IPython.Cell.prototype.render.apply(this); + if (continue) { + this.execute(); + }; + return continue; }; - CodeCell.prototype.unfocus = function () { - IPython.Cell.prototype.focus.apply(this); - this.code_mirror.blur(); + CodeCell.prototype.unrender = function () { + var continue = IPython.Cell.prototype.unrender.apply(this); + if (continue) { + this.clear_output(true, true, true); + }; + return continue; }; + CodeCell.prototype.command_mode = function () { + var continue = IPython.Cell.prototype.command_mode.apply(this); + if (continue) { + this.focus_cell(); + }; + return continue; + } + + CodeCell.prototype.edit_mode = function () { + var continue = IPython.Cell.prototype.edit_mode.apply(this); + if (continue) { + this.focus_editor(); + }; + return continue; + } + CodeCell.prototype.select_all = function () { var start = {line: 0, ch: 0}; var nlines = this.code_mirror.lineCount(); diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index e396b12..3eebb2f 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -946,7 +946,7 @@ var IPython = (function (IPython) { text = ''; }; // The edit must come before the set_text. - target_cell.edit(); + target_cell.unrender(); target_cell.set_text(text); // make this value the starting point, so that we can only undo // to this state, instead of a blank cell @@ -976,7 +976,7 @@ var IPython = (function (IPython) { text = ''; }; // The edit must come before the set_text. - target_cell.edit(); + target_cell.unrender(); target_cell.set_text(text); // make this value the starting point, so that we can only undo // to this state, instead of a blank cell @@ -1011,7 +1011,7 @@ var IPython = (function (IPython) { }; // The edit must come before the set_text. target_cell.set_level(level); - target_cell.edit(); + target_cell.unrender(); target_cell.set_text(text); // make this value the starting point, so that we can only undo // to this state, instead of a blank cell @@ -1179,7 +1179,7 @@ var IPython = (function (IPython) { cell.set_text(textb); cell.render(); var new_cell = this.insert_cell_above('markdown'); - new_cell.edit(); // editor must be visible to call set_text + new_cell.unrender(); // editor must be visible to call set_text new_cell.set_text(texta); new_cell.render(); this.select_next(); @@ -1208,7 +1208,7 @@ var IPython = (function (IPython) { if (cell instanceof IPython.CodeCell) { cell.set_text(upper_text+'\n'+text); } else if (cell instanceof IPython.MarkdownCell) { - cell.edit(); + cell.unrender(); cell.set_text(upper_text+'\n'+text); cell.render(); }; @@ -1238,7 +1238,7 @@ var IPython = (function (IPython) { if (cell instanceof IPython.CodeCell) { cell.set_text(text+'\n'+lower_text); } else if (cell instanceof IPython.MarkdownCell) { - cell.edit(); + cell.unrender(); cell.set_text(text+'\n'+lower_text); cell.render(); }; diff --git a/IPython/html/static/notebook/js/textcell.js b/IPython/html/static/notebook/js/textcell.js index cf7f003..e8cbd35 100644 --- a/IPython/html/static/notebook/js/textcell.js +++ b/IPython/html/static/notebook/js/textcell.js @@ -104,13 +104,13 @@ var IPython = (function (IPython) { this.element.keydown(function (event) { if (event.which === 13 && !event.shiftKey) { if (that.rendered) { - that.edit(); + that.unrender(); return false; }; }; }); this.element.dblclick(function () { - that.edit(); + that.unrender(); }); }; @@ -134,57 +134,59 @@ var IPython = (function (IPython) { return false; }; - /** - * Select the current cell and trigger 'focus' - * @method select - */ + // Cell level actions + TextCell.prototype.select = function () { - IPython.Cell.prototype.select.apply(this); - var output = this.element.find("div.text_cell_render"); - output.trigger('focus'); + var continue = IPython.Cell.prototype.select.apply(this); + if (continue) { + if (this.mode === 'edit') { + this.code_mirror.refresh(); + } + }; + return continue; }; - /** - * unselect the current cell and `render` it - * @method unselect - */ - TextCell.prototype.unselect = function() { - // render on selection of another cell - this.render(); - IPython.Cell.prototype.unselect.apply(this); + TextCell.prototype.render = function () { + var continue = IPython.Cell.prototype.render.apply(this); + if (continue) { + this.execute(); + }; + return continue; }; - /** - * - * put the current cell in edition mode - * @method edit - */ - TextCell.prototype.edit = function () { - if (this.rendered === true) { + TextCell.prototype.unrender = function () { + if (this.read_only) return; + var continue = IPython.Cell.prototype.unrender.apply(this); + if (continue) { var text_cell = this.element; var output = text_cell.find("div.text_cell_render"); output.hide(); text_cell.find('div.text_cell_input').show(); - this.code_mirror.refresh(); - this.code_mirror.focus(); - // We used to need an additional refresh() after the focus, but - // it appears that this has been fixed in CM. This bug would show - // up on FF when a newly loaded markdown cell was edited. - this.rendered = false; + this.focus_editor(); if (this.get_text() === this.placeholder) { this.set_text(''); this.refresh(); } - } - }; + }; + return continue; + }; - /** - * Empty, Subclasses must define render. - * @method render - */ - TextCell.prototype.render = function () {}; + TextCell.prototype.command_mode = function () { + var continue = IPython.Cell.prototype.command_mode.apply(this); + if (continue) { + this.focus_cell(); + }; + return continue; + } + TextCell.prototype.edit_mode = function () { + var continue = IPython.Cell.prototype.edit_mode.apply(this); + if (continue) { + this.focus_editor(); + }; + return continue; + } /** * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}} @@ -382,11 +384,12 @@ var IPython = (function (IPython) { /** @method render **/ RawCell.prototype.render = function () { + this.rendered = true; var text = this.get_text(); if (text === "") { text = this.placeholder; } - console.log('rendering', text); this.set_text(text); + this.unrender(); };