????
Current Path : C:/Windows/SystemApps/Microsoft.Windows.CloudExperienceHost_cw5n1h2txyewy/js/ |
Current File : C:/Windows/SystemApps/Microsoft.Windows.CloudExperienceHost_cw5n1h2txyewy/js/jsConsole.js |
window.DebugJS = window.DebugJS || {}; function DebugJSConsole() { this._registers = []; this._pendingOutput = []; this._pendingOutputTimer = null; this._createUI(); this._catchErrors(); this._loadCommandHistory(); this._eval = eval; var that = this; function interceptKey(ev) { if (that._isVisible() && !ev.key.match("F\\d")) { ev.stopPropagation(); ev.stopImmediatePropagation(); return true; } return false; } window.addEventListener("keydown", function (ev) { if (ev.keyCode === 74 && ev.shiftKey && ev.ctrlKey) { ev.preventDefault(); that._toggleLayerVisibility(); } else if (interceptKey(ev)) { var controlKeys = [ "ArrowUp", "Up", "ArrowDown", "Down", "PageUp", "PageDown", "Home", "End" ]; if (controlKeys.indexOf(ev.key) === -1 && !ev.ctrlKey && !ev.altKey) { that._textInputElement.focus(); } if (ev.key === "Esc" || ev.key === "Escape") { that._toggleLayerVisibility(); } if (document.activeElement === that._textInputElement) { that._onTextInput(ev); } } }, true); window.addEventListener("keyup", interceptKey, true); window.addEventListener("keypress", interceptKey, true); this._textInputFlipElement.addEventListener("click", function () { if (that._isSingleLineMode()) { this.innerText = "<"; that._textInputElement.className = "debugConsoleMultiLine"; } else { this.innerText = ">"; that._textInputElement.className = "debugConsoleSingleLine"; } that._setCommand(that._textInputElement.value); that._textInputElement.focus(); }, false); } DebugJSConsole.prototype._onTextInput = function (ev) { this._textInputElement.scrollIntoView(); if (ev.key === "Enter" && (ev.ctrlKey || this._isSingleLineMode())) { ev.preventDefault(); var command = this._textInputElement.value.trim(); this._textInputElement.value = ""; if (command !== "") { this._appendText("", "> " + toSingleLine(command)); var index = -1; this._commandHistory.forEach(function (previousCommand, i) { if (toSingleLine(command) === toSingleLine(previousCommand)) { index = i; } }); if (index !== -1) { var other = this._commandHistory.splice(index, 1)[0]; if (this._isSingleLineMode()) { command = other; } } this._commandHistory.unshift(command); this._commandHistory.length = Math.min(this._commandHistory.length, 20); this._commandHistoryPosition = -1; this._saveCommandHistory(); this._eval( "with (DebugJS.console._getCommands()) {\n" + (this._safety ? " try {\n" : "") + " dump(stash(eval(" + JSON.stringify(command) + ")));\n" + (this._safety ? " } catch (ex) {\n" : "") + (this._safety ? " err(ex);\n" : "") + (this._safety ? " }\n" : "") + "}" ); this._textInputElement.scrollIntoView(); } } else if ((ev.key === "Up" || ev.key === "ArrowUp") && (ev.ctrlKey || this._isSingleLineMode())) { ev.preventDefault(); if (this._commandHistoryPosition < this._commandHistory.length - 1) { this._setCommand(this._commandHistory[++this._commandHistoryPosition]); } } else if ((ev.key === "Down" || ev.key === "ArrowDown") && (ev.ctrlKey || this._isSingleLineMode())) { ev.preventDefault(); if (this._commandHistoryPosition > 0) { this._setCommand(this._commandHistory[--this._commandHistoryPosition]); } else { this._commandHistoryPosition = -1; this._setCommand(""); } } else if (ev.key === "Tab") { ev.preventDefault(); this._tabComplete(); } }; function nub (sequence) { var members = {}; sequence.forEach(function (item) { this[item] = null; }, members); return Object.keys(members); } DebugJSConsole.prototype._tabComplete = function () { var cursorPosition = this._textInputElement.selectionStart, fullText = this._textInputElement.value, preCursorText = fullText.slice(0, cursorPosition), postCursorText = fullText.slice(cursorPosition); var match = preCursorText.match(/[^=\s\(\){}\+\-\*\/,;&|!"']+$/); if (match !== null && match.length === 1 && match[0] !== ".") { var candidate = match[0].trim(); var lastDot = candidate.lastIndexOf("."); var isGlobal = false; var realPart = ""; var queryPart = ""; if (lastDot === -1) { isGlobal = true; realPart = "window"; queryPart = candidate; } else { isGlobal = false; realPart = candidate.substr(0, lastDot); queryPart = candidate.substr(lastDot + 1); } var realValue = this._eval( "var __tabCompleteResult = null;" + "with (DebugJS.console._getCommands()) {" + " try {" + " __tabCompleteResult = eval(" + JSON.stringify(realPart) + ");" + " } catch (ex) { }" + "}" + "__tabCompleteResult;" ); var matchingFields = {}; for (var field in realValue) { if (field.substr(0, queryPart.length).toLowerCase() === queryPart.toLowerCase()) { matchingFields[field] = null; } } var matchingFieldsArray = Object.keys(matchingFields); var newQueryPart = null; if (matchingFieldsArray.length === 1) { newQueryPart = matchingFieldsArray[0]; } else if (matchingFieldsArray.length > 1) { matchingFields.toString = function () { return matchingFieldsArray.length.toString() + " matches"; }; var commonPrefix = matchingFieldsArray.reduce(function (prev, next) { var i = 0; for (var len = Math.min(prev.length, next.length); i < len; i++) { if (prev[i].toLowerCase() !== next[i].toLowerCase()) { break; } } return next.substring(0, i); }); var differentQuery = this._lastRealPart !== realPart || this._lastQuery.toLowerCase() !== queryPart.toLowerCase(); if (differentQuery) { this._appendTreeView(new DataTreeView(candidate + "*", realValue, matchingFields, ["toString"]), true); } else if (commonPrefix.length === queryPart.length) { var trimmedFields = nub(matchingFieldsArray.map(function (s) { return s.slice(0, queryPart.length); })); newQueryPart = trimmedFields[(trimmedFields.indexOf(queryPart) + 1) % trimmedFields.length]; } if (commonPrefix.length > queryPart.length) { var distance = function (s) { return Array.prototype.reduce.call(queryPart, function (total, c, i) { return (c === s[i] ? 0 : 1) + total; }, 0); }; newQueryPart = matchingFieldsArray.sort(function (a,b) { return distance(a) - distance(b); })[0].slice(0, commonPrefix.length); } } if (newQueryPart !== null) { var newPreCursorText = preCursorText.substr(0, match.index) + (isGlobal ? "" : (realPart + ".")) + newQueryPart; this._textInputElement.value = newPreCursorText + postCursorText; this._textInputElement.setSelectionRange(newPreCursorText.length, newPreCursorText.length); } this._lastQuery = newQueryPart !== null ? newQueryPart : queryPart; this._lastRealPart = realPart; } }; DebugJSConsole.prototype._createUI = function () { this._styleElement = document.createElement("style"); this._styleElement.id = "debugConsoleStyles"; this._styleElement.type = "text/css"; this._styleElement.innerText = DebugJSConsole.CSS; this._rootElement = createElement("div", "debugConsoleRoot", null); this._rootElement.innerHTML = "<div id=debugConsoleBackground>" + "<div id=debugConsoleLayer>" + "<div id=debugConsoleOutput></div>" + "<div>" + "<span id=debugConsoleInputFlip title='Click here to switch between single and multi-line input'>></span> " + "<textarea id=debugConsoleInput class=debugConsoleSingleLine></textarea>" + "</div>" + "</div>" + "</div>"; this._layerElement = this._rootElement.querySelector("#debugConsoleLayer"); this._outputElement = this._rootElement.querySelector("#debugConsoleOutput"); this._textInputElement = this._rootElement.querySelector("#debugConsoleInput"); this._textInputElement.spellcheck = false; this._lastQuery = ""; this._lastRealPart = ""; this._textInputFlipElement = this._rootElement.querySelector("#debugConsoleInputFlip"); }; DebugJSConsole.prototype.writeHTML = function (html) { var div = document.createElement("div"); div.innerHTML = html; this._appendOutput(div); }; DebugJSConsole.outputBufferLimit = 1000; DebugJSConsole.prototype._appendOutput = function (div, parentElement) { if (parentElement !== this._outputElement && parentElement !== undefined) { parentElement.appendChild(div); } else { this._pendingOutput.push(div); if (this._pendingOutput.length > DebugJSConsole.outputBufferLimit) { this._pendingOutput.shift(); } if (this._isVisible() && !this._pendingOutputTimer) { this._pendingOutputTimer = setTimeout(this._applyPendingOutput.bind(this), 250); } } }; DebugJSConsole.prototype._applyPendingOutput = function () { this._pendingOutputTimer = null; var parentElement = this._outputElement; var maintainScrollPosition = false; var stuckToBottom = false; var scrollTop; if (this._rootElement.parentNode !== null) { maintainScrollPosition = true; scrollTop = this._layerElement.scrollTop; var scrollHeight = this._layerElement.scrollHeight; var clientHeight = this._layerElement.clientHeight; stuckToBottom = (scrollHeight - scrollTop <= clientHeight + 10); } var pendingOutput = this._pendingOutput; this._pendingOutput = []; pendingOutput.forEach(function (div) { parentElement.appendChild(div); }); var newHeight; if (maintainScrollPosition && !stuckToBottom) { newHeight = this._layerElement.scrollHeight; } for (var excess = parentElement.childNodes.length - DebugJSConsole.outputBufferLimit; excess > 0; excess--) { parentElement.removeChild(parentElement.firstChild); } if (stuckToBottom) { this._layerElement.scrollTop = this._layerElement.scrollHeight - this._layerElement.clientHeight; } else if (maintainScrollPosition) { this._layerElement.scrollTop = scrollTop - (newHeight - this._layerElement.scrollHeight); } }; DebugJSConsole.prototype._clearOutput = function () { this._outputElement.innerHTML = ""; }; DebugJSConsole.prototype._appendText = function (className, text, parentElement) { this._appendOutput(createElement("div", className, text), parentElement); }; DebugJSConsole.prototype._appendData = function (label, data, shouldExpand) { this._appendTreeView(new DataTreeView(label, data, data, []), shouldExpand); }; DebugJSConsole.prototype._appendHTML = function (node, shouldExpand) { this._appendTreeView(new HtmlTreeView(node), shouldExpand); }; DebugJSConsole.prototype._appendCSS = function (element) { this._appendTreeView(new CssTraceTreeView(element), true); }; DebugJSConsole.prototype._appendSheet = function (sheet, shouldExpand) { this._appendTreeView(new CssTreeView(sheet), shouldExpand); }; DebugJSConsole.prototype._appendRule = function (rule, shouldExpand) { this._appendTreeView(new CssRuleTreeView(rule, null), shouldExpand); }; DebugJSConsole.prototype._appendStyle = function (style, shouldExpand) { this._appendTreeView(new CssStyleTreeView(style, null), shouldExpand); }; DebugJSConsole.prototype._appendTreeView = function (treeView, shouldExpand, parentElement) { var canExpand = treeView.length > 0; if (treeView.isExpanded === undefined) { treeView.isExpanded = canExpand && shouldExpand && treeView.length <= 20; } var div = createElement("div", "debugConsoleOutputText", null); var expanderRegion = createElement("span", "debugConsolePropertyName", null, div); var expanderElement = createElement("span", "debugConsolePropertyExpander debugConsoleOutputText", "+", expanderRegion); if (treeView.label) { createElement("span", null, treeView.label + ": ", expanderRegion); } var valueElement = createElement("span", null, treeView.value, div); if (treeView.html) { valueElement.innerHTML = treeView.html.outerHTML; } else if (treeView.className) { valueElement.className = treeView.className; } var that = this; var register = createElement("span", "debugConsoleRegister", (treeView.label !== "prototype") ? this._getRegisterName(treeView.register) : null, valueElement); valueElement.addEventListener("click", function (ev) { that._toggleRegister(treeView.register); }, false); register.onRegisterChange = function (registerValue, registerName) { if (registerValue === treeView.register && treeView.label !== "prototype") { this.innerText = registerName; } }; var detailsElement = createElement("div", "debugConsoleObjectProperties", null, div); if (canExpand) { expanderRegion.addEventListener("click", function (ev) { if (detailsElement.innerHTML !== "") { detailsElement.innerHTML = ""; expanderElement.innerText = "+"; treeView.isExpanded = false; } else { expanderElement.innerText = "-"; that._expandTreeView(treeView, detailsElement); } }, false); if (treeView.isExpanded) { expanderElement.innerText = "-"; that._expandTreeView(treeView, detailsElement); } } else { expanderElement.style.visibility = "hidden"; } this._appendOutput(div, parentElement); }; DebugJSConsole.prototype._expandTreeView = function (treeView, detailsElement) { if (treeView.children === undefined) { treeView.children = []; for (var i = 0, len = treeView.length; i < len; i++) { treeView.children.push(treeView.createChild(i)); } } treeView.isExpanded = true; treeView.children.forEach(function (child) { this._appendTreeView(child, false, detailsElement); }, this); }; function TreeView() { } TreeView.prototype.label = ""; TreeView.prototype.value = ""; TreeView.prototype.className = ""; TreeView.prototype.html = null; TreeView.prototype.register = null; TreeView.prototype.length = 0; TreeView.prototype.isExpanded = false; TreeView.prototype.children = []; TreeView.prototype.createChild = function (index) { return null; }; function DataTreeView(label, data, proto, excluded) { this.label = label; this._data = this.register = data; this.value = valueToString(proto); if (this.value) { var maxLength = 1000; this.value = this.value.trim(); if (label) { this.value = this.value.replace(/\s+/g, " "); maxLength = 100; } if (this.value.length > maxLength) { this.value = this.value.substr(0, maxLength) + "..."; } } this._fields = getProperties(proto, true, excluded).sort(function (a, b) { if ((typeof data[a] === "function") !== (typeof data[b] === "function")) { return (typeof data[a] === "function") ? 1 : -1; } var aAsNumber = Number(a); var bAsNumber = Number(b); var aIsNumber = aAsNumber !== null && !isNaN(aAsNumber); var bIsNumber = bAsNumber !== null && !isNaN(bAsNumber); if (aIsNumber && bIsNumber) { return aAsNumber - bAsNumber; } if (aIsNumber !== bIsNumber) { return aIsNumber ? 1 : -1; } if ((a[0] === "_") !== (b[0] === "_")) { return (a[0] === "_") ? 1 : -1; } return a.localeCompare(b); }); if (typeof data === "function" && !isEmpty(data.prototype, [])) { this._prototype = { data: data.prototype, proto: data.prototype, excluded: [] }; this._fields.splice(0, 0, this._prototype); } else if (!isEmpty(proto, excluded)) { var nextPrototype = Object.getPrototypeOf(proto); var nextExcluded = excluded.concat(this._fields); if (!isEmpty(nextPrototype, nextExcluded)) { this._prototype = { data: data, proto: nextPrototype, excluded: nextExcluded }; this._fields.splice(0, 0, this._prototype); } } this.length = this._fields.length; } DataTreeView.prototype.createChild = function (index) { if (this._prototype !== undefined && index === 0) { return new DataTreeView("prototype", this._prototype.data, this._prototype.proto, this._prototype.excluded); } else { var field = this._fields[index], value, className; try { value = this._data[field]; className = "debugConsoleOutputText"; } catch (ex) { value = ex; className = "debugConsoleErrorText"; } var treeView = new DataTreeView(field, value, value, []); treeView.className = className; return treeView; } }; function HtmlTreeView(node) { var i, len; this._element = this.register = node; if (instanceOf(node, HTMLStyleElement)) { var style = node; this._displayable = style.sheet.cssRules; } else if (instanceOf(node, HTMLLinkElement) && node.type === "text/css") { var link = node; this._displayable = link.sheet.cssRules; } else { this._displayable = []; for (i = 0, len = node.childNodes.length; i < len; i++) { if (isDisplayableHtmlNode(node.childNodes[i])) { this._displayable.push(node.childNodes[i]); } } } this.length = this._displayable.length; if (node.nodeType === Node.TEXT_NODE) { this.className = "debugConsoleHtmlText"; var textNode = node; this.value = toSingleLine(textNode.textContent.trim()); } else if (node.nodeType === Node.COMMENT_NODE) { this.className = "debugConsoleHtmlComment"; this.value = toSingleLine(node.text); } else { var htmlNode = node; this.html = createElement("span", null, null); createElement("span", "debugConsoleHtmlBracket", "<", this.html); createElement("span", "debugConsolePropertyName", htmlNode.nodeName.toLowerCase(), this.html); if (htmlNode.id) { this._appendHtmlAttribute("id", htmlNode.id); } if (htmlNode.className) { this._appendHtmlAttribute("class", htmlNode.className); } for (i = 0, len = htmlNode.attributes.length; i < len; i++) { var attribute = htmlNode.attributes[i]; if (attribute.name !== "id" && attribute.name !== "class") { this._appendHtmlAttribute(attribute.name, attribute.value); } } createElement("span", "debugConsoleHtmlBracket", ">", this.html); } } HtmlTreeView.prototype.createChild = function (index) { var child = this._displayable[index]; if (instanceOf(child, CSSRule)) { return new CssRuleTreeView(this._displayable[index]); } else { return new HtmlTreeView(this._displayable[index]); } }; HtmlTreeView.prototype._appendHtmlAttribute = function (attrName, attrValue) { createElement("span", null, " ", this.html); createElement("span", "debugConsoleHtmlAttrName", attrName, this.html); createElement("span", null, "=\"", this.html); createElement("span", "debugConsoleHtmlAttrValue", attrValue, this.html); createElement("span", null, "\"", this.html); }; function CssTraceTreeView(element) { this._element = element; this._matches = []; if (element.style.length > 0) { this._matches.push(new CssStyleTreeView(element.style, "<inline-styles>", element)); } Array.prototype.forEach.call(document.styleSheets, function (sheet) { this._addMatches(sheet.cssRules, element); }, this); this.label = "trace"; this.value = this.register = element; this.length = this._matches.length; } CssTraceTreeView.prototype._addMatches = function (rules, element, prefix) { Array.prototype.forEach.call(rules, function (rule) { if (rule.type === rule.MEDIA_RULE) { var mql = window.matchMedia ? window.matchMedia(rule.media) : window.msMatchMedia(rule.media); if (mql.matches) { this._addMatches(rule.cssRules, element, (prefix || "") + "@media (" + rule.media + ") "); } } else if (element.matches ? element.matches(rule.selectorText) : element.msMatchesSelector(rule.selectorText)) { this._matches.push(new CssRuleTreeView(rule, element, prefix)); } }, this); }; CssTraceTreeView.prototype.createChild = function (index) { return this._matches[index]; }; function CssTreeView(sheet) { if (sheet.href) { this.value = sheet.href; } else if (sheet.id) { this.value = sheet.id; } else if (sheet.title) { this.value = sheet.title; } this.register = this._sheet = sheet; this.label = "css"; this.length = sheet.cssRules.length; } CssTreeView.prototype.createChild = function (index) { return new CssRuleTreeView(this._sheet.cssRules[index]); }; function CssRuleTreeView(rule, match, prefix) { if (rule.type === rule.STYLE_RULE) { var styleTree = this._styleTree = new CssStyleTreeView(rule.style, rule.selectorText, match); this.value = (prefix || "") + styleTree.value; this.label = match ? "match" : "rule"; this.length = styleTree.length; } else if (rule.type === rule.IMPORT_RULE) { this.label = "@import"; this.value = rule.href; this.length = rule.styleSheet.cssRules.length; } else if (rule.type === rule.MEDIA_RULE) { this.label = "@media"; this.value = rule.media; this.length = rule.cssRules.length; } else { this.label = "rule"; this.value = rule.cssText; this.length = 0; } this._rule = this.register = rule; this._match = match; } CssRuleTreeView.prototype.createChild = function (index) { var styleTree = this._styleTree; if (styleTree) { return styleTree.createChild(index); } var rule = this._rule; if (rule.type === rule.IMPORT_RULE) { return new CssRuleTreeView(rule.styleSheet.cssRules[index], this._match); } if (rule.type === rule.MEDIA_RULE) { return new CssRuleTreeView(rule.cssRules[index], this._match); } return null; }; function CssStyleTreeView(style, value, match) { this._style = this.register = style; this._match = match; this.label = "style"; this.value = value; this._children = []; for (var i = 0, len = style.length; i < len; i++) { if (this.cssIgnoreName[style[i]] === undefined) { var parts = style[i].split("-"); if (/^-ms-/.test(style[i])) { parts.splice(0, 3, "-ms-" + parts[2]); } this._insertChild(parts); } } this.length = this._children.length; } CssStyleTreeView.prototype._insertChild = function (parts) { for (var i = 0, len = this._children.length; i < len; i++) { if (this._children[i].insert(parts)) { return; } } this._children.push(new CssPropertyTreeView(this._style, null, parts, this._match)); }; CssStyleTreeView.prototype.createChild = function (index) { return this._children[index].getLeaf(); }; CssStyleTreeView.prototype.cssIgnoreName = {}; CssStyleTreeView.prototype.cssIgnoreName["-ms-text-size-adjust"] = true; function CssPropertyTreeView(style, base, remaining, match) { this._style = style; this._match = match; this.part = remaining.splice(0, 1)[0]; this.label = base ? base + "-" + this.part : this.part; this._children = []; if (remaining.length > 0) { this._children.push(new CssPropertyTreeView(style, this.label, remaining, match)); } var indexer = this.cssFixedName[this.label]; if (!indexer) { indexer = this.label.replace(/^-ms/, "ms"); indexer = indexer.replace(/-\w/g, function (m) { return m[1].toUpperCase(); }); } this.value = this._style[indexer]; if (this.value === undefined) { indexer = indexer.replace(/^ms\w/, function (m) { return m[2].toLowerCase(); }); this.value = this._style[indexer]; } if (this.value !== undefined) { this.register = this.value; if (this._match && this._match.currentStyle && !areCssValuesEqual(this.value, this._match.currentStyle[indexer])) { this.html = createElement("span", "debugConsoleCssOverriden", null); createElement("span", "debugConsoleOutputText", this.value, this.html); } } } CssPropertyTreeView.prototype.createChild = function (index) { return this._children[index].getLeaf(); }; Object.defineProperty(CssPropertyTreeView.prototype, "length", { get: function () { return this._children.length; }}); CssPropertyTreeView.prototype.insert = function (parts) { if (this.part === parts[0]) { parts.splice(0, 1); if (parts.length > 0) { for (var i = 0, len = this._children.length; i < len; i++) { if (this._children[i].insert(parts)) { return true; } } this._children.push(new CssPropertyTreeView(this._style, this.label, parts, this._match)); } return true; } else { return false; } }; CssPropertyTreeView.prototype.getLeaf = function () { if (this._children.length === 1) { return this._children[0].getLeaf(); } else { return this; } }; CssPropertyTreeView.prototype.cssFixedName = { "-ms-scrollbar-3dlight-color": "scrollbar3dLightColor", "scrollbar-3dlight-color": "scrollbar3dLightColor", "-ms-scrollbar-darkshadow-color": "scrollbarDarkShadowColor", "scrollbar-darkshadow-color": "scrollbarDarkShadowColor", "-ms-transform-origin-x": "msTransformOrigin", "-ms-transform-origin-y": "msTransformOrigin" }; function ElementEvents(callback, context) { var domEvents = {}, body = document.body, selection = body, border = 2, root = createElement("div", "debugConsoleRoot", null, body), overlayLeft = createElement("div", "debugConsoleVerticalOverlay", null, root).style, overlayRight = createElement("div", "debugConsoleVerticalOverlay", null, root).style, overlayTop = createElement("div", "debugConsoleHorizontalOverlay", null, root).style, overlayBottom = createElement("div", "debugConsoleHorizontalOverlay", null, root).style; overlayLeft.width = overlayRight.width = overlayTop.height = overlayBottom.height = String(border) + "px"; function restoreConsole() { for (var evName in domEvents) { document.removeEventListener(evName, domEvents[evName], true); } body.removeChild(root); callback.call(context, selection); } function positionOverlay() { var rect = selection.getBoundingClientRect(), offsetLeft = rect.left + body.scrollLeft - body.clientLeft, offsetTop = rect.top + body.scrollTop - body.clientTop, selectionWidth = selection.offsetWidth, selectionHeight = selection.offsetHeight; overlayLeft.left = overlayTop.left = overlayBottom.left = String(offsetLeft) + "px"; overlayRight.left = String(offsetLeft + selectionWidth - border) + "px"; overlayLeft.top = overlayRight.top = overlayTop.top = String(offsetTop) + "px"; overlayBottom.top = String(offsetTop + selectionHeight - border) + "px"; overlayLeft.height = overlayRight.height = String(selectionHeight) + "px"; overlayTop.width = overlayBottom.width = String(selectionWidth) + "px"; } domEvents.mousemove = function (ev) { var target = document.elementFromPoint(ev.clientX, ev.clientY); if (/^debugConsole/.test(target.className)) { return; } if (target !== selection) { selection = target; positionOverlay(); } }; domEvents.click = function (ev) { ev.preventDefault(); ev.stopPropagation(); restoreConsole(); }; domEvents.keydown = function (ev) { if (ev.keyCode === 192 && ev.shiftKey) { restoreConsole(); } if (ev.key === "Esc" || ev.key === "Escape") { ev.preventDefault(); ev.stopPropagation(); selection = null; restoreConsole(); } }; for (var eventName in domEvents) { document.addEventListener(eventName, domEvents[eventName], true); } positionOverlay(); } DebugJSConsole.prototype.stashHtml = function (element) { this._rootElement.style.display = ""; if (element) { this._toggleRegister(element); this._appendHTML(element, true); } this._textInputElement.focus(); }; DebugJSConsole.prototype._selectHtml = function () { this._rootElement.style.display = "none"; new ElementEvents(this.stashHtml, this); }; DebugJSConsole.prototype.log = function (level, text) { var secondsSinceStart = (Date.now() - this._startTime) / 1000; var messageStyle; switch (level) { case "error": messageStyle = "debugConsoleErrorText"; break; case "warning": messageStyle = "debugConsoleWarningText"; break; default: messageStyle = "debugConsoleLogText"; break; } this._appendText(messageStyle, "Log@" + secondsSinceStart.toFixed(3) + ": " + text); }; DebugJSConsole.prototype._isVisible = function () { return (this._rootElement.parentNode !== null); }; DebugJSConsole.prototype._toggleLayerVisibility = function () { if (!this._isVisible()) { if (this._styleElement.parentNode === null) { document.getElementsByTagName("head")[0].appendChild(this._styleElement); } this._applyPendingOutput(); document.body.appendChild(this._rootElement); this._textInputElement.focus(); } else { document.body.removeChild(this._rootElement); clearTimeout(this._pendingOutputTimer); this._pendingOutputTimer = null; } }; DebugJSConsole.prototype._catchErrors = function () { var that = this; window.onerror = function (msg, file, line) { that._appendText("debugConsoleExceptionText", "Unhandled exception: " + msg + "\n file: " + file + "\n line: " + line); return false; }; }; DebugJSConsole.prototype._loadCommandHistory = function () { this._commandHistory = DebugJS.getCookie("consoleCommandHistory", []); }; DebugJSConsole.prototype._saveCommandHistory = function () { DebugJS.setCookie("consoleCommandHistory", this._commandHistory); }; DebugJSConsole.prototype._setCommand = function (value) { if (this._isSingleLineMode()) { value = toSingleLine(value); } else if (this._commandHistoryPosition >= 0 && this._commandHistoryPosition < this._commandHistory.length && toSingleLine(this._textInputElement.value) === toSingleLine(this._commandHistory[this._commandHistoryPosition])) { value = this._commandHistory[this._commandHistoryPosition]; } this._textInputElement.value = value; }; DebugJSConsole.prototype._isSingleLineMode = function () { return (this._textInputElement.className.split(" ").indexOf("debugConsoleSingleLine") !== -1); }; DebugJSConsole.prototype._setSafety = function (enableSafety) { this._safety = enableSafety; this._appendText("debugConsoleOutputText", "Safety " + (enableSafety ? "enabled" : "disabled")); }; DebugJSConsole.prototype._stash = function (value) { this._registers[0] = value; }; DebugJSConsole.prototype._toggleRegister = function (value) { for (var i = 1, len = this._registers.length; i < len; i++) { if (this._registers[i] === value) { delete this._registers[i]; this._updateRegisterElements(value, ""); return; } } for (i = 1, len = this._registers.length; i < len; i++) { if (this._registers[i] === undefined) { break; } } this._registers[i] = value; this._updateRegisterElements(value, "$" + i.toString()); }; DebugJSConsole.prototype._getRegisterName = function (value) { var registerName = ""; if (value !== undefined) { var registerIndex = this._registers.indexOf(value, 1); if (registerIndex !== -1) { registerName = "$" + registerIndex.toString(); } } return registerName; }; DebugJSConsole.prototype._updateRegisterElements = function (value, registerName) { var registerElements = document.querySelectorAll(".debugConsoleRegister"); for (var i = 0, len = registerElements.length; i < len; i++) { registerElements[i].onRegisterChange(value, registerName); } }; DebugJSConsole.prototype._loadScriptFile = function (path) { var scriptElement = document.createElement("script"); var that = this; scriptElement.onload = function () { that._appendText("debugConsoleOutputText", "Script file loaded: " + path); }; scriptElement.onerror = function () { that._appendText("debugConsoleErrorText", "Error loading script file: " + path); }; scriptElement.type = "text/javascript"; scriptElement.src = path; document.getElementsByTagName("head")[0].appendChild(scriptElement); }; DebugJSConsole.prototype._getCommands = function () { return new ConsoleCommands(this, this._registers); }; DebugJSConsole.prototype._startTime = Date.now(); DebugJSConsole.prototype._styleElement = null; DebugJSConsole.prototype._rootElement = null; DebugJSConsole.prototype._layerElement = null; DebugJSConsole.prototype._outputElement = null; DebugJSConsole.prototype._textInputElement = null; DebugJSConsole.prototype._textInputFlipElement = null; DebugJSConsole.prototype._commandHistory = null; DebugJSConsole.prototype._commandHistoryPosition = -1; DebugJSConsole.prototype._safety = true; function ConsoleCommands(debugConsole, registers) { this._console = debugConsole; for (var i = 0, len = registers.length; i < len; i++) { Object.defineProperty(this, "$" + i.toString(), { value: registers[i] }); } } ConsoleCommands.prototype.clip = function (text) { window.clipboardData.setData("Text", text); }; ConsoleCommands.prototype.dump = function (data, label) { if (data !== undefined || label !== undefined) { this._console._appendData(label, data, true); } }; ConsoleCommands.prototype.log = function (data) { if (data !== undefined) { this._console._appendData(null, data, true); } }; ConsoleCommands.prototype.html = function (data) { if (data === undefined) { data = document.documentElement; } if (instanceOf(data, Node)) { this._console._appendHTML(data, true); } else { this.err("Not an HTML node"); } }; ConsoleCommands.prototype.css = function (data) { if (instanceOf(data, HTMLElement)) { this._console._appendCSS(data); } else if (instanceOf(data, CSSStyleDeclaration)) { this._console._appendStyle(data, true); } else if (instanceOf(data, CSSRule)) { this._console._appendRule(data, true); } else if (instanceOf(data, CSSStyleSheet)) { this._console._appendSheet(data, true); } else if (data === undefined) { Array.prototype.forEach.call(document.styleSheets, function (sheet) { if (sheet.id !== "debugConsoleStyles") { this._console._appendSheet(sheet, false); } }, this); } else { this.err("Not a valid object type"); } }; ConsoleCommands.prototype.err = function (msg) { this._console._appendText("debugConsoleErrorText", msg); }; ConsoleCommands.prototype.load = function (path) { this._console._loadScriptFile(path); }; ConsoleCommands.prototype.hook = function (source, eventName) { var that = this; function listener() { that.dump({source: source, eventName: eventName, args: arguments }, "Event fired"); } if (source) { if (source.addEventListener !== undefined) { source.addEventListener(eventName, listener, false); } else if (source.addListener !== undefined) { source.addListener(eventName, listener); } else if (source.on !== undefined) { source.on(eventName, listener); } } }; ConsoleCommands.prototype.promise = function (p) { var that = this; p.then( function () { that.dump({ promise: p, args: arguments }, "Promise complete"); }, function () { that.dump({ promise: p, args: arguments }, "Promise error"); }, function () { that.dump({ promise: p, args: arguments }, "Promise progress"); } ); }; ConsoleCommands.prototype.safety = function (enableSafety) { this._console._setSafety(enableSafety); }; Object.defineProperty(ConsoleCommands.prototype, "cls", { get: function () { this._console._clearOutput(); }}); Object.defineProperty(ConsoleCommands.prototype, "select", { get: function () { this._console._selectHtml(); }}); Object.defineProperty(ConsoleCommands.prototype, "help", { get: function () { this._console._appendText( "debugConsoleOutputText", "The console command-line accepts any javascript code and dumps the result.\n" + "Built-in commands:\n" + " cls - clears the output area\n" + " log(string) - outputs a string\n" + " clip(string) - copies the string to the clipboard\n" + " dump(obj [, label]) - dumps an object with an optional label\n" + " html([node]) - dumps the HTML tree, optionally rooted to a specific node\n" + " select - stash an HTML element by selecting it in the actual UI\n" + " css([element|sheet|rule|style]) - dumps CSS, optionally matching a provided object\n" + " hook(obj, event) - hooks an event on an object and dumps when it fires\n" + " promise(p) - listens to the complete/error/progress events on a promise\n" + " load(string) - loads the specified javascript file\n" + " safety(bool) - enables/disables catching errors thrown from console evaluation\n" + "\n" + "You can click the > next to the input area to toggle between single-line and multi-line input modes. The console supports a persistent command history, use the arrow keys (or Ctrl+arrow keys in multi-line mode) to repeat past commands.\n" + "\n" + "The result of the last evaluation is stored in a stash register. You can access with the $0 symbol. Clicking on any value in the output will store that value into a numbered register, like $1 or $2. All of these registers can be used anywhere in an expression. Note that a register is a value, not an alias to a property. If the property that the register was created from changes, the register will not.\n" + "\n" + "In depth usage instructions can be found at http://codebox/jsconsole" ); }}); ConsoleCommands.prototype.stash = function (value) { this._console._stash(value); return value; }; function getProperties(data, own, excluded) { var props = []; if (data) { var hasProps = false; if (typeof data === "function") { hasProps = true; Array.prototype.push.apply(excluded, Object.getOwnPropertyNames(Function)); } else if (typeof data === "object") { hasProps = true; } if (hasProps) { var proto = data; do { if (proto === Object.prototype || proto === Array.prototype || proto === Function.prototype) { break; } var prototypeProperties; try { prototypeProperties = Object.getOwnPropertyNames(proto); } catch (ex) { break; } for (var i = 0, len = prototypeProperties.length; i < len; i++) { var propertyName = prototypeProperties[i]; if (props.indexOf(propertyName) === -1 && excluded.indexOf(propertyName) === -1 && propertyName !== "constructor") { props.push(propertyName); } } proto = Object.getPrototypeOf(proto); } while (!own && proto); } } return props; } function isEmpty(data, excluded) { var empty = getProperties(data, false, excluded).length === 0; if (typeof data === "function") { empty = empty && isEmpty(data.prototype, []); } return empty; } var constructorCache = []; function getConstructorName(constructorFunction) { var constructorName; var cached = false; var len = constructorCache.length; for (var i = 0; i < len; ++i) { if (constructorCache[i].fn === constructorFunction) { cached = true; constructorName = constructorCache[i].name; break; } } if (!cached) { constructorName = DebugJS.scanTypes(function (testConstructorFunction, testConstructorName) { if (testConstructorFunction === constructorFunction) { return testConstructorName; } }); if (!constructorName) { var code = constructorFunction.toString(); if (code.substr(0, 9) === "function ") { var parenthesisIndex = code.indexOf("("); if (parenthesisIndex !== -1) { var possibleName = code.substr(9, parenthesisIndex - 9).trim(); if (possibleName.match(/^[\w$]+$/) !== null) { constructorName = possibleName; } } } } constructorCache.push({ fn: constructorFunction, name: constructorName }); } return constructorName; } function toSingleLine(value) { return value.replace(/(\/\/[^\r\n]*)|(\/\*(.|[\r\n])*\*\/)/g, "$2").replace(/\s*[\r\n]\s*/g, " "); } function valueToString(data, isRecursive) { var string = "{...}"; try { switch (typeof data) { case "undefined": case "string": string = JSON.stringify(data); break; case "number": case "boolean": string = data.toString(); break; default: if (data === null) { string = "null"; } else { if (Array.isArray(data)) { string = "length=" + data.length.toString(); if (data.length < 20 && !isRecursive) { string += " [" + data.map(function (item) { return valueToString(item, true); }).join(", ") + "]"; } } else { if (data.toString) { string = data.toString(); } else { string = "" + data; } } if (string === "[object Object]") { var constructorName = getConstructorName(data.constructor); if (constructorName) { string = "[object " + constructorName + "]"; } } if (data.name) { string = string + " " + data.name; } if (data._debugObjectName) { string = string + " " + data._debugObjectName; } if (data.id) { string = string + " #" + data.id; } if (data.className) { string = string + " " + data.className.trim().split(/\s+/).map(function (className) { return "." + className; }).join(" "); } if (data.objectId) { string = string + " " + data.objectId; } } break; } } catch (ex) { } return string; } function instanceOf(obj, proto) { return obj instanceof proto; } function isDisplayableHtmlNode(node) { switch (node.nodeType) { case Node.TEXT_NODE: case Node.COMMENT_NODE: var textNode = node; return textNode.textContent.trim().length > 0; } return true; } function createElement(nodeType, className, innerText, parentElement) { var element = document.createElement(nodeType); if (className) { element.className = className; } if (innerText) { element.innerText = innerText; } if (parentElement) { parentElement.appendChild(element); } return element; } function areCssValuesEqual(valueA, valueB) { if ((valueA + "").trim() === (valueB + "").trim()) { return true; } var aAsNumber = Number(valueA); var bAsNumber = Number(valueB); return aAsNumber !== null && !isNaN(aAsNumber) && aAsNumber === bAsNumber; } DebugJS.getCookie = function (valueName, defaultValue) { var result = defaultValue; try { document.cookie.split(";").forEach(function (cookie) { var split = cookie.split("="); var cookieName = split[0].trim(); if (cookieName === valueName) { result = JSON.parse(unescape(split[1])); } }); } catch (ex) { } return result; }; DebugJS.setCookie = function (valueName, value) { var date = new Date(); date.setFullYear(date.getFullYear() + 1); document.cookie = valueName + "=" + escape(JSON.stringify(value)) + "; expires=" + date.toUTCString(); }; DebugJS.scanTypes = function (fn, namespace, namespaceName, alreadyChecked, depth) { DebugJS.scanningTypes++; try { namespace = namespace || window; namespaceName = namespaceName || ""; alreadyChecked = alreadyChecked || [ window.Windows, window.Microsoft ]; depth = depth || 0; if (depth < 10 && alreadyChecked.length < 1000) { for (var field in namespace) { if ((field[0] >= "A" && field[0] <= "Z") || field[0] === "$") { try { var objectToCheck = namespace[field]; var isNamespace = typeof objectToCheck === "object" && objectToCheck !== null && objectToCheck.constructor === Object; var isFunction = typeof objectToCheck === "function" && objectToCheck !== Function; if ((isNamespace || isFunction) && alreadyChecked.indexOf(objectToCheck) === -1) { alreadyChecked.push(objectToCheck); var objectName = (namespaceName ? namespaceName + "." : "") + field; var result; if (isFunction) { result = fn(objectToCheck, objectName, namespace, field); } if (!result) { result = DebugJS.scanTypes(fn, objectToCheck, objectName, alreadyChecked, depth + 1); } if (result) { return result; } } } catch (ex) { } } } } } finally { DebugJS.scanningTypes--; } }; DebugJSConsole.CSS = ".debugConsoleRoot {" + "width:0;" + "height:0;" + "direction: ltr;" + "-ms-user-select: element;" + "cursor: text; " + "}" + "#debugConsoleBackground {" + "text-overflow:clip;" + "position:fixed;" + "top:0;" + "left:0;" + "width:100%;" + "height:100%;" + "z-index:2000;" + "background-color:rgba(0,0,0,0.8);" + "overflow:hidden;" + "}" + "#debugConsoleLayer {" + "width:98%;" + "height:100%;" + "padding:0 1%;" + "color:white;" + "font-family:'Segoe UI', 'Segoe UI Symbol';" + "font-size:10pt;" + "overflow-x:hidden;" + "overflow-y:scroll;" + "}" + "#debugConsoleOutput {" + "width:100%;" + "overflow-x: hidden;" + "white-space: nowrap;" + "}" + "#debugConsole div {" + "width:100%;" + "overflow:hidden;" + "}" + ".debugConsoleVerticalOverlay {" + "background-color:blue;" + "position:absolute;" + "z-index:100000;" + "}" + ".debugConsoleHorizontalOverlay {" + "background-color:blue;" + "position:absolute;" + "z-index:100000;" + "}" + ".debugConsoleLogText {" + "color:lightgreen;" + "font-style:italic;" + "}" + ".debugConsoleExceptionText {" + "color:red;" + "font-weight:bold;" + "}" + ".debugConsoleOutputText {" + "color:rgba(200,200,200,1);" + "}" + ".debugConsoleErrorText {" + "color:red;" + "}" + ".debugConsoleWarningText {" + "color:yellow;" + "}" + ".debugConsolePropertyExpander { " + "cursor:pointer;" + "margin-right:5px;" + "font-family:Consolas;" + "}" + ".debugConsolePropertyName {" + "color:rgba(200,100,200,1);" + "}" + ".debugConsoleObjectProperties {" + "margin-left:15px;" + "}" + "#debugConsoleInput {" + "font-family:inherit;" + "font-size:inherit;" + "border:none;" + "width:95%;" + "color:inherit;" + "padding:0px;" + "margin:0px;" + "}" + "#debugConsoleInput.debugConsoleSingleLine {" + "height: 1.5em;" + "overflow: hidden;" + "background:none;" + "}" + "#debugConsoleInput.debugConsoleMultiLine {" + "height: 10em;" + "overflow: auto;" + "background-color: rgba(0,0,0,0.4);" + "}" + "#debugConsoleInputFlip { " + "vertical-align:top;" + "cursor:pointer;" + "}" + ".debugConsoleRegister {" + "margin-left:5px;" + "color:cyan;" + "text-decoration:none;" + "}" + ".debugConsoleHtmlComment {" + "color:#d0d090;" + "font-style:italic;" + "}" + ".debugConsoleHtmlAttrName {" + "color:#b0d0f0;" + "}" + ".debugConsoleHtmlAttrValue {" + "color:#80c0e0;" + "}" + ".debugConsoleHtmlBracket {" + "color:#f0c0f0;" + "}" + ".debugConsoleHtmlText {" + "color:#d0d0d0;" + "font-style:italic;" + "}" + ".debugConsoleCssOverriden {" + "color:red;" + "text-decoration:line-through;" + "}" + "@media screen and (max-width:340px) {" + "#debugConsoleLayer {" + "font-size: 8pt" + "}" + "}"; DebugJS.console = new DebugJSConsole();