I am using the autocomplete feature of jQuery UI to create a passive database of associative values. I have three inputs: Lens Type, Lens Design and Lens Material.
All three values are autocomplete, and upon form submit if there are values unique to those inputs they are stored in the database.
What I want to do is return autocomplete values for each input based upon the known input of the previous input. So for example Lens Type a only has Lens Design input's: c,d,g. Where as if Lens type is set to b then autocomplete would return a,b,e,f.
How would I do this with jQuery UI autocomplete? I already know how to write the database and server side logic but the autocomplete frontend has be stumped.
Edit: I have worked out a hardcoded method of doing this by the using following java-script:
$('input.autocompleteme').each( function() {
var $input = $(this);
$input.autocomplete({
source: function( request, response ) {
var fieldName = $input.attr('id');
if ( fieldName.indexOf( "Right" ) !== -1 ) {
var lensSide = "Right";
}else{
var lensSide = "Left";
}
var LensType = $("#" + "Patient" + lensSide + "EyeLensType").attr("value");
var LensDesign = $("#" + "Patient" + lensSide + "EyeLensDesign").attr("value");
var LensMaterial = $("#" + "Patient" + lensSide + "EyeLensMaterial").attr("value");
var LensCoating = $("#" + "Patient" + lensSide + "EyeLensCoating").attr("value");
var LensTints = $("#" + "Patient" + lensSide + "EyeLensTints").attr("value");
var serverUrl = "/autocomplete.json?field=" + fieldName + "&LensType=" + LensType + "&LensDesign=" + LensDesign + "&LensMaterial=" + LensMaterial + "&LensCoating=" + LensCoating + "&LensTints=" + LensTints;
var term = request.term;
lastXhr = $.getJSON( serverUrl, request, function( data, status, xhr ) {
response( data );
});
},
minLength: 2,
});
});
This submits a url to a cakephp function that looks similar to:
function admin_autocomplete(){
Controller::loadModel('AutoField');
$param = $this->params["url"]["term"];
$fieldName = $this->params["url"]["field"];
$hasParent = false;
$output = array();
if ($param == ''){
$this->set("output", NULL);
return;
}
switch ($fieldName){
case "PatientRightEyeLensType":
case "PatientLeftEyeLensType":
$fieldName = "LensType";
break;
case "PatientRightEyeLensDesign":
case "PatientLeftEyeLensDesign":
$fieldName = "LensDesign";
$hasParent = "LensType";
break;
case "PatientRightEyeLensMaterial":
case "PatientleftEyeLensMaterial":
$fieldName = "LensMaterial";
$hasParent = "LensDesign";
break;
case "PatientRightEyeLensCoating":
case "PatientLeftEyeLensCoating":
$fieldName = "LensCoating";
$hasParent = "LensMaterial";
break;
case "PatientRightEyeLensTints":
case "PatientLeftEyeLensTints":
$fieldName = "LensTints";
$hasParent = "LensCoating";
break;
default:
die("Field Name is not known");
break;
}
if ($hasParent === false){ // This is the root of the tree.
$query = array(
"conditions" => array(
"type" => $fieldName,
"parent_id" => NULL,
"value REGEXP '^$param'"
),
"fields" => array(
"value"
),
);
$results = $this->AutoField->find("all", $query);
}else{
$parentValue = $this->params["url"][$hasParent];
$query = array(
"conditions" => array(
"type" => $hasParent,
"value" => $parentValue,
),
"fields" => array(
"id",
)
);
$results = $this->AutoField->find("all", $query);
$parentIds = "";
foreach ($results as $parentId){
$parentIds .= $parentId["AutoField"]["id"] . ",";
}
$parentIds = substr_replace($parentIds ,"",-1);
$query = array(
"conditions" => array(
"type" => $fieldName,
"parent_id IN ($parentIds)",
"value REGEXP '^$param'"
),
"fields" => array(
"value"
),
);
$results = $this->AutoField->find("all", $query);
}
foreach ($results as $result){
$output[] = $result["AutoField"]["value"];
}
$this->set("output", $output);
}
My Mysql database looks like the following:
--
-- Table structure for table `auto_fields`
--
CREATE TABLE IF NOT EXISTS `auto_fields` (
`id` int(11) unsigned NOT NULL auto_increment,
`created` datetime default NULL,
`modified` datetime default NULL,
`parent_id` int(11) default NULL,
`type` varchar(100) default NULL,
`value` varchar(150) default NULL,
`count` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Dumping data for table `auto_fields`
--
INSERT INTO `auto_fields` (`id`, `created`, `modified`, `parent_id`, `type`, `value`, `count`) VALUES
(1, '2012-04-12 10:51:00', '2012-04-12 10:51:02', NULL, 'LensType', 'Progressive', 0),
(2, '2012-04-12 10:51:00', '2012-04-12 10:51:00', NULL, 'LensType', 'Bifocal', 0),
(3, '2012-04-12 11:55:46', '2012-04-12 11:55:46', 1, 'LensDesign', 'AAA', 0),
(4, '2012-04-12 11:55:46', '2012-04-12 11:55:46', 1, 'LensDesign', 'BBB', 0);
I am sure someone with better Javascript skills than myself would be able to write that side of the UI interaction so that it doesn't require hard coding of inherited variables.
For me this works as expected with the inheritance being mapped by the switch in the php function. If I can figure out the javascript front end I may write this into a cakephp helper and component.