diff --git a/IPython/html/static/notebook/js/keyboardmanager.js b/IPython/html/static/notebook/js/keyboardmanager.js index bf35e0f..c5d213e 100644 --- a/IPython/html/static/notebook/js/keyboardmanager.js +++ b/IPython/html/static/notebook/js/keyboardmanager.js @@ -1,14 +1,17 @@ -// Copyright (c) IPython Development Team. -// Distributed under the terms of the Modified BSD License. +//---------------------------------------------------------------------------- +// Copyright (C) 2011 The IPython Development Team +// +// Distributed under the terms of the BSD License. The full license is in +// the file COPYING, distributed as part of this software. +//---------------------------------------------------------------------------- -define([ - 'base/js/namespace', - 'jquery', - 'base/js/utils', - 'base/js/keyboard', -], function(IPython, $, utils, keyboard) { +//============================================================================ +// Keyboard management +//============================================================================ + +var IPython = (function (IPython) { "use strict"; - + var browser = utils.browser[0]; var platform = utils.platform; @@ -40,437 +43,449 @@ define([ KeyboardManager.prototype.get_default_common_shortcuts = function() { var that = this; var shortcuts = { - 'shift' : { - help : '', - help_index : '', - handler : function (event) { - // ignore shift keydown - return true; - } - }, - 'shift-enter' : { - help : 'run cell, select below', - help_index : 'ba', - handler : function (event) { + 'shift' : { + help : '', + help_index : '', + handler : function (event) { + // ignore shift keydown + return true; + } + }, + 'shift-enter' : { + help : 'run cell, select below', + help_index : 'ba', + handler : function (event) { that.notebook.execute_cell_and_select_below(); - return false; - } - }, - 'ctrl-enter' : { - help : 'run cell', - help_index : 'bb', - handler : function (event) { + return false; + } + }, + 'ctrl-enter' : { + help : 'run cell', + help_index : 'bb', + handler : function (event) { that.notebook.execute_cell(); - return false; - } - }, - 'alt-enter' : { - help : 'run cell, insert below', - help_index : 'bc', - handler : function (event) { + return false; + } + }, + 'alt-enter' : { + help : 'run cell, insert below', + help_index : 'bc', + handler : function (event) { that.notebook.execute_cell_and_insert_below(); - return false; - } + return false; } - }; + } + }; - if (platform === 'MacOS') { + if (platform === 'MacOS') { shortcuts['cmd-s'] = - { - help : 'save notebook', - help_index : 'fb', - handler : function (event) { + { + help : 'save notebook', + help_index : 'fb', + handler : function (event) { that.notebook.save_checkpoint(); - event.preventDefault(); - return false; - } - }; - } else { + event.preventDefault(); + return false; + } + }; + } else { shortcuts['ctrl-s'] = - { - help : 'save notebook', - help_index : 'fb', - handler : function (event) { + { + help : 'save notebook', + help_index : 'fb', + handler : function (event) { that.notebook.save_checkpoint(); - event.preventDefault(); - return false; - } - }; - } + event.preventDefault(); + return false; + } + }; + } return shortcuts; }; KeyboardManager.prototype.get_default_edit_shortcuts = function() { var that = this; return { - 'esc' : { - help : 'command mode', - help_index : 'aa', - handler : function (event) { + 'esc' : { + help : 'command mode', + help_index : 'aa', + handler : function (event) { that.notebook.command_mode(); - return false; - } - }, - 'ctrl-m' : { - help : 'command mode', - help_index : 'ab', - handler : function (event) { + return false; + } + }, + 'ctrl-m' : { + help : 'command mode', + help_index : 'ab', + handler : function (event) { that.notebook.command_mode(); - return false; - } - }, - 'up' : { - help : '', - help_index : '', - handler : function (event) { + return false; + } + }, + 'up' : { + help : '', + help_index : '', + handler : function (event) { var index = that.notebook.get_selected_index(); var cell = that.notebook.get_cell(index); - if (cell && cell.at_top() && index !== 0) { - event.preventDefault(); + if (cell && cell.at_top() && index !== 0) { + event.preventDefault(); that.notebook.command_mode(); that.notebook.select_prev(); that.notebook.edit_mode(); var cm = that.notebook.get_selected_cell().code_mirror; - cm.setCursor(cm.lastLine(), 0); - return false; - } else if (cell) { - var cm = cell.code_mirror; - cm.execCommand('goLineUp'); - return false; - } + cm.setCursor(cm.lastLine(), 0); + return false; + } else if (cell) { + var cm = cell.code_mirror; + cm.execCommand('goLineUp'); + return false; } - }, - 'down' : { - help : '', - help_index : '', - handler : function (event) { + } + }, + 'down' : { + help : '', + help_index : '', + handler : function (event) { var index = that.notebook.get_selected_index(); var cell = that.notebook.get_cell(index); if (cell.at_bottom() && index !== (that.notebook.ncells()-1)) { - event.preventDefault(); + event.preventDefault(); that.notebook.command_mode(); that.notebook.select_next(); that.notebook.edit_mode(); var cm = that.notebook.get_selected_cell().code_mirror; - cm.setCursor(0, 0); - return false; - } else { - var cm = cell.code_mirror; - cm.execCommand('goLineDown'); - return false; - } - } - }, - 'ctrl-shift--' : { - help : 'split cell', - help_index : 'ea', - handler : function (event) { - that.notebook.split_cell(); + cm.setCursor(0, 0); return false; - } - }, - 'ctrl-shift-subtract' : { - help : '', - help_index : 'eb', - handler : function (event) { - that.notebook.split_cell(); + } else { + var cm = cell.code_mirror; + cm.execCommand('goLineDown'); return false; } - }, - }; + } + }, + 'ctrl-shift--' : { + help : 'split cell', + help_index : 'ea', + handler : function (event) { + that.notebook.split_cell(); + return false; + } + }, + 'ctrl-shift-subtract' : { + help : '', + help_index : 'eb', + handler : function (event) { + that.notebook.split_cell(); + return false; + } + }, + }; }; KeyboardManager.prototype.get_default_command_shortcuts = function() { var that = this; return { - 'enter' : { - help : 'edit mode', - help_index : 'aa', - handler : function (event) { + 'space': { + help: "Scroll down to next H1 cell", + handler: function(event) { + return that.notebook.scrollmanager.scroll(1); + }, + }, + 'shift-space': { + help: "Scroll up to previous H1 cell", + handler: function(event) { + return that.notebook.scrollmanager.scroll(-1); + }, + }, + 'enter' : { + help : 'edit mode', + help_index : 'aa', + handler : function (event) { that.notebook.edit_mode(); - return false; - } - }, - 'up' : { - help : 'select previous cell', - help_index : 'da', - handler : function (event) { + return false; + } + }, + 'up' : { + help : 'select previous cell', + help_index : 'da', + handler : function (event) { var index = that.notebook.get_selected_index(); - if (index !== 0 && index !== null) { + if (index !== 0 && index !== null) { that.notebook.select_prev(); that.notebook.focus_cell(); - } - return false; } - }, - 'down' : { - help : 'select next cell', - help_index : 'db', - handler : function (event) { + return false; + } + }, + 'down' : { + help : 'select next cell', + help_index : 'db', + handler : function (event) { var index = that.notebook.get_selected_index(); if (index !== (that.notebook.ncells()-1) && index !== null) { that.notebook.select_next(); that.notebook.focus_cell(); - } - return false; } - }, - 'k' : { - help : 'select previous cell', - help_index : 'dc', - handler : function (event) { + return false; + } + }, + 'k' : { + help : 'select previous cell', + help_index : 'dc', + handler : function (event) { var index = that.notebook.get_selected_index(); - if (index !== 0 && index !== null) { + if (index !== 0 && index !== null) { that.notebook.select_prev(); that.notebook.focus_cell(); - } - return false; } - }, - 'j' : { - help : 'select next cell', - help_index : 'dd', - handler : function (event) { + return false; + } + }, + 'j' : { + help : 'select next cell', + help_index : 'dd', + handler : function (event) { var index = that.notebook.get_selected_index(); if (index !== (that.notebook.ncells()-1) && index !== null) { that.notebook.select_next(); that.notebook.focus_cell(); - } - return false; } - }, - 'x' : { - help : 'cut cell', - help_index : 'ee', - handler : function (event) { + return false; + } + }, + 'x' : { + help : 'cut cell', + help_index : 'ee', + handler : function (event) { that.notebook.cut_cell(); - return false; - } - }, - 'c' : { - help : 'copy cell', - help_index : 'ef', - handler : function (event) { + return false; + } + }, + 'c' : { + help : 'copy cell', + help_index : 'ef', + handler : function (event) { that.notebook.copy_cell(); - return false; - } - }, - 'shift-v' : { - help : 'paste cell above', - help_index : 'eg', - handler : function (event) { + return false; + } + }, + 'shift-v' : { + help : 'paste cell above', + help_index : 'eg', + handler : function (event) { that.notebook.paste_cell_above(); - return false; - } - }, - 'v' : { - help : 'paste cell below', - help_index : 'eh', - handler : function (event) { + return false; + } + }, + 'v' : { + help : 'paste cell below', + help_index : 'eh', + handler : function (event) { that.notebook.paste_cell_below(); - return false; - } - }, - 'd' : { - help : 'delete cell (press twice)', - help_index : 'ej', - count: 2, - handler : function (event) { + return false; + } + }, + 'd' : { + help : 'delete cell (press twice)', + help_index : 'ej', + count: 2, + handler : function (event) { that.notebook.delete_cell(); - return false; - } - }, - 'a' : { - help : 'insert cell above', - help_index : 'ec', - handler : function (event) { + return false; + } + }, + 'a' : { + help : 'insert cell above', + help_index : 'ec', + handler : function (event) { that.notebook.insert_cell_above(); that.notebook.select_prev(); that.notebook.focus_cell(); - return false; - } - }, - 'b' : { - help : 'insert cell below', - help_index : 'ed', - handler : function (event) { + return false; + } + }, + 'b' : { + help : 'insert cell below', + help_index : 'ed', + handler : function (event) { that.notebook.insert_cell_below(); that.notebook.select_next(); that.notebook.focus_cell(); - return false; - } - }, - 'y' : { - help : 'to code', - help_index : 'ca', - handler : function (event) { + return false; + } + }, + 'y' : { + help : 'to code', + help_index : 'ca', + handler : function (event) { that.notebook.to_code(); - return false; - } - }, - 'm' : { - help : 'to markdown', - help_index : 'cb', - handler : function (event) { + return false; + } + }, + 'm' : { + help : 'to markdown', + help_index : 'cb', + handler : function (event) { that.notebook.to_markdown(); - return false; - } - }, - 'r' : { - help : 'to raw', - help_index : 'cc', - handler : function (event) { + return false; + } + }, + 'r' : { + help : 'to raw', + help_index : 'cc', + handler : function (event) { that.notebook.to_raw(); - return false; - } - }, - '1' : { - help : 'to heading 1', - help_index : 'cd', - handler : function (event) { + return false; + } + }, + '1' : { + help : 'to heading 1', + help_index : 'cd', + handler : function (event) { that.notebook.to_heading(undefined, 1); - return false; - } - }, - '2' : { - help : 'to heading 2', - help_index : 'ce', - handler : function (event) { + return false; + } + }, + '2' : { + help : 'to heading 2', + help_index : 'ce', + handler : function (event) { that.notebook.to_heading(undefined, 2); - return false; - } - }, - '3' : { - help : 'to heading 3', - help_index : 'cf', - handler : function (event) { + return false; + } + }, + '3' : { + help : 'to heading 3', + help_index : 'cf', + handler : function (event) { that.notebook.to_heading(undefined, 3); - return false; - } - }, - '4' : { - help : 'to heading 4', - help_index : 'cg', - handler : function (event) { + return false; + } + }, + '4' : { + help : 'to heading 4', + help_index : 'cg', + handler : function (event) { that.notebook.to_heading(undefined, 4); - return false; - } - }, - '5' : { - help : 'to heading 5', - help_index : 'ch', - handler : function (event) { + return false; + } + }, + '5' : { + help : 'to heading 5', + help_index : 'ch', + handler : function (event) { that.notebook.to_heading(undefined, 5); - return false; - } - }, - '6' : { - help : 'to heading 6', - help_index : 'ci', - handler : function (event) { + return false; + } + }, + '6' : { + help : 'to heading 6', + help_index : 'ci', + handler : function (event) { that.notebook.to_heading(undefined, 6); - return false; - } - }, - 'o' : { - help : 'toggle output', - help_index : 'gb', - handler : function (event) { + return false; + } + }, + 'o' : { + help : 'toggle output', + help_index : 'gb', + handler : function (event) { that.notebook.toggle_output(); - return false; - } - }, - 'shift-o' : { - help : 'toggle output scrolling', - help_index : 'gc', - handler : function (event) { + return false; + } + }, + 'shift-o' : { + help : 'toggle output scrolling', + help_index : 'gc', + handler : function (event) { that.notebook.toggle_output_scroll(); - return false; - } - }, - 's' : { - help : 'save notebook', - help_index : 'fa', - handler : function (event) { + return false; + } + }, + 's' : { + help : 'save notebook', + help_index : 'fa', + handler : function (event) { that.notebook.save_checkpoint(); - return false; - } - }, - 'ctrl-j' : { - help : 'move cell down', - help_index : 'eb', - handler : function (event) { + return false; + } + }, + 'ctrl-j' : { + help : 'move cell down', + help_index : 'eb', + handler : function (event) { that.notebook.move_cell_down(); - return false; - } - }, - 'ctrl-k' : { - help : 'move cell up', - help_index : 'ea', - handler : function (event) { + return false; + } + }, + 'ctrl-k' : { + help : 'move cell up', + help_index : 'ea', + handler : function (event) { that.notebook.move_cell_up(); - return false; - } - }, - 'l' : { - help : 'toggle line numbers', - help_index : 'ga', - handler : function (event) { + return false; + } + }, + 'l' : { + help : 'toggle line numbers', + help_index : 'ga', + handler : function (event) { that.notebook.cell_toggle_line_numbers(); - return false; - } - }, - 'i' : { - help : 'interrupt kernel (press twice)', - help_index : 'ha', - count: 2, - handler : function (event) { + return false; + } + }, + 'i' : { + help : 'interrupt kernel (press twice)', + help_index : 'ha', + count: 2, + handler : function (event) { that.notebook.kernel.interrupt(); - return false; - } - }, - '0' : { - help : 'restart kernel (press twice)', - help_index : 'hb', - count: 2, - handler : function (event) { + return false; + } + }, + '0' : { + help : 'restart kernel (press twice)', + help_index : 'hb', + count: 2, + handler : function (event) { that.notebook.restart_kernel(); - return false; - } - }, - 'h' : { - help : 'keyboard shortcuts', - help_index : 'ge', - handler : function (event) { + return false; + } + }, + 'h' : { + help : 'keyboard shortcuts', + help_index : 'ge', + handler : function (event) { that.quick_help.show_keyboard_shortcuts(); - return false; - } - }, - 'z' : { - help : 'undo last delete', - help_index : 'ei', - handler : function (event) { + return false; + } + }, + 'z' : { + help : 'undo last delete', + help_index : 'ei', + handler : function (event) { that.notebook.undelete_cell(); - return false; - } - }, - 'shift-m' : { - help : 'merge cell below', - help_index : 'ek', - handler : function (event) { + return false; + } + }, + 'shift-m' : { + help : 'merge cell below', + help_index : 'ek', + handler : function (event) { that.notebook.merge_cell_below(); - return false; - } - }, - 'q' : { - help : 'close pager', - help_index : 'gd', - handler : function (event) { + return false; + } + }, + 'q' : { + help : 'close pager', + help_index : 'gd', + handler : function (event) { that.pager.collapse(); - return false; - } - }, - }; + return false; + } + }, + }; }; KeyboardManager.prototype.bind_events = function () { diff --git a/IPython/html/static/notebook/js/main.js b/IPython/html/static/notebook/js/main.js index 4ddee4b..acfa4d5 100644 --- a/IPython/html/static/notebook/js/main.js +++ b/IPython/html/static/notebook/js/main.js @@ -19,6 +19,7 @@ require([ 'notebook/js/keyboardmanager', 'notebook/js/config', 'notebook/js/kernelselector', + 'notebook/js/scrollmanager' // only loaded, not used: 'custom/custom', ], function( @@ -38,7 +39,8 @@ require([ savewidget, keyboardmanager, config, - kernelselector + kernelselector, + scrollmanager ) { "use strict"; @@ -67,6 +69,7 @@ require([ save_widget: save_widget, config: user_config}, common_options)); + var scrollmanager = new scrollmanager.ScrollManager(notebook); var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options); var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', { notebook: notebook, @@ -132,6 +135,7 @@ require([ IPython.save_widget = save_widget; IPython.config = user_config; IPython.tooltip = notebook.tooltip; + IPython.scrollmanager = scrollmanager; events.trigger('app_initialized.NotebookApp'); notebook.load_notebook(common_options.notebook_name, common_options.notebook_path); diff --git a/IPython/html/static/notebook/js/scrollmanager.js b/IPython/html/static/notebook/js/scrollmanager.js new file mode 100644 index 0000000..bd3465a --- /dev/null +++ b/IPython/html/static/notebook/js/scrollmanager.js @@ -0,0 +1,78 @@ +// Copyright (c) IPython Development Team. +// Distributed under the terms of the Modified BSD License. +define([], function(){ + "use strict"; + + var ScrollManager = function (notebook) { + // Public constructor. + this.notebook = notebook; + }; + + ScrollManager.prototype.scroll = function (delta) { + // Scroll the document. + // + // Parameters + // ---------- + // delta: integer + // direction to scroll the document. Positive is downwards. + + // If one or more slides exist, scroll to the slide. + var $slide_cells = $('.slideshow-slide'); + if ($slide_cells.length > 0) { + var i, cell; + + // Get the active slide cell index. + var selected_index = this.notebook.find_cell_index(this.notebook.get_selected_cell()); + var active_slide = -1; + var cells = this.notebook.get_cells(); + for (i = selected_index; i >= 0; i--) { + cell = cells[i]; + var ns = cell.metadata.slideshow; + if (ns && ns.slide_type == 'slide') { + active_slide = i; + break; + } + } + + // Translate cell index into slide cell index. + if (active_slide != -1) { + for (i = 0; i < $slide_cells.length; i++) { + if (cells[active_slide].element[0] == $slide_cells[i]) { + active_slide = i; + break; + } + } + } + + // Scroll. + if (active_slide != -1 || delta > 0) { + active_slide += delta; + active_slide = Math.max(0, Math.min($slide_cells.length-1, active_slide)); + + var cell_element = $slide_cells[active_slide]; + cell = $(cell_element).data('cell'); + this.notebook.select(this.notebook.find_cell_index(cell)); + + this.scroll_to(cell_element); + //cell_element.scrollIntoView(true); + } + + // Cancel browser keyboard scroll. + return false; + + // No slides exist, default browser scroll + } else { + return true; + } + }; + + ScrollManager.prototype.scroll_to = function(destination) { + $('html, body').animate({'scrollTop': element.offset().top}, 'slow', 'swing'); + }; + + // For convinience, add the ScrollManager class to the global namespace + IPython.ScrollManager = ScrollManager; + // Return naemspace for require.js loads + return ScrollManager; + +});