How to append elements to the parent elements extracted by getElementsByClassName? - javascript

Below is my JSP code,
<%
while(resultSet1.next()){
out.println("<p class='comm'>");
out.println(resultSet1.getString("answer_content"));
out.println("</p>");
}
%>
Below is the script I have used,
<script>
$( document ).ready(function() {
var par = document.getElementsByClassName("comm");
var insert = document.createElement("form");
insert.setAttribute("action","ForumSubmitCommentController");
var text = document.createElement("input");
text.setAttribute("type","text");
text.setAttribute("name","comm_text");
text.setAttribute("id","comm_text");
insert.appendChild(text);
var comm_submit = document.createElement("input");
comm_submit.setAttribute("type","submit");
comm_submit.setAttribute("value","Comment");
insert.appendChild(comm_submit);
par.appendChild(insert);
});
</script>
I'am expecting to get a form attached to all the 'p' elements with "class='comm'" but I'm getting none. So can anyone point out what I'm doing wrong?
Thanks in advance.

because par is an array, so doesn't have appendChild method
$(document).ready(function () {
$('.comm').each(function () {
var insert = document.createElement("form");
insert.setAttribute("action", "ForumSubmitCommentController");
var text = document.createElement("input");
text.setAttribute("type", "text");
text.setAttribute("name", "comm_text");
text.setAttribute("id", "comm_text");
insert.appendChild(text);
var comm_submit = document.createElement("input");
comm_submit.setAttribute("type", "submit");
comm_submit.setAttribute("value", "Comment");
insert.appendChild(comm_submit);
this.appendChild(insert);
})
});
Demo: Fiddle
But a easier way to do it is to use
$(document).ready(function () {
var form = '<form action="ForumSubmitCommentController"><input type="text" name="comm_text" id="comm_text"><input type="submit" value="Comment"></form>';
$('.comm').append(form)
});
Demo: Fiddle

This kind of DOM manipulations is very basic stuff when you use some library (like jQuery) but sometimes can be hard or at least verbose with plain old DOM API.
For example document.getElementsByClassName returns HTMLCollection. It is array-like collection of elements found. You need to traverse it in some way to put your form to all of the elements.
For example:
nodesList = document.getElementsByClassName("helloworld");
for(var i = 0; i < nodeList.length; i++) {
var node = nodeList[i];
// create form etc...
node.appendChild(form);
}
Notice that HTMLCollection does not even provide forEach method - we have to use plain for-loop or convert it to Array first (e.g. by using hacks like this one). And you must create your form node (or use cloneNode) before every appendChild, because each DOM node is unique and appendChild only moves it to desire location.
jQuery and other libraries do that behind the scene, hiding complexities and making your code more readable. I suggest you to learn DOM API only to get the understanding about how things really work. In real projects just stick with jQuery, learn it and use it for all manipulations.

Related

How do we convert jQuery prepend() to VanillaJS [duplicate]

