Import source for “1.7.1” from upstream tarball.
[debian_jquery-textcomplete.git] / doc / how_to_use.md
blob6c73dea53aebed185d34e32dbc6aaedcf87aaf54
1 How to use
2 ==========
4 jQuery MUST be loaded ahead.
6 ```html
7 <script src="path/to/jquery.js"></script>
8 <script src="path/to/jquery.textcomplete.js"></script>
9 ```
11 Then `jQuery.fn.textcomplete` is defined. The method MUST be called for textarea elements, contenteditable elements or `input[type="text"]`.
13 ```js
14 $('textarea').textcomplete(strategies, option);  // Recommended.
15 // $('[contenteditable="true"]').textcomplete(strategies, option);
16 // $('input[type="text"]').textcomplete(strategies, option);
17 ```
19 The `strategies` is an Array. Each element is called as strategy object.
21 ```js
22 var strategies = [
23   // There are two strategies.
24   strategy,
25   { /* the other strategy */ }
27 ```
29 The `strategy` is an Object which MUST have `match`, `search` and `replace` and MAY have `index`, `template`, `cache`, `context` and `idProperty`.
31 ```js
32 var strategy = {
33   // Required
34   match:      matchRegExpOrFunc,
35   search:     searchFunc,
36   replace:    replaceFunc,
38   // Optional                 // Default
39   cache:      cacheBoolean,   // false
40   context:    contextFunc,    // function (text) { return true; }
41   id:         idString,       // null
42   idProperty: idPropertyStr,  // null
43   index:      indexNumber,    // 2
44   template:   templateFunc,   // function (value) { return value; }
46 ```
48 The `matchRegExpOrFunc` MUST be a RegExp or a Function which returns a RegExp.
49 And `indexNumber` and `contextFunc` MUST be a Number and a Function respectively.
51 `contextFunc` is called with the current value of the target textarea and it works as a preprocessor. When it returns `false`, the strategy is skipped. When it returns a String, `matchRegExpOrFunc` tests the returned string.
53 `matchRegExpOrFunc` MUST contain capturing groups and SHOULD end with `$`. The word captured by `indexNumber`-th group is going to be the `term` argument of `searchFunc`. `indexNumber` defaults to 2.
55 ```js
56 // Detect the word starting with '@' as a query term.
57 var matchRegExpOrFunc = /(^|\s)@(\w*)$/;
58 var indexNumber = 2;
59 // Normalizing the input text.
60 var contextFunc = function (text) { return text.toLowerCase(); };
61 ```
63 The `searchFunc` MUST be a Function which gets two arguments, `term` and `callback`. It MAY have the third argument `match` which is the result of regexp matching. It MUST invoke `callback` with an Array. It is guaranteed that the function will be invoked exclusively even though it contains async call.
65 If you want to execute `callback` multiple times per a search, you SHOULD give `true` to the second argument while additional execution remains. This is useful to use data located at both local and remote. Note that you MUST invoke `callback` without truthy second argument at least once per a search.
67 The `cacheBoolean` MUST be a Boolean. It defaults to `false`. If it is `true` the `searchFunc` will be memoized by `term` argument. This is useful to prevent excessive API access.
69 TextComplete automatically make the dropdown unique when the callbacked array consists of Strings. If it consists of Objects and the dropdown should be unique, use `idPropertyStr` for teaching the specified property is good to identify each elements.
71 ```js
72 var searchFunc = function (term, callback, match) {
73   // term === match[indexNumber]
74   callback(cache[term], true); // Show local cache immediately.
76   $.getJSON('/search', { q: term })
77     .done(function (resp) {
78       callback(resp); // `resp` must be an Array
79     })
80     .fail(function () {
81       callback([]); // Callback must be invoked even if something went wrong.
82     });
84 ```
86 The `templateFunc` MUST be a Function which returns a string. The function is going to be called as an iterator for the array given to the `callback` of `searchFunc`. You can change the style of each dropdown item.
88 ```js
89 var templateFunc = function (value, term) {
90   // `value` is an element of array callbacked by searchFunc.
91   return '<b>' + value + '</b>';
93 // Default:
94 //   templateFunc = function (value) { return value; };
95 ```
97 The `replaceFunc` MUST be a Function which returns a String, an Array of two Strings or `undefined`. It is invoked when a user will click and select an item of autocomplete dropdown.
99 ```js
100 var replaceFunc = function (value, event) { return '$1@' + value + ' '; };
103 The result is going to be used to replace the value of textarea using `String.prototype.replace` with `matchRegExpOrFunc`:
105 ```js
106 textarea.value = textarea.value.replace(matchRegExpOrFunc, replaceFunc(value, event));
109 Suppose you want to do autocomplete for HTML elements, you may want to reposition the cursor in the middle of elements after the autocomplete. In this case, you can do that by making `replaceFunc` return an Array of two Strings. Then the cursor points between these two strings.
111 ```js
112 var replaceFunc = function (value) {
113   return ['$1<' + value + '>', '</' + value + '>'];
117 If `undefined` is returned from a `replaceFunc`, textcomplete does not replace the text.
119 If `idString` is given, textcomplete sets the value as `data-strategy` attribute of the dropdown element. You can change dropdown style by using the property.
121 The `option` is an optional Object which MAY have `appendTo`, `height` , `maxCount`, `placement`, `header`, `footer`, `zIndex`, `debounce` and `onKeydown`. If `appendTo` is given, the element of dropdown is appended into the specified element. If `height` is given, the dropdown element's height will be fixed.
123 ```js
124 var option = {
125   adapter:           adapterClass,              // undefined
126   appendTo:          appendToString,            // 'body'
127   className:         classNameStr,              // DEPRECATED ''
128   debounce:          debounceNumber,            // undefined
129   dropdownClassName: dropdownClassNameStr,      // 'dropdown-menu textcomplete-dropdown'
130   footer:            footerStrOrFunc,           // undefined
131   header:            headerStrOrFunc,           // undefined
132   height:            heightNumber,              // undefined
133   maxCount:          maxCountNumber,            // 10
134   noResultsMessage:  noResultsMessageStrOrFunc, // undefined
135   onKeydown:         onKeydownFunc,             // undefined
136   placement:         placementStr,              // ''
137   rightEdgeOffset:   rightEdgeOffsetInteger,    // 30
138   zIndex:            zIndexStr,                 // '100'
142 The `maxCountNumber` MUST be a Number and default to 10. Even if `searchFunc` callbacks with large array, the array will be truncated into `maxCountNumber` elements.
144 If `placementStr` includes 'top', it positions the drop-down to above the caret. If `placementStr` includes 'absleft' and 'absright', it positions the drop-down absolutely to the very left and right respectively. You can mix them.
146 You can override the z-index property and the class attribute of dropdown element using `zIndex` and `dropdownClassName` option respectively.
148 If you want to add some additional keyboard shortcut, set a function to `onKeydown` option. The function will be called with two arguments, the keydown event and commands hash.
150 ```js
151 var onKeydownFunc = function (e, commands) {
152   // `commands` has `KEY_UP`, `KEY_DOWN`, `KEY_ENTER`, `KEY_PAGEUP`, `KEY_PAGEDOWN`,
153   // `KEY_ESCAPE` and `SKIP_DEFAULT`.
154   if (e.ctrlKey && e.keyCode === 74) {
155     // Treat CTRL-J as enter key.
156     return commands.KEY_ENTER;
157   }
158   // If the function does not return a result or undefined is returned,
159   // the plugin uses default behavior.
163 Textcomplete debounces `debounceNumber` milliseconds, so `searchFunc` is not called until user stops typing.
165 ```js
166 var placementStr = 'top|absleft';
169 If you want to use textcomplete with a rich editor, please write an adapter for it and give the adapter as `adapterClass`.
171 Finally, if you want to stop autocompleting, give `'destroy'` to `textcomplete` method as follows:
173 ```js
174 $('textarea').textcomplete('destroy');
177 Example
178 -------
180 ```js
181 $('textarea').textcomplete([
182   { // mention strategy
183     match: /(^|\s)@(\w*)$/,
184     search: function (term, callback) {
185       callback(cache[term], true);
186       $.getJSON('/search', { q: term })
187         .done(function (resp) { callback(resp); })
188         .fail(function ()     { callback([]);   });
189     },
190     replace: function (value) {
191       return '$1@' + value + ' ';
192     },
193     cache: true
194   },
195   { // emoji strategy
196     match: /(^|\s):(\w*)$/,
197     search: function (term, callback) {
198       var regexp = new RegExp('^' + term);
199       callback($.grep(emojies, function (emoji) {
200         return regexp.test(emoji);
201       }));
202     },
203     replace: function (value) {
204       return '$1:' + value + ': ';
205     }
206   }
207 ], { maxCount: 20, debounce: 500 });