Modifying Content in JavaScript-Generated HTML Code - javascript

I am trying to modify the innerHTML of a div when clicked. I have dynamically generated an array of divs, and I want to specifically access the table which the user has clicked.
I have tried dynamically setting the ID of the tables in the JavaScript code:
(for var i=0;i<array.length;i++){
var IDvalue = "foo";
// append table to HTML string.
html += "<div onclick='modifyInnerHTML(\"" + IDvalue + "\")'>...</div>";
var divs = document.getElementsByTagName('div');
divs[divs.length-1].id=array[i].IDvalue;
}
Then in modifyInnerHTML() I access the element by ID:
function modifyInnerHTML(id){
document.getElementById(id).innerHTML+="Add an update";
}
While I think this code should work fine, it is breaking at the document.getElementById(id) function, and I realize the id of the divs is not being set dynamically. Any thoughts on why this might be or are there faster ways to do this?
Thanks in advance!

You'd better use a DOM manipulation library for this, like jQuery.
As for the events, jQuery will let you define them in a much more reliable way. You should avoid defining event handlers in attributes anyway, better attach them to the DOM using references to elements, or, better yet, jQuery elemnt sets.
Case 1: Generate some divs dynamically with an event handler already set:
for(var i = 0; i < 10; ++i) {
$("<div>")
.addClass("clickable-div")
.html("click me!")
.on("click", function() {
$(this).html("You clicked me!");
})
.appendTo("body");
}
Case 2: Add an event handler to all divs that contain the class clickable-div
$("div.clickable-div").on("click", function() {
$(this).html("You clicked me!");
});
jQuery is much faster to get things done with than anything you'd write in pure JS.

Related

How do you target an element that is dynamically generated? [duplicate]

Beginner to all of this, playing around with Firebase. Basically, I want to retrieve text entries from Firebase and have an "Approve" button next to it. When the button is clicked, I want that specific text entry to be pushed to a new Firebase location and the text removed from the page. I am creating the button and the text dynamically and I am having some trouble with selecting the button and the divs I created. I know I have to use on() but I'm unsure of how to use it.
Thanks!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
$('<div id="post">').text(posts.text).append('<button style ="button" id="approve">Approve</button>').appendTo($('#feed'));
});
$('#approve').on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
You have to bind .on() on a container of your dynamically added element that is already on the page when you load it, and have it like this:
$('#yourContainer').on('click', '#approve', function(){
//your code here..
});
Your .on() didn't work, because you are adding the button dynamically. You can't find the dynamically added elements directly using that elements id selector like $('#approve'). So you should
bind .on() with $(document) selector. This will always contain your dynamically added elements.
$(document).on( eventName, selector, function(){} );
$(document).on('click','#approve',function(){
//your code here
});
I find a quick dip into the DOM, and then running back into jQuery very handy for this problem:
// Construct some new DOM element.
$(whatever).html('... id="mynewthing"...');
// This won't work...
$("#mynewthing")...
// But this will...
$(document.getElementById("mynewthing"))...
This works by turning the DOM object directly into a selector. I like it because the approach is transparent in operation/intent.
Another alternative, simpler to understand, less powerful, also perfectly valid, is to simply bind the event while you create the element:
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var $button = $('<button style ="button" id="approve">Approve</button>');
$button.on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
$('<div id="post">').text(posts.text).append($button).appendTo($('#feed'));
});
Another problem you are going to run into, assuming there will be more than one of these on a page, is that you are using IDs in the records. They're going to clash if they aren't unique.
A great alternative is to refer to these items with data-* tags or other identifying characteristics, such as css tags. But in your case, you don't need them at all!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var id = snapshot.name();
var $button = $('<button style="button">Approve</button>');
$button.on("click", function(){
// use parent.closest(...) in place of an ID here!
var text = $(this).parent().closest('textarea').val();
postsRef.push({'text':text});
$(this).parent().remove();
});
/* just an example of how to use a data-* tag; I could now refer to this element using:
$('#feed').find('[data-record="'+id+'"]') if I needed to find it */
$('<div data-record="'+id+'">').text(posts.text).append($button).appendTo($('#feed'));
});
I don't sure exactly what are you looking for. You can use .find() to select dynamically elements. I think .find() will look at the html structure again to get needed elements.
$("#button").click(function(e){
$(".parentContainer").find(".dynamically-child-element").html("Hello world");
});
Or
$(".parentContainer").find(".dynamically-child-element").html("Hello world"); // not in click event
So this is my demo

Assign java scripts to cloned HTML element

