Bug 1242201 - Part 1: Move markup view into the inspector panel frame. r=bgrins draft
authorGabriel Luong <gabriel.luong@gmail.com>
Fri, 11 Aug 2017 14:48:01 -0700
changeset 645098 67c3aaa3290fa641359a2cf89983ad63de420e9e
parent 645097 2b8fe8c61b34625cf397b59493c09b627e23a865
child 725820 5ba2d34b958698784048120ab63bed08f70e6e23
push id73663
push userbmo:gl@mozilla.com
push dateFri, 11 Aug 2017 21:48:31 +0000
reviewersbgrins
bugs1242201
milestone57.0a1
Bug 1242201 - Part 1: Move markup view into the inspector panel frame. r=bgrins MozReview-Commit-ID: 2BGEN4zlgHq
devtools/client/inspector/inspector.js
devtools/client/inspector/inspector.xhtml
devtools/client/inspector/markup/markup.js
devtools/client/inspector/markup/markup.xhtml
devtools/client/inspector/markup/views/html-editor.js
devtools/client/inspector/markup/views/markup-container.js
devtools/client/jar.mn
devtools/client/themes/inspector.css
devtools/client/themes/markup.css
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -104,17 +104,16 @@ function Inspector(toolbox) {
   // telemetry counts in the Grid Inspector are not double counted on reload.
   this.previousURL = this.target.url;
 
   this.nodeMenuTriggerInfo = null;
 
   this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
   this._onContextMenu = this._onContextMenu.bind(this);
   this._onBeforeNavigate = this._onBeforeNavigate.bind(this);
-  this._onMarkupFrameLoad = this._onMarkupFrameLoad.bind(this);
   this._updateSearchResultsLabel = this._updateSearchResultsLabel.bind(this);
 
   this.onDetached = this.onDetached.bind(this);
   this.onMarkupLoaded = this.onMarkupLoaded.bind(this);
   this.onNewSelection = this.onNewSelection.bind(this);
   this.onNewRoot = this.onNewRoot.bind(this);
   this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
   this.onPanelWindowResize = this.onPanelWindowResize.bind(this);
@@ -267,17 +266,16 @@ Inspector.prototype = {
         }
       };
       this.target.on("thread-paused", this.updateDebuggerPausedWarning);
       this.target.on("thread-resumed", this.updateDebuggerPausedWarning);
       this._toolbox.on("select", this.updateDebuggerPausedWarning);
       this.updateDebuggerPausedWarning();
     }
 
