diff --git a/IPython/frontend/html/notebook/static/css/notebook.css b/IPython/frontend/html/notebook/static/css/notebook.css
index a9f2862..dc2b0ac 100644
--- a/IPython/frontend/html/notebook/static/css/notebook.css
+++ b/IPython/frontend/html/notebook/static/css/notebook.css
@@ -104,7 +104,7 @@ div#notebook {
width: 100%;
/* This spaces the cell away from the edge of the notebook area */
padding: 5px 5px 15px 5px;
- margin: 0px
+ margin: 0px;
background-color: white;
}
@@ -137,6 +137,7 @@ div.cell {
div.code_cell {
background-color: white;
}
+
/* any special styling for code cells that are currently running goes here */
div.code_cell.running {
}
@@ -168,13 +169,50 @@ div.input_prompt {
border-top: 1px solid transparent;
}
-div.output {
+div.output_wrapper {
/* This is a spacer between the input and output of each cell */
margin-top: 5px;
+ margin-left: 5px;
+ /* FF needs explicit width to stretch */
+ width: 100%;
+ /* this position must be relative to enable descendents to be absolute within it */
+ position: relative;
+}
+
+/* class for the output area when it should be height-limited */
+div.output_scroll {
+ /* ideally, this would be max-height, but FF barfs all over that */
+ height: 24em;
+ /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
+ width: 100%;
+
+ overflow: auto;
+ border-radius: 3px;
+ box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
+}
+
+/* output div while it is collapsed */
+div.output_collapsed {
+ margin-right: 5px;
+}
+
+div.out_prompt_overlay {
+ height: 100%;
+ padding: 0px;
+ position: absolute;
+ border-radius: 3px;
+}
+
+div.out_prompt_overlay:hover {
+ /* use inner shadow to get border that is computed the same on WebKit/FF */
+ box-shadow: inset 0 0 1px #000;
+ background: rgba(240, 240, 240, 0.5);
}
div.output_prompt {
color: darkred;
+ /* 5px right shift to account for margin in parent container */
+ margin: 0 5px 0 -5px;
}
/* This class is the outer container of all output sections. */
diff --git a/IPython/frontend/html/notebook/static/js/codecell.js b/IPython/frontend/html/notebook/static/js/codecell.js
index 5c5ead2..c4a1884 100644
--- a/IPython/frontend/html/notebook/static/js/codecell.js
+++ b/IPython/frontend/html/notebook/static/js/codecell.js
@@ -218,6 +218,11 @@ var IPython = (function (IPython) {
};
+ CodeCell.prototype.toggle_output_scroll = function () {
+ this.output_area.toggle_scroll();
+ };
+
+
CodeCell.prototype.set_input_prompt = function (number) {
this.input_prompt_number = number;
var ns = number || " ";
diff --git a/IPython/frontend/html/notebook/static/js/menubar.js b/IPython/frontend/html/notebook/static/js/menubar.js
index a809cfd..e2e6c61 100644
--- a/IPython/frontend/html/notebook/static/js/menubar.js
+++ b/IPython/frontend/html/notebook/static/js/menubar.js
@@ -158,6 +158,15 @@ var IPython = (function (IPython) {
this.element.find('#toggle_output').click(function () {
IPython.notebook.toggle_output();
});
+ this.element.find('#collapse_all_output').click(function () {
+ IPython.notebook.collapse_all_output();
+ });
+ this.element.find('#scroll_all_output').click(function () {
+ IPython.notebook.scroll_all_output();
+ });
+ this.element.find('#expand_all_output').click(function () {
+ IPython.notebook.expand_all_output();
+ });
this.element.find('#clear_all_output').click(function () {
IPython.notebook.clear_all_output();
});
diff --git a/IPython/frontend/html/notebook/static/js/notebook.js b/IPython/frontend/html/notebook/static/js/notebook.js
index 7c02bf7..2978047 100644
--- a/IPython/frontend/html/notebook/static/js/notebook.js
+++ b/IPython/frontend/html/notebook/static/js/notebook.js
@@ -194,7 +194,11 @@ var IPython = (function (IPython) {
return false;
} else if (event.which === 79 && that.control_key_active) {
// Toggle output = o
- that.toggle_output();
+ if (event.shiftKey){
+ that.toggle_output_scroll();
+ } else {
+ that.toggle_output();
+ }
that.control_key_active = false;
return false;
} else if (event.which === 83 && that.control_key_active) {
@@ -883,6 +887,53 @@ var IPython = (function (IPython) {
};
+ Notebook.prototype.toggle_output_scroll = function (index) {
+ var i = this.index_or_selected(index);
+ this.get_cell(i).toggle_output_scroll();
+ };
+
+
+ Notebook.prototype.collapse_all_output = function () {
+ var ncells = this.ncells();
+ var cells = this.get_cells();
+ for (var i=0; i");
+ this.collapse_button = $("");
+ this.prompt_overlay = $("");
+ this.wrapper.append(this.prompt_overlay);
+ this.wrapper.append(this.element);
+ this.wrapper.append(this.collapse_button);
};
OutputArea.prototype.style = function () {
+ this.collapse_button.hide();
+ this.prompt_overlay.hide();
+
+ this.wrapper.addClass('output_wrapper');
this.element.addClass('output vbox');
+
+ this.collapse_button.button();
+ this.collapse_button.addClass('output_collapsed vbox');
+ this.collapse_button.attr('title', 'click to expand outout');
+ this.collapse_button.html('. . .');
+
+ this.prompt_overlay.addClass('out_prompt_overlay prompt');
+ this.prompt_overlay.attr('title', 'click to expand outout; double click to hide output');
+
this.collapse();
};
+ OutputArea.prototype._should_scroll = function (lines) {
+ if (!lines) {
+ lines = 50;
+ }
+ // line-height from http://stackoverflow.com/questions/1185151
+ var fontSize = this.element.css('font-size');
+ var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
+
+ return (this.element.height() > lines * lineHeight);
+ };
+
+
+ OutputArea.prototype.bind_events = function () {
+ var that = this;
+ this.prompt_overlay.dblclick(function () { that.toggle_output(); });
+ this.prompt_overlay.click(function () { that.toggle_scroll(); });
+
+ this.element.resize(function () {
+ // maybe scroll output,
+ // if it's grown large enough and hasn't already been scrolled.
+ if ( !that.scrolled && that._should_scroll()) {
+ that.scroll_area();
+ }
+ });
+ this.collapse_button.click(function () {
+ that.expand();
+ });
+ this.collapse_button.hover(function () {
+ $(this).addClass("ui-state-hover");
+ }, function () {
+ $(this).removeClass("ui-state-hover");
+ });
+ };
+
+
OutputArea.prototype.collapse = function () {
if (!this.collapsed) {
this.element.hide();
+ this.prompt_overlay.hide();
+ if (this.element.html()){
+ this.collapse_button.show();
+ }
this.collapsed = true;
};
};
@@ -45,7 +109,9 @@ var IPython = (function (IPython) {
OutputArea.prototype.expand = function () {
if (this.collapsed) {
+ this.collapse_button.hide();
this.element.show();
+ this.prompt_overlay.show();
this.collapsed = false;
};
};
@@ -60,6 +126,38 @@ var IPython = (function (IPython) {
};
+ OutputArea.prototype.scroll_area = function () {
+ this.element.addClass('output_scroll');
+ this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
+ this.scrolled = true;
+ };
+
+
+ OutputArea.prototype.unscroll_area = function () {
+ this.element.removeClass('output_scroll');
+ this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
+ this.scrolled = false;
+ };
+
+
+ OutputArea.prototype.scroll_if_long = function (lines) {
+ if (this._should_scroll(lines)) {
+ // only allow scrolling long-enough output
+ this.scroll_area();
+ };
+ };
+
+
+ OutputArea.prototype.toggle_scroll = function () {
+ if (this.scrolled) {
+ this.unscroll_area();
+ } else {
+ // only allow scrolling long-enough output
+ this.scroll_if_long(20);
+ };
+ };
+
+
// typeset with MathJax if MathJax is available
OutputArea.prototype.typeset = function () {
if (window.MathJax){
@@ -132,6 +230,8 @@ var IPython = (function (IPython) {
this.append_stream(json);
};
this.outputs.push(json);
+ var that = this;
+ setTimeout(function(){that.element.trigger('resize');}, 100);
};
@@ -346,6 +446,7 @@ var IPython = (function (IPython) {
// clear all, no need for logic
output_div.html("");
this.outputs = [];
+ this.unscroll_area();
return;
}
// remove html output
@@ -360,7 +461,8 @@ var IPython = (function (IPython) {
if (other) {
output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
}
-
+ this.unscroll_area();
+
// remove cleared outputs from JSON list:
for (var i = this.outputs.length - 1; i >= 0; i--) {
var out = this.outputs[i];
diff --git a/IPython/frontend/html/notebook/static/js/quickhelp.js b/IPython/frontend/html/notebook/static/js/quickhelp.js
index 3376883..d609e70 100644
--- a/IPython/frontend/html/notebook/static/js/quickhelp.js
+++ b/IPython/frontend/html/notebook/static/js/quickhelp.js
@@ -35,6 +35,7 @@ var IPython = (function (IPython) {
{key: 'Ctrl-m a', help: 'insert cell above'},
{key: 'Ctrl-m b', help: 'insert cell below'},
{key: 'Ctrl-m o', help: 'toggle output'},
+ {key: 'Ctrl-m O', help: 'toggle output scroll'},
{key: 'Ctrl-m l', help: 'toggle line numbers'},
{key: 'Ctrl-m s', help: 'save notebook'},
{key: 'Ctrl-m j', help: 'move cell down'},
diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html
index 64da27c..26eb12f 100644
--- a/IPython/frontend/html/notebook/templates/notebook.html
+++ b/IPython/frontend/html/notebook/templates/notebook.html
@@ -117,8 +117,15 @@ data-notebook-id={{notebook_id}}
Heading 5
Heading 6
- Toggle Output
- Clear All Output
+ Toggle Current Output
+ All Output
+
+
Kernel