How can you change the hyrarchy / structure of html when it's rendered with javascript?
I would like to remove a parent div and copy it's attribute and classname
to it's child element. But I want to do this in the whole page that contains a certain class name.
In code example: I need this code
<div class="abc" myid="123" position="2">
<div class="someblock">
<p>Some paragraph</p>
<img width="140px; height: 140px; class="myimg" src="url to imgage">
</div>
changed to :
<div class="someblock" class="abc" myid="123" position="2">
<p>Some paragraph</p>
<img width="140px; height: 140px; class="myimg" src="url to imgage" />
</div>
Does anyone know how this can be done with JavaScript, or jQuery?
Thanks in advance!,
Chris.
You can try:
<script>
$('.abc').each(function(){
$(this).children().addClass($(this).attr('class'));
$(this).children().attr('myid', $(this).attr('myid'));
$(this).children().attr('position', $(this).attr('position'));
$('body').append($(this).html());
$(this).remove();
});
</script>
Be careful.
$('.someblock').each(function () {
var pt = $(this).parent(),
cl = pt.attr('class'),
id = pt.attr('id'),
pos = pt.attr('position');
$(this).unwrap().attr({id:id, position:pos}).addClass(cl);
});
May be something like this could help:
function deleteParent(id){
var element = document.getElementById(id);
var parent = element.parentNode;
var grandParent = parent.parentNode;
var html = parent.innerHTML;
grandParent.removeChild(parent);
grandParent.innerHTML += html;
}
$('.abc .someblock').contents().unwrap().parent().addClass('someblock');
Demo ---> http://jsfiddle.net/VQRQV/1/
var el = document.getElementById('123');
if(el) {
el.className += el.className ? ' someblock' : 'abc';
}
You can do this first by getting all the elements as
var allElem = document.getElementByID ("*");
then loop through all the elements.
To get to child element check whether a element has children find the last child and a get attribute value example:
var elemVal = allElem[i].className ; or allElem[i].getAttribute("xyx")
and then put the value of this element to desired element in html.
document.getElementById("div").className = elemVal ;
Related
Using the solution suggested here: https://stackoverflow.com/a/32135318/10279127 i'm trying to create a new div, and append it inside a parent div with id, next to a child <a> html element.
html:
<div id="div0">
anchor text
// I'd like to place the new div here
</div>
js:
Element.prototype.appendAfter = function(element) {
element.parentNode.insertBefore(this, element.nextSibling);
}, false;
var NewElement = document.createElement('div');
NewElement.id = 'newDivID';
var tToAfter = $('#div' + index + ' > a'); // this is what i tried but doesn't work
NewElement.appendAfter(tToAfter);
If inside .appendAfter(...) instead of tToAfter i write document.getElementById('randomElementId') it works and appends it, so i think must be pure javascript, is there a way in js to do something like: document.getElementById('div' + index).firstChild to get the <a> ?
Or to make it entirely with jQuery using the insertAfter (https://stackoverflow.com/a/8707793/10279127) ?
you can select inside div#div0 by using
const anchor = document.querySelector("#div0>a");
You can simplify your approach by using insertAdjacentElement. For example (the css is irrelevant - just there so you can visually see the inserted div):
const anchor = document.querySelector('#div0 a');
const elem = document.createElement('div');
elem.id = 'newDivID';
anchor.insertAdjacentElement('afterend', elem);
div:not(#div0) {
height: 20px;
background-color: green;
}
<div id="div0">
anchor text
// I'd like to place the new div here
</div>
I am looking for a way to get the entire HTML document, excluding a few items (possibly tagged with a className called 'exclude') as a string.
I know I can grab the entire document with document.documentElement.innerHTML
or document.documentElement.outerHTML
and document.getElementsByTagName('html')[0].innerHTML
What i am still still struggling with is how do I exclude some of the nodes (such as buttons or divs or any other tags, that have a common className, before I get the innerHTML?
I'd probably clone the whole tree, then remove the elements you don't want:
var clone = document.body.cloneNode(true);
clone.querySelectorAll(".exclude").forEach(function(element) {
element.parentNode.removeChild(element);
});
var html = clone.outerHTML;
Note that this assumes body, itself, doesn't have the exclude class.
Example:
var clone = document.body.cloneNode(true);
// Snippet-specific: Also remove the script
clone.querySelectorAll(".exclude, script").forEach(function(element) {
element.parentNode.removeChild(element);
});
var html = clone.outerHTML;
console.log(html);
<div>
I want this
<div>And this</div>
</div>
<div class="exclude">
I don't want this
<div>Or this, since its parent is excluded</div>
</div>
I know I'm late to the party but here is my contribution, I have used chŝdk's idea to implement it.
let markup = document.querySelectorAll('*:not(.exclude)')[0].innerHTML;
console.log("Data Type: " + typeof(markup));
console.log(markup);
<center>
<div>Hello World</div>
<div class="exclude">Hello World [Exclude Me]</div>
<div>Hello World</div>
<div>Hello World</div>
<div>Hello World</div>
<div class="exclude">Hello World [Exclude Me]</div>
<div class="exclude">Hello World [Exclude Me]</div>
<div>Hello World</div>
<div>Hello World</div>
<div class="exclude">Hello World [Exclude Me]</div>
</center>
Well you can use querySelector() along with the :not() css selector upon your HTML block, to exclude unwanted elements from it.
var content = document.getElementsByTagName('html')[0]
var selection = content.querySelectorAll('*:not(.ignore)');
Then just use outerHTML to get the whole content from your selection:
var htmlString = selection[0].outerHTML;
Otherwise you can loop over the selection elements and for each one append its HTML to your result string:
var htmlString = "";
selection.forEach(function(el) {
htmlString += el.innerHTML;
});
Demo:
var content = document.getElementsByTagName('html')[0]
var selection = content.querySelectorAll('*:not(.ignore)');
//Then log the selection content
console.log(selection[0].outerHTML);
//Or maybe loop throught the elements and get their contents
var htmlString = "";
selection.forEach(function(el) {
htmlString += el.innerHTML;
});
console.log(htmlString);
Note:
In this demo there were no elements with ignore class, but you can always put it and test.
You can see that this will also keep all HTML elements including
scripts and styles tags.
I am modifying an elements innerHTML property inside a $.each() loop. Now if my stack of elements contains childrens of the element where I update the innerHTML, the DOM reference of that children will get lost.
Example:
$(function(){
$stack = $(".myelement, .myelement *");
$stack.each(function(){
var $this = $(this);
var element = $(this)[0];
console.log(element.innerHTML = element.innerHTML + " modified");
});
});
Fiddle: https://jsfiddle.net/b0ux0v5e/
What happens is that I first modify the innerHTML of .myelement. This includes the children p. Therefore the DOM reference of this element is get lost and "modified" will not be appended.
How can such an scenario be solved without building a function that creates a unique selector for the element and re-catches it in each loop?
Note: I am not asking for specifically appending some text to nodes. This is just an example. In a real project I am replacing text in the innerHTML.
I guess you want to modify the text content. in this case you would like to know about .contents() method, which lets you loop through with text nodes as well:
$(function() {
$(".myelement").contents().each(function(i, el) {
el.textContent += " 'modified'";
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myelement">
I am the myelement
<p>
Hello world
</p></div>
Don't modify innerHTML, it will destroy/recreate all the elements inside and force a re-render. You can use insertAdjacentHTML or jQuery's append to add to an element.
Also you do not need to do:
element = $(this)[0];
this will already be a reference to the element.
$(function(){
$stack = $(".myelement, .myelement *");
$stack.each(function(){
var $this = $(this);
//this.insertAdjacentHTML("beforeend"," modified");
//Or
$this.append(" modified");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="myelement">
<span>A span</span>
<div>A div</div>
<div>
<p>a paragraph in a div</p>
</div>
</div>
EDIT
As it seems you want to replace word(s) and not append a word, you could do a replace on the html and then reset it, but again this will destroy/recreate the elements inside, so if any of them have something like event listeners attached they will be lost
var modified = $".myelement").html().replace(/yourword/g,"modified");
$(".myelement").html(modified);
Or you could just loop over all the Text nodes and replace the word from there, this will keep the elements, their event listeners, and so on intact.
$(".myelement, .myelement *").contents().filter(function() {
return this.nodeType == 3;
}).each(function(){
this.textContent = this.textContent.replace(/A/g,"modified");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="myelement">
Inside A element <br>
<span>A span</span>
<div>A div</div>
<div>
<p>a paragraph in A div</p>
</div>
</div>
just change
$stack = $(".myelement, .myelement *");
to
$stack = $(".myelement");
And you will see in your console
I am the myelement
<p>
Hello world
</p> modified
I need a function which creates element and than adds text to that element and than adds that new element to a some location in DOM. I am noob to this.
I find this function but I don't know how to automaticaly specify location so that I can just call function and for example specify third argument as an element to which I want to append new element.
function appendElement (elemNode,textNode) {
var element = document.createElement(elemNode);
var text = document.createTextNode(textNode);
element.appendChild(text);
document.body.appendChild(element);
}
appendElement("b","lorem");
function appendElement (elemNode,textNode,containerToAppend) {
var container = document.getElementById(containerToAppend);
var element = document.createElement(elemNode);
var text = document.createTextNode(textNode);
element.appendChild(text);
container.appendChild(element);
}
appendElement("b","lorem","ContainerId");
Here's a way to do it in one line:
function appendElement (elemNode, textContent, parent) {
parent.appendChild(document.createElement(elemNode)).textContent = textContent;
}
appendElement("b","lorem", document.getElementById("container"));
div { background-color: aqua }
<div id="container"></div>
function appendElement (elemNode,textNode,containerToAppend) {
var container = document.getElementById(containerToAppend);
var element = document.createElement(elemNode);
var text = document.createTextNode(textNode);
element.appendChild(text);
container.appendChild(element);
}
appendElement("p","this is text","ContainerId");
Here is my attempt. Completely ripped off from developer.Mozilla.org with a minor tweak.
JSFIDDLE DEMO
Javascript:
function addElement() {
// Create a new div element and give it some content
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hi there and greetings!");
newDiv.appendChild(newContent); //Add the text node to the newly created div.
// Add the newly created element and its content into the Parent of the clicked button
var parentDiv = event.target.parentNode;
document.body.insertBefore(newDiv, parentDiv);
}
HTML
<div id="div1">
<input type="button" onclick="addElement(event)" value="Click me to add div" />
</div>
<div id="div2">
<input type="button" onclick="addElement(event)" value="Click me to add div" />
</div>
<div id="div3">
<input type="button" onclick="addElement(event)" value="Click me to add div" />
</div>
So I want to get the first <a> tag in this <div>. This is really driving me nuts. Thanks for any help.
HTML
<div id="PGD" class="album" onmouseover="load(this)">
<a class="dl" href="#">DOWNLOAD</a>
</div>
Javascript
function load(dl)
{
var ID = $(dl).attr('id');
var elemnt = $('ID:first').attr('id');
}
Non-jQuery: (was not tagged with jQuery before, so I included this)
If you want to get the first child element only:
var element = document.getElementById('PGD').children[0];
If you want to get the first anchor element:
var element = document.getElementById('PGD').getElementsByTagName('a')[0];
With jQuery:
var element = $('#PGD').find('a:first');
// or, to avoid jQuery's pseudo selecors:
// var element = $('#PGD').find('a').first();
and actually your function can just be
function load(dl)
{
var element = $(dl).find('a:first');
}
Update:
As you are using jQuery, I suggest to not attach the click handler in your HTML markup. Do it the jQuery way:
$(function() {
$("#PGD").mouseover(function() {
$(this).find('a:first').attr('display','inline');
alert($(this).find('a:first').attr('display'));
});
});
and your HTML:
<div id="PGD" class="album">
<a class="dl" href="#">DOWNLOAD</a>
</div>
See for yourself: http://jsfiddle.net/GWgjB/
$("#PGD").children("a:first")
This will give you the first child "a" tag, but not the descendents. E.g.
<div id="log">
<p>Foo</p>
Hello
Hello
</div>
Will give you : Hello
$(ID).find(':first')
See find jQuery command.
$('#PGD').find('a:first')
Actualy I've not understanding problem, so I'm trying correct your function, to make it clear for you:
function load(dl)
{
// var ID = $(dl).attr('id');
// var elemnt = $('ID:first').attr('id'); // Here is error-mast be like $(ID+':first')
var ID = $(dl).attr('id');
var elemnt = $(ID).find('*:first').attr('id');
}
I supose dl that is $('#PGD'). But child element A have not attribute id, what are you trying to find?
Also See: http://api.jquery.com/category/selectors/