jquery-archive / jquery-mobile

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

Ajax loading does not work under Phonegap in Alpha 3 #991

Closed octatone closed 13 years ago

octatone commented 13 years ago

While working on a project using alpha 3, when trying to navigate multiple pages, the default ajax load never works under Phonegap. I always get the message "Error Loading Page" when clicking a link to another page.

By adding rel=external the content will load fine, but obviously without transitions.

jblas commented 13 years ago

@octatone

What device and OS are you using to test you Phonegap app?

Would it be possible for you to try the fix for issue 997 to see if it fixes things for you?

https://github.com/jquery/jquery-mobile/issues/issue/991

https://github.com/jquery/jquery-mobile/commit/1c9414d0306d415f953ce3695fecba186ff6178f

octatone commented 13 years ago

This is the behavior I see just from launching the iOS 4.2simulator.

But, I will try the patch when I get home this evening.

octatone commented 13 years ago

Just tested, still same behavior.

octatone commented 13 years ago

I did some more testing and the error seems to involve how the request is being handled as file://(/) vs. http://. When building outside of phonegap, the navigation works when accessed from a server with http:// based urls, but when accessed as local files with file://(/) loading fails.

Hope that helps you fix the bug!!!

octatone commented 13 years ago

Diving into .navigation.js and trying to get a feel for it, I found that path.origin is being set by path.setOrigin, but it is not actually being used anywhere in the made alpha 3. I also noticed that Chrome is failing because the origin is null - but this might be just because of how Chrome treats the file:// protocol. Under phonegap local files are treated as having the same origin, but I get the feeling alpha 3 is failing because the origin is being explicitly set somewhere as null.

jblas commented 13 years ago

@octatone

Thanks for looking into this more. I'm still trying to get phonegap set up on my system, but it involves me updating my cygwin, which is taking a long while to download.

Yeah, we need to remove the path.origin stuff. It should be a complete no-op so I'm not sure why Chrome would be failing. origin seems to be initialized to a blank string?

I'll give loading a local file:// URL a try and see if I can see what you're seeing.

Just so I know, does the document you initially load into the browser contain a base tag? If so, what does it look like?

octatone commented 13 years ago

Inspector in chrome shows the base tag is being generated and looks right base href="file://path/"

Inspector in safari shows no base tag present.

There is no base tag in the actual document, but that phonegap might write one ... not to sure about that.

jblas commented 13 years ago

@octatone

Here's something interesting I noticed. The jquery core ajax() function is returning an error whenever we try to load a file via the file:// protocol. If I roll back to jquery 1.4.4 things work fine.

I know there were some ajax changes in 1.5 I'll need to ping John R. and some folks to see if there's something new we should be doing.

octatone commented 13 years ago

Ah, under 1.4.4 things are working much better. Thanks for the update.

jblas commented 13 years ago

Looks like it was a problem in jQuery core 1.5. Here's the bug ticket:

http://bugs.jquery.com/ticket/8125

and here's the fix:

https://github.com/jquery/jquery/commit/cb85da7b62e74e7339ed652ade209aaffbd0c15b/

thiagofesta commented 13 years ago

i made a little bit different, on the jquery 1.5 full: SEARCH BY IT: // If successful, handle type chaining if ( status >= 200 && status < 300 || status === 304 ) { AND REPLACE FOR: if ( status >= 200 && status < 300 || status === 304 || status === 0 ) {

It worked for me

jblas commented 13 years ago

Just an FYI, I got word that there will be a jQuery 1.5.1 release with the fix at the end of the month.

thiagofesta commented 13 years ago

Thanks, just told that for immediately fix and work, so when it be on the Internet i'll update my jquery.

Thanks

markusweb commented 13 years ago

could someone confirm, that this fix (mentioned by thiagofesta) works. i also had to change the isExternal function and patched it, so that isExternal is false when accessing the mobile-subpages on my webserver. this works with static html and ajax call. how could i do this with json? i suffer from the crossdomain with ajax. i thought in jquery.1.5 i could set crossDomain=true but this doesn't help

markus

thiagofesta commented 13 years ago

For local html files or json files works...

if will you use crossdomain, take a look at the JSONP.

markusweb commented 13 years ago

