jquery mobile page transition seems to be stopping $(document).ready from firing - jquery-mobile

I'm building my first jquery mobile site and have run into a problem. When just doing a straightforward hyperlink from one page to another it seems like the page transition effect is stopping the
$(document).ready(function(){
alert("hello");
});
From firing. If I refresh the page or link to the page directly the event fires.
I've tried removing the data-transition from the hyperlink and even tried
<a data-role="button" data-transition="none" href="/otherpage/">link</a>
But still have the same problem.
Andy ideas please? Thanks.

This is by design, as jQuery Mobile loads pages in the background, then incorporates them in the current document before transitioning. This means the original page is not reloaded, so the document does not become ready again.
Accordingly, the documentation on events prominently says (emphasis from original):
Important: Use $(document).bind('pageinit'), not $(document).ready()
Therefore, you should write:
$(document).bind("pageinit", function() {
alert("hello");
});

Related

Jquery for Mobile in a mobile website - Adsense Issue [duplicate]

I have used $.mobile.changepage to do the redirect in my phonegap+jquerymobile projects. However what makes me confused is that I need to put the script of all the pages to the same file index.html. If not, the redirect page can not execute the function in its header.
for example, my index.html seem to be
$(document).bind("deviceready",function(){$.mobile.changepage("test.html");})
then, my device will redirect to test.html which seem to be
$("#btnTest").click(function(){alert("123");})
<button id="btnTest">Test</button>
However, the script will never execute in test.html. Then I put the script to index.html, what I expect to be is done. Whatever, if I put all the script to the same page, the project will become harder and harder to be preserved. Appreciated for your help.
Intro
This article can also be found HERE as a part of my blog.
How jQuery Mobile handles page changes
To understand this situation you need to understand how jQuery Mobile works. It uses ajax to load other pages.
First page is loaded normally. Its HEAD and BODY is loaded into the DOM, and they are there to await other content. When second page is loaded, only its BODY content is loaded into the DOM. To be more precise, even BODY is not fully loaded. Only first div with an attribute data-role="page" will be loaded, everything else is going to be discarded. Even if you have more pages inside a BODY only first one is going to be loaded. This rule only applies to subsequent pages, if you have more pages in an initial HTML all of them will be loaded.
That's why your button is show successfully but click event is not working. Same click event whose parent HEAD was disregarded during the page transition.
Here's an official documentation: http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html
Unfortunately you are not going to find this described in their documentation. Ether they think this is a common knowledge or they forgot to describe this like my other topics. (jQuery Mobile documentation is big but lacking many things).
Solution 1
In your second page, and every other page, move your SCRIPT tag into the BODY content, like this:
<body>
<div data-role="page">
// And rest of your HTML content
<script>
// Your javascript will go here
</script>
</div>
</body>
This is a quick solution but still an ugly one.
Working example can be found in my other answer here: Pageshow not triggered after changepage
Another working example: Page loaded differently with jQuery-mobile transition
Solution 2
Move all of your javascript into the original first HTML. Collect everything and put it inside a single js file, into a HEAD. Initialize it after jQuery Mobile has been loaded.
<head>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="index.js"></script> // Put your code into a new file
</head>
In the end I will describe why this is a part of a good solution.
Solution 3
Use rel="external" in your buttons and every elements you are using to change page. Because of it ajax is not going to be used for page loading and your jQuery Mobile app will behave like a normal web application. Unfortunately this is not a good solution in your case. Phonegap should never work as a normal web app.
Next
Official documentation, look for a chapter: Linking without Ajax
Realistic solution
Realistic solution would use Solution 2. But unlike solution 2, I would use that same index.js file and initialize it inside a HEAD of every possible other page.
Now you can ask me WHY?
Phonegap like jQuery Mobile is buggy, and sooner or later there's going to be an error and your app will fail (including loaded DOM) if your every js content is inside a single HTML file. DOM could be erased and Phonegap will refresh your current page. If that page don't have javascript that it will not work until it is restarted.
Final words
This problem can be easily fixed with a good page architecture. If anyone is interested I have wrote an ARTICLE about good jQuery Mobile page architecture. In a nut shell I am discussing that knowledge of how jQuery Mobile works is the most important thing you need to know before you can successfully create you first app.
Unlike normal ordinary HTML pages, jQuery Mobile uses ajax technology when navigating between pages. So make sure to import all your JS files and libraries in all your html pages.
If you notice closely you will see that JS files from previous page is taken into consideration when loading the second page. But if you force rrefresh the current page then the js files of the current page will be effective.
So as I said earlier make sure to import the js files in all the html files.
Also no need to call deviceready, use following syntax to call your page specific js functions
$(document).on('pageshow', '#YourPageID', function(){
// Your code goes here
});
Jquery Mobile uses ajax to load a "page". A "page" here is a div with data-role=page. If you load a physical page index.html, you can navigate using changePage to any "page" div inside that page.
However, if you want to load a "page" from other physical page, jQM will only load the first "page" div from that page. What actually happen is you do not change page, jQM just load that particular "page" div using ajax and inject it to your current page.
You have two possible architecture where you put all your "pages" in a html page and navigate from there. Or you can have multiple page architecture. You can always mix this.
To physically change page, you need to add rel=external to your link.

