From 6d52f5c4461bd26c4e1dea68686d88c71a9d3e22 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 21 Nov 2014 22:14:00 +0100 Subject: TJuiAutoComplete multiselection + quickstart doc implemented Separator, minChars and Frequency properties, added the related quickstart parts --- .../protected/pages/JuiControls/Home.page | 4 ++ .../JuiControls/Samples/TJuiAutoComplete/Home.page | 45 +++++++++++++++ .../JuiControls/Samples/TJuiAutoComplete/Home.php | 39 +++++++++++++ .../protected/pages/JuiControls/Widgets.page | 25 +++++++- .../source/prado/activecontrols/activecontrols3.js | 29 ++++++++-- framework/Web/UI/JuiControls/TJuiAutoComplete.php | 67 ++++++++++++++++++---- .../JuiControls/JuiAutoCompleteTestCase.php | 50 ++++++++++++++++ 7 files changed, 244 insertions(+), 15 deletions(-) create mode 100644 demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.page create mode 100644 demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.php create mode 100755 tests/FunctionalTests/quickstart/JuiControls/JuiAutoCompleteTestCase.php diff --git a/demos/quickstart/protected/pages/JuiControls/Home.page b/demos/quickstart/protected/pages/JuiControls/Home.page index 2573b162..68765faa 100644 --- a/demos/quickstart/protected/pages/JuiControls/Home.page +++ b/demos/quickstart/protected/pages/JuiControls/Home.page @@ -80,6 +80,10 @@ For informations of the specific options of each interaction, follow jQuery-UI I TJuiProgressbar displays a progress bar. +
  • + TJuiProgressbar + provides a list of suggestions on the current partial word typed in the textbox +
  • diff --git a/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.page b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.page new file mode 100644 index 00000000..1338b651 --- /dev/null +++ b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.page @@ -0,0 +1,45 @@ + +

    TJuiAutoComplete Samples

    + + + + + + + + +
    +Simple Autocompleter: + + + + +
  • <%# $this->Data['name'] %>
  • +
    +
    + +
    +Autocompleter with multiple selection: + + + + +
  • <%# $this->Data['name'] %>
  • +
    +
    +(Use ',' to separate the selected suggestions) + +
    + +
    diff --git a/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.php b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.php new file mode 100644 index 00000000..c3fba3a9 --- /dev/null +++ b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiAutoComplete/Home.php @@ -0,0 +1,39 @@ +getToken(); + // Sender is the Suggestions repeater + $sender->DataSource=$this->suggestionsForName($token); + $sender->dataBind(); + } + + public function suggestionSelected1($sender,$param) { + $id=$sender->Suggestions->DataKeys[ $param->selectedIndex ]; + $this->Selection1->Text='Selected ID: '.$id; + } + + public function suggestionSelected2($sender,$param) { + $id=$sender->Suggestions->DataKeys[ $param->selectedIndex ]; + $this->Selection2->Text='Selected ID: '.$id; + } + + public function suggestionsForName($name) { + $allChoices = array( + array('id'=>1, 'name'=>'John'), + array('id'=>2, 'name'=>'Paul'), + array('id'=>3, 'name'=>'George'), + array('id'=>4, 'name'=>'Ringo') + ); + + if($name) { + return array_filter($allChoices, function ($el) use ($name) { + return stripos($el['name'], $name) !== false; + }); + } else + return $allChoices; + } + +} \ No newline at end of file diff --git a/demos/quickstart/protected/pages/JuiControls/Widgets.page b/demos/quickstart/protected/pages/JuiControls/Widgets.page index cf72d41d..cedec675 100644 --- a/demos/quickstart/protected/pages/JuiControls/Widgets.page +++ b/demos/quickstart/protected/pages/JuiControls/Widgets.page @@ -10,7 +10,7 @@ PRADO Jui widgets controls can be divided in two groups: For informations of the specific options of each widget, follow jQuery-UI Widget API Documentation for the specific interaction.

    - +

    TJuiProgressbar

    -
    jQuery UI API @@ -25,4 +25,27 @@ The panel takes the aspect of a progressbar ranging from a value of 0 to the val
    + +

    TJuiAutoComplete

    + -
    jQuery UI API + +

    +TJuiAutoComplete is an extension to TActiveTextBox based on jQuery-UI's autocomplete widget. +

    + +

    +TJuiAutoComplete is an extended ActiveTextBox that provides a list of suggestions on the current partial word typed in the textbox. The suggestions are requested using callbacks. The Frequency and MinChars properties sets the delay and minimum number of characters typed, respectively, before requesting for sugggestions. An embedded TRepeater is used to Display the list of suggestions. It can be accessed and styled through the Suggestions property and its sub-properties. +

    + +

    +On each request for suggestions, the OnSuggestion event will be raised. The event handler receives the entered token that can be used to build the list of suggestions and to dataBind() it to the Suggestions repeater. +

    + +

    +When a suggestion is selected the OnSuggestionSelected event is raised, with the index of the selected suggestion contained in the parameter. Multiple selections can be performed in the same textbox. The selections must be separated by any characters specified with the Separator property. +

    + + +
    + diff --git a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js index 0a7511c1..5d4beef8 100644 --- a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js +++ b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js @@ -103,7 +103,12 @@ Prado.WebUI.TJuiAutoComplete = jQuery.klass(Prado.WebUI.TActiveTextBox, this.hasResults = false; jQuery.extend(this.options, { source: this.getUpdatedChoices.bind(this), - select: this.selectEntry.bind(this) + select: this.selectEntry.bind(this), + focus: function () { + return false; + }, + minLength: this.options.minLength, + frequency: this.options.frequency }); jQuery('#'+options.ID).autocomplete(this.options) .data( "ui-autocomplete")._renderItem = function( ul, item ) { @@ -131,22 +136,38 @@ Prado.WebUI.TJuiAutoComplete = jQuery.klass(Prado.WebUI.TActiveTextBox, getUpdatedChoices : function(request, callback) { - var params = new Array(request.term,"__TJuiAutoComplete_onSuggest__"); + var lastTerm = this.extractLastTerm(request.term); + var params = new Array(lastTerm, "__TJuiAutoComplete_onSuggest__"); var options = jQuery.extend(this.options, { 'autocompleteCallback' : callback }); Prado.Callback(this.options.EventTarget, params, this.onComplete.bind(this), this.options); }, + extractLastTerm: function(string) + { + var re = new RegExp("[" + this.options.Separators + "]"); + return string.split(re).pop().trim(); + }, + /** * Overrides parent implements, don't update if no results. */ - selectEntry: function(event, ui) - { + selectEntry: function(event, ui) { + var value = event.target.value; + var lastTerm = this.extractLastTerm(value); + + // strip (possibly) incomplete last part + var previousTerms = value.substr(0, value.length - lastTerm.length); + // and append selected value + ui.item.value = previousTerms + ui.item.value; + + //ui.item.value = event.target.value; var options = [ui.item.id, "__TJuiAutoComplete_onSuggestionSelected__"]; Prado.Callback(this.options.EventTarget, options, null, this.options); }, + onComplete : function(request, result) { var that = this; diff --git a/framework/Web/UI/JuiControls/TJuiAutoComplete.php b/framework/Web/UI/JuiControls/TJuiAutoComplete.php index 115969c5..f6663057 100644 --- a/framework/Web/UI/JuiControls/TJuiAutoComplete.php +++ b/framework/Web/UI/JuiControls/TJuiAutoComplete.php @@ -147,6 +147,57 @@ class TJuiAutoComplete extends TActiveTextBox implements INamingContainer, IJuiO 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 @@ -316,17 +367,11 @@ class TJuiAutoComplete extends TActiveTextBox implements INamingContainer, IJuiO */ protected function getPostBackOptions() { - //disallow page state update ? - //$this->getActiveControl()->getClientSide()->setEnablePageStateUpdate(false); $options = $this->getOptions()->toArray(); - /* - if(strlen($string = $this->getSeparator())) - { - $string = strtr($string,array('\t'=>"\t",'\n'=>"\n",'\r'=>"\r")); - $token = preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY); - $options['tokens'] = $token; - } - */ + + if(strlen($separator = $this->getSeparator())) + $options['Separators'] = $separator; + if($this->getAutoPostBack()) { $options = array_merge($options,parent::getPostBackOptions()); @@ -334,6 +379,8 @@ class TJuiAutoComplete extends TActiveTextBox implements INamingContainer, IJuiO } 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(); diff --git a/tests/FunctionalTests/quickstart/JuiControls/JuiAutoCompleteTestCase.php b/tests/FunctionalTests/quickstart/JuiControls/JuiAutoCompleteTestCase.php new file mode 100755 index 00000000..a3c1ff78 --- /dev/null +++ b/tests/FunctionalTests/quickstart/JuiControls/JuiAutoCompleteTestCase.php @@ -0,0 +1,50 @@ +url("../../demos/quickstart/index.php?page=JuiControls.Samples.TJuiAutoComplete.Home&notheme=true&lang=en"); + + $this->assertEquals("PRADO QuickStart Sample", $this->title()); + + $this->assertContains('TJuiAutoComplete Samples', $this->source()); + + $base = 'ctl0_body_'; + + + $this->assertText("{$base}Selection1", ""); + + $this->byId("{$base}AutoComplete")->click(); + $this->keys('J'); + $this->pause(800); + $this->assertContains('John', $this->source()); + + $this->byCssSelector("#{$base}AutoComplete_result ul li")->click(); + $this->pause(800); + $this->assertValue("{$base}AutoComplete", "John"); + $this->assertText("{$base}Selection1", "Selected ID: 1"); + + + $this->byId("{$base}AutoComplete2")->click(); + $this->keys('Joh'); + $this->pause(800); + $this->byCssSelector("#{$base}AutoComplete2_result ul li")->click(); + $this->pause(800); + $this->assertValue("{$base}AutoComplete2", "John"); + $this->assertText("{$base}Selection2", "Selected ID: 1"); + + //$this->keys(PHPUnit_Extensions_Selenium2TestCase_Keys::END); + $this->keys(',Ge'); + $this->pause(800); + $this->byCssSelector("#{$base}AutoComplete2_result ul li")->click(); + $this->pause(500); + $this->assertValue("{$base}AutoComplete2", "John,George"); + $this->assertText("{$base}Selection2", "Selected ID: 3"); + + } +} -- cgit v1.2.3