I have a html div and I clone it using Jquery. That div contains labels and text fields. ids of all of them generated and assigned dynamically. I have no problem with that.
A java script is assigned to a text field of original div. The cloned text fields does not have the javascript assigned to it.
the script I need to assign:
<script>
$(function() {
$("#datepick_onBooking,#datepick_Pay1,#datepick_Pay2,#datepick_totPay,#datepick_deedFees").datepicker();
});
</script>
the script I use to make clones:
<script>
var i = 3;
//When DOM loaded we attach click event to button
$(document).ready(function() {
$('#addAnotherPayment').click(function() {
var cloned = $('.PayDiv0').first().clone();
var noOfDivs = $('.PayDiv0').length+2;
cloned.insertBefore("#totPayForm");
// append count to the ids
cloned.attr('id', 'PayDiv' + noOfDivs);
cloned.find('label').attr('id', 'PayLbl' + noOfDivs);
cloned.find('input[type="text"]').attr('id', 'datepick_Pay'+ noOfDivs);
cloned.find('input[type="number"]').attr('id', 'amount_Pay'+ noOfDivs);
cloned.find('.PayLbl2').html("Payment No " + i++ + ':');
});
});
</script>
datepick_Pay1, datepick_Pay2, datepick_totPay, datepick_deedFees are static elements and they have been assigned to the script. I create text fields using cloning as datepick_Pay3,datepick_Pay4, and so on.
I cannot figure out how to dynamically assign the script to that newly created elements.How can I do that?
A Boolean indicating whether event handlers and data should be copied along with the elements.
change this line.
var cloned = $('.PayDiv0').first().clone(true);
when you clone something especially elements which having events
use parameter as
clone(true)
But this will be harmfull based on how event is attached on the actual element when copying the events to the cloned element may affect the actual.
You need to clone with events. http://api.jquery.com/clone/
var cloned = $('.PayDiv0').first().clone(true);
Then your script needs to be changed to work for dynamic elements. Here as soon as input elements gets focus, asssign the datepicker based on wild card id selector, if it doesn't already have one.
$(function() {
$('body').on('focus',"input[id^=datepick_]", function(){
if(!$(this).hasClass('.hasdatepicker'))
{
$(this).datepicker();
}
});
});

JQuery Event Listeners in a For Loop

