jquery-archive / jquery-mobile

jQuery Mobile Framework
https://jquerymobile.com
Other
9.69k stars 2.41k forks source link

Redirecting on first load, using changePage, does not work in WebKit browsers #3190

Closed chris-steele closed 11 years ago

chris-steele commented 12 years ago

I've tested this on the following:

Safari 5.0.2 on iOS 4.2.1 (iPhone 3G), Safari 5.0.2 on iOS 4.3 (iPhone 4) Safari 5.0.2 on iOS 4.3.5 (iPad 2) Safari 5.1.1 on Windows XP 32-bit (desktop)

It does work in Firefox (tested Firefox 8.0 on Windows XP 32-bit desktop) and IE (tested IE 8.0 on Windows XP 32-bit desktop).

See http://jsbin.com/ukewu3/184 for a simple example.

Safari is not maxing-out the CPU but it is busy with something - something that doesn't seem to end!

Thanks

chris-steele commented 12 years ago

Just discovered there is a workaround, by using setTimeout, but would be good to get to the bottom of the issue!

See http://jsbin.com/ukewu3/186 for the workaround.

kangaroo5383 commented 12 years ago

Isn't settimeout generally a bad idea as it may just be covering up a race condition?

chris-steele commented 12 years ago

Oh I certainly agree - I'm just posting the workaround in case anyone is facing a deadline like me and needs a quick fix. Maybe knowing how to work around the issue will help the JQM developers fix it properly.

bdoms commented 12 years ago

I also just noticed this and it appears to affect all WebKit based browsers, as it was happening for me in Chrome (on a Mac) as well.

As an alternative to setTimeout, I found that calling the page change from within a $(window).load() also worked for me. From what I could tell, the root cause of this bug is that the first "page" is not properly inserted into the browser's history before the page change is called.

So my overall theory is that non-WebKit browsers insert the page immediately, but WebKit browsers wait until all of the page's resources are loaded before adding it, so that changing the page immediately on an event like pageinit causes unexpected behavior.

MauriceG commented 12 years ago

@chris-steele What's happen, if you change e.preventDefault(); to if ( !$.browser.webkit ) { e.preventDefault(); } at your example?

eddiemonge commented 12 years ago

Forgive me for asking, but why would you want to do this?

jakeboone02 commented 12 years ago

@eddiemonge We have a situation where the user starts on page A, chooses a value from a dropdown and submits the form to page B. Page B can redirect to C1, C2, or C3 depending on a value derived from the choice made on page A.

(At the time A loads, we don't know which choices will lead to C1 vs C2 vs C3, so we have to hit B to decide at the moment the user submits the form.)

Since there is no reason to show B to the user, we want to redirect as quick as possible. It's weird, I know.

On Webkit browsers, if a user got to C1 and clicked a link to C1a, then clicked Back, the user would be taken to page B instead of C1 because the history stack was missing a page. We used the setTimeout workaround.

Short version: Start at A submit form to B redirect to C1 click link to C1a... Back button goes to B.

As far as I can tell this has nothing to do with jQM.

eddiemonge commented 12 years ago

Submit the form using ajax and then call pagechange to go to Cx depending on the response. No redirects needed.

chris-steele commented 12 years ago

@bdoms Thanks I will try this out :)

@MauriceG Thanks for the suggestion, but this gives the same result; i.e. WebKit browsers fall into what appears to be an infinite loop and nothing is rendered. This said, and to be fair to Safari, I have updated the issue description.

@eddiemonge, @jakeboone02 My situation is that I have a single HTML file with multiple page templates inside. When I open this file code decides which template is to be used. This template is then copied in the DOM, enhanced and manipulated and we then use changePage to navigate to the copy. A clean-up routine removes the copy once we navigate to a new page.

chris-steele commented 12 years ago

FYI doing a redirect on the pagechange event works fine in WebKit browsers. See http://jsbin.com/ukewu3/187. So, there is a little redundancy going on here, but it's a better solution than using setTimeout.

itechnology commented 12 years ago

Just ran into a similar issue.