my problem is, that i want to use the stuff in a phonegap app to load data from my server. in the xcode simulator it works, but not on my iphone. i only get the html-block back but it is not inserted into the dom of the index page. i first tried it with jqtouch. there the phonegap solution worked. with jquery mobile it is not working. both using $.ajax to load the page. does the "isExternal" handling makes the problem? when does jquery mobile decide whether to use a http call to laod a new page and when to use ajax to load html bits and inserts it into the tom?

next step would be to use jsonp to do the stuff.

markusweb commented 13 years ago

@thiagofesta: i just downloaded alpha3 again from git. put all in my local html files. opened it with firefox. main page works. when i now click on a link to load the generated html-part from my webserver i get just the plain html back. nothing is inserted into the dom of my (jquery mobile) main page.

what do i wrong? shouldn't the axaj call work? i checked jquery.1.5.js. there status will be set to 302 thus resulting in a non ok status.

thiagofesta commented 13 years ago

@markusweb: are you using $.mobile.changePage() function or just put the Test ?

Any way, it needs to work on firefox.

The status 302 is not modified, but i results the success on jQuery.

I tested on Chrome 9 and worked, sometimes the DOM is not inserted (it occurs when i access a page, click on back and access again, it shows, but using the object inspector it's not there, but on Firefox 3.6.13 worked perfect for me (i user firebug to see the dom).

Sorry, i don't know what is happening.

I hope that i told helps you.

markusweb commented 13 years ago

no, i just have plain html link: a href in li element. which then uses http://myserver/page to retrieve html. this don't work. i don't use any special function. so nothing special here

toddparker commented 13 years ago

Another issue on WebOS that might be related: http://developer.palm.com/distribution/viewtopic.php?f=11&t=10978

toddparker commented 13 years ago

There are a lot of duplicate issues related to file URLs so this I just bumped this to critical. #1002 and #746 are definitely dups of this.

jhaag75 commented 13 years ago

I believe #986 is also related to the same issue with file URLs: https://github.com/jquery/jquery-mobile/issuesearch?state=open&q=webos#issue/986

markusweb commented 13 years ago

if i use the patch in jquery1.5 and then the external http page is loaded, but jquerymobile doesn't treat is an internal/lokal file. so the content is displayed/loaded in a new page and not inserted into the dom. if i patch isExternal recognition in jquerymobile then i get the error:

to.data("page") is undefined, line 1925

toddparker commented 13 years ago

Hi all - it turns out this is a bug related to Ajax file URLs in jQuery core 1.5. A fix has been landed and will be pushed with 1.5.1 which will be pushed as a RC as early as tomorrow. Everything on the mobile end is ready to go, so we're just waiting for jQuery at this point. This will resolve all file:// related issues.

scottjehl commented 13 years ago

1.5.1 is in the jQuery Mobile repo now. Can someone do a build and test in Phonegap to see if this issue can be closed out? Thanks!

octatone commented 13 years ago

I'm confirming that jquery 1.5.1 rc does fix this issue in Phonegap. Compiled and tested.

scottjehl commented 13 years ago

Great! Thanks!

jhaag75 commented 13 years ago

I'm still having issues in Web OS. Will try a few other tests and check back in.

markusweb commented 13 years ago

doesn't work for me either. tried in firefox (win) with file://...index.html. loading content from my webserver does not work. it loads the content but this is not inserted into the DOM and is openend in a new/fresh window. will try it with phonegap. but i thought that the fix with jquery 1.5.1 should also work with file-urls in browser? do i have to add something to my a-href? at the moment i have: index.html opened via file://

then there is a

Wuppertal

Copyright © 1995–2011

jhaag75 commented 13 years ago

I have some sample code as well to show here. I'm going to try some other test cases today and most likely will try to find the contact from phonegap that created the tutorial.

BTW, What type of markup is used to show code on Github?

jblas commented 13 years ago

@jhaag75

If you want to show code, make sure you indent each line by at least 4 spaces. Github will automatically draw lines indented in that manner in a gray box.

jblas commented 13 years ago

@markusweb

If you are loading your document via file:// and then using an URL of http://www.server.com, the load would qualify as a cross-domain request, which I believe should fail in most browsers when using XHR.

Does PhoneGap have a setting that allows you to mix file and http:// domains?

jblas commented 13 years ago

@markusweb

I also meant to ask if this same markup/code you are showing worked in jQuery Mobile Alpha 2? Or if this is something new you are trying?

jhaag75 commented 13 years ago

Thanks guys for the tip. This is the same code for me as I tried packaging in phonegap with 1.5. I haven't changed anything except now using the new 1.5.1 JQuery update. Here is the same code I'm working with (using JQM alpha 3 and jquery 1.5.1 rc1):

    <!DOCTYPE html> 
    <html> 
    <head>

    <link href="css/style.css" rel="stylesheet" type="text/css" />

    <!-- JQuery Mobile -->
    <link rel="stylesheet" href="css/jquery.mobile-1.0a3.min.css" />
    <script src="javascript/jquery-1.5.1.rc1.js"></script>
    <script src="javascript/jquery.mobile-1.0a3.min.js"></script>
    <!-- JQuery Mobile -->

    <!-- PhoneGap -->
    <script src="/usr/palm/frameworks/mojo/mojo.js" x-mojo-version="1"></script>
    <script src="javascript/phonegap.js"></script>
    <!-- PhoneGap -->

    <script language="javascript" type="text/javascript" charset="utf-8"> 
    function onLoad() {
        if (window.PalmSystem) {
            window.PalmSystem.stageReady();
        }
    }
    </script>

    <title>TIP Training</title>
    </head>
    <body onload="onLoad()"> 

    <div data-role="page" data-theme="d">

    <div data-role="header" data-theme="b" data-backbtn="false" >
            <div align="center"><h3>TIP General Awareness Training</h3></div>
    </div><!-- /header -->

    <div data-role="content">   
        <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
            <li><a href="intro/index.html">Introduction</a></li>
            <li><a href="mod1/index.html">1 What is TIP?</a></li>
            <li><a href="mod2/index.html">2 Who is Involved in TIP?</a></li> 
            <li><a href="mod3/index.html">3 Why Does TIP Occur?</a></li> 
            <li><a href="mod4/index.html">4 Victims of TIP</a></li> 
            <li><a href="mod5/index.html">5 Combating TIP</a></li> 
            <li><a href="mod6/index.html">6 Legal & Policy</a></li>
        </ul>
    </div>
    <!-- /content -->
    <div data-role="footer" data-theme="b" data-position="fixed">
            <div data-role="navbar">
                <ul>
                    <li><a href="glossary.html" data-icon="info" data-iconpos="top" data-transition="slideup">Glossary</a></li>
                    <li><a href="resources.html" data-icon="star" data-iconpos="top" data-transition="slideup">Resources</a></li>
                    <li><a href="help.html" data-icon="alert" data-iconpos="top" data-inline="true" data-rel="dialog" data-transition="pop">Help</a></li>
                </ul>
            </div><!-- /navbar -->
        </div><!-- /footer -->
    </div>
    <!-- /page -->
    </body>
    </html>

When running a log, it looks as everything starts failing after trying to load mojo.js locally from the device. This is the same approach as the phonegap tutorial provides, but they only have a single html page. The same exact content (minus the mojo and phonegap inclusion) work fine in the browser on web OS.

It's like it's treating everything after the mojo.js file as if they are local files. Same scenario as reported here: http://developer.palm.com/distribution/viewtopic.php?f=11&t=10978

markusweb commented 13 years ago

@jblas: i have to admit i have never tried it with jqm alpha 2. alpha 2 was only used in safari "web"-mode, never as file:// or phonegap way. strange thing is, that this worked with jqtouch and phonegap pretty well, when i first tried to built an app with phonegap. but i want to switch to jqm ;-)

so it seems that it is somehow jqm related. how can i get over the crossdomain problem? problem is, that the ajax call itself worked, the data is loaded but jqm treats this as crossdomain and displays the result/data in a new window instead of inserting it into the dom.

jhaag75 commented 13 years ago

I haven't tried any tests with alpha 2 either. Should I? I just tried opening my index as local file:// in chrome 4.0.249.30, firefox 3.6.13, and safari webkit 5.0.3. The transitions load fine in chrome and safari, but it fails in firefox. New html pages won't load into the dom and it is stuck at the "loading" transition message.

This is the same behavior in Web OS. I will try a few test today asap using alpha2 and also with the older jquery core 1.4.4 and check back in later. Thanks.

ndarilek commented 13 years ago

Whew, glad to have found this issue. :)

