Welcome Guest, Not a member yet? Register   Sign In
Yet Another Ajax Solution for CI
#1

[eluser]timpisti[/eluser]
Hello.

Sorry for my poor english, now I try to explain my lame little solution to handle a complex AJAX site in CI.
Features:
+ Use Jquery javascript framework
+ Working site with/without javascript - Search bot friendly
+ Change content of multiple divs - without using specified JSON/XML data
+ Bookmarkable hashed URL-s
+ FFOX/Crome history support (IE is difficult).
+ Less work with setting the page render differences when it's AJAX call or not.

Concept:
If the page request URL contain an 'ajax/', the page render contain only the ajax HTML result.
like:
Not AJAX call:
Quote:http://example.com/index.php/class/function/params

AJAX call:
Quote:http://example.com/index.php/ajax/class/function/params

First step:
Modify the Router.php at Library

\system\libraries\Router.php
Original:
Code:
// Fetch the complete URI string
        $this->uri->_fetch_uri_string();

        // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
        if ($this->uri->uri_string == '' )
To this:
Code:
// Fetch the complete URI string
        $this->uri->_fetch_uri_string();

        /*------------------------------------------*/
        //Check if uri contain 'ajax'
        if (strstr($this->uri->uri_string,'ajax/'))
        {
            //Set the object
            $this->is_ajax = true;
            //remove from uri to proper work
            $this->uri->uri_string = str_replace('ajax/', '', $this->uri->uri_string);
        }
        /*------------------------------------------*/

        
        // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
        if ($this->uri->uri_string == '' )

Now if the URL contain the 'ajax/' part, the CI object set a param, and all the rest will work like a normal way in CI.

Second step:
Now we need to set up the javascript.
After the loading of Jquery, we need 2 functions:
First: We need to set up all the <a> href param to the AJAX call, and browser URL to handle the browser bookmarking functions:
Code:
function processLinks() {
    //All of a tag in the DOM
    $("a").each(function() {
        //set a temporary variable
        var thr = $(this).attr('href');
        //if exist    
        if (thr && thr.indexOf('index.php')!=-1) {
            //Set up the browser URL
            if (thr.substr(thr.indexOf('index.php')+10,1)!='#') $(this).attr('href', '#'+thr.substr(thr.indexOf('index.php')+10));
        }
        //After this, the <a> tag clicking returned false (no page load), and the browser url set.
        $(this).attr('onClick','location.hash="'+$(this).attr('href')+'";return false;');
    });
}

You'll see, after this function call, the <a> tag will not do any page load, only set the browser url with hash (no way to set the browser url before the hash without page loading/refresh!)

Now set up the hash handler
Code:
function hashChange() {
    //Check the hash change
    if (hash != (hash = document.location.hash)) {
        //set up the CI url.
        var url ='&lt;?=site_url()?&gt;/ajax/'+hash.substr(1);
        $.ajax({
            type: "GET",
            url: url,
            success: function(result){
                //Cycling thru result DOM
                for (i=0;i<$(result).length;i++) {
                    //Switch all the content by the container ID
                    //remove the '-' from inner-HTML
                    
                    $('#'+$(result)[i].id).html($(result)[i].inner-HTML);
                }
            //If the result contain any link, this will set it
            processLinks();
            }
        });
    }
    //checking the url hash change
    setTimeout('hashChange()',100);
}

Now we need to run this functions at first page load:
Code:
var hash='';
$(document).ready(function(){
    processLinks();
    hashChange();
});

If everything set up and works, you can distinguish the page render by URL, and you can easily bulid a page, when you need an AJAX call result or full page render.
Like this somewhere in your page render:

Code:
function Page_render(&$data)
    {
        $data['final_display']='';
        if ($this->router->is_ajax ===TRUE) {
            $data['is_ajax']='YES'; //to later use
            $data['final_display'].=$this->load->view('some_other_part_of_site_view',$data,TRUE);
        } else {
        // Full page render
            $data['is_ajax']='NO'; //to later use
            $data['final_display'].=$this->load->view('head_part_view',$data,TRUE);
            $data['final_display'].=$this->load->view('menu_part_view',$data,TRUE);
            $data['final_display'].=$this->load->view('some_other_part_of_site_view',$data,TRUE);
            $data['final_display'].=$this->load->view('foot_part_view',$data,TRUE);
        }
        $this->load->view('main_page_render_view',$data);
    }

All the rest is the same old working with CI.
This is a small procedure example, you can extend with form handling (serialize all the forms data, and send to the prepared url with jquery), or bulid IE browser navigate button support with invisible iframe method.
Take care to extend the JS, if you send a new container with the AJAX result - as you see in the downloadable sample app at the bottom.
You need change the javascript functions if you use rewrite rule to hide index.php!

Download the codes and sample app!

Good luck and programming!




Theme © iAndrew 2016 - Forum software by © MyBB