//---------------------------------------------------------------------------- // Copyright (C) 2008-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. //---------------------------------------------------------------------------- //============================================================================ // OutputArea //============================================================================ var IPython = (function (IPython) { "use strict"; var utils = IPython.utils; var OutputArea = function (selector, prompt_area) { this.selector = selector; this.wrapper = $(selector); this.outputs = []; this.collapsed = false; this.scrolled = false; this.clear_out_timeout = null; if (prompt_area === undefined) { this.prompt_area = true; } else { this.prompt_area = prompt_area; } this.create_elements(); this.style(); this.bind_events(); }; OutputArea.prototype.create_elements = function () { this.element = $("
"); 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 output'); this.collapse_button.html('. . .'); this.prompt_overlay.addClass('out_prompt_overlay prompt'); this.prompt_overlay.attr('title', 'click to expand output; double click to hide output'); this.collapse(); }; OutputArea.prototype._should_scroll = function (lines) { if (!lines) { lines = 100; } // 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 () { // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled if ( IPython.utils.browser[0] === "Firefox" ) { return; } // 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; } }; OutputArea.prototype.expand = function () { if (this.collapsed) { this.collapse_button.hide(); this.element.show(); this.prompt_overlay.show(); this.collapsed = false; } }; OutputArea.prototype.toggle_output = function () { if (this.collapsed) { this.expand(); } else { this.collapse(); } }; 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){ MathJax.Hub.Queue(["Typeset",MathJax.Hub]); } }; OutputArea.prototype.handle_output = function (msg_type, content) { var json = {}; json.output_type = msg_type; if (msg_type === "stream") { json.text = content.data; json.stream = content.name; } else if (msg_type === "display_data") { json = this.convert_mime_types(json, content.data); } else if (msg_type === "pyout") { json.prompt_number = content.execution_count; json = this.convert_mime_types(json, content.data); } else if (msg_type === "pyerr") { json.ename = content.ename; json.evalue = content.evalue; json.traceback = content.traceback; } // append with dynamic=true this.append_output(json, true); }; OutputArea.prototype.convert_mime_types = function (json, data) { if (data['text/plain'] !== undefined) { json.text = data['text/plain']; } if (data['text/html'] !== undefined) { json.html = data['text/html']; } if (data['image/svg+xml'] !== undefined) { json.svg = data['image/svg+xml']; } if (data['image/png'] !== undefined) { json.png = data['image/png']; } if (data['image/jpeg'] !== undefined) { json.jpeg = data['image/jpeg']; } if (data['text/latex'] !== undefined) { json.latex = data['text/latex']; } if (data['application/json'] !== undefined) { json.json = data['application/json']; } if (data['application/javascript'] !== undefined) { json.javascript = data['application/javascript']; } return json; }; OutputArea.prototype.append_output = function (json, dynamic) { // If dynamic is true, javascript output will be eval'd. this.expand(); this.flush_clear_timeout(); if (json.output_type === 'pyout') { this.append_pyout(json, dynamic); } else if (json.output_type === 'pyerr') { this.append_pyerr(json); } else if (json.output_type === 'display_data') { this.append_display_data(json, dynamic); } else if (json.output_type === 'stream') { this.append_stream(json); } this.outputs.push(json); var that = this; setTimeout(function(){that.element.trigger('resize');}, 100); }; OutputArea.prototype.create_output_area = function () { var oa = $("").addClass("output_area"); if (this.prompt_area) { oa.append($('').addClass('prompt')); } return oa; }; OutputArea.prototype.append_pyout = function (json, dynamic) { var n = json.prompt_number || ' '; var toinsert = this.create_output_area(); if (this.prompt_area) { toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:'); } this.append_mime_type(json, toinsert, dynamic); this.element.append(toinsert); // If we just output latex, typeset it. if ((json.latex !== undefined) || (json.html !== undefined)) { this.typeset(); } }; OutputArea.prototype.append_pyerr = function (json) { var tb = json.traceback; if (tb !== undefined && tb.length > 0) { var s = ''; var len = tb.length; for (var i=0; i