JQUERY - 2 functions not working alongside each other [duplicate] - php

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 years ago.
Suppose I have some jQuery code that attaches an event handler to all elements with class .myclass.
For example:
$(function(){
$(".myclass").click( function() {
// do something
});
});
And my HTML might be as follows:
<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>
That works with no problem.
However, consider if the .myclass elements were written to the page at some future time.
For example:
<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
$("#anchor1").click( function() {
$("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
});
</script>
In this case, the test4 link is created when a user clicks on a#anchor1.
The test4 link does not have the click() handler associated with it, even though it has class="myclass".
Basically, I would like to write the click() handler once and have it apply to both content present at page load, and content brought in later via AJAX / DHTML. Any idea how I can fix this?

I am adding a new answer to reflect changes in later jQuery releases. The .live() method is deprecated as of jQuery 1.7.
From http://api.jquery.com/live/
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
For jQuery 1.7+ you can attach an event handler to a parent element using .on(), and pass the a selector combined with 'myclass' as an argument.
See http://api.jquery.com/on/
So instead of...
$(".myclass").click( function() {
// do something
});
You can write...
$('body').on('click', 'a.myclass', function() {
// do something
});
This will work for all a tags with 'myclass' in the body, whether already present or dynamically added later.
The body tag is used here as the example had no closer static surrounding tag, but any parent tag that exists when the .on method call occurs will work. For instance a ul tag for a list which will have dynamic elements added would look like this:
$('ul').on('click', 'li', function() {
alert( $(this).text() );
});
As long as the ul tag exists this will work (no li elements need exist yet).

Sometimes doing this (the top-voted answer) is not always enough:
$('body').on('click', 'a.myclass', function() {
// do something
});
This can be an issue because of the order event handlers are fired. If you find yourself doing this, but it is causing issues because of the order in which it is handled.. You can always wrap that into a function, that when called "refreshes" the listener.
For example:
function RefreshSomeEventListener() {
// Remove handler from existing elements
$("#wrapper .specific-selector").off();
// Re-add event handler for all matching elements
$("#wrapper .specific-selector").on("click", function() {
// Handle event.
}
}
Because it is a function, whenever I set up my listener this way, I typically call it on document ready:
$(document).ready(function() {
// Other ready commands / code
// Call our function to setup initial listening
RefreshSomeEventListener();
});
Then, whenever you add some dynamically added element, call that method again:
function SomeMethodThatAddsElement() {
// Some code / AJAX / whatever.. Adding element dynamically
// Refresh our listener, so the new element is taken into account
RefreshSomeEventListener();
}
Hopefully this helps!
Regards,

After jQuery 1.7 the preferred methods are .on() and .off()
Sean's answer shows an example.
Now Deprecated:
Use the jQuery functions .live() and .die(). Available in
jQuery 1.3.x
From the docs:
To display each paragraph's text in an
alert box whenever it is clicked:
$("p").live("click", function(){
alert( $(this).text() );
});
Also, the livequery plugin does this and has support for more events.

If you're adding a pile of anchors to the DOM, look into event delegation instead.
Here's a simple example:
$('#somecontainer').click(function(e) {
var $target = $(e.target);
if ($target.hasClass("myclass")) {
// do something
}
});

You can bind a single click event to a page for all elements, no matter if they are already on that page or if they will arrive at some future time, like that:
$(document).bind('click', function (e) {
var target = $(e.target);
if (target.is('.myclass')) {
e.preventDefault(); // if you want to cancel the event flow
// do something
} else if (target.is('.myotherclass')) {
e.preventDefault();
// do something else
}
});
Been using it for a while. Works like a charm.
In jQuery 1.7 and later, it is recommended to use .on() in place of bind or any other event delegation method, but .bind() still works.

Binds a handler to an event (like click) for all current - and future - matched element. Can also bind custom events.
link text
$(function(){
$(".myclass").live("click", function() {
// do something
});
});

If your on jQuery 1.3+ then use .live()
Binds a handler to an event (like
click) for all current - and future -
matched element. Can also bind custom
events.

You want to use the live() function. See the docs.
For example:
$("#anchor1").live("click", function() {
$("#anchor1").append('<a class="myclass" href="#">test4</a>');
});

Related

JQuery not working with new DOM elements [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 7 years ago.
I've got a few functions in JQuery that stop working after I perform an Ajax request (to a PHP file) to add elements to the DOM.
This is the ajax function:
function paginacion(pagina){
$.ajax({
method: "GET",
url: "paginacion.php",
data: {pag: pagina}
})
.done(function(msg) {
$(".bt_container").remove();
$(".contenido").append(msg);
});
}
Here I call it:
$(".button").on("click", function(){
var pag = parseInt($(this).attr("data-pag"));
pag++;
paginacion(pag);
});
When I click the button, it works correctly the first time. But the elements I retrieve, should work with another function, and they don't, while the previous elements do work without any problem. Also, the old button gets removed and another one gets added at the end of the file, being retrieved by the same function as above. That button doesn't work either.
I'm sure that I'm having some problem with JQuery, making it to not work with these new DOM element's I'm retrieving. What can I do to make it work?
Use event delegation:
Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.
$(document).on('click', '.button', function () {
var pag = parseInt($(this).data("pag"));
// ^^^^
pag++;
paginacion(pag);
});
Also, use data() to get data attribute value.
http://api.jquery.com/data/
Refer: http://learn.jquery.com/events/event-delegation/
It is loaded dynamically! Use .on for Event Delegation.
$("body").on('click', '.button', function () {
var pag = parseInt($(this).attr("data-pag"));
pag++;
paginacion(pag);
});
You need to use .on() for bindig events for dynamically generated elements
$(document).on('click', '.button', function () {
var pag = parseInt($(this).attr("data-pag"));
pag++;
paginacion(pag);
});
You are looking for Event delegation. You dynamically added and replace the dom elements use event delegation.
$(".contenido").on("click", ".button", function(){
//------^ Immediate parent or document
// Your code
});

jQuery - reference a selector that is included with .load

can you help me with this?
I have a local website that displays "news". The newest one is displayed when the page is first loaded, but the older news are loaded only if the visitor clicks a link called #oldnews:
$('#oldnews').load('ajax/older_news.php');
The "older_news.php" file, after is loaded, has another link which is meant to hide these older news. However, this link is not working.
The jQuery code that handles this "hide" mechanism is in the homepage, so my guess is that jQuery doesn't hide the news because it doesn't know that the link exists (since it is only loaded when the user clicks the link).
Any insights on the better approach to solve this? Thank you.
2 things. As pointedd out in comments, you can use .delegate. In the new versions of jQuery (1.7+) this is extremely simple.
$(function() { // good old $(document).load(function(){ //shorter!
// use document to asign delegation
// asign an event like "click" or "keyup"
// asign a selector like "#elementID" or ".element-class-name" or even just "ul li"
$(document).on("event", "selector", function(e) {
/* DO WORK
like any other event callback
*/
})
// for older versions of jQuery, use .delegate or .bind
$(document).delegate("event", "selector", function(e) { })
})
However, don't forget, .load has a callback function as well. Thus you could do something like:
$(function() {
$('#oldnews').load('ajax/older_news.php', function(response, status, jqXHR) {
$(".new-stuff:visible").hide();
});
})
.bind()
.delegate()
.load()
.on()

Can jQuery be applied in jQuery generated content?

I don't know why this is not working.
When a li element is clicked I call a PHP file to get some results back and print them in my page. So far so good.
$("li").click(function(){
var item = $(this).html();
$.getJSON('fSearch.php',{sTerm: item}, function(data){
var results='';
$.each(data, function(i, item) {
results += "<li id='t'>"+item.Description+"</li>";
});
$('#ResultsHolder').html("<ul>"+results+"</ul>");
});
});
The first time I click to a li element all works fine, I get results. Now these results is another set of li's and I want them to behave the same, but when I click on the generated li's the function is not executed..
Why is this happening? Why jQuery does not recognize the dynamically inserted li elements?
Thanks in advance!
When you use a event shortcut (such as click, or hover) it will only work for events which are available to the DOM on page load. As you are appending elements dynamically you need to delegate the event listener to an element which is always available in your page.
In the example below, I've used #ResultsHolder.
$("#ResultsHolder").on("click", "li", function(){
var item = $(this).html();
$.getJSON('fSearch.php',{sTerm: item}, function(data){
var results='';
$.each(data, function(i, item) {
results += "<li id='t'>"+item.Description+"</li>";
});
$('#ResultsHolder').html("<ul>"+results+"</ul>");
});
});
That should work for jQuery 1.7+. For an older version of jQuery, use delegate()...
$("#ResultsHolder").delegate("li", "click", function(){ ...
Also, all the appended li elements have the id of 't'. This will end up with invalid code as ids should be unique. Use a class instead if you want to have a group identifier.
.click() is not a live handler, is only binds the event to elements that exist in the DOM at the time of execution. If you want the events to be live, you'll need to look into another handler, such as .on()
When you call ("li").click(), you are binding events to the existing li elements. When you create new li elements, you need to bind them to the event so the click will work.
So, change your loop to something more like this...
$.each(data, function(i, item) {
var li = $('li').text(item.Description);
$(li).click(function(e) { loadChildren(this); });
$("#ResultsHolder").append(li);
});
The 'li' elements that are added to the page don't have the function bound to their click event handler. You need to use the jQuery live() function to do this.
http://api.jquery.com/live/
Basically rather than .click(function(){}) you need to do .live("click",function(){})
Because the binding the .click functionality to all li's happened before this new one was created. JQuery has the .on() function, which could solve your issue.
$("li").on("click", function(event){
// do functionality
});
Use .delegate() : $(document).delegate("li","click",function(){...})
Or, the newer version, .on() $('li').on("click",function(){...})
If your li's are in some fixed div, you can make it faster by replacing document in the first snippet with the selector of that div; and make the second one $(SELECTOR).on("click","li",function(){...})

jquery append with checkbox, if checked, it wont return anything?

I have dynamically generated a list of wine types from the database using AJAx and PHP
here is the function
function wineTypeHandler(data){
var Type = data.Type;
var countType = data.countType;
for(var i = 0; i < countType; i++){
$("#selectType").append(
$("<input />").attr({
type: 'checkbox',
name: 'Type',
class: 'wineTypeCheck',
value: Type[i]
}), Type[i] + "<br />"
);
}
}
As you can see I have "appended" the results to some div with id selectType, this whole thing works fine, my only problem is when I want to update another list based on what has been checked from this list, it doesnt respond to anything!. When i try this one and many other ways
$(document).ready(function(){
$(':checkbox').click(function(){
alert('started');
// other code
return true;
});
});
It doesnt alert anything!! Can anybody help me with this problem.
thank you in advance.
.click() attaches itself to elements that exist when the DOM is created. Your elements are being dynamically generated, so .click() doesn't actually get applied to them.
You should use .live() to target dynamically generated elements, as it attaches itself to any element that is created after the DOM is initially loaded. I also suggest using the change event instead of a click:
$(':checkbox').live('change', function(){
// No need to return true;
});
This is because you are assigning the click function once your page has loaded but before your checkboxes have been dynamically created.
Depending on what version of jQuery you are using you can use the on() (for jQuery version 1.7 or above), delegate() (for older versions of jquery) or live() (simple but inefficient) functions to register an event to dynamically created elements.
Just try this
$(':checkbox').live('change', function(){
});
You need to bind the click event after the element has been added to the DOM. This is a popular problem for JavaScript development. I'd recommend creating a function that sets the bind event, and calling it after your append call (as well as on jQuery(document).ready()).
Edit: I see a lot of recommendations for jQuery.live() It's important to note that the live() method of jQuery is deprecated and should not be used.
The event is bound only to the existing elements. You need to use live
$(':checkbox').live("click", function(){
alert('started');
});
EDIT:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
jQuery 1.4.3+ use delegate
$(#selectType).delegate(':checkbox', "click", function(){
alert('started');
});
jQuery 1.7+ use on
$(#selectType).on("click", ':checkbox', function(){
alert('started');
});

Using jQuery 'click' function that was loaded with Ajax content?

I have the contents of a php file loaded via Ajax that contains HTML and JavaScript. I have a button:
<button class="search_button">Search</button>
And I have a script underneath that will update the documents hash from a jQuery function
<script type="text/javascript">
$(".search_button").click(function() {
var searchTerm = $('#search_box').val();
document.location.hash="searchTerm";
return false;
});
</script>
This code works when I run the php file separately, but when loading this page from an Ajax call, the function no longer runs. In firebug the script is not present so I am assuming I cannot load a script in using this method. I tried also putting the JavaScript snippet instead a header for the whole website, but this failed also.
I was also thinking perhaps the function has to be declared when there is a search_button class already present, but it was structured in this way when I previously had them in one file (that was retrieved via Ajax) to no avail so I'm confused as to the problem.
You can include it globally with a live event:
$(".search_button").live('click', function() {
var searchTerm = $('#search_box').val();
document.location.hash="searchTerm";
return false;
});
jQuery will automatically evaluate script blocks, you cannot see the function in the HTML because it has been stripped out. However it should have already run. The problem is most likely timing. You could do something like
setTimeout(function(){
$(".search_button").click(function() {
var searchTerm = $('#search_box').val();
document.location.hash="searchTerm";
return false;
});
}, 500);
So that when the script is loaded it waits to be executed (hopefully giving jquery time to update the DOM with the new element).
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
This method provides a means to attach delegated event handlers to the document element of a page, which simplifies the use of event handlers when content is dynamically added to a page. See the discussion of direct versus delegated events in the .on() method for more information.
Rewriting the .live() method in terms of its successors is straightforward; these are templates for equivalent calls for all three event attachment methods:
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
Example usage of .on() to bind click event
$(document).on("click", "#post a", function(){
alert("1");
})
Try to add the script inside a function
function name(){
$(".search_button").click(function() {
var searchTerm = $('#search_box').val();
document.location.hash="searchTerm";
return false;
});
}
and call this function just after the end of the ajax call.
$(document).ready(function() {
name();
});

Categories