Bug 1304328 - Stop using XUL in webconsole/jsterm.js; r=nchevobbe draft
authorJan Odvarko <odvarko@gmail.com>
Mon, 25 Sep 2017 16:34:10 +0200
changeset 669878 a39a74185feaaa80052b319275de9ca8ec2349d5
parent 668887 97282b0c985aa1778ced171514d1ae61945c634c
child 733077 41639a28d939618d7d064ddf29f55810bebd8185
push id81457
push userjodvarko@mozilla.com
push dateMon, 25 Sep 2017 14:34:39 +0000
reviewersnchevobbe
bugs1304328
milestone58.0a1
Bug 1304328 - Stop using XUL in webconsole/jsterm.js; r=nchevobbe MozReview-Commit-ID: ChyHBETlYOn
devtools/client/themes/webconsole.css
devtools/client/webconsole/jsterm.js
devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
devtools/client/webconsole/new-console-output/test/mochitest/head.js
devtools/client/webconsole/webconsole.xhtml
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -413,50 +413,81 @@ html #webconsole-notificationbox {
   background-color: #fff;
   border-top-color: #e0e0e0;
 }
 
 .theme-firebug .jsterm-input-container {
   border-top: 1px solid #ccc;
 }
 
-.jsterm-input-node,
+html .jsterm-stack-node {
+  position: relative;
+}
+
+html .jsterm-input-node,
+html .jsterm-complete-node {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  border: none;
+  margin: 0;
+  -moz-appearance: none;
+  background-color: transparent;
+  resize: none;
+  font-size: var(--theme-toolbar-font-size);
+  line-height: 16px;
+  overflow-x: hidden;
+  /* Set padding for console input on textarea to make sure it is included in
+     scrollHeight that is used when resizing JSTerminal's input. */
+  padding: 4px 0;
+  padding-inline-start: 20px;
+}
+
 .jsterm-complete-node {
+  color: var(--theme-comment);
+}
+
+/* Focused attribute based selector can be removed as soon as the old
+   Console UI is removed. See bug: 1381834 */
+textbox.jsterm-input-node[focused="true"],
+html .jsterm-input-node:focus {
+  background-image: var(--theme-command-line-image-focus);
+  box-shadow: none;
+}
+
+/* This entire selector + rules can be removed as soon as the old
+   Console UI is removed. See bug: 1381834 */
+textbox.jsterm-input-node,
+textbox.jsterm-complete-node {
   border: none;
   padding: 0;
   padding-inline-start: 20px;
   margin: 0;
   -moz-appearance: none;
   background-color: transparent;
 }
 
-.jsterm-input-node[focused="true"] {
-  background-image: var(--theme-command-line-image-focus);
-  box-shadow: none;
-}
-
-.jsterm-complete-node {
-  color: var(--theme-comment);
-}
-
 .jsterm-input-node {
   /* Always allow scrolling on input - it auto expands in js by setting height,
      but don't want it to get bigger than the window. 24px = toolbar height. */
   max-height: calc(90vh - 24px);
   background-image: var(--theme-command-line-image);
   background-repeat: no-repeat;
   background-size: 16px 16px;
   background-position: 4px 50%;
   color: var(--theme-content-color1);
 }
 
-:-moz-any(.jsterm-input-node,
-          .jsterm-complete-node) > .textbox-input-box > .textbox-textarea {
+/* This entire selector + rules can be removed as soon as the old
+   Console UI is removed. See bug: 1381834 */
+:-moz-any(textbox.jsterm-input-node,
+          textbox.jsterm-complete-node) > .textbox-input-box > .textbox-textarea {
   overflow-x: hidden;
-  /* Set padding for console input on textbox to make sure it is inlcuded in
+  /* Set padding for console input on textbox to make sure it is included in
      scrollHeight that is used when resizing JSTerminal's input. Note: textbox
      default style has important already */
   padding: 4px 0 !important;
 }
 
 .inlined-variables-view .message-body {
   display: flex;
   flex-direction: column;
@@ -1093,27 +1124,28 @@ a.learn-more-link.webconsole-learn-more-
   overflow: auto;
   -moz-user-select: text;
   position: relative;
 }
 
 html,
 body,
 #app-wrapper {
-  height: 100%;
   margin: 0;
   padding: 0;
 }
 
 body {
   overflow: hidden;
 }
 
 #app-wrapper {
