opitzconsulting / jquery-mobile-angular-adapter

jquery mobile angular adapter
MIT License
517 stars 114 forks source link

Problems with Android 2.3 and internal pages #110

Closed tbosch closed 11 years ago

tbosch commented 11 years ago

From an email of Jaume Estivill:

Hi Tobias, Sorry for the late response but I have had some crazy days at work. Today I have tried to fix the problem and report the issue as you told me, but I have found some serious issues. It is a complex thing, so let's go by parts.

First of all, the version of the adapter that I am using right now is this one, which is the one you recommend in the jsfiddle template: https://github.com/tigbro/jquery-mobile-angular-adapter/raw/master/compiled/jquery-mobile-angular-adapter-standalone-1.1.2-SNAPSHOT.js

And I try to load a very simple page (for testing purposes) that is this one:

<!DOCTYPE html> 
<html ng-app="amovens">
 <head>
  <script src="https://github.com/tigbro/jquery-mobile-angular-adapter/raw/master/compiled/jquery-mobile-angular-adapter-standalone-1.1.2-SNAPSHOT.js" type="text/javascript"></script>
   <link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />

   <script>
     var module = angular.module("amovens", []);
   </script>
 </head> 
 <body> 

   <!-- Start of first page -->
   <div data-role="page" id="foo">

     <div data-role="header">
       <h1>Foo</h1>
     </div><!-- /header -->

     <div data-role="content">  
       <p>I'm first in the source order so I'm shown as the page.</p>       
       <p>View internal page called <a href="#bar">bar</a></p>  
     </div><!-- /content -->

     <div data-role="footer">
       <h4>Page Footer</h4>
     </div><!-- /footer -->
   </div><!-- /page -->

   <!-- Start of second page -->
   <div data-role="page" id="bar">

     <div data-role="header">
       <h1>Bar</h1>
     </div><!-- /header -->

     <div data-role="content">  
       <p>I'm the second in the source order so I'm hidden when the page loads. I'm just shown if a link that references my id is beeing clicked.</p>       
       <p><a href="#foo">Back to foo</a></p>    
     </div><!-- /content -->

     <div data-role="footer">
       <h4>Page Footer</h4>
     </div><!-- /footer -->
   </div><!-- /page -->
 </body>
</html>

If you run that page with a browser using Android with version 2.3 (the most common right now due to manufacturer's limitations like Samsung, at least in Spain) and try to go to the second page, the url is converted to a strange one adding some strange characters before the id of the page you want to go and it does not work. For example, I host the page locally in amovens-server.amovens.local/en and when clicking in the BAR link in the page to go to he bar page, the final url is: amovens-server.amovens.local/en#!/en%23bar

However, that does not happen using an Android tablet running version 2.4. And if I run the same page in my Android v2.3 without adding the adapter and using plain jquerymobile and angular it works!

<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />

Using only jquery mobile or angular, the URL is not converted. So it has something to do with the angular adapter. Am I using the wrong adapter script? Do you know why it happens? For us it is critical that our webpage can be displayed using Android 2.3.

Thank you very much,

Jaume

tbosch commented 11 years ago

Well, the right version is the 1.2.0, which I released just before christmas. However, the error also exists in 1.2.0, I just checked with the Android Emulator.

Why this strange hash in the url after navigation? This is the default way of angular representing an url with $locationProvider.html5Mode(true) if the browser does not support the history api (like the browser in android 2.3). See here http://docs.angularjs.org/guide/dev_guide.services.$location for details. The only problem here is the %23 in the path. This should be a #. So the new url should be .../en#!/en#bar instead of .../en#!/en%23bar.

What the adapter further does is:

This seems to be an angular bug. Try this snippet, which only uses angular and also shows this problem:

<!DOCTYPE html>
<html ng-app="amovens">
<head>
    <base>

    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"/>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js" type="text/javascript"></script>

    <script>
        var baseTag = document.getElementsByTagName("base")[0];
        baseTag.setAttribute("href", location.href);

        var module = angular.module("amovens", []);
        module.config(['$provide', function ($provide) {
            $provide.decorator("$sniffer", ['$delegate', function ($sniffer) {
                $sniffer.history = false;
                return $sniffer;
            }]);
        }]);
        module.config(function($locationProvider) {
            $locationProvider.html5Mode(true);
            $locationProvider.hashPrefix("!");
        });
        module.controller("TestCtrl", function($scope, $location, $browser) {
            console.log($browser.baseHref());
            $scope.showAngularHash = function() {
                alert("Parsed hash by angular (should be 'someHash'): "+$location.hash());
            }
        });
    </script>
</head>
<body ng-controller="TestCtrl">

<a href="#someHash">Set someHash in location</a>
<br>
<button ng-click="showAngularHash()">Show hash read by angular</button>

</body>
</html>

First click on the Link "Set someHash in location". After this, have a look at the location in your browser. On Android 2.3, this is something like ...#!/...%23someHash, in e.g. desktop Chrome this is ...#!/...#someHash.

You can check if angular can read this url correctly by clicking on the second Button "Show hash read by angular". This should show an alert box with the hash someHash. This works in desktop Chrome, but not on Android 2.3.

Note: The following code tells angular not to use the history api even if the browser supports it. I use this to that desktop Chrome is more closely to Android 2.3.

        module.config(['$provide', function ($provide) {
            $provide.decorator("$sniffer", ['$delegate', function ($sniffer) {
                $sniffer.history = false;
                return $sniffer;
            }]);
        }]);

So, next step would be to search for a corresponding issue in the angular mailing list, or create a new one...

Tobias

tbosch commented 11 years ago

Here is a workaround for the problem (which should have no side effects on other browsers):

    module.config(['$provide', function ($provide) {
        $provide.decorator("$browser", ['$delegate', function ($browser) {
            var _url = $browser.url;
            $browser.url = function() {
                var res = _url.apply(this, arguments);
                if (arguments.length===0) {
                    res = res.replace(/%23/g,'#');
                }
                return res;
            };
            return $browser;
        }]);
    }]);

As I said, this is an angular bug. I will file an issue in angular, so this workaround is no more needed, leaving this issue open for this to be done.

Tobias

jaumeavila commented 11 years ago

It works great! Thank you very much, Tobias!

jaumeavila commented 11 years ago

I see there are still some issues. The back button now does not work. I don't know if that affects popups and dialogs...

Jaume

tbosch commented 11 years ago

Hi, just tested the back button with your example on Android 2.3 and it does work: You can get back to the previous jqm page. Could you describe the problem in more detail? Also, please create a new issue for this.

Tobias

tbosch commented 11 years ago

Closing this, see #112 for the bug discussed in the last comments.

tbosch commented 11 years ago

Reopening this, as the fix mentioned is not yet merged into the code base.

tbosch commented 11 years ago

code base updated, closing.