How can I implement prepend and append with regular JavaScript without using jQuery?
Here's a snippet to get you going:
theParent = document.getElementById("theParent");
theKid = document.createElement("div");
theKid.innerHTML = 'Are we there yet?';
// append theKid to the end of theParent
theParent.appendChild(theKid);
// prepend theKid to the beginning of theParent
theParent.insertBefore(theKid, theParent.firstChild);
theParent.firstChild will give us a reference to the first element within theParent and put theKid before it.
Perhaps you're asking about the DOM methods appendChild and insertBefore.
parentNode.insertBefore(newChild, refChild)
Inserts the node newChild as a child of parentNode before the
existing child node refChild. (Returns newChild.)
If refChild is null, newChild is added at the end of the list of
children. Equivalently, and more readably, use
parentNode.appendChild(newChild).
You didn't give us much to go on here, but I think you're just asking how to add content to the beginning or end of an element?
If so here's how you can do it pretty easily:
//get the target div you want to append/prepend to
var someDiv = document.getElementById("targetDiv");
//append text
someDiv.innerHTML += "Add this text to the end";
//prepend text
someDiv.innerHTML = "Add this text to the beginning" + someDiv.innerHTML;
Pretty easy.
If you want to insert a raw HTML string no matter how complex, you can use:
insertAdjacentHTML, with appropriate first argument:
'beforebegin'
Before the element itself.
'afterbegin'
Just inside the element, before its first child.
'beforeend'
Just inside the element, after its last child.
'afterend'
After the element itself.
Hint: you can always call Element.outerHTML to get the HTML string representing the element to be inserted.
An example of usage:
document.getElementById("foo").insertAdjacentHTML("beforeBegin",
"<div><h1>I</h1><h2>was</h2><h3>inserted</h3></div>");
DEMO
Caution: insertAdjacentHTML does not preserve listeners that where attached with .addEventLisntener.
I added this on my project and it seems to work:
HTMLElement.prototype.prependHtml = function (element) {
const div = document.createElement('div');
div.innerHTML = element;
this.insertBefore(div, this.firstChild);
};
HTMLElement.prototype.appendHtml = function (element) {
const div = document.createElement('div');
div.innerHTML = element;
while (div.children.length > 0) {
this.appendChild(div.children[0]);
}
};
Example:
document.body.prependHtml(`Hello World`);
document.body.appendHtml(`Hello World`);
Here's an example of using prepend to add a paragraph to the document.
var element = document.createElement("p");
var text = document.createTextNode("Example text");
element.appendChild(text);
document.body.prepend(element);
result:
<p>Example text</p>
In order to simplify your life you can extend the HTMLElement object. It might not work for older browsers, but definitely makes your life easier:
HTMLElement = typeof(HTMLElement) != 'undefined' ? HTMLElement : Element;
HTMLElement.prototype.prepend = function(element) {
if (this.firstChild) {
return this.insertBefore(element, this.firstChild);
} else {
return this.appendChild(element);
}
};
So next time you can do this:
document.getElementById('container').prepend(document.getElementById('block'));
// or
var element = document.getElementById('anotherElement');
document.body.prepend(div);
In 2017 I know for Edge 15 and IE 12, the prepend method isn't included as a property for Div elements, but if anyone needs a quick reference to polyfill a function I made this:
HTMLDivElement.prototype.prepend = (node, ele)=>{
try { node.insertBefore(ele ,node.children[0]);}
catch (e){ throw new Error(e.toString()) } }
Simple arrow function that's compatible with most modern browsers.
var insertedElement = parentElement.insertBefore(newElement, referenceElement);
If referenceElement is null, or undefined, newElement is inserted at the end of the list of child nodes.
insertedElement The node being inserted, that is newElement
parentElement The parent of the newly inserted node.
newElement The node to insert.
referenceElement The node before which newElement is inserted.
Examples can be found here: Node.insertBefore
You can also use unshift() to prepend to a list
document.write() is not a good practice, some browsers like Chrome give you a warning if you use it, and it may be a bad solution if you are providing it to a customer, they don't want to use your code and see warnings in the debug console!
Also jQuery may also be a bad thing if you are giving your code to a customer who already uses jQuery for other functionality on their site, there will be a conflict if there is already a different version of jQuery running.
If you want to insert content into an iframe, and do that with pure JS, and with no JQuery, and without document.write(), I have a solution.
You can use the following steps
1.Select your iframe:
var iframe = document.getElementById("adblock_iframe");
2.Create an element that you want to insert into the frame, let's say an image:
var img = document.createElement('img');
img.src = "https://server-name.com/upload/adblock" + id + ".jpg";
img.style.paddingLeft = "450px";
//scale down the image is we have a high resolution screen on the client side
if (retina_test_media == true && high_res_test == true) {
img.style.width = "200px";
img.style.height = "50px";
} else {
img.style.width = "400px";
img.style.height = "100px";
}
img.id = "image";
3.Insert the image element into the iframe:
iframe.contentWindow.document.body.appendChild(img);
This is not best way to do it but if anyone wants to insert an element before everything, here is a way.
var newElement = document.createElement("div");
var element = document.getElementById("targetelement");
element.innerHTML = '<div style="display:none !important;"></div>' + element.innerHTML;
var referanceElement = element.children[0];
element.insertBefore(newElement,referanceElement);
element.removeChild(referanceElement);

Javascript - remove button and parent

