Autocomplete
The AutocompleteComponent originally submitted by Nate to CakeForge. With a nice intro at
http://cakebaker.42dh.com/2006/06/06/autocompletion-the-easy-way/ The full component and some sample controller and view code is here.
http://cakebaker.42dh.com/2006/06/06/autocompletion-the-easy-way/ The full component and some sample controller and view code is here.
Controller Class:
Download code
<?php
var $components = array('Autocomplete');
var $helpers = array('Html', 'Javascript', 'Ajax');
?>
View Template:
Download code
<?php echo $ajax->autoComplete('Company/name'); ?>
-----------------------------------------------------------
Component Class:
Download code
<?php
<?php
/* SVN FILE: $Id: autocomplete.php 2932 2006-05-23 04:25:29Z nate $ */
/**
* Automagically handles requests for autocomplete fields
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.cake.libs.controller.components
* @since CakePHP v 0.10.4.1076
* @version $Revision: 2932 $
* @modifiedby $LastChangedBy: nate $
* @lastmodified $Date: 2006-05-23 00:25:29 -0400 (Tue, 23 May 2006) $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Autocomplete Handler
*
* @package cake
* @subpackage cake.cake.libs.controller.components
*
*/
class AutocompleteComponent extends Object {
var $layout = 'ajax';
var $enabled = true;
var $components = array('RequestHandler');
var $handles = array();
/**
* Startup
*
* @param object A reference to the controller
* @return null
*/
function startup(&$controller) {
if (!$this->enabled || !$this->RequestHandler->isAjax() || !$this->RequestHandler->isPost()) {
return true;
}
$data = $controller->data;
if (empty($data) || count($data) != 1) {
return false;
}
list($model) = array_keys($data);
if (!is_array($data[$model]) || count($data[$model]) != 1 || !is_object($controller->{$model})) {
return false;
}
list($field) = array_keys($data[$model]);
$conditions = array();
if (!empty($this->handles)) {
$handled = false;
$fields = array();
foreach ($this->handles as $key => $val) {
if (is_int($key)) {
$key = $val;
$val = array();
}
if ($key == $model.'.'.$field || $key == $field || $key == $model.'.*') {
$handled = true;
$conditions = $val;
break;
}
}
if (!$handled) {
return true;
}
}
$base = array($model.'.'.$field => 'LIKE %'.$data[$model][$field].'%');
if (!empty($conditions)) {
$conditions = array($base, $conditions);
} else {
$conditions = $base;
}
$results = $controller->{$model}->findAll($conditions);
if (is_array($results) && !empty($results)) {
e("<ul>\n");
foreach ($results as $rec) {
if (isset($rec[$model][$field])) {
e("\t<li>".$rec[$model][$field]."</li>\n");
}
}
e("</ul>\n");
}
exit();
}
}
?>
?>
Comments
Question
1 multiple fields
can you also tell how I can show results from two or more fields in the autocomplete box. I want to display full name which consists of first_name and last_name
Regards,
Ritesh
Comment
2 using two fields
foreach ($users as $key=>$user) {
$user[$key]['User']['fullname'] = $user[$key]['User']['first_name'] . ' ' $user[$key]['User']['last_name'];
}
either of those should work.
Comment
3 For the newbees
1. put the js files from http://script.aculo.us in your webroot/js/ folder.
2. put the following (in this order) between the head tags:
charsetTag('UTF-8'); ?> link('prototype'); ?> link('scriptaculous.js?load=effects'); ?> link('controls'); ?>
Very nice!
Question
4 multiple fields
where exactly do i have to add or replace the line in the above code if i want to have 2 or more fields -
in my (similar) case, i want to display lastname, firstname and the client's id e.g. smith, adam [007] - so to offer means to distinguish between two smith adams. -
thanx 4 your help,
tom
Question
5 Ajax not defined
Al
Comment
6 Ajax not defined
charsetTag('UTF-8'); ?> link('prototype'); ?> link('scriptaculous.js?load=effects'); ?> link('controls'); ?>just thought that my error might help another Cake novice.
Al
Comment
7 suggestion
change line 90 to.
$base = array($model.'.'.$field => 'LIKE '.$data[$model][$field].'%');
Comment
8 Help
Is this right? The code it genreates is this:
<input name="data[Article][title]" type="text" id="ArticleTitle" autocomplete="off" value="" />
<div id="ArticleTitle_autoComplete" class="auto_complete"></div>
<script type="text/javascript">new Ajax.Autocompleter('ArticleTitle', 'ArticleTitle_autoComplete', '/mech7/articles/add', {});</script>
I suppose it is because it says autocomplete=off ?
Comment
9 Possible Security Issue
CakePHP makes this especially easy, since naming standards allow users to see exactly what your data model looks like.
Is there something here to prevent it that I am not seeing?
Comment
10 How do i..
Comment
11 yes
Comment
12 It doesn t work
this.element.setAttribute is not a function
this.element.setAttribute('autocomplete','off');
controls.js (line 82)
Can someone explain me how to solve this problem ?
Comment
13 Problems with script.acoul.us and JQuery
These errors prevent autocomplete from working (as well as many other script.acoul.us functions).
I've solved this problem by just not using JQuery anymore, as sad as this is...
Bug
14 autocomplete off problem
line 450 of ajax.php had:
$htmlOptions['autocomplete'] = "off";
Which I changed to on, and it works fine now... I'm not sure this is the correct fix, but it works for me. I think this is possibly a bug?
Comment
15 I think you are misunderstanding
The autocomplete="off" attribute of the input field is actually turning off the browsers autocomplete abilities, not the websites. The reason that it is set to off is so that the browsers autocomplete doesn't interfere with the ajax autocomplete. When you say that you've fixed it by altering the framework code I believe all you've really done is turn on the browser autocomplete abilities. I've been playing around with this and find that it works great and I've checked the code and the autocomplete of the input is still set to off.
Here is the M$(yuck) explanation for reference:
http://msdn2.microsoft.com/en-us/library/ms533486(VS.85).aspx
Bug
16 I get two problems..
Source File: http://localhost/index.php/products/add/
Line: 63
<script type="text/javascript">new Ajax.Autocompleter('ProductName', 'ProductName_autoComplete', '/index.php/products/add/', {});</script>
And also nothing happens. I ahve all the helpers, components and manually link to prototype and scriptalicous in head tags.
Comment
17 Made it work
- ensure you have the javascript links in your (add them to app/webroot/default.ctp)
echo $javascript->link('prototype');- add the model's name to the $uses var in your controller (I then had to add every model that controller used, bugger)echo $javascript->link('scriptaculous');
- complete the $components and $helpers variables in the controller
- in the view, add a link such as
echo $ajax->autoComplete('Model.field');Comment
18 To get working for Cake 1.2
Line 90 should now be:
$base = array($model.'.'.$field.' LIKE ' => '%'.$data[$model][$field].'%');
Also in the view don't forget Model.field now instead of Model/field.
Question
19 Security issue still there?
As Allen and chris pointed out that there is a security issue with the component, I tried to change the Model and field via firebug to show me the user passwords. But it did not work.
Has the security issue already been bugfixed or am I doing something wrong and the component is still unsafe?
Comment
20 Dual pairs
Oh and +1 for Adriano Varoli Piazza's post - worked well :)
Comment
21 To get working for Cake 1.2 (continuation)
$results = $controller->{$model}->find('all', array('conditions' => $conditions));
Comment
22 ad
Question
23 Help -- User when selected shud get his other details in the next page automatically from the user's table
In the next page it shud display the selected empolyee and his department and salary which are present in the users table.
How do i do it..please guide me.
Comment
24 I can't get this to work.