autocomplete.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * HTML class for an autocomplete element
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * LICENSE: This source file is subject to version 3.01 of the PHP license
  9. * that is available through the world-wide-web at the following URI:
  10. * http://www.php.net/license/3_01.txt If you did not receive a copy of
  11. * the PHP License and are unable to obtain it through the web, please
  12. * send a note to license@php.net so we can mail you a copy immediately.
  13. *
  14. * @category HTML
  15. * @package HTML_QuickForm
  16. * @author Matteo Di Giovinazzo <matteodg@infinito.it>
  17. * @copyright 2001-2009 The PHP Group
  18. * @license http://www.php.net/license/3_01.txt PHP License 3.01
  19. * @version CVS: $Id: autocomplete.php,v 1.8 2009/04/04 21:34:02 avb Exp $
  20. * @link http://pear.php.net/package/HTML_QuickForm
  21. */
  22. /**
  23. * HTML class for an autocomplete element
  24. *
  25. * Creates an HTML input text element that
  26. * at every keypressed javascript event checks in an array of options
  27. * if there's a match and autocompletes the text in case of match.
  28. *
  29. * For the JavaScript code thanks to Martin Honnen and Nicholas C. Zakas
  30. * See {@link http://www.faqts.com/knowledge_base/view.phtml/aid/13562} and
  31. * {@link http://www.sitepoint.com/article/1220}
  32. *
  33. * Example:
  34. * <code>
  35. * $autocomplete =& $form->addElement('autocomplete', 'fruit', 'Favourite fruit:');
  36. * $options = array("Apple", "Orange", "Pear", "Strawberry");
  37. * $autocomplete->setOptions($options);
  38. * </code>
  39. *
  40. * @category HTML
  41. * @package HTML_QuickForm
  42. * @author Matteo Di Giovinazzo <matteodg@infinito.it>
  43. * @version Release: 3.2.11
  44. * @since 3.2
  45. */
  46. class HTML_QuickForm_autocomplete extends HTML_QuickForm_text
  47. {
  48. // {{{ properties
  49. /**
  50. * Options for the autocomplete input text element
  51. *
  52. * @var array
  53. * @access private
  54. */
  55. public $_options = array();
  56. /**
  57. * "One-time" javascript (containing functions), see bug #4611
  58. *
  59. * @var string
  60. * @access private
  61. */
  62. public $_js = '';
  63. // }}}
  64. // {{{ constructor
  65. /**
  66. * Class constructor
  67. *
  68. * @param string $elementName (optional)Input field name attribute
  69. * @param string $elementLabel (optional)Input field label in form
  70. * @param array $options (optional)Autocomplete options
  71. * @param mixed $attributes (optional)Either a typical HTML attribute string
  72. * or an associative array. Date format is passed along the attributes.
  73. * @access public
  74. * @return void
  75. */
  76. public function __construct($elementName = null, $elementLabel = null, $options = null, $attributes = null)
  77. {
  78. parent::__construct($elementName, $elementLabel, $attributes);
  79. $this->_persistantFreeze = true;
  80. $this->_type = 'autocomplete';
  81. if (isset($options)) {
  82. $this->setOptions($options);
  83. }
  84. } //end constructor
  85. // }}}
  86. // {{{ setOptions()
  87. /**
  88. * Sets the options for the autocomplete input text element
  89. *
  90. * @param array $options Array of options for the autocomplete input text element
  91. * @access public
  92. * @return void
  93. */
  94. function setOptions($options)
  95. {
  96. $this->_options = array_values($options);
  97. } // end func setOptions
  98. // }}}
  99. // {{{ toHtml()
  100. /**
  101. * Returns Html for the autocomplete input text element
  102. *
  103. * @access public
  104. * @return string
  105. */
  106. function toHtml()
  107. {
  108. // prevent problems with grouped elements
  109. $arrayName = str_replace(array('[', ']'), array('__', ''), $this->getName()) . '_values';
  110. $this->updateAttributes(array(
  111. 'onkeypress' => 'return autocomplete(this, event, ' . $arrayName . ');'
  112. ));
  113. if ($this->_flagFrozen) {
  114. $js = '';
  115. } else {
  116. $js = "<script type=\"text/javascript\">\n//<![CDATA[\n";
  117. if (!defined('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS')) {
  118. $this->_js .= <<<EOS
  119. /* begin javascript for autocomplete */
  120. function setSelectionRange(input, selectionStart, selectionEnd) {
  121. if (input.setSelectionRange) {
  122. input.setSelectionRange(selectionStart, selectionEnd);
  123. }
  124. else if (input.createTextRange) {
  125. var range = input.createTextRange();
  126. range.collapse(true);
  127. range.moveEnd("character", selectionEnd);
  128. range.moveStart("character", selectionStart);
  129. range.select();
  130. }
  131. input.focus();
  132. }
  133. function setCaretToPosition(input, position) {
  134. setSelectionRange(input, position, position);
  135. }
  136. function replaceSelection (input, replaceString) {
  137. var len = replaceString.length;
  138. if (input.setSelectionRange) {
  139. var selectionStart = input.selectionStart;
  140. var selectionEnd = input.selectionEnd;
  141. input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);
  142. input.selectionStart = selectionStart + len;
  143. input.selectionEnd = selectionStart + len;
  144. }
  145. else if (document.selection) {
  146. var range = document.selection.createRange();
  147. var saved_range = range.duplicate();
  148. if (range.parentElement() == input) {
  149. range.text = replaceString;
  150. range.moveEnd("character", saved_range.selectionStart + len);
  151. range.moveStart("character", saved_range.selectionStart + len);
  152. range.select();
  153. }
  154. }
  155. input.focus();
  156. }
  157. function autocompleteMatch (text, values) {
  158. for (var i = 0; i < values.length; i++) {
  159. if (values[i].toUpperCase().indexOf(text.toUpperCase()) == 0) {
  160. return values[i];
  161. }
  162. }
  163. return null;
  164. }
  165. function autocomplete(textbox, event, values) {
  166. if (textbox.setSelectionRange || textbox.createTextRange) {
  167. switch (event.keyCode) {
  168. case 38: // up arrow
  169. case 40: // down arrow
  170. case 37: // left arrow
  171. case 39: // right arrow
  172. case 33: // page up
  173. case 34: // page down
  174. case 36: // home
  175. case 35: // end
  176. case 13: // enter
  177. case 9: // tab
  178. case 27: // esc
  179. case 16: // shift
  180. case 17: // ctrl
  181. case 18: // alt
  182. case 20: // caps lock
  183. case 8: // backspace
  184. case 46: // delete
  185. return true;
  186. break;
  187. default:
  188. var c = String.fromCharCode(
  189. (event.charCode == undefined) ? event.keyCode : event.charCode
  190. );
  191. replaceSelection(textbox, c);
  192. sMatch = autocompleteMatch(textbox.value, values);
  193. var len = textbox.value.length;
  194. if (sMatch != null) {
  195. textbox.value = sMatch;
  196. setSelectionRange(textbox, len, textbox.value.length);
  197. }
  198. return false;
  199. }
  200. }
  201. else {
  202. return true;
  203. }
  204. }
  205. /* end javascript for autocomplete */
  206. EOS;
  207. define('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS', true);
  208. }
  209. $jsEscape = array(
  210. "\r" => '\r',
  211. "\n" => '\n',
  212. "\t" => '\t',
  213. "'" => "\\'",
  214. '"' => '\"',
  215. '\\' => '\\\\'
  216. );
  217. $js .= $this->_js;
  218. $js .= 'var ' . $arrayName . " = new Array();\n";
  219. for ($i = 0; $i < count($this->_options); $i++) {
  220. $js .= $arrayName . '[' . $i . "] = '" . strtr($this->_options[$i], $jsEscape) . "';\n";
  221. }
  222. $js .= "//]]>\n</script>";
  223. }
  224. return $js . parent::toHtml();
  225. }// end func toHtml
  226. // }}}
  227. } // end class HTML_QuickForm_autocomplete
  228. ?>