Raphael Jolivet
Raphael Jolivet

Reputation: 4040

Support for page redirection in Jquery mobile using Ajax calls

I am building a JQuery Mobile application based on a MVC framework.

My problem is that I cannot send "redirect" directives (either HTTP, Javascript, META-refresh) to the browser.

It results in the browser displaying a single line : "undefined".

Here is the code for the redirect on the server side :

<html><head>
      <script>location.href='$url'</script>
</head></html>

I know that I can fix the problem by using data-ajax=false, but i don't want that since :

Is there a way to make JQuery Mobile handle correctly one kind of redirect ? either HTTP, HTML META or Javascript ?

Upvotes: 7

Views: 2654

Answers (2)

Simon_Weaver
Simon_Weaver

Reputation: 145890

Looks like this would be a better solution - from the jQuery Mobile demos.

Basically you set a http header in your redirect and look for it on pagecontainerload. This should avoid weirdness with browser history.

Here's a a href to get to the page

<a href="redirect.php?to=redirect-target.html" 
   data-role="button" data-inline="true">Redirect</a>

In PHP you do this

<?php
// ************************************************************************
// The two-second sleep simulates network delays, hopefully causing a
// loading indicator message to appear on the client side.
// ************************************************************************
sleep(2);

$dst = ( isset( $_GET[ "to" ] )
    ? $_GET[ "to" ]
    : ( isset( $_POST[ "to" ] )
        ? $_POST[ "to" ]
        : false ) );
if ( $dst ) {
    // **********************************************************************
    // The crucial line: Issue a custom header with the location to which the
    // redirect should happen. For simplicity, we simply redirect to whatever
    // location was specified in the request's "to" parameter, but real-world
    // scripts can compute the destination based on server-side state.
    //
    // NB: This is not a HTTP redirect. As far as HTTP is concerned, this is
    // a normal request/response cycle with a status code of 200.
    // **********************************************************************
    header( "X-Redirect: " . $dst );
}
?>

Then in your javascript you do this to intercept the URL and reset it.

$( document ).bind( "pagecontainerload", function( e, triggerData ) {

        // We can use this event to recognize that this is a redirect. The event is
        // triggered when jQuery Mobile has finished loading a page and inserting
        // it into the DOM, but before it has altered the browser history. In this
        // example the server helpfully returns a custom header. However, if you
        // don't have access to the server side, you can still examine
        // triggerData.page, which contains the page that was loaded, but which
        // has not yet been displayed or even recorded in the browser history. You
        // can also examine triggerData.xhr which contains the full XMLHTTPRequest.
        // If there is a way to recognize that this is not the expected page, you
        // can discard it and issue a second load() call for the page that really
        // needs to be displayed to the user, reusing the options from the overall
        // page change process.

        var redirect = triggerData.xhr.getResponseHeader( "X-Redirect" );
        if ( redirect ) {

            // We have identified that this page is really a redirect. Thus, we load
            // the real page instead, reusing the options passed in. It is important
            // to reuse the options, because they contain the deferred governing this
            // page change process. We must also prevent the default on this event so
            // that the page change process continues with the desired page.
            $( e.target ).pagecontainer( "load", redirect, triggerData.options );
            e.preventDefault();
        }
    });

Note: at time of writing there was a broken link on the jquery demos page for this demo so I had to find it on github

https://github.com/jquery/jquery-mobile/blob/master/demos/navigation-php-redirect/index.php https://github.com/jquery/jquery-mobile/blob/master/demos/navigation-php-redirect/redirect.php

The demo for 1.3 is still working http://demos.jquerymobile.com/1.3.0/docs/examples/redirect/

Upvotes: 1

Raphael Jolivet
Raphael Jolivet

Reputation: 4040

With help from the JQuery mobile community, I have came up with an elegant solution that can handle both standard HTML redirection (data-ajax="false") and JQM page transitions.

The trick is that, when doing JQM transitions, JQM loads the result HTML with javascript; searches for a page `data-role='page' and replaces it in the DOM : It ignores the HTML header.

Hence, we have to put a standard Javascript redirection in the header, and a JQM page load in a dummy page.

Here is the code of the redirection method in my MVC template :

<html>
    <head>
        <!-- HTML reload (for data-ajax=false) -->
        <script>
            location.href='<?= $url ?>'
        </script>
    </head>
    <body>
        <!-- Change page : JQueryMobile redirect -->
        <div data-role="page" id="redirect">
            <script>
                $.mobile.changePage('<?= $url ?>');
            </script>
        </div>
    </body>
</html>

I hope this helps someone.

Upvotes: 8

Related Questions