jQuery click event does not fire on 'loaded' html - javascript

I'm trying to understand why loading HTML into a div block renders its class statement effectively non-existent to a click event.
My HTML code looks like this:
<div id="load-to"></div>
<div id="load-from">
<div class="load-from-css"> Hello!</div>
</div>
<button>load it!</button>
My JS code looks like this:
$('button').click(function(){
var html = $('#load-from').html();
$('#load-to').html(html);
});
$('.load-from-css').click(function(){
alert('clicked');
});
When I click the button the HTML from the lower div block is loaded into the upper div block, and then the HTML looks like this:
<div id="load-to">
<div class="load-from-css"> Hello!</div>
</div>
<div id="load-from">
<div class="load-from-css"> Hello!</div>
</div>
My question is, why does the second click event (defined in my jQuery code) only work on the original lower "Hello!" div block but not on the loaded upper one, when both have the same class definition?

Other answers have already covered the core reason for your problem (that copying the HTML of an element and placing it elsewhere will create a brand new DOM element and does not copy any events that were bound to the original element... keeping in mind that when you add an event listener, it will only bind to any elements that exist at the time that you do so)
However, I wanted to add some other options for accomplishing what you want to do.
jQuery has a few different techniques that make this sort of thing easy:
.clone() will essentially do the same thing as you are doing now*, it will copy the HTML content and create a new DOM element. However, if you pass true (ie: .clone(true)), it will clone it with all data and events intact.
* note that to truly get the same result as using .html(), you need to do .children().clone(), otherwise you'll get both the inner and outer div.. this may or may not be necessary depending on the use case
ex: https://jsfiddle.net/Lx0973gc/1/
Additionally, if you were in this same situation but did not want to make a clone, and simply wanted to move an element from one place to another, there is another method called .detach() which will remove the element from the DOM, but keep all data and events, allowing you to re-insert it later, in the same state.
ex: https://jsfiddle.net/Lx0973gc/2/ (not the best example because you won't see it move anywhere, but it's doing it!)
As another alternative, you can use delegated event binding, which actually binds the event to a different element (a parent) which you know won't change, but still allows you to target a child element within it:
$('body').on({
'click': function() {
alert('clicked');
}
}, '.load-from-css');
ex: https://jsfiddle.net/Lx0973gc/4/

The $('.load-from-css') finds all elements currently existing and .click(...) attaches a listener to all these elements. This is executed once.
Then you copy the raw html which does not transfer any listeners. The DOM has nodes onto which the listeners are attached but when you copy the plain HTML you essentially create new nodes based on the html.

Because you are copying just the HTML. The js file is loaded at the beginning, when there is just one instance of a div with the "load-from-css" class. You should execute again the code adding the listener after you copy the html. Somethinglike:
$('button').click(function(){
var html = $('#load-from').html();
$('#load-to').html(html);
$('.load-from-css').click(function(){
alert('clicked');
});
});

#load-to inner HTML is initially empty. so added click listener only for #load-from .load-from-css. Dynamically bind element will not attach the click listener.
jQuery new version have the feature to attach the event for dynamic elements also. Try this
$('button').click(function(){
var html = $('#load-from').html();
$('#load-to').html(html);
});
$(document).on('click', '.load-from-css', function(){
alert('clicked');
});
Also we can use like this
$( document ).delegate( "load-from-css", "click", function() {
alert( "Clicked!" ); // jQuery 1.4.3+
});

Simply because the page did not refresh. You loaded a content to another content without loading the page, and the browser wont recognized any event added to the loaded element.
What you should do is load your javascript tag with the load along with the content.
Your code should be like this:
<div id="load-to">
<div class="load-from-css"> Hello!</div>
</div>
<div id="load-from">
<div class="load-from-css"> Hello!</div>
<script>$('button').click(function(){
var html = $('#load-from').html();
$('#load-to').html(html);
});
$('.load-from-css').click(function(){
alert('clicked');
});</script>
</div>

