JS Triggers fire correctly only on every other pageload - javascript

I'm running JQ 1.10.2 and JQM 1.4.0 The code has been trimmed for explanation.
index.php: Contains a number of menu items and the following JS. When a menu item is clicked, the JS is executed on the destination page because of pagebeforeshow. The destination page contains links back to index.php.
$(document).on('pagebeforeshow',function() {
var baseHref = document.getElementsByTagName('base')[0].href;
var filename = baseHref.split('/').pop();
switch (filename) {
case 'page1.php':
$(this).on('tap','.log-item',function(){
$(this).children('.log-item-more').toggle();
});
break;
case 'page2.php':
//other js
break;
case 'page3.php':
//other js
break;
}
});
In short, that JS finds the destination's filename and uses a switch statement to determine which page-specific JS to load.
The unexplainable thing is that when I load up index.php and click the page1.php link, page1.php loads as expected and it's JS from the switch statement works as expected as well. Next, I click the link to go back to index.php, then click the link to goto page1.php, the page loads as expected but the JS doesn't fire this time.
If I repeat the back and forth, the JS works 1 time, then doesn't the next and continues in this predictable 'on/off' cycle. I've never seen this behavior before and I'm at a loss.
UPDATE:
After further looking into this. I realize that the code within the switch statement is initialized each time the page is created. That means that the .on('tap') event listener is initialized once on the 1st page load, 2x on the 2nd page load, 3x on the 3rd page load, etc. I'm using a toggle, which is hide or show, and that's why it appeared that the code was not working when in fact is was!
Now, my question is which event should I be listening for in place of pagebeforeshow to only be triggered the 1st time that particular page is loaded in the session?
UPDATE:
Looking at the jQuery Mobile API Documentation, it looks like pagecreate is the event listener I'm looking for, but it behaves just like pagebeforeshow and pageinit.
I don't know why these events are acting this way... are they broken in this version of jQM?
Or am I linking these pages incorrectly? Perhaps <a href='log.php' data-transition='flip'>Log Page</a> is the wrong way to construct the anchor?

