Giter Site home page Giter Site logo

kraaden / autocomplete Goto Github PK

View Code? Open in Web Editor NEW
448.0 7.0 87.0 573 KB

Blazing fast and lightweight autocomplete widget without dependencies. Only 1KB gzipped. Demo:

Home Page: https://smartscheduling.com/en/documentation/autocomplete

TypeScript 92.25% JavaScript 4.87% CSS 2.14% HTML 0.74%
autocomplete typescript javascript vanilla-js typeahead dropdown suggestions widget component input

autocomplete's Issues

Rollup minify

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.

Autocomplete div destruction

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

show all suggestions on focus

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.

Documentation suggestion

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?

Autocomplete closing when dismissing keyboard in IOS

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.

Question: Bold <strong> tags

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.

Resize will show "AutocompleteSettings.emptyMsg"

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.

Allow customisation / unrestrict suggestions width

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.

Do search in my word

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 ;)

Enable configuring of the name of the 'label' and 'group' properties

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.

Viewport boundary bugs with updatePosition()

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).

Trigger update

Is there a way to trigger the update programmatically?

Allow any text and click select another cell

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 bug is related to incorrect calculation of css properties top.

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.

image

image

Custom container element?

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?

Bug with scrollEventHandler() call prevents autocomplete container from scrolling

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.

Setting minLength=1 With debounceWaitMs > 0 Causes an Unnecessary Fetch

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 :)

Debouncing input (e.g. for ajax requests)

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!

Interface for show\hide autocomplete panel

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,
};

Bug with ignored keys causing fetch callback to skip update()

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; }

[Feature Request] Typescript Source Map

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

data handling problem

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

Enable Mac keyboard shortcuts

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.

typescript: esModuleInterop flag needed

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.

Would be nice to have custom onAttach and onDetach callbacks

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()).

Form is submitting on enter (selection)

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.

Is it possible to disallow values not in list ?

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.

Option to Disable Select Item on Enter

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

textarea

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.

After updating autocomplete, it stopped working

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.