Some background;
By default when you click a link to a separate HTML page JQM loads the first data-role="page" on that page and attaches it to the DOM of the first page, the thing is JQM only loads that page div and not any scripts etc. that are outside that container.
I have a jQuery mobile app with 5 pages "login.html" "menu.html" "account.html" "settings.html" ..etc
I change pages with like;
$.mobile.changepage("account.html")
Also I put all my page load logic to my first page login.html like this;
<script>
$(document).on('pageinit', '#loginpage', function() {
//do some stuff run some ajax scripts and add some html to its body
});
$(document).on('pageinit', '#accountpage', function() {
//do some stuff run some ajax scripts and add some html to its body
});
$(document).on('pageinit', '#settingspage', function() {
//do some stuff run some ajax scripts and add some html to its body
});
</script>
While this app works well, Problem is I find it very fragile and hard to survive from unexpected errors. for example;
Since how every page's body html will load is defined in login.html, this means if any moment user manually refreshs any of these pages, the page will load without running those scripts and load an empty page a without a body. In that moment since the correct DOM is deleted from memory, user is stuck in an app with full of empty pages, only way is he is smart enough to go and type "login.html" to address bar and only then all process can start smoothly.
I think we cant %100 hide address bar, it is visible again after scroll down.
SO this is one problem I come up with, some other weird things can happen and if somehow the DOM gets corrupted only way to use app again is typing login.html address bar, which users probably will not thing about it.
How can I make this app more robust like detecting any DOM corruption or refresh and forward the user to login.html, so he does not stuck in an app with empty pages.
One way to alleviate some pain is to put your page-specific scripts inside data-role="page"
element in the appropriate html files and keep scripts that are the same for every page outside that element (at the and of the body
and/or head
).
That way even if the user refreshes the page all necessary scripts will still be executed. One problem though, before binding any handlers you need to unbind them first. Otherwise you'll end up having multiple handlers attached.
To illustrate this:
in login.html
(updated):
<div data-role="page" id="loginpage">
<script>
$(document).off('pageinit', '#loginpage').on('pageinit', '#loginpage', function() {
$(document).off('click', '#btnaccount').on('click', '#btnaccount', function(){
$.mobile.changePage("jqmaccount.html", {reloadPage: true});
});
console.log("paginit in loginpage");
});
$(document).off('pageshow', '#loginpage').on('pageshow', '#loginpage', function() {
console.log("pageshow in loginpage");
});
</script>
<div data-role="content">
<a id="btnaccount" href="#" data-role="button">Account</a>
</div>
</div>
in account.html
(updated):
<div data-role="page" id="accountpage">
<script>
$(document).off('pageinit', '#accountpage').on('pageinit', '#accountpage', function() {
$(document).off('click', '#btnlogout').on('click', '#btnlogout', function(){
$.mobile.changePage("jqmlogin.html", {reloadPage: true});
});
console.log("pageinit in accountpage");
});
$(document).off('pageshow', '#accountpage').on('pageshow', '#accountpage', function() {
console.log("pageshow in accountpage");
});
</script>
<div data-role="content">
<a id="btnlogout" href="#" data-role="button">Logout</a>
</div>
</div>
In this setup if the user refreshes account.html the Logout button on that page will still work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With