Hi I am just learning Javascript and after following some tutorials I thought it would be nice to practise some Javascript by making stuff.
So now I am trying to make a very easy to-do-list. Just for practise, but I get stuck.
I managed to add items with a remove-button to an UL with JS. But, BUT:
How do I make it so; when you click on the removeMe button, that only that Li will be removed?
What should I use?
Here's my code:
var buttonAdd = document.getElementById('but1');
var buttonRemove = document.getElementById('but2');
var ul = document.getElementById('myUl');
function addLi() {
var newLi = document.createElement('li');
var removeThis = document.createElement('button');
var textInput = document.getElementById('inputText').value;
if(textInput === ""){
alert('Add text');
}else{
newLi.innerHTML = textInput;
newLi.appendChild(removeThis);
removeThis.innerHTML = "Remove me";
removeThis.setAttribute("onClick", "removeMe(this);");
ul.appendChild(newLi);
}
}
buttonAdd.onclick = function() {
addLi();
};
buttonRemove.onclick = function() {
ul.innerHTML = "";
};
function removeMe(item){
//get called when clicked on the remove button
}
and my HTML:
<body>
<ul id="myUl"></ul>
<input id="inputText" type="text"><br />
<button id="but1">Add stuff</button><br />
<button id="but2">Remove all</button>
</body>
Thanks
The function remove() is a brand new DOM 4 method and not very widely supported yet. The clunky, but bulletproof way would be:
function removeMe(item){
item.parentElement.parentElement.removeChild(item.parentElement);
}
or with a bit more elegance:
function removeMe(item){
var parent = item.parentElement;
parent.parentElement.removeChild(parent);
}
http://jsfiddle.net/BtbR4/
Also be careful with this:
removeThis.setAttribute("onClick", "removeMe(this);");
Handing a function reference as a string is always a bad idea for several reasons (eval'ing the string, messing up the scope). There are several better options:
removeThis.onclick = removeMe;
or if you need to hand over parameters
removeThis.onclick = function(){removeMe(your,parameters)};
The best option however is to attach eventhandlers always like this:
Element.addEventListener("type-of-event",functionReference);
You just need to remove the parent node (the li), as I've shown using jsbin.
function removeMe(item){
item.parentNode.remove();
}
Please note Blue Skies's comment that this may not work across all browsers, an alternative is:
var par = item.parentNode; par.parentNode.removeChild(par);
a cleaner way to do things is to add
removeThis.onclick = removeMe;
and
function removeMe(mouseEvent){
this.parentNode.remove();
}
This is consistent with how you add the other onclick functions in your code. Since you said you are learning js, it is a good idea to learn how events and functions work. So, the take away from this is that the 'this' of a function that is attached to an object is the object itself (the removeThis object in this case), and event handlers give you access to the event that invoked them (mouseEvent) in the argument list.
JSfiddle: http://jsfiddle.net/QT4E3/

How to improve jQuery code

I have the syntax below. I was wondering if this part: $($(this).parent().siblings('div')[0]) could be writen more elegantly by accessing a jQuery object directly without the need to use $(); again.
I used .parent().siblings and didn't use the class of div because I want to reuse the code somewhere where the classes are different.
$('textarea').click(function(){
$($(this).parent().siblings('div')[0]).html('<span>140</span>');
$($(this).parent().siblings('div')[1]).html('<span>Reply</span>');
});
<div class="post_area2">
<div class="wrap_area2 left">
<textarea></textarea>
</div>
<div class="word_c left"></div>
<div class="submit left"></div>
</div>
You can use .eq() method.
$('textarea').click(function(){
$(this).parent().siblings('div')
.eq(0).html('<span>140</span>').end()
.eq(1).html('<span>Reply</span>');
});
Try
$('textarea').click(function(){
$(this).parent().next().html('<span>140</span>')
.next().html('<span>Reply</span>');
});
http://jsfiddle.net/rVfJ4/
I agree with sweetamylase's answer.
That code should work. Because it is using native javascript, I think it is good for performance.
Or use class name for determinate div:
$('textarea').click(function(){
var parentDiv = $(this).parents('div.post_area2'); // avoid to use $(this) multi time in this function
parentDiv.find('div.word_c').html('<span>140</span>');
parentDiv.find('div.submit').html('<span>Reply</span>');
});
That will work exactly even you add new another div.
Don't use 'eq()' if you have another solution.
I'm sorry, I'm not enough reputation for voting.
I would re-write it as such:
$('textarea').click(function(){
var divContainer = $(this).parent().siblings('div');
divContainer[0].innerHTML = '<span>140</span>';
divContainer[1].innerHTML = '<span>Reply</span>';
});
You can use native attribute innerHTML to set the contents of the DOM element, it is equivalent to using .html() minus the requirement of invoking the jQuery object.
Also, it depends if your coding style likes to do chaining because that's really easily done with jQuery, but can be difficult to read when the line becomes long.
You should give the other divs extra classes to represent what they mean.
$('textarea').click(function(){
$(this).parents('form').children('.hide-until-using-form').show();
});
This creates a highly reusable function that doesn't depend on how many siblings are involved, what the text of the button is (Post? Edit?), etc.
There is infinite ways to do it,
You can think a bit out of the box, i'm not sure that the latest version of jquery optimize the access to elements, if i'm wrong feel free to make me sorry on it.
But here are a few ways to do it:
var parentSelector = $(this).parent().parent();
var parentSelector = $(this).parents('#uniqueId');
var currentId = this.id;
var childrenSelector = parentSelector.children('div[id!="' + currentId + '"'];
var one = $(childrenSelector.get(0));
var two = $(childrenSelector.get(1));
A simple way to optimize the access to elements is to wrap/create new function that save reference to DOM elements, there is some issues that need to be consider but you can make a nice dom-cache library.
Perhaps like this
$('textarea').click(function () {
var parentSiblings = $(this).parent().siblings('div');
$(parentSiblings[0]).html('<span>140</span>');
$(parentSiblings[1]).html('<span>Reply</span>');
});
Or
$('textarea').click(function () {
var parentSiblings = $($(this).parent().siblings('div'));
parentSiblings.eq(0).html('<span>140</span>');
parentSiblings.eq(1).html('<span>Reply</span>');
});
Others may see using vanilla javascript more elegant.
function empty(element) {
"use strict";
while (element.hasChildNodes()) {
element.removeChild(element.lastChild);
}
}
function addEvent(nodeList, type, callBack) {
"use strict";
var length = nodeList.length,
i = 0;
while (i < length) {
nodeList[i].addEventListener(type, callBack, false);
i += 1;
}
}
addEvent(document.getElementsByTagName("textarea"), "click", function (evt) {
"use strict";
var divContainer = evt.target.parentNode.parentNode.getElementsByTagName("div"),
span;
empty(divContainer[1]);
span = document.createElement("span");
span.textContent = "140";
divContainer[1].appendChild(span);
empty(divContainer[2]);
span = document.createElement("span");
span.textContent = "Reply";
divContainer[2].appendChild(span);
});
These and others are available on jsfiddle
I guess it depends on how exactly you define more elegant. Sometimes readability is more important, perhaps not including ant 3rd party libraries and using vanilla javascript.

How can I implement prepend and append with regular JavaScript?

How can I implement prepend and append with regular JavaScript without using jQuery?
Here's a snippet to get you going:
theParent = document.getElementById("theParent");
theKid = document.createElement("div");
theKid.innerHTML = 'Are we there yet?';
// append theKid to the end of theParent
theParent.appendChild(theKid);
// prepend theKid to the beginning of theParent
theParent.insertBefore(theKid, theParent.firstChild);
theParent.firstChild will give us a reference to the first element within theParent and put theKid before it.
Perhaps you're asking about the DOM methods appendChild and insertBefore.
parentNode.insertBefore(newChild, refChild)
Inserts the node newChild as a child of parentNode before the
existing child node refChild. (Returns newChild.)
If refChild is null, newChild is added at the end of the list of
children. Equivalently, and more readably, use
parentNode.appendChild(newChild).
You didn't give us much to go on here, but I think you're just asking how to add content to the beginning or end of an element?
If so here's how you can do it pretty easily:
//get the target div you want to append/prepend to
var someDiv = document.getElementById("targetDiv");
//append text
someDiv.innerHTML += "Add this text to the end";
//prepend text
someDiv.innerHTML = "Add this text to the beginning" + someDiv.innerHTML;
Pretty easy.
If you want to insert a raw HTML string no matter how complex, you can use:
insertAdjacentHTML, with appropriate first argument:
'beforebegin'
Before the element itself.
'afterbegin'
Just inside the element, before its first child.
'beforeend'
Just inside the element, after its last child.
'afterend'
After the element itself.
Hint: you can always call Element.outerHTML to get the HTML string representing the element to be inserted.
An example of usage:
document.getElementById("foo").insertAdjacentHTML("beforeBegin",
"<div><h1>I</h1><h2>was</h2><h3>inserted</h3></div>");
DEMO
Caution: insertAdjacentHTML does not preserve listeners that where attached with .addEventLisntener.
I added this on my project and it seems to work:
HTMLElement.prototype.prependHtml = function (element) {
const div = document.createElement('div');
div.innerHTML = element;
this.insertBefore(div, this.firstChild);
};
HTMLElement.prototype.appendHtml = function (element) {
const div = document.createElement('div');
div.innerHTML = element;
while (div.children.length > 0) {
this.appendChild(div.children[0]);
}
};
Example:
document.body.prependHtml(`Hello World`);
document.body.appendHtml(`Hello World`);
Here's an example of using prepend to add a paragraph to the document.
var element = document.createElement("p");
var text = document.createTextNode("Example text");
element.appendChild(text);
document.body.prepend(element);
result:
<p>Example text</p>
In order to simplify your life you can extend the HTMLElement object. It might not work for older browsers, but definitely makes your life easier:
HTMLElement = typeof(HTMLElement) != 'undefined' ? HTMLElement : Element;
HTMLElement.prototype.prepend = function(element) {
if (this.firstChild) {
return this.insertBefore(element, this.firstChild);
} else {
return this.appendChild(element);
}
};
So next time you can do this:
document.getElementById('container').prepend(document.getElementById('block'));
// or
var element = document.getElementById('anotherElement');
document.body.prepend(div);
In 2017 I know for Edge 15 and IE 12, the prepend method isn't included as a property for Div elements, but if anyone needs a quick reference to polyfill a function I made this:
HTMLDivElement.prototype.prepend = (node, ele)=>{
try { node.insertBefore(ele ,node.children[0]);}
catch (e){ throw new Error(e.toString()) } }
Simple arrow function that's compatible with most modern browsers.
var insertedElement = parentElement.insertBefore(newElement, referenceElement);
If referenceElement is null, or undefined, newElement is inserted at the end of the list of child nodes.
insertedElement The node being inserted, that is newElement
parentElement The parent of the newly inserted node.
newElement The node to insert.
referenceElement The node before which newElement is inserted.
Examples can be found here: Node.insertBefore
You can also use unshift() to prepend to a list
document.write() is not a good practice, some browsers like Chrome give you a warning if you use it, and it may be a bad solution if you are providing it to a customer, they don't want to use your code and see warnings in the debug console!
Also jQuery may also be a bad thing if you are giving your code to a customer who already uses jQuery for other functionality on their site, there will be a conflict if there is already a different version of jQuery running.
If you want to insert content into an iframe, and do that with pure JS, and with no JQuery, and without document.write(), I have a solution.
You can use the following steps
1.Select your iframe:
var iframe = document.getElementById("adblock_iframe");
2.Create an element that you want to insert into the frame, let's say an image:
var img = document.createElement('img');
img.src = "https://server-name.com/upload/adblock" + id + ".jpg";
img.style.paddingLeft = "450px";
//scale down the image is we have a high resolution screen on the client side
if (retina_test_media == true && high_res_test == true) {
img.style.width = "200px";
img.style.height = "50px";
} else {
img.style.width = "400px";
img.style.height = "100px";
}
img.id = "image";
3.Insert the image element into the iframe:
iframe.contentWindow.document.body.appendChild(img);
This is not best way to do it but if anyone wants to insert an element before everything, here is a way.
var newElement = document.createElement("div");
var element = document.getElementById("targetelement");
element.innerHTML = '<div style="display:none !important;"></div>' + element.innerHTML;
var referanceElement = element.children[0];
element.insertBefore(newElement,referanceElement);
element.removeChild(referanceElement);

Javascript DOM howto?

I am a javascript noob.
I would like to select the second 'p' element of the div.box.
How do I do this?
Thanks a lot!
Tom
To get second p element of div with class box you'd do this:
var paragraph = null;
var divs = document.findElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
if (div.class == 'box') {
var paragraphs = div.getElementsByTagName('p');
if (paragraphs.length > 1)
paragraph = paragraphs[1];
break;
}
}
The paragraph would then be in the paragraph variable (or null if it wasn't found).
However you can do this much easier with a library such as jQuery:
var paragraph = $('div.box p:eq(1)');
Without using jQuery, the basic method would be to attach an unique ID to your Dom element
<p id="second_p_elmt"> [...] </p>
and then accessing it through the getElementById() method:
<script ...>
var second_p_elmt = document.getElementById('second_p_elmt');
</script>
<script type="text/javascript">
var boxElem = document.getElementById('box'),
pElems = boxElem.getElementsByTagName('p'),
whatYouWant = pElems[1]; // [1] is the second element in the response from getElementsByTagName
</script>
You have several options. As stated above, you could use one of the excellent frameworks, like jQuery or prototype. Or you give the <p/> an ID, that you can use simply with document.getElementById().
Then, as reko_t pointed out, without the above, you must write a lengthy DOM traversing code (which is preferable, if you don't use JS frameworks elsewhere, over embedding them only for this task).
In the most recent browsers (namely, IE>=8, FF>=3.5, recent Opera and Safari > 3) you can also use this simple snippet:
var p = document.querySelectorAll("div.box p");

Categories

Resources