-    this._initMarkup();
     this.isReady = false;
 
     return new Promise(resolve => {
       this.once("markuploaded", () => {
         this.isReady = true;
 
         // All the components are initialized. Let's select a node.
         if (defaultSelection) {
@@ -287,16 +285,18 @@ Inspector.prototype = {
 
         // And setup the toolbar only now because it may depend on the document.
         this.setupToolbar();
 
         this.emit("ready");
         resolve(this);
       });
 
+      this._initMarkup();
+
       this.setupSearchBox();
       this.setupSidebar();
     });
   },
 
   _onBeforeNavigate: function () {
     this._defaultNode = null;
     this.selection.setNodeFront(null);
@@ -772,18 +772,18 @@ Inspector.prototype = {
       // Cancel this promise resolution as a new one had
       // been queued up.
       if (this._pendingSelection != onNodeSelected) {
         return;
       }
       this._pendingSelection = null;
       this.selection.setNodeFront(defaultNode, "navigateaway");
 
+      this.once("markuploaded", this.onMarkupLoaded);
       this._initMarkup();
-      this.once("markuploaded", this.onMarkupLoaded);
 
       // Setup the toolbar again, since its content may depend on the current document.
       this.setupToolbar();
     };
     this._pendingSelection = onNodeSelected;
     this._getDefaultNodeForSelection()
         .then(onNodeSelected, this._handleRejectionIfNotDestroyed);
   },
@@ -1435,70 +1435,30 @@ Inspector.prototype = {
       linkFollow.label = INSPECTOR_L10N.getFormatStr(
         "inspector.menu.selectElement.label", popupNode.dataset.link);
     }
 
     return [linkFollow, linkCopy];
   },
 
   _initMarkup: function () {
-    let doc = this.panelDoc;
-
-    this._markupBox = doc.getElementById("markup-box");
-
-    // create tool iframe
-    this._markupFrame = doc.createElement("iframe");
-    this._markupFrame.setAttribute("flex", "1");
-    // This is needed to enable tooltips inside the iframe document.
-    this._markupFrame.setAttribute("tooltip", "aHTMLTooltip");
-    this._markupFrame.addEventListener("contextmenu", this._onContextMenu);
-
-    this._markupBox.setAttribute("collapsed", true);
-    this._markupBox.appendChild(this._markupFrame);
-
-    this._markupFrame.addEventListener("load", this._onMarkupFrameLoad, true);
-    this._markupFrame.setAttribute("src", "markup/markup.xhtml");
-    this._markupFrame.setAttribute("aria-label",
-      INSPECTOR_L10N.getStr("inspector.panelLabel.markupView"));
-  },
-
-  _onMarkupFrameLoad: function () {
-    this._markupFrame.removeEventListener("load", this._onMarkupFrameLoad, true);
-
-    this._markupFrame.contentWindow.focus();
-
-    this._markupBox.removeAttribute("collapsed");
-
-    this.markup = new MarkupView(this, this._markupFrame, this._toolbox.win);
-
+    this.markup = new MarkupView(this, this.panelDoc, this._toolbox.win);
     this.emit("markuploaded");
   },
 
   _destroyMarkup: function () {
     let destroyPromise;
 
-    if (this._markupFrame) {
-      this._markupFrame.removeEventListener("load", this._onMarkupFrameLoad, true);
-      this._markupFrame.removeEventListener("contextmenu", this._onContextMenu);
-    }
-
     if (this.markup) {
       destroyPromise = this.markup.destroy();
       this.markup = null;
     } else {
       destroyPromise = promise.resolve();
     }
 
-    if (this._markupFrame) {
-      this._markupFrame.remove();
-      this._markupFrame = null;
-    }
-
-    this._markupBox = null;
-
     return destroyPromise;
   },
 
   /**
    * When the pane toggle button is clicked or pressed, toggle the pane, change the button
    * state and tooltip.
    */
   onPaneToggleButtonClicked: function (e) {
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -18,19 +18,25 @@
   <link rel="stylesheet" href="chrome://devtools/skin/animationinspector.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/sidebar-toggle.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabs.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabbar.css"/>
   <link rel="stylesheet" href="resource://devtools/client/inspector/components/inspector-tab-panel.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/split-box.css"/>
   <link rel="stylesheet" href="resource://devtools/client/inspector/layout/components/Accordion.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/markup.css"/>
+  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css"/>
+  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css"/>
+  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css"/>
 
   <script type="application/javascript"
           src="chrome://devtools/content/shared/theme-switching.js"></script>
+  <script type="application/javascript"
+          src="chrome://devtools/content/sourceeditor/codemirror/codemirror.bundle.js"></script>
   <script type="text/javascript">
     /* eslint-disable */
     var isInChrome = window.location.href.includes("chrome:");
     if (isInChrome) {
       var exports = {};
       var Cu = Components.utils;
       var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
       var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
@@ -55,17 +61,21 @@
           <input id="inspector-searchbox" class="devtools-searchinput"
                  type="search"
                  data-localization="placeholder=inspectorSearchHTML.label3"/>
           <button id="inspector-searchinput-clear" class="devtools-searchinput-clear" tabindex="-1"></button>
         </div>
         <button id="inspector-eyedropper-toggle" class="devtools-button command-button-invertable"></button>
         <div id="inspector-sidebar-toggle-box"></div>
       </div>
-      <div id="markup-box"></div>
+      <div id="markup-container" data-localization="aria-label=inspector.panelLabel.markupView" class="devtools-monospace">
+        <div class="markup-wrapper" role="presentation">
+          <div id="markup-root" class="markup-root" role="presentation"></div>
+        </div>
+      </div>
       <div id="inspector-breadcrumbs-toolbar" class="devtools-toolbar">
         <div id="inspector-breadcrumbs" class="breadcrumbs-widget-container"
              role="group" data-localization="aria-label=inspector.breadcrumbs.label" tabindex="0"></div>
       </div>
     </div>
 
     <!-- Splitter -->
     <div xmlns="http://www.w3.org/1999/xhtml" id="inspector-splitter-box">
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -53,26 +53,28 @@ const ATTR_COLLAPSE_LENGTH_PREF = "devto
  */
 
 /**
  * The markup tree.  Manages the mapping of nodes to MarkupContainers,
  * updating based on mutations, and the undo/redo bindings.
  *
  * @param  {Inspector} inspector
  *         The inspector we're watching.
- * @param  {iframe} frame
- *         An iframe in which the caller has kindly loaded markup.xhtml.
+ * @param  {Document} document
+ *         The document that will contain the markup view.
+ * @param  {DOMWindow} controllerWindow
+ *         The window object of the toolbox document
  */
-function MarkupView(inspector, frame, controllerWindow) {
+function MarkupView(inspector, document, controllerWindow) {
   this.inspector = inspector;
   this.walker = this.inspector.walker;
-  this._frame = frame;
-  this.win = this._frame.contentWindow;
-  this.doc = this._frame.contentDocument;
-  this._elt = this.doc.querySelector("#root");
+  this.doc = document;
+  this.win = this.doc.defaultView;
+  this._container = this.doc.getElementById("markup-container");
+  this._elt = this.doc.getElementById("markup-root");
 
   this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize",
                                                DEFAULT_MAX_CHILDREN);
 
   this.collapseAttributes =
     Services.prefs.getBoolPref(ATTR_COLLAPSE_ENABLED_PREF);
   this.collapseAttributeLength =
     Services.prefs.getIntPref(ATTR_COLLAPSE_LENGTH_PREF);
@@ -106,22 +108,23 @@ function MarkupView(inspector, frame, co
     this._onCollapseAttributesPrefChange.bind(this);
   this._isImagePreviewTarget = this._isImagePreviewTarget.bind(this);
   this._onBlur = this._onBlur.bind(this);
 
   EventEmitter.decorate(this);
 
   // Listening to various events.
   this._elt.addEventListener("click", this._onMouseClick);
+  this._elt.addEventListener("contextmenu", this.inspector._onContextMenu);
   this._elt.addEventListener("mousemove", this._onMouseMove);
   this._elt.addEventListener("mouseout", this._onMouseOut);
   this._elt.addEventListener("blur", this._onBlur, true);
-  this.win.addEventListener("mouseup", this._onMouseUp);
-  this.win.addEventListener("copy", this._onCopy);
-  this._frame.addEventListener("focus", this._onFocus);
+  this._elt.addEventListener("focus", this._onFocus);
+  this._elt.addEventListener("mouseup", this._onMouseUp);
+  this._elt.addEventListener("copy", this._onCopy);
   this.walker.on("mutations", this._mutationObserver);
   this.walker.on("display-change", this._onDisplayChange);
   this.inspector.selection.on("new-node-front", this._onNewSelection);
   this.toolbox.on("picker-canceled", this._onToolboxPickerCanceled);
   this.toolbox.on("picker-node-hovered", this._onToolboxPickerHover);
 
   this._onNewSelection();
   this._initTooltips();
@@ -308,17 +311,17 @@ MarkupView.prototype = {
     loop();
   },
 
   _onMouseClick: function (event) {
     // From the target passed here, let's find the parent MarkupContainer
     // and ask it if the tooltip should be shown
     let parentNode = event.target;
     let container;
-    while (parentNode !== this.doc.body) {
+    while (parentNode !== this._container) {
       if (parentNode.container) {
         container = parentNode.container;
         break;
       }
       parentNode = parentNode.parentNode;
     }
 
     if (container instanceof MarkupElementContainer) {
@@ -507,17 +510,17 @@ MarkupView.prototype = {
   _isImagePreviewTarget: Task.async(function* (target) {
     // From the target passed here, let's find the parent MarkupContainer
     // and ask it if the tooltip should be shown
     if (this.isDragging) {
       return false;
     }
 
     let parent = target, container;
-    while (parent !== this.doc.body) {
+    while (parent !== this._container) {
       if (parent.container) {
         container = parent.container;
         break;
       }
       parent = parent.parentNode;
     }
 
     if (container instanceof MarkupElementContainer) {
@@ -662,16 +665,17 @@ MarkupView.prototype = {
   },
 
   /**
    * Register all key shortcuts.
    */
   _initShortcuts: function () {
     let shortcuts = new KeyShortcuts({
       window: this.win,
+      target: this._elt,
     });
 
     this._onShortcut = this._onShortcut.bind(this);
 
     // Process localizable keys
     ["markupView.hide.key",
      "markupView.edit.key",
      "markupView.scrollInto.key"].forEach(name => {
@@ -1746,41 +1750,44 @@ MarkupView.prototype = {
 
     this.undo.destroy();
     this.undo = null;
 
     this.popup.destroy();
     this.popup = null;
 
     this._elt.removeEventListener("click", this._onMouseClick);
+    this._elt.removeEventListener("contextmenu", this.inspector._onContextMenu);
     this._elt.removeEventListener("mousemove", this._onMouseMove);
     this._elt.removeEventListener("mouseout", this._onMouseOut);
     this._elt.removeEventListener("blur", this._onBlur, true);
-    this.win.removeEventListener("mouseup", this._onMouseUp);
-    this.win.removeEventListener("copy", this._onCopy);
-    this._frame.removeEventListener("focus", this._onFocus);
+    this._elt.removeEventListener("focus", this._onFocus);
+    this._elt.removeEventListener("mouseup", this._onMouseUp);
+    this._elt.removeEventListener("copy", this._onCopy);
     this.walker.off("mutations", this._mutationObserver);
     this.walker.off("display-change", this._onDisplayChange);
     this.inspector.selection.off("new-node-front", this._onNewSelection);
-    this.toolbox.off("picker-node-hovered",
-                                this._onToolboxPickerHover);
+    this.toolbox.off("picker-node-hovered", this._onToolboxPickerHover);
 
     this._prefObserver.off(ATTR_COLLAPSE_ENABLED_PREF,
                            this._onCollapseAttributesPrefChange);
     this._prefObserver.off(ATTR_COLLAPSE_LENGTH_PREF,
                            this._onCollapseAttributesPrefChange);
     this._prefObserver.destroy();
 
-    this._elt = null;
-
     for (let [, container] of this._containers) {
       container.destroy();
     }
     this._containers = null;
 
+    this._elt.innerHTML = "";
+    this._elt = null;
+
+    this._container = null;
+
     this.eventDetailsTooltip.destroy();
     this.eventDetailsTooltip = null;
 
     this.imagePreviewTooltip.destroy();
     this.imagePreviewTooltip = null;
 
     this.win = null;
     this.doc = null;
deleted file mode 100644
--- a/devtools/client/inspector/markup/markup.xhtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<!DOCTYPE html>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-  <link rel="stylesheet" href="chrome://devtools/skin/markup.css" type="text/css"/>
-  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" type="text/css"/>
-  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css" type="text/css"/>
-  <link rel="stylesheet" href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" type="text/css"/>
-
-  <script type="application/javascript"
-          src="chrome://devtools/content/shared/theme-switching.js"></script>
-  <script type="application/javascript"
-          src="chrome://devtools/content/sourceeditor/codemirror/codemirror.bundle.js"></script>
-</head>
-<body class="theme-body devtools-monospace" role="application">
-  <div id="root-wrapper" role="presentation">
-    <div id="root" role="presentation"></div>
-  </div>
-</body>
-</html>
--- a/devtools/client/inspector/markup/views/html-editor.js
+++ b/devtools/client/inspector/markup/views/html-editor.js
@@ -27,17 +27,17 @@ function HTMLEditor(htmlDocument) {
   this.doc = htmlDocument;
   this.container = this.doc.createElement("div");
   this.container.className = "html-editor theme-body";
   this.container.style.display = "none";
   this.editorInner = this.doc.createElement("div");
   this.editorInner.className = "html-editor-inner";
   this.container.appendChild(this.editorInner);
 
-  this.doc.body.appendChild(this.container);
+  this.doc.getElementById("markup-container").appendChild(this.container);
   this.hide = this.hide.bind(this);
   this.refresh = this.refresh.bind(this);
 
   EventEmitter.decorate(this);
 
   this.doc.defaultView.addEventListener("resize",
     this.refresh, true);
 
--- a/devtools/client/inspector/markup/views/markup-container.js
+++ b/devtools/client/inspector/markup/views/markup-container.js
@@ -42,19 +42,19 @@ MarkupContainer.prototype = {
    * @param  {String} type
    *         The type of container to build. This can be either 'textcontainer',
    *         'readonlycontainer' or 'elementcontainer'.
    */
   initialize: function (markupView, node, type) {
     this.markup = markupView;
     this.node = node;
     this.undo = this.markup.undo;
-    this.win = this.markup._frame.contentWindow;
+    this.win = this.markup.win;
     this.id = "treeitem-" + markupContainerID++;
-    this.htmlElt = this.win.document.documentElement;
+    this.htmlElt = this.markup.doc.getElementById("markup-container");
 
     this.buildMarkup(type);
 
     this.elt.container = this;
 
     this._onMouseDown = this._onMouseDown.bind(this);
     this._onToggle = this._onToggle.bind(this);
     this._onMouseUp = this._onMouseUp.bind(this);
@@ -191,17 +191,17 @@ MarkupContainer.prototype = {
   clearFocus: function () {
     if (!this.canFocus) {
       return;
     }
 
     this.canFocus = false;
     let doc = this.markup.doc;
 
-    if (!doc.activeElement || doc.activeElement === doc.body) {
+    if (!doc.activeElement || doc.activeElement === this.htmlElt) {
       return;
     }
 
     let parent = doc.activeElement;
 
     while (parent && parent !== this.elt) {
       parent = parent.parentNode;
     }
@@ -377,22 +377,20 @@ MarkupContainer.prototype = {
     let rootElt = this.markup.getContainer(this.markup._rootNode).elt;
     this._isDragging = isDragging;
     this.markup.isDragging = isDragging;
     this.tagLine.setAttribute("aria-grabbed", isDragging);
 
     if (isDragging) {
       this.htmlElt.classList.add("dragging");
       this.elt.classList.add("dragging");
-      this.markup.doc.body.classList.add("dragging");
       rootElt.setAttribute("aria-dropeffect", "move");
     } else {
       this.htmlElt.classList.remove("dragging");
       this.elt.classList.remove("dragging");
-      this.markup.doc.body.classList.remove("dragging");
       rootElt.setAttribute("aria-dropeffect", "none");
     }
   },
 
   get isDragging() {
     return this._isDragging;
   },
 
@@ -569,18 +567,18 @@ MarkupContainer.prototype = {
 
     if (this.isDragging) {
       let x = 0;
       let y = event.pageY - this.win.scrollY;
 
       // Ensure we keep the dragged element within the markup view.
       if (y < 0) {
         y = 0;
-      } else if (y >= this.markup.doc.body.offsetHeight - this.win.scrollY) {
-        y = this.markup.doc.body.offsetHeight - this.win.scrollY - 1;
+      } else if (y >= this.htmlElt.offsetHeight - this.win.scrollY) {
+        y = this.htmlElt.offsetHeight - this.win.scrollY - 1;
       }
 
       let diff = y - this._dragStartY + this.win.scrollY;
       this.elt.style.top = diff + "px";
 
       let el = this.markup.doc.elementFromPoint(x, y);
       this.markup.indicateDropTarget(el);
     }
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -15,17 +15,16 @@ devtools.jar:
     content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul)
     content/scratchpad/scratchpad.js (scratchpad/scratchpad.js)
     content/shared/splitview.css (shared/splitview.css)
     content/shared/theme-switching.js (shared/theme-switching.js)
     content/shared/frame-script-utils.js (shared/frame-script-utils.js)
     content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul)
     content/storage/storage.xul (storage/storage.xul)
     content/inspector/inspector.js (inspector/inspector.js)
-    content/inspector/markup/markup.xhtml (inspector/markup/markup.xhtml)
     content/animationinspector/animation-controller.js (animationinspector/animation-controller.js)
     content/animationinspector/animation-panel.js (animationinspector/animation-panel.js)
     content/animationinspector/animation-inspector.xhtml (animationinspector/animation-inspector.xhtml)
     content/sourceeditor/codemirror/addon/dialog/dialog.css (sourceeditor/codemirror/addon/dialog/dialog.css)
     content/sourceeditor/codemirror/addon/hint/show-hint.js (sourceeditor/codemirror/addon/hint/show-hint.js)
     content/sourceeditor/codemirror/addon/tern/tern.js (sourceeditor/codemirror/addon/tern/tern.js)
     content/sourceeditor/codemirror/codemirror.bundle.js (sourceeditor/codemirror/codemirror.bundle.js)
     content/sourceeditor/codemirror/lib/codemirror.css (sourceeditor/codemirror/lib/codemirror.css)
--- a/devtools/client/themes/inspector.css
+++ b/devtools/client/themes/inspector.css
@@ -191,26 +191,8 @@ window {
 /* "no results" warning message displayed in the ruleview and in the computed view */
 
 #ruleview-no-results,
 #computed-no-results {
   color: var(--theme-body-color-inactive);
   text-align: center;
   margin: 5px;
 }
-
-/* Markup Box */
-
-iframe {
-  border: 0;
-}
-
-#markup-box {
-  width: 100%;
-  flex: 1;
-  min-height: 0;
-}
-
-#markup-box > iframe {
-  height: 100%;
-  width: 100%;
-}
-
--- a/devtools/client/themes/markup.css
+++ b/devtools/client/themes/markup.css
@@ -1,55 +1,56 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :root {
   --markup-outline: var(--theme-splitter-color);
+  -moz-control-character-visibility: visible;
 }
 
 .theme-dark:root {
   --markup-outline: var(--theme-highlight-pink);
 }
 
-* {
-  padding: 0;
-  margin: 0;
-}
-
-:root {
-  -moz-control-character-visibility: visible;
-}
-
-body {
-  -moz-user-select: none;
+#markup-container {
+  width: 100%;
+  height: 100%;
+  flex: 1;
+  overflow: auto;
 }
 
 /* Force height and width (possibly overflowing) from inline elements.
  * This allows long overflows of text or input fields to still be styled with
  * the container, rather than the background disappearing when scrolling */
-#root {
+#markup-root {
   float: left;
   min-width: 100%;
 }
 
 /* Don't display a parent-child outline for the root elements */
-#root > ul > li > .children {
+#markup-root > ul > li > .children {
   background: none;
 }
 
-html.dragging {
+.markup-root * {
+  padding: 0;
+  margin: 0;
+  -moz-user-select: none;
+}
+
+.dragging {
   overflow-x: hidden;
 }
 
-body.dragging .tag-line {
+.dragging .tag-line {
   cursor: grabbing;
 }
 
-#root-wrapper:after {
+.markup-wrapper:after {
    content: "";
    display: block;
    clear: both;
    position:relative;
 }
 
 .html-editor {
   display: none;