// -*- java -*-

function Console(containerId) {
    this.counter = 0;
    this.containerId = containerId;
    this.inputId = containerId + "_expression";
    this.outputId = containerId + "_output";
    this.buildView();
}

Console.prototype.escapeHTML = function (s) {
    var n = document.createElement("div");
    n.appendChild(document.createTextNode(s));
    return n.innerHTML;
}

Console.prototype.unescapeHTML = function (s) {
    var n = document.createElement("div");
    n.innerHTML = s;
    return n.firstChild.textContent;
}

Console.prototype.prependOutputDiv = function (styletext, content) {
    var d = document.createElement("div");
    d.style.cssText = styletext;
    d.innerHTML = content;

    var o = document.getElementById(this.outputId);
    o.insertBefore(d, o.firstChild);
}

Console.prototype.prependIO = function (styletext, input, output) {
    var id = this.containerId + 'expr' + this.counter;
    this.counter++;

    var editButtonId = id + '_editButton';
    var bodyHtml = '<div style="color: grey; font-style: italic">' +
    '<input style="float: right" id="'+editButtonId+'" value="Edit expression" type="submit">' +
    '<span id="'+id+'">' + this.escapeHTML(input.toString()) + '</span>' +
    '</div>';

    if (output != undefined) {
	this.prependOutputDiv(styletext, bodyHtml +
			      "<div style='border-top: 1px dashed grey'>" +
                              this.escapeHTML(output.toString()) +
			      "</div>");
    } else {
	this.prependOutputDiv(styletext, bodyHtml);
    }

    var thisConsole = this;
    document.getElementById(editButtonId).onclick = function () { thisConsole.loadInput(id); };
}

Console.prototype.recordOutput = function (input, output) {
    this.prependIO("border: 1px solid black; margin-top: 0.5em", input, output);
}

Console.prototype.recordError = function (input, e) {
    var style = "border: 2px solid red; background: #ffeeee; margin-top: 0.5em";
    if ((typeof e == typeof {}) && ('message' in e)) {
	this.prependIO(style, input, e.message + " (" + e.name + ")");
    } else {
	this.prependIO(style, input, e.toString());
    }
}

Console.prototype.refocusInput = function () {
    var codearea = document.getElementById(this.inputId);
    codearea.select();
    codearea.focus();
}

Console.prototype.loadInput = function (id) {
    document.getElementById(this.inputId).value =
        this.unescapeHTML(document.getElementById(id).innerHTML);
    this.refocusInput();
}

Console.prototype.processInput = function () {
    var codearea = document.getElementById(this.inputId);
    var code = codearea.value.replace(/^\s*|\s*$/g,'');
    if (code) {
	var result;
	var haveError = false;
	try {
	    result = eval(code);
	} catch (e) {
	    haveError = true;
	    result = e;
	}
	if (haveError) {
	    this.recordError(code, result);
	} else {
	    this.recordOutput(code, result);
	}
    }
    this.refocusInput();
}

Console.prototype.clearOutput = function () {
    document.getElementById(this.outputId).innerHTML = "";
    this.refocusInput();
}

Console.prototype.buildView = function () {
    var evalButtonId = this.containerId + "_evalButton";
    var clearButtonId = this.containerId + "_clearButton";

    var h = '<div style="margin-bottom: 0.5em">' +
    '<textarea id="'+this.inputId+'" rows="6" cols="70"></textarea><br>' +
    '<p>(Shortcut key: press ALT+P (on Windows or Linux) or CTRL+P (on Macintosh) to evaluate.</p>' +
    '<input id="'+evalButtonId+'" accesskey="p" type="submit" value="Evaluate">' +
    '<input id="'+clearButtonId+'" type="submit" value="Clear">' +
    '</div>' +
    '<div id="'+this.outputId+'"></div>';

    document.getElementById(this.containerId).innerHTML = h;

    var thisConsole = this;
    document.getElementById(evalButtonId).onclick = function () { thisConsole.processInput() };
    document.getElementById(clearButtonId).onclick = function () { thisConsole.clearOutput() };
}

Console.prototype.hide = function () {
    document.getElementById(this.containerId).style.display = "none";
}

Console.prototype.show = function () {
    document.getElementById(this.containerId).style.display = "block";
}
// -*- java -*-
// ==UserScript==
// @name           Embedded Console
// @namespace      http://eighty-twenty.org/embedded-js-console
// @description    
// @include        *
// ==/UserScript==

var EmbeddedConsole = null;
function setupEmbeddedConsole() {
    var n = document.createElement("div");
    n.id = "__embeddedConsole__user__js__";
    document.body.appendChild(n);
    EmbeddedConsole = new Console("__embeddedConsole__user__js__");
}

setupEmbeddedConsole();

