jQuery not working on AJAX loaded html content - javascript

I have a PHP admin dashboard in which am using bootstrap theme. We know it have inbuilt jQuery objects like drop-down menu, collapse, tabs, etc., And it all will work if we just added bootstrap js file.
Now the problem is when I get contents from ajax call and display it on my page, all javascript controls which loaded via ajax are not working.
Am using this ajax call for all my inner pages display. So it may have any bootstrap javascript control on loaded HTML.
So how can I fix this dynamically on every ajax call. My ajax loading javascript is below
$('a').bind('click',function(event){
event.preventDefault();
$.get(this.href,{},function(response){
$('#app-content-body').html(response)
});
});
Note : My problem is not in my above code. Actual problem is bootstrap javascript controls not working when I load html content from above code

jQuery is only aware of the elements in the page at the time that it runs, so new elements added to the DOM are unrecognized by jQuery. To combat that use event delegation, bubbling events from newly added items up to a point in the DOM that was there when jQuery ran on page load. Many people use document as the place to catch the bubbled event, but it isn't necessary to go that high up the DOM tree. Ideally you should delegate to the nearest parent that exists at the time of page load.
Change your click event to use on(), provided your version of jQuery supports it;
$(document).on('click', 'a', function(event){
If you're using jQuery older than version 1.7 use delegate():
$('body').delegate('a' , 'click', function() {
Note the operator order, they are different with on() reading a little more logically.

Related

What's the smartest way to refresh dom handlers after new ajax-loaded content?

I'm working with a large template of charts and other widgets. I also manually implemented some ajax tabs. Now whenever those tabs load new content (charts), the problem is that all the template scripts in the head tag won't work with those ajax-loaded elements anymore.
I know, normally you would use .live for this kind of problem, but this would mean to go into the whole 50k lines-js template and change everything to .live calls... Not really able to do that.
Is there instead a jquery way of reloading/reactivating all the scripts within the head-tag?
First off .live() has long since been deprecated and even removed from the latest versions of jQuery. You should never be thinking of using .live().
Second, as it sounds like you already know, the "right" way to fix this is to change your code to use the delegated form of .on() which is what replaced .live(). Yes, change all the code that does it the wrong way. Here's a post on using the delegated form of .on() instead of .live().
Third, a work-around would be to put all your initialization code that hooks up these event handlers into a single function (or called by a single function). Then, you call that single function upon initialization and then you can call that single function any time later after you reload your content. The trick is that you can only put code into that initialization function that can be called or should be called more than once after you content has been reloaded. If you put some event handlers in there that should not be in there, then you may get duplicate event handlers installed. So, only event handler initialization that applies to the replaced content should go in this function.
Suppose that function was called initDynamicContent, then it could look like this:
// init event handlers on the original version of the dynamic content
$(document).ready(initDynamicContent);
Then, sometime later after you replace the dynamic content, you can just do:
// code here that replaces the dynamic content with new content
initDynamicContent();
There is no magic jQuery way for this to happen automatically. jQuery has absolutely no way of knowing which code should be run again and which code should not.

How do I hide all my label tags in my jQuery Mobile site in an accessibility friendly way?

I am trying to hide all the label tags on my jQuery Mobile site in an accessibility friendly way. To this end, I am using javascript to apply the class ui-hidden-accessible to every label tag on my site per documentation (http://jquerymobile.com/test/docs/forms/docs-forms.html).
However, my javascript is not working.
Here is a Fiddle demonstrating how the label tag still appears.
http://jsfiddle.net/tW4Xu/
Why is it not working? I have also scrutinized other jQM event handlers such as pageinit and pagecreate:
http://jquerymobile.com/test/docs/api/events.html
My javascript to hide label tags:
// done after page is loaded
$(document).on("pageshow", "label", function(event) {
$(this).addClass("ui-hidden-accessible");
});​
It seems like you have a few things going wrong here, although I'm not sure how much of it is coming from the jsfiddle summary and how much is in your full code.
The first thing to note is that 'pageshow' is a page transition event. It seems like you might want to use 'pageinit' instead. Here's how the jQM docs describe it:
Triggered on the page being initialized, after initialization occurs. We recommend binding to this event instead of DOM ready() because this will work regardless of whether the page is loaded directly or if the content is pulled into another page as part of the Ajax navigation system.
$( '#aboutPage' ).live( 'pageinit',function(event){
alert( 'This page was just enhanced by jQuery Mobile!' );
});
Note also here that 1) the event is being bound with live() instead of on() (no idea if there's a difference), and 2) it is being attached to a specific id for a jQM 'page'. This is part of what is missing in your jsfiddle example. There aren't any named jQM pages. jQM kind of messes up the whole idea of a page being ready, since everything is in one html file and then gets chunked out using ids and inserted via AJAX.
And so finally: Even though jQM says not to, if your goal is to add this class to every single label on every single jQM page, I would use good-old $(document).ready() and then use $.each() to change them all in one go. Again, from the jQM docs:
However, in jQuery Mobile, Ajax is used to load the contents of each page into the DOM as you navigate, and the DOM ready handler only executes for the first page. To execute code whenever a new page is loaded and created, you can bind to the pageinit event.
So there isn't anything evil about $.ready(), it's just that this event is only fired once so subsequent page transitions won't trigger it. But that could be exactly what you want in the first place.
This code works on jsfiddle:
$(document).ready( function(event) {
$("label").each( function(index, element) {
element.addClass("ui-hidden-accessible");
});
});​
If in your real site you notice that page transitions cause the labels to come back, then you'll want to bind to something else, again probably 'pageinit'.
Hope this helps! Apologies for the verbosity...I kind of got going there huh?
http://jsfiddle.net/tW4Xu/2/
That? Not sure what your specific requirement is for using on('pageshow'), in my fiddle I used
$(function() {
$('label').addClass("ui-hidden-accessible");
});​
Don't use live its deprecated as of jquery 1.7. You had the right idea just do it before pageshow and make sure you use the page id. Also in your fiddle the top drop down menu change from onload to no wrap(head). I have had issues with that in the past.
$(document).on("pageinit", "#thepageid", function(event) {
$('label').addClass("ui-hidden-accessible");
});​
This will work for all your JQM pages.
$(document).on("pageinit", "[data-role=page]", function(event) {
$('label').addClass("ui-hidden-accessible");
});​

jQuery events and double firing?

When I load jQuery dynamically with AJAX, elements with existing events fire multiple times.
Basically I have one file called 'myjs.js' which hold All my jQuery and is included when the page is loaded therefore setting up events and such for elements.
Now when a user triggers an event like posting a new comment, it sends off (via Ajax) the comment, then it returns a page with the new comment, edit comment, reply etc. Obviously when myjs.js was first loaded it didn't create any events for the newly loaded elements. Therefore I include myjs.js in the page returned with AJAX.
As the myjs.js has already been loaded with the page, when the Ajax page is returned with myjs.js included, it adds another event to the elements that have already been loaded with the page.
I have already tried
$('*').unbind();
But this caused some strange effects.
So any ideas on loading jQuery dynamically while not affecting any events which already exist for elements?
Without seeing the jQuery code, I suspect that the selectors being used to bind behaviour are too generic so as you have discovered, all existing elements plus the newly loaded elements are matched each time:
You could use more specific binding in the JavaScript returned in the AJAX response to add behaviour only to the newly loaded elements.
However, returning the same JavaScript for each AJAX request is inefficient as the browser cannot cache. Ideally you should try and load the JavaScript on the main page once and then rely on jQuery to do .live() binding automatically for the newly loaded elements. This is also known as event delegation - .delegate()
Note that as of jQuery 1.7 these methods have been deprecated in favour of a more concise event binding infrastructure - the .on()

Dynamic content and loading of JQuery scripts several times

I am having a page that loads content dynamically. Depending on which menu item the user clicks, different tables are dynamically loaded and presented using jquery.
One column of each table is having an update linke used to update the content that specific row is representing. When clicking that link a JQuery UI Modal Dialog is presented with a form loaded from a server in which the user should update the content and post back.
This is how I understand it, please correct me if I am wrong. I need to load the jquery script at the same time as I load the dynamic content in order to bind the events between the javascript functions and the elements that is being loaded.
Assuming my assumption is correct I do load the content and the same JQuery UI Dialog scripts each time the user selects a different table. I load the content and jquery files from different javascript functions loaded together with the main index file.
The consequence is unpredictable behaviour (probably predictable using the same use case). When loading the table more than once and updating something so the modal dialog is presented, the dialog is not presented anymore after the first or second usage, as one example.
Could it be a problem that the jquery script is loaded more than once? If it is, what's the principle or patterna I should use for this kind of application. If all above is false assumption, still, what's the principle or patterns for designing this kind of solution where different kind of dynamic content is loaded at several places (all presented within the same index file) and all need the same jquery files.
Take a look a jQuery $.live() and $.delegate():
http://api.jquery.com/live/
http://api.jquery.com/delegate/
These will allow you to bind events to dynamically loaded content.
If I understand you correctly, you are asking how to bind events on dynamically generated content. You do not, in fact, have to load new script at the same time as new content in order to be able to hook events to said content.
What you want is the jQuery 'live' handler. You can specify the target of the binding using standard jQuery selectors. However, instead of the following syntax:
$('.foo').click(function(){ });
You would use
$('.foo').live('click', (function(){ });
The way this works is through event bubbling, where an event invoked on a child element (such as an input box) 'bubbles' up through all parent nodes. In this case, jQuery just watches the whole document for event bubbles, and then matches it against your specific selector conditions.
If I understand you correctly:
1) Multiple tables with an update link on each rows to update their content.
2) Update button opens a modal box with a form.
3) Form is posted and data is retrieved after being processed by the server to feed the concerned table row.
If the flow described above is correct, I don't see why you should load jQuery or jQuery ui more than once.
You should do something like
1) Load the page with all the scripts required.
2) Set up and ajax call with the jquery .ajax() method (doc)
3) Use the ajax call to submit the form data to the server and retrieve the results
4) Use the success callback of .ajax() to feed the row with the updated data. Within the success method you should be able to retrieve the context (a.k.a. the link you clicked) and identify the actual row you clicked.
I hope I make sense.
If by any chance you need to create new rows then you should consider checking the .live() and .delegate() method of jQuery.
Good luck.

Gallery slider bug while loading content via AJAX in jQuery

I'm using a jQuery plugin (link) to pull external pages into a div on my homepage, and each one of the external pages contains a jQuery-based horizontal gallery slider.
Example: http://www.iamtimothylong.com/example
You'll notice that when the external pages are loaded through the AJAX request (by clicking 'book one' or 'book two'), the horizontal slider within those external pages stops functioning.
However, the horizontal slider does work if statically placed in the div (just so it's clear that it's not a problem with the slider itself).
Anyone know a solution/workaround? One guy said
"You need to rebind the slider to the new elements after the XHR request has completed. Inside the success handler of your AJAX request, perform the mScrollBar() binding."
Unfortunately, I'm a programming ignoramus and I need it spelled out in laymen's terms. :)
And the AJAX loader source is located here: /js/menu.js
I would say it is a classic case of replacing the event that is not firing with .live('event')
Basically when the javascript is fired and attaches event handlers when the page is loaded (or whenever they are called), it attaches them to currently existing elements that exist on the page at that time, so when you load in new content (via AJAX) those events are not attached to the new content events that have just been loaded and match the selector.
To fix this jQuery has a .live() event that matches any currently existing DOM elements AND future ones added dyamically.

Categories