xp-consoles/console.js

234 lines
7.5 KiB
JavaScript

function JSEval (code) {
try {
return eval(code);
} catch (err) {
console.error(err);
}
}
function supportsVB () {
return typeof window.VBSEval === 'unknown' && typeof window.VBSExecute === 'unknown'
}
function hasWebWizardExtensions () {
if (typeof window.external !== 'unknown') return false
return supportsVB() ? InWebWizard() : typeof window.external.SetWizardButtons === 'unknown'
}
function inSketchUp () {
return /\bSketchUp\//.test(navigator.userAgent)
}
var originalConsole = window.console;
window.onload = function () {
var output = document.getElementById("output");
var input = document.getElementById("input");
var languageSelect = document.getElementById("languageselect");
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 {
return removeCarriageReturns(new String(value).toString());
} catch (err) {
// Give up, just print the type.
return '[' + typeof value + ']';
}
}
window.console = {};
function makeLogger (name, color) {
return function () {
if (originalConsole && originalConsole[name] && originalConsole[name].apply) originalConsole[name].apply(originalConsole, arguments);
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);
entry.scrollIntoView();
}
}
console.log = makeLogger('log');
console.debug = makeLogger('debug', 'darkgray');
console.info = makeLogger('info');
console.warn = makeLogger('warn', 'orange');
console.error = makeLogger('error', '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());
}
console.clear = function () {
if (originalConsole && originalConsole.clear) {
if (originalConsole.clear.apply) originalConsole.clear.apply(originalConsole, arguments);
else originalConsole.clear();
}
output.innerHTML = "";
}
var inputLogger = makeLogger('log', 'lightblue');
function run () {
var code = getSelectedText(input) || input.value;
if (!code.trim()) return;
inputLogger(code);
try {
switch (languageSelect.value) {
case 'js':
result = JSEval(code);
break;
case 'vbs-eval':
result = VBSEval(code);
break;
case 'vbs-execute':
result = VBSExecute(code);
break;
default:
console.error('Unsupported language', languageSelect.value);
return;
}
console.log(result);
} catch (err) {
console.error(err);
}
}
input.onkeypress = function (event) {
if (!event) event = window.event;
// Run code if Shift+Enter is pressed
if (event && event.keyCode === 13 && event.shiftKey) {
event.cancelBubble = true;
event.returnValue = false;
if (event.stopPropagation) event.stopPropagation();
if (event.preventDefault) event.preventDefault();
run();
}
}
languageSelect.onchange = function () {
switch (languageSelect.value) {
case 'js':
languageSelect.setAttribute('placeholder', 'Type some JavaScript to run and press Shift+Enter');
break;
case 'vbs-eval':
languageSelect.setAttribute('placeholder', 'Type a VBScript expression to evaluate and press Shift+Enter');
break;
case 'vbs-execute':
languageSelect.setAttribute('placeholder', 'Type some VBScript to run and press Shift+Enter');
break;
default:
languageSelect.setAttribute('placeholder', 'Type the name of a demonic entity to summon and press Shift+Enter');
break;
}
}
runButton.onclick = run;
clearButton.onclick = console.clear;
if (!supportsVB()) {
for (var i = 0; i < languageSelect.children.length; i++) {
if (languageSelect.children[i].value.slice(0, 3) === 'vbs') {
languageSelect.children[i].disabled = true;
languageSelect.children[i].title = 'VBScript is not supported in this browser.';
}
}
}
}
// Try to detect the wizard extensions.
try {
if (hasWebWizardExtensions()) {
window.external.SetHeaderText('Windows Scripting Console', "Explore this wizard's scripting environment.");
window.external.SetWizardButtons(1, 0, 0);
// An onback function is required by the web wizard specification
window.onback = function () {
window.external.FinalBack();
}
}
} catch (err) {
/*
* In some browser contexts, such as IE7 embedded in the Compiled HTML viewer,
* interactions with window.external can cause "Not implemented" errors;
* if any of those occur, we ignore them.
* We cannot filter the errors to specifically ignore "Not implemented",
* because the error text gets translated to other languages
* ("Non implémenté" in French) and there are no other attributes to compare on.
*/
if (originalConsole && originalConsole.error) {
originalConsole.error('Could not setup Web Wizard extensions:', err)
}
}