2

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?

Mahdi Ghiasi
  • 14,873
  • 19
  • 71
  • 119
  • Use a delegated event handler: `$(document).on("pagebeforeshow", "#mainpage",function() { ... });`. That way the event handler will be ready whenever the actual element is in the DOM. – Jasper Sep 11 '12 at 21:04
  • @Jasper I have tried it now, but the problem still exists... – Mahdi Ghiasi Sep 11 '12 at 21:07
  • 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. – Kevin B Sep 11 '12 at 21:08
  • 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. – Kevin B Sep 11 '12 at 21:12
  • I have checked, and the pages are removing correctly from DOM. – Mahdi Ghiasi Sep 11 '12 at 21:14
  • @KevinB Can you please explain more? – Mahdi Ghiasi Sep 11 '12 at 21:14
  • 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. – Kevin B Sep 11 '12 at 21:17
  • 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. – Kevin B Sep 11 '12 at 21:21
  • @MahdiGhiasi you said that all pages are removing correctly. the only way that is possible is if you are not using transitions. If you are using transitions, both pages will exist in the document during the transition and right before the transition, when the pageInit event happens. – Kevin B Sep 11 '12 at 21:23
  • @KevinB They are available at `pageinit`, but not after transition. Also, I'm removing them in `pageshow` event of the main page... – Mahdi Ghiasi Sep 11 '12 at 21:25
  • 1
    By the way, `$("*")` will not select the window. you have to remove that event directly. – Kevin B Sep 11 '12 at 21:28
  • @KevinB If I have something like this, `$("#link").on('vmousemove',function() { /* something */ });`, Will it work even when divs with `link` id are created, destroyed and then created and ... (navigating between pages)? – Mahdi Ghiasi Sep 11 '12 at 21:28
  • @MahdiGhiasi No, it would have to be `$(document).on("vmousemove","#link",func)` then it will do what you mentioned in the comment. – Kevin B Sep 11 '12 at 21:29
  • @KevinB Problem solved by adding `$(window).off()` to `pagebeforeshow` of `a.html`, as you said. Can you please send all of your comments (even your suggestion about using global scripts, and your the last comment) as an answer? – Mahdi Ghiasi Sep 11 '12 at 21:37
  • yes, http://stackoverflow.com/a/33271131/257319 –  Oct 21 '15 at 23:46

1 Answers1

3

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.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Thank you so much. This solved my problem: `$("*").not("#mainpage").off(); $(window).off();`, And I think having a global script is much better, cleaner and faster, Thanks for your suggestion :) – Mahdi Ghiasi Sep 11 '12 at 21:42