browser/metro/base/content/console.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/metro/base/content/console.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,352 @@
     1.4 +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +let ConsolePanelView = {
    1.10 +  _list: null,
    1.11 +  _inited: false,
    1.12 +  _evalTextbox: null,
    1.13 +  _evalFrame: null,
    1.14 +  _evalCode: "",
    1.15 +  _bundle: null,
    1.16 +  _showChromeErrors: -1,
    1.17 +  _enabledPref: "devtools.errorconsole.enabled",
    1.18 +
    1.19 +  get enabled() {
    1.20 +    return Services.prefs.getBoolPref(this._enabledPref);
    1.21 +  },
    1.22 +
    1.23 +  get follow() {
    1.24 +    return document.getElementById("console-follow-checkbox").checked;
    1.25 +  },
    1.26 +
    1.27 +  init: function cv_init() {
    1.28 +    if (this._list)
    1.29 +      return;
    1.30 +
    1.31 +    this._list = document.getElementById("console-box");
    1.32 +    this._evalTextbox = document.getElementById("console-eval-textbox");
    1.33 +    this._bundle = Strings.browser;
    1.34 +
    1.35 +    this._count = 0;
    1.36 +    this.limit = 250;
    1.37 +    this.fieldMaxLength = 140;
    1.38 +
    1.39 +    try {
    1.40 +      // update users using the legacy pref
    1.41 +      if (Services.prefs.getBoolPref("browser.console.showInPanel")) {
    1.42 +        Services.prefs.setBoolPref(this._enabledPref, true);
    1.43 +        Services.prefs.clearUserPref("browser.console.showInPanel");
    1.44 +      }
    1.45 +    } catch(ex) {
    1.46 +      // likely don't have an old pref
    1.47 +    }
    1.48 +    Services.prefs.addObserver(this._enabledPref, this, false);
    1.49 +  },
    1.50 +
    1.51 +  show: function show() {
    1.52 +    if (this._inited)
    1.53 +      return;
    1.54 +    this._inited = true;
    1.55 +
    1.56 +    this.init(); // In case the panel is selected before init has been called.
    1.57 +
    1.58 +    Services.console.registerListener(this);
    1.59 +
    1.60 +    this.appendInitialItems();
    1.61 +
    1.62 +    // Delay creation of the iframe for startup performance
    1.63 +    this._evalFrame = document.createElement("iframe");
    1.64 +    this._evalFrame.id = "console-evaluator";
    1.65 +    this._evalFrame.collapsed = true;
    1.66 +    document.getElementById("console-container").appendChild(this._evalFrame);
    1.67 +
    1.68 +    this._evalFrame.addEventListener("load", this.loadOrDisplayResult.bind(this), true);
    1.69 +  },
    1.70 +
    1.71 +  uninit: function cv_uninit() {
    1.72 +    if (this._inited)
    1.73 +      Services.console.unregisterListener(this);
    1.74 +
    1.75 +    Services.prefs.removeObserver(this._enabledPref, this, false);
    1.76 +  },
    1.77 +
    1.78 +  observe: function(aSubject, aTopic, aData) {
    1.79 +    if (aTopic == "nsPref:changed") {
    1.80 +      // We may choose to create a new menu in v2
    1.81 +      }
    1.82 +    else
    1.83 +      this.appendItem(aSubject);
    1.84 +  },
    1.85 +
    1.86 +  showChromeErrors: function() {
    1.87 +    if (this._showChromeErrors != -1)
    1.88 +      return this._showChromeErrors;
    1.89 +
    1.90 +    try {
    1.91 +      let pref = Services.prefs;
    1.92 +      return this._showChromeErrors = pref.getBoolPref("javascript.options.showInConsole");
    1.93 +    }
    1.94 +    catch(ex) {
    1.95 +      return this._showChromeErrors = false;
    1.96 +    }
    1.97 +  },
    1.98 +
    1.99 +  appendItem: function cv_appendItem(aObject) {
   1.100 +    let index = -1;
   1.101 +    try {
   1.102 +      // Try to QI it to a script error to get more info
   1.103 +      let scriptError = aObject.QueryInterface(Ci.nsIScriptError);
   1.104 +
   1.105 +      // filter chrome urls
   1.106 +      if (!this.showChromeErrors && scriptError.sourceName.substr(0, 9) == "chrome://")
   1.107 +        return;
   1.108 +      index = this.appendError(scriptError);
   1.109 +    }
   1.110 +    catch (ex) {
   1.111 +      try {
   1.112 +        // Try to QI it to a console message
   1.113 +        let msg = aObject.QueryInterface(Ci.nsIConsoleMessage);
   1.114 +
   1.115 +        if (msg.message)
   1.116 +          index = this.appendMessage(msg.message);
   1.117 +        else // observed a null/"clear" message
   1.118 +          this.clearConsole();
   1.119 +      }
   1.120 +      catch (ex2) {
   1.121 +        // Give up and append the object itself as a string
   1.122 +        index = this.appendMessage(aObject);
   1.123 +      }
   1.124 +    }
   1.125 +    if (this.follow) {
   1.126 +      this._list.ensureIndexIsVisible(index);
   1.127 +    }
   1.128 +  },
   1.129 +
   1.130 +  truncateIfNecessary: function (aString) {
   1.131 +    if (!aString || aString.length <= this.fieldMaxLength) {
   1.132 +      return aString;
   1.133 +    }
   1.134 +    let truncatedString = aString.substring(0, this.fieldMaxLength);
   1.135 +    let Ci = Components.interfaces;
   1.136 +    let ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
   1.137 +                                                  Ci.nsIPrefLocalizedString).data;
   1.138 +    truncatedString = truncatedString + ellipsis;
   1.139 +    return truncatedString;
   1.140 +  },
   1.141 +
   1.142 +  appendError: function cv_appendError(aObject) {
   1.143 +    let row = this.createConsoleRow();
   1.144 +    let nsIScriptError = Ci.nsIScriptError;
   1.145 +
   1.146 +    // Is this error actually just a non-fatal warning?
   1.147 +    let warning = aObject.flags & nsIScriptError.warningFlag != 0;
   1.148 +
   1.149 +    let typetext = warning ? "typeWarning" : "typeError";
   1.150 +    row.setAttribute("typetext", this._bundle.GetStringFromName(typetext));
   1.151 +    row.setAttribute("type", warning ? "warning" : "error");
   1.152 +    row.setAttribute("msg", aObject.errorMessage);
   1.153 +    row.setAttribute("category", aObject.category);
   1.154 +    if (aObject.lineNumber || aObject.sourceName) {
   1.155 +      row.setAttribute("href", aObject.sourceName);
   1.156 +      row.setAttribute("line", aObject.lineNumber);
   1.157 +    }
   1.158 +    else {
   1.159 +      row.setAttribute("hideSource", "true");
   1.160 +    }
   1.161 +    // hide code by default, otherwise initial item display will
   1.162 +    // hang the browser.
   1.163 +    row.setAttribute("hideCode", "true");
   1.164 +    row.setAttribute("hideCaret", "true");
   1.165 +
   1.166 +    if (aObject.sourceLine) {
   1.167 +      row.setAttribute("code", this.truncateIfNecessary(aObject.sourceLine.replace(/\s/g, " ")));
   1.168 +      if (aObject.columnNumber) {
   1.169 +        row.setAttribute("col", aObject.columnNumber);
   1.170 +      }
   1.171 +    }
   1.172 +
   1.173 +    let mode = document.getElementById("console-filter").value;
   1.174 +    if (mode != "all" && mode != row.getAttribute("type")) {
   1.175 +      row.collapsed = true;
   1.176 +    }
   1.177 +
   1.178 +    row.setAttribute("onclick", "ConsolePanelView.onRowClick(this)");
   1.179 +    this.appendConsoleRow(row);
   1.180 +    return this._list.getIndexOfItem(row);
   1.181 +  },
   1.182 +
   1.183 +  appendMessage: function cv_appendMessage (aMessage) {
   1.184 +    let row = this.createConsoleRow();
   1.185 +    row.setAttribute("type", "message");
   1.186 +    row.setAttribute("msg", aMessage);
   1.187 +
   1.188 +    let mode = document.getElementById("console-filter").value;
   1.189 +    if (mode != "all" && mode != "message")
   1.190 +      row.collapsed = true;
   1.191 +
   1.192 +    this.appendConsoleRow(row);
   1.193 +    return this._list.getIndexOfItem(row);
   1.194 +  },
   1.195 +
   1.196 +  createConsoleRow: function cv_createConsoleRow() {
   1.197 +    let row = document.createElement("richlistitem");
   1.198 +    row.setAttribute("class", "console-row");
   1.199 +    return row;
   1.200 +  },
   1.201 +
   1.202 +  appendConsoleRow: function cv_appendConsoleRow(aRow) {
   1.203 +    this._list.appendChild(aRow);
   1.204 +    if (++this._count > this.limit) {
   1.205 +      this.deleteFirst();
   1.206 +    }
   1.207 +  },
   1.208 +
   1.209 +  deleteFirst: function cv_deleteFirst() {
   1.210 +    let node = this._list.firstChild;
   1.211 +    this._list.removeChild(node);
   1.212 +    --this._count;
   1.213 +  },
   1.214 +
   1.215 +  appendInitialItems: function cv_appendInitialItems() {
   1.216 +    this._list.collapsed = true;
   1.217 +    let messages = Services.console.getMessageArray();
   1.218 +
   1.219 +    // In case getMessageArray returns 0-length array as null
   1.220 +    if (!messages)
   1.221 +      messages = [];
   1.222 +
   1.223 +    let limit = messages.length - this.limit;
   1.224 +    if (limit < 0)
   1.225 +      limit = 0;
   1.226 +
   1.227 +    // Checks if console ever been cleared
   1.228 +    for (var i = messages.length - 1; i >= limit; --i) {
   1.229 +      if (!messages[i].message) {
   1.230 +        break;
   1.231 +      }
   1.232 +    }
   1.233 +
   1.234 +    // Populate with messages after latest "clear"
   1.235 +    while (++i < messages.length) {
   1.236 +      this.appendItem(messages[i]);
   1.237 +    }
   1.238 +    this._list.collapsed = false;
   1.239 +  },
   1.240 +
   1.241 +  clearConsole: function cv_clearConsole() {
   1.242 +    if (this._count == 0) // already clear
   1.243 +      return;
   1.244 +    this._count = 0;
   1.245 +
   1.246 +    let newRows = this._list.cloneNode(false);
   1.247 +    this._list.parentNode.replaceChild(newRows, this._list);
   1.248 +    this._list = newRows;
   1.249 +    this.selectedItem = null;
   1.250 +  },
   1.251 +
   1.252 +  copyAll: function () {
   1.253 +    let mode = document.getElementById("console-filter").value;
   1.254 +    let rows = this._list.childNodes;
   1.255 +    let copyText = "";
   1.256 +    for (let i=0; i < rows.length; i++) {
   1.257 +      let row = rows[i];
   1.258 +      if (mode == "all" || row.getAttribute ("type") == mode) {
   1.259 +        let text = "* " + row.getAttribute("msg");
   1.260 +        if (row.hasAttribute("href")) {
   1.261 +          text += "\r\n " + row.getAttribute("href") + " line:" + row.getAttribute("line");
   1.262 +        }
   1.263 +        if (row.hasAttribute("code")) {
   1.264 +          text += "\r\n " + row.getAttribute("code") + " col:" + row.getAttribute("col");
   1.265 +        }
   1.266 +        copyText += text + "\r\n";
   1.267 +      }
   1.268 +    }
   1.269 +    let clip = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
   1.270 +    clip.copyString(copyText, document);
   1.271 +  },
   1.272 +
   1.273 +  changeMode: function cv_changeMode() {
   1.274 +    let mode = document.getElementById("console-filter").value;
   1.275 +    if (this._list.getAttribute("mode") != mode) {
   1.276 +      let rows = this._list.childNodes;
   1.277 +      for (let i=0; i < rows.length; i++) {
   1.278 +        let row = rows[i];
   1.279 +        if (mode == "all" || row.getAttribute ("type") == mode)
   1.280 +          row.collapsed = false;
   1.281 +        else
   1.282 +          row.collapsed = true;
   1.283 +      }
   1.284 +      this._list.mode = mode;
   1.285 +      this._list.scrollToIndex(0);
   1.286 +    }
   1.287 +  },
   1.288 +
   1.289 +  onContextMenu: function cv_onContextMenu(aEvent) {
   1.290 +    let row = aEvent.target;
   1.291 +    let text = ["msg", "href", "line", "code", "col"].map(function(attr) row.getAttribute(attr))
   1.292 +               .filter(function(x) x).join("\r\n");
   1.293 +
   1.294 +    ContextMenuUI.showContextMenu({
   1.295 +      target: row,
   1.296 +      json: {
   1.297 +        types: ["copy"],
   1.298 +        string: text,
   1.299 +        xPos: aEvent.clientX,
   1.300 +        yPos: aEvent.clientY
   1.301 +      }
   1.302 +    });
   1.303 +  },
   1.304 +
   1.305 +  onRowClick: function (aRow) {
   1.306 +    if (aRow.hasAttribute("code")) {
   1.307 +      aRow.setAttribute("hideCode", "false");
   1.308 +    }
   1.309 +    if (aRow.hasAttribute("col")) {
   1.310 +      aRow.setAttribute("hideCaret", "false");
   1.311 +    }
   1.312 +  },
   1.313 +
   1.314 +  onEvalKeyPress: function cv_onEvalKeyPress(aEvent) {
   1.315 +    if (aEvent.keyCode == 13)
   1.316 +      this.evaluateTypein();
   1.317 +  },
   1.318 +
   1.319 +  onConsoleBoxKeyPress: function cv_onConsoleBoxKeyPress(aEvent) {
   1.320 +    if ((aEvent.charCode == 99 || aEvent.charCode == 67) && aEvent.ctrlKey && this._list && this._list.selectedItem) {
   1.321 +      let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
   1.322 +      clipboard.copyString(this._list.selectedItem.getAttribute("msg"), document);
   1.323 +    }
   1.324 +  },
   1.325 +
   1.326 +  evaluateTypein: function cv_evaluateTypein() {
   1.327 +    this._evalCode = this._evalTextbox.value;
   1.328 +    this.loadOrDisplayResult();
   1.329 +  },
   1.330 +
   1.331 +  loadOrDisplayResult: function cv_loadOrDisplayResult() {
   1.332 +    if (this._evalCode) {
   1.333 +      this._evalFrame.contentWindow.location = "javascript: " + this._evalCode.replace(/%/g, "%25");
   1.334 +      this._evalCode = "";
   1.335 +      return;
   1.336 +    }
   1.337 +
   1.338 +    let resultRange = this._evalFrame.contentDocument.createRange();
   1.339 +    resultRange.selectNode(this._evalFrame.contentDocument.documentElement);
   1.340 +    let result = resultRange.toString();
   1.341 +    if (result)
   1.342 +      Services.console.logStringMessage(result);
   1.343 +      // or could use appendMessage which doesn't persist
   1.344 +  },
   1.345 +
   1.346 +  repeatChar: function cv_repeatChar(aChar, aCol) {
   1.347 +    if (--aCol <= 0)
   1.348 +      return "";
   1.349 +
   1.350 +    for (let i = 2; i < aCol; i += i)
   1.351 +      aChar += aChar;
   1.352 +
   1.353 +    return aChar + aChar.slice(0, aCol - aChar.length);
   1.354 +  }
   1.355 +};

mercurial