We want to display a dialog on entering a page, so the logical solution was to create a page containing one data-role=dialog, and one data-role=page, and on jquery(document).ready() (since jqm version of ready() isn't available yet) make a call to changepage to call the dialog.

This however will only work by inserting an additional setTimeout before calling the dialog.

Suppose we will have to wait for $.mobile.ready() ..or maybe i should be using "pageinit" (..will have to look at this)

MauriceG commented 12 years ago

@itechnology I can't see this issue. When using pageinit, it works on Safari 5.0.5. On first page: http://jsfiddle.net/MauriceG/sEcyg/show/ on a page, shown by a click: http://jsfiddle.net/MauriceG/sEcyg/8/show/ (http://jsfiddle.net/MauriceG/sEcyg/8 for source)

agcolom commented 12 years ago

Hi Maurice :-)

When I try your fiddle, on FF I get the dialog, and if I close the dialog, I get the first page (page One with the Open Dialog button). However, if I try with Safari Version 5.1.1 (6534.51.22) on Mac OS, I get the dialog, and if I close the dialog, I get nothing, as if the history hadn't registered the first page.

MauriceG commented 12 years ago

Hi Anne .net :-) Yes, you're right! With Safari 5.1.1 at OS X the dialog-close-button don't work as expected. I've tried some other browsers: Safari 5.0.5 ok, FF 8.0 ok, Chrome 15.0 ok, Chome latest (15.0.874.121m) not ok, Opera 11.02 ok, iPhone 4S and iPad 2 iOS 5.0.1 not ok Safari 5.1.2 on Windows not ok

johnbender commented 12 years ago

@chris-steele

It appears, at least on first inspection that calling changePage inside of an early binding fired by changePage is probably the root of the issue. The setTimeout workaround seems to support this. I'm not entirely clear what it is that's causing the consistent difference between handling by the js engines + webkit (your sample works in my chrome). You'll note that the $.mobile.activePage does reference the correct div (page2), which seems to suggest that the issue has to do with the application of transitions (which we do a bit of simple locking on).

In any case if you bind to pagechange, which in this case is semantically equivalent to "wait until the first page loads and then redirect", my testing on Safari shows you won't run into these issues because it's triggered at the tail end of the previous changepage call and the transitions have completed.

johnbender commented 12 years ago

@chris-steele

I neglected to mention both the jsbin with my modification and that the transition should be disabled explicitly in the call to changePage.

itechnology commented 12 years ago

No more setTimeout, the following seems to work fine here

    jQuery("#home-index").live("pageinit", function(event) {
      jQuery.mobile.changePage("#home-disclaimer");
    });   
arschmitz commented 11 years ago

@toddparker @ uGoMobi This looks like it is fixed webkit browsers i test all seem to work with @johnbenders jsbin updated to latest http://jsbin.com/ukewu3/272/edit @itechnology also seems to indicate its fixed

toddparker commented 11 years ago

I'm going to close this as resolved, but can re-open if anyone can chime in with a test page showing there is still an issue. Thanks all!

thenewmr commented 11 years ago

I'm having this problem currently but, strangely, only when running inside a PhoneGap app. It runs fine when running in Safari on the same iPad.

See this question on stackoverflow.

http://stackoverflow.com/questions/16647188/jquery-mobile-mobile-changepage-not-working-properly-on-iphone-in-phonegap/16647212#16647212

kripper commented 10 years ago

Ok, let's start reviewing how it is supposed to work:

BUG 1:

BUG 2:

jaspermdegroot commented 10 years ago

Re: BUG 1. '''fromPage && fromPage[0] === toPage[0] && !settings.allowSamePageTransition''' means you navigate to same page ('''fromPage[0] === toPage[0]''') but haven't set '''allowSamePageTransition''' to '''true''' so to me it makes sense '''releasePageTransitionLock()''' isn't executed.

Re: BUG 2. We really need to see a test page to get an idea of what those circumstances are and if it's bug.

AndrewRayCode commented 10 years ago

I am experiencing a bug where I execute $.mobile.changePage inside of a $(document).one('change' handler, and the page sometimes does not change. I cannot make a fiddle for this because I do not have an isolated example that is reproducible in a browser.

In this case the page lives at /url, and the page change brings you to /url#page1. If I go directly to #page1 in my browser I do not see the issue occur, but if I go to /url it will occasionally not ever go to page1, even though the hash will change.

arschmitz commented 10 years ago

@DelvarWorld im sorry with out a test page reproducing this issue we cannot look into this

harshadmadaye commented 4 years ago

most simple solution is allowing arbitrary load to all domains.