can't change outerHTML with javascript - javascript

I have this HTML template on a page:
<div id="bid_wrapper_[[bid_id]]_[[template]]">
<div class="form_item_block" id="bid_wrapper_[[bid_id]]_[[template]]">
<div id="bid_delete_[[bid_id]]_[[template]]"><img src="/images/icons/cross.png"></div>
<div id="bid_label_wrapper_[[bid_id]]_[[template]]">Bid #1</div>
<div><input type="text" name="bid_summary" id="bid_summary_[[bid_id]]_[[template]]"></div>
<div><input name="bid_price" id="bid_price_[[bid_id]]_[[template]]"></div>
</div>
</div>
I'm trying to strip out the _[[template]] text, and also replace the [[bid_id]] with a number. I tried this:
var bid_template = document.getElementById('bid_wrapper_[[bid_id]]_[[template]]').cloneNode(true)
var new_bid_id = 2
var new_oh = bid_template.outerHTML
new_oh = new_oh.replace(/_\[\[template\]\]/g, '')
new_oh = new_oh.replace(/\[\[bid_id\]\]/g, new_bid_id)
At this point if I console.log new_oh, it is exactly what I want - everything is replaced correctly. However the next lines...
var new_bid = document.createElement('div')
new_bid.outerHTML = new_oh
Nothing happens here when I try to set the outerHTML. It does work if I set the innerHTML, but I would prefer to set the outerHTML. I don't get any error messages, and I can't figure out why it's not setting the outerHTML.

I assuming the error has occurred : that 'outerHTML' property on 'Element', so element has no parent node.
if you want to create it with new div, then :
var div = document.createElement('div');
div.innerHTML = output;
document.body.appendChild(div);
if not : then try this
var bid_template = document.getElementById('bid_wrapper_[[bid_id]]_[[template]]').cloneNode(true);
var new_bid_id = 2;
var parent = document.querySelector('.parent');
var new_oh = bid_template.outerHTML;
var output = new_oh.replace(/_\[\[template\]\]/g, '');
output = output.replace(/\[\[bid_id\]\]/g, new_bid_id);
parent.innerHTML = output;
alert(output)
<div class="parent">
<div id="bid_wrapper_[[bid_id]]_[[template]]">
<div class="form_item_block" id="bid_wrapper_[[bid_id]]_[[template]]">
<div id="bid_delete_[[bid_id]]_[[template]]">
<img src="/images/icons/cross.png">
</div>
<div id="bid_label_wrapper_[[bid_id]]_[[template]]">Bid #1</div>
<div>
<input type="text" name="bid_summary" id="bid_summary_[[bid_id]]_[[template]]">
</div>
<div>
<input name="bid_price" id="bid_price_[[bid_id]]_[[template]]">
</div>
</div>
</div>
</div>

You need to insert or append the new_bid div to the document first, then reset its outerHTML.

Related

Adding Div With IFrame Through JavaScript

I need to newProductPanelContainer insie replaceclass="Replace" through JS. I'm wondering why this doesn't add anything? I'm adding an iframe to it.
Where to add
<div class="Replace">
<div class="hello">Hello</div>
<div class="hi">Hi</div>
<div class="yes">Wait</div>
</div>
Expected Output
<div class="Replace">
<div class="hello">Hello</div>
<div class="hi">Hi</div>
<div class="yes">Wait</div>
<div class="newProductPanelContainer">
<iframe id="productPanelIFrame" src="https://test.com" width="100%" height="100%" style="border: none"></iframe>
</div>
</div>
Iframe div
<script type="text/javascript">
var innerDiv = document.createElement("div");
innerDiv.className = 'newProductPanelContainer';
innerDiv.innerHTML = `<iframe id="productPanelIFrame" src="https://test.com" width="100%" height="100%" style="border: none"></iframe>`;
innerDiv.style.width = "100%";
var hello = document.getElementsByClassName("Replace");
hello.appendChild(innerDiv);
</script>
getElementsByClassName returns a collection. You can iterate over the collection and add the iframe to each element in the collection or select an (probably the first) element and add the iframe to that.
Alternatively use the querySelector method which returns the first matching element in the DOM. This is what I have done below. Note don't get confused with querySelectorAll, which returns a collection.
var innerDiv = document.createElement("div");
innerDiv.className = 'newProductPanelContainer';
innerDiv.innerHTML = `<p>I'm inserted</p><iframe id="productPanelIFrame" src="https://test.com" width="100%" height="100%" style="border: none"></iframe>`;
innerDiv.style.width = "100%";
var hello = document.querySelector(".Replace");
hello.appendChild(innerDiv);
<div class="Replace">
<div class="hello">Hello</div>
<div class="hi">Hi</div>
<div class="yes">Wait</div>
</div>
#1: You can not create an element with specific class name newProductPanelContainer with just document.createElement("newProductPanelContainer")
you can use the 2nd parameter to do that (the options) refer this
#2: You can not get the DOM of un-mount element const productPanelIFrame = document.getElementById("productPanelIFrame");
the Iframe.productPanelIFrame is the children of div.newProductPanelContainer. But you can see, its parent has not mounted yet.
Try this. It works for me
const innerDiv = document.createElement("div");
innerDiv.className = "newProductPanelContainer";
innerDiv.style.width = "100%";
const iFR = document.createElement("iframe");
iFR.id = "productPanelIFrame";
iFR.src = "https://test.com";
iFR.width = "100%";
iFR.height = "100%";
iFR.style = "border: none";
const hello = document.getElementsByClassName("Replace");
hello[0].appendChild(innerDiv);
innerDiv.appendChild(iFR);

