3

I would like to grab the HTML element and all it's computedStyles.

I managed to make it work when the HTML element has no children, but what if the HTML element has many children, how can I grab all the computedStyles of each child

here's what I have so far:

  • The user clicks on an html element, I grab the HTML element using event.target.cloneNode(true)
  • I then set an Id to the cloned element
  • I grab the computedStyle
  • Then I add the style to my cloned element
  private onClickHtmlCssGrabber = (event) => {
      // clone the html element
      let clickedHtmlElement = event.target.cloneNode(true)

      // set an id to the cloned element
      clickedHtmlElement.setAttribute('id', 'clonedElement')

      // get the computed style of the element
      let clikedHtmlElementStyle =  getComputedStyle(event.target).cssText

      // set the style on my newly cloned element
      clickedHtmlElement.style.cssText = clikedHtmlElementStyle
  }

So basically at this point I end up with something like:

<div id="clonedElement" style="... all the coputedStyle">Example text</div>

But my problem occurs when the HTML element that I want to extract has many children:

<div class="style1">
  <div class="style-child-1">
    <div class="style-child-2">
      example text child 2
    <div>
    <div class="style-child-3">
      example text child 3
    </div>
  <div>
</div>

So how can I extract the whole HTML element with its children and their styles ?

MaxiGui
  • 6,190
  • 4
  • 16
  • 33
AziCode
  • 2,510
  • 6
  • 27
  • 53
  • 1
    Havent used it yet, but you should be able to "walk" through your element + children with TreeWalker https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker. You probably need `TreeWalker.nextNode()` and then pull your styles out one by one and while walking through it, create your clone. – Alex Berger Feb 10 '21 at 11:09
  • 1
    Hey this particular discussion might help you with some insights - https://stackoverflow.com/questions/1848445/duplicating-an-element-and-its-style-with-javascript/1848489 – Lakshya Thakur Feb 10 '21 at 11:15

1 Answers1

1

So I was curious about this myself and created a quick example to walk through an element. Should also work without any children in it, because the loop will simply not run.

// container where we want to put the clone
const targetContainer = document.querySelector('.target');

// your element that you want to clone
const root = document.querySelector('.style1');
const rootWalker = document.createTreeWalker(
    root,
    NodeFilter.SHOW_ELEMENT,
    { acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } }
);

// now clone the element and also creat a walker for it
const rootClone = root.cloneNode(true);
const cloneWalker = document.createTreeWalker(
    rootClone,
    NodeFilter.SHOW_ELEMENT,
    { acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; }}
);

// clone styles for the root element itself
rootClone.style.cssText = getComputedStyle(root).cssText
rootClone.className = '' // simply clearing it to see if styles are copied

// get the first child node, if there is no child, .nextNode() will return null
let nextRootNode = rootWalker.nextNode();
let nextCloneNode = cloneWalker.nextNode();

// now if we have a child node, the loop is running
while (nextRootNode !== null) {
  // get styles from original to clone
    nextCloneNode.style.cssText = getComputedStyle(nextRootNode).cssText;
  nextCloneNode.className = '' // again removing classes for demonstration
  
  // get next node, again if there are no more, null will be returned and loop will stop
  nextRootNode = rootWalker.nextNode();
  nextCloneNode = cloneWalker.nextNode();
}

// simply append the cloned node to your desired target
targetContainer.append(rootClone);
.style1 {
  background: yellow;
  padding: 10px;
  margin: 5px 0;
}

.style-child-1 {
  background: green;
  padding: 10px;
}

.style-child-2 {
  color: blue;
}

.style-child-3 {
  color: orange;
  text-transform: uppercase;
}
<div class="style1">
  <div class="style-child-1">
    <div class="style-child-2">
      example text child 2
    </div>
    <div class="style-child-3">
      example text child 3
    </div>
   </div>
</div>

<div class="target">

</div>

If you want you can grab this and fit it to your needs. Eg. creating a function and run it on click.

AziCode
  • 2,510
  • 6
  • 27
  • 53
Alex Berger
  • 1,357
  • 1
  • 10
  • 22
  • 1
    Great this is exactly what I need, I edited your answer and removed the 4th argument `false` of document.createTreeWalker() because after some research it appears that it has been deprecated. I will accept the answer after the edition is accepted. Thanks – AziCode Feb 11 '21 at 14:28
  • 1
    Have checked it again and you are absolutely right, it's deprecated. Removed it from my answer. – Alex Berger Feb 11 '21 at 14:31