title: JavaScript to "flatten" a webpage DOM preserving visual appearance?
body: <p>I would like to write JavaScript code that "flattens" the DOM of an arbitrary webpage while preserving the visual appearance (but not necessarily the resize or other dynamic behaviors)</p>
  
  <p>In theory I believe this should simply be a matter of recording the position of each element relative to the window (e.x. <a href="http://www.quirksmode.org/js/findpos.html" rel="nofollow">PPK's <code>findPos(element)</code></a>) as well as it's computed CSS styles (e.x. <a href="https://developer.mozilla.org/en/DOM%3awindow.getComputedStyle" rel="nofollow"><code>window.getComputedStyle(element).cssText</code></a>), moving the element from it's parent to a direct child of "body", making it absolutely positioned at the previously recorded position, and setting the recorded CSS attributes directly on the element.</p>
  
  <p>I've had some success with this approach but it's not close to being perfect:</p>
  
  <pre><code>function walkDOM(element, parent, nodes) {
      parent = parent || { top : 0, left : 0, depth : 0 };
      nodes = nodes || [];
  
      if (element.nodeType === 1) {
          var node = findPos(element);
          node.element = element;
          node.width = element.scrollWidth;
          node.height = element.scrollHeight;
          node.depth = parent.depth + 1;
          node.cssText = window.getComputedStyle(element).cssText;
          nodes.push(node);
  
          for (var i = 0; i &lt; element.childNodes.length; i++) {
              walkDOM(element.childNodes[i], node, nodes);
          }
      }
      return nodes;
  }
  
  // based on http://www.quirksmode.org/js/findpos.html
  function findPos(element) {
      var position = { left : 0, top : 0 };
      if (element.offsetParent) {
          do {
              position.left += element.offsetLeft;
              position.top += element.offsetTop;
          } while (element = element.offsetParent);
      }
      return position;
  }
  
  var nodes = walkDOM(document.body);
  
  nodes.forEach(function(node) {
      var e = node.element;
  
      if (e !== document.body)
          e.parentNode.removeChild(e);
  
      // e.setAttribute("style", node.cssText);
      e.style.position = "absolute";
      e.style.top = node.top + "px";
      e.style.left = node.left + "px";
      e.style.width = node.width + "px";
      e.style.height = node.height + "px";
      e.style.zIndex = node.depth + 1;
  
      if (e !== document.body)
          document.body.appendChild(e);
  });
  </code></pre>