8000 Merge pull request #387 from mauromascarenhas/autocomplete-function · materializecss/materialize@3dcfae8 · GitHub
Skip to content

Commit 3dcfae8

Browse files
authored
Merge pull request #387 from mauromascarenhas/autocomplete-function
Replacement for standard search function in autocomplete
2 parents 807d65b + 0752834 commit 3dcfae8

File tree

2 files changed

+54
-22
lines changed

2 files changed

+54
-22
lines changed

pug/contents/autocomplete_content.html

+42-11
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,38 @@
5151

5252
<div id="initialization" class="scrollspy section">
5353
<h3 class="header">Initialization</h3>
54-
<p>The data is a json object where the key is the matching string and the value is an optional image url.</p>
55-
<p>The key must be a text string. If you trust your data, or have properly sanitized your user input, you may
56-
use HTML by setting the option <code class="language-javascript">allowUnsafeHTML: true</code>.</p>
54+
<p>The data is an array of option objects, which supports three different attributes:</p>
55+
<p>
56+
<ul class="collection">
57+
<li class="collection-item">
58+
<p style="margin: 0;">
59+
<b>id</b>: This is the only mandatory attribute: it must be a primitive value that can be
60+
converted to string. If "text" is not provided, it will also be used as "option text" as well;
61+
</p>
62+
</li>
63+
<li class="collection-item">
64+
<p style="margin: 0;">
65+
<b>text</b>: This optional attribute is used as "display value" for the current entry.
66+
When provided, it will also be taken into consideration by the standard search function.
67+
</p>
68+
<P style="margin: 0;">
69+
If you trust your data or have properly sanitized your user input, you may use
70+
use HTML by setting the option <code class="language-javascript">allowUnsafeHTML: true</code>;
71+
</P>
72+
</li>
73+
<li class="collection-item">
74+
<p style="margin: 0;">
75+
<b>image</b>: This optional attribute is used to provide a valid image URL to the current option.
76+
This attribute is ignored by the standard search function.
77+
</p>
78+
</li>
79+
</ul>
80+
</p>
81+
<p>
82+
You may also provide additional attributes to an option object but they will not be taken into
83+
consideration by the standard search function. If you want to use them for option filtering, you
84+
must specify a custom function in "<b>onSearch</b>" option.
85+
</p>
5786
<pre style="padding-top: 0px;">
5887
<span class="copyMessage">Copied!</span>
5988
<i class="material-icons copyButton">content_copy</i>
@@ -99,7 +128,8 @@ <h3 class="header">Initialization</h3>
99128
{id: 13, text: "Microsoft"},
100129
{id: 42, text: "Google", image: 'http://placehold.it/250x250'}
101130
],
102-
onSearch: function(text, autocomplete) {
131+
// This search function considers every object entry as "search values".
132+
onSearch: (text, autocomplete) => {
103133
const filteredData = autocomplete.options.data.filter(item => {
104134
return Object.keys(item)
105135
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
@@ -188,13 +218,14 @@ <h5 class="method-header">
188218
<span class="copyMessage">Copied!</span>
189219
<i class="material-icons copyButton">content_copy</i>
190220
<code class="language-javascript copiedText">
191-
onSearch: function(text, autocomplete) {
192-
const filteredData = autocomplete.options.data.filter(item => {
193-
return Object.keys(item)
194-
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
195-
.some(isMatch => isMatch);< 7D55 /div>
196-
});
197-
autocomplete.setMenuItems(filteredData);
221+
onSearch: (text, autocomplete) => {
222+
const normSearch = text.toLocaleLowerCase();
223+
autocomplete.setMenuItems(
224+
autocomplete.options.data.filter((option) =>
225+
option.id.toString().toLocaleLowerCase().includes(normSearch)
226+
|| option.text?.toLocaleLowerCase().includes(normSearch)
227+
)
228+
);
198229
}
199230
</code>
200231
</pre>

src/autocomplete.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ let _defaults = {
1313
},
1414
minLength: 1, // Min characters before autocomplete starts
1515
isMultiSelect: false,
16-
onSearch: function(text, autocomplete) {
17-
const filteredData = autocomplete.options.data.filter(item => {
18-
return Object.keys(item)
19-
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
20-
.some(isMatch => isMatch);
21-
});
22-
autocomplete.setMenuItems(filteredData);
16+
onSearch: (text: string, autocomplete) => {
17+
const normSearch = text.toLocaleLowerCase();
18+
autocomplete.setMenuItems(
19+
autocomplete.options.data.filter((option) =>
20+
option.id.toString().toLocaleLowerCase().includes(normSearch)
21+
|| option.text?.toLocaleLowerCase().includes(normSearch)
22+
)
23+
);
2324
},
2425
maxDropDownHeight: '300px',
2526
allowUnsafeHTML: false
@@ -175,7 +176,7 @@ export class Autocomplete extends Component {
175176
_handleInputKeyupAndFocus = (e: KeyboardEvent) => {
176177
if (e.type === 'keyup') Autocomplete._keydown = false;
177178
this.count = 0;
178-
const actualValue = this.el.value.toLowerCase();
179+
const actualValue = this.el.value.toLocaleLowerCase();
179180
// Don't capture enter or arrow key usage.
180181
if (M.keys.ENTER.includes(e.key) || M.keys.ARROW_UP.includes(e.key) || M.keys.ARROW_DOWN.includes(e.key)) return;
181182
// Check if the input isn't empty
@@ -254,7 +255,7 @@ export class Autocomplete extends Component {
254255
}
255256

256257
_highlightPartialText(input, label) {
257-
const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
258+
const start = label.toLocaleLowerCase().indexOf('' + input.toLocaleLowerCase() + '');
258259
const end = start + input.length - 1;
259260
//custom filters may return results where the string does not match any part
260261
if (start == -1 || end == -1) {
@@ -288,7 +289,7 @@ export class Autocomplete extends Component {
288289
}
289290

290291
// Text
291-
const inputText = this.el.value.toLowerCase();
292+
const inputText = this.el.value.toLocaleLowerCase();
292293
const parts = this._highlightPartialText(inputText, (entry.text || entry.id).toString());
293294
const div = document.createElement('div');
294295
div.setAttribute('style', 'line-height:1.2;font-weight:500;');
@@ -378,7 +379,7 @@ export class Autocomplete extends Component {
378379
}
379380

380381
open() {
381-
const inputText = this.el.value.toLowerCase();
382+
const inputText = this.el.value.toLocaleLowerCase();
382383
this._resetAutocomplete();
383384
if (inputText.length >= this.options.minLength) {
384385
this.isOpen = true;

0 commit comments

Comments
 (0)