diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js
index bb903ad..aa85d17 100644
--- a/IPython/html/static/base/js/utils.js
+++ b/IPython/html/static/base/js/utils.js
@@ -514,6 +514,12 @@ define([
}
};
+ var mergeopt = function(_class, options, overwrite){
+ options = options || {};
+ overwrite = overwrite || {};
+ return $.extend(true, {}, _class.options_default, options, overwrite);
+ };
+
var ajax_error_msg = function (jqXHR) {
// Return a JSON error message if there is one,
// otherwise the basic HTTP status text.
@@ -552,6 +558,7 @@ define([
platform: platform,
is_or_has : is_or_has,
is_focused : is_focused,
+ mergeopt: mergeopt,
ajax_error_msg : ajax_error_msg,
log_ajax_error : log_ajax_error,
};
diff --git a/IPython/html/static/notebook/js/cell.js b/IPython/html/static/notebook/js/cell.js
index a747c80..0485ca9 100644
--- a/IPython/html/static/notebook/js/cell.js
+++ b/IPython/html/static/notebook/js/cell.js
@@ -42,7 +42,7 @@ define([
options = options || {};
this.keyboard_manager = options.keyboard_manager;
this.events = options.events;
- var config = this.mergeopt(Cell, options.config);
+ var config = utils.mergeopt(Cell, options.config);
// superclass default overwrite our default
this.placeholder = config.placeholder || '';
@@ -94,12 +94,6 @@ define([
Cell.options_default.cm_config.dragDrop = false;
}
- Cell.prototype.mergeopt = function(_class, options, overwrite){
- options = options || {};
- overwrite = overwrite || {};
- return $.extend(true, {}, _class.options_default, options, overwrite);
- };
-
/**
* Empty. Subclasses must implement create_element.
* This should contain all the code to create the DOM element in notebook
diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js
index c7724c4..2703042 100644
--- a/IPython/html/static/notebook/js/codecell.js
+++ b/IPython/html/static/notebook/js/codecell.js
@@ -76,7 +76,7 @@ define([
onKeyEvent: $.proxy(this.handle_keyevent,this)
};
- var config = this.mergeopt(CodeCell, this.config, {cm_config: cm_overwrite_options});
+ var config = utils.mergeopt(CodeCell, this.config, {cm_config: cm_overwrite_options});
Cell.apply(this,[{
config: config,
keyboard_manager: options.keyboard_manager,
diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js
index 8aaf8b4..8b837ee 100644
--- a/IPython/html/static/notebook/js/notebook.js
+++ b/IPython/html/static/notebook/js/notebook.js
@@ -53,7 +53,7 @@ define([
// base_url : string
// notebook_path : string
// notebook_name : string
- this.config = options.config || {};
+ this.config = utils.mergeopt(Notebook, options.config);
this.base_url = options.base_url;
this.notebook_path = options.notebook_path;
this.notebook_name = options.notebook_name;
@@ -63,6 +63,7 @@ define([
this.tooltip = new tooltip.Tooltip(this.events);
this.ws_url = options.ws_url;
this._session_starting = false;
+ this.default_cell_type = this.config.default_cell_type || 'code';
// default_kernel_name is a temporary measure while we implement proper
// kernel selection and delayed start. Do not rely on it.
this.default_kernel_name = 'python';
@@ -134,6 +135,14 @@ define([
rawcell_celltoolbar.register(this);
slideshow_celltoolbar.register(this);
};
+
+ Notebook.options_default = {
+ // can be any cell type, or the special values of
+ // 'above', 'below', or 'selected' to get the value from another cell.
+ Notebook: {
+ default_cell_type: 'code',
+ }
+ };
/**
@@ -835,10 +844,25 @@ define([
Notebook.prototype.insert_cell_at_index = function(type, index){
var ncells = this.ncells();
- index = Math.min(index,ncells);
- index = Math.max(index,0);
+ index = Math.min(index, ncells);
+ index = Math.max(index, 0);
var cell = null;
- type = type || this.get_selected_cell().cell_type;
+ type = type || this.default_cell_type;
+ if (type === 'above') {
+ if (index > 0) {
+ type = this.get_cell(index-1).cell_type;
+ } else {
+ type = 'code';
+ }
+ } else if (type === 'below') {
+ if (index < ncells) {
+ type = this.get_cell(index).cell_type;
+ } else {
+ type = 'code';
+ }
+ } else if (type === 'selected') {
+ type = this.get_selected_cell().cell_type;
+ }
if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) {
var cell_options = {
diff --git a/IPython/html/static/notebook/js/textcell.js b/IPython/html/static/notebook/js/textcell.js
index e599a99..ec0b534 100644
--- a/IPython/html/static/notebook/js/textcell.js
+++ b/IPython/html/static/notebook/js/textcell.js
@@ -3,13 +3,14 @@
define([
'base/js/namespace',
+ 'base/js/utils',
'jquery',
'notebook/js/cell',
'base/js/security',
'notebook/js/mathjaxutils',
'notebook/js/celltoolbar',
'components/marked/lib/marked',
-], function(IPython, $, cell, security, mathjaxutils, celltoolbar, marked) {
+], function(IPython, utils, $, cell, security, mathjaxutils, celltoolbar, marked) {
"use strict";
var Cell = cell.Cell;
@@ -40,7 +41,7 @@ define([
var cm_overwrite_options = {
onKeyEvent: $.proxy(this.handle_keyevent,this)
};
- var config = this.mergeopt(TextCell, this.config, {cm_config:cm_overwrite_options});
+ var config = utils.mergeopt(TextCell, this.config, {cm_config:cm_overwrite_options});
Cell.apply(this, [{
config: config,
keyboard_manager: options.keyboard_manager,
@@ -226,7 +227,7 @@ define([
// keyboard_manager: KeyboardManager instance
// notebook: Notebook instance
options = options || {};
- var config = this.mergeopt(MarkdownCell, options.config);
+ var config = utils.mergeopt(MarkdownCell, options.config);
TextCell.apply(this, [$.extend({}, options, {config: config})]);
this.cell_type = 'markdown';
@@ -279,7 +280,7 @@ define([
// keyboard_manager: KeyboardManager instance
// notebook: Notebook instance
options = options || {};
- var config = this.mergeopt(RawCell, options.config);
+ var config = utils.mergeopt(RawCell, options.config);
TextCell.apply(this, [$.extend({}, options, {config: config})]);
// RawCell should always hide its rendered div
@@ -339,7 +340,7 @@ define([
// keyboard_manager: KeyboardManager instance
// notebook: Notebook instance
options = options || {};
- var config = this.mergeopt(HeadingCell, options.config);
+ var config = utils.mergeopt(HeadingCell, options.config);
TextCell.apply(this, [$.extend({}, options, {config: config})]);
this.level = 1;
diff --git a/IPython/html/tests/notebook/dualmode_cellinsert.js b/IPython/html/tests/notebook/dualmode_cellinsert.js
index e87f895..039babe 100644
--- a/IPython/html/tests/notebook/dualmode_cellinsert.js
+++ b/IPython/html/tests/notebook/dualmode_cellinsert.js
@@ -12,31 +12,66 @@ casper.notebook_test(function () {
var c = 'print("c")';
index = this.append_cell(c);
this.execute_cell_then(index);
-
+
+ this.thenEvaluate(function() {
+ IPython.notebook.default_cell_type = 'code';
+ });
+
this.then(function () {
// Cell insertion
this.select_cell(2);
+ this.trigger_keydown('m'); // Make it markdown
this.trigger_keydown('a'); // Creates one cell
this.test.assertEquals(this.get_cell_text(2), '', 'a; New cell 2 text is empty');
- this.test.assertEquals(this.get_cell(2).cell_type, 'code', 'a; inserts a code cell when on code cell');
+ this.test.assertEquals(this.get_cell(2).cell_type, 'code', 'a; inserts a code cell');
this.validate_notebook_state('a', 'command', 2);
this.trigger_keydown('b'); // Creates one cell
this.test.assertEquals(this.get_cell_text(2), '', 'b; Cell 2 text is still empty');
this.test.assertEquals(this.get_cell_text(3), '', 'b; New cell 3 text is empty');
- this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell when on code cell');
+ this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell');
this.validate_notebook_state('b', 'command', 3);
});
+
+ this.thenEvaluate(function() {
+ IPython.notebook.default_cell_type = 'selected';
+ });
+
this.then(function () {
- // Cell insertion
this.select_cell(2);
this.trigger_keydown('m'); // switch it to markdown for the next test
- this.trigger_keydown('a'); // Creates one cell
- this.test.assertEquals(this.get_cell_text(2), '', 'a; New cell 2 text is empty');
- this.test.assertEquals(this.get_cell(2).cell_type, 'markdown', 'a; inserts a markdown cell when on markdown cell');
- this.validate_notebook_state('a', 'command', 2);
- this.trigger_keydown('b'); // Creates one cell
- this.test.assertEquals(this.get_cell_text(2), '', 'b; Cell 2 text is still empty');
- this.test.assertEquals(this.get_cell(3).cell_type, 'markdown', 'b; inserts a markdown cell when on markdown cell');
- this.validate_notebook_state('b', 'command', 3);
+ this.test.assertEquals(this.get_cell(2).cell_type, 'markdown', 'test cell is markdown');
+ this.trigger_keydown('a'); // new cell above
+ this.test.assertEquals(this.get_cell(2).cell_type, 'markdown', 'a; inserts a markdown cell when markdown selected');
+ this.trigger_keydown('b'); // new cell below
+ this.test.assertEquals(this.get_cell(3).cell_type, 'markdown', 'b; inserts a markdown cell when markdown selected');
+ });
+
+ this.thenEvaluate(function() {
+ IPython.notebook.default_cell_type = 'above';
+ });
+
+ this.then(function () {
+ this.select_cell(2);
+ this.trigger_keydown('1'); // switch it to heading for the next test
+ this.test.assertEquals(this.get_cell(2).cell_type, 'heading', 'test cell is heading');
+ this.trigger_keydown('b'); // new cell below
+ this.test.assertEquals(this.get_cell(3).cell_type, 'heading', 'b; inserts a heading cell below heading cell');
+ this.trigger_keydown('a'); // new cell above
+ this.test.assertEquals(this.get_cell(3).cell_type, 'heading', 'a; inserts a heading cell below heading cell');
+ });
+
+ this.thenEvaluate(function() {
+ IPython.notebook.default_cell_type = 'below';
+ });
+
+ this.then(function () {
+ this.select_cell(2);
+ this.trigger_keydown('r'); // switch it to markdown for the next test
+ this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'test cell is raw');
+ this.trigger_keydown('a'); // new cell above
+ this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'a; inserts a raw cell above raw cell');
+ this.trigger_keydown('y'); // switch it to code for the next test
+ this.trigger_keydown('b'); // new cell below
+ this.test.assertEquals(this.get_cell(3).cell_type, 'raw', 'b; inserts a raw cell above raw cell');
});
});