kraaden / autocomplete Goto Github PK
View Code? Open in Web Editor NEWBlazing fast and lightweight autocomplete widget without dependencies. Only 1KB gzipped. Demo:
Home Page: https://smartscheduling.com/en/documentation/autocomplete
Blazing fast and lightweight autocomplete widget without dependencies. Only 1KB gzipped. Demo:
Home Page: https://smartscheduling.com/en/documentation/autocomplete
Could you expose the search input along with the item in the render
function? That way I can use a replace function to wrap the matching text in a div to highlight it.
Thank you.
I can't figure out if it is possible to declare a custom container, such as:
autocomplete({
debounceWaitMs: 150,
input: document.getElementById("product-search"),
container: document.getElementById("search-dropdown"),
// ...
and
<label class="input-group-field">Search for product names, numbers
<input id="product-search" type="search" placeholder="Search for product names, numbers">
</label>
<ol id="search-dropdown"></ol>
But it would be really nice if there was. Is there?
Will really appreciate if new version will be tagged in git with version number.
In some cases (like FF extensions) link onto exact code is needed (see How to determine the third-party library link), tags will help to provide a link onto exact version.
Autocomplete closing when clicking scrollbar in Internet Explorer, but this issue can't be replicated in Chrome.
Device: Apple iPhone 5 32Gb MD295LL/A
Browser Safari, user agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_4 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G61 Safari/602.1
The bug is related to incorrect calculation of css properties top. At the same time, if you change css position c fixed to absolute, then autocomplete will appear in the right place.
Hi
I want to show all suggestions when the input is focused. without further input by the user.
Is there already a way to trigger autocomplete
manually or any option to set like setting minLength: 0
?
Thank you.
After selecting an item or having characters in the input below the threshold should destroy the div.autocomplete
container. It messes styling involving shadows and/or rgba colors because of the stack of divs
With an increasing number of items (e.g. +50), navigating through the items with the keyboard (↑ and ↓) seems to get slower and slower.
Do you experience the same issue?
Thanks a lot in advance!
Great autocomplete! It works well. One thing which is problematic for me though is the style attributes given to the autocomplete div when it opens, namely, the restriction of the dropdown's width to the offsetwidth of the input.
For addresses and similar, this results in very long, crushed up text in the autocomplete results.
It would be great if there were a way to override this restriction.
Is there a way to trigger the update programmatically?
When resizing the window (e.G. switching from landscape into portrait mode) the autocomplete will trigger the update
function.
This is ok so far, because maybe you would have to re-calculate the position if the search input has different styles. But if you have nothing entered yet, so the autocomplete-list is not visible, it will show the list with AutocompleteSettings.emptyMsg
.
You can reproduce this when going to https://kraaden.github.io/autocomplete/ and just grab the window and resize it. The message will appear, even you've never started to type anything before.
The "easiest" way would be to introduce a new function which behaves like following:
function updateOnResize(): boolean {
if(!containerDisplayed()){
return false;
}
update();
return true;
}
Additionally you've to update window.removeEventListener("resize", updateOnResize);
and window.addEventListener("resize", updateOnResize);
according to the new function.
Hi,
Ag-Grid seems to be a pretty bad way to enter new data to the grid. I am trying to implement a way for a user to either select an option from the autocomplete and that will automatically fill the rest of the pinned row columns with that specific items other values. Now there should also be an option for creating a completely new item so it would go like this: User types a name and maybe clicks the next row. How can I actually 'save' this free text now? Also Tab triggers both onFreeTextSelect AND onSelect, i guess there is a way to around this problem. Enter would select the free text / selection but enter also creates a new row from the data in the pinned row so that's a problem as well.
The example just only alert. Not complete. This just show a suggest list. Please update the example so that the selected item will complete the input.
Thanks!
If you set minLength to 1 instead of 2 (the default), there is an unnecessary fetch for the first character of the search term. The first fetch should be fired after debounceWaitMs milliseconds, but there is an immediate fetch for the first character.
The issue probably has to be somewhere between line 392 and line 404:
https://github.com/kraaden/autocomplete/blob/master/autocomplete.ts#L392
Strangely that first fetch doesn't happen with minLength=2. I'm not sure why, but probably you know that code better than I do :)
This would really help when we're working with models coming from the server. I have to either add the label and group properties to my back-end model solely for the autocomplete (which the server shouldn't really know about) or I have to do the same on the front-end or extend the TS class with the AutocompleteClient
- which forces me to use a different model than my usual.
I know in JavaScript you can use a object["propertyName"]
syntax to get properties so enabling us to configure their name shouldn't be too difficult.
It would really help improve code maintainability.
I updated the npm dependency to the latest version (5.1.3), and the plugin stopped working.
When I am debugging autocomplete.js I see that this expression always evaluates to false: keypressCounter === savedKeypressCounter
in the "startFetch" function.
This is how we are setting up our autocomplete:
const input = document.getElementById('product');
const products = getProducts();
if (products.length && !!input) {
autocomplete({
input: input,
fetch: (text, update) => {
text = text.toLowerCase();
const suggestions = products.filter(n => n.label.toLowerCase().startsWith(text));
update(suggestions);
},
onSelect: ({ label }) => {
input.value = label;
},
minLength: 1,
emptyMsg: 'No matches'
});
}
What are we doing wrong?
This was tested on mac os v10.13.6 on a chrome Version 78.0.3904.70 (Official Build) (64-bit)
Using webjars in a java project, I've deployed the npm project on webjars, but it doesn't contain any minified files.
Please add minification to rollup build.
Since body.scrollTop doesn't work in strict mode. The autocomplete shows up in the wrong place.
There is a need to show\hide autocomplete panel outside of it - for instance, there maybe history button that will autocomplete panel.
Maybe two more functions can be added, something like:
function show() {
startFetch(1);
}
function hide() {
clear();
}
...
return {
destroy: destroy,
show: show,
hide: hide,
};
My data object has extra properties such as id
and value
that I would like to add to the input when the onSelect fires.
I think adding this would help with many use cases.
Looking through the source there doesn't seem to be any effort to debounce/throttle calls to the fetch() method. It would be great if an optional debounce in milliseconds could be passed as a config option. It's nice to have for ajax requests so a remote request isn't fired on every keystroke.
P.S.
Thanks for making autocomplete, it's great!
When selecting an element with arrow keys, autocomplete re renders the complete div which causes a flickering of images I have rendered in the autocomplete view. And causes an unnecessary re fetch of that images.
If I have a basic tsconfig.json like:
{
"include": [
"src/index.ts"
]
}
And import as described in your readme:
import autocomplete from "autocompleter";
console.log(autocomplete); // undefined
It doesn't work, "autocomplete" is undefined. It works fine if I set esModuleInterop to true in tsconfig.json. I can also use require instead of import as mentioned here.
I think it would be worth adding an explanation to your README to make it easier for typescript users of your library.
P.S I have just started using this and it seems to work well so thanks.
I ran in to an issue today and tracked it down to (I think!) the way scrollEventHandler is being fired.
Issue:
With overflow: auto
set for the .autocomplete
container and the first item in the list automatically selected/highlighted when autocomplete first opens with suggestions (as per default behavior), you cannot then use the mouse to scroll the container's scrollbar to browse other items. updateScroll()
prevents this due to this piece of code:
if (element.offsetTop < container.scrollTop) { container.scrollTop = element.offsetTop; }
To reproduce the issue, simply resize the browser window so the autocomplete container doesn't have enough vertical space to display all of its child items/suggestions (and thus overflows with a scroll bar). If the first suggestion is selected, scrolling down with the mouse will not work. If you use the keyboard up/down buttons to move through the list, you will find scrolling will work again until the newly selected/highlighted suggestion reaches the top or bottom of the container.
Why is this happening?
I think it may be because of how the scroll event is being bound:
doc.addEventListener("scroll", scrollEventHandler, true);
Passing true
(i.e. putting it in capture mode) causes scrollEventHandler()
to fire first and intercept the scroll action of the autocomplete container. This then in turn triggers a full rebuild of the autocomplete container, ending in a call to updateScroll()
which blocks the scroll.
Maybe a fix would be to turn off capture mode for the main scroll event listener (i.e. pass false
as last arg) and also prevent scroll events from the autocomplete container from bubbling up?
Alternatively, maybe scrollEventHandler() can inspect the call site of the event and, if it originated from the autocomplete container element, simply discard it rather than triggering an update.
Hi!
Mac OS X offers some keyboard shortcuts that acts like ↑
and ↓
keys:
control
+ p
acts like ↑
control
+ n
acts like ↓
It's a native shortcut, so I'm able to replace the arrow keys with their control
shortcut equivalent on every app. When I'm typing a website address on Google Chrome, I used to press control
+ ↓
or ↑
to navigate through the suggestions.
Could you support those two shortcuts too? Even under a settings flag like macShortcuts: true
.
Hi, I'm trying to allow users to press enter to search the text inside their input but because of the code block below, it get's triggered by another addEventListener
registering the item as selected:
if (keyCode === 13 /* Enter */) {
if (selected) {
settings.onSelect(selected, input);
clear();
}
if (preventSubmit) {
ev.preventDefault();
}
}
It would be great if you could add a config option to disable this Select on Enter functionality from happening.
Cheers,
Spike
On iOS 13.5 searching and then dismissing the keyboard to scroll in the results will cause the results to disappear. It would be very good if they stayed
In the example data:
var countries = [
{label: 'United Kingdom', item: 'UK'},
{label: 'United States', item: 'US'}
];
but what if I need something more complicated?
var data = [
{id: 8, name: 'some item name', title: 'some title', img: 'some image link', data: ['some linked data']}
];
on click onSelect
will not give me the access to this data
it will give me nothing at all as it only works with property item
and there is no such property
I would like to add a class to the body element when the autocomplete container is attached to the dom. It would be very convenient when there is an option for custom onAttach and onDetach callbacks (which are called in attach() resp. detach()).
Since last version i'm getting this error when and can't initialize the autocomplete as it says that it's not a function. basic reproduction below
Hi, just that. I'm tring to use in a Laravel 5.3 project and it's dons't work. It's use webpack to compile the js
There are two container height bugs caused by this line in the updatePosition()
function:
containerStyle.maxHeight = (window.innerHeight - top) + "px";
Bug 1:
top
accounts for scrollTop but window.innerHeight
does not. This means if the input element autocomplete is attached to is below the fold of the page, maxHeight
is never set by the browser as the value is negative. Note: I'm not sure if this is a true bug or intentional behaviour.
Bug 2 (more important):
If the input element that autocomplete is attached to happens to be right on the lower edge of the viewport, maxHeight is set and ends up clipping the suggestions container to a tiny px value (e.g. 1 or 2 px high).
We discovered the above issues when a user with an unusual screen resolution (1920x1200) complained that the suggestions were not displaying correctly. It turns out that because of Bug 1 above, we had not noticed anything strange on our 1920x10180 monitors (because the input was off screen and maxHeight never got applied). On his screen the input was right at the lower edge of the viewport and so suggestions were being clipped to a height of 2px.
The fix is easy:
Get the height of the container and correctly account for scrollTop.
Revised updatePosition()
could look something like this:
function updatePosition() {
if (!containerDisplayed()) {
return;
}
containerStyle.height = "auto";
containerStyle.width = input.offsetWidth + "px";
var docEl = doc.documentElement;
var clientTop = docEl.clientTop || doc.body.clientTop || 0;
var clientLeft = docEl.clientLeft || doc.body.clientLeft || 0;
var scrollTop = window.pageYOffset || docEl.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft;
function calc() {
var inputRect = input.getBoundingClientRect();
var top = inputRect.top + input.offsetHeight + scrollTop - clientTop;
var left = inputRect.left + scrollLeft - clientLeft;
var height = container.getBoundingClientRect().height;
containerStyle.top = top + "px";
containerStyle.left = left + "px";
if ((((scrollTop + window.innerHeight) - (top + height)) < 1) && (clipHeight > 0)) {
// clip container to height needed to keep it in viewport (but make sure clipped height is no less than `clipHeight`)
var difference = (top + height) - (scrollTop + window.innerHeight);
containerStyle.maxHeight = ((height - difference) > clipHeight) ? height - difference + 'px' : clipHeight + 'px';
}
}
// we need to recalculate layout twice, because sometimes it will return an invalid value for inputRect.left on the first call
calc();
calc();
}
And then add:
var clipHeight = settings.clipHeight || 0;
to autocomplete()
function (which preserves the previous behaviour but gives users the option to apply a minimum maxHeight on containers that spill out below the viewport).
Please, how can I do a search in the middle of the word? ex: label is United Kingdom and enter only 'ing' and Sorry for English ;)
Hi.
Because of this line in the keyup
function:
if (keypressCounter === savedKeypressCounter && elements) {
If elements
is an empty array (which evaluates to true in javascript), the update()
function is called. If elements
is false (i.e. developer chooses to ignore the current documentation and passes false as parameter to the fetch callback), update()
is not called.
This is actually quite nice as it gives the developer a choice of what to do in the situation where e.g. they are using ajax to power the autocomplete suggestions and a user types the beginning of a place name, ajax returns with some results and user keeps on typing. In this case, if another ajax request is fired but this time no results come back, the developer can decide whether to pass an empty array in the fetch calback (thus closing the suggestions) or pass false
(which would keep the suggestions open from the first ajax result).
I am using the above technique at the moment and it is actually quite useful. Maybe the documentation for fetch
should mention this possibility so others can benefit?
In my use case i want only that user choose value from the list. and dissalow him for entering another value or text. Other saying, i want only to text to be only fill using on select event.
When pressing the enter key to select, the form is being submitted.
The only way I can select an item is using the mouse. How can I select on enter?
Also, would be nice to select on "tab". Eg.: use arrow keys to select and press tab.
With that you can catch the event, for example when 'enter' is pressed you could add some custom logic in that case.
Hi, first thanks for awesome library.
Can you provide me with a simple example to use the library with Angular 7 and use HttpRequest to fetch the data ?
Regards
When you close keyboard in iOS with done, autocomplete also closes (focus out event?). Would like to have an option keep autocomplete still open, to scroll around in long list of choices - without keyboard taking up half the screen.
Is there any reason why using the website's example which outputs html in this way, is not showing the actual bold fonts inside the tags ?
<div class=" selected"><strong>Colo</strong>mbia</div>
What I see is only regular font text even if there's a part of it inside the strong tag
I also am using the autocomplete.css and everything seems to be as in the example.
The min-height
and height
attributes are causing autocomplete pop-up background to be not correctly sized under both mobile and desktop Chrome, so whenever user scrolls the page, the items at the bottom of the list would appear without a background.
In my case the solution was to remove autocomplete.ts:138 and autocomplete.ts:139.
Re-rendering by pressing the up and down buttons
https://drive.google.com/file/d/1rnIz_Cv-xK7wmXnrOs2D8whFlBRcITHS/view?usp=sharing
Hi,
The function 'startFetch' ignores the input parameter 'trigger'. As a result, when the 'focusEventHandler' is invoked, EventTrigger.Focus is not passed to the fetch.
Line number:
https://github.com/kraaden/autocomplete/blob/3bd03c2fd7caa35a6cab5d08043bb6b71eb49b6a/autocomplete.ts#L444
Thanks!
When long pressing an autocomplete item it hides the autocomplete entirely, and it won't trigger the onSelect
method.
Just test https://kraaden.github.io/autocomplete/ on iPhone.
When you scroll up, autocomplete overlaps the input and goes up to the screen.
Hi again (sorry for bugging you so much lately)!
I bumped in to a bug tonight with the way autocomplete handles ignored keys in the keyup()
func.
The problem is the position of this line: var savedKeypressCounter = ++keypressCounter;
savedKeypressCounter
and keypressCounter
get incremented before the ignored keys and down key checks are performed. If keyup()
returns early as a result of one of these checks being positive, the callback function passed to fetch
reads an earlier value of savedKeypressCounter
causing the if (keypressCounter === savedKeypressCounter && elements)
check to fail (since savedKeypressCounter
is local to the keyup()
func and its earlier value is no longer in sync with the current value of keypressCounter
, which is a global var).
To see this bug in action, you simply need to enter some text in the input field while holding down the SHIFT key (e.g. imagine the input field was for entering airport three letter codes, some people like to enter these in upper case and use SHIFT to do it rather than caps lock). In this case fetch
fires but no results are shown as update()
is never called by the callback function.
The fix seems easy: simply move the line that increments saveKeypressCounter
and keypressCounter
BELOW the ignored keys and down key checks. Basically, place var savedKeypressCounter = ++keypressCounter;
directly after:
if (keyCode === 40 /* Down */ && containerDisplayed()) { return; }
Hi,would this work inside a textarea?
for example to be used to call users mention github style with the @username
Let me know your thoughts.
When i try to use autocompte i get the error input undefined
I am using this library in an Angular Project and it's using the typescript file. Is possible to generate a source map for this as when something goes bad on Angular, it's pointing me to the export line of autocomplete.
Thanks
While trying out the customize snippet in the readme, I observed that it not work on smaller screen resolutions (or resizing your browser window), The autocomplete container shows up floating above the input.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.