jump to navigation

combobox helper (Editable Selectbox) May 4, 2006

Posted by rossoft in CakePHP.
trackback

Usage:
Include the helper var $helpers=array('xxxx','combobox');

$telephones=array('959955'=>'Mark', '323223'=>'Steve');

echo $combobox->combobox('User/telephone',$telephones);

Then a combobox will be shown, if you select Mark or Steve, then in the input box the telephone value will appear. The user can select the telephone from the selectbox or enter one manually (this field is an integer)

Other example is that after selecting Mark, the value 'Mark' will be at the input field ( this field is a string )

$names=array('Mark'=>'Mark', 'Steve'=>'Steve');

echo $combobox->combobox('User/name',$names);

1. Copy this to /webroot/js/combobox/
2. Copy the helpers HeadHelper, UtilHelper from this blog to helpers/ (search the blog)
3. Copy that code to helpers/combobox.php

<?
/**
 * Combobox Helper
 * Creates an editable select tag
 * @author RosSoft
 * @version 0.1
 * @link http://www.metabuilders.com/Tools/ComboBox.aspx
 */
class ComboboxHelper extends Helper
{
    var $helpers=array('Head','Javascript','Util');

    /**
     * Creates the combobox
     * @param string $fieldName Name of the field in cake form (Model/field)
     * @param array $optionsElements Hash array with option key->value to be displayed
     * @param string $value The initial value to be shown. If null, then it will be fetched from data array
     * @param array $htmlOptions Html options to be appended to the textbox
     */    
    function combobox($fieldName,$optionElements,$value=null,$htmlOptions=null)
    {        
        $id=str_replace('/','_',$fieldName);
        
        if ($value===null)
        {
            $value=$this->Util->retrieve_value($fieldName);
            if ($value===null) $value='';
        }
        $fieldName=$this->Util->translate_fieldname($fieldName);        
        
        $htmlOptions=$this->Util->parse_attributes($htmlOptions);

        $this->Head->register_js('combobox/combobox');        
        $this->Head->register_jsblock("var ComboBoxes= new Array();");
        $this->Head->register_jsblock("ComboBoxes.push('$id');");
        $this->Head->register_jsblock("Event.observe(window, 'load', ComboBox_Init, false);");
        ob_start();
        ?>
        <span id="<?=$id?>_container">
            <input name="<?=$fieldName?>" type="text"
              id="<?=$id?>" autocomplete="off" <?=$htmlOptions?> value="<?=$value?>" />
            
            <span id="<?=$id?>_button" />
        </span>
        
        <select name="<?=$id?>_select"
        onchange="ComboBox_SimpleAttach(this, this.form['<?=$id?>']);"
        listSize="4" id="<?=$id?>_select">
        <? foreach ($optionElements as $id=>$value):?>
            <option value="<?=$id?>"><?=$value?></option>
        <? endforeach; ?>
        </select>

        <? return ob_get_clean();
        }
}
?>

Comments»

1. wluigi - June 17, 2006

any online exemple ?

2. Storage Room » Cakephp Tips - August 30, 2006

[...] combobox helper (Editable Selectbox) [...]

3. Fab Dag - January 15, 2008

where is the js file? the server is not active anymore. Thanks.

4. Fab Dag - January 22, 2008

Here is the js file by the way.

