Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :

  • I want nice Jquery mobile transitions
  • This is much faster in Ajax
  • I don't want to wonder for each link whenever the framework might send a redirect

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

like image 681
Raphael Jolivet Avatar asked Aug 02 '12 09:08

Raphael Jolivet


People also ask

How do I redirect a page in ajax?

ajax({ type: 'POST', url: 'AJAX URL', data: "YOUR DATA" // don't forget to pass your csrf_token when using post success: function(data){ $("what_ever_you_want_to_replace"). html(data. view); }, error: function(xhr, type, exception) { // if ajax fails display error alert alert("ajax error response type "+type); } });

Can we redirect using ajax?

Using $. post() to call a servlet using Ajax and then using the resulting HTML fragment to replace a div element in the user's current page. However, if the session times out, the server sends a redirect directive to send the user to the login page.

How does an ajax call work?

How AJAX Calls Work. AJAX uses both a browser built-in XMLHttpRequest object to get data from the web server and JavaScript and HTML DOM to display that content to the user. Despite the name “AJAX” these calls can also transport data as plain text or JSON instead of XML.

Which ajax property's associated JavaScript function is invoked after the page is updated?

It uses readyState property of XMLHTTPRequest; readyState is simply an integer value which describes the status of HTTP request, whenever onreadystatechange function is called when readyState property changes.


2 Answers

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.

like image 136
Raphael Jolivet Avatar answered Oct 06 '22 03:10

Raphael Jolivet


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/

like image 38
Simon_Weaver Avatar answered Oct 06 '22 03:10

Simon_Weaver