• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
jQuery UI Autocomplete with CI ??

#11
[eluser]pickupman[/eluser]
Since jQuery UI sends the search term as a get parameter you will either enable query strings, or use a js callback function.
Code:
//Javascript
$(".productpicker").autocomplete({
            minLength: 1,
            source: function(req, add){
                $.ajax({
                    url: '<?php echo site_url('search');?>',
                    dataType: 'json',
                    type: 'POST',
                    data: req,
                    success: function(data){
                        if(data.response =='true'){
                           add(data.message);
                        }
                    }
                });
            },
            select: function(event, ui){}
              log(ui.item ? ("Selected: " + ui.item.value + " aka " + ui.item.id) : "Nothing selected, input was " + this.value);
        });

//In controller
$keyword = $this->input->post('term');

$data['response'] = 'false'; //Set default response

$query = $this->your_model->search($keyword); //Search DB

if($query->num_rows() > 0){
   $data['response'] = 'true'; //Set response
   $data['message'] = array(); //Create array
   foreach($query->$result as $row){
      $data['message'][] = array('label'=> $row->name, 'value'=> $row->name); //Add a row to array
   }
}
echo json_encode($data);

#12
[eluser]seanloving[/eluser]
[quote author="pickupman" date="1272786369"]Since jQuery UI sends the search term as a get parameter you will either enable query strings, or use a js callback function.
[/quote]

@pickupman- this moves me in the right direction, thank you very much.

What is a good method for debugging in this situation? Basically, I don't know if search.php is being called by jQuery or not. How can I tell?

Can I echo data to the display from search.php?. Something tells me no - that this call from jQuery to /search.php is not in the flow of normal data.