function ComboBox_InitWith(n) {
if ( typeof( window.addEventListener ) != “undefined” ) {
window.addEventListener(”load”, ComboBox_Init(n), false);
} else if ( typeof( window.attachEvent ) != “undefined” ) {
window.attachEvent(”onload”, ComboBox_Init(n));
} else {
ComboBox_Init(n)();
}
}
function ComboBox_Init(n) {
return function () {
if ( ComboBox_UplevelBrowser( n ) ) {
ComboBox_Load( n );
}
}
}
function ComboBox_UplevelBrowser( n ) {
if( typeof( document.getElementById ) == “undefined” ) return false;
var combo = document.getElementById( n + “_Container” );
if( combo == null || typeof( combo ) == “undefined” ) return false;
if( typeof( combo.style ) == “undefined” ) return false;
if( typeof( combo.innerHTML ) == “undefined” ) return false;
return true;
}
function ComboBox_Load( comboId ) {
var combo = document.getElementById( comboId + “_Container” );
var button = document.getElementById( comboId + “_Button” );
var list = document.getElementById( comboId + “_List” );
var text = document.getElementById( comboId );

combo.List = list;
combo.Button = button;
combo.Text = text;

button.Container = combo;
button.Toggle = ComboBox_ToggleList;
button.onclick = button.Toggle;
button.onmouseover = function(e) { this.Container.List.DisableBlur(e); };
button.onmouseout = function(e) { this.Container.List.EnableBlur(e); };
button.innerHTML = “\u25BC”;
button.onselectstart = function(e){ return false; };
button.style.height = ( list.offsetHeight - 4 ) + “px”;

text.Container = combo;
text.TypeDown = ComboBox_TextTypeDown;
text.KeyAccess = ComboBox_TextKeyAccess;
text.onkeyup = function(e) { this.KeyAccess(e); this.TypeDown(e); };
text.style.width = ( list.offsetWidth ) + “px”;

list.Container = combo;
list.Show = ComboBox_ShowList;
list.Hide = ComboBox_HideList;
list.EnableBlur = ComboBox_ListEnableBlur;
list.DisableBlur = ComboBox_ListDisableBlur;
list.Select = ComboBox_ListItemSelect;
list.ClearSelection = ComboBox_ListClearSelection;
list.KeyAccess = ComboBox_ListKeyAccess;
list.FireTextChange = ComboBox_ListFireTextChange;
list.onchange = null;
list.onclick = function(e){ this.Select(e); this.ClearSelection(); this.FireTextChange(); };
list.onkeyup = function(e) { this.KeyAccess(e); };
list.EnableBlur(null);
list.style.position = “absolute”;
list.size = ComboBox_GetListSize( list );
list.IsShowing = true;
list.Hide();

}
function ComboBox_InitEvent( e ) {
if( typeof( e ) == “undefined” && typeof( window.event ) != “undefined” ) e = window.event;
if( e == null ) e = new Object();
return e;
}
function ComboBox_ListClearSelection() {
if ( typeof( this.Container.Text.createTextRange ) == “undefined” ) return;
var rNew = this.Container.Text.createTextRange();
rNew.moveStart(’character’, this.Container.Text.value.length) ;
rNew.select();
}
function ComboBox_GetListSize( theList ) {
ComboBox_EnsureListSize( theList );
return theList.listSize;
}
function ComboBox_EnsureListSize( theList ) {
if ( typeof( theList.listSize ) == “undefined” ) {
if( typeof( theList.getAttribute ) != “undefined” ) {
if( theList.getAttribute( “listSize” ) != null && theList.getAttribute( “listSize” ) != “” ) {
theList.listSize = theList.getAttribute( “listSize” );
return;
}
}
if( theList.options.length > 0 ) {
theList.listSize = theList.options.length;
return;
}
theList.listSize = 4;
}
}
function ComboBox_ListKeyAccess(e) { //Make enter/space and escape do the right thing :)
e = ComboBox_InitEvent( e );
if( e.keyCode == 13 || e.keyCode == 32 ) {
this.Select();
return;
}
if( e.keyCode == 27 ) {
this.Hide();
this.Container.Text.focus();
return;
}
}
function ComboBox_TextKeyAccess(e) { //Make alt+arrow expand the list
e = ComboBox_InitEvent( e );
if( e.altKey && (e.keyCode == 38 || e.keyCode == 40) ) {
this.Container.List.Show();
}
}
function ComboBox_TextTypeDown(e) { //Make the textbox do a type-down on the list
e = ComboBox_InitEvent( e );
var items = this.Container.List.options;
if( this.value == “” ) return;
var ctrlKeys = Array( 8, 46, 37, 38, 39, 40, 33, 34, 35, 36, 45, 16, 20 );
for( var i = 0; i < ctrlKeys.length; i++ ) {
if( e.keyCode == ctrlKeys[i] ) return;
}
for( var i = 0; i 0 ) {
var text = this.Container.Text;
var oldValue = text.value;
var newValue = this.options[ this.selectedIndex ].value;
text.value = newValue;
if ( typeof( text.createTextRange ) != “undefined” ) {
if (newValue != oldValue) {
var rNew = text.createTextRange();
rNew.moveStart(’character’, oldValue.length) ;
rNew.select();
}
}
}
this.Hide();
this.Container.Text.focus();
}
function ComboBox_ToggleList(e) {
if( this.Container.List.IsShowing == true ) {
this.Container.List.Hide();
} else {
this.Container.List.Show();
}
}
function ComboBox_ShowList(e) {
if ( !this.IsShowing && !this.disabled ) {
this.style.width = ( this.Container.offsetWidth ) + “px”;
this.style.top = ( this.Container.offsetHeight + ComboBox_RecursiveOffsetTop(this.Container,true) ) + “px”;
this.style.left = ( ComboBox_RecursiveOffsetLeft(this.Container,true) + 1 ) + “px”;
ComboBox_SetVisibility(this,true);
this.focus();
this.IsShowing = true;
}
}
function ComboBox_HideList(e) {
if( this.IsShowing ) {
ComboBox_SetVisibility(this,false);
this.IsShowing = false;
}
}
function ComboBox_SetVisibility(theList,isVisible) {
var isIE = ( typeof( theList.dataSrc ) != “undefined” ); // dataSrc is an IE-only property which is unlikely to be supported elsewhere
var ua = navigator.userAgent.toLowerCase();
var isSafari = (ua.indexOf(’safari’) != - 1);
if ( isIE || isSafari) {
if ( isVisible ) {
theList.style.visibility = “visible”;
} else {
theList.style.visibility = “hidden”;
}
} else {
if ( isVisible ) {
theList.style.display = “block”;
} else {
theList.style.display = “none”;
}
}
}
function ComboBox_RecursiveOffsetTop(thisObject,isFirst) {
if(thisObject.offsetParent) {
if ( thisObject.style.position == “absolute” && !isFirst && typeof(document.designMode) != “undefined” ) {
return 0;
}
return (thisObject.offsetTop + ComboBox_RecursiveOffsetTop(thisObject.offsetParent,false));
} else {
return thisObject.offsetTop;
}
}
function ComboBox_RecursiveOffsetLeft(thisObject,isFirst) {
if(thisObject.offsetParent) {
if ( thisObject.style.position == “absolute” && !isFirst && typeof(document.designMode) != “undefined” ) {
return 0;
}
return (thisObject.offsetLeft + ComboBox_RecursiveOffsetLeft(thisObject.offsetParent,false));
} else {
return thisObject.offsetLeft;
}
}
function ComboBox_SimpleAttach(selectElement,textElement) {
textElement.value = selectElement.options[ selectElement.options.selectedIndex ].value;
var textOnChange = textElement.onchange;
if ( textOnChange != null && typeof( textOnChange ) == “function” ) {
textOnChange();
}
}