Browser "back" issue on jQuery Mobile and ASP.net MVC

I started working with JqueryMobile a little time ago and I'm trying to adapt my website for mobile devices.
I'm using ASP.NET Mvc and the structure of my page is this:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jquerymobile")
#Scripts.Render("~/bundles/jqueryflexslider")
</head>
<body>
<div data-role="page" data-theme="a">
#RenderBody()
</div>
</body>
</html>
The thing is that inside my layout page I have a partial view with a simple jquery function that animate my menu, slideup/down on click. When I reaload the page it works fine, but when i hit the back button it simple doesn't work anymore, but if i hit refresh again voialaaa, it's works.
I read the jquery mobile documentation about "Scripts & styles in the head" and it says that
..The default behavior of the navigation system is to use that link's href to formulate an Ajax request (instead of allowing the browser's default link behavior of requesting that href with full page load). When that Ajax request goes out, the framework will receive its entire text content, but it will only inject the contents of the response's body element (or more specifically the data-role="page" element, if it's provided)
My question is how do i reload the content and get my scripts working (presuming that the problem is the reload thing) if not, someone could point me a direction or what is the best structure for this case?
I finally got it working!
My problem was that everytime I navigate from page to page, my <div id="page" data-role="page"> was duplicated. Since I got two pages on DOM and two IDS of the same menu, the click simple didn't work anymore. Once I add the data-ajax='false' on the links who were responsible for redirect me for another page, my page reloaded as usual and finally i got no more duplicated divs, IDS and everything runs flawless now.
JQuery Mobile uses AJAX navigation unless you tell it otherwise. The ASP.NET redirects have no problem to normal requests, but cause issues with AJAX. So the my answer is to turn off AJAX. For that, all you have to do is add the attribute data-ajax='false' to the tag.
In my case, an easy solution could be (as changing each Html.ActionLink/Url.Action is time consuming), adding this at the end of the _Layout.cshtml (just before closing of the 'body' tag).
$(document).on('pageinit', function() {
$('a').each(function() {
$(this).attr("data-ajax", "false");
});
});
That would be fine assuming you don't want jQuery mobile to use any Ajax with links too. I am happy to let it go ahead and use Ajax in most circumstances, so I only turn it off selectively where it can cause a problem.

How to completely disable Jquery mobile

