Reputation: 98
I have a function that wraps an HTML element with a <div>
. For handling purposes, the div shouldn't change location or change the page design (except for obvious changes like going down a line etc.) The current function just adds it to end of the parent element.
In the snippet I show an example of three elements, but the function will be run on complicated pages with complicated design. It is a chrome extension function so it will run on unknown pages.
function contain(htmlnode) {
// surrounds the recived html element with a div parent and returns
// the container with the element nested within
parent = $(htmlnode).parent();
container = document.createElement('div');
container.id = "manuelfound";
console.log(container);
container.appendChild(htmlnode);
parent[0].appendChild(container);
return container;
}
contain(document.getElementById("contained"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h6>first example</h6>
<h6 id="contained">second example</h6>
<h6>third example</h6>
</div>
Upvotes: 0
Views: 759
Reputation: 97
Tip: Copying all styles from child to container won't help you.
actually, changing the Dom structure is nearly impossible to do what you want. you need to work with siblings, overlays and positioning. Let me know if you need more info on what i am actually suggesting.
So... To answer your Question:
(function($){
$.fn.getStyleObject = function(){
var dom = this.get(0);
var style;
var returns = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
}
style = window.getComputedStyle(dom, null);
for(var i=0;i<style.length;i++){
var prop = style[i];
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
returns[camel] = val;
}
return returns;
}
if(dom.currentStyle){
style = dom.currentStyle;
for(var prop in style){
returns[prop] = style[prop];
}
return returns;
}
return this.css();
}
})(jQuery);
function contain(htmlnode) {
// surrounds the recived html element with a div parent and returns
// the container with the element nested within
parent = $(htmlnode).parent();
next = $(htmlnode).next();
container = document.createElement('div');
container.id = "manuelfound";
var styles = $(htmlnode).getStyleObject();
$(container).append( $(htmlnode).clone() );
$(container).insertBefore(next);
// Uncomment this if you want to maintain all styles.
// $(container).css(styles)
$(htmlnode).remove();
return container;
}
contain(document.getElementById("contained"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h6>first example</h6>
<h6 id="contained" style='color:#ff00ff; border:1px solid #000000;'>second example</h6>
<h6>third example</h6>
</div>
Upvotes: 1
Reputation: 1400
I think this will be very challenging to get to look exactly right because there is the potential to disrupt stylesheets that depend on the exact DOM structure. For example, in the modified snippet below, the style is no longer applied to the captured element. You could get around this by saving the original style of every element with window.getComputedStyle() then reapplying it.
To fix your problem of the element appearing in the wrong place is easy though: just use replaceChild. Calling replaceChild
first removes htmlnode
from the DOM and puts container
in its place. Then htmlnode
is appended to container.
function contain(htmlnode) {
// surrounds the recived html element with a div parent and returns
// the container with the element nested within
parent = htmlnode.parentNode;
container = document.createElement('div');
container.id = "manuelfound";
console.log(container);
parent.replaceChild(container, htmlnode);
container.appendChild(htmlnode);
return container;
}
contain(document.getElementById("contained"));
main > h6 {
background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main>
<h6>first example</h6>
<h6 id="contained">second example</h6>
<h6>third example</h6>
</main>
Upvotes: 1