I cannot manipulate/select divs loaded via Ajax call? - javascript

I've a simple application, and I decided to use ajax to load levels for simplicity / whatever reason (maybe to learn a bit).
But I'm stuck...
$.ajax({
url: "actions.php",
get: "GET",
data: "show_level=" + 1,
cache: false,
success: function (views){
$(".slides_container").append(views);
}
});
The problem is, views appended to my container is not selectable anymore, basically all jquery functions I had stopped working alltogether.
What is happening?

If you are using bindings like $(".target-element").click(function(){ do something here}); they are only valid for elements already in the DOM when the binding happens.
You would need to use $("#element-already-in-dom").on("click", ".target-element", function(){do something here});

You are a victim of non event bubbling.
When you bind an event to an element you typically do this on window load. If an element is added to the DOM after window load, the event will not be bound to it, despite it meeting all other conditions as laid out by your event handler.
Instead, you must use delegation, this means that events are bound to non changing elements on the page and then bubble up to the correct elements.
$('.appended-view').click(function(event) { ... }
Will not work
$('body').on('click', '.appended-view', function(event) { ... }
Will work

Related

Use onclick function after ajax call

So I have built one page that all the data gets pulled into. Works great in IE9+ and chrome but need it to work in IE8 and anything that is pulled in through ajax wont work. Code would be something like this.
ajax
$.ajax({
url: "includes/myfile.php",
type: "GET",
data: ({'data' : data,}),
success: function(data){
$("section").append(data);
}
});
JS
function myfunction(data){
//do something
}
HTML
< button onclick='myfunction(data)' > click here < /button>
Note: I know $(something).on(stuff,stuff) will work but that would involve rebuilding all my functions. so trying to avoid that if I can.
It is because jQuery /JavaScript is unaware of the items that are loaded in myfile.php. The easiest solution is to use on() to delegate the events there, so those events will bubble up the DOM tree.
http://api.jquery.com/on/
For instance -
$(document).on('click', 'element', function() {
Now, when element is clicked the click event bubbles up to document where it will be acted on. The element that the event bubbles up to must exist at the time your jQuery code originally runs so jQuery is 'aware' of the element and can intercept bubbled events to that element. That makes document a fairly safe bet, but you can narrow it down if you desire.
If you don't want to go the easier route you can write event delegation in vanilla JavaScript:
// get the parent element, add a click listener...
document.getElementById("element").addEventListener("click", function(e) {
// example using a list item
if(e.target && e.target.nodeName == "li") {
console.log("list item ", e.target.id.replace("post-"), " was clicked!");
}
});

jQuery trigger click triggers twice

I have a checkout form that uses php to load some javascript & html into #Div-A when the page loads. The javascript binds a click event to #Button-A in the same div. Something like this:
<div id="#Div-A"><input type="button" id="Button-A"/>
<script type="text/javascript">
$('#Button-A').bind('click', function() {
$.ajax({
type: 'get',
url: 'some/url/gets/called',
success: function() { this happens on success }
});
});</script>
</div>
Afterward, #Global-Button is created and a javascript function binds a different click event to this second button which then triggers #Button-A to be clicked like this:
$('#Global-Button').live('click', function(event) {
$("#Button-A").trigger("click");
})
The reason being that the contents of #Div-A can change (via ajax), so the second button acts as a global trigger regardless of which button or function happens to reside in #Div-A.
The problem I'm encountering is that for some reason if #Global-Button is clicked after page load #Button-A gets triggered twice. If an Ajax event reloads the contents of #Div-A then all is well and the the trigger happens only once as it should.
I've examined the html within #Div-A before and after reloading via Ajax and everything appears to be identical. There are definitely no duplicate buttons or functions anywhere as far as I can see that would cause two events to be triggered.
I know only a very little about the DOM and can only guess this has something to do with the order in which things are loaded and events are bound.
This is always recommended to use 'unbind' before bind to make sure the event is not bound multiple times. In your case, there may be two possibilities -
'#Global-Button' click function is bound twice.
'#Button-A' click function is bound twice and '#Global-Button' is actually triggering the click once.
Change your code like -
$('#Global-Button').unbind('click').bind('click', function(event) {
$("#Button-A").trigger("click");
})
and also -
$('#Button-A').unbind('click').bind('click', function() {
$.ajax({
type: 'get',
url: 'some/url/gets/called',
success: function() { this happens on success }
});
});
Don't use .live. Live is deprecated use .on instead
Every time you click on #Blobal-Button you are biding an click event.So you need to off before use it
Use .off to remove event handler
$('#Global-Button').off('click');
$('#Global-Button').on('click', function(event) {
$("#Button-A").trigger("click");
})
You can also use
$(".selector").on("click", function (**e**) {
**e**.stopImmediatePropagation();//use to stop click twice or more
})

How to avoid multiple loading of jQuery functions?

I am using following code on my page which I am loading in ajax.
$(document).ready(function() {
$('#button_id').click(function() {
//Do Something
});
});
Now When I click on the button action happens multiple times. I know that its happening because I am loading the ajax page multiple times.
Please help me solve this.
You can use .off() to remove existing listeners:
$(function() {
$('#button_id').off('click').click(function() {
//Do Something
});
});
If I am wrong about your implementation I apologize. Your problem may exist because the binding is created on first page load and then on subsequent ajax loads with new scripts being inserted and creating duplicate bindings. You should prevent any bindings from being generated on ajax loads to prevent duplicate bindings unless you are good with cleanup.
If the button you are clicking on exists in the ajax loaded area then you should use delegation to ensure that the click handlers still work.
For example:
$( "body" ).on( "click", "#button_id", function() {
//do something
});
This will add a binding to the body element, but more specifically to the id #button_id. A click event on the button will propagate and bubble up to the body element (or whatever parent element you choose).
This makes it so that dynamic elements can be inserted in the DOM and only one event handler is needed to listen for it.
No need for .on() or .off() calls for individual ajax loads. This allows your bindings to be much cleaner.
Of course, if your button is not likely to exist on the page all the time then it would not be a good idea to keep extra bindings. Only create these types of binding if they are always needed to prevent optimization issues.
A cleaner solution would be to remove that code from the ajax loaded HTML and use one single event handler in the master page
I guess your problem is the event is firing many times.
To fire only once try this:
$(document).ready(function() {
$('#button_id').on("click",function(e) {
e.preventDefault(); // This prevents the default non-js action (very used for anchors without links or hashes)
e.stopPropagation(); // Prevent the bubling of the event and spread more times
//Do Something
});
});
If doesn't work with e.stopPropagation(); try with e.stopInmediatePropagation();
Adding documentation for the last method I suggested. It could solve your problem.
http://api.jquery.com/event.stopimmediatepropagation/

What's the best way to event handle dynamically created HTML? [duplicate]

This question already has answers here:
Adding event listeners to dynamically added elements using jQuery [duplicate]
(4 answers)
Closed 8 years ago.
It's very easy to event-handle when dealing with items the document has from the get go:
$(document).ready(function() {
$('.element-in-question').on("event", function (event) {
//do what you need to do during the event
});
});
My problem is how would I best deal with dynamic elements. For example, let's say I dynamically load notifications, some of which are friend requests during an AJAX request. Would I create the event-handler in the success callback, or would I do it somewhere else?
The way I would currently go about it:
$(document).ready(function() {
$.ajax({
url: '/friendships/requests',
type: 'GET',
success: function(responseData) {
//dynamically create your elements (with classes accepted and rejected)
$('.accepted, .rejected').on("click", function(event) {
//do what is needed in this event
});
}
});
});
Is this the idiomatic way to go about it, or is there another way I probably should be going about it?
use jquery's "on" merhod to bind event handler to parent element (which will not change) and pass a selector of the element you want to listen to:
$('.parent').on('event', '.child', handlerFunction);
If you dynamically create an element, such as a 'button', that was not on the page before, handle it like this:
$(function() {
(function() {
$('body').append('<button id="newButton">Hello World!</button>');
})();
$('body').on('click','#newButton',function() {
console.log($(this).html()); //"Hello World!"
});
});
I think this is the (partly) right approach. You cannot and should not apply eventhandlers to objects that might or might not be available, even if possible.
If the situation would involve 10000 different eventhandlers, they should be only available when present in dom. When removed the eventhandler should be removed as well.
The way you do it is rudimentary but correct.
2 other thoughts. If you bind the listener in the ajax callback you might add to the "stack" of events, since they are not replaced. Not a good thing. If the ajax query will happend more than once, do not add it again, if not removed first.
Another aproach might be to just add them to all pages, if this is a small page/application and first check that the element exist. Like so:
if ($('#id').size() > 0) {
// bind events for #id here
}

Is it safe to put all your code inside `$(document).ready`?

I'm using jQuery for a small project I have and it's one of my first times using it. Is it safe to put all my UI code in $(document).ready() ? I'm basically creating a form that pops up when a button is pressed, and the form is processed via AJAX. Basically, when I separate my AJAX function from the functions controlling the UI, the AJAX doesn't work. However, when I put both of them in $(document).ready(), everything works fine. Here's my code. Please ignore my comments, as they were for learning purposes.
$(document).ready(function(){ //ready for DOM manipulation
/*FORM UI*/
var container_form=$('#container_form'); //container form box
var addButton=$('.addButton'); //"+" add button
container_form.hide(); //initially hides form
$(addButton).click(function(){
$(container_form).toggle('fast');
/*SUBMISSION AJAX*/
$('form.ajax').on('submit',function() { //Make form with class "ajax" a JQuery object
var that = $(this), //"that"-current form, "url"-php file, "type"-post, "data"-empty object for now
url=that.attr('action'),
type=that.attr('method'),
data={};
that.find('[name]').each(function(index,value){ //search all elements in the form with the attribute "name"
var that=$(this), //legal attribute
name=that.attr('name'); //name of the legal attribute
value=that.val(); //value of text field in legal attribute
data[name]=value; //data object is filled with text inputs
});
$.ajax({
url: url, //url of form
type: type, //type of form
data: data, //data object generated in previous
success: function(response){ //reponse handler for php
if(!response){
console.log("Error");
}
console.log(response);
}
});
return false; //Stops submission from going to external php page.
});
});
});
Generally any selectors such as $('form.ajax')., $('#container_form'), $('.addButton') needs to be in doc.ready to ensure that the DOM is ready before you try to select an element from it, since it may not find the element if the DOM hasn't finished processing. So that pretty much applies to all of your code. If you had a function such as this:
//defines a function
function addThem(first,second)
{
return first + second;
}
You could declare it outside of doc ready, and call it from within doc ready.
$(document).ready(function(){
$('#someInput').val(
addThem( $('#anotherInput').val() , $('#thirdInput').val() )
);
});
The way I think about this, is doc ready is an event, so you should be doing things in response to the "document is now ready for your to query event", not declaring things. Declaring function just says what that function does, but doesn't actually do anything, so it can go outside of the document ready. It'd be pretty silly to declare this function inside of doc.ready since it can be defined at anytime (although it certainly is possible to put it inside doc ready, it just generally clutters things up). Even if it were selecting an element, that code isn't actually running until it is called:
function hideContainer()
{
//this code never runs until the function is called
//we're just defining a function that says what will happen when it is called
return $('#container').hide();
}
$(document).ready(function(){
//here we are calling the function after the doc.ready, so the selector should run fine
hideContainer();
});
Note that the act of wiring up to other events is an action in itself, such as when you subscribed to the click events and form submit events. You are saying, "find the form element with class .ajax, and subscribe to its submit event". You wouldn't want to try and wire up to events of DOM elements until the DOM is done processing. They might not "exist" yet as far as the browser is concerned if it is in the middle of processing the DOM, and thus your attempt to wire up to the click/form submit events may fail. I say may because depending on timing/processing lag it may sometimes work and sometimes not.
There's not only nothing wrong with putting all your code into one $(document).ready(), but there's nothing wrong with putting it into multiple $(document).ready() functions either so that you can separate repeated functionality into individual JS files.
For example, I use $(document).ready() in a script included on all my site's webpages to set up UI elements, prevent clickjacking, etc. At the same time, each page regularly has its own $(document).ready() which sets up page specific user interactions.
It is absolutely OK. If you find yourself needing to abstract your code into multiple function or multiple files, then by all means, but there's nothing wrong with throwing everything in $(document).ready().

Categories