EllisLab text mark
Advanced Search
     
Yet Another Ajax Solution for CI
Posted: 07 April 2009 05:24 AM
Joined: 2008-11-18
15 posts

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:

http://example.com/index.php/class/function/params

AJAX call:

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

First step:
Modify the Router.php at Library

\system\libraries\Router.php
Original:

// 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:

// 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:

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

function hashChange() {
    
//Check the hash change
    
if (hash != (hash document.location.hash)) {
        
//set up the CI url.
        
var url ='<?=site_url()?>/ajax/'+hash.substr(1);
        $.
ajax({
            type
"GET",
            
urlurl,
            
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:

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:

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!