10 changed files with 1181 additions and 2 deletions
@ -0,0 +1,201 @@ |
|||
Apache License |
|||
Version 2.0, January 2004 |
|||
http://www.apache.org/licenses/ |
|||
|
|||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, |
|||
and distribution as defined by Sections 1 through 9 of this document. |
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by |
|||
the copyright owner that is granting the License. |
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all |
|||
other entities that control, are controlled by, or are under common |
|||
control with that entity. For the purposes of this definition, |
|||
"control" means (i) the power, direct or indirect, to cause the |
|||
direction or management of such entity, whether by contract or |
|||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|||
outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity |
|||
exercising permissions granted by this License. |
|||
|
|||
"Source" form shall mean the preferred form for making modifications, |
|||
including but not limited to software source code, documentation |
|||
source, and configuration files. |
|||
|
|||
"Object" form shall mean any form resulting from mechanical |
|||
transformation or translation of a Source form, including but |
|||
not limited to compiled object code, generated documentation, |
|||
and conversions to other media types. |
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or |
|||
Object form, made available under the License, as indicated by a |
|||
copyright notice that is included in or attached to the work |
|||
(an example is provided in the Appendix below). |
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object |
|||
form, that is based on (or derived from) the Work and for which the |
|||
editorial revisions, annotations, elaborations, or other modifications |
|||
represent, as a whole, an original work of authorship. For the purposes |
|||
of this License, Derivative Works shall not include works that remain |
|||
separable from, or merely link (or bind by name) to the interfaces of, |
|||
the Work and Derivative Works thereof. |
|||
|
|||
"Contribution" shall mean any work of authorship, including |
|||
the original version of the Work and any modifications or additions |
|||
to that Work or Derivative Works thereof, that is intentionally |
|||
submitted to Licensor for inclusion in the Work by the copyright owner |
|||
or by an individual or Legal Entity authorized to submit on behalf of |
|||
the copyright owner. For the purposes of this definition, "submitted" |
|||
means any form of electronic, verbal, or written communication sent |
|||
to the Licensor or its representatives, including but not limited to |
|||
communication on electronic mailing lists, source code control systems, |
|||
and issue tracking systems that are managed by, or on behalf of, the |
|||
Licensor for the purpose of discussing and improving the Work, but |
|||
excluding communication that is conspicuously marked or otherwise |
|||
designated in writing by the copyright owner as "Not a Contribution." |
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity |
|||
on behalf of whom a Contribution has been received by Licensor and |
|||
subsequently incorporated within the Work. |
|||
|
|||
2. Grant of Copyright License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
copyright license to reproduce, prepare Derivative Works of, |
|||
publicly display, publicly perform, sublicense, and distribute the |
|||
Work and such Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
(except as stated in this section) patent license to make, have made, |
|||
use, offer to sell, sell, import, and otherwise transfer the Work, |
|||
where such license applies only to those patent claims licensable |
|||
by such Contributor that are necessarily infringed by their |
|||
Contribution(s) alone or by combination of their Contribution(s) |
|||
with the Work to which such Contribution(s) was submitted. If You |
|||
institute patent litigation against any entity (including a |
|||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
|||
or a Contribution incorporated within the Work constitutes direct |
|||
or contributory patent infringement, then any patent licenses |
|||
granted to You under this License for that Work shall terminate |
|||
as of the date such litigation is filed. |
|||
|
|||
4. Redistribution. You may reproduce and distribute copies of the |
|||
Work or Derivative Works thereof in any medium, with or without |
|||
modifications, and in Source or Object form, provided that You |
|||
meet the following conditions: |
|||
|
|||
(a) You must give any other recipients of the Work or |
|||
Derivative Works a copy of this License; and |
|||
|
|||
(b) You must cause any modified files to carry prominent notices |
|||
stating that You changed the files; and |
|||
|
|||
(c) You must retain, in the Source form of any Derivative Works |
|||
that You distribute, all copyright, patent, trademark, and |
|||
attribution notices from the Source form of the Work, |
|||
excluding those notices that do not pertain to any part of |
|||
the Derivative Works; and |
|||
|
|||
(d) If the Work includes a "NOTICE" text file as part of its |
|||
distribution, then any Derivative Works that You distribute must |
|||
include a readable copy of the attribution notices contained |
|||
within such NOTICE file, excluding those notices that do not |
|||
pertain to any part of the Derivative Works, in at least one |
|||
of the following places: within a NOTICE text file distributed |
|||
as part of the Derivative Works; within the Source form or |
|||
documentation, if provided along with the Derivative Works; or, |
|||
within a display generated by the Derivative Works, if and |
|||
wherever such third-party notices normally appear. The contents |
|||
of the NOTICE file are for informational purposes only and |
|||
do not modify the License. You may add Your own attribution |
|||
notices within Derivative Works that You distribute, alongside |
|||
or as an addendum to the NOTICE text from the Work, provided |
|||
that such additional attribution notices cannot be construed |
|||
as modifying the License. |
|||
|
|||
You may add Your own copyright statement to Your modifications and |
|||
may provide additional or different license terms and conditions |
|||
for use, reproduction, or distribution of Your modifications, or |
|||
for any such Derivative Works as a whole, provided Your use, |
|||
reproduction, and distribution of the Work otherwise complies with |
|||
the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. Unless You explicitly state otherwise, |
|||
any Contribution intentionally submitted for inclusion in the Work |
|||
by You to the Licensor shall be under the terms and conditions of |
|||
this License, without any additional terms or conditions. |
|||
Notwithstanding the above, nothing herein shall supersede or modify |
|||
the terms of any separate license agreement you may have executed |
|||
with Licensor regarding such Contributions. |
|||
|
|||
6. Trademarks. This License does not grant permission to use the trade |
|||
names, trademarks, service marks, or product names of the Licensor, |
|||
except as required for reasonable and customary use in describing the |
|||
origin of the Work and reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. Unless required by applicable law or |
|||
agreed to in writing, Licensor provides the Work (and each |
|||
Contributor provides its Contributions) on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|||
implied, including, without limitation, any warranties or conditions |
|||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|||
PARTICULAR PURPOSE. You are solely responsible for determining the |
|||
appropriateness of using or redistributing the Work and assume any |
|||
risks associated with Your exercise of permissions under this License. |
|||
|
|||
8. Limitation of Liability. In no event and under no legal theory, |
|||
whether in tort (including negligence), contract, or otherwise, |
|||
unless required by applicable law (such as deliberate and grossly |
|||
negligent acts) or agreed to in writing, shall any Contributor be |
|||
liable to You for damages, including any direct, indirect, special, |
|||
incidental, or consequential damages of any character arising as a |
|||
result of this License or out of the use or inability to use the |
|||
Work (including but not limited to damages for loss of goodwill, |
|||
work stoppage, computer failure or malfunction, or any and all |
|||
other commercial damages or losses), even if such Contributor |
|||
has been advised of the possibility of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. While redistributing |
|||
the Work or Derivative Works thereof, You may choose to offer, |
|||
and charge a fee for, acceptance of support, warranty, indemnity, |
|||
or other liability obligations and/or rights consistent with this |
|||
License. However, in accepting such obligations, You may act only |
|||
on Your own behalf and on Your sole responsibility, not on behalf |
|||
of any other Contributor, and only if You agree to indemnify, |
|||
defend, and hold each Contributor harmless for any liability |
|||
incurred by, or claims asserted against, such Contributor by reason |
|||
of your accepting any such warranty or additional liability. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work. |
|||
|
|||
To apply the Apache License to your work, attach the following |
|||
boilerplate notice, with the fields enclosed by brackets "[]" |
|||
replaced with your own identifying information. (Don't include |
|||
the brackets!) The text should be enclosed in the appropriate |
|||
comment syntax for the file format. We also recommend that a |
|||
file or class name and description of purpose be included on the |
|||
same "printed page" as the copyright notice for easier |
|||
identification within third-party archives. |
|||
|
|||
Copyright [yyyy] [name of copyright owner] |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
@ -0,0 +1,124 @@ |
|||
# autoComplete.js :sparkles: |
|||
|
|||
[](https://opensource.org/licenses/Apache-2.0) |
|||
[](https://badge.fury.io/gh/tarekraafat%2FautoComplete.js) |
|||
[](https://badge.fury.io/js/%40tarekraafat%2Fautocomplete.js) |
|||
 |
|||
![\[Zero Dependencies\]()](https://img.shields.io/badge/Dependencies-0-blue.svg) |
|||
![\[Size\]()](https://img.shields.io/badge/Size-10%20KB-green.svg) |
|||
 |
|||
[](https://www.jsdelivr.com/package/npm/@tarekraafat/autocomplete.js) |
|||
 |
|||
[](https://github.com/TarekRaafat/autoComplete.js) |
|||
|
|||
<br> |
|||
<br> |
|||
<p align="center"> |
|||
<a href="https://tarekraafat.github.io/autoComplete.js/"> |
|||
<img src="./docs/img/autoComplete.js.png" alt="autoComplete.js Design" width="50%"> |
|||
</a> |
|||
</p> |
|||
<br> |
|||
<br> |
|||
|
|||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">:rocket: Live Demo</a> **v8.3** |
|||
|
|||
autoComplete.js is a simple pure vanilla Javascript library that's progressively designed for speed, high versatility and seamless integration with a wide range of projects & systems, made for users and developers in mind. |
|||
|
|||
## Features |
|||
|
|||
- Pure Vanilla Javascript |
|||
- Zero Dependencies |
|||
- Simple & Easy to use |
|||
- Extremely Lightweight |
|||
- Blazing Fast |
|||
- Versatile |
|||
- Hackable & highly customizable |
|||
|
|||
## [](https://codepen.io/tarekraafat/pen/rQopdW?editors=0010) |
|||
|
|||
## Get Started |
|||
|
|||
### Clone: |
|||
|
|||
- Clone autoComplete.js to your local machine |
|||
|
|||
```shell |
|||
git clone https://github.com/TarekRaafat/autoComplete.js.git |
|||
``` |
|||
|
|||
### Installation: |
|||
|
|||
- <a href="https://www.jsdelivr.com/package/gh/TarekRaafat/autoComplete.js"><img src="https://www.jsdelivr.com/img/logo@2x.png" alt="jsDelivr" width="100px"></a> CDN |
|||
|
|||
`CSS` |
|||
|
|||
```html |
|||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/css/autoComplete.min.css"> |
|||
``` |
|||
|
|||
`JS` |
|||
|
|||
```html |
|||
<script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@8.3.2/dist/js/autoComplete.min.js"></script> |
|||
``` |
|||
|
|||
- <a href="https://www.npmjs.com/package/@tarekraafat/autocomplete.js">npm</a> install `(Node Package Manager)` |
|||
|
|||
```shell |
|||
npm i @tarekraafat/autocomplete |
|||
``` |
|||
|
|||
- <a href="https://yarn.pm/@tarekraafat/autocomplete.js">Yarn</a> install `(Javascript Package Manager)` |
|||
|
|||
```shell |
|||
yarn add @tarekraafat/autocomplete |
|||
``` |
|||
|
|||
<!-- * * * --> |
|||
|
|||
## Documentation: |
|||
|
|||
- For more details check out **autoComplete.js** <a href="https://tarekraafat.github.io/autoComplete.js/">**docs** :notebook_with_decorative_cover:</a> |
|||
|
|||
<!-- * * * --> |
|||
|
|||
## Third-Party Plugins: |
|||
|
|||
- [Contao autoComplete.js Bundle](https://github.com/heimrichhannot/contao-autocompletejs-bundle) by [@heimrichhannot](https://github.com/heimrichhannot) |
|||
- [Contentful Fontawesome autoComplete Field](https://github.com/ModiiMedia/contentful-fontawesome-autocomplete-field) by [@ModiiMedia](https://github.com/ModiiMedia) |
|||
|
|||
* * * |
|||
|
|||
## Support |
|||
|
|||
For general questions about autoComplete.js, tweet at [@TarekRaafat]. |
|||
|
|||
For technical questions, you should post a question on [Stack Overflow] and tag |
|||
it with [autoComplete.js][so tag]. |
|||
|
|||
<!-- section links --> |
|||
|
|||
[stack overflow]: https://stackoverflow.com/ |
|||
|
|||
[@tarekraafat]: https://twitter.com/TarekRaafat |
|||
|
|||
[so tag]: https://stackoverflow.com/questions/tagged/autoComplete.js |
|||
|
|||
* * * |
|||
|
|||
## Author |
|||
|
|||
**Tarek Raafat** |
|||
|
|||
- Email: tarek.m.raafat@gmail.com |
|||
- Website: <http://www.tarekraafat.com/> |
|||
- Github: <https://github.com/TarekRaafat/> |
|||
|
|||
Distributed under the Apache 2.0 license. See `Apache 2.0` for more information. |
|||
|
|||
* * * |
|||
|
|||
## License |
|||
|
|||
Apache 2.0 © [Tarek Raafat](http://www.tarekraafat.com) |
@ -0,0 +1,153 @@ |
|||
.autoComplete_wrapper { |
|||
position: relative; |
|||
display: inline-block; |
|||
width: 370px; |
|||
} |
|||
|
|||
/*#autoComplete { |
|||
height: 3rem; |
|||
margin: 0; |
|||
padding: 0 2rem 0 3.2rem; |
|||
box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
-webkit-box-sizing: border-box; |
|||
font-size: 1rem; |
|||
text-overflow: ellipsis; |
|||
color: rgba(11, 94, 215, 0.3); |
|||
outline: none; |
|||
border-radius: 10rem; |
|||
border: 0; |
|||
border: 0.05rem solid rgba(255, 122, 122, 0.5); |
|||
background-image: url(./images/search.svg); |
|||
background-size: 1.4rem; |
|||
background-position: left 1.05rem top 0.8rem; |
|||
background-repeat: no-repeat; |
|||
background-origin: border-box; |
|||
background-color: #fff; |
|||
transition: all 0.4s ease; |
|||
-webkit-transition: all -webkit-transform 0.4s ease; |
|||
}*/ |
|||
|
|||
#autoComplete::placeholder { |
|||
color: rgba(11, 94, 215, 0.5); |
|||
transition: all 0.3s ease; |
|||
-webkit-transition: all -webkit-transform 0.3s ease; |
|||
} |
|||
|
|||
#autoComplete:hover::placeholder { |
|||
color: rgba(11, 94, 215, 0.6); |
|||
transition: all 0.3s ease; |
|||
-webkit-transition: all -webkit-transform 0.3s ease; |
|||
} |
|||
|
|||
#autoComplete:focus::placeholder { |
|||
padding: 0.1rem 0.6rem; |
|||
font-size: 0.95rem; |
|||
color: rgba(11, 94, 215, 0.4); |
|||
} |
|||
|
|||
#autoComplete:focus::selection { |
|||
background-color: rgba(11, 94, 215, 0.15); |
|||
} |
|||
|
|||
#autoComplete::selection { |
|||
background-color: rgba(11, 94, 215, 0.15); |
|||
} |
|||
|
|||
#autoComplete:hover { |
|||
color: rgba(11, 94, 215, 0.8); |
|||
transition: all 0.3s ease; |
|||
-webkit-transition: all -webkit-transform 0.3s ease; |
|||
} |
|||
|
|||
#autoComplete:focus { |
|||
color: rgba(11, 94, 215, 1); |
|||
border: 0.06rem solid rgba(11, 94, 215, 0.8); |
|||
} |
|||
|
|||
#autoComplete_list { |
|||
position: absolute; |
|||
top: 100%; |
|||
left: 0; |
|||
right: 0; |
|||
padding: 0; |
|||
margin-top: 0.5rem; |
|||
border-radius: 0.6rem; |
|||
background-color: #fff; |
|||
box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); |
|||
border: 1px solid rgba(33, 33, 33, 0.07); |
|||
z-index: 1000; |
|||
outline: none; |
|||
} |
|||
|
|||
.autoComplete_result { |
|||
margin: 0.3rem; |
|||
padding: 0.3rem 0.5rem; |
|||
list-style: none; |
|||
text-align: left; |
|||
font-size: 1rem; |
|||
color: #212121; |
|||
transition: all 0.1s ease-in-out; |
|||
border-radius: 0.35rem; |
|||
background-color: rgba(255, 255, 255, 1); |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
transition: all 0.2s ease; |
|||
} |
|||
|
|||
.autoComplete_result::selection { |
|||
color: rgba(#ffffff, 0); |
|||
background-color: rgba(#ffffff, 0); |
|||
} |
|||
|
|||
.autoComplete_result:hover { |
|||
cursor: pointer; |
|||
background-color: rgba(11, 94, 215, 0.15); |
|||
} |
|||
|
|||
.autoComplete_highlighted { |
|||
color: rgba(11, 94, 215, 1); |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.autoComplete_highlighted::selection { |
|||
color: rgba(#ffffff, 0); |
|||
background-color: rgba(#ffffff, 0); |
|||
} |
|||
|
|||
.autoComplete_selected { |
|||
cursor: pointer; |
|||
background-color: rgba(11, 94, 215, 0.15); |
|||
} |
|||
|
|||
@media only screen and (max-width: 600px) { |
|||
.autoComplete_wrapper { |
|||
width: 320px; |
|||
} |
|||
|
|||
#autoComplete { |
|||
width: 18rem; |
|||
background-size: 1.6rem; |
|||
background-position: left 1.1rem top 0.75rem; |
|||
} |
|||
|
|||
#autoComplete_list { |
|||
margin: 10px; |
|||
} |
|||
} |
|||
|
|||
@media screen and (-webkit-min-device-pixel-ratio: 0) { |
|||
#autoComplete { |
|||
border-width: 1px; |
|||
} |
|||
} |
|||
|
|||
@-moz-document url-prefix() { |
|||
#autoComplete { |
|||
background-size: 1.2rem; |
|||
background-origin: border-box; |
|||
border-width: 1px; |
|||
background-position: left 1.1rem top 0.8rem; |
|||
} |
|||
} |
After Width: | Height: | Size: 670 B |
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,618 @@ |
|||
(function (global, factory) { |
|||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : |
|||
typeof define === 'function' && define.amd ? define(factory) : |
|||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.autoComplete = factory()); |
|||
}(this, (function () { 'use strict'; |
|||
|
|||
function _classCallCheck(instance, Constructor) { |
|||
if (!(instance instanceof Constructor)) { |
|||
throw new TypeError("Cannot call a class as a function"); |
|||
} |
|||
} |
|||
|
|||
function _defineProperties(target, props) { |
|||
for (var i = 0; i < props.length; i++) { |
|||
var descriptor = props[i]; |
|||
descriptor.enumerable = descriptor.enumerable || false; |
|||
descriptor.configurable = true; |
|||
if ("value" in descriptor) descriptor.writable = true; |
|||
Object.defineProperty(target, descriptor.key, descriptor); |
|||
} |
|||
} |
|||
|
|||
function _createClass(Constructor, protoProps, staticProps) { |
|||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); |
|||
if (staticProps) _defineProperties(Constructor, staticProps); |
|||
return Constructor; |
|||
} |
|||
|
|||
function _defineProperty(obj, key, value) { |
|||
if (key in obj) { |
|||
Object.defineProperty(obj, key, { |
|||
value: value, |
|||
enumerable: true, |
|||
configurable: true, |
|||
writable: true |
|||
}); |
|||
} else { |
|||
obj[key] = value; |
|||
} |
|||
|
|||
return obj; |
|||
} |
|||
|
|||
function ownKeys(object, enumerableOnly) { |
|||
var keys = Object.keys(object); |
|||
|
|||
if (Object.getOwnPropertySymbols) { |
|||
var symbols = Object.getOwnPropertySymbols(object); |
|||
if (enumerableOnly) symbols = symbols.filter(function (sym) { |
|||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; |
|||
}); |
|||
keys.push.apply(keys, symbols); |
|||
} |
|||
|
|||
return keys; |
|||
} |
|||
|
|||
function _objectSpread2(target) { |
|||
for (var i = 1; i < arguments.length; i++) { |
|||
var source = arguments[i] != null ? arguments[i] : {}; |
|||
|
|||
if (i % 2) { |
|||
ownKeys(Object(source), true).forEach(function (key) { |
|||
_defineProperty(target, key, source[key]); |
|||
}); |
|||
} else if (Object.getOwnPropertyDescriptors) { |
|||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); |
|||
} else { |
|||
ownKeys(Object(source)).forEach(function (key) { |
|||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return target; |
|||
} |
|||
|
|||
function _unsupportedIterableToArray(o, minLen) { |
|||
if (!o) return; |
|||
if (typeof o === "string") return _arrayLikeToArray(o, minLen); |
|||
var n = Object.prototype.toString.call(o).slice(8, -1); |
|||
if (n === "Object" && o.constructor) n = o.constructor.name; |
|||
if (n === "Map" || n === "Set") return Array.from(o); |
|||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); |
|||
} |
|||
|
|||
function _arrayLikeToArray(arr, len) { |
|||
if (len == null || len > arr.length) len = arr.length; |
|||
|
|||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; |
|||
|
|||
return arr2; |
|||
} |
|||
|
|||
function _createForOfIteratorHelper(o, allowArrayLike) { |
|||
var it; |
|||
|
|||
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { |
|||
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { |
|||
if (it) o = it; |
|||
var i = 0; |
|||
|
|||
var F = function () {}; |
|||
|
|||
return { |
|||
s: F, |
|||
n: function () { |
|||
if (i >= o.length) return { |
|||
done: true |
|||
}; |
|||
return { |
|||
done: false, |
|||
value: o[i++] |
|||
}; |
|||
}, |
|||
e: function (e) { |
|||
throw e; |
|||
}, |
|||
f: F |
|||
}; |
|||
} |
|||
|
|||
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); |
|||
} |
|||
|
|||
var normalCompletion = true, |
|||
didErr = false, |
|||
err; |
|||
return { |
|||
s: function () { |
|||
it = o[Symbol.iterator](); |
|||
}, |
|||
n: function () { |
|||
var step = it.next(); |
|||
normalCompletion = step.done; |
|||
return step; |
|||
}, |
|||
e: function (e) { |
|||
didErr = true; |
|||
err = e; |
|||
}, |
|||
f: function () { |
|||
try { |
|||
if (!normalCompletion && it.return != null) it.return(); |
|||
} finally { |
|||
if (didErr) throw err; |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
var inputComponent = (function (config) { |
|||
config.inputField.setAttribute("type", "text"); |
|||
config.inputField.setAttribute("role", "combobox"); |
|||
config.inputField.setAttribute("aria-haspopup", true); |
|||
config.inputField.setAttribute("aria-expanded", false); |
|||
config.inputField.setAttribute("aria-controls", config.resultsList.idName); |
|||
config.inputField.setAttribute("aria-autocomplete", "both"); |
|||
}); |
|||
|
|||
var createList = (function (config) { |
|||
var list = document.createElement(config.resultsList.element); |
|||
list.setAttribute("id", config.resultsList.idName); |
|||
list.setAttribute("aria-label", config.name); |
|||
list.setAttribute("class", config.resultsList.className); |
|||
list.setAttribute("role", "listbox"); |
|||
list.setAttribute("tabindex", "-1"); |
|||
if (config.resultsList.container) config.resultsList.container(list); |
|||
var destination = "string" === typeof config.resultsList.destination ? document.querySelector(config.resultsList.destination) : config.resultsList.destination(); |
|||
destination.insertAdjacentElement(config.resultsList.position, list); |
|||
return list; |
|||
}); |
|||
|
|||
var createItem = (function (item, index, config) { |
|||
var result = document.createElement(config.resultItem.element); |
|||
result.setAttribute("id", "".concat(config.resultItem.idName, "_").concat(index)); |
|||
result.setAttribute("class", config.resultItem.className); |
|||
result.setAttribute("role", "option"); |
|||
result.innerHTML = item.match; |
|||
if (config.resultItem.content) config.resultItem.content(item, result); |
|||
return result; |
|||
}); |
|||
|
|||
var closeAllLists = function closeAllLists(config, element) { |
|||
var list = document.getElementsByClassName(config.resultsList.className); |
|||
for (var index = 0; index < list.length; index++) { |
|||
if (element !== list[index] && element !== config.inputField) list[index].parentNode.removeChild(list[index]); |
|||
} |
|||
config.inputField.removeAttribute("aria-activedescendant"); |
|||
config.inputField.setAttribute("aria-expanded", false); |
|||
}; |
|||
var generateList = function generateList(config, data, matches) { |
|||
var list = createList(config); |
|||
config.inputField.setAttribute("aria-expanded", true); |
|||
var _loop = function _loop(index) { |
|||
var item = data.results[index]; |
|||
var resultItem = createItem(item, index, config); |
|||
resultItem.addEventListener("click", function (event) { |
|||
var dataFeedback = { |
|||
event: event, |
|||
matches: matches, |
|||
input: data.input, |
|||
query: data.query, |
|||
results: data.results, |
|||
selection: _objectSpread2(_objectSpread2({}, item), {}, { |
|||
index: index |
|||
}) |
|||
}; |
|||
if (config.onSelection) config.onSelection(dataFeedback); |
|||
}); |
|||
list.appendChild(resultItem); |
|||
}; |
|||
for (var index = 0; index < data.results.length; index++) { |
|||
_loop(index); |
|||
} |
|||
return list; |
|||
}; |
|||
|
|||
var eventEmitter = (function (target, detail, name) { |
|||
target.dispatchEvent(new CustomEvent(name, { |
|||
bubbles: true, |
|||
detail: detail, |
|||
cancelable: true |
|||
})); |
|||
}); |
|||
|
|||
var navigate = function navigate(config, dataFeedback) { |
|||
var currentFocus = -1; |
|||
var update = function update(event, list, state, config) { |
|||
event.preventDefault(); |
|||
if (state) { |
|||
currentFocus++; |
|||
} else { |
|||
currentFocus--; |
|||
} |
|||
addActive(list); |
|||
config.inputField.setAttribute("aria-activedescendant", list[currentFocus].id); |
|||
eventEmitter(event.srcElement, _objectSpread2(_objectSpread2({ |
|||
event: event |
|||
}, dataFeedback), {}, { |
|||
selection: dataFeedback.results[currentFocus] |
|||
}), "navigation"); |
|||
}; |
|||
var removeActive = function removeActive(list) { |
|||
for (var index = 0; index < list.length; index++) { |
|||
list[index].removeAttribute("aria-selected"); |
|||
list[index].classList.remove("autoComplete_selected"); |
|||
} |
|||
}; |
|||
var addActive = function addActive(list) { |
|||
if (!list) return false; |
|||
removeActive(list); |
|||
if (currentFocus >= list.length) currentFocus = 0; |
|||
if (currentFocus < 0) currentFocus = list.length - 1; |
|||
list[currentFocus].setAttribute("aria-selected", "true"); |
|||
list[currentFocus].classList.add("autoComplete_selected"); |
|||
}; |
|||
var navigation = function navigation(event) { |
|||
var list = document.getElementById(config.resultsList.idName); |
|||
if (!list) return config.inputField.removeEventListener("keydown", navigate); |
|||
list = list.getElementsByTagName(config.resultItem.element); |
|||
if (event.keyCode === 27) { |
|||
config.inputField.value = ""; |
|||
closeAllLists(config); |
|||
} else if (event.keyCode === 40 || event.keyCode === 9) { |
|||
update(event, list, true, config); |
|||
} else if (event.keyCode === 38 || event.keyCode === 9) { |
|||
update(event, list, false, config); |
|||
} else if (event.keyCode === 13) { |
|||
event.preventDefault(); |
|||
if (currentFocus > -1) { |
|||
if (list) list[currentFocus].click(); |
|||
} |
|||
} |
|||
}; |
|||
var navigate = config.resultsList.navigation || navigation; |
|||
if (config.inputField.autoCompleteNavigate) config.inputField.removeEventListener("keydown", config.inputField.autoCompleteNavigate); |
|||
config.inputField.autoCompleteNavigate = navigate; |
|||
config.inputField.addEventListener("keydown", navigate); |
|||
}; |
|||
|
|||
var searchEngine = (function (query, record, config) { |
|||
var recordLowerCase = config.diacritics ? record.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC") : record.toLowerCase(); |
|||
if (config.searchEngine === "loose") { |
|||
query = query.replace(/ /g, ""); |
|||
var match = []; |
|||
var searchPosition = 0; |
|||
for (var number = 0; number < recordLowerCase.length; number++) { |
|||
var recordChar = record[number]; |
|||
if (searchPosition < query.length && recordLowerCase[number] === query[searchPosition]) { |
|||
recordChar = config.highlight ? "<span class=\"autoComplete_highlighted\">".concat(recordChar, "</span>") : recordChar; |
|||
searchPosition++; |
|||
} |
|||
match.push(recordChar); |
|||
} |
|||
if (searchPosition === query.length) { |
|||
return match.join(""); |
|||
} |
|||
} else { |
|||
if (recordLowerCase.includes(query)) { |
|||
var pattern = new RegExp("".concat(query), "i"); |
|||
query = pattern.exec(record); |
|||
var _match = config.highlight ? record.replace(query, "<span class=\"autoComplete_highlighted\">".concat(query, "</span>")) : record; |
|||
return _match; |
|||
} |
|||
} |
|||
}); |
|||
|
|||
var getInputValue = function getInputValue(inputField) { |
|||
return inputField instanceof HTMLInputElement || inputField instanceof HTMLTextAreaElement ? inputField.value.toLowerCase() : inputField.innerHTML.toLowerCase(); |
|||
}; |
|||
var prepareQueryValue = function prepareQueryValue(inputValue, config) { |
|||
return config.query && config.query.manipulate ? config.query.manipulate(inputValue) : config.diacritics ? inputValue.normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC") : inputValue; |
|||
}; |
|||
var checkTriggerCondition = function checkTriggerCondition(config, queryValue) { |
|||
return config.trigger.condition ? config.trigger.condition(queryValue) : queryValue.length >= config.threshold && queryValue.replace(/ /g, "").length; |
|||
}; |
|||
var listMatchingResults = function listMatchingResults(config, query) { |
|||
var resList = []; |
|||
var _loop = function _loop(index) { |
|||
var record = config.data.store[index]; |
|||
var search = function search(key) { |
|||
var recordValue = (key ? record[key] : record).toString(); |
|||
if (recordValue) { |
|||
var match = typeof config.searchEngine === "function" ? config.searchEngine(query, recordValue) : searchEngine(query, recordValue, config); |
|||
if (match && key) { |
|||
resList.push({ |
|||
key: key, |
|||
index: index, |
|||
match: match, |
|||
value: record |
|||
}); |
|||
} else if (match && !key) { |
|||
resList.push({ |
|||
index: index, |
|||
match: match, |
|||
value: record |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
if (config.data.key) { |
|||
var _iterator = _createForOfIteratorHelper(config.data.key), |
|||
_step; |
|||
try { |
|||
for (_iterator.s(); !(_step = _iterator.n()).done;) { |
|||
var key = _step.value; |
|||
search(key); |
|||
} |
|||
} catch (err) { |
|||
_iterator.e(err); |
|||
} finally { |
|||
_iterator.f(); |
|||
} |
|||
} else { |
|||
search(); |
|||
} |
|||
}; |
|||
for (var index = 0; index < config.data.store.length; index++) { |
|||
_loop(index); |
|||
} |
|||
var list = config.sort ? resList.sort(config.sort) : resList; |
|||
return list; |
|||
}; |
|||
|
|||
var debouncer = (function (callback, delay) { |
|||
var inDebounce; |
|||
return function () { |
|||
var context = this; |
|||
var args = arguments; |
|||
clearTimeout(inDebounce); |
|||
inDebounce = setTimeout(function () { |
|||
return callback.apply(context, args); |
|||
}, delay); |
|||
}; |
|||
}); |
|||
|
|||
var autoComplete = function () { |
|||
function autoComplete(config) { |
|||
_classCallCheck(this, autoComplete); |
|||
var _config$name = config.name, |
|||
name = _config$name === void 0 ? "Search" : _config$name, |
|||
_config$selector = config.selector, |
|||
selector = _config$selector === void 0 ? "#autoComplete" : _config$selector, |
|||
_config$observer = config.observer, |
|||
observer = _config$observer === void 0 ? false : _config$observer, |
|||
_config$data = config.data, |
|||
src = _config$data.src, |
|||
key = _config$data.key, |
|||
_config$data$cache = _config$data.cache, |
|||
cache = _config$data$cache === void 0 ? false : _config$data$cache, |
|||
store = _config$data.store, |
|||
results = _config$data.results, |
|||
query = config.query, |
|||
_config$trigger = config.trigger; |
|||
_config$trigger = _config$trigger === void 0 ? {} : _config$trigger; |
|||
var _config$trigger$event = _config$trigger.event, |
|||
event = _config$trigger$event === void 0 ? ["input"] : _config$trigger$event, |
|||
_config$trigger$condi = _config$trigger.condition, |
|||
condition = _config$trigger$condi === void 0 ? false : _config$trigger$condi, |
|||
_config$searchEngine = config.searchEngine, |
|||
searchEngine = _config$searchEngine === void 0 ? "strict" : _config$searchEngine, |
|||
_config$diacritics = config.diacritics, |
|||
diacritics = _config$diacritics === void 0 ? false : _config$diacritics, |
|||
_config$threshold = config.threshold, |
|||
threshold = _config$threshold === void 0 ? 1 : _config$threshold, |
|||
_config$debounce = config.debounce, |
|||
debounce = _config$debounce === void 0 ? 0 : _config$debounce, |
|||
_config$resultsList = config.resultsList; |
|||
_config$resultsList = _config$resultsList === void 0 ? {} : _config$resultsList; |
|||
var _config$resultsList$r = _config$resultsList.render, |
|||
render = _config$resultsList$r === void 0 ? true : _config$resultsList$r, |
|||
_config$resultsList$c = _config$resultsList.container, |
|||
container = _config$resultsList$c === void 0 ? false : _config$resultsList$c, |
|||
destination = _config$resultsList.destination, |
|||
_config$resultsList$p = _config$resultsList.position, |
|||
position = _config$resultsList$p === void 0 ? "afterend" : _config$resultsList$p, |
|||
_config$resultsList$e = _config$resultsList.element, |
|||
resultsListElement = _config$resultsList$e === void 0 ? "ul" : _config$resultsList$e, |
|||
_config$resultsList$i = _config$resultsList.idName, |
|||
resultsListId = _config$resultsList$i === void 0 ? "autoComplete_list" : _config$resultsList$i, |
|||
_config$resultsList$c2 = _config$resultsList.className, |
|||
resultsListClass = _config$resultsList$c2 === void 0 ? "autoComplete_list" : _config$resultsList$c2, |
|||
_config$resultsList$n = _config$resultsList.navigation, |
|||
navigation = _config$resultsList$n === void 0 ? false : _config$resultsList$n, |
|||
_config$sort = config.sort, |
|||
sort = _config$sort === void 0 ? false : _config$sort, |
|||
placeHolder = config.placeHolder, |
|||
_config$maxResults = config.maxResults, |
|||
maxResults = _config$maxResults === void 0 ? 5 : _config$maxResults, |
|||
_config$resultItem = config.resultItem; |
|||
_config$resultItem = _config$resultItem === void 0 ? {} : _config$resultItem; |
|||
var _config$resultItem$co = _config$resultItem.content, |
|||
content = _config$resultItem$co === void 0 ? false : _config$resultItem$co, |
|||
_config$resultItem$el = _config$resultItem.element, |
|||
resultItemElement = _config$resultItem$el === void 0 ? "li" : _config$resultItem$el, |
|||
_config$resultItem$id = _config$resultItem.idName, |
|||
resultItemId = _config$resultItem$id === void 0 ? "autoComplete_result" : _config$resultItem$id, |
|||
_config$resultItem$cl = _config$resultItem.className, |
|||
resultItemClass = _config$resultItem$cl === void 0 ? "autoComplete_result" : _config$resultItem$cl, |
|||
noResults = config.noResults, |
|||
_config$highlight = config.highlight, |
|||
highlight = _config$highlight === void 0 ? false : _config$highlight, |
|||
feedback = config.feedback, |
|||
onSelection = config.onSelection; |
|||
this.name = name; |
|||
this.selector = selector; |
|||
this.observer = observer; |
|||
this.data = { |
|||
src: src, |
|||
key: key, |
|||
cache: cache, |
|||
store: store, |
|||
results: results |
|||
}; |
|||
this.query = query; |
|||
this.trigger = { |
|||
event: event, |
|||
condition: condition |
|||
}; |
|||
this.searchEngine = searchEngine; |
|||
this.diacritics = diacritics; |
|||
this.threshold = threshold; |
|||
this.debounce = debounce; |
|||
this.resultsList = { |
|||
render: render, |
|||
container: container, |
|||
destination: destination || this.selector, |
|||
position: position, |
|||
element: resultsListElement, |
|||
idName: resultsListId, |
|||
className: resultsListClass, |
|||
navigation: navigation |
|||
}; |
|||
this.sort = sort; |
|||
this.placeHolder = placeHolder; |
|||
this.maxResults = maxResults; |
|||
this.resultItem = { |
|||
content: content, |
|||
element: resultItemElement, |
|||
idName: resultItemId, |
|||
className: resultItemClass |
|||
}; |
|||
this.noResults = noResults; |
|||
this.highlight = highlight; |
|||
this.feedback = feedback; |
|||
this.onSelection = onSelection; |
|||
this.inputField = typeof this.selector === "string" ? document.querySelector(this.selector) : this.selector(); |
|||
this.observer ? this.preInit() : this.init(); |
|||
} |
|||
_createClass(autoComplete, [{ |
|||
key: "start", |
|||
value: function start(input, query) { |
|||
var _this = this; |
|||
var results = this.data.results ? this.data.results(listMatchingResults(this, query)) : listMatchingResults(this, query); |
|||
var dataFeedback = { |
|||
input: input, |
|||
query: query, |
|||
matches: results, |
|||
results: results.slice(0, this.maxResults) |
|||
}; |
|||
eventEmitter(this.inputField, dataFeedback, "results"); |
|||
if (!results.length) return this.noResults ? this.noResults(dataFeedback, generateList) : null; |
|||
if (!this.resultsList.render) return this.feedback(dataFeedback); |
|||
results.length ? generateList(this, dataFeedback, results) : null; |
|||
eventEmitter(this.inputField, dataFeedback, "rendered"); |
|||
navigate(this, dataFeedback); |
|||
document.addEventListener("click", function (event) { |
|||
return closeAllLists(_this, event.target); |
|||
}); |
|||
} |
|||
}, { |
|||
key: "dataStore", |
|||
value: function dataStore() { |
|||
var _this2 = this; |
|||
return new Promise(function ($return, $error) { |
|||
if (_this2.data.cache && _this2.data.store) return $return(null); |
|||
return new Promise(function ($return, $error) { |
|||
if (typeof _this2.data.src === "function") { |
|||
return _this2.data.src().then($return, $error); |
|||
} |
|||
return $return(_this2.data.src); |
|||
}).then(function ($await_5) { |
|||
try { |
|||
_this2.data.store = $await_5; |
|||
eventEmitter(_this2.inputField, _this2.data.store, "fetch"); |
|||
return $return(); |
|||
} catch ($boundEx) { |
|||
return $error($boundEx); |
|||
} |
|||
}, $error); |
|||
}); |
|||
} |
|||
}, { |
|||
key: "compose", |
|||
value: function compose() { |
|||
var _this3 = this; |
|||
return new Promise(function ($return, $error) { |
|||
var input, query, triggerCondition; |
|||
input = getInputValue(_this3.inputField); |
|||
query = prepareQueryValue(input, _this3); |
|||
triggerCondition = checkTriggerCondition(_this3, query); |
|||
if (triggerCondition) { |
|||
return _this3.dataStore().then(function ($await_6) { |
|||
try { |
|||
closeAllLists(_this3); |
|||
_this3.start(input, query); |
|||
return $If_3.call(_this3); |
|||
} catch ($boundEx) { |
|||
return $error($boundEx); |
|||
} |
|||
}, $error); |
|||
} else { |
|||
closeAllLists(_this3); |
|||
return $If_3.call(_this3); |
|||
} |
|||
function $If_3() { |
|||
return $return(); |
|||
} |
|||
}); |
|||
} |
|||
}, { |
|||
key: "init", |
|||
value: function init() { |
|||
var _this4 = this; |
|||
inputComponent(this); |
|||
if (this.placeHolder) this.inputField.setAttribute("placeholder", this.placeHolder); |
|||
this.hook = debouncer(function () { |
|||
_this4.compose(); |
|||
}, this.debounce); |
|||
this.trigger.event.forEach(function (eventType) { |
|||
_this4.inputField.removeEventListener(eventType, _this4.hook); |
|||
_this4.inputField.addEventListener(eventType, _this4.hook); |
|||
}); |
|||
eventEmitter(this.inputField, null, "init"); |
|||
} |
|||
}, { |
|||
key: "preInit", |
|||
value: function preInit() { |
|||
var _this5 = this; |
|||
var config = { |
|||
childList: true, |
|||
subtree: true |
|||
}; |
|||
var callback = function callback(mutationsList, observer) { |
|||
var _iterator = _createForOfIteratorHelper(mutationsList), |
|||
_step; |
|||
try { |
|||
for (_iterator.s(); !(_step = _iterator.n()).done;) { |
|||
var mutation = _step.value; |
|||
if (_this5.inputField) { |
|||
observer.disconnect(); |
|||
eventEmitter(_this5.inputField, null, "connect"); |
|||
_this5.init(); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator.e(err); |
|||
} finally { |
|||
_iterator.f(); |
|||
} |
|||
}; |
|||
var observer = new MutationObserver(callback); |
|||
observer.observe(document, config); |
|||
} |
|||
}, { |
|||
key: "unInit", |
|||
value: function unInit() { |
|||
this.inputField.removeEventListener("input", this.hook); |
|||
eventEmitter(this.inputField, null, "unInit"); |
|||
} |
|||
}]); |
|||
return autoComplete; |
|||
}(); |
|||
|
|||
return autoComplete; |
|||
|
|||
}))); |
File diff suppressed because one or more lines are too long
@ -0,0 +1,67 @@ |
|||
new autoComplete({ |
|||
data: { // Data src [Array, Function, Async] | (REQUIRED)
|
|||
src: async () => { |
|||
// API key token
|
|||
// const token = "this_is_the_API_token_number";
|
|||
// User search query
|
|||
const query = document.querySelector("#autoComplete").value; |
|||
// Fetch External Data Source
|
|||
const source = await fetch(`http://localhost/api/pokemon.json?nom=${query}`); |
|||
// Format data into JSON
|
|||
const data = await source.json(); |
|||
// Return Fetched data
|
|||
return data; |
|||
}, |
|||
key: ["nom"], |
|||
cache: false |
|||
}, |
|||
query: { // Query Interceptor | (Optional)
|
|||
manipulate: (query) => { |
|||
return query.replace("Pikachu", "Charmander"); |
|||
} |
|||
}, |
|||
sort: (a, b) => { // Sort rendered results ascendingly | (Optional)
|
|||
if (a.match < b.match) return -1; |
|||
if (a.match > b.match) return 1; |
|||
return 0; |
|||
}, |
|||
placeHolder: "Saisir un nom de pokemon, type, generation...", // Place Holder text | (Optional)
|
|||
selector: "#autoComplete", // Input field selector | (Optional)
|
|||
observer: true, // Input field observer | (Optional)
|
|||
threshold: 3, // Min. Chars length to start Engine | (Optional)
|
|||
debounce: 300, // Post duration for engine to start | (Optional)
|
|||
searchEngine: "strict", // Search Engine type/mode | (Optional)
|
|||
resultsList: { // Rendered results list object | (Optional)
|
|||
container: source => { |
|||
source.setAttribute("id", "pokemon_list"); |
|||
}, |
|||
destination: "#autoComplete", |
|||
position: "afterend", |
|||
element: "ul" |
|||
}, |
|||
maxResults: 5, // Max. number of rendered results | (Optional)
|
|||
highlight: { |
|||
render: true, // Highlight matching results | (Optional)
|
|||
}, |
|||
resultItem: { // Rendered result item | (Optional)
|
|||
content: (data, source) => { |
|||
source.innerHTML = data.match; |
|||
}, |
|||
element: "li" |
|||
}, |
|||
noResults: (dataFeedback, generateList) => { |
|||
// Generate autoComplete List
|
|||
generateList(autoCompleteJS, dataFeedback, dataFeedback.results); |
|||
// No Results List Item
|
|||
const result = document.createElement("li"); |
|||
result.setAttribute("class", "no_result"); |
|||
result.setAttribute("tabindex", "1"); |
|||
result.innerHTML = `<span style="display: flex; align-items: center; font-weight: 100; color: rgba(0,0,0,.2);">Found No Results for "${dataFeedback.query}"</span>`; |
|||
document.querySelector(`#${autoCompleteJS.resultsList.idName}`).appendChild(result); |
|||
}, |
|||
onSelection: feedback => { // Action script onSelection event | (Optional)
|
|||
const resultNameFromAutocomplete = feedback.matches[0].value.nom |
|||
document.getElementById("autoComplete").value = resultNameFromAutocomplete |
|||
window.location = "/pokemon?keyword=" + resultNameFromAutocomplete |
|||
} |
|||
}); |
Loading…
Reference in new issue