-  height: 100%;
+  /* The content wrapper take entire vertical space of the panel
+     except of the command line. */
+  height: calc(100% - 24px);
   display: flex;
   flex-direction: column;
 }
 
 body #output-container {
   flex: 1;
   overflow: hidden;
 }
--- a/devtools/client/webconsole/jsterm.js
+++ b/devtools/client/webconsole/jsterm.js
@@ -1001,19 +1001,26 @@ JSTerm.prototype = {
   resizeInput: function () {
     let inputNode = this.inputNode;
 
     // Reset the height so that scrollHeight will reflect the natural height of
     // the contents of the input field.
     inputNode.style.height = "auto";
 
     // Now resize the input field to fit its contents.
-    let scrollHeight = inputNode.inputField.scrollHeight;
+    // TODO: remove `inputNode.inputField.scrollHeight` when the old
+    // console UI is removed. See bug 1381834
+    let scrollHeight = inputNode.inputField ?
+      inputNode.inputField.scrollHeight : inputNode.scrollHeight;
+
     if (scrollHeight > 0) {
       inputNode.style.height = scrollHeight + "px";
+
+      let appWrapper = inputNode.ownerDocument.querySelector("#app-wrapper");
+      appWrapper.style.height = `calc(100% - ${scrollHeight}px)`;
     }
   },
 
   /**
    * Sets the value of the input field (command line), and resizes the field to
    * fit its contents. This method is preferred over setting "inputNode.value"
    * directly, because it correctly resizes the field.
    *
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -55,17 +55,18 @@ NewConsoleOutputWrapper.prototype = {
       }
 
       // Do not focus if an input field was clicked
       if (target.closest("input")) {
         return;
       }
 
       // Do not focus if something other than the output region was clicked
-      if (!target.closest(".webconsole-output")) {
+      // (including e.g. the clear messages button in toolbar)
+      if (!target.closest(".webconsole-output-wrapper")) {
         return;
       }
 
       // Do not focus if something is selected
       let selection = this.document.defaultView.getSelection();
       if (selection && !selection.isCollapsed) {
         return;
       }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
@@ -13,48 +13,43 @@ const TEST_URI =
     console.log("console message 1");
   </script>`;
 
 add_task(function* () {
   let hud = yield openNewTabAndConsole(TEST_URI);
 
   hud.jsterm.clearOutput();
   let inputNode = hud.jsterm.inputNode;
-  ok(inputNode.getAttribute("focused"), "input node is focused after output is cleared");
+  ok(hasFocus(inputNode), "input node is focused after output is cleared");
 
   info("Focus during message logging");
   ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
     content.wrappedJSObject.console.log("console message 2");
   });
   let msg = yield waitFor(() => findMessage(hud, "console message 2"));
-  ok(inputNode.getAttribute("focused"), "input node is focused, first time");
+  ok(hasFocus(inputNode, "input node is focused, first time"));
 
   info("Focus after clicking in the output area");
   yield waitForBlurredInput(hud);
   EventUtils.sendMouseEvent({type: "click"}, msg);
-  ok(inputNode.getAttribute("focused"), "input node is focused, second time");
+  ok(hasFocus(inputNode), "input node is focused, second time");
 
   info("Setting a text selection and making sure a click does not re-focus");
   yield waitForBlurredInput(hud);
   let selection = hud.iframeWindow.getSelection();
   selection.selectAllChildren(msg.querySelector(".message-body"));
   EventUtils.sendMouseEvent({type: "click"}, msg);
-  ok(!inputNode.getAttribute("focused"),
-    "input node not focused after text is selected");
+  ok(!hasFocus(inputNode), "input node not focused after text is selected");
 });
 
 function waitForBlurredInput(hud) {
   let inputNode = hud.jsterm.inputNode;
   return new Promise(resolve => {
     let lostFocus = () => {
-      ok(!inputNode.getAttribute("focused"), "input node is not focused");
+      ok(!hasFocus(inputNode), "input node is not focused");
       resolve();
     };
     inputNode.addEventListener("blur", lostFocus, { once: true });
 
-    // Clicking on a DOM Node outside of the webconsole document. The 'blur' event fires
-    // if we click on something in this document (like the filter box), but the 'focus'
-    // event won't re-fire on the textbox XBL binding when it's clicked on again.
-    // Bug 1304328 is tracking removal of XUL for jsterm, we should be able to click on
-    // the filter textbox instead of the url bar after that.
-    document.getElementById("urlbar").click();
+    // The 'blur' event fires if we focus e.g. the filter box.
+    inputNode.ownerDocument.querySelector("input.text-filter").focus();
   });
 }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
@@ -49,17 +49,17 @@ add_task(function* () {
   let clearShortcut;
   if (Services.appinfo.OS === "Darwin") {
     clearShortcut = WCUL10n.getStr("webconsole.clear.keyOSX");
   } else {
     clearShortcut = WCUL10n.getStr("webconsole.clear.key");
   }
   synthesizeKeyShortcut(clearShortcut);
   yield waitFor(() => findMessages(hud, "").length == 0);
-  is(hud.jsterm.inputNode.getAttribute("focused"), "true", "jsterm input is focused");
+  ok(hasFocus(hud.jsterm.inputNode), "jsterm input is focused");
 
   // Focus filter
   info("try ctrl-f to focus filter");
   synthesizeKeyShortcut(WCUL10n.getStr("webconsole.find.key"));
-  ok(!hud.jsterm.inputNode.getAttribute("focused"), "jsterm input is not focused");
+  ok(!hasFocus(hud.jsterm.inputNode), "jsterm input is not focused");
   is(hud.ui.filterBox, outputScroller.ownerDocument.activeElement,
     "filter input is focused");
 });
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -1,15 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 /* import-globals-from ../../../../framework/test/shared-head.js */
 /* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitFor, findMessage,
-   openContextMenu, hideContextMenu, loadDocument,
+   openContextMenu, hideContextMenu, loadDocument, hasFocus,
    waitForNodeMutation, testOpenInDebugger, checkClickOnNode */
 
 "use strict";
 
 // shared-head.js handles imports, constants, and utility functions
 // Load the shared-head file first.
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
@@ -248,8 +248,15 @@ function* checkClickOnNode(hud, toolbox,
 
   let dbg = toolbox.getPanel("jsdebugger");
   is(
     dbg._selectors.getSelectedSource(dbg._getState()).get("url"),
     url,
     "expected source url"
   );
 }
+
+/**
+ * Returns true if the give node is currently focused.
+ */
+function hasFocus(node) {
+  return node.ownerDocument.activeElement == node;
+}
--- a/devtools/client/webconsole/webconsole.xhtml
+++ b/devtools/client/webconsole/webconsole.xhtml
@@ -18,23 +18,23 @@
     <script src="chrome://devtools/content/shared/theme-switching.js"></script>
     <script type="application/javascript"
             src="resource://devtools/client/webconsole/new-console-output/main.js"></script>
   </head>
   <body class="theme-sidebar" role="application">
     <div id="app-wrapper" class="theme-body">
       <div id="output-container" role="document" aria-live="polite"/>
       <div id="jsterm-wrapper">
-        <xul:notificationbox id="webconsole-notificationbox">
+        <div id="webconsole-notificationbox">
           <div class="jsterm-input-container" style="direction:ltr">
-            <xul:stack class="jsterm-stack-node" flex="1">
-              <xul:textbox class="jsterm-complete-node devtools-monospace"
+            <div class="jsterm-stack-node" flex="1">
+              <textarea class="jsterm-complete-node devtools-monospace"
                        multiline="true" rows="1" tabindex="-1"/>
-              <xul:textbox class="jsterm-input-node devtools-monospace"
+              <textarea class="jsterm-input-node devtools-monospace"
                        multiline="true" rows="1" tabindex="0"
                        aria-autocomplete="list"/>
-            </xul:stack>
+            </div>
           </div>
-        </xul:notificationbox>
+        </div>
       </div>
     </div>
   </body>
 </html>