Appendchild only works on last element

I am trying to create an element in JavaScript and apply it to all elements by class name. For this example I will use a paragraph for ease. The purpose of creating an element by JavaScript however is because I want to create a different element later on in my code.
In the code I am using, only the last element of the array of elements will contain the element created by the JavaScript. Could anyone explain why this is happening and what I could do to solve the problem accordingly to my requirement? I am trying to apply a whole element inside another element (so not just a value or property of a paragraph element).
My code:
//Creating my element:
let myElement = document.createElement("p");
/*let text = document.createTextNode("test");
myElement.appendChild(text);*/ //<-- Enable following to see text in result or check developer console for added paragraphs
//Single example:
let ele = document.getElementById("bar");
ele.appendChild(myElement);
//Not working...:
//Now class:
let eles = document.getElementsByClassName("foo");
for (i = 0; i < eles.length; i++) {
//eles[i].innerHTML = "abc";//<-- Does work (but hardcoded)?
//eles[i].innerHTML = myElement;//<-- returns "[object HTMLParagraphElement]"?
eles[i].appendChild(myElement); //<!-- Does work only for last element in array?
}
<div class="foo" id="bar">
</div>
<div class="foo">
</div>
<div class="foo">
</div>
<div class="foo">
<!-- Only this one will obtain the the paragraph element? -->
</div>
JSFiddle
You need to use cloneNode of element <p>, because appendChild moves it from its current position to the new position. See documentation
//Creating my element:
const myElement = document.createElement("p");
myElement.innerHTML = 'paragraph';
//Single example:
const ele = document.getElementById("bar");
ele.appendChild(myElement.cloneNode(true));
//Now class:
const eles = document.getElementsByClassName("foo");
for (let i = 0; i < eles.length; i++) {
eles[i].appendChild(myElement.cloneNode(true));
}
.foo {
border: 1px solid #333;
}
.foo p {
font-weight: bold;
}
<div class="foo" id="bar">
bar:
</div>
<div class="foo">
foo1
</div>
<div class="foo">
foo2
</div>
<div class="foo">
foo3
</div>
Your <p> element is appended only to the last because it is assigned to the myElementvariable. And because that variable is declared before your loop, each iteration will move the <p> tag through all your <div.foo>.
But if you declare your paragraph inside your for loop, a new one is created and appended to each of your blocks, because there are all different elements.
let eles = document.getElementsByClassName("foo");
for (i = 0; i < eles.length; i++) {
let myElement = document.createElement("p");
myElement.innerText = 'I am a paragraph.';
eles[i].appendChild(myElement);
}
<div class="foo" id="bar">
</div>
<div class="foo">
</div>
<div class="foo">
</div>
<div class="foo">
</div>

How to add a div between two divs by Javascript

I am using wordpress and I want to add some html code on page using Javascript. I don't want to make child theme then edit php files. It is risky and I don't know about php.
I want to add a sibling div. This is an example code as default.
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
Now I want to add my custom div and its inside html between both div1 and div2.
<div class="mydiv">
<div class="mydivinside">
Text
</div>
</div>
Please let me know how is it possible using Javascript.
There are (at least) two ways, the first:
// document.querySelector() finds, and returns, the first element
// matching the supplied selector (or null, if no element is found):
var el1 = document.querySelector('.div1');
// here we create an adjacent element from the string of HTML,
// the 'afterend' argument states that this adjacent element
// follows the el1 node, rather than preceding it or appearing
// within:
el1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
var div1 = document.querySelector('.div1');
div1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
And the second where you first create that <div> to be inserted, and then use parentNode.insertBefore():
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
// here we create a <div> element:
div = document.createElement('div'),
// we retrieve the element after which the new
// element should be inserted:
div1 = document.querySelector('.div1');
// assign the supplied HTML string to the innerHTML of the
// created element:
div.innerHTML = htmlString;
// and use parentNode.insertBefore to insert the desired element
// (the first argument) before the element identified in the
// second argument, which is the nextSibling of the found
// 'div1' element:
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
div = document.createElement('div'),
div1 = document.querySelector('.div1');
div.innerHTML = htmlString;
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
References:
document.createElement().
document.querySelector().
Element.insertAdjacentHTML().
Node.firstChild.
Node.insertBefore().
Node.nextSibling.
Node.parentNode.
Use Node#insertBefore method.
// create a div element
var div = document.createElement('div');
// set class name
div.className = 'mydiv';
// set html contents
div.innerHTML = ' <div class="mydivinside"> Text </div>';
// get .div2 element
var ele = document.querySelector('.div2');
// insert before the .div2 element by getting
// its parent node
ele.parentNode.insertBefore(div, ele);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
You can just use the before method to append a div between both div1 and div2. Here is the example:
$('.div2inside').before("<div class='mydiv'><div class='mydivinside'>Text</div></div>");
You could do something like this?
var firstDiv = document.getElementById('div1');
firstDiv.parentNode.insertBefore(document.getElementById('new-div'), firstDiv.nextSibling);
This however assumes that your new-div is already in the dom.
EDIT: to create a the new-div on the fly you can use #david-thomas's solution https://stackoverflow.com/a/41425079/1768337
This link will be helpfull to get the above result.
https://plainjs.com/javascript/manipulation/insert-an-element-after-or-before-another-32/