I am trying to create some basic button rollover functionality using Jquery and toggleClass. I am building a list of elements by cloning a DIV from my HTML and duplicating it multiple times (its populating a list of data from a database). To do this I am using a for loop. Here is the currently working code.
var displayNode = document.getElementById('phoneDisplayContainer');
for(var i=0; i<length; i++) {
//Clone the original container display.
var clonedDisplay = displayNode.cloneNode(true);
clonedDisplay.setAttribute('id', 'phoneDisplayContainer' + i);
//Remove hidden class from cloned Element. NOT CROSS BROWSER!
clonedDisplay.classList.remove('hidden');
var children = clonedDisplay.getElementsByTagName('div');
//Fill new nodes children containers with data.
children[1].innerHTML = contact.phone[i].type;
children[2].innerHTML = contact.phone[i].number;
children[3].setAttribute('onclick', 'PhoneUtility.edit(' + i + ');');
children[3].setAttribute('id', 'phoneEditDisplay' + i);
children[4].setAttribute('onclick', 'PhoneUtility.remove(' + i + ');');
//Hidden elements
var hidden = new Array(children[3], children[4]);
//Set rollover events.
clonedDisplay.setAttribute('onmouseover', '$("#' + children[3].id + '").toggleClass("hidden");');
clonedDisplay.setAttribute('onmouseout', '$("#' + children[3].id + '").toggleClass("hidden");');
//Append the new node to the display container
phoneContainer.appendChild(clonedDisplay);
}
}
Is there a way to use Jquery event listeners instead of having to set onmouseover and onmouseout directly on the element?
I tried this:
$(clonedDisplay).mouseover(function() {
$(children[3]).toggleClass('hidden');
});
With no luck. It just displays performs the rollover effect on the last element in the list. This is actually my first attempt at using jQuery so any other suggestions to ways I could jQuery inside the code would be helpful too.
EDIT: I'd also like to toggle multiple children from the arraylist mentioned in the for loop. How would I set this up? I can't seem to pass an array to the jquery command without getting errors.
The following code after your for loop should let you assign all the mouseover and mouseout handlers in one go to apply to all the clones:
$('div[id^="phoneDisplayContainer"]').mouseover(function() {
$(this).find("div").eq(3).toggleClass("hidden");
}).mouseout(function() {
$(this).find("div").eq(3).toggleClass("hidden");
});
// or, given that both handlers do the same thing:
$('div[id^="phoneDisplayContainer"]').on("mouseover mouseout", function() {
$(this).find("div").eq(3).toggleClass("hidden");
})
(If you're using jQuery older than 1.7 use .bind() instead of .on().)
The above says to find all the divs with an id beginning with "phoneDisplayContainer" and assign event handlers. Within the handler, find the fourth descendant div and toggle the class.
You don't show your HTML or CSS, but you could do this all in your CSS if you like. Assuming you can assign a common class ("parentDiv") to the divs that you want to trap the hover event on, and a common class ("childDiv") to their child div (the one to be hidden), you can do this:
.parentDiv .childDiv { visibility: hidden; }
.parentDiv:hover .childDiv { visibility: visible; }
(Obviously you can give more meaningful class names to fit your structure.)
Otherwise, again if you can assign those classes to the appropriate divs then after your loop you can do this with jQuery:
$(".parentDiv").on("mouseover mouseout", function() {
$(this).find(".childDiv").toggleClass('hidden');
});
Basically the same as what I said initially, but using classes for selectors. If you feel like I'm pushing a class-based solution on you that's because I am: it tends to make this sort of thing much easier.

Get the id of a the item that is clicked

I have this html code:
<b class = "edit" id = "foo1">FOO</b>
<b class = "edit" id = "foo2">FOO2</b>
<b class = "edit" id = "foo3">FOO3</b>
And I have this code in jQuery:
$('b.edit').click(function(){
//GET THE ID OF THE b.edit: e.g foo1, foo2, foo3
$('.editP').focus();
});
How can I get the id value of the b.edit, as there are multiple instances of b.edit, and I want to get the specific id of the one clicked? How can I do this?
Thanks, Sorry, I am pretty new to javascript.
I'm assuming from your sample code that you're using jQuery? If so you can get the id as follows:
$('b.edit').click(function(){
this.id;
});
EDIT:
The direct reference to the attribute is indeed more efficient if all that is required is simply the id.
Also can be obtained from the jQuery object:
$('b.edit').click(function(){
$(this).attr('id');
});
Sample fiddle: http://jsfiddle.net/5bQQT/
Try with this:
$('b.edit').click(function(e){ //When you use an event is better
//send the event variable to the
//binding function.
var id = e.target.id; //get the id of the clicked element.
/*do your stuff*/
$('.editP').focus();
});
try this. You can use keyword "this" to retrieve the attr ID...
$('b.edit').click(function(){
alert($(this).attr("id"));
});
$('.edit').click(function(){
var theId = $(this).attr('id');
}
This will get you the ID of anything clicked with a class of .edit
$('.edit').live('click', function() {
alert( this.id );
});
Sample
http://jsfiddle.net/ck2Xk/
When passing a click handler in JQuery, you actually have a reference to something called an event object. This event object has a property called target, which is a reference to the element that was clicked.
$('b.edit').click(function(eventObject){
eventObject.target // this is the element that was clicked.
});
Since you have a reference to the target element, you can do whatever you like. In this case, you could just access eventObject.target.id.
Since nobody has shown the simplest method yet that doesn't even need jQuery to get the id:
$('.edit').click(function() {
alert(this.id);
});
I never understand why people use jQuery for getting simple attributes which involves two jQuery function calls (and a bunch of overhead to create a jQuery object) instead of one direct attribute reference.
something like this:
var id = $(this).attr('id');
More clearly:
$('b.edit').live('click', function(){
var id = $(this).attr('id');
// in this scope this.id works too
// var id = this.id;
});
This is called event delegation in Javascript. More info can be found in Zakas blog http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
The idea in few words is you attache the event to a parent node and then waiting for some event on the child node. In the example below I attach the onclick event to the document itself. Then inside the event handler you will write a switch statement to check the clicked element id, then do what you want to do for that element
document.onclick = function(event){
//IE doesn't pass in the event object
event = event || window.event;
//IE uses srcElement as the target
var target = event.target || event.srcElement;
switch(target.id){
case "foo1":
foo1();
break;
case "foo2":
foo2();
break;
case "foo3":
foo3();
break;
//others?
}
};
//some dummy handlers
var foo1 = function(){
alert("You clicked foo1");
};
var foo2 = function(){
alert("You clicked foo2");
};
var foo3 = function(){
alert("You clicked foo3");
};
For how to implement event delegation in jQuery you can check http://api.jquery.com/on/#direct-and-delegated-events
Even though this is not a real answer to your question. I will try to explain why what your asking is not the way to go. Since you are new especially, since learing bad practices could be hard to unlearn. Allways try to search for an ID before finding an element by its Class. Also try to avoid giving every element the same class (and in this case ID to), just give it an encapsulating parent.
Furthermore, the id of an element is really specific and should preferably used to find / select / bind events to. An id should usually be unique for this to work, so in your case a couple of things could be optimized, lets say like:
<div id="foo">
<b id="1">Foo</b>
<b id="2">Other foo</b>
<b id="3">Some foo</b>
</div>
Now if you want to know which was clicked there are multiple ways to accomplish it, but a nice one is simply binding a parent its children (i.e <div id="foo"> .. </div>). This way you can alter the structure of your pretty fast, without changing all the classes and id's.
With jQuery you can get the attribute id using the .attr() function. However I told you the id was pretty specific and thus has its own rights in javascript world. An id can also be directly targeted ('DOMelement.id', but this would be too much to explain for now)
In two ways the <b> can be targetted:
Example a)
var b_elements = $("#foo").children();
Example b)
var b_elements = $("#foo").find('b');
We can add jQuery (or javascript events) to these found elements. The nice thing about jQuery is that it simplifies alot of work. So in your case if you would like to know an id of a certain clicked <b> field you could use a very verbose way:
b_elements.click(function()
{
var clicked_element = $(this);
alert(clicked_element.attr('id'));
});
Verbose because you can do it much much shorter, but who cares about a few bytes when your learning and this makes remembering functions and events alot easier. Say you wanted to get the class edit by finding the where you knew the id that was clicked:
b_elements.click(function()
{
var clicked_element = $(this);
alert(clicked_element.attr('class'));
});
And to conclude, the id of an element is ment to be unique because it makes searching through big documents alot faster. Also don't forget to look and learn plain javascript, as it helps coding in jQuery alot too, but not the other way around. Your given question would require a for loop in plain javascript since it cannot do a lookup by class nor id nor have they have a common parent.
Good luck with learning :)

