2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
 
   5  * HTML class for an autocomplete element
 
   9  * LICENSE: This source file is subject to version 3.01 of the PHP license
 
  10  * that is available through the world-wide-web at the following URI:
 
  11  * http://www.php.net/license/3_01.txt If you did not receive a copy of
 
  12  * the PHP License and are unable to obtain it through the web, please
 
  13  * send a note to license@php.net so we can mail you a copy immediately.
 
  16  * @package     HTML_QuickForm
 
  17  * @author      Matteo Di Giovinazzo <matteodg@infinito.it>
 
  18  * @copyright   2001-2011 The PHP Group
 
  19  * @license     http://www.php.net/license/3_01.txt PHP License 3.01
 
  21  * @link        http://pear.php.net/package/HTML_QuickForm
 
  25  * HTML class for a text field
 
  27 require_once 'HTML/QuickForm/text.php';
 
  30  * HTML class for an autocomplete element
 
  32  * Creates an HTML input text element that
 
  33  * at every keypressed javascript event checks in an array of options
 
  34  * if there's a match and autocompletes the text in case of match.
 
  36  * For the JavaScript code thanks to Martin Honnen and Nicholas C. Zakas
 
  37  * See {@link http://www.faqts.com/knowledge_base/view.phtml/aid/13562} and
 
  38  * {@link http://www.sitepoint.com/article/1220}
 
  42  * $autocomplete =& $form->addElement('autocomplete', 'fruit', 'Favourite fruit:');
 
  43  * $options = array("Apple", "Orange", "Pear", "Strawberry");
 
  44  * $autocomplete->setOptions($options);
 
  48  * @package     HTML_QuickForm
 
  49  * @author      Matteo Di Giovinazzo <matteodg@infinito.it>
 
  50  * @version     Release: 3.2.16
 
  53 class HTML_QuickForm_autocomplete extends HTML_QuickForm_text
 
  58      * Options for the autocomplete input text element
 
  63     var $_options = array();
 
  66      * "One-time" javascript (containing functions), see bug #4611
 
  79      * @param     string    $elementName    (optional)Input field name attribute
 
  80      * @param     string    $elementLabel   (optional)Input field label in form
 
  81      * @param     array     $options        (optional)Autocomplete options
 
  82      * @param     mixed     $attributes     (optional)Either a typical HTML attribute string
 
  83      *                                      or an associative array. Date format is passed along the attributes.
 
  87     function HTML_QuickForm_autocomplete($elementName = null, $elementLabel = null, $options = null, $attributes = null)
 
  89         $this->HTML_QuickForm_text($elementName, $elementLabel, $attributes);
 
  90         $this->_persistantFreeze = true;
 
  91         $this->_type = 'autocomplete';
 
  92         if (isset($options)) {
 
  93             $this->setOptions($options);
 
 101      * Sets the options for the autocomplete input text element
 
 103      * @param     array    $options    Array of options for the autocomplete input text element
 
 107     function setOptions($options)
 
 109         $this->_options = array_values($options);
 
 110     } // end func setOptions
 
 116      * Returns Html for the autocomplete input text element
 
 123         // prevent problems with grouped elements
 
 124         $arrayName = str_replace(array('[', ']'), array('__', ''), $this->getName()) . '_values';
 
 126         $this->updateAttributes(array(
 
 127             'onkeypress' => 'return window.autocomplete(this, event, ' . $arrayName . ');'
 
 129         if ($this->_flagFrozen) {
 
 132             $js = "<script type=\"text/javascript\">\n//<![CDATA[\n";
 
 133             if (!defined('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS')) {
 
 136 /* begin javascript for autocomplete */
 
 137 function setSelectionRange(input, selectionStart, selectionEnd) {
 
 138     if (input.setSelectionRange) {
 
 139         input.setSelectionRange(selectionStart, selectionEnd);
 
 141     else if (input.createTextRange) {
 
 142         var range = input.createTextRange();
 
 143         range.collapse(true);
 
 144         range.moveEnd("character", selectionEnd);
 
 145         range.moveStart("character", selectionStart);
 
 151 function setCaretToPosition(input, position) {
 
 152     setSelectionRange(input, position, position);
 
 155 function replaceSelection (input, replaceString) {
 
 156         var len = replaceString.length;
 
 157     if (input.setSelectionRange) {
 
 158         var selectionStart = input.selectionStart;
 
 159         var selectionEnd = input.selectionEnd;
 
 161         input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);
 
 162                 input.selectionStart  = selectionStart + len;
 
 163                 input.selectionEnd  = selectionStart + len;
 
 165     else if (document.selection) {
 
 166         var range = document.selection.createRange();
 
 167                 var saved_range = range.duplicate();
 
 169         if (range.parentElement() == input) {
 
 170             range.text = replaceString;
 
 171                         range.moveEnd("character", saved_range.selectionStart + len);
 
 172                         range.moveStart("character", saved_range.selectionStart + len);
 
 180 function autocompleteMatch (text, values) {
 
 181     for (var i = 0; i < values.length; i++) {
 
 182         if (values[i].toUpperCase().indexOf(text.toUpperCase()) == 0) {
 
 190 function autocomplete(textbox, event, values) {
 
 191     if (textbox.setSelectionRange || textbox.createTextRange) {
 
 192         switch (event.keyCode) {
 
 194             case 40:    // down arrow
 
 195             case 37:    // left arrow
 
 196             case 39:    // right arrow
 
 198             case 34:    // page down
 
 207             case 20:    // caps lock
 
 214                 var c = String.fromCharCode(
 
 215                     (event.charCode == undefined) ? event.keyCode : event.charCode
 
 217                 replaceSelection(textbox, c);
 
 218                 sMatch = autocompleteMatch(textbox.value, values);
 
 219                 var len = textbox.value.length;
 
 221                 if (sMatch != null) {
 
 222                     textbox.value = sMatch;
 
 223                     setSelectionRange(textbox, len, textbox.value.length);
 
 232 /* end javascript for autocomplete */
 
 235                 define('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS', true);
 
 247             $js .= 'var ' . $arrayName . " = new Array();\n";
 
 248             for ($i = 0; $i < count($this->_options); $i++) {
 
 249                 $js .= $arrayName . '[' . $i . "] = '" . strtr($this->_options[$i], $jsEscape) . "';\n";
 
 251             $js .= "//]]>\n</script>";
 
 253         return $js . parent::toHtml();
 
 257 } // end class HTML_QuickForm_autocomplete