Related

How can I dynamicaly append elements outside the event handler with the help of an element created by this event handler?

I made the following code to clarify the question:
Html:
<body>
<div class="static">This is a static div</div>
<button class="add-dynamic-button">Click me to add a new button</button>
</body>
Js:
$(function(){
$('.add-dynamic-button').on("click",function(){
$('body').append("<button class='dynamic-button'>Click me to add a dynamic div'</button>");
});
$('.dynamic-button').on('click',function(){
$('body').append("<div class='dynamic-div'>This is a dynamic div</div>");
});
});
And here is jsfiddle to test: http://jsfiddle.net/6ZN5J/
When I have the $('.dynamic-button').on('click') handler inside the first click handler, a .dynamic-div is added fine.
But when I place it outside the first click handler scope (as in the example above), nothing happens. I initially thought that $.on works on any DOM element that is not yet created, but now it turns out that it works on new elements of the same class or type if they are already in the DOM or when $.on is placed inside the function that creates those elements.
Can you clarify why this happens and whether there are any methods to allow for using event handlers on dynamically created elements outside the handler they were created with?
Thanks
$() is a selector. It finds the element(s) that were in the document or the parent element from which you're peforming the whole query at the time you did it.
If you want further buttons bound to click event you'll need to manually bind them:
$('body').append("<button class='dynamic-button'>Click me to add a dynamic div'</button>")
.on("click", ....);

Access jQuery function from page elements generated in jQuery