Was trying to put together a simple HTML 5 mobile app, accessed from a file:// URL and calling out to an http-based web service, but kept getting 302 errors. This didn't make sense to me, as I clearly saw the requests hitting my server and in Firebug. Find my failing test case here:

http://dl.dropbox.com/u/147071/html.zip

This fails for me in a recent Minefield, but by changing from JQuery 1.5 to 1.4.4, everything works. The error callback isn't triggered at all, much less with an odd 302 status code where none should be. Note that I encountered the 302 despite a) seeing a 401 and b) changing the URL to something that didn't exist and should have returned a 404.

I tried upgrading to 1.5.1rc1, but that didn't fix the problem.

bvitale commented 13 years ago

This is still broken for me with 1.5.1 final and a3. I've attached a test case here: http://forum.jquery.com/topic/typeerror-result-of-expression-to-data-page-undefined-is-not-an-object#14737000002043205

I first saw the problem in the Android 2.2 emulator and can repro it in Firefox desktop.

jblas commented 13 years ago

@bvitale

Thanks for the sample. Does it work if you remove the ./ in front of the file name? That is if you change:

<a href="./page2.html">Link to page 2</a>

to

<a href="page2.html">Link to page 2</a>

If so, I think I know what it is.

bvitale commented 13 years ago

@jblas fails regardless.

