xp-consoles/console.js

159 lines
5.1 KiB
JavaScript

window.console = {};
window.onload = function () {
var output = document.getElementById("output");
var input = document.getElementById("input");
var runButton = document.getElementById("runbutton");
var clearButton = document.getElementById("clearbutton");
if (!String.prototype.trim) {
var _r = /(^\s+|\s+$)/g;
String.prototype.trim = function () {
return this.replace(_r, '');
}
}
function removeCarriageReturns (value) {
return value.replace(/\r/g, '');
}
function getSelectedText (element) {
if (typeof element.selectionStart === 'number' && typeof element.selectionEnd === 'number') {
return element.value.substring(element.selectionStart, element.selectionEnd);
}
var range = document.selection.createRange();
if (!range || range.parentElement() !== element) return '';
var normalizedValue = removeCarriageReturns(element.value);
var inputRange = element.createTextRange();
inputRange.moveToBookmark(range.getBookmark());
var endRange = element.createTextRange();
endRange.collapse(false);
// Selection begins at the end of the input, so it's empty
if (inputRange.compareEndPoints('StartToEnd', endRange) > -1) return '';
var start = -inputRange.moveStart('character', -element.value.length);
start += normalizedValue.slice(0, start).split('\n').length - 1;
var end = element.value.length;
if (inputRange.compareEndPoints('EndToEnd', endRange) < 0) {
end = -inputRange.moveEnd('character', -element.value.length);
end += normalizedValue.slice(0, end).split('\n').length - 1;
}
return element.value.substring(start, end)
}
// Try to output something cleanly as a string despite IE's disagreement.
// TODO: Cool object output and errors with stack traces?
function tryString (value) {
try {
if (value instanceof Error && value.message) return removeCarriageReturns(value.message);
return removeCarriageReturns(new String(value).toString());
} catch (err) {
// Give up, just print the type.
return '[' + typeof value + ']';
}
}
function makeLogger (color) {
return function () {
var entry = document.createElement('div');
entry.style.margin = '0';
entry.style.padding = '1px';
entry.style.borderBottom = '1px solid lightgray';
if (color) entry.style.color = color;
var outputText = '';
for (var i = 0; i < arguments.length; i++) {
outputText += tryString(arguments[i]);
if (i + 1 !== arguments.length) outputText += ' ';
}
entry.appendChild(document.createTextNode(outputText));
output.appendChild(entry);
}
}
console.log = makeLogger();
console.debug = makeLogger('darkgray');
console.info = makeLogger();
console.warn = makeLogger('orange');
console.error = makeLogger('red');
console.assert = function (assertion) {
if (assertion) return;
var argArray = Array.prototype.slice.call(arguments);
argArray.shift();
console.error.apply(null, argArray);
}
console.trace = function () {
var current = arguments.callee.caller;
var stack = 'console.trace(): \n ';
while (current) {
try {
var funcString = current.toString();
funcString = funcString.substring(funcString.indexOf('function') + 8);
stack += funcString.substring(0, funcString.indexOf('(')).trim() || 'anonymous';
} catch (err) {
stack += 'unknown function';
}
stack += '\n ';
current = current.caller;
}
console.log(stack.trim())
}
var inputLogger = makeLogger('lightBlue');
function run () {
var selected = getSelectedText(input);
var code = selected ? selected : input.value;
if (!code.trim()) return;
inputLogger(code);
try {
console.log(tryString(eval(code)));
} catch (err) {
console.error(err);
}
}
console.clear = function () {
output.innerHTML = "";
}
input.onkeypress = function (event) {
// Run code if Shift+Enter is pressed
if (event && event.keyCode === 13 && event.shiftKey) {
event.preventDefault();
run();
}
}
runButton.onclick = run;
clearButton.onclick = console.clear;
// Try to detect the wizard extensions.
if (typeof window.external === 'object' && typeof window.external.SetWizardButtons === 'unknown') {
window.external.SetHeaderText('JavaScript Console', "Explore this wizard's JavaScript environment.");
// Enable the back button
window.external.SetWizardButtons(1, 0, 0);
}
if (/MSIE 7.0/.test(navigator.userAgent)) {
/*
* For some reason, IE 7 messes up the textarea's width and height
* pretty badly. We hardcode the height, removing a little margin,
* and add some margin to the output.
* Setting the input's width causes it to somehow divide itself by 2
* on every keystroke.
*/
input.style.height = document.documentElement.clientHeight - 7 + 'px';
output.style.marginLeft = '7px';
}
}
// An onback function is required by the web wizard specification
window.onback = function () {
window.external.FinalBack();
}