autocomplete.php 8.4 KB

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