I'm binding to the jQuery Mobile pageinit event to do some additional stuff after a page has been created/enhanced and loaded into the DOM (per the docs) like so:
$('#home').live('pageinit', function()
{
...
};
But, all I'm getting is a white spinner and the page never displays on an iOS device running OS6. It works fine in the simulator. What could I be doing wrong?
There are plenty of references to pageinit not working if placed in the wrong part of the page, though generally that wouldn't cause the page to stop loading.
A script error in the event handler (the ... part) could cause the symptoms described, but would likely work the same in the simulator.
Are you sure all the files are referenced correctly? Unlike OSX, iOS is case sensitive, so a reference to jQuery.js instead of jquery.js will cause problems that you can't see anywhere else. You should be able to connect the desktop safari web inspector to the app to find any load errors.
Related
I am building a cross platform app using PhoneGap Build, version 3.3.0. The app is a news app, so requires updating of the DOM as different views are loaded. Every time this happens the old page is removed and replaced by the new view render. The app is built around backbone.js , using jQuery and Twig to render the views.
I am using the inAppBrowser to handle links to external sites, and have successfully set these up, using:
<gap:plugin name="org.apache.cordova.inappbrowser" />
in the config, and a link to
<script src="phonegap.js"></script>
in the index.html file. I am then launching the inAppBroswer using
window.open('myURL', '_blank', 'location=yes');
and this works fine the first time I use it in a session. Even if the browser is then closed and another link on the same view is selected, the browser still works.
However, in iOS 6+, if the view is then replaced by another view, then the links in the new view do not fire. The onclick event attached to the link is definitely firing (I can tell by using alerts), but the inAppBroswer does not open. However, if I exit the app and then return to it, the inAppBroswer has opened. It is as if losing the focus on the app fires off the queued event.
I have confirmed this behaviour by placing an alert in the loadstart event handler, this does not fire until exiting the app and returning to it.
I have tried keeping a persistent reference to the the inAppBrowser and destroying the instance after it has has closed. I have also tried calling the .show() method after creating the inAppBroswer instance, but none of this seems to make any difference.
Is this an issue that anyone else has come across? I could not find another question about this specific issue. This only seems to happen in iOS 6 and 7, not in Android.
Thanks
Seem to have solved it, this article looks at the same issue (in a different context):
https://issues.apache.org/jira/browse/CB-2102
One solution that came out of this was to use iframe bridge mode. Instructions are here:
https://groups.google.com/forum/#!msg/phonegap/iNl2M57xPEA/t2BW2kBXsbYJ
I got it to work, by calling the following:
var exec = cordova.require('cordova/exec');
exec.setJsToNativeBridgeMode(exec.jsToNativeModes.IFRAME_NAV);
on the deviceready event, and this now solves the problem for my app.
Hope this helps anyone with the same issue.
I have a strange problem in a web-app (using jQuery 1.10.2 and jQuery UI 1.10.3: the tabs (of the Tabs-plugin) are SOMETIMES rendered correctly and SOMETIMES not. "incorrect" means that the divs with the tab-contents are shown one below the other, no
That happens with IE7,8,10 and FF26 and on machines with rigid policies as well as those with more relaxed policy.
The browser may show a page incorrectly and then you just press F5 and the reload renders correctly.
Has anyone else had similar problems before? I have no idea how to approach this thing, yet the project-mgr wants to see something happening...
(I have validated the HTML/JS using CSE HTMLValidator and it did not report issues, also the JS console does not show any errors, but reports a few warnings (like 'Expected declaration, but found '*' for CSS-declaration like '*cursor: hand;' etc., but nothing related to the stuff I do)
How are you loading the tab content? Is it in the page when it's downloaded, or are they loaded via Ajax?
If already present in the document, you should try hiding (display: none) the content div's - that way you won't see them all if the tab initialization fails (which is likely what is happening intermittently).
This sounds like it could be a timing issue - where are the tabs initialized? Make sure you have them in the document.ready function so you are sure jQuery and jQuery UI are fully loaded first.
After a failure you could try manually initializing the tabs from the console - the result (success or failure) should give some additional insight.
Also use Firebug to examine the content divs to see if they are getting changed by the tab initialization - there should be classes added.
I'm trying all kind of things with no success.
I have a Phonegap application with JQuery mobile that I test on my Samsung android 2.3.3 device (the first generation).
I'm loading a splash screen reside in index.html while doing all kind of stuff on the background. Then I'm calling $.mobile.changePage('scenario1.html'); which reside in another file. This file has many pages.
The first page is loaded but when I call the next page it does not load.
I used $.mobile.changePage('#page2') which didn't work so I replace it with a simple <a href="#page2">Next</> which still does not work.
Please help since I'm clueless.
I'm currently debugging a webpage which is embedded in a UIWebView for display in the app.
It uses some elaborate on-load Javascript which works fine in the Android app but breaks in the iOS app.
This answer pointed me to Safari Web Inspector for UIWebView - however, since the broken Javascript is being run on page load, I can't actually attach the inspector in time to capture whatever's going wrong.
Right now I'm hacking around it by manually inserting a delay into the page, but is there a better way (one that doesn't require I make changes to the page code itself, start the app, rush to load it up in Safari, then wait a while longer for it to continue)?
Important edit: in Safari 7.0, you can reload the page by selecting the "Resources" view, and clicking the refresh arrow next to the top-level page. [It seems you can also do it in at least some versions of Safari 6 by selecting the document tab, clicking the top-level page to select it, and pressing Command+R (the same shortcut used to refresh the page in normal Safari).] Breakpoints you set will still exist if you refresh the page from the Safari Web Inspector, because doing so does not cause SWI to detach the way reloading the page from within your app or the Xcode debugger does. This means that as long as the page doesn't do a Javascript redirect or trigger side-effects in the app itself, you can step through the onload Javascript by loading the page once, setting your breakpoint there, and then reloading the page from within SWI.
Original post: The only solution I was able to find was putting in an "extra" call to shouldStartLoadWithRequest: as follows:
Add a script (not onload, synchronous) as the first element in the page head:
<script type="text/javascript">
window.location = "myapp://catchme";
</script>
Set an XCode breakpoint in shouldStartLoadWithRequest:
Edit the breakpoint to set a condition of:
(bool)[[[request URL] absoluteString] isEqualToString:#"myapp://catchme"]
(Without this condition it will stop on the initial shouldStartLoadWithRequest: call, which isn't what you want because the page won't yet be available to attach the Mobile Web Inspector to at this stage.)
Start the page load, and when it hits the (Xcode) breakpoint, switch to Safari, and launch Mobile Web Inspector with Develop > iPhone Simulator > (my page), then switch back to Xcode and resume execution within a short window before all the resource requests on the page time out.
Weinre helped me to solve this issue, since it's connected right from the start, you get full control of the page.
Why not putting a breakpoint in shouldStartLoadWithRequest and then open the inspector?
Not 100% related to the question OP asked, but I had a similar problem with an Android WebView, in a mobile app whose native code I do not control (but which has WebView debugging enabled).
document.reload() and all other similar means of reloading the page were not working for me
I was thinking to put alert() at the very top of the page, which in theory is a blocking call, but it was not working for me either.
Finally, I went with a blocking, synchronous XHR.
In order to inject an artificial delay when the page is loading, I added a fake call to an endpoint under my control that returns 200 OK after 15 seconds.
Put this at the very top of the <head>
<script>
try {
var request = new XMLHttpRequest();
request.open('GET', 'https://whatever/please-freeze', false); // false = sync XHR
request.send(null);
} catch (err){
debugger;
};
debugger;
</script>
You can for example create your own simple http server with an endpoint behaving like this, but this is a bit of an overkill.
The debugger statements didn't trigger breakpoints in Chrome for whatever reason, but the manually defined breakpoints in the dynamically loaded code (created before) worked fine.
A hack for Windows (Fiddler) users
Since I'm on Windows, I used Fiddler to create an autoresponder with latency.
I also used Fiddler to edit the HTML of the original page request, to inject the <script> mentioned earlier.
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!