I would like to remove the parent without removing the child - is this possible?
HTML structure:
<div class="wrapper">
<img src"">
</div>
<div class="button">Remove wrapper</div>
After clicking on the button I would like to have:
<img src"">
<div class="button">Remove wrapper</div>
Pure JS (ES2015) solution, in my opinion easier to read than jQuery-solutions.
node.replaceWith(...node.childNodes)
Node has to be an ElementNode
const wrapperNode = document.querySelector('h1')
wrapperNode.replaceWith(...wrapperNode.childNodes)
<h1>
<a>1</a>
<b>2</b>
<em>3</em>
</h1>
Pure JS solution that doesn't use innerHTML:
function unwrap(wrapper) {
// place childNodes in document fragment
var docFrag = document.createDocumentFragment();
while (wrapper.firstChild) {
var child = wrapper.removeChild(wrapper.firstChild);
docFrag.appendChild(child);
}
// replace wrapper with document fragment
wrapper.parentNode.replaceChild(docFrag, wrapper);
}
Try it:
unwrap(document.querySelector('.wrapper'));
Surprised that nobody's posting the simplest answer:
// Find your wrapper HTMLElement
var wrapper = document.querySelector('.wrapper');
// Replace the whole wrapper with its own contents
wrapper.outerHTML = wrapper.innerHTML;
Could use this API: http://api.jquery.com/unwrap/
Demo http://jsfiddle.net/7GrbM/
.unwrap
Code will look something on these lines:
Sample Code
$('.button').click(function(){
$('.wrapper img').unwrap();
});
Pure javascript solution, i'm sure someone can simplify it more but this is an alternative for pure javascript guys.
HTML
<div class="button" onclick="unwrap(this)">Remove wrapper</div>
Javascript (pure)
function unwrap(i) {
var wrapper = i.parentNode.getElementsByClassName('wrapper')[0];
// return if wrapper already been unwrapped
if (typeof wrapper === 'undefined') return false;
// remmove the wrapper from img
i.parentNode.innerHTML = wrapper.innerHTML + i.outerHTML;
return true;
}
JSFIDDLE
if you're using jQuery:
$(".wrapper").replaceWith($(".wrapper").html());
If the wrapper element contains text, the text remains with child nodes.
Related
For example,
<div class="panel">
<div class="inner-panel">
<button onclick="hideParentElement()">
Hide
</button>
</div>
</div>
If I want to add a class to the outer most division, I need to fetch that element and add a class to it. How can this be achieved using pure javascript?
I have tried the following:
this.parentElement.parentElement.classList.add("classname");
This works but if there are more than 2 parentElements it is not the right way.
Please suggest a better way
You have to cycle the parents like this.
var el = this.parentElement;
while(el.className != 'panel'){
el = el.parentElement;
}
//el is now your parent
el.className += "classname";
With pure Javascript this is the way to do it.
In case when your class list is changing dynamically:
let parent = this.parentElement;
while (!parent.classList.contains('panel'))
parent = parent.parentElement;
parent.classList.add('classname');
Kind of late to the party, but this seems to work:
var pn = element.parentNode
for(i=4;i>0;i--){
pn = pn.parentNode;
}
I have HTML:
<footer class="footer">
<div class="container-fluid wrapper">
...
</div>
</footer>
How do I remove the whole footer markup using javascript (no jQuery available)?
I've tried:
var elem = document.getElementsByName("footer");
elem.remove();
...and a couple of other variations, but I can't get it to delete.
Any ideas?
Thanks, Mark
Yes, you can do like this
function removeTagByTagName(tagName) {
var ele = document.getElementsByTagName(tagName);
return ele[0].parentNode.removeChild(ele[0]);
}
function removeTag(tag) {
var ele = document.getElementsByTagName(tag);
return ele[0].parentNode.removeChild(ele[0]);
}
var btn = document.getElementById("delet");
btn.addEventListener("click", function(){
removeTagByTagName("footer");
});
<body>
<button id="delet">Delete Footer!</button>
<footer class="footer" name="footer">
<div class="container-fluid wrapper">
blab bal babla
</div>
</footer>
</body>
you cannot use .remove with all browsers, since the support is not that good yet. I would recommend polyfilling the remove, so that you can use this. Use the following polyfill (taken from MDN):
// from:https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/remove()/remove().md
(function (arr) {
arr.forEach(function (item) {
if (item.hasOwnProperty('remove')) {
return;
}
Object.defineProperty(item, 'remove', {
configurable: true,
enumerable: true,
writable: true,
value: function remove() {
this.parentNode.removeChild(this);
}
});
});
})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
Now you can use .remove() with ease.
You can also use .removeChild() if you know the parent of the node you want to delete. Something like this:
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.removeChild(child);
So since your is inside the , you can treat the body as the parent and remove its child () using similar code as above snippet.
You would need to grab that specific footer element. What you have with var elem = document.getElementsByName("footer"); grabs a collection of all elements named "footer" but if you want to do it that way, you need to add the name="footer" attribute to your footer element. The way your HTML is set up right now, you could change that line to:
var elem = document.getElementsByTagName("footer");
If you only have one footer element, then you can target that one like this:
var elem = document.getElementsByTagName("footer")[0];
Otherwise, you could assign that element an ID, or figure out which footer item in the collection it was (i.e. document.getElementsByTagName("footer")[3]).
Once you have that specific element, you can remove it like this:
elem.parentNode.removeChild(elem);
The removeChild function and querySelector can be used to fulfil your needs.
function remove(){
var el=document.querySelector('footer.footer');
el.parentNode.removeChild(el);
}
remove();
<footer class="footer">
<div class="container-fluid wrapper">
...
</div>
</footer>
I need to create a function which gets user input (a css selector) and removes all of those elements.
This is the function so far
function removeBySelector(selector) {
var thisOne = document.querySelectorAll(selector);
for(var i = 0; i<thisOne.length; i++) {
document.removeChild(thisOne[0]);
};
};
and the HTML that starts it
<button type="button" name="button" onclick="removeBySelector(prompt('Type the selector e.g p/ p.pClass'));">Remove By Selector</button>
change your method to
function removeBySelector(selector)
{
var thisOne = document.querySelectorAll(selector);
for(var i = 0; i<thisOne.length; i++)
{
thisOne[i].parentNode.removeChild( thisOne[i] ); //changed parentElement to parentNode
};
}
i'd advise using the framework jQuery! It is a very powerful tool that helps you simplify and improve your JavaScript code and it's performance.
With jQuery you can easily use this piece of code to remove any elements by CSS selector.
// Use any CSS Selector here
var elements = $(".class");
$.each(elements, function(){
$(this).remove();
)};
This keeps your code very easy to read and has a high performance.
//Try this code:
var removeElement=function(selector){
$(document).find(selector).remove();
};
removeElement('h1'); // will remove all H1 elements from Document.
You can do the same, without using any library with pure javascript (ES6 syntax in this case):
let elements = document.querySelectorAll(".please-remove");
elements.forEach(e => e.remove());
<div>
<div class="keep">Keep this element</div>
<div class="please-remove">1</div>
<div class="please-remove">2</div>
<div class="please-remove">3</div>
<div class="please-remove">4</div>
<div class="please-remove">5</div>
<div class="please-remove">6</div>
</div>
I'm building a scraper in Node.js and have come up against a slight problem. I'm trying to build a function which gets an element's text, regardless of whether it's embedded in a <p> tag, in a <span> or just a <div> with text inside.
The following currently works ONLY for text contained in <p> tags:
function getDescription(product){
var text =[];
$('.description *')
.each(function(i, elem) {
var dirty = $(this).text();
var clean = sanitize(dirty).trim();
if (clean.length){
text.push(clean);
}
});
text.join(',');
sanitize(text).trim();
return text;
}
This works for code like this:
<div class="description">
<p>Test test test</p>
</div>
But doesn't work for this:
<div class="description">
Test test test
</div>
For reference, the sanitize and trim functions are part of Node Validator, but that's not particularly relevant to my problem - they just take a string and remove whitespace from it.
Any ideas on what I can do to make the one function work for BOTH instances? To add insult to injury, I'm slightly more limited as node uses the cheerio library to replicate some functions of jQuery, but not all of them.
Use .contents() instead of *
function getDescription(product){
var text =[];
$('.description').contents()
.each(function(i, elem) {
var dirty = $(this).text();
var clean = sanitize(dirty).trim();
if (clean.length){
text.push(clean);
}
});
text.join(',');
sanitize(text).trim();
return text;
}
Use $(".description").contents() (docs).
The * only selects element nodes, but not text nodes.
You can use innerText:
var text =[];
$('.description').each(function(i, elem) {
var dirty = elem.innerText;
var clean = sanitize(dirty).trim();
if (clean.length){
text.push(clean);
}
});
Folks,
Let's say that I have the following situation:
<div class="outer">
<div>
<span>
<ul>
<div> </div>
<div> </div>
</ul>
</span>
</div>
</div>
How would I find the total number of elements inside div.outer? Something like $('div.outer').children().size() or length returns 1 (I'm looking, in this case, for 5) is there a shortcut or function to find the total element count using js/jQuery or should I write a function just for this issue? TIA.
var totalDescendants = $('div.outer *').length;
and done.
var totalDescendants = $('div.outer').find('*').length;
would also work.
A simple (and likely faster than jQuery) JavaScript alternative would be
var el = document.getElementById("foo");
var descendantElementCount = el.getElementsByTagName("*").length;
This does assume you've given the element an id. You could use jQuery to get all the elements with class outer, if this is important:
var descendantElementCount = 0;
$('div.outer').each(function() {
descendantElementCount += this.getElementsByTagName("*").length;
});
jQuery recursive child node count function:
jQuery(document).ready(function(){
var totalChildren=jQuery("*","div.outer").length;
});