I have a little jQuery call that returns perfectly for my element bound to an on function:
$(".claim-detail a").on("click", function(){
...some stuff
})
Then a little html:
<p class="claim-detail">get the data</p>
Works perfectly.
But I need that claim-detail html to be generated in javascript. And when I move it there, the html is generated on the page with no problem, but the jQuery function breaks entirely . Doesn't matter which piece precedes which in the javascript.
Anything I'm doing obviously wrong?
You need to use event delegation for dynamically generated elements that do not exist at DOM ready. Change your click handler to:
$(document).on("click", ".claim-detail a", function(){
Chances are (I'm saying this because we don't know how your code was generated) that your click handler was trying to bind to the element before it existed
Use
<p class="claim-detail"><a onclick="myNewFunction()" href="#modal" data-toggle="modal">get the data</a></p>
Where my myNewFunction is the function you were using in the event. Other option is create the event when you actually finish creating the HTML id and/or classes in the DOM.

Run jQuery function onclick

so i implemented a bit of jQuery that basically toggles content via a slider that was activated by an <a> tag. now thinking about it id rather have the DIV thats holding the link be the link its self.
the jQuery that i am using is sitting in my head looks like this:
<script type="text/javascript">
function slideonlyone(thechosenone) {
$('.systems_detail').each(function(index) {
if ($(this).attr("id") == thechosenone) {
$(this).slideDown(200);
}
else {
$(this).slideUp(600);
}
});
}
</script>
i was using this as a index type box so there are several products when you click on the <a> tag that used to be an image* it would render a bit of content beneath it describing the products details:
<div class="system_box">
<h2>BEE Scorecard database</h2>
<p>________________</p>
</div>
the products details are wrapped in this div.
<div class="systems_detail" id="sms_box">
</div>
so when you click on what used to be a image* it would run the slideonlyone('div_id_name') function. the function above then first closes all the other divs with the class name 'system details' and then opens/slides the div with the id that was passed into the slideonlyone function. that way you can toggle products details and not have them all showing at once.
note i only kept the <a> tag to show you what was in there i will be getting rid of it.
note: i had an idea of just wrapping the whole div in an <a> tag but is that good practice?
So now what i am wondering is since you need JavaScript to run onclick on a div tag how do you write it so that it still runs my slideonlyone function?
Using obtrusive JavaScript (i.e. inline code) as in your example, you can attach the click event handler to the div element with the onclick attribute like so:
<div id="some-id" class="some-class" onclick="slideonlyone('sms_box');">
...
</div>
However, the best practice is unobtrusive JavaScript which you can easily achieve by using jQuery's on() method or its shorthand click(). For example:
$(document).ready( function() {
$('.some-class').on('click', slideonlyone('sms_box'));
// OR //
$('.some-class').click(slideonlyone('sms_box'));
});
Inside your handler function (e.g. slideonlyone() in this case) you can reference the element that triggered the event (e.g. the div in this case) with the $(this) object. For example, if you need its ID, you can access it with $(this).attr('id').
EDIT
After reading your comment to #fmsf below, I see you also need to dynamically reference the target element to be toggled. As #fmsf suggests, you can add this information to the div with a data-attribute like so:
<div id="some-id" class="some-class" data-target="sms_box">
...
</div>
To access the element's data-attribute you can use the attr() method as in #fmsf's example, but the best practice is to use jQuery's data() method like so:
function slideonlyone() {
var trigger_id = $(this).attr('id'); // This would be 'some-id' in our example
var target_id = $(this).data('target'); // This would be 'sms_box'
...
}
Note how data-target is accessed with data('target'), without the data- prefix. Using data-attributes you can attach all sorts of information to an element and jQuery would automatically add them to the element's data object.
Why do you need to attach it to the HTML? Just bind the function with hover
$("div.system_box").hover(function(){ mousin },
function() { mouseout });
If you do insist to have JS references inside the html, which is usualy a bad idea you can use:
onmouseover="yourJavaScriptCode()"
after topic edit:
<div class="system_box" data-target="sms_box">
...
$("div.system_box").click(function(){ slideonlyone($(this).attr("data-target")); });
You can bind the mouseenter and mouseleave events and jQuery will emulate those where they are not native.
$("div.system_box").on('mouseenter', function(){
//enter
})
.on('mouseleave', function(){
//leave
});
fiddle
note: do not use hover as that is deprecated
There's several things you can improve upon here. To start, there's no reason to use an <a> (anchor) tag since you don't have a link.
Every element can be bound to click and hover events... divs, spans, labels, inputs, etc.
I can't really identify what it is you're trying to do, though. You're mixing the goal with your own implementation and, from what I've seen so far, you're not really sure how to do it. Could you better illustrate what it is you're trying to accomplish?
== EDIT ==
The requirements are still very vague. I've implemented a very quick version of what I'm imagining you're saying ... or something close that illustrates how you might be able to do it. Left me know if I'm on the right track.
http://jsfiddle.net/THEtheChad/j9Ump/

jQuery select dynamically created html element

There are a lot of asked questions with almost similar titles with this question of mine, but you know I didn't find an answer.
My simple question is:
I have button, when I click on it, javascript creates modal window
<div class="aui-dialog">
html here...
<button id="closeButton">Close</button>
</div>
just after <body> tag.
I can bind click event of close button with no problem using jQuery live:
$("#closeButton").live("click", function() {
alert("asdf"); // it calls
$("body").find(".aui-dialog").remove();
});
My problem is, I cannot select that dynamically created modal window div by its classname. So that I could call jQuery .remove() method to make close action. Now I know, I must deal with dynamic elements in another way.
What way?
EDIT:
I think it's important to mention this:
I dont' create the modal window myself, I use liferay portal. It has built-in javascript framework AUI(YUI) that creates that modal window. I can just create that close button inside it in its view.
EDIT 2:
Modal window div class attribute value is: "aui-component aui-panel aui-dialog aui-widget-positioned"
Since jquery will read the current DOM-state when page loads:
jQuery( document ).ready(function( $ ) {
it will miss the elements you generate post to page load.
One simple solution is to listen for clicks on document, and filter with the class or element-type that you want to use to execute your code. That way jquery will find new elements generated under document, after page load.
$(document).on("click", '#closeButton', function(){
$(".aui-dialog").remove();
});
Create a reference when you're creating the modal window:
var modalWindow = $('<div class="aui-dialog">html here... <button id="closeButton">Close</button></div>');
// later...
modalWindow.remove();
To your edit:
Get the window via jQuery's parent when the button is inside the modal window:
$('#closeButton').on('click',function() {
$(this).parent().remove();
return false;
});
Many users will come on this page when they want to select some element generated runtime by JQuery and it failed, like me.
The solution is simply approach the root (the parent) of your randomly generated element and then get inner by jQuery TAG selection. For example you generate many TDs of users in a table at runtime, the element having your users list is a table with id tblUsers then you can iterate over runtime generated TRs or TDs as following:
$("#tblUsers tr").each(function(i){
alert('td' + i);
});
further if you have inputs in tds you can go deep in selection as
$("tblUsers tr td input")
Another case could be a randomly generated dialog or popup, then you have to approach its root(parent) and next same selection by TAG as stated above.
You could do a few things, but first, if you are using jQuery 1.7, better use .on(). it has replaced .live() which is deprecated.
if you have no control over the building of the modal but know that the button is a direct child of the modal, then use parent()
$('#closeButton').on('click',function() {
$(this).parent().remove();
return false;
});
if the button is somewhere deep in the parent but has a fixed depth from the parent, use parents() which gets all ancestors of the element, and then filter it to a specific depth. if the close was 2 levels deep, the index of :eq() would be 1.
$('#closeButton').on('click',function() {
//where N is zero-indexed integer, meaning first item of the set starts with 0
$(this).parents(':eq(N)').remove();
return false;
});
another way is to add the handler when the modal is created
var modal = $('modalHTML');
$('#closeButton',modal).on('click',function(){
//modal still refers to the whole modal html in this scope
modal.remove();
});
//show modal
UPDATED:
You can use:
$(".aui-dialog").live('click', function() {
$(this).remove();
return false;
});)
This attach an event handler for all elements which match the current selector, now and in the future.
Please not that this method is depreciated in newer version of jQuery and you should consider using .on() instead of .live().
I found an answer, hope it would be helpful for developers who faced with dynamically generated html with IFRAME inside.
If you have a button (#closeButton) inside that IFRAME, and you want select iframe parent window's dom elements, just add second argument window.parent.document for your selector:
// This functions is inside generated IFRAME
$("#closeButton").on("click", function() {
// body - is your main page body tag
/* Will alert all html with your dynamically
generated html with iframe and etc. */
alert($('body', window.parent.document).html());
return false;
});

does jQuery's html() remove all data attached to elements that are replaced?

I'm displaying a tabbed interface with the help of jQuery. When you click a tab, a ajax call will replace all html from a $(".content") element with new html, using something like
$(".content").html(response);
When I do this, are all jquery events and functions that are attached to elements inside the .content div removed? Is it ok to fire these events and functions again after I replace the HTML ? If I click the tabs 324523452354 times, will it duplicate jQuery data every time?
Yes. They will be removed. You can use the live event to attach to elements that dont exist yet.
$(".myElementClass").live("click", function (e) {
e.preventDefault();
//do stuff
});
In this case, this function will always be called on myElement no matter when it is injected into the DOM.
All HTML inside of your selector is replaced with the parameter you pass in, implying it is completely removed from the DOM. Meaning if you have:
<div id="mine">
<ul>
<li>One thing</li>
</ul>
</div>
And I do a call as such:
$('div#mine').html("hey");
My HTML will then be:
<div id="mine">
hey
</div>
As you can see the is completely removed and all its bound events mean nothing. If you use the jQuery.live() binding instead however, then elements that don't yet exist can have events associated with them. Meaning if you add some elements to the DOM then they events will still work, without you have to rebind if you add more, or replace them.
**.live** events are binded at the document level , read the following document which is really useful
http://www.bennadel.com/blog/1751-jQuery-Live-Method-And-Event-Bubbling.htm

Categories

Resources