We encounter the following problems with Jquery Mobile.
Our site is divided in a mobile and a fixed desktop site.
Both use the same database and php code. Only the templates are different.
On our mobile site we use Jquery mobile for a better user experience and that works fine. However we integrated a button "goto desktop".
This link should bring us back to our "normal" desktop site.
But there is the problem. In the desktop-site, Jquery mobile is still activated and it replaces drop down fields, input fields and make a complete mess of the desktop site.
We tried everything to disable JQM but nothing seems to work.
How we can switch from our mobile site template to the desktop site template and disable JQM completely when we are on the desktop template?
Thanks a lot for help!
There are few available solutions but only one will really do.
Working example: http://jsfiddle.net/Gajotres/NvEcW/
Few things are needed, first we need to set this:
<script>
$(document).on('mobileinit', function () {
$.mobile.ignoreContentEnabled = true;
});
</script>
it will give us an ability to programatically turn on/off content enhancement. If you already don't know this mobileinit event must be initialized before jQuery Mobile initialization but after the jQuery initialization. This must always be a part of a page.
There's one last step. When we want to move from mobile to desktop page we need to reload page and use this javascript:
$(document).on('pagebeforecreate', '#index', function(){
$(this).attr('data-enhance','false');
});
Pagebeforecreate event is important because at this point content is still not enhanced and attribute data-enhance = false will prevent any further page enhancement. If you want to turn it on again just set attribute value to true.
If you want more solutions then take a look at my other answer, search for the topic Methods of markup enhancement prevention : jQuery Mobile: Markup Enhancement of dynamically added content.

How do I stop jQuery mobile from theming an ASP.NET MVC site?

We have an MVC site that has custom formatting throughout. We are using jQuery Mobile and want to use the features in it, but it themes everything. We do not want this.
I found this SO question and I added this Javascript code in the _Layout.cshtml page:
$(function () {
$('html').find('*').attr('data-role', 'none');
});
This works for all of the elements, but sometime after the page loads jQuery inserts a <div> with the attribute data-role="page" which still causes issues.
Can I somehow disable themes altogether?
Try simple add data-ajax=false to the links/buttons who are responsible for the navigation.
Ex:
<a href="#Url.Action("Index", "MyPage")" data-ajax="false">
This will prevent jquery from use ajax for the transitions, you page will reload and the duplicated data-role=page will not be on DOM anymore.
It works for me, maybe can help you too.

Document pageinit fires more than once on iOS (jQueryMobile)

I've got a Phonegap & jQuery Mobile app that works nicely on Android and web. On iOS I am getting unexpected results, which seem to be caused by the fact that the document.pageinit event to which I bind the handler for most of the app's processes is fired twice.
No, I didn't bind it twice. No, I didn't use document.ready. Yes, I did bind it to the document, early on in the script and not inside any other function.
$(document).on('pageinit',function(event){
alert(' Pageinit on document');
//Some more code
})
The first time it fires, the splash screen is still showing. At this point, while testing on a MacBook Pro with XCode, the console is not even avaiable: the above message didn't show up in the console when I used console.log.
Second time around, the fires shortly after jQueryMobile has created the first page.
What is causing this double firing and what can I do about it?
EDIT: I noticed later on that pageinit doesn't just fire a second time, but every time I open a new data-role='page' div. See my answer below.
I appreciate Zoltans answer and it may be relevant in some cases, but that was not the cause.
$(document).on('pageinit') will fire for every page transition used in your jQuery Mobile app. This will happen both with HTML links and when using $.mobile.changePage();.
Shockingly, the docs don't mention this anywhere: they advise you to use it without mentioning that it will fire for every subsequent page.
I can't believe that they are framing this problematic example as a valid equivalent of $(document).ready().
They should be advising you to bind using .one() instead of .bind() or on() to avoid multiple code execution.
It happens because i think you use jquery and jquery mobile together.
But the solution is simple. Try
$(document:not(.processed)).addClass('processed').on('pageinit',function(event)
This should solve it
Edit body to <body data-role="page"> should solve the problem.
I was struggling with that problem too long to not share with others. And I think it is not only problem under iOS but under Android as well (it caused flickering in my case).
"pageinit" event was called twice each time a request has been made. First one was the proper one to get data for provided url, another one was called after new page was loaded into DOM (jQueryMobile page dynamically injected into document). I think there are more solutions to solve this problem, here goes mine:
$(document).ready(function(){
$(this).delegate("#page-selector", "pageinit", function(ev, data){});
// I don't know why the line has to be present, but otherwise does not work
});
And my HTML document looks like:
<html>
<head>...here goes scripts...</head>
<body>
<div id="#page-selector"> <!-- just wrapper -->
<div data-role="page">
... content...
</div>
</div>
</body>
</html>
I hope it will spare precious time for others!

Resources