Skip to content

Another AJAX approach from CI

World Wide Web Server edited this page Jul 4, 2012 · 6 revisions

Category:Contributions - Modifications I try to explain my lame little solution to handle a complex AJAX site in CI.

[h3]Features:[/h3]

  • Use Jquery javascript framework
  • Working entire 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.

[h3]Concept:[/h3] If the page request URL contain an ‘ajax/’, the page render contain only the ajax HTML result. like: [h4]Not AJAX call:[/h4]

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

[h4]AJAX call:[/h4]

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

[h3]First step:[/h3] 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 == '' )

[/code] 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 == '' )

[/code]

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.

[h3]Second step:[/h3] 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 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 tag clicking returned false (no page load), and the browser url set. $(this).attr('onClick','location.hash="'+$(this).attr('href')+'";return false;'); }); } [/code] You’ll see, after this function call, the 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 ='<?=site_url()?>/ajax/'+hash.substr(1); $.ajax({ type: "GET", url: url, success: function(result){ //Cycling thru result DOM for (i=0;i&lt;$(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);

} [/code] Now we need to run this functions at first page load: [code] var hash=''; $(document).ready(function(){ processLinks(); hashChange(); }); [/code] 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); } [/code] 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!

[url=http://www.adminlight.com/static/files/ci_ajax.zip]Download code and sample apps[/url]

Clone this wiki locally