function JSEval (code) { try { return eval(code); } catch (err) { console.error(err); } } function supportsVB () { return typeof window.VBSEval === 'unknown' && typeof window.VBSExecute === 'unknown' } 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 + ']'; } } var originalConsole = window.console; 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 (/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'; } 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. if (supportsVB() && InWebWizard()) { 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(); } }