Is it correct that search.php does not have any classes or functions? search.php seems to operate like a CI view, except in this case echo sends data to the jQuery request, not to the screen. (correct me if I'm wrong)

Here is my search.php file
Code:
<?php
    $keyword = $this->input->post('term');
    $data['response'] = 'false'; //Set default response
    $this->load->model('inventory/products_model');
    $query = $this->products_model->lookup($keyword); //Search DB
    if($query->num_rows() > 0)
    {
        $data['response'] = 'true'; //Set response
        $data['message'] = array(); //Create array
        foreach($query->$result as $row)
        {
            $data['message'][] = array('label'=> $row->description, 'value'=> $row->product); //Add a row to array
        }
    }
    echo json_encode($data);
?>

#13
[eluser]pickupman[/eluser]
The server knows when a request is sent via ajax/jQuery. Put this in your config file
Code:
//Global define for AJAX Requests
define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');

In the spirit of what jQuery is, you will want things to work properly with(out) javascript. This doesn't quite apply for the autocomplete functionality, but perhaps in other ajax stuff you might do. You create a search controller just like any other situation, but use the IS_AJAX tag to determine how you output your data.

Code:
class Search extends Controller{
  
  function Search(){
    parent:Controller();
  }

  function index(){
     $keyword = $this->input->post('term');
     $data['response'] = 'false'; //Set default response
     $this->load->model('inventory/products_model');
     $query = $this->products_model->lookup($keyword); //Search DB
     if($query->num_rows() > 0)
     {
        $data['response'] = 'true'; //Set response
        $data['message'] = array(); //Create array
        foreach($query->result() as $row)
        {
            $data['message'][] = array('label'=> $row->description, 'value'=> $row->product); //Add a row to array
        }
     }
     if(IS_AJAX){
       echo json_encode($data); //echo json string if ajax request
     }else{
       $this->load->view('search/index',$data); //Load html view of search results
     }
     echo json_encode($data);
  }

}

Now you have coded the functionality to handle both ajax searches and load a page if someone has js disabled. Since you have done this in a controller, you have access to all the other features as well. (ie pagination for html view)

#14
[eluser]seanloving[/eluser]
Wow, I didn't think it was going to be this hard... but I got it working.

@pickupman- Thanks a whole bunch! With your help I was able to to use firebug console to see the output of my search function (database query results). That made things a lot easier after I could see what was going on. Thanks also for the tip on how to handle javascript disabled

Sincerely,
Sean Loving

#15
[eluser]pickupman[/eluser]
Glad you got it figured out. I know there were a couple tickets for POST support for ui autocomplete, but since ui provides the option to use a callback it works in a round about way.

#16
[eluser]goldorak[/eluser]
[quote author="seanloving" date="1272753370"]

Not sure if I need the jQuery AJAX helper and hook for CI in order to make this work with "remote data".

My ultimate goal is to autocomplete from MySQL database.[/quote]

Hi. Did you finally use the helper and hook?

I'm into a project which seems like yours since the datasource is a Mysql Database and the use of the new ui autocomplete would be great. seanloving, Would you share the complete code modified to your needs, please?

I am looking for a Google kind of behaviour too, so when the result is clicked or we select it and press enter, the resulting page is shown.

#17
[eluser]pickupman[/eluser]
I've already [url="http://ellislab.com/forums/viewreply/745033/"]posted[/url] the complete jquery.autocomplete part above, and the only thing you need to supply is a json response with label, item, & value for each row in DB from your controller.

Here's an example I am using
Code:
//In Location.php controller
public function json_zip(){
        
        $search = $this->input->post('term');
        
        if(!IS_AJAX || empty($search))
            redirect('location');
        
        $data['response'] = 'false';
        
        $locations = $this->location_m->get_city_zip_search( $search );
        
        if(count($locations) > 0){
            $data['message'] = array();
            
            foreach($locations as $location){
               $data['message'][] = array(  'label' => $location->city . ', ' . $location->state . ' ' . $location->zip,
                                            'item'  => $location->zip,
                                            'value' => $location->zip );
            }
            
            $data['response'] = 'true';
        }
        echo json_encode($data);      
     }

//jQuery in head tag of view
$("input[name='zip']").autocomplete({
        source: function(req, add){
                $.ajax({
                    url: '<?php echo site_url('location/json_zip');?>',
                    dataType: 'json',
                    type: 'POST',
                    data: req,
                    success: function(data){
                        if(data.response =='true'){
                           add(data.message);
                        }
                    }
                });
        },
        minLength: 3,
        select: function(event, ui){
            $(this).end().val(ui.item.value);
        }
     });

#18
[eluser]seanloving[/eluser]
[quote author="goldorak" date="1276040359"]

Hi. Did you finally use the helper and hook?

I'm into a project which seems like yours since the datasource is a Mysql Database and the use of the new ui autocomplete would be great. seanloving, Would you share the complete code modified to your needs, please?

I am looking for a Google kind of behaviour too, so when the result is clicked or we select it and press enter, the resulting page is shown.[/quote]

@goldorak-

I did not use the helper and the hook from the wiki. Instead, here is what I came up with, based on the help I got from @pickupman.

First you have to generate a form in which one of the elements is a text input field with class="productpicker".

I am using the Form Generation Library by @macigniter like this:
Code:
$this->form
          ->text('qty'.$item.'|qtyID', '', 'trim|numeric|max_length[2]', $this->input->post('qty'.$item), array('onkeyup'=>'amount(this.name.substr(3,2));shipping()','style'=>'width:20px;margin:0;border:0;background:none;',$this->input->post('readonly')=>'readonly','element_suffix' => '') )
          ->text('item'.$item.'|itemID', '', 'trim|max_length[12]', $this->input->post('item'.$item), array('style'=>'width:70px;margin:0;border:0;background:none;',$this->input->post('readonly')=>'readonly','class'=>'productpicker','element_suffix' => '') )
          ->text('desc'.$item.'|descID', '', 'trim|max_length[150]', $this->input->post('desc'.$item), array('style'=>'width:230px;margin:0;border:0;background:none;','element_suffix' => '') )
          ->text('discount'.$item.'|discountID', '', 'trim|max_length[4]', $this->input->post('discount'.$item), array('onkeyup'=>'amount(this.name.substr(8,2))','style'=>'width:50px;margin:0;border:0;background:none;text-align:center;', 'element_suffix' => '') )
          ->text('unit_price'.$item.'|unit_priceID', '', 'trim|max_length[50]', $this->input->post('unit_price'.$item), array('style'=>'width:50px;margin:0;border:0;background:none;text-align:right;','element_suffix' => '') )
          ->text('amount'.$item.'|amountID', '', 'trim|max_length[50]', $this->input->post('amount'.$item), array('ondblclick'=>'amount(this.name.substr(6,2))', 'style'=>'width:60px;margin:0;border:0;background:none;text-align:right;' );

Of course, you don't have to use the FGL, but the important thing is to use class="productpicker" for the text input field for which you want to enable autocomplete.

in .js file (or in header)...
Code:
$().ready( function() {    
        
        $(".productpicker").autocomplete({
            minLength: 1,
            source:
                function(req, add)
                {
                    $.ajax({
                        url: '<?php echo site_url('inventory/products/lookup');?>',
                        dataType: 'json',
                        type: 'POST',
                        data: req,
                        success:    
                            function(data)
                            {
                                if(data.response =='true')
                                {
                                    add(data.message);
                                }
                            }
                    });
                },
            select:
                function(event, ui)
                {
                    //var lineItem = this.id;
                    var lineItem = this.id.substr(4,1);
                    $('#desc'+lineItem+'ID').val(ui.item.description);
                    $('#unit_price'+lineItem+'ID').val(ui.item.price);
                    amount( lineItem );
                    total();
                    shipping();
                }
        });    
    });

the .js function above calls the following lookup controller...
Code:
function lookup()
    {
        // process posted form data (the requested product)
        $keyword = $this->input->post('term');
        $data['response'] = 'false'; //Set default response
        $query = $this->products_model->seek_products($keyword); //Search DB
        if( ! empty($query) )
        {
            //print_r[$row];
            $data['response'] = 'true'; //Set response
            $data['message'] = array(); //Create array
            foreach( $query as $row )
            {
                $data['message'][] = array( 'label'=> $row->product,
                                            'value'=> $row->product,
                                            'description'=>$row->description,
                                            'price'=>$row->price); //Add a row to array
            }
        }
        if(IS_AJAX)
        {
            echo json_encode($data); //echo json string if ajax request
        }
        else
        {
            $this->load->view('search/index',$data); //Load html view of search results
        }
    
    } // end of lookup

the lookup() controller calls the this model...
Code:
function seek_products( $part_number )
    {
        
        $query = $this->CI->db
            ->select( " product_id,
                        product,
                        description,
                        price",
                        FALSE)
            ->from('products')
            ->group_by('product')
            ->like('product', $part_number, 'both');
            
        return $query->get()->result();
    }

I hope this helps the CI community better understand how to use jQueryUI Autocomplete

-seanloving

#19
[eluser]seanloving[/eluser]
and here is the order in which I include my js files in the page header
Code:
jquery-1.4.2.min.js
jquery.ui.core.js
jquery.ui.widget.js
//jquery.ui.position.js
jquery.ui.autocomplete.js
so.js (my js file)

#20
[eluser]packetfox[/eluser]
Hello there, i am also trying to get this to work nicely, but am failing:

Firstly here is my simple View

Code:
<s-ript type="text/javascript">

$("#companies").autocomplete({
    source: function(req, add){
        $.ajax({
            url: 'vendors/json',
            dataType: 'json',
            type: 'POST',
                data: req,
                success: function(data){
                    if(data.response =='true'){
                        add(data.message);
                    }
                }
        });
    },
    minLength: 1,
    select: function(event, ui){
        $(this).end().val(ui.item.value);
    }
});
    
</s-ript>


<div id="main-content">
    <h3>Test Stuff</h3>
    <label for='companies'>Companies</label>
    &lt;input name='companies' id='companies' type='text' value='' /&gt;
</div>

And the vendors/json controller function looks like

Code:
function json(){
        $companies = $this->M_companies->getCompanies();
        $o = array();
        foreach ($companies as $company){
            $o[] = "$company[company_name]";
        }
        echo json_encode($o);
    }

If i call the above vendors/json in my Browser, i will get

Code:
["Netgear","Cisco","Wifi Inc","Microsoft","Apple"]

When i pull up the view in the Browser and start typing, i get nothing. Any clues what i am doing wrong?

Many thanks,
D


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.