Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replacement for standard search function in autocomplete #387

Merged
merged 2 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 42 additions & 11 deletions pug/contents/autocomplete_content.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,38 @@

<div id="initialization" class="scrollspy section">
<h3 class="header">Initialization</h3>
<p>The data is a json object where the key is the matching string and the value is an optional image url.</p>
<p>The key must be a text string. If you trust your data, or have properly sanitized your user input, you may
use HTML by setting the option <code class="language-javascript">allowUnsafeHTML: true</code>.</p>
<p>The data is an array of option objects, which supports three different attributes:</p>
<p>
<ul class="collection">
<li class="collection-item">
<p style="margin: 0;">
<b>id</b>: This is the only mandatory attribute: it must be a primitive value that can be
converted to string. If "text" is not provided, it will also be used as "option text" as well;
</p>
</li>
<li class="collection-item">
<p style="margin: 0;">
<b>text</b>: This optional attribute is used as "display value" for the current entry.
When provided, it will also be taken into consideration by the standard search function.
</p>
<P style="margin: 0;">
If you trust your data or have properly sanitized your user input, you may use
use HTML by setting the option <code class="language-javascript">allowUnsafeHTML: true</code>;
</P>
</li>
<li class="collection-item">
<p style="margin: 0;">
<b>image</b>: This optional attribute is used to provide a valid image URL to the current option.
This attribute is ignored by the standard search function.
</p>
</li>
</ul>
</p>
<p>
You may also provide additional attributes to an option object but they will not be taken into
consideration by the standard search function. If you want to use them for option filtering, you
must specify a custom function in "<b>onSearch</b>" option.
</p>
<pre style="padding-top: 0px;">
<span class="copyMessage">Copied!</span>
<i class="material-icons copyButton">content_copy</i>
Expand Down Expand Up @@ -99,7 +128,8 @@ <h3 class="header">Initialization</h3>
{id: 13, text: "Microsoft"},
{id: 42, text: "Google", image: 'http://placehold.it/250x250'}
],
onSearch: function(text, autocomplete) {
// This search function considers every object entry as "search values".
onSearch: (text, autocomplete) => {
const filteredData = autocomplete.options.data.filter(item => {
return Object.keys(item)
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
Expand Down Expand Up @@ -188,13 +218,14 @@ <h5 class="method-header">
<span class="copyMessage">Copied!</span>
<i class="material-icons copyButton">content_copy</i>
<code class="language-javascript copiedText">
onSearch: function(text, autocomplete) {
const filteredData = autocomplete.options.data.filter(item => {
return Object.keys(item)
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
.some(isMatch => isMatch);
});
autocomplete.setMenuItems(filteredData);
onSearch: (text, autocomplete) => {
const normSearch = text.toLocaleLowerCase();
autocomplete.setMenuItems(
autocomplete.options.data.filter((option) =>
option.id.toString().toLocaleLowerCase().includes(normSearch)
|| option.text?.toLocaleLowerCase().includes(normSearch)
)
);
}
</code>
</pre>
Expand Down
23 changes: 12 additions & 11 deletions src/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ let _defaults = {
},
minLength: 1, // Min characters before autocomplete starts
isMultiSelect: false,
onSearch: function(text, autocomplete) {
const filteredData = autocomplete.options.data.filter(item => {
return Object.keys(item)
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
.some(isMatch => isMatch);
});
autocomplete.setMenuItems(filteredData);
onSearch: (text: string, autocomplete) => {
const normSearch = text.toLocaleLowerCase();
autocomplete.setMenuItems(
autocomplete.options.data.filter((option) =>
option.id.toString().toLocaleLowerCase().includes(normSearch)
|| option.text?.toLocaleLowerCase().includes(normSearch)
)
);
},
maxDropDownHeight: '300px',
allowUnsafeHTML: false
Expand Down Expand Up @@ -175,7 +176,7 @@ export class Autocomplete extends Component {
_handleInputKeyupAndFocus = (e: KeyboardEvent) => {
if (e.type === 'keyup') Autocomplete._keydown = false;
this.count = 0;
const actualValue = this.el.value.toLowerCase();
const actualValue = this.el.value.toLocaleLowerCase();
// Don't capture enter or arrow key usage.
if (M.keys.ENTER.includes(e.key) || M.keys.ARROW_UP.includes(e.key) || M.keys.ARROW_DOWN.includes(e.key)) return;
// Check if the input isn't empty
Expand Down Expand Up @@ -254,7 +255,7 @@ export class Autocomplete extends Component {
}

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

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

open() {
const inputText = this.el.value.toLowerCase();
const inputText = this.el.value.toLocaleLowerCase();
this._resetAutocomplete();
if (inputText.length >= this.options.minLength) {
this.isOpen = true;
Expand Down