SOLVED:
I was not following jQuery's jQuery's Multiple Page Temple Structure properly!
I structured each page to be wrapped in a <div data-role="page" id="pagename"> tag.
I then included each page's JS just before closing that page's data-role="page" tag. I did not wrap it in any event listener ($(document).on('pageinit',function(){ });)!
Lastly, on the dashboard.php (my webapp's home page, basically), I included data-prefetch="true" in each anchor tag.

Related

jQuery not working when called into another page

I have this form on one page that we use as a tool. It's on page tool.html, in div id="tool"
Since this tool is to be shown on another page as well, I want to pull the tool in and not have to copy and paste (in case changes are done later on, this will reflect it everywhere)
Now, I have put all the jQuery functions in a separate file that I link in, so I can reuse it on many pages.
I can call in the form properly by using
<script>
$(document).ready(function() {
$("#lyristool").load("../path/tool.html #tool");
});
</script>
And I can confirm that the linked script page is loaded in properly, but it's not working at all.
Why will the linked script work on the original page, but not on the page when that whole containing div is pulled in?
Try to execute this line:
$("#lyristool").load("../path/tool.html #tool");
before loading the other script. I think your binding is not working because those elements don't exist on the page at the moment of binding.
In order to be able to do that, you should put all your binding code in a document.ready callback.

Fire event when browser parses/renders a DOM element

Assume that we know that an element (or a very specific selector) is going to appear on a page. Is it possible to set up beforehand, via JS or jQuery, an event that goes off when the browser gets to that element and parses it? This is NOT content loaded through AJAX but is present in the primary page's source.
The reason for this need is that I'm working with a hosted system that greatly limits where and when I can inject code to fix problems with the page. I can pretty much only place my code at the start and end of what is a really long page. Right now, the page has to load completely before it can inject any desired changes (yuck!). Plus, I cannot make the pages shorter in content.
This is basically the process I would like to happen:
Page begins loading
Listener set up to watch for .specialClass elements
...
.specialClass element gets parsed/added to DOM
Listener triggers function on that element
...
.specialClass element gets parsed/added to DOM
Repeat as before
...
Page finishes rendering
So, is this possible at all? Thanks in advance.

jQuery function and Page Reload issue (maybe)

I have this code (accepted solution).
This code snipped loads from a js file. When I put a breakpoint at this function, I see that this function getting called when the page (that includes it) is loaded.
After the initial page load, when I choose an option in this page, that anchor element is reloaded (Ajax) exactly same (js file does not reload) as part of the piece of data. However, now when I click on anchor link, it does not fire / open the outlook window.
Is it something about jQuery functionality that I am mis reading/using?
How do I resolve this?
If the element is reloaded you'll need to rebind the click event to it.
Alternatively to the way you are doing it you could bind to the window/body and just specify the id as the selector like this:
$('body').on('click', '#emailLink', function (event) {
// your code here...
});

Get the loaded page in jQuery Mobile 1.4.2

I'm used to the older jQuery Mobile interface where I could write:
$("#page").on("pageLoad", function(){
//Do something
});
With the newer pageContainer widget and it's events, I do not know to do detect what page was loaded.
For example, I need to know how to detect that the #settings page was just loaded. So far I can figure out
$("body").on( "pagecontainerload", function( event, ui ){});
but I have no way of knowing what page was loaded. I've tried using the returned event and ui values but without success.
It seems part of my problem is coming from improper use of
$("body").pagecontainer("load", "welcome.html");
I use that in the beginning of my js file to load them all into the DOM. However, when I navigate to that page, then away from it again it is removed from the DOM. For example, I load welcome.html, settings.html, and devices.html with the above code. Then, I have links like
Settings
And when I use that link to go to the settings page, then another of the same kind of link to go to the devices page, the settings link no longer works. Upon inspecting the DOM, #settings has been removed. Infact, so has #welcome. As soon as I navigate away from that page it is removed from the DOM. So either I have done something wrong, or my understanding of the pagecontainer widget is flawed.
Update
Based on your updated OP, external pages are removed once you navigate away from them, this is the default behavior of jQM. If you want to keep those pages, you need to add data-dom-cache="true" to page div of each external page.
You can retrieve page loaded from ui object emitted on pagecontainerload.
$(document).on("pagecontainerload", function (e, ui) {
var loadedPage = $(ui.page),
pageID = loadedPage[0].id;
if (pageID == "settings") {
/* code */
}
});
Note that pagecontainerbeforeload, pagecontainerload and pagecontainerfail, are only emitted on pages loaded externaly. Moreover, they will fire everytime an external page is loaded, unless DOM cache is enabled. Read more about those events here.
Demo

How to clear javascript of functions initialised after ajax call

I have the following pages. Page A and page B.
Page A contains:
Page A HTML
Page A javascript
Page B javascript
I then use an ajax call to load Page B HTML into page A and fire a function to initialise page B's javascript.
If I decide to remove Page B from Page A, I will also want clear all of the JavaScript functions that were also initialised when pageB was loaded?
Is there a way to clear JavaScript functions?
You can use separate namespaces in both pages. So, e.g., page A places all its JavaScript under window['pageA'] whereas page B uses window['pageB'].
To unload all of the functions from page B you simply have to use
delete window['pageB'];
Beware, however, that this does not clear any handlers or references to the functions of page B. So if there are some left, this might lead to errors.
For the way you structured your code, you can simply "delete" the function initPageB_function and you should be golden, like so:
delete initPageB_function;
If you have to reload the content of pageB again into the page, then it's a different story, because you should re-bind the event handlers for your onclick events.
At this point it's much way better to follow another approach:
Put the markup AND the javascript code that deals with the event handlers for pageB "into" pageB; this way, when you load pageB via Ajax you'll load also all the JS code that deals with that page; this is called delegation (and it makes perfect sense, cause your container - pageA - is not supposed to know what it is going to be loaded).
If you're using an helper library like jQuery, everything should be pretty simple:
somewhere in pageA, you define a spot for loading pageB content:
<div id='pageB'></div>
when you have to load it:
$('#pageB').load( 'http://url.for.pageB' );
As soon as the load progress, the JS code in pageB will be executed and you'll be golden :)
To remove the content of the page you will simply empty the container:
$('#pageB').empty();
And the JS too will be gone.
The next time you'll reload the page again, its own JS will be executed again. pretty simple and effective. :)

Categories