Adding a child element to all divs of the same class

I'm attempting to add a child span to all div's with the same class.
I can achieve this to a individual element by targeting its Id
HTML
<div id="h1" class="header">Hello </div>
<hr>
<div id="h2" class="header">what about this one </div>
JavaScript
var header = document.getElementById('h1');
var newSpan = document.createElement("span");
header.appendChild(newSpan);
newSpan.innerHTML = "i'm here";
However when I change it to
var header = document.getElementsByClassName('header');
It fails to work.
Can anyone see where I'm going wrong?
JSFiddle
To do that you need to iterate over them, since getElementsByClassName() returns an array like html element collection. You can use for loop
var headers = document.getElementsByClassName('header');
for (var i = 0; i < headers.length; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = "i'm here";
headers[i].appendChild(newSpan);
}
<div id="h1" class="header">Hello</div>
<hr>
<div id="h2" class="header">what about this one</div>
or you can use Array.prototype.forEach with call() to iterate over it
var headers = document.getElementsByClassName('header');
[].forEach.call(headers,function(ele) {
var newSpan = document.createElement("span");
newSpan.innerHTML = "i'm here";
ele.appendChild(newSpan);
})
<div id="h1" class="header">Hello</div>
<hr>
<div id="h2" class="header">what about this one</div>
For more about iteration check :- For loop for HTMLCollection elements
The javascript document.getElementById will return only one Id, but document.getElementByClassName will return a collection of array-like objects and it should be used here.
I have updated your js code to :
var header = document.getElementsByClassName('header');
//console.log(header);
for(var i=0;i<header.length;i++){
var newSpan = document.createElement("span");
header[i].appendChild(newSpan);
newSpan.innerHTML = "i'm here";
}
and HTML code to :
<div id="h1" class="header">Hello </div>
<hr>
<div id="h2" class="header">what about this one </div>
HTML code had some slight mistake of class"header" instead class="header"
Fiddle
You can consider inserting the text as CSS generated content:
.header::after {
content: "i'm here";
}
<div id="h1" class="header">Hello </div>
<hr />
<div id="h2" class="header">what about this one </div>

find the id of the next element present in next div-jquery

My form has number of input elements. When i looping through some elements i need to find the id of the next element which is in next div.
The whole code is in jsfiddle
$(":text[name^=sedan]").each(function(i){
var curTxtBox = $(this);
var curId = this.id;
alert(curId);
//var nextTextFieldId = $(this).closest('div').find('.number').attr("id"); // gives undefined
var nextTextFieldId = $('#'+curId).next('div:input[type=text]').attr("id"); // gives undefined
alert(nextTextFieldId )
});
this is not working. nextTextFieldId gives value undefined.
html
<div class="first">
<div class="second">
<input type="text" class ="myClass" name="sedan1" id = "sedan1" value="1" />
</div>
<div class="third">
<input type="text" class ="yourClass" name="suv1" id ="suv1" value="2"/>
</div>
</div>
<div class="first">
<div class="second">
<input type="text" class ="myClass" name="sedan2" id = "sedan2" value="3" />
</div>
<div class="third">
<input type="text" class ="yourClass" name="suv2" id = "suv2" value="" />
</div>
</div>
var nextTextFieldId = $(this).parent().next().find(':text').attr("id");
Expanding my comment (summary: don't do this, simply iterate over the jQuery object with for and be happy) into an answer:
$(document).ready(function(){
var $textBoxes = $(":text[name^=sedan]");
for(var i = 0; i < $textBoxes.length; ++i) {
var $curTxtBox = $textBoxes.eq(i);
alert($curTxtBox.attr("id"));
if (i < $textBoxes.length - 1) {
var nextTextBoxId = $textBoxes.eq(i + 1).attr("id");
alert(nextTextBoxId);
}
else {
// This was the last one, there is no "next" textbox
}
}
});
Note that:
Doing things this way does not require walking the DOM tree all the time like naive approaches using each (which end up searching the tree for the same element multiple times).
This approach will work correctly as long as you keep the sedanXX ids. Approaches that re-walk the DOM tree will break as soon as there is any significant change to your HTML.
If all you want is the id's, and they are incrementing integers, even this is overkill.
Try changing to this line:
var nextTextFieldId = $('#'+curId).parent().next('div:input[type=text]').attr("id"); // gives undefined
Your line expects the input tag to have a sibling div tag.

Categories

Resources