Javascript/jQuery - How do I obtain name of the class of clicked element?

I googled and googled and I concluded that it's very hard to get answer on my own.
I am trying to use jquery or JavaScript to get a property of clicked element. I can use "this.hash" for example - it returns hash value I presume.
Now I would like to get name of the class of clicked element.
Is it even possible? How? And where would I find this kind of information?
jQuery documentation? - All I can find is methods and plugins, no properties.. if its there - please provide me with link.
JavaScript documentation? - is there even one comprehensive one? again please a link.
DOM documentation? - the one on W3C or where (link appreciated).
And what is this.hash? - DOM JavaScript or jQuery?
In jQuery, if you attach a click event to all <div> tags (for example), you can get it's class like this:
Example: http://jsfiddle.net/wpNST/
$('div').click(function() {
var theClass = this.className; // "this" is the element clicked
alert( theClass );
});
This uses jQuery's .click(fn) method to assign the handler, but access the className property directly from the DOM element that was clicked, which is represented by this.
There are jQuery methods that do this as well, like .attr().
Example: http://jsfiddle.net/wpNST/1/
$('div').click(function() {
var theClass = $(this).attr('class');
alert( theClass );
});
Here I wrapped the DOM element with a jQuery object so that it can use the methods made available by jQuery. The .attr() method here gets the class that was set.
This example will work on every element in the page. I'd recommend using console.log(event) and poking around at what it dumps into your console with Firebug/Developer tools.
jQuery
​$(window).click(function(e) {
console.log(e); // then e.srcElement.className has the class
});​​​​
Javascript
window.onclick = function(e) {
console.log(e); // then e.srcElement.className has the class
}​
Try it out
http://jsfiddle.net/M2Wvp/
Edit
For clarification, you don't have to log console for the e.srcElement.className to have the class, hopefully that doesn't confuse anyone. It's meant to show that within the function, that will have the class name.
$(document).click(function(e){
var clickElement = e.target; // get the dom element clicked.
var elementClassName = e.target.className; // get the classname of the element clicked
});
this supports on clicking anywhere of the page. if the element you clicked doesn't have a class name, it will return null or empty string.
$('#ele').click(function() {
alert($(this).attr('class'));
});
And here are all of the attribute functions.
http://api.jquery.com/category/attributes/
You can use element.className.split(/\s+/); to get you an array of class names, remember elements can have more than one class.
Then you can iterate all of them and find the one you want.
window.onclick = function(e) {
var classList = e.srcElement.className.split(/\s+/);
for (i = 0; i < classList.length; i++) {
if (classList[i] === 'someClass') {
//do something
}
}
}
jQuery does not really help you here but if you must
$(document).click(function(){
var classList =$(this).attr('class').split(/\s+/);
$.each( classList, function(index, item){
if (item==='someClass') {
//do something
}
});
});
There's a way to do this without coding. Just open the console of your browser (f12?) and go to element you want. After that, hover or click the item you want to track.
Every change done on the DOM will be for a few seconds marked (or lightened) as another color on the console. (Watch the screen capture)
On the example, each time I hover a "colorItem", the 'div' parent and the "colorItem" class appears lightened. So in this case the clicked class will be 'swiper-model-watch' or 'swiper-container' (class of the lightened div)

Categories