CAutoComplete.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. /**
  3. * CAutoComplete class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CAutoComplete generates an auto-complete text field.
  12. *
  13. * CAutoComplete is based on the {@link http://plugins.jquery.com/project/autocompletex jQuery Autocomplete}.
  14. *
  15. * This class is deprecated since Yii 1.1.3. Consider using CJuiAutoComplete.
  16. * There is {@link http://www.learningjquery.com/2010/06/autocomplete-migration-guide a good migration guide from the author of both JavaScript solutions}.
  17. *
  18. * @author Qiang Xue <qiang.xue@gmail.com>
  19. * @package system.web.widgets
  20. * @since 1.0
  21. * @deprecated in 1.1.3
  22. */
  23. class CAutoComplete extends CInputWidget
  24. {
  25. /**
  26. * @var boolean whether to show the autocomplete using a text area. Defaults to false,
  27. * meaning a text field is used.
  28. */
  29. public $textArea=false;
  30. /**
  31. * @var array data that would be saved as client-side data to provide candidate selections.
  32. * Each array element can be string or an associative array.
  33. * The {@link url} property will be ignored if this property is set.
  34. * @see url
  35. */
  36. public $data;
  37. /**
  38. * @var string|array the URL that can return the candidate selections.
  39. * A 'q' GET parameter will be sent with the URL which contains what the user has entered so far.
  40. * If the URL is given as an array, it is considered as a route to a controller action and will
  41. * be used to generate a URL using {@link CController::createUrl};
  42. * If the URL is an empty string, the currently requested URL is used.
  43. * This property will be ignored if {@link data} is set.
  44. * @see data
  45. */
  46. public $url='';
  47. /**
  48. * @var mixed the CSS file used for the widget. Defaults to null, meaning
  49. * using the default CSS file included together with the widget.
  50. * If false, no CSS file will be used. Otherwise, the specified CSS file
  51. * will be included when using this widget.
  52. */
  53. public $cssFile;
  54. /**
  55. * @var integer the minimum number of characters a user has to type before
  56. * the autocompleter activates. Defaults to 1.
  57. */
  58. public $minChars;
  59. /**
  60. * @var integer the delay in milliseconds the autocompleter waits after
  61. * a keystroke to activate itself. Defaults to 400.
  62. */
  63. public $delay;
  64. /**
  65. * @var integer the number of backend query results to store in cache.
  66. * If set to 1 (the current result), no caching will happen. Must be >= 1. Defaults to 10.
  67. */
  68. public $cacheLength;
  69. /**
  70. * @var boolean whether or not the autocompleter can use a cache for more
  71. * specific queries. This means that all matches of "foot" are a subset
  72. * of all matches for "foo". Usually this is true, and using this options
  73. * decreases server load and increases performance. Only useful with
  74. * cacheLength settings bigger than one, like 10. Defaults to true.
  75. */
  76. public $matchSubset;
  77. /**
  78. * @var boolean whether or not the comparison is case sensitive. Important
  79. * only if you use caching. Defaults to false.
  80. */
  81. public $matchCase;
  82. /**
  83. * @var boolean whether or not the comparison looks inside
  84. * (i.e. does "ba" match "foo bar") the search results. Important only if
  85. * you use caching. Don't mix with autofill. Defaults to false.
  86. */
  87. public $matchContains;
  88. /**
  89. * @var boolean if set to true, the autocompleter will only allow results that
  90. * are presented by the backend. Note that illegal values result in an empty
  91. * input box. Defaults to false.
  92. */
  93. public $mustMatch;
  94. /**
  95. * @var boolean if this is set to true, the first autocomplete value will
  96. * be automatically selected on tab/return, even if it has not been handpicked
  97. * by keyboard or mouse action. If there is a handpicked (highlighted) result,
  98. * that result will take precedence. Defaults to true.
  99. */
  100. public $selectFirst;
  101. /**
  102. * @var array extra parameters for the backend. If you were to specify
  103. * array('bar'=>4), the autocompleter would call the backend with a GET
  104. * parameter 'bar' 4. The param can be a function that is called to calculate
  105. * the param before each request.
  106. */
  107. public $extraParams;
  108. /**
  109. * @var string a javascript function that provides advanced markup for an item.
  110. * For each row of results, this function will be called. The returned value will
  111. * be displayed inside an LI element in the results list. Autocompleter will
  112. * provide 4 parameters: the results row, the position of the row in the list of
  113. * results (starting at 1), the number of items in the list of results and the search term.
  114. * The default behavior assumes that a single row contains a single value.
  115. */
  116. public $formatItem;
  117. /**
  118. * @var string a javascript function that can be used to limit the data that autocomplete
  119. * searches for matches. For example, there may be items you want displayed to the user,
  120. * but don't want included in the data that's searched. The function is called with the same arguments
  121. * as {@link formatItem}. Defaults to formatItem.
  122. */
  123. public $formatMatch;
  124. /**
  125. * @var string a javascript function that provides the formatting for the value to be
  126. * put into the input field. Again three arguments: Data, position (starting with one) and
  127. * total number of data. The default behavior assumes either plain data to use as result
  128. * or uses the same value as provided by formatItem.
  129. */
  130. public $formatResult;
  131. /**
  132. * @var boolean whether to allow more than one autocompleted-value to enter. Defaults to false.
  133. */
  134. public $multiple;
  135. /**
  136. * @var string seperator to put between values when using multiple option. Defaults to ", ".
  137. */
  138. public $multipleSeparator;
  139. /**
  140. * @var integer specify a custom width for the select box. Defaults to the width of the input element.
  141. */
  142. public $width;
  143. /**
  144. * @var boolean fill the textinput while still selecting a value, replacing the value
  145. * if more is typed or something else is selected. Defaults to false.
  146. */
  147. public $autoFill;
  148. /**
  149. * @var integer limit the number of items in the select box. Is also sent as
  150. * a "limit" parameter with a remote request. Defaults to 10.
  151. */
  152. public $max;
  153. /**
  154. * @var boolean|string Whether and how to highlight matches in the select box.
  155. * Set to false to disable. Set to a javascript function to customize.
  156. * The function gets the value as the first argument and the search term as the
  157. * second and must return the formatted value. Defaults to Wraps the search term in a &lt;strong&gt; element.
  158. */
  159. public $highlight;
  160. /**
  161. * @var boolean whether to scroll when more results than configured via scrollHeight are available. Defaults to true.
  162. */
  163. public $scroll;
  164. /**
  165. * @var integer height of scrolled autocomplete control in pixels. Defaults to 180.
  166. */
  167. public $scrollHeight;
  168. /**
  169. * @var string the CSS class for the input element. Defaults to "ac_input".
  170. */
  171. public $inputClass;
  172. /**
  173. * @var string the CSS class for the dropdown list. Defaults to "ac_results".
  174. */
  175. public $resultsClass;
  176. /**
  177. * @var string the CSS class used when the data is being loaded from backend. Defaults to "ac_loading".
  178. */
  179. public $loadingClass;
  180. /**
  181. * @var array additional options that can be passed to the constructor of the autocomplete js object.
  182. * This allows you to override existing functions of the autocomplete js class (e.g. the parse() function)
  183. *
  184. * If you want to provide JavaScript native code, you have to wrap the string with {@link CJavaScriptExpression} otherwise it will
  185. * be enclosed by quotes.
  186. */
  187. public $options=array();
  188. /**
  189. * @var string the chain of method calls that would be appended at the end of the autocomplete constructor.
  190. * For example, ".result(function(...){})" would cause the specified js function to execute
  191. * when the user selects an option.
  192. */
  193. public $methodChain;
  194. /**
  195. * Initializes the widget.
  196. * This method registers all needed client scripts and renders
  197. * the autocomplete input.
  198. */
  199. public function init()
  200. {
  201. list($name,$id)=$this->resolveNameID();
  202. if(isset($this->htmlOptions['id']))
  203. $id=$this->htmlOptions['id'];
  204. else
  205. $this->htmlOptions['id']=$id;
  206. if(isset($this->htmlOptions['name']))
  207. $name=$this->htmlOptions['name'];
  208. $this->registerClientScript();
  209. if($this->hasModel())
  210. {
  211. $field=$this->textArea ? 'activeTextArea' : 'activeTextField';
  212. echo CHtml::$field($this->model,$this->attribute,$this->htmlOptions);
  213. }
  214. else
  215. {
  216. $field=$this->textArea ? 'textArea' : 'textField';
  217. echo CHtml::$field($name,$this->value,$this->htmlOptions);
  218. }
  219. }
  220. /**
  221. * Registers the needed CSS and JavaScript.
  222. */
  223. public function registerClientScript()
  224. {
  225. $id=$this->htmlOptions['id'];
  226. $acOptions=$this->getClientOptions();
  227. $options=$acOptions===array()?'{}' : CJavaScript::encode($acOptions);
  228. $cs=Yii::app()->getClientScript();
  229. $cs->registerCoreScript('autocomplete');
  230. if($this->data!==null)
  231. $data=CJavaScript::encode($this->data);
  232. else
  233. {
  234. $url=CHtml::normalizeUrl($this->url);
  235. $data='"'.$url.'"';
  236. }
  237. $cs->registerScript('Yii.CAutoComplete#'.$id,"jQuery(\"#{$id}\").legacyautocomplete($data,{$options}){$this->methodChain};");
  238. if($this->cssFile!==false)
  239. self::registerCssFile($this->cssFile);
  240. }
  241. /**
  242. * Registers the needed CSS file.
  243. * @param string $url the CSS URL. If null, a default CSS URL will be used.
  244. */
  245. public static function registerCssFile($url=null)
  246. {
  247. $cs=Yii::app()->getClientScript();
  248. if($url===null)
  249. $url=$cs->getCoreScriptUrl().'/autocomplete/jquery.autocomplete.css';
  250. $cs->registerCssFile($url);
  251. }
  252. /**
  253. * @return array the javascript options
  254. */
  255. protected function getClientOptions()
  256. {
  257. static $properties=array(
  258. 'minChars', 'delay', 'cacheLength', 'matchSubset',
  259. 'matchCase', 'matchContains', 'mustMatch', 'selectFirst',
  260. 'extraParams', 'multiple', 'multipleSeparator', 'width',
  261. 'autoFill', 'max', 'scroll', 'scrollHeight', 'inputClass',
  262. 'resultsClass', 'loadingClass');
  263. static $functions=array('formatItem', 'formatMatch', 'formatResult', 'highlight');
  264. $options=$this->options;
  265. foreach($properties as $property)
  266. {
  267. if($this->$property!==null)
  268. $options[$property]=$this->$property;
  269. }
  270. foreach($functions as $func)
  271. {
  272. if($this->$func!==null)
  273. {
  274. if($this->$func instanceof CJavaScriptExpression)
  275. $options[$func]=$this->$func;
  276. else
  277. $options[$func]=new CJavaScriptExpression($this->$func);
  278. }
  279. }
  280. return $options;
  281. }
  282. }