jblas commented 13 years ago

I took a very brief look at this a few minutes ago. There seems to be something in jQuery Core that has changed between 1.4.4 and 1.5.x, such that the data being passed to our ajax success callback is no longer an HTML string. It looks like in the file:// case, we are being passed an actual DOM Document node which breaks the code inside of our callback.

jblas commented 13 years ago

Ok, it looks like we can fix this by simply passing dataType: "html" in our ajax call in jquery.mobile.navigation.js. Apparently the default "*" auto-guess feature for the ajax() method causes the ajax code to pass in the DOM Document node versus the responseText like it did in versions of jQuery prior to 1.5.

jblas commented 13 years ago

I landed the workaround in the HEAD:

https://github.com/jquery/jquery-mobile/commit/b4a822236629bc1d431ebd6da924db759c197bfd

I'll ping John R. to let him know that things still don't work as expected.

jblas commented 13 years ago

Can someone who mentioned 1.5.1 didn't work for them, pick up the fix I just checked in and verify that it does fix their problem?

I'll close the bug once I hear back from folks.

jhaag75 commented 13 years ago

I tried running the same content using JQuery 1.4.4 instead. I also tried going back to JQuery Mobile Alpha 2 and still having the same issue on Web OS using PhoneGap. This same content works fine in the browser on Web OS.

jhaag75 commented 13 years ago

@jblas is the workaround you landed above? Which file(s) are affected? Do I need to pull down the entire repo?

jblas commented 13 years ago

@jhaag75

Is it possible for you to move your mojo.js and phone gap includes above the jquery mobile include ?

I think the base tag jqm is injecting may be causing the mojo.js load to fail.

Regarding the fix I made, all you have to do is get the un-minified version of jam 1.0a3 and add that one line to the $.ajax() call in the file.

rmoriz commented 13 years ago

(disregard)

markusweb commented 13 years ago

jquery 1.5.1 works when the page was loaded from a webserver. what i want to achive is running it in phonegap. in this case, the index.html is loaded via "file://". jquery can handle this and load the content of the subpages, but jqm treats that not as an internal click but as an external. i have patched the jquery.mobile-1.0a3.js:

it starts on line 2177

    var $this = $(this),

        //get href, if defined, otherwise fall to null #
        href = $this.attr( "href" ) || "#",

        //get href, remove same-domain protocol and host
        url = path.clean( href ),

        //rel set to external
        isRelExternal = $this.is( "[rel='external']" ),

        // path Origin
        isFileOrigin = path.origin.indexOf('file:') === 0,

        //rel set to external
        isEmbeddedPage = path.isEmbeddedPage( url ),

        //check for protocol or rel and its not an embedded page
        //TODO overlap in logic from isExternal, rel=external check should be
        //     moved into more comprehensive isExternalLink
        isExternal = path.isExternal( url )   && !isFileOrigin || isRelExternal && !isEmbeddedPage,

i added a check, whether the origin page was loaded via file://. have to check, whether the other function work, but for our app this seems to do the trick i used jqm alpha 3 and jquery 1.5.1

jblas commented 13 years ago

@markusweb

So in your case the link you are clicking on is NOT relative to the document, but an absolute file:// URL? Do things work if you use relative URLs?

I'm thinking the fix should be that if we detect a protocol being used, that we first compare it against the base path before assuming it is an external link.

I'll need to talk to Scott J. to ask why it is currently assuming that all absolute URLs are external.