I would like to change the product names on all product pages from h2 to h1
I would like to change this somehow to h1 with custom code.
<h2 itemprop="name" class="product_title likeh2">Aspen Ágykeret Bársony Sötétzöld 160 cm</h2>
You could to something like this:
//select all h2 elements
document.querySelectorAll('h2').forEach( element => {
//create new h1 element
const newElement = document.createElement('h1');
//set the inner html to the original h2 element
newElement.innerHTML = element.innerHTML;
//take all attributes from original element and assign them to the new one
Array.from(element.attributes).forEach( attr => {
newElement.setAttribute(attr.nodeName, attr.nodeValue)
})
//replace the node in the dom
element.parentNode.replaceChild(newElement, element);
})
Here's one way to do it. It will depend on browser support for outerHTML, but that's looking pretty good nowadays: https://caniuse.com/#search=outerHTML
querySelectorAll is used rather than getElementsByTagName because the array of elements does not change even as the elements change. When you actually update the element within that array, it uses the reference to update the actual element, but it doesn't change within the array. That way we can continue looping through and altering all <h2> tags on the document, whereas the live list returned by getElementsByTagName would lose elements each time an h2 tag is converted to an h1.
const hTwos = document.querySelectorAll('h2');
for (let i = 0; i < hTwos.length; i++) {
hTwos[i].outerHTML = hTwos[i].outerHTML.replace(/h2/g,"h1");
};
<h2>Product 1</h2>
<h2>Product 2</h2>
Related
Here out of all 4 header element I am getting only first header element to be printed as green
for (let i = 1; i <= 4; i++) {
var tag = document.createElement("h1");
var text = document.createTextNode(i + " Tutorix is the best e-learning platform");
tag.appendChild(text);
var element = document.getElementById("new");
element.appendChild(tag);
let h1 = document.querySelector("h1");
h1.setAttribute("style", "color: green;");
// console.log("Hi there"+h1);
}
<div id="new">
</div>
I am getting only first header element style color as green, why?
Because document.querySelector only selects the first element that matches.
If you want to set the color of the element you just added, use the reference you already have to the element: tag. (Side note: tag is an odd name for that variable, because it doesn't contain or refer to a tag, it refers to an element.)
for (let i = 1; i <= 4; i++) {
var tag = document.createElement("h1");
var text = document.createTextNode(i + " Tutorix is the best e-learning platform");
tag.appendChild(text);
var element = document.getElementById("new");
element.appendChild(tag);
tag.setAttribute("style", "color: green;");
}
<div id="new">
</div>
Side note: In general, it's cleaner to assign to properties on the style object rather than setting the style attribute:
tag.style.color = "green";
They do different things (the above only sets the color to green without changing anything else; setting the style attribute completely replaces all inline styles for the element with what you provide).
The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.
Query Selector
The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.
querySelectorAll
Let's say my code was something pretty simple like this:
let content = "";
for(let i=0; i<array.length; i++){
content+='<h1>array[i]</h1>';
}
document.getElementById('some_id').innerHTML = content;
I don't like the idea of putting HTML in my JavaScript code, but I don't know any other way of inserting elements into the DOM without using innerHTML, JQuery's html() method, or simply creating new DOM elements programmatically.
In the industry or for best practices, what's the best way to insert HTML elements from JavaScript?
Thanks in advance!
You can use a DOMParser and ES6 string literals:
const template = text => (
`
<div class="myClass">
<h1>${text}</h1>
</div>
`);
You can create a in memory Fragment:
const fragment = document.createDocumentFragment();
const parser = new DOMParser();
const newNode = parser.parseFromString(template('Hello'), 'text/html');
const els = newNode.documentElement.querySelectorAll('div');
for (let index = 0; index < els.length; index++) {
fragment.appendChild(els[index]);
}
parent.appendChild(fragment);
Since the document fragment is in memory and not part of the main DOM tree, appending children to it does not cause page reflow (computation of element's position and geometry). Historically, using document fragments could result in better performance.
Source: https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment
Basically you can use whatever template you want because it's just a function that return a string that you can feed into the parser.
Hope it helps
You can use the createElement() method
In an HTML document, the document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn't recognized.
Here is an example,
document.body.onload = addElement;
function addElement () {
// create a new div element
var newDiv = document.createElement("div");
// and give it some content
var newContent = document.createTextNode("Hi there and greetings!");
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
}
<!DOCTYPE html>
<html>
<head>
<title>||Working with elements||</title>
</head>
<body>
<div id="div1">The text above has been created dynamically.</div>
</body>
</html>
A flexible and more faster (efficient) way to insert HTML elements using JavaScript's insertAdjacentHTML method. It allows you to specify exactly where to place the element. Possible position values are:
'beforebegin'
'afterbegin'
'beforeend'
'afterend'
Like this:
document.getElementById("some_id").insertAdjacentElement("afterbegin", content);
Here's a Fiddle example
Creating the element programmatically instead of via HTML should have the desired effect.
const parent = document.getElementById('some_id');
// clear the parent (borrowed from https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript)
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
// loop through array and create new elements programmatically
for(let i=0; i<array.length; i++){
const newElem = document.createElement('h1');
newElem.innerText = array[i];
parentElement.appendChild(newElem);
}
I have created my own JS library. In that i am trying to define append method like this:
append: function (els) {
var elChild = document.createElement('span');
elChild.innerHTML = els;
for(i = 0; i < this.length; i++){
this[i].appendChild(elChild);
}
}
Now i am calling this append method in my script tag of HTML page like this:
<body>
<h1 class="first_heading">hello</h1>
<h1 class="second_heading">hi</h1>
<button>Test Me</button>
</body>
<script>
dome.get('h1').append('<p>some text</p>');
</script>
But the problem is all h1 tags not appending the paragraph text. Only last h1 is appending paragraph text. Any solution?
https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild:
The Node.appendChild() method adds a node to the end of the list of children of a specified parent node. If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position
In other words, the same node can't appear in multiple places in a document. You have to call document.createElement('span') separately for each child you want to create.
As mentioned this this corresponds to the object in scope. In this scenario, it is the window object. Here is a simple way to append the string to all headers
function append(tagname, text) {
// get all tag names
all_t = document.getElementsByTagName(tagname);
// loop through and append the string to the inner html of each tag
for (var x = 0; x < all_t.length; ++x) {
all_t[x].innerHTML += text
}
}
append('h1', '<p>some text</p>')
<h1 class="first_heading">hello</h1>
<h1 class="second_heading">hi</h1>
<button id="b">Test Me</button>
Knowledge level: Beginner
What I expect from my code:
The user clicks on a class named open.
The textNode within 'open' gets replaced with a - sign.
Then I go to the first child of the parent of that class which is an h2 tag and get the title in order to place it within the sibling of 'open' named 'info'.
At last info turns visible.
The ternary operator is to check if we have only a nodeType of 3 within the firstChild. If yes get the text, if not then get the entire innerHTML.
Since I get a html collection from getElementsByClassName I tend to create a loop so that I can modify the style.
Why I do this or don't use jQuery:
I am trying to push myself and learn how to effectively manipulate the dom without third party libraries. I would appreciate hints on improving my code but please keep the basic structure the same as I am still not into advanced short cuts and I am trying to learn not copy.
Problem I am not sure how "correct" my idea of manipulating the dom is. I could not get this to work, neither do I know how to effectively tell javascript to handle only the currently clicked element.
http://jsfiddle.net/r7bL6vLy/28/
function wrapper () {
var open = document.getElementsByClassName(open);
function trigger (){
var info = this.nextSibling;
var getTitle = this.parentNode.firstChild.(nodeType == 3 ? textContent : innerHTML)
this.removeChild(textContent);
this.appendChild(document.createTextNode('-'));
info.appendChild(document.createTextNode(getTitle + 'details'));
info.style.visibility = 'visible';
}
for (i = 0; i < open.length; i++) {
open[i].addEventListener('click', trigger, false);
}
}
HTML
<div id='A'>
<h1>Stackoverflow Question</h1>
<div class='open'>+</div>
<div class='info'>Content A...</div>
</div>
<div id='B'>
<h1>Stackoverflow Question</h1>
<div class='open'>+</div>
<div class='info'>Content B...</div>
</div>
this.nextSibling will give you the textNode representing the whitespace between the elements. Use .this.nextElementSibling instead.
You don't need to do any traversal to change the + to a - since you already have the open element. Just assign it the new value.
this.textContent = "-";
To assign the h2 content, simple use .previousElementSibling.textContent and assign it to info.textContent
info.textContent = this.previousElementSibling.textContent
Some things you were doing wrong were:
using invalid syntax here:
var getTitle = this.parentNode.firstChild.(nodeType == 3 ? textContent : innerHTML)
Should have been an if statement, though the condition doesn't really seem necessary. You can use .textContent on an element too, as long as you don't need the HTML representation.
Technically you could do this:
var child = this.parentNode.firstElementChild;
var getTitle = child[child.nodeType === 3 ? "textContent" : "innerHTML"];
...but that's pretty ugly. Avoid clever tricks like this.
Using textContent as a reference to an element:
this.removeChild(textContent);
Things that could be improved:
When changing text, favor manipulating .textContent over creating new text nodes. The existing nodes are mutable and so can be reused.
If you want to copy a section of the DOM to a new location, don't use .innerHTML but instead use .cloneNode(true).
var copy = myElem.cloneNode(true);
targetElem.appendChild(copy);
Otherwise you're taking the DOM nodes, serializing them to HTML and then immediately parsing the HTML into new nodes. All that string manipulation can be avoided simply by cloning.
You almost had it:
function trigger (){
var info = this.nextElementSibling,
getTitle = this.parentNode.firstElementChild.textContent;
this.textContent = '-';
info.appendChild(document.createTextNode(getTitle + 'details'));
info.style.visibility = 'visible';
}
var open = document.getElementsByClassName('open');
for (i = 0; i < open.length; i++)
open[i].addEventListener('click', trigger, false);
function trigger (){
var info = this.nextElementSibling,
getTitle = this.parentNode.firstElementChild.textContent;
this.textContent = '-';
info.appendChild(document.createTextNode(getTitle + 'details'));
info.style.visibility = 'visible';
}
var open = document.getElementsByClassName('open');
for (i = 0; i < open.length; i++)
open[i].addEventListener('click', trigger, false);
#a, #b {
width:50%;
height:100%;
margin:auto;
}
h1 {
width:100%;
font-size:160%;
text-align:center;
}
.open {
width:22%;
margin:auto;
padding:10% 0;
line-height:0;
font-size:150%;
text-align:center;
font-weight:bold;
background:yellow;
border-radius:100%;
}
.info {
width:100%;
padding:5%;
margin:5% auto 0 auto;
text-align:center;
background:ghostwhite;
visibility:hidden;
}
<div id='A'>
<h1>Stackoverflow Question</h1>
<div class='open'>+</div>
<div class='info'>Content A...</div>
</div>
<div id='B'>
<h1>Stackoverflow Question</h1>
<div class='open'>+</div>
<div class='info'>Content B...</div>
</div>
Remember that whitespace between elements becomes a text node. So better use firstElementChild and nextElementSibling instead of firstChild and nextSibling.
I want to know if we can change tag name in a tag rather than its content. i have this content
< wns id="93" onclick="wish(id)">...< /wns>
in wish function i want to change it to
< lmn id="93" onclick="wish(id)">...< /lmn>
i tried this way
document.getElementById("99").innerHTML =document.getElementById("99").replace(/wns/g,"lmn")
but it doesnot work.
plz note that i just want to alter that specific tag with specific id rather than every wns tag..
Thank you.
You can't change the tag name of an existing DOM element; instead, you have to create a replacement and then insert it where the element was.
The basics of this are to move the child nodes into the replacement and similarly to copy the attributes. So for instance:
var wns = document.getElementById("93");
var lmn = document.createElement("lmn");
var index;
// Copy the children
while (wns.firstChild) {
lmn.appendChild(wns.firstChild); // *Moves* the child
}
// Copy the attributes
for (index = wns.attributes.length - 1; index >= 0; --index) {
lmn.attributes.setNamedItem(wns.attributes[index].cloneNode());
}
// Replace it
wns.parentNode.replaceChild(lmn, wns);
Live Example: (I used div and p rather than wns and lmn, and styled them via a stylesheet with borders so you can see the change)
document.getElementById("theSpan").addEventListener("click", function() {
alert("Span clicked");
}, false);
document.getElementById("theButton").addEventListener("click", function() {
var wns = document.getElementById("target");
var lmn = document.createElement("p");
var index;
// Copy the children
while (wns.firstChild) {
lmn.appendChild(wns.firstChild); // *Moves* the child
}
// Copy the attributes
for (index = wns.attributes.length - 1; index >= 0; --index) {
lmn.attributes.setNamedItem(wns.attributes[index].cloneNode());
}
// Insert it
wns.parentNode.replaceChild(lmn, wns);
}, false);
div {
border: 1px solid green;
}
p {
border: 1px solid blue;
}
<div id="target" foo="bar" onclick="alert('hi there')">
Content before
<span id="theSpan">span in the middle</span>
Content after
</div>
<input type="button" id="theButton" value="Click Me">
See this gist for a reusable function.
Side note: I would avoid using id values that are all digits. Although they're valid in HTML (as of HTML5), they're invalid in CSS and thus you can't style those elements, or use libraries like jQuery that use CSS selectors to interact with them.
var element = document.getElementById("93");
element.outerHTML = element.outerHTML.replace(/wns/g,"lmn");
FIDDLE
There are several problems with your code:
HTML element IDs must start with an alphabetic character.
document.getElementById("99").replace(/wns/g,"lmn") is effectively running a replace command on an element. Replace is a string method so this causes an error.
You're trying to assign this result to document.getElementById("99").innerHTML, which is the HTML inside the element (the tags, attributes and all are part of the outerHTML).
You can't change an element's tagname dynamically, since it fundamentally changes it's nature. Imagine changing a textarea to a select… There are so many attributes that are exclusive to one, illegal in the other: the system cannot work!
What you can do though, is create a new element, and give it all the properties of the old element, then replace it:
<wns id="e93" onclick="wish(id)">
...
</wns>
Using the following script:
// Grab the original element
var original = document.getElementById('e93');
// Create a replacement tag of the desired type
var replacement = document.createElement('lmn');
// Grab all of the original's attributes, and pass them to the replacement
for(var i = 0, l = original.attributes.length; i < l; ++i){
var nodeName = original.attributes.item(i).nodeName;
var nodeValue = original.attributes.item(i).nodeValue;
replacement.setAttribute(nodeName, nodeValue);
}
// Persist contents
replacement.innerHTML = original.innerHTML;
// Switch!
original.parentNode.replaceChild(replacement, original);
Demo here: http://jsfiddle.net/barney/kDjuf/
You can replace the whole tag using jQuery
var element = $('#99');
element.replaceWith($(`<lmn id="${element.attr('id')}">${element.html()}</lmn>`));
[...document.querySelectorAll('.example')].forEach(div => {
div.outerHTML =
div.outerHTML
.replace(/<div/g, '<span')
.replace(/<\/div>/g, '</span>')
})
<div class="example">Hello,</div>
<div class="example">world!</div>
You can achieve this by using JavaScript or jQuery.
We can delete the DOM Element(tag in this case) and recreate using .html or .append menthods in jQuery.
$("#div-name").html("<mytag>Content here</mytag>");
OR
$("<mytag>Content here</mytag>").appendTo("#div-name");