Archive for the ‘PHP’ Category

YUI AutoComplete with CakePHP

Tuesday, July 29th, 2008

YUI Autocomplete

Usually I find the YUI components fairly easy to understand and implement. Not so with Autocomplete. After a lot of aggrivation I have it implemented. Hopefully my work here will save you the same time and hassel I experienced. The resource best resource I found was James Gardner’s YUI Autocomplete AJAX Select Dropdown with ID post.

VIEW:

link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.5.2/build/autocomplete/assets/skins/sam/autocomplete.css"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/get/get-min.js"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/connection/connection-min.js"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/animation/animation-min.js"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/json/json-min.js"
script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/autocomplete/autocomplete-min.js"
    label for="breed">Breed
        input id="breed_id" type="hidden" name="breed_id" />
        input id="breed" type="text" name="item" maxlength="50"/>
        div id="breedContainer">

    script type="text/javascript">
        var mySchema = ["ResultSet.Result","Name","ID"];
        var myDataSource = new YAHOO.widget.DS_XHR("/find_a_pet/breed", mySchema);
        myDataSource.responseType = YAHOO.widget.DS_XHR.TYPE_JSON;
        var myAutoComp = new YAHOO.widget.AutoComplete("breed", "breedContainer", myDataSource);

        // populate hidden field (id)
        function fnCallback(e, args) {
            YAHOO.util.Dom.get("breed_id").value = args[2][1];
         }
        myAutoComp.itemSelectEvent.subscribe(fnCallback);

        //myAutoComp.forceSelection = true;
        //myAutoComp.useIFrame = true;

CONTROLLER:

// directly execute... /find_a_pet/breed?query=labr
function breed() {
        $this->layout = null;

        $query = (ctype_print($_GET['query'])) ? $query = $_GET['query'] : $query = '';

        //if (!empty($query)) {
                $this->set('breed', $this->FindAPet->getBreed($query));
        //}
}

MODEL:

public function getBreed($query) {

    $sql = "SELECT id, name FROM breed WHERE name LIKE '" . Sanitize::escape($query) . "%' ORDER BY name";
    $model = $this->query($sql);

    $totalResultsReturned = $this->getAffectedRows(); // do this immediately after the query

    $sql = "SELECT COUNT(*) AS count FROM breed";
    $result = $this->query($sql);
    $totalResultsAvailable = $result[0][0]['count'];

    $json = '';

    $breed = array();
    foreach ($model as $entry) {
        $breed['Name'] = $entry['breed']['name'];
        $breed['ID'] = $entry['breed']['id'];
        $json .= json_encode($breed) . ",";
    }
    $json = substr($json, 0, strlen($json)-1);

    $json = '{"ResultSet": {"totalResultsAvailable":"' . $totalResultsAvailable . '","totalResultsReturned":' . $totalResultsReturned . ',"firstResultPosition":1,"Result": [' . $json . ']}}';

    return $json;
}

Missing data in beforeValidate()

If you are submitting a form and the data is not visible in model::beforevalidate(), then you can solve this by adding $this->Model->data = $this->data in the controller before validates(). Once you do this you can use $this->data in beforevalidate().

function admin_add() {

       if (!empty($this->data)) {

               $this->FindAPet->data = $this->data;

               if ($this->FindAPet->validates()) {
                       $this->FindAPet->save();