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.
Related
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.
programs! I've found solutions to similar problems such as mine here on the site but what's happening to me is rather unusual and I don't think they apply.
On this page: http://tdg.gswitchhost.com/calendar/
I'm locked into using this plugin which I really don't care for. This is a Wordpress site but the plugin, which lists upcoming events, doesn't behave like Wordpress. It has this system in place which is entirely unique to it. Posts live outside of the posts database table and you have to query these in an entirely different way. It's a bummer. So my problem:
We have some jquery working its magic on the events list to add an accordion effect and this works. However. When you click on the pagination links to load the next set of events, the plugin, instead of linking to page 2 of events, it runs an asynchronous query and loads the next set of events on to the existing page without a page reload. If you click on one of the new events, the accordion no longer works.
What I think is happening is that on click, the plugin removes the entire UL which contains the events and loads a second entirely new one, containing the second record set, with the same class name but since the javascript initialized on the first UL, the one the plugin removed, the new set hasn't been affected since the page didn't reload and run the javascript again.
I've tried using .on() and the Livequery plugin to rerun the javascript when you click the pagination links but there's a delay as the query is running and loading the new UL so I believe that the javascript runs again when you click on the link but because the UL hasn't been loaded already when you click, there's nothing for the jquery to work on.
Sorry this is so long but I just want to be as clear as possible. Am I wrong? This is killing me, I'm running out of time and I really need to get this to work so that no matter which set of events has been loaded on the page, the accordion function works on it.
Here's the javascript that initializes the accordion:
$('.eventListingNew').accordion({
headerClassName: 'accordionHeader',
headerActiveClassName: 'accordionHeader-active',
contentClassName: 'accordionContent',
collapseAll: false,
speed: 250
});
And here's a pastebin of the entire accordion function since it's so long. http://pastebin.com/BvDseg3g
Easy thing is just call it when the Ajax complete is done running to reinitialize it.
$(document).ajaxComplete(function(event, xhr, settings) {
$('.eventListingNew').accordion({
headerClassName: 'accordionHeader',
headerActiveClassName: 'accordionHeader-active',
contentClassName: 'accordionContent',
collapseAll: false,
speed: 250
});
});
I am creating a jQuery Mobile web app, which loads some pages.
For example, a.html is my main page. It may call b1.html,b2.html,...,b100.html (User may click on one of buttons). (The pages are loading with ajax navigation feature of jQuery Mobile)
And there is some events in each b[i].html page, and ids and many things are same in every b[i].html page. But the point is, at any time, just one of them may be in DOM. So there will be no id conflicts or such.
The problem
The problem is the conflict of the events. When user come back to a.html from b[i].html, the HTML will be removed, but events will remain. This will cause many problems if I first go to b[i].html, and then come back to a.html and then go to b[j].html. I mean, b[j].html will not work correctly... :(
What I have tried
I have putted this in a.html, to remove all events:
$("#mainpage").off("pagebeforeshow").on("pagebeforeshow",function() {
$("*").not("#mainpage").off();
//Other initialization codes...
});
But, problem not solved...
(mainpage is the id of data-role="page" of a.html)
Example
For example, I have this in each b[i].html:
$(window).resize(function () {
alert("Resized");
});
At the beginning (in a.html), If I resize the window, there will be no alerts, but after visiting b[i].html and then coming back to a.html, I'll see alerts if I resize the window, even with that line of code (What I have tried part.)...
So, How to remove those event handlers when users come back to a.html from b[i].html?
If you are using jQuery Mobile, more than one of said pages may exist in the dom at the same time, resulting in non-unique id conflicts.
I would ditch putting js on the individual pages and have it done from the primary page, or through a script loading system such as require.js. Then do all of the events through delegation from the document. Obviously that won't work with window.resize(), but it doesn't need to be delegated anyway.
"Can you please explain more?"
Basically, if you are including scripts on the child pages, you will need to have both setup and teardown for every page. setup adds the events, and teardown removes them. If you instead used a single global script that adds ALL of the events using event delegation from the document, all of the pages should work. Obviously that global script could get pretty big on a complex site, so you could instead use require.js to load in js that does the same thing as needed, preventing it from loading the same dependency more than once.
As far as removing all events, I've never tried this, but can you use $("*").off()? According to the docs it should work. I'm not sure how it will affect jQuery mobile. To remove events on the document and/or window, you will have to do it manually because $("*") will not select them.
$(document).on("vmousemove","#link",func) is how you delegate an event from the document.
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.
I have a page that lists a bunch of files. This page can be accessed directly via a URL or it can be loaded in a modal dialog via ajax from a different page.
If the files page is loaded via ajax, I would like to allow the user to click the name of the file and trigger an action in the page which loaded the files page. For example, there is an article edit page. This page contains an "attach a file" button. When the user clicks the button, the files page is loaded in a modal dialog and when a filename is clicked, the id of the file is inserted into the article form and the dialog is closed. However there is also an event edit page with a similar button, but I would like to handle the filename-click event slightly differently on this page.
I'd like to handle these click events slightly differently depending on the calling page. At the moment I'm defining a handler function with global scope in the page containing the form to which files are being attached, then testing for that function in the the files-page when the filename is clicked and calling if it exists. It works but it feels a little hacky. Is there some kind of best practice for this sort of thing that I'm not aware of?
I'm using jQuery if this makes things easier in any way..
Instead of relying on a global handler function as the interface between pages, you could rely on custom events instead:
"calling page":
$(document).bind("fileClicked", function(event, fileName) {
alert(fileName);
});
"page loaded via ajax":
$(".file").click(function() {
$(document).trigger("fileClicked", [$(this).text()]);
});
You should look at jQuery Live
Attach a handler to the event for all elements which match the current selector, now and in the future.
When a Ajax page is loaded it's not processed by the DOM in the same way the main page was loaded, therefore using live will attach the event on all current event emitters as well as the future ones such as dynamic Ajax content
Within your Ajax model
<div>
...
Add to main page
...
</div>
and within your static page (the one originally loaded)
$("#ajax_click_event").live('click',function(){
//Work wit the value of the form within the ajax div.
})