Wiki source code of Suggest Widget

Last modified by Marius Dumitru Florea on 2026/03/24 13:27

Hide last authors
Sergiu Dumitriu 49.1 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
Marius Dumitru Florea 67.1 2 {{toc start="2"/}}
Sergiu Dumitriu 49.1 3 {{/box}}
Sergiu Dumitriu 48.1 4
Marius Dumitru Florea 88.1 5 The suggest widget is implemented using [[Tom Select>>https://github.com/orchidjs/tom-select]] with its Bootstrap skin and is bundled by default in XWiki platform.
ElenaOanaTabaranu 1.1 6
Marius Dumitru Florea 88.1 7 {{version before="18.2.0RC1"}}
8 In older versions of XWiki the suggest widget was implemented using [[Selectize.js>>http://selectize.github.io/selectize.js/]]. Unfortunately Selectize stop being maintained so we decided to replace it with Tom Select, which is actually a fork of Selectize. Tom Select preserves most of the public JavaScript API and configuration options of Selectize, so the following documentation should apply to older XWiki versions using Selectize, with small adjustments.
9 {{/version}}
10
Marius Dumitru Florea 67.1 11 == Predefined Suggesters ==
ElenaOanaTabaranu 1.1 12
Marius Dumitru Florea 67.1 13 A couple of suggesters are available by default in XWiki. Each suggester provides:
ElenaOanaTabaranu 14.1 14
Marius Dumitru Florea 67.1 15 * dedicated helper Velocity macros (to import required resources and to output the required HTML)
16 * a jQuery plugin to activate the suggest behavior on any input or select element
17 * a CSS class that activates the suggest behavior automatically
ElenaOanaTabaranu 14.1 18
Marius Dumitru Florea 67.1 19 The dedicated Velocity macros are in fact loading a JavaScript code that calls the dedicated jQuery plugin on all the elements (input or select) that are marked with the dedicated CSS class. Here's the list of available suggesters:
Sergiu Dumitriu 49.1 20
Marius Dumitru Florea 67.1 21 |=Data|=Velocity Macros|=jQuery Plugin|=CSS Class
22 |Pages|pagePicker, pagePicker_import|suggestPages|suggest-pages
23 |Attachments|attachmentPicker, attachmentPicker_import|suggestAttachments|suggest-attachments
24 |Users|userPicker, userPicker_input, userPicker_import|suggestUsers|suggest-users
25 |Groups|groupPicker|suggestGroups|suggest-groups
26 |Property Values|xpropertySuggestInputDisplayer|suggestPropertyValues|suggest-propertyValues
Sergiu Dumitriu 49.1 27
Marius Dumitru Florea 67.1 28 === Usage ===
ElenaOanaTabaranu 14.1 29
Marius Dumitru Florea 67.1 30 There are 3 ways in which you can activate a predefined suggester:
31
32 * from Velocity (by calling the dedicated Velocity macro)
33 * from JavaScript (by calling the dedicated jQyery plugin)
34 * from HTML (by marking form fields with the dedicated CSS class)
35
36 Use the one that suits you the best.
37
38 ==== From Velocity ====
39
Marius Dumitru Florea 89.1 40 You can do this by putting the following code in the content of a wiki page. Here we're calling the dedicated ##pagePicker## Velocity macro. Note that you can pass configuration options. Most of these settings are translated into HTML attributes (of the generated suggest input element) read by the dedicated jQuery plugin. You can use the ##data-xwiki-selectize## parameter to pass configuration options to the [[Tom Select>>https://tom-select.js.org/docs/]] widget. Each predefined suggester might also have custom parameters you can set, check their documentation below.
Marius Dumitru Florea 67.1 41
42 {{code language="none"}}
43 {{velocity}}
44 {{html}}
45 #set ($pagePickerParams = {
46 'name': 'targetPages',
47 'value': ['Path.To.Alice', 'Path.To.Bob'],
48 'multiple': 'multiple'
49 })
50 #pagePicker($pagePickerParams)
51 {{/html}}
52 {{/velocity}}
Sergiu Dumitriu 48.1 53 {{/code}}
ElenaOanaTabaranu 1.1 54
Marius Dumitru Florea 67.1 55 ==== From JavaScript ====
ElenaOanaTabaranu 1.1 56
Marius Dumitru Florea 89.1 57 You can do this from a JavaScript Skin extension. First you need to configure the path to the suggester you want to use and then you need to call the dedicated jQuery plugin (##suggestAttachments##) from a require block. Note that you can pass configuration options when activating the suggester. These configuration options are either generic (for the [[Tom Select>>https://tom-select.js.org/docs/]] widget) or specific to each suggester (see below).
Marius Dumitru Florea 67.1 58
59 {{code language="js"}}
60 require.config({
61 paths: {
62 'xwiki-suggestAttachments': "$xwiki.getSkinFile('uicomponents/suggest/suggestAttachments.js', true)" +
63 "?v=$escapetool.url($xwiki.version)"
64 }
65 });
66
67 require(['jquery', 'xwiki-suggestAttachments'], function($) {
68 $('input[name="logo"]').suggestAttachments({
69 accept: 'image/,.mp4,.pdf',
70 uploadAllowed: true
71 });
72 });
Sergiu Dumitriu 48.1 73 {{/code}}
ElenaOanaTabaranu 1.1 74
Marius Dumitru Florea 67.1 75 Of course, you still need to load your skin extension code (from the content of a wiki page):
ElenaOanaTabaranu 17.1 76
Marius Dumitru Florea 67.1 77 {{code language="none"}}
78 {{velocity}}
79 {{html}}
80 #set ($discard = $xwiki.jsx.use('Path.To.Your.JSX'))
81 <input type="text" name="logo" value="[email protected]"/>
82 {{/html}}
83 {{/velocity}}
84 {{/code}}
ElenaOanaTabaranu 17.1 85
Marius Dumitru Florea 67.1 86 ==== From HTML ====
ElenaOanaTabaranu 17.1 87
Marius Dumitru Florea 89.1 88 Put the following code in the content of a wiki page. First you need to import the resources required by the suggester and then you need to mark the form fields you wish to enhance (using the dedicated CSS class, ##suggest-users## here). Note that you can use the ##data-xwiki-selectize## attribute to pass configuration options in JSON format to the [[Tom Select>>https://tom-select.js.org/docs/]] widget. Each predefined suggester might also have custom attributes you can set, check their documentation below.
ElenaOanaTabaranu 18.1 89
Marius Dumitru Florea 67.1 90 {{code language="none"}}
91 {{velocity output="false"}}
92 #userPicker_import
93 {{/velocity}}
ElenaOanaTabaranu 1.1 94
Marius Dumitru Florea 67.1 95 {{html}}
96 <input type="text" name="manager" value="XWiki.mflorea" class="suggest-users"/>
97 {{/html}}
98 {{/code}}
Sergiu Dumitriu 49.1 99
Marius Dumitru Florea 67.1 100 === Suggest Pages ===
ElenaOanaTabaranu 30.1 101
Marius Dumitru Florea 67.1 102 This suggester displays the page rendered title and the page location. The value that is saved in the end is the page reference. The hidden page user preference is taken into account.
103
104 {{code language="none"}}
105 {{velocity}}
106 {{html}}
107 #set ($pagePickerParams = {
108 ...
109 })
110 #pagePicker($pagePickerParams)
111 {{/html}}
112 {{/velocity}}
Sergiu Dumitriu 48.1 113 {{/code}}
ElenaOanaTabaranu 14.1 114
Marius Dumitru Florea 80.1 115 {{image reference="pagePicker.png"/}}
ElenaOanaTabaranu 14.1 116
Marius Dumitru Florea 67.1 117 Custom configuration parameters:
118
119 |=Name|=Description|=Default Value
Marius Dumitru Florea 83.1 120 |data-document-reference|The document where the selected values are saved. Stored document references will be relative to this document.|Current page
121 |data-search-scope|(((Where to look for pages. The following is supported:
122 * "wiki:wikiName" look for pages in the specified wiki
Marius Dumitru Florea 84.1 123 * "space:spaceReference" look for pages in the specified space)))|Current wiki
Marius Dumitru Florea 67.1 124
125 === Suggest Attachments ===
126
127 This suggester displays the attachment (file) name and the attachment location. The suggestion icon is either a preview, if the attachment is an image or an icon that depends on the attachment media type. The value that is saved in the end is the attachment reference. The hidden page user preference is taken into account (e.g. attachments from hidden pages are not displayed by default).
128
129 {{code language="none"}}
130 {{velocity}}
131 {{html}}
132 #set ($attachmentPickerParams = {
133 ...
134 })
135 #attachmentPicker($attachmentPickerParams)
136 {{/html}}
137 {{/velocity}}
Sergiu Dumitriu 48.1 138 {{/code}}
139
Marius Dumitru Florea 67.1 140 {{image reference="attachmentPicker.png"/}}
Sergiu Dumitriu 48.1 141
Marius Dumitru Florea 67.1 142 It supports local file upload, either by selecting the files from the file browser or by dropping them on the suggest input. It also supports drag and drop of attachment links from the Attachment tab at the bottom of the wiki page.
143
144 Custom configuration parameters:
145
146 |=Name|=Description|=Default Value
147 |data-document-reference|The document where the selected values are saved and where new files are being uploaded. Stored attachment references will be relative this document.|Current page
148 |data-search-scope|(((Where to look for attachments. The following is supported:
149 * "wiki:wikiName" look for attachments in the specified wiki
Marius Dumitru Florea 84.1 150 * "space:spaceReference" look for attachments in the specified space
Marius Dumitru Florea 67.1 151 * "document:documentReference" look for attachments in the specified document)))|Current wiki
152 |data-upload-allowed|Whether to allow the user to upload files|false
153 |data-accept|(((Indicates the type of files that can be selected or uploaded. The value is a comma separated list of:
154 * file name extensions (e.g. .png,.pdf)
155 * complete or partial media types (e.g. image/,video/mpeg)
156
157 If nothing is specified then no restriction is applied.)))|None
158
159 === Suggest Users ===
160
161 This suggester displays the user avatar and their name. The value that is saved in the end is the user reference (the reference of the user profile page).
162
Vincent Massol 87.1 163 The users listed are sorted alphabetically based first on their first name and then last names, independently of the case. When no input is specified, all the users from wiki or the farm are matched. The first 10 users that are accessible to the current user are displayed.
slauriere 85.1 164
Marius Dumitru Florea 67.1 165 {{code language="none"}}
166 {{velocity}}
167 {{html}}
168 #set ($userPickerParams = {
169 ...
170 })
slauriere 85.1 171 #userPicker(true, $userPickerParams)
Marius Dumitru Florea 67.1 172 {{/html}}
173 {{/velocity}}
Sergiu Dumitriu 48.1 174 {{/code}}
ElenaOanaTabaranu 17.1 175
Marius Dumitru Florea 67.1 176 {{image reference="userPicker.png"/}}
Sergiu Dumitriu 49.1 177
slauriere 85.1 178 The ##userPicker## macro requires two parameters: the first one indicates whether the picker accepts multiple values or not, and the second one contains complementary configuration parameters:
MensoHeus 45.1 179
Marius Dumitru Florea 67.1 180 |=Name|=Description|=Default Value
181 |data-userScope|Where to retrieve the user suggestions from. Supported values are: LOCAL_ONLY, GLOBAL_ONLY, LOCAL_AND_GLOBAL|User scope of the current wiki
MensoHeus 45.1 182
Marius Dumitru Florea 67.1 183 === Suggest Groups ===
184
185 The suggester displays the group logo and its name. The group logo is the first image attachment found on the group page. The value that is saved in the end is the group reference (the reference of the group page).
186
187 {{code language="none"}}
188 {{velocity}}
189 {{html}}
190 #set ($groupPickerParams = {
191 ...
192 })
slauriere 85.1 193 #groupPicker(true, $groupPickerParams)
Marius Dumitru Florea 67.1 194 {{/html}}
195 {{/velocity}}
Sergiu Dumitriu 48.1 196 {{/code}}
MensoHeus 45.1 197
Marius Dumitru Florea 67.1 198 {{image reference="groupPicker.png"/}}
ElenaOanaTabaranu 18.1 199
slauriere 85.1 200 Like the ##userPicker## macro, ##groupPicker## requires two parameters: the first one indicates whether the picker accepts multiple values or not, and the second one contains complementary configuration parameters:
ElenaOanaTabaranu 18.1 201
Marius Dumitru Florea 67.1 202 |=Name|=Description|=Default Value
203 |data-userScope|Where to retrieve the group suggestions from. Supported values are: LOCAL_ONLY, GLOBAL_ONLY, LOCAL_AND_GLOBAL. Note that GLOBAL_ONLY has the same effect as LOCAL_AND_GLOBAL because a wiki with only global users can have local groups|User scope of the current wiki
Oana Florea 38.1 204
Marius Dumitru Florea 67.1 205 === Suggest Property Values ===
Sergiu Dumitriu 49.1 206
Marius Dumitru Florea 67.1 207 This suggester displays the label assocaited with a property value and saves the raw property value. The following property types are supported by this suggester: Static List and Database List. Note that these property types have default custom displayers associated that load the suggest widget when the "Use suggest" meta property is on. So normally the only thing you need to do is to display the property.
Sergiu Dumitriu 49.1 208
Marius Dumitru Florea 67.1 209 {{code language="none"}}
210 {{velocity}}
211 $doc.display('myDatabaseListProperty')
212 {{/velocity}}
213 {{/code}}
Oana Florea 38.1 214
Marius Dumitru Florea 67.1 215 {{image reference="propertyValuePicker.png"/}}
216
Marius Dumitru Florea 81.1 217 If you don't have a property to display then you can also enable this suggester by calling the generic ##suggestInput## macro like this:
218
219 {{code language="none"}}
220 {{velocity}}
221 {{html}}
222 #set ($discard = $xwiki.jsfx.use('uicomponents/suggest/suggestPropertyValues.js',
223 {'forceSkinAction': true, 'language': $xcontext.locale}))
224 #set ($suggestParams = {
225 'class': 'suggest-propertyValues',
226 'placeholder': 'Select the movie director',
227 'data-className': 'Help.Applications.Movies.Code.MoviesClass',
228 'data-propertyName': 'databaseList1'
229 })
230 #suggestInput($suggestParams)
231 {{/html}}
232 {{/velocity}}
233 {{/code}}
234
Marius Dumitru Florea 82.1 235 If you need tag suggestions then you can use this configuration:
236
237 {{code language="none"}}
238 #set ($suggestParams = {
239 'class': 'suggest-propertyValues',
240 'multiple': 'multiple',
241 'data-className': 'XWiki.TagClass',
242 'data-propertyName': 'tags'
243 })
244 {{/code}}
245
Marius Dumitru Florea 67.1 246 Custom configuration parameters:
247
248 |=Name|=Description|=Default Value
249 |data-className|The class where the property is defined|None
250 |data-propertyName|The property whose values are to be retrieved as suggestions|None
251 |data-freeText|Whether free text is allowed or forbidden. Possible values are: allowed, forbidden|None
252
253 == Custom Suggesters ==
254
255 === Suggest from Static Data ===
256
257 Let's see how you can use the suggest widget with static data (i.e. data that is available when the web page is loaded).
258
259 {{html wiki="true"}}
260 <div>
261 <ul class="nav nav-tabs" role="tablist">
262 <li role="presentation" class="active">
263 <a href="#staticDataV1" aria-controls="staticDataV1" role="tab" data-toggle="tab">V1: The Basics</a>
264 </li>
265 <li role="presentation">
266 <a href="#staticDataV2" aria-controls="staticDataV2" role="tab" data-toggle="tab">V2: Separate Data</a>
267 </li>
268 <li role="presentation">
269 <a href="#staticDataV3" aria-controls="staticDataV3" role="tab" data-toggle="tab">V3: Helper Macros</a>
270 </li>
271 <li role="presentation">
272 <a href="#staticDataV4" aria-controls="staticDataV4" role="tab" data-toggle="tab">V4: Reusable Code</a>
273 </li>
274 </ul>
275
276 <div class="tab-content">
277 <div role="tabpanel" class="tab-pane active" id="staticDataV1">
278 <p>The following code:</p>
279
280 * loads the resources (JavaScript and CSS) needed by the suggest widget
281 * outputs the HTML (select element) needed by the suggest widget
282
283 <p>Note that the select element is marked with the ##xwiki-selectize## CSS class which activates the suggest widget.</p>
284
285 {{code language="none"}}
286 {{velocity}}
Marius Dumitru Florea 89.1 287 #set ($discard = $xwiki.jsfx.use('uicomponents/suggest/xwiki.selectize.js'))
Marius Dumitru Florea 67.1 288 {{/velocity}}
289
290 {{html}}
291 <select class="xwiki-selectize">
292 <option value="">Select the country</option>
293 <option value="fr">France</option>
294 <option value="de">Germany</option>
295 <option value="ro">Romania</option>
296 </select>
297 {{/html}}
Sergiu Dumitriu 49.1 298 {{/code}}
299
Marius Dumitru Florea 67.1 300 </div>
Oana Florea 38.1 301
Marius Dumitru Florea 67.1 302 <div role="tabpanel" class="tab-pane" id="staticDataV2">
303 <p>In this version we separate the code that generates the data used to provide suggestions. The data is usually retrieved from the database.</p>
304
305 {{code language="none"}}
306 {{velocity}}
307 {{html}}
Marius Dumitru Florea 89.1 308 #set ($discard = $xwiki.jsfx.use('uicomponents/suggest/xwiki.selectize.js'))
Marius Dumitru Florea 67.1 309 #set ($countries = [
310 {'name': 'France', 'code': 'fr'},
311 {'name': 'Germany', 'code': 'de'},
312 {'name': 'Romania', 'code': 'ro'}
313 ])
Marius Dumitru Florea 89.1 314 ## See https://tom-select.js.org/docs/
Marius Dumitru Florea 67.1 315 #set ($selectizeSettings = {})
316 <select class="xwiki-selectize" data-xwiki-selectize="$escapetool.xml($jsontool.serialize($selectizeSettings))">
317 <option value="">Select the country</option>
318 #foreach ($country in $countries)
319 <option value="$!escapetool.xml($country.code)">$!escapetool.xml($country.name)</option>
320 #end
321 </select>
322 {{/html}}
323 {{/velocity}}
Sergiu Dumitriu 48.1 324 {{/code}}
Oana Florea 38.1 325
Marius Dumitru Florea 67.1 326 </div>
327
328 <div role="tabpanel" class="tab-pane" id="staticDataV3">
329 <p>In this version we use some helper Velocity macros: ##picker_import## and ##suggestInput##. Notice the way we specify the selected value and the placeholder by passing parameters to the ##suggestInput## macro.</p>
330
331 {{code language="none"}}
332 {{velocity output="false"}}
333 #set ($countries = [
334 {'name': 'France', 'code': 'fr'},
335 {'name': 'Germany', 'code': 'de'},
336 {'name': 'Romania', 'code': 'ro'}
337 ])
338
339 #macro (countryPicker_displayOptions $selectedValues)
340 #foreach ($country in $countries)
341 <option value="$!escapetool.xml($country.code)"#if ($selectedValues.contains($country.code)) selected="selected"#end
342 >$!escapetool.xml($country.name)</option>
343 #end
344 #end
345 {{/velocity}}
346
347 {{velocity}}
348 {{html}}
349 #picker_import
Marius Dumitru Florea 89.1 350 #set ($discard = $xwiki.jsfx.use('uicomponents/suggest/xwiki.selectize.js'))
351 ## See https://tom-select.js.org/docs/
Marius Dumitru Florea 67.1 352 #set ($selectizeSettings = {})
353 #set ($suggestInputAttributes = {
354 'name': 'country',
355 'class': 'xwiki-selectize',
356 'data-xwiki-selectize': $selectizeSettings,
357 'value': 'ro',
358 'placeholder': 'Select the country'
359 })
360 #suggestInput($suggestInputAttributes 'countryPicker_displayOptions')
361 {{/html}}
362 {{/velocity}}
Sergiu Dumitriu 48.1 363 {{/code}}
Oana Florea 38.1 364
Marius Dumitru Florea 67.1 365 </div>
Buzila Vlad 52.1 366
Marius Dumitru Florea 67.1 367 <div role="tabpanel" class="tab-pane" id="staticDataV4">
368 <p>In this last version we make the code reusable by creating the ##countryPicker## and ##countryPicker_import## Velocity macros.</p>
Buzila Vlad 52.1 369
Marius Dumitru Florea 67.1 370 {{code language="none"}}
371 {{velocity output="false"}}
372 #set ($countries = [
373 {'name': 'France', 'code': 'fr'},
374 {'name': 'Germany', 'code': 'de'},
375 {'name': 'Romania', 'code': 'ro'}
376 ])
Buzila Vlad 52.1 377
Marius Dumitru Florea 67.1 378 #macro (countryPicker_displayOptions $selectedValues)
379 #foreach ($country in $countries)
380 <option value="$!escapetool.xml($country.code)"#if ($selectedValues.contains($country.code)) selected="selected"#end
381 >$!escapetool.xml($country.name)</option>
382 #end
383 #end
Buzila Vlad 52.1 384
Marius Dumitru Florea 67.1 385 #macro (countryPicker_import)
386 #picker_import
Marius Dumitru Florea 89.1 387 #set ($discard = $xwiki.jsfx.use('uicomponents/suggest/xwiki.selectize.js'))
Marius Dumitru Florea 67.1 388 #end
Buzila Vlad 52.1 389
Marius Dumitru Florea 67.1 390 #macro (countryPicker $parameters)
391 #countryPicker_import
392 #if ("$!parameters" == "")
393 #set ($parameters = {})
394 #end
395 #set ($discard = $parameters.put('class', "$!parameters.get('class') xwiki-selectize suggest-countries"))
396 #if (!$parameters.containsKey('placeholder'))
397 #set ($parameters.placeholder = 'Select the country')
398 #end
399 #suggestInput($parameters 'countryPicker_displayOptions')
400 #end
401 {{/velocity}}
Buzila Vlad 52.1 402
Marius Dumitru Florea 67.1 403 {{velocity}}
404 {{html}}
405 #set ($countryPickerParams = {
406 'name': 'country',
407 'value': 'ro'
408 })
409 #countryPicker($countryPickerParams)
410 {{/html}}
411 {{/velocity}}
Buzila Vlad 52.1 412 {{/code}}
413
Marius Dumitru Florea 67.1 414 </div>
415 </div>
416 </div>
417 {{/html}}
Buzila Vlad 52.1 418
Marius Dumitru Florea 67.1 419 === Suggest from Remote Data ===
Buzila Vlad 52.1 420
Marius Dumitru Florea 67.1 421 Most of the time you will want to retrive suggestions when the user types rather than loading all the suggestions on page load. Let's see how you can do this.
422
423 {{html wiki="true"}}
424 <div>
425 <ul class="nav nav-tabs" role="tablist">
426 <li role="presentation" class="active">
427 <a href="#remoteDataV1" aria-controls="remoteDataV1" role="tab" data-toggle="tab">V1: The Basics</a>
428 </li>
429 <li role="presentation">
430 <a href="#remoteDataV2" aria-controls="remoteDataV2" role="tab" data-toggle="tab">V2: Reusable Code</a>
431 </li>
432 </ul>
433
434 <div class="tab-content">
435 <div role="tabpanel" class="tab-pane active" id="remoteDataV1">
436 <p>In order to retrieve suggestions as you type you need to write some JavaScript code that makes an asynchronous HTTP request to retrive the data. You can put this code in a JavaScript Skin extension object. Then you need to load this JavaScript code on the page where you want to activate the suggest widget.</p>
437
438 {{code language="js"}}
439 require.config({
440 paths: {
Marius Dumitru Florea 89.1 441 'xwiki-selectize': "$xwiki.getSkinFile('uicomponents/suggest/xwiki.selectize.js')" +
Marius Dumitru Florea 67.1 442 "?v=$escapetool.url($xwiki.version)"
443 }
444 });
445
446 require(['jquery', 'xwiki-selectize'], function($) {
447 var settings = {
448 load: function(typedText, callback) {
449 $.getJSON('your/service/url', {
450 text: typedText
451 }).done(callback).fail(callback);
452 },
453 loadSelected: function(selectedValue, callback) {
454 $.getJSON('your/service/url', {
Marius Dumitru Florea 86.1 455 text: selectedValue,
Marius Dumitru Florea 67.1 456 exactMatch: true
457 }).done(callback).fail(callback);
Buzila Vlad 54.1 458 }
Marius Dumitru Florea 67.1 459 };
Buzila Vlad 52.1 460
Marius Dumitru Florea 67.1 461 $('.suggest-countries').xwikiSelectize(settings);
462 });
Buzila Vlad 52.1 463 {{/code}}
464
Marius Dumitru Florea 67.1 465 {{code language="none"}}
466 {{velocity}}
467 #set ($discard = $xwiki.jsx.use('Path.To.Your.JSX'))
468 {{/velocity}}
ElenaOanaTabaranu 1.1 469
Marius Dumitru Florea 67.1 470 {{html}}
471 <select class="suggest-countries">
472 <option value="">Select the country</option>
473 </select>
474 {{/html}}
475 {{/code}}
ElenaOanaTabaranu 1.1 476
Marius Dumitru Florea 67.1 477 </div>
Adel Atallah 58.1 478
Marius Dumitru Florea 67.1 479 <div role="tabpanel" class="tab-pane" id="remoteDataV2">
480 <p>In this last version we make the code reusable by creating a jQuery plugin and some helper Velocity macros.</p>
Adel Atallah 58.1 481
Marius Dumitru Florea 67.1 482 {{code language="js"}}
483 require.config({
484 paths: {
Marius Dumitru Florea 89.1 485 'xwiki-selectize': "$xwiki.getSkinFile('uicomponents/suggest/xwiki.selectize.js')" +
Marius Dumitru Florea 67.1 486 "?v=$escapetool.url($xwiki.version)"
487 }
488 });
Adel Atallah 58.1 489
Marius Dumitru Florea 67.1 490 define('xwiki-suggestCountries', ['jquery', 'xwiki-selectize'], function($) {
491 var getSettings = function(select) {
492 return {
493 load: function(typedText, callback) {
494 $.getJSON('your/service/url', {
495 text: typedText
496 }).done(callback).fail(callback);
497 },
498 loadSelected: function(selectedValue, callback) {
499 $.getJSON('your/service/url', {
Marius Dumitru Florea 86.1 500 text: selectedValue,
Marius Dumitru Florea 67.1 501 exactMatch: true
502 }).done(callback).fail(callback);
503 }
504 };
505 };
Adel Atallah 60.1 506
Marius Dumitru Florea 67.1 507 $.fn.suggestCountries = function(settings) {
508 return this.each(function() {
509 $(this).xwikiSelectize($.extend(getSettings($(this)), settings));
510 });
511 };
512 });
Adel Atallah 58.1 513
Marius Dumitru Florea 67.1 514 require(['jquery', 'xwiki-suggestCountries', 'xwiki-events-bridge'], function($) {
515 var init = function(event, data) {
516 var container = $((data && data.elements) || document);
517 container.find('.suggest-countries').suggestCountries();
518 };
Adel Atallah 58.1 519
Marius Dumitru Florea 67.1 520 $(document).on('xwiki:dom:loaded xwiki:dom:updated', init);
521 XWiki.domIsLoaded && init();
522 });
523 {{/code}}
Adel Atallah 66.1 524
Marius Dumitru Florea 67.1 525 {{code language="none"}}
526 {{velocity output="false"}}
527 #macro (countryPicker_import)
528 #picker_import
529 #set ($discard = $xwiki.jsx.use('Path.To.Your.JSX'))
530 #end
ElenaOanaTabaranu 1.1 531
Marius Dumitru Florea 67.1 532 #macro (countryPicker $parameters)
533 #countryPicker_import
534 #if ("$!parameters" == "")
535 #set ($parameters = {})
536 #end
537 #set ($discard = $parameters.put('class', "$!parameters.get('class') suggest-countries"))
538 #if (!$parameters.containsKey('placeholder'))
539 #set ($parameters.placeholder = 'Select the country')
540 #end
541 #suggestInput($parameters)
542 #end
543 {{/velocity}}
Oana Florea 36.1 544
Marius Dumitru Florea 67.1 545 {{velocity}}
546 {{html}}
547 #set ($countryPickerParams = {
548 'name': 'country',
549 'value': 'ro'
550 })
551 #countryPicker($countryPickerParams)
552 {{/html}}
553 {{/velocity}}
554 {{/code}}
Sergiu Dumitriu 48.1 555
Marius Dumitru Florea 67.1 556 </div>
557 </div>
558 </div>
559 {{/html}}
560
561 The remote data should have the following JSON format:
562
563 {{code language="js"}}
564 [
565 {
566 'label': '...',
567 'value': '...',
568 'url': '...',
569 'icon': {
570 'iconSetName': '...',
571 'iconSetType': 'IMAGE or FONT',
572 'cssClass': 'for font icons',
573 'url': 'for image icons'
574 },
575 'hint': '...'
576 },
577 ...
578 ]
579 {{/code}}

Get Connected