diff options
author | emkael <emkael@tlen.pl> | 2016-02-24 23:18:07 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2016-02-24 23:18:07 +0100 |
commit | 6f7fdef0f500cd4bb540affd3bc1482243f337c1 (patch) | |
tree | 4853eecd0769a903e6130c1896e1d070848150dd /lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php | |
parent | 61f2ea48a4e11cb5fb941b3783e19c9e9ef38a45 (diff) |
* Prado 3.3.0
Diffstat (limited to 'lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php')
-rw-r--r-- | lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php b/lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php new file mode 100644 index 0000000..be6b1b4 --- /dev/null +++ b/lib/prado/framework/Web/UI/JuiControls/TJuiAutoComplete.php @@ -0,0 +1,495 @@ +<?php +/** + * TJuiAutoComplete class file. + * + * @author Wei Zhuo <weizhuo[at]gamil[dot]com> + * @link https://github.com/pradosoft/prado + * @copyright Copyright © 2005-2015 The PRADO Group + * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT + * @package System.Web.UI.ActiveControls + */ + +/** + * Load active text box. + */ +Prado::using('System.Web.UI.ActiveControls.TActiveTextBox'); +Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter'); +Prado::using('System.Web.UI.JuiControls.TJuiControlAdapter'); +/** + * TJuiAutoComplete class. + * + * TJuiAutoComplete is a textbox that provides a list of suggestion on + * the current partial word typed in the textbox. The suggestions are + * requested using callbacks, and raises the {@link onSuggestion OnSuggestion} + * event. The events of the TActiveText (from which TJuiAutoComplete is extended from) + * and {@link onSuggestion OnSuggestion} are mutually exculsive. That is, + * if {@link onTextChange OnTextChange} and/or {@link onCallback OnCallback} + * events are raise, then {@link onSuggestion OnSuggestion} will not be raise, and + * vice versa. + * + * The list of suggestions should be set in the {@link onSuggestion OnSuggestion} + * event handler. The partial word to match the suggestion is in the + * {@link TCallbackEventParameter::getCallbackParameter TCallbackEventParameter::CallbackParameter} + * property. The datasource of the TJuiAutoComplete must be set using {@link setDataSource} + * method. This sets the datasource for the suggestions repeater, available through + * the {@link getSuggestions Suggestions} property. Header, footer templates and + * other properties of the repeater can be access via the {@link getSuggestions Suggestions} + * property and its sub-properties. + * + * The {@link setTextCssClass TextCssClass} property if set is used to find + * the element within the Suggestions.ItemTemplate and Suggestions.AlternatingItemTemplate + * that contains the actual text for the suggestion selected. That is, + * only text inside elements with CSS class name equal to {@link setTextCssClass TextCssClass} + * will be used as suggestions. + * + * To return the list of suggestions back to the browser, supply a non-empty data source + * and call databind. For example, + * <code> + * function autocomplete_suggestion($sender, $param) + * { + * $token = $param->getToken(); //the partial word to match + * $sender->setDataSource($this->getSuggestionsFor($token)); //set suggestions + * $sender->dataBind(); + * } + * </code> + * + * The suggestion will be rendered when the {@link dataBind()} method is called + * <strong>during a callback request</strong>. + * + * When an suggestion is selected, that is, when the use has clicked, pressed + * the "Enter" key, or pressed the "Tab" key, the {@link onSuggestionSelected OnSuggestionSelected} + * event is raised. The + * {@link TCallbackEventParameter::getCallbackParameter TCallbackEventParameter::CallbackParameter} + * property contains the index of the selected suggestion. + * + * TJuiAutoComplete allows multiple suggestions within one textbox with each + * word or phrase separated by any characters specified in the + * {@link setSeparator Separator} property. The {@link setFrequency Frequency} + * and {@link setMinChars MinChars} properties sets the delay and minimum number + * of characters typed, respectively, before requesting for sugggestions. + * + * Use {@link onTextChange OnTextChange} and/or {@link onCallback OnCallback} events + * to handle post backs due to {@link setAutoPostBack AutoPostBack}. + * + * In the {@link getSuggestions Suggestions} TRepater item template, all HTML text elements + * are considered as text for the suggestion. Text within HTML elements with CSS class name + * "informal" are ignored as text for suggestions. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TJuiAutoComplete extends TActiveTextBox implements INamingContainer, IJuiOptions +{ + /** + * @var ITemplate template for repeater items + */ + private $_repeater=null; + /** + * @var TPanel result panel holding the suggestion items. + */ + private $_resultPanel=null; + + /** + * Creates a new callback control, sets the adapter to + * TActiveControlAdapter. If you override this class, be sure to set the + * adapter appropriately by, for example, by calling this constructor. + */ + public function __construct() + { + parent::__construct(); + $this->setAdapter(new TJuiControlAdapter($this)); + } + + /** + * @return string the name of the jQueryUI widget method + */ + public function getWidget() + { + return 'autocomplete'; + } + + /** + * @return string the clientid of the jQueryUI widget element + */ + public function getWidgetID() + { + return $this->getClientID(); + } + + /** + * Object containing defined javascript options + * @return TJuiControlOptions + */ + public function getOptions() + { + if (($options=$this->getViewState('JuiOptions'))===null) + { + $options=new TJuiControlOptions($this); + $this->setViewState('JuiOptions', $options); + } + return $options; + } + + /** + * Array containing valid javascript options + * @return array() + */ + public function getValidOptions() + { + return array('appendTo', 'autoFocus', 'delay', 'disabled', 'minLength', 'position', 'source'); + } + + /** + * Array containing valid javascript events + * @return array() + */ + public function getValidEvents() + { + return array(); + } + + /** + * @param string Css class name of the element to use for suggestion. + */ + public function setTextCssClass($value) + { + $this->setViewState('TextCssClass', $value); + } + + /** + * @return string Css class name of the element to use for suggestion. + */ + public function getTextCssClass() + { + return $this->getViewState('TextCssClass'); + } + + + /** + * @return string word or token separators (delimiters). + */ + public function getSeparator() + { + return $this->getViewState('separator', ''); + } + + /** + * @param string word or token separators (delimiters). + */ + public function setSeparator($value) + { + $this->setViewState('separator', TPropertyValue::ensureString($value), ''); + } + + /** + * @return float maximum delay (in seconds) before requesting a suggestion. + */ + public function getFrequency() + { + return $this->getViewState('frequency', 0.4); + } + + /** + * @param float maximum delay (in seconds) before requesting a suggestion. + * Default is 0.4. + */ + public function setFrequency($value) + { + $this->setViewState('frequency', TPropertyValue::ensureFloat($value), 0.4); + } + + /** + * @return integer minimum number of characters before requesting a suggestion. + */ + public function getMinChars() + { + return $this->getViewState('minChars',''); + } + + /** + * @param integer minimum number of characters before requesting a suggestion. + * Default is 1 + */ + public function setMinChars($value) + { + $this->setViewState('minChars', TPropertyValue::ensureInteger($value), 1); + } + + /** + * Raises the callback event. This method is overrides the parent implementation. + * If {@link setAutoPostBack AutoPostBack} is enabled it will raise + * {@link onTextChanged OnTextChanged} event event and then the + * {@link onCallback OnCallback} event. The {@link onSuggest OnSuggest} event is + * raise if the request is to find sugggestions, the {@link onTextChanged OnTextChanged} + * and {@link onCallback OnCallback} events are <b>NOT</b> raised. + * This method is mainly used by framework and control developers. + * @param TCallbackEventParameter the event parameter + */ + public function raiseCallbackEvent($param) + { + $token = $param->getCallbackParameter(); + if(is_array($token) && count($token) == 2) + { + if($token[1] === '__TJuiAutoComplete_onSuggest__') + { + $parameter = new TJuiAutoCompleteEventParameter($this->getResponse(), $token[0]); + $this->onSuggest($parameter); + } + else if($token[1] === '__TJuiAutoComplete_onSuggestionSelected__') + { + $parameter = new TJuiAutoCompleteEventParameter($this->getResponse(), null, $token[0]); + $this->onSuggestionSelected($parameter); + } + } + else if($this->getAutoPostBack()) + parent::raiseCallbackEvent($param); + } + + /** + * This method is invoked when an autocomplete suggestion is requested. + * The method raises 'OnSuggest' event. If you override this + * method, be sure to call the parent implementation so that the event + * handler can be invoked. + * @param TCallbackEventParameter event parameter to be passed to the event handlers + */ + public function onSuggest($param) + { + $this->raiseEvent('OnSuggest', $this, $param); + } + + /** + * This method is invoked when an autocomplete suggestion is selected. + * The method raises 'OnSuggestionSelected' event. If you override this + * method, be sure to call the parent implementation so that the event + * handler can be invoked. + * @param TCallbackEventParameter event parameter to be passed to the event handlers + */ + public function onSuggestionSelected($param) + { + $this->raiseEvent('OnSuggestionSelected', $this, $param); + } + + /** + * @param array data source for suggestions. + */ + public function setDataSource($data) + { + $this->getSuggestions()->setDataSource($data); + } + + /** + * Overrides parent implementation. Callback {@link renderSuggestions()} when + * page's IsCallback property is true. + */ + public function dataBind() + { + parent::dataBind(); + if($this->getPage()->getIsCallback()) + $this->renderSuggestions($this->getResponse()->createHtmlWriter()); + } + + /** + * @return TPanel suggestion results panel. + */ + public function getResultPanel() + { + if($this->_resultPanel===null) + $this->_resultPanel = $this->createResultPanel(); + return $this->_resultPanel; + } + + /** + * @return TPanel new instance of result panel. Default uses TPanel. + */ + protected function createResultPanel() + { + $panel = Prado::createComponent('System.Web.UI.WebControls.TPanel'); + $this->getControls()->add($panel); + $panel->setID('result'); + return $panel; + } + + /** + * @return TRepeater suggestion list repeater + */ + public function getSuggestions() + { + if($this->_repeater===null) + $this->_repeater = $this->createRepeater(); + return $this->_repeater; + } + + /** + * @return TRepeater new instance of TRepater to render the list of suggestions. + */ + protected function createRepeater() + { + $repeater = Prado::createComponent('System.Web.UI.WebControls.TRepeater'); + $repeater->setItemTemplate(new TTemplate('<%# $this->Data %>',null)); + $this->getControls()->add($repeater); + return $repeater; + } + + /** + * Renders the end tag and registers javascript effects library. + */ + public function renderEndTag($writer) + { + parent::renderEndTag($writer); + $this->renderResultPanel($writer); + } + + /** + * Renders the result panel. + * @param THtmlWriter the renderer. + */ + protected function renderResultPanel($writer) + { + $this->getResultPanel()->render($writer); + } + + /** + * Renders the suggestions during a callback respones. + * @param THtmlWriter the renderer. + */ + public function renderCallback($writer) + { + $this->renderSuggestions($writer); + } + + /** + * Renders the suggestions repeater. + * @param THtmlWriter the renderer. + */ + public function renderSuggestions($writer) + { + if($this->getActiveControl()->canUpdateClientSide()) + { + $data=array(); + $items=$this->getSuggestions()->getItems(); + $writer = new TTextWriter; + for($i=0; $i<$items->Count; $i++) + { + $items->itemAt($i)->render($writer); + $item=$writer->flush(); + $data[]=array( 'id' => $i, 'label' => $item); + } + + $this->getResponse()->getAdapter()->setResponseData($data); + } + } + + /** + * @return array list of callback options. + */ + protected function getPostBackOptions() + { + $options = $this->getOptions()->toArray(); + + if(strlen($separator = $this->getSeparator())) + $options['Separators'] = $separator; + + if($this->getAutoPostBack()) + { + $options = array_merge($options,parent::getPostBackOptions()); + $options['AutoPostBack'] = true; + } + if(strlen($textCssClass = $this->getTextCssClass())) + $options['textCssClass'] = $textCssClass; + $options['minLength'] = $this->getMinChars(); + $options['delay'] = $this->getFrequency()*1000.0; + $options['appendTo'] = '#'.$this->getResultPanel()->getClientID(); + $options['ID'] = $this->getClientID(); + $options['EventTarget'] = $this->getUniqueID(); + $options['CausesValidation'] = $this->getCausesValidation(); + $options['ValidationGroup'] = $this->getValidationGroup(); + return $options; + } + + /** + * Override parent implementation, no javascript is rendered here instead + * the javascript required for active control is registered in {@link addAttributesToRender}. + */ + protected function renderClientControlScript($writer) + { + } + + /** + * @return string corresponding javascript class name for this TActiveButton. + */ + protected function getClientClassName() + { + return 'Prado.WebUI.TJuiAutoComplete'; + } +} + +/** + * TAutCompleteEventParameter contains the {@link getToken Token} requested by + * the user for a partial match of the suggestions. + * + * The {@link getSelectedIndex SelectedIndex} is a zero-based index of the + * suggestion selected by the user, -1 if not suggestion is selected. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TJuiAutoCompleteEventParameter extends TCallbackEventParameter +{ + private $_selectedIndex=-1; + + /** + * Creates a new TCallbackEventParameter. + */ + public function __construct($response, $parameter, $index=-1) + { + parent::__construct($response, $parameter); + $this->_selectedIndex=$index; + } + + /** + * @return int selected suggestion zero-based index, -1 if not selected. + */ + public function getSelectedIndex() + { + return $this->_selectedIndex; + } + + /** + * @return string token for matching a list of suggestions. + */ + public function getToken() + { + return $this->getCallbackParameter(); + } +} + +/** + * TJuiAutoCompleteTemplate class. + * + * TJuiAutoCompleteTemplate is the default template for TJuiAutoCompleteTemplate + * item template. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TJuiAutoCompleteTemplate extends TComponent implements ITemplate +{ + private $_template; + + public function __construct($template) + { + $this->_template = $template; + } + /** + * Instantiates the template. + * It creates a {@link TDataList} control. + * @param TControl parent to hold the content within the template + */ + public function instantiateIn($parent) + { + $parent->getControls()->add($this->_template); + } +} |