Wiki source code of Suggest Widget

Version 62.1 by Adel Atallah on 2018/11/22

Hide last authors
Sergiu Dumitriu 49.2 1 {{velocity output="false"}}
Jerome 35.1 2 ##
3 ## TODO:
4 ## - Document the REST usage of the suggest (this is the recommanded way of using the suggest now - when possible)
5 ## - Merge the example document in this one (why are there 2 documents ?)
6 ##
Sergiu Dumitriu 49.2 7 {{/velocity}}
8
Sergiu Dumitriu 49.1 9 {{box cssClass="floatinginfobox" title="**Contents**"}}
10 {{toc/}}
11 {{/box}}
Sergiu Dumitriu 48.1 12
Manuel Smeria 50.2 13 {{info}}
14 This is a Javascript widget bundled by default with the XWiki platform.
15 {{/info}}
ElenaOanaTabaranu 1.1 16
Manuel Smeria 50.2 17 = Usage =
ElenaOanaTabaranu 1.1 18
Sergiu Dumitriu 49.1 19 The suggest widget can be triggered when typing something in a text field. The suggested list can contain field values from a class defined in your wiki, data retrieved from a custom document or a REST resource, or any custom information you provide.
ElenaOanaTabaranu 14.1 20
Manuel Smeria 50.2 21 == Suggest fields from a class defined in the wiki ==
ElenaOanaTabaranu 14.1 22
Sergiu Dumitriu 49.1 23 Use information from a predefined class in your wiki (e.g. ##XWiki.TagClass##, ##XWiki.XWikiUsers##, etc.) or from a class defined by yourself.
24
Adel Atallah 58.1 25 For example, use **XWiki.TagClass** to suggest tags from the wiki tag cloud:
Sergiu Dumitriu 49.1 26
Vincent Massol 57.7 27 [[image:Documentation.DevGuide.FrontendResources.AutoSuggestWidget.WebHome@suggest.png]]
ElenaOanaTabaranu 14.1 28
Sergiu Dumitriu 48.1 29 {{code}}
ElenaOanaTabaranu 7.1 30 $!xwiki.jsx.use("DevGuide.AutoSuggestWidgetExample")
ElenaOanaTabaranu 1.1 31 <form method="post" action="#">
32 <label for="myinput">Type the name of a tag and test the suggest list:</label>
33 <input id="myinput" size="20" type="text" value=""/>
34 </form>
Sergiu Dumitriu 48.1 35 {{/code}}
ElenaOanaTabaranu 1.1 36
Vincent Massol 57.3 37 The ##JavascriptExtension## object from the [[platform:DevGuide.AutoSuggestWidgetExample]] page contains the Javascript code to enable the widget when focusing on the text field:
ElenaOanaTabaranu 1.1 38
Sergiu Dumitriu 48.1 39 {{code}}
ElenaOanaTabaranu 1.1 40 (function(){
41 document.observe('dom:loaded', function () {
42 if($('myinput')) {
43 Event.observe($('myinput'), "focus", function() {
Jerome 34.1 44 new XWiki.widgets.Suggest(this, {
Sergiu Dumitriu 49.1 45 script: '$xwiki.getURL("${doc.space}.WebHome", "view")?xpage=suggest&classname=XWiki.TagClass&fieldname=tags&secCol=-&',
Adel Atallah 58.1 46 varname: "input",
Jerome 34.1 47 seps: " ,|",
48 offsety: 13
49 });
ElenaOanaTabaranu 1.1 50 });
51 }
52 }); // end of doc observe
53 })();
Sergiu Dumitriu 48.1 54 {{/code}}
ElenaOanaTabaranu 1.1 55
Manuel Smeria 50.2 56 === Options used in the ##suggest.vm## template: ===
ElenaOanaTabaranu 17.1 57
Sergiu Dumitriu 48.1 58 |=Option|=Details
Sergiu Dumitriu 49.1 59 |xpage|For class properties use ##xpage=suggest## because the ##suggest.vm## template can handle such requests.
Sergiu Dumitriu 48.1 60 |classname|The name of the class for the elements of the suggest list.
61 |fieldname|The field name from the class considered for the suggest list.
62 |firCol|First column of the list of results.
63 |secCol|Second column of the list of results. For a user defined query, use **-** value for one column and no hidden input. Otherwise the list of results will have two columns and a hidden input.
ElenaOanaTabaranu 17.1 64
Manuel Smeria 50.2 65 === Example ===
ElenaOanaTabaranu 17.1 66
Vincent Massol 57.3 67 Check out the example for class field values at [[Class Field Example>>platform:DevGuide.AutoSuggestWidgetExample]]
ElenaOanaTabaranu 18.1 68
Manuel Smeria 50.2 69 == Suggest custom information ==
ElenaOanaTabaranu 1.1 70
Sergiu Dumitriu 49.1 71 When the information you want to suggest is not available through a class field or you generate it using a custom query, you need to create a service (plain wiki page called with the ##get## action and with ##outputSyntax=plain## parameter in the url, for example: ##xwiki/bin/get/Space/Page?outputSyntax=plain##) that maps your results to the **xml** input accepted by the widget. For example, you can build a list of suggestions that contains the wiki page names within a certain space:
72
Vincent Massol 57.8 73 [[image:Documentation.DevGuide.FrontendResources.AutoSuggestWidget.WebHome@customsuggest.png]]
ElenaOanaTabaranu 30.1 74
Sergiu Dumitriu 48.1 75 {{code}}
ElenaOanaTabaranu 15.1 76 $!xwiki.jsx.use("DevGuide.AjaxSuggestCustomExample")
ElenaOanaTabaranu 14.1 77 <form method="post" action="#">
Sergiu Dumitriu 49.1 78 <label for="myinput">Type the name of an example page from the <tt>DevGuide</tt> space and test the suggest list:</label>
Raluca Stavro 31.1 79 <input id="myinput_suggest" size="20" type="text" value=""/>
80 <input id="myinput" type="hidden" />
81 <input id="mybutton" type="button" value="Go" /><br/>
ElenaOanaTabaranu 14.1 82 </form>
Sergiu Dumitriu 48.1 83 {{/code}}
ElenaOanaTabaranu 14.1 84
Vincent Massol 57.3 85 The ##JavascriptExtension## object from the [[platform:DevGuide.AjaxSuggestCustomExample]] page contains the Javascript code to enable the widget when focusing on the text field. Also, the ##script## option uses the URL for the results page.
ElenaOanaTabaranu 14.1 86
Sergiu Dumitriu 48.1 87 {{code}}
ElenaOanaTabaranu 14.1 88 (function(){
89 document.observe('dom:loaded', function () {
Raluca Stavro 31.1 90 if($('myinput_suggest')) {
91 Event.observe($('myinput_suggest'), "focus", function() {
Jerome 34.1 92 new XWiki.widgets.Suggest(this, {
Vincent Massol 57.6 93 script: "$xwiki.getURL('Documentation.DevGuide.FrontendResources.AutoSuggestWidget.SuggestService', 'get', 'outputSyntax=plain&spacename=Documentation.DevGuide')&",
Sergiu Dumitriu 49.1 94 varname: "input",
95 seps: " ,|",
Jerome 33.1 96 offsety: 13,
97 minchars: 3
98 });
ElenaOanaTabaranu 14.1 99 });
100 }
101 }); // end of doc observe
102 })();
Sergiu Dumitriu 48.1 103 {{/code}}
104
Sergiu Dumitriu 49.1 105 The service page uses a query to get all the pages from the space provided using ##spacename## parameter in the URL. The generated response must be an **xml** file that has ##<results>## as a root node and ##<rs>## as children.
Sergiu Dumitriu 48.1 106
107 {{code}}
ElenaOanaTabaranu 14.1 108 ##
109 ## Service to generate the suggest list of files from a certain space.
110 ## @spacename
111 ## @input
112 ##
113 #set($input = $request.get("input").toLowerCase())
114 #set($spacename = $request.get("spacename"))
115 $response.setContentType("text/xml") ## generate a xml file
116 ## select pages
117 #if("$!input" == "")
Raluca Stavro 31.1 118 #set($query = "where doc.space='$spacename' and doc.name<>'WebHome' and doc.name<>'WebPreferences' order by doc.date desc")
ElenaOanaTabaranu 14.1 119 #else
Raluca Stavro 31.1 120 #set($query = "where doc.space='$spacename' and doc.name<>'WebHome' and doc.name<>'WebPreferences' and lower(doc.name) like '%" + $input + "%' order by doc.date desc")
ElenaOanaTabaranu 14.1 121 #end
Raluca Stavro 31.1 122 #set($searchresults = $xwiki.searchDocuments($query, 30, 0))
ElenaOanaTabaranu 14.1 123 <results space="$spacename">
124 #foreach($result in $searchresults)
Raluca Stavro 31.1 125 #set($resultDoc = $xwiki.getDocument($result))
126 #set($resultDocName = $resultDoc.name)
127 #set($resultDocURL = $resultDoc.getURL())
128 <rs id="1" info="$resultDocURL">$resultDocName</rs>
ElenaOanaTabaranu 14.1 129 #end
130 </results>
Sergiu Dumitriu 48.1 131 {{/code}}
ElenaOanaTabaranu 17.1 132
Manuel Smeria 50.2 133 To provide autosuggest to several elements on the form, you can use JavaScript to loop through all the form elements and provide autosuggest if they meet certain conditions. In the example below, if there are form elements with id //Supplier// in the form, they get assigned a suggest widget that uses the //Suppliers// space as its source. If the element id matches //Product//, the suggest is told to use the //Products// space as its source instead.
Sergiu Dumitriu 49.1 134
MensoHeus 45.1 135 This method can be very useful when a form contains a lot of similar elements that require autosuggest. If you make sure the naming is done consistently, you can also use javascript to assign autosuggest based on part of the element id, for example 'all elements ending with _foo' or 'all elements starting with Bar_'. You can use the velocity code from the example above with the code below.
136
Sergiu Dumitriu 48.1 137 {{code}}
MensoHeus 45.1 138 (function(){
Buzila Vlad 52.1 139 document.observe('dom:loaded', function () {
140 myForm = document.getElementById('inline').elements;
141 for(i=0; i<myForm.length; i++){
142 if(myForm[i].id =='Supplier'){
143 mySuggest(myForm[i], 'Suppliers');
144 }
145 if(myForm[i].id=='Product'){
146 mySuggest(myForm[i], 'Products');
147 }
148 }
149 }); // end of doc observe
MensoHeus 45.1 150 })();
151
152 function mySuggest(element, space) {
Buzila Vlad 52.1 153 if (!element.suggest) {
154 element.suggest = new XWiki.widgets.Suggest(element, {
155 script: "$xwiki.getURL('Sandbox.AutoSuggest', 'get', 'outputSyntax=plain&spacename=')"+space+"&",
156 varname: "input",
157 seps: " ,|",
158 offsety: 13,
159 minchars: 1
160 });
161 }
MensoHeus 45.1 162 }
Sergiu Dumitriu 48.1 163 {{/code}}
MensoHeus 45.1 164
Manuel Smeria 50.2 165 === Example ===
ElenaOanaTabaranu 18.1 166
Vincent Massol 57.3 167 Check out the example for custom information at [[Custom Information Example>>platform:DevGuide.AjaxSuggestCustomExample]]
ElenaOanaTabaranu 18.1 168
Manuel Smeria 50.2 169 == Suggest Users or Groups from the wiki ==
Oana Florea 38.1 170
Sergiu Dumitriu 48.1 171 Local or global users and groups from the wiki can be suggested using the **uorgsuggest.vm** template.
Sergiu Dumitriu 49.1 172
Oana Florea 38.1 173 Example:
Sergiu Dumitriu 49.1 174
175 {{code}}
Oana Florea 38.1 176 $xwiki.jsx.use("$doc.fullName")##
177
178 <input name="userInput" id="userInput" value="" type="text"/>
Sergiu Dumitriu 49.1 179 {{/code}}
180
Oana Florea 44.1 181 Here is the code that made the suggestion of global users from the wiki possible:
Oana Florea 38.1 182
Sergiu Dumitriu 48.1 183 {{code}}
Oana Florea 38.1 184 ...
185 <input name="userInput" id="userInput" value="" type="text"/>
186 ...
Sergiu Dumitriu 48.1 187 {{/code}}
Oana Florea 38.1 188
Sergiu Dumitriu 48.1 189 {{code}}
Oana Florea 38.1 190 (function(){
191 document.observe('dom:loaded', function () {
192 if($('userInput')) {
193 Event.observe($('userInput'), "focus", function() {
194 new XWiki.widgets.Suggest(this, {
Oana Florea 43.1 195 script: '$xwiki.getURL("${doc.fullName}", "view")?xpage=uorgsuggest&classname=XWiki.XWikiUsers&wiki=global&uorg=user&',
Adel Atallah 58.1 196 varname: "input",
Oana Florea 38.1 197 seps: " ,|",
198 delay : 200,
199 timeout: 5000,
200 offsety: 13
201 });
202 });
203 }
204 }); // end of doc observe
205 })();
Sergiu Dumitriu 48.1 206 {{/code}}
Oana Florea 38.1 207
Buzila Vlad 52.1 208 == Search suggest shows document title but searches by document name ==
209
210 Example:
211
212 The request
213
214 {{code}}
215
216 #set($suggestURL = $xwiki.getURL('Main.WebHome', 'view', "&xpage=suggest&classname=SomeSpace.SomeClass&fieldname=entity&firCol=obj.name&secCol=doc.title"))
217
218 onfocus='new XWiki.widgets.Suggest(this, {script:"$escapetool.javascript("${suggestURL}&")", varname:"input", callback: function(obj) {resource.onChangeEntity(obj.info, obj.value);}} )'
219
220 {{/code}}
221
222 The JavascriptExtension object
223
224 {{code}}
225
226 // entityValue is the document name and entityInfo is the document title
227 onChangeEntity: function(entityValue, entityInfo) {
228 // Update entity value
Buzila Vlad 52.2 229 $('SomeSpace.SomeClass_0_entity_suggest').value = entityInfo;
230 var serviceURL = new XWiki.Document('SomePageOne', 'SomeSpace').getURL('view');
Buzila Vlad 52.1 231 var ajx = new Ajax.Request(serviceURL, {
232 method: 'get',
Buzila Vlad 52.2 233 parameters: 'xpage=plain&outputSyntax=plain&entity=' + encodeURIComponent(entityValue)
Buzila Vlad 54.1 234 }
235 }
Buzila Vlad 52.1 236
237 {{/code}}
238
Manuel Smeria 50.2 239 = Javascript parameters for the ##XWiki.widgets.Suggest## constructor =
ElenaOanaTabaranu 1.1 240
Sergiu Dumitriu 50.1 241 |=Parameter|=Details|=Default value
242 |##className##|The CSS classname of the suggest list.|##ajaxsuggest##
243 |##minchars##|The minimum number of characters after which to trigger the suggest.|##1##
244 |##delay##|Throttle delay: how much to wait after a keypress before requesting suggestions from the server, in milliseconds.|##500##
245 |##timeout##|How long to display the list of suggestions, in milliseconds. If the user doesn't interact with the suggestions before the timeout expires, the list will be cleared.|##2500## (2.5 seconds).
246 |##offsety##|How much to shift the list of suggestions vertically from the normal position, in pixels. This allows, for example, room for extra decorations between the input and the list.|##0##
247 |##shownoresults##|What to do when no results match the current input: display a "no results" message (##true##), or simply hide the suggest box when no suggestions are available (##false##).|##true##
248 |##noresults##|Default displayed message when ##shownoresults## is enabled and there are no results to display.|##No results!## (translation key ##core.widgets.suggest.noResults##)
249 |##hideButton##|Controls whether a //hide suggestions// button (or two) is displayed or not. If used, must be a map (JS Object) with two possible keys: ##hideButton.positions## is an array that accepts as values ##top## and ##bottom##, specifying where to place hide buttons, and ##hideButton.text## is the text that should be displayed.|##{positions: ['top'], text: 'hide suggestions'}## (translation key ##core.widgets.suggest.hide##)
250 |##cache##|Cache the list suggestions returned for a specific input for the lifetime of the current page.|##false##
251 |##seps##|If suggestions should be returned for each token instead of the full text in the input, set this to a list of characters that should be used for splitting the input into tokens. Leave empty to skip tokenizing and use the whole text instead.|Empty string
252 |##parentContainer##|The id of the element that will hold the suggest element. Useful when the enhanced input is not statically positioned, for example in a modal dialog|##body##
253 |##sources##|Array of sources from where to fetch suggestions. If there are any entries in this array, then the suggest functions in //multi-source// mode; if not, then the suggest is in //single-source// mode. Every entry should be a map (JS Object), and the following parameters should be used as keys in every such map instead of keys in the global options.|None, by default the suggest is in single-source mode
254 |##script##|URL for the ajax request that will get the suggested list. Must end with ##&## because ##varname## parameter will be appended. Use ##suggest.vm## to get field values from a wiki class or a custom URL to generate the suggested list.|None, this parameter is mandatory
255 |##varname##|The name of the request parameter holding the input stub.|##input##
256 |##method##|The HTTP method for the AJAX request.|##get##
257 |##resultsParameter##|The name of the JSON variable or XML element holding the results.|##results## for XML results, must be changed to ##searchResults## for the REST search
258 |##resultId##|The name of the JSON parameter or XML attribute holding the result identifier.|##id## for both the old suggest and the REST search
259 |##resultValue##|The name of the JSON parameter or XML attribute holding the result value.|##value## for the old suggest, must be changed to ##pageFullName## for the REST search
260 |##resultInfo##|The name of the JSON parameter or XML attribute holding the result auxiliary information.|##info## for the old suggest, must be changed to ##pageFullName## for the REST search
261 |##icon##|An icon to display for every entry in the results fetched from this source.|None, no icon is displayed
262 |##highlight##|Should results fragments be highlighted when matching typed input.|##true##
Guillaume Delhumeau 51.1 263 |##align##|Control where the suggest box will be displayed. Possible values are: ##left##, ##center##, ##right##.
264 Since 6.2: there is also the ##auto## value, that will place the search box from the left of the input box unless there is not enough place to display it entirely, otherwise it will be displayed from the right.|##right##
Eduard Moraru 51.9 265 |##propagateEventKeyCodes##|A sublist of key codes, from the list of keys handled by this widget, for which to propagate the keyboard event. Useful when another keyboard event listener exists on the input field, even if it may be registered at a difference level. See the ##onKeyPress## in the code for a clearer picture.|Empty list. By default, none of the handled key events propagate. All other, not handled, events do.
ElenaOanaTabaranu 1.1 266
Adel Atallah 58.1 267 = Velocity macros =
268
269 You can use velocity macros to insert the suggest widgets.
270
271 == Page picker widget ==
272
Adel Atallah 61.1 273 {{info}}
274 Since 10.9
275 {{/info}}
276
Adel Atallah 60.2 277 [[image:page-picker.jpg||height="246" width="796"]]
Adel Atallah 60.1 278
Adel Atallah 58.1 279 The page picker widget can be inserted on a page using the following code:
280 {{code}}{{velocity}}
281 {{html}}
282 #pagePicker()
283 {{/html}}
284 {{/velocity}}{{/code}}
285
286 You can specify the HTML attributes of the select by doing this:
287 {{code}}#set ($parameters = {'multiple': 'multiple', 'id': 'my-id'})
288 #pagePicker($parameters){{/code}}
289
Manuel Smeria 50.2 290 = Tips =
ElenaOanaTabaranu 1.1 291
Eduard Moraru 51.2 292 * Suggest event:(((
293 xwiki:suggest:selected##{{code}}Event.observe($('myInput'), "xwiki:suggest:selected", function(event) {
Oana Florea 46.1 294 // do something with event.memo.value or event.memo.id or event.memo.info ...
Eduard Moraru 51.2 295 });{{/code}}##
Manuel Smeria 50.2 296 )))
Oana Florea 37.1 297 * Check out the code:
Manuel Smeria 50.2 298 ** [[for your wiki instance>>http://localhost:8080/xwiki/resources/js/xwiki/suggest/ajaxSuggest.js]]
Guillaume Delhumeau 51.1 299 ** the suggest resources on GitHub (for example tag xwiki-platform-4.1): {{scm branch="xwiki-platform-4.1" path="xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/uicomponents/suggest/"/}}
Oana Florea 36.1 300
Manuel Smeria 50.2 301 = Bugs we know about =
Sergiu Dumitriu 48.1 302
Thomas Mortagne 56.1 303 The suggest feature will not work if the page called by the widget is not saved with programming rights (see details on [[this issue>>https://jira.xwiki.org/browse/XE-539]]).

Get Connected