Initiated AutoComplete component

pull/12/head
cagataycivici 2019-01-28 14:49:18 +03:00
parent 10c42cc444
commit 6aa9680df9
9 changed files with 702 additions and 0 deletions

View File

@ -0,0 +1,247 @@
{
"data": [
{"name": "Afghanistan", "code": "AF"},
{"name": "Åland Islands", "code": "AX"},
{"name": "Albania", "code": "AL"},
{"name": "Algeria", "code": "DZ"},
{"name": "American Samoa", "code": "AS"},
{"name": "Andorra", "code": "AD"},
{"name": "Angola", "code": "AO"},
{"name": "Anguilla", "code": "AI"},
{"name": "Antarctica", "code": "AQ"},
{"name": "Antigua and Barbuda", "code": "AG"},
{"name": "Argentina", "code": "AR"},
{"name": "Armenia", "code": "AM"},
{"name": "Aruba", "code": "AW"},
{"name": "Australia", "code": "AU"},
{"name": "Austria", "code": "AT"},
{"name": "Azerbaijan", "code": "AZ"},
{"name": "Bahamas", "code": "BS"},
{"name": "Bahrain", "code": "BH"},
{"name": "Bangladesh", "code": "BD"},
{"name": "Barbados", "code": "BB"},
{"name": "Belarus", "code": "BY"},
{"name": "Belgium", "code": "BE"},
{"name": "Belize", "code": "BZ"},
{"name": "Benin", "code": "BJ"},
{"name": "Bermuda", "code": "BM"},
{"name": "Bhutan", "code": "BT"},
{"name": "Bolivia", "code": "BO"},
{"name": "Bosnia and Herzegovina", "code": "BA"},
{"name": "Botswana", "code": "BW"},
{"name": "Bouvet Island", "code": "BV"},
{"name": "Brazil", "code": "BR"},
{"name": "British Indian Ocean Territory", "code": "IO"},
{"name": "Brunei Darussalam", "code": "BN"},
{"name": "Bulgaria", "code": "BG"},
{"name": "Burkina Faso", "code": "BF"},
{"name": "Burundi", "code": "BI"},
{"name": "Cambodia", "code": "KH"},
{"name": "Cameroon", "code": "CM"},
{"name": "Canada", "code": "CA"},
{"name": "Cape Verde", "code": "CV"},
{"name": "Cayman Islands", "code": "KY"},
{"name": "Central African Republic", "code": "CF"},
{"name": "Chad", "code": "TD"},
{"name": "Chile", "code": "CL"},
{"name": "China", "code": "CN"},
{"name": "Christmas Island", "code": "CX"},
{"name": "Cocos (Keeling) Islands", "code": "CC"},
{"name": "Colombia", "code": "CO"},
{"name": "Comoros", "code": "KM"},
{"name": "Congo", "code": "CG"},
{"name": "Congo, The Democratic Republic of the", "code": "CD"},
{"name": "Cook Islands", "code": "CK"},
{"name": "Costa Rica", "code": "CR"},
{"name": "Cote D\"Ivoire", "code": "CI"},
{"name": "Croatia", "code": "HR"},
{"name": "Cuba", "code": "CU"},
{"name": "Cyprus", "code": "CY"},
{"name": "Czech Republic", "code": "CZ"},
{"name": "Denmark", "code": "DK"},
{"name": "Djibouti", "code": "DJ"},
{"name": "Dominica", "code": "DM"},
{"name": "Dominican Republic", "code": "DO"},
{"name": "Ecuador", "code": "EC"},
{"name": "Egypt", "code": "EG"},
{"name": "El Salvador", "code": "SV"},
{"name": "Equatorial Guinea", "code": "GQ"},
{"name": "Eritrea", "code": "ER"},
{"name": "Estonia", "code": "EE"},
{"name": "Ethiopia", "code": "ET"},
{"name": "Falkland Islands (Malvinas)", "code": "FK"},
{"name": "Faroe Islands", "code": "FO"},
{"name": "Fiji", "code": "FJ"},
{"name": "Finland", "code": "FI"},
{"name": "France", "code": "FR"},
{"name": "French Guiana", "code": "GF"},
{"name": "French Polynesia", "code": "PF"},
{"name": "French Southern Territories", "code": "TF"},
{"name": "Gabon", "code": "GA"},
{"name": "Gambia", "code": "GM"},
{"name": "Georgia", "code": "GE"},
{"name": "Germany", "code": "DE"},
{"name": "Ghana", "code": "GH"},
{"name": "Gibraltar", "code": "GI"},
{"name": "Greece", "code": "GR"},
{"name": "Greenland", "code": "GL"},
{"name": "Grenada", "code": "GD"},
{"name": "Guadeloupe", "code": "GP"},
{"name": "Guam", "code": "GU"},
{"name": "Guatemala", "code": "GT"},
{"name": "Guernsey", "code": "GG"},
{"name": "Guinea", "code": "GN"},
{"name": "Guinea-Bissau", "code": "GW"},
{"name": "Guyana", "code": "GY"},
{"name": "Haiti", "code": "HT"},
{"name": "Heard Island and Mcdonald Islands", "code": "HM"},
{"name": "Holy See (Vatican City State)", "code": "VA"},
{"name": "Honduras", "code": "HN"},
{"name": "Hong Kong", "code": "HK"},
{"name": "Hungary", "code": "HU"},
{"name": "Iceland", "code": "IS"},
{"name": "India", "code": "IN"},
{"name": "Indonesia", "code": "ID"},
{"name": "Iran, Islamic Republic Of", "code": "IR"},
{"name": "Iraq", "code": "IQ"},
{"name": "Ireland", "code": "IE"},
{"name": "Isle of Man", "code": "IM"},
{"name": "Israel", "code": "IL"},
{"name": "Italy", "code": "IT"},
{"name": "Jamaica", "code": "JM"},
{"name": "Japan", "code": "JP"},
{"name": "Jersey", "code": "JE"},
{"name": "Jordan", "code": "JO"},
{"name": "Kazakhstan", "code": "KZ"},
{"name": "Kenya", "code": "KE"},
{"name": "Kiribati", "code": "KI"},
{"name": "Korea, Democratic People\"S Republic of", "code": "KP"},
{"name": "Korea, Republic of", "code": "KR"},
{"name": "Kuwait", "code": "KW"},
{"name": "Kyrgyzstan", "code": "KG"},
{"name": "Lao People\"S Democratic Republic", "code": "LA"},
{"name": "Latvia", "code": "LV"},
{"name": "Lebanon", "code": "LB"},
{"name": "Lesotho", "code": "LS"},
{"name": "Liberia", "code": "LR"},
{"name": "Libyan Arab Jamahiriya", "code": "LY"},
{"name": "Liechtenstein", "code": "LI"},
{"name": "Lithuania", "code": "LT"},
{"name": "Luxembourg", "code": "LU"},
{"name": "Macao", "code": "MO"},
{"name": "Macedonia, The Former Yugoslav Republic of", "code": "MK"},
{"name": "Madagascar", "code": "MG"},
{"name": "Malawi", "code": "MW"},
{"name": "Malaysia", "code": "MY"},
{"name": "Maldives", "code": "MV"},
{"name": "Mali", "code": "ML"},
{"name": "Malta", "code": "MT"},
{"name": "Marshall Islands", "code": "MH"},
{"name": "Martinique", "code": "MQ"},
{"name": "Mauritania", "code": "MR"},
{"name": "Mauritius", "code": "MU"},
{"name": "Mayotte", "code": "YT"},
{"name": "Mexico", "code": "MX"},
{"name": "Micronesia, Federated States of", "code": "FM"},
{"name": "Moldova, Republic of", "code": "MD"},
{"name": "Monaco", "code": "MC"},
{"name": "Mongolia", "code": "MN"},
{"name": "Montserrat", "code": "MS"},
{"name": "Morocco", "code": "MA"},
{"name": "Mozambique", "code": "MZ"},
{"name": "Myanmar", "code": "MM"},
{"name": "Namibia", "code": "NA"},
{"name": "Nauru", "code": "NR"},
{"name": "Nepal", "code": "NP"},
{"name": "Netherlands", "code": "NL"},
{"name": "Netherlands Antilles", "code": "AN"},
{"name": "New Caledonia", "code": "NC"},
{"name": "New Zealand", "code": "NZ"},
{"name": "Nicaragua", "code": "NI"},
{"name": "Niger", "code": "NE"},
{"name": "Nigeria", "code": "NG"},
{"name": "Niue", "code": "NU"},
{"name": "Norfolk Island", "code": "NF"},
{"name": "Northern Mariana Islands", "code": "MP"},
{"name": "Norway", "code": "NO"},
{"name": "Oman", "code": "OM"},
{"name": "Pakistan", "code": "PK"},
{"name": "Palau", "code": "PW"},
{"name": "Palestinian Territory, Occupied", "code": "PS"},
{"name": "Panama", "code": "PA"},
{"name": "Papua New Guinea", "code": "PG"},
{"name": "Paraguay", "code": "PY"},
{"name": "Peru", "code": "PE"},
{"name": "Philippines", "code": "PH"},
{"name": "Pitcairn", "code": "PN"},
{"name": "Poland", "code": "PL"},
{"name": "Portugal", "code": "PT"},
{"name": "Puerto Rico", "code": "PR"},
{"name": "Qatar", "code": "QA"},
{"name": "Reunion", "code": "RE"},
{"name": "Romania", "code": "RO"},
{"name": "Russian Federation", "code": "RU"},
{"name": "RWANDA", "code": "RW"},
{"name": "Saint Helena", "code": "SH"},
{"name": "Saint Kitts and Nevis", "code": "KN"},
{"name": "Saint Lucia", "code": "LC"},
{"name": "Saint Pierre and Miquelon", "code": "PM"},
{"name": "Saint Vincent and the Grenadines", "code": "VC"},
{"name": "Samoa", "code": "WS"},
{"name": "San Marino", "code": "SM"},
{"name": "Sao Tome and Principe", "code": "ST"},
{"name": "Saudi Arabia", "code": "SA"},
{"name": "Senegal", "code": "SN"},
{"name": "Serbia and Montenegro", "code": "CS"},
{"name": "Seychelles", "code": "SC"},
{"name": "Sierra Leone", "code": "SL"},
{"name": "Singapore", "code": "SG"},
{"name": "Slovakia", "code": "SK"},
{"name": "Slovenia", "code": "SI"},
{"name": "Solomon Islands", "code": "SB"},
{"name": "Somalia", "code": "SO"},
{"name": "South Africa", "code": "ZA"},
{"name": "South Georgia and the South Sandwich Islands", "code": "GS"},
{"name": "Spain", "code": "ES"},
{"name": "Sri Lanka", "code": "LK"},
{"name": "Sudan", "code": "SD"},
{"name": "Suriname", "code": "SR"},
{"name": "Svalbard and Jan Mayen", "code": "SJ"},
{"name": "Swaziland", "code": "SZ"},
{"name": "Sweden", "code": "SE"},
{"name": "Switzerland", "code": "CH"},
{"name": "Syrian Arab Republic", "code": "SY"},
{"name": "Taiwan, Province of China", "code": "TW"},
{"name": "Tajikistan", "code": "TJ"},
{"name": "Tanzania, United Republic of", "code": "TZ"},
{"name": "Thailand", "code": "TH"},
{"name": "Timor-Leste", "code": "TL"},
{"name": "Togo", "code": "TG"},
{"name": "Tokelau", "code": "TK"},
{"name": "Tonga", "code": "TO"},
{"name": "Trinidad and Tobago", "code": "TT"},
{"name": "Tunisia", "code": "TN"},
{"name": "Turkey", "code": "TR"},
{"name": "Turkmenistan", "code": "TM"},
{"name": "Turks and Caicos Islands", "code": "TC"},
{"name": "Tuvalu", "code": "TV"},
{"name": "Uganda", "code": "UG"},
{"name": "Ukraine", "code": "UA"},
{"name": "United Arab Emirates", "code": "AE"},
{"name": "United Kingdom", "code": "GB"},
{"name": "United States", "code": "US"},
{"name": "United States Minor Outlying Islands", "code": "UM"},
{"name": "Uruguay", "code": "UY"},
{"name": "Uzbekistan", "code": "UZ"},
{"name": "Vanuatu", "code": "VU"},
{"name": "Venezuela", "code": "VE"},
{"name": "Viet Nam", "code": "VN"},
{"name": "Virgin Islands, British", "code": "VG"},
{"name": "Virgin Islands, U.S.", "code": "VI"},
{"name": "Wallis and Futuna", "code": "WF"},
{"name": "Western Sahara", "code": "EH"},
{"name": "Yemen", "code": "YE"},
{"name": "Zambia", "code": "ZM"},
{"name": "Zimbabwe", "code": "ZW"}
]
}

View File

@ -8,6 +8,7 @@
</a>
<div :class="{'submenuhide': activeMenuIndex !== 0, 'submenushow': activeMenuIndex === 0}">
<div>
<router-link to="/autocomplete">&#9679; AutoComplete</router-link>
<router-link to="/checkbox">&#9679; Checkbox</router-link>
<router-link to="/chips">&#9679; Chips</router-link>
<router-link to="/dropdown">&#9679; Dropdown</router-link>

View File

@ -1,5 +1,6 @@
@import '../../components/common/Common.css';
@import '../../components/accordion/Accordion.css';
@import '../../components/autocomplete/AutoComplete.css';
@import '../../components/button/Button.css';
@import '../../components/card/Card.css';
@import '../../components/checkbox/Checkbox.css';

View File

@ -0,0 +1,163 @@
.p-autocomplete {
width: auto;
zoom: 1;
cursor: pointer;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
position: relative;
display: inline-block;
}
.p-autocomplete .p-autocomplete-dropdown {
height: 100%;
width: 2em;
margin-right: 0;
vertical-align: top;
}
.p-autocomplete .p-autocomplete-input {
padding-right: 1.5em;
}
.p-autocomplete-loader {
position: absolute;
right: .25em;
top: 50%;
margin-top: -.5em;
}
.p-autocomplete-query {
font-weight: bold;
}
.p-autocomplete .p-autocomplete-panel {
min-width: 100%;
}
.p-autocomplete-panel {
position: absolute;
overflow: auto;
}
.p-autocomplete-panel .p-autocomplete-list {
padding: 0;
margin: 0;
border: 0 none;
}
.p-autocomplete-panel .p-autocomplete-list-item {
border: 0 none;
cursor: pointer;
font-weight: normal;
margin: 1px 0;
padding: 0.186em 0.313em;
text-align: left;
}
.p-autocomplete .p-button-icon-only,
.p-autocomplete .p-button-icon-only:enabled:hover,
.p-autocomplete .p-button-icon-only:enabled:focus,
.p-autocomplete .p-button-icon-only:enabled:active {
border-left: 0 none;
}
/* Multiple Selection */
.p-autocomplete-multiple-container {
display: inline-block;
vertical-align: middle;
}
.p-autocomplete-multiple-container.p-inputtext {
clear: left;
cursor: text;
list-style-type: none;
margin: 0;
overflow: hidden;
padding: 0 1.5em 0 .25em;
}
.p-autocomplete-token {
cursor: default;
display: inline-block;
vertical-align: middle;
overflow: hidden;
padding: .125em .5em;
white-space: nowrap;
position: relative;
margin-right: .125em;
border: 0 none;
font-size: .9em;
}
.p-autocomplete-token-label {
display: block;
margin-right: 2em;
}
.p-autocomplete-token-icon {
margin-top: -.5em;
position: absolute;
right: 0.2em;
top: 50%;
cursor: pointer;
}
.p-autocomplete-input-token {
display: inline-block;
vertical-align: middle;
list-style-type: none;
margin: 0 0 0 .125em;
padding: .25em .25em .25em 0;
}
.p-autocomplete-input-token input {
border: 0 none;
width: 10em;
outline: medium none;
background-color: transparent;
margin: 0;
padding: 0;
box-shadow: none;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
}
.p-autocomplete-dd .p-autocomplete-loader {
right: 2.25em;
}
.p-autocomplete-dd input,
.p-autocomplete-dd .p-autocomplete-multiple-container {
-moz-border-radius-topright: 0px;
-webkit-border-top-right-radius: 0px;
border-top-right-radius: 0px;
-moz-border-radius-bottomright: 0px;
-webkit-border-bottom-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.p-autocomplete-dd .p-autocomplete-dropdown {
-moz-border-radius-topleft: 0px;
-webkit-border-top-left-radius: 0px;
border-top-left-radius: 0px;
-moz-border-radius-bottomleft: 0px;
-webkit-border-bottom-left-radius: 0px;
border-bottom-left-radius: 0px;
}
/** AutoComplete **/
.p-fluid .p-autocomplete,
.p-fluid .p-autocomplete-input {
width: 100%;
}
.p-fluid .p-autocomplete.p-autocomplete-dd .p-autocomplete-input,
.p-fluid .p-autocomplete.p-autocomplete-dd .p-autocomplete-multiple-container {
width: calc(100% - 2em);
}
.p-fluid .p-autocomplete .p-autocomplete-dropdown.p-button {
width: 2em;
}

View File

@ -0,0 +1,224 @@
<template>
<span :class="containerClass">
<input ref="input" :class="inputClass" v-bind="$attrs" v-on="listeners" :value="inputValue" type="text" autoComplete="off">
<i className="p-autocomplete-loader pi pi-spinner pi-spin" v-show="searching"></i>
<transition name="p-input-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<div ref="overlay" class="p-autocomplete-panel" :style="{'max-height': scrollHeight}" v-if="overlayVisible">
<ul class="p-autocomplete-items p-autocomplete-list p-component">
<li v-for="(item, i) of suggestions" class="p-autocomplete-list-item" :key="i" @click="onItemClick($event, item)">
<slot name="item" :item="item" :index="i">
{{getItemContent(item)}}
</slot>
</li>
</ul>
</div>
</transition>
</span>
</template>
<script>
import ObjectUtils from '../utils/ObjectUtils';
import DomHandler from '../utils/DomHandler';
export default {
inheritAttrs: false,
props: {
value: null,
suggestions: Array,
dropdown: Boolean,
multiple: Boolean,
disabled: Boolean,
field: String,
scrollHeight: {
type: String,
default: '200px'
},
minLength: {
type: Number,
default: 1
},
delay: {
type: Number,
default: 300
},
},
timeout: null,
outsideClickListener: null,
data() {
return {
searching: false,
focused: false,
filled: false,
overlayVisible: false
};
},
watch: {
suggestions() {
if (this.searching) {
if (this.suggestions && this.suggestions.length)
this.showOverlay();
else
this.hideOverlay();
this.searching = false;
}
}
},
methods: {
onOverlayEnter() {
this.alignOverlay();
this.bindOutsideClickListener();
},
onOverlayLeave() {
this.unbindOutsideClickListener();
},
alignOverlay() {
DomHandler.relativePosition(this.$refs.overlay, this.$refs.input);
},
bindOutsideClickListener() {
if (!this.outsideClickListener) {
this.outsideClickListener = (event) => {
if (this.overlayVisible && this.$refs.overlay && this.isOutsideClicked()) {
this.hideOverlay();
}
};
document.addEventListener('click', this.outsideClickListener);
}
},
isOutsideClicked() {
if (this.multiple) {
return !this.$refs.overlay.contains(event.target) && event.target !== this.$refs.input;
}
else {
return !this.$refs.overlay.contains(event.target) && event.target !== this.$refs.input;
}
},
unbindOutsideClickListener() {
if (this.outsideClickListener) {
document.removeEventListener('click', this.outsideClickListener);
this.outsideClickListener = null;
}
},
onItemClick(event, item) {
if (this.multiple) {
/*this.inputEl.value = '';
if (!this.isSelected(option)) {
let newValue = this.props.value ? [...this.props.value, option] : [option];
this.updateModel(event, newValue);
}*/
}
else {
this.$emit('input', item);
}
this.$emit('select', {
originalEvent: event,
value: item
});
this.focus();
this.hideOverlay();
},
getItemContent(item) {
return this.field ? ObjectUtils.resolveFieldData(item, this.field) : item;
},
showOverlay() {
this.overlayVisible = true;
},
hideOverlay() {
this.overlayVisible = false;
},
focus() {
if (this.multiple)
this.$refs.multiInput.focus();
else
this.$refs.input.focus();
},
search(event, query, source) {
//allow empty string but not undefined or null
if (query === undefined || query === null) {
return;
}
//do not search blank values on input change
if (source === 'input' && query.trim().length === 0) {
return;
}
this.searching = true;
this.$emit('complete', {
originalEvent: event,
query: query
});
}
},
computed: {
listeners() {
return {
...this.$listeners,
input: event => {
if (this.timeout) {
clearTimeout(this.timeout);
}
let query = event.target.value;
if (!this.multiple) {
this.$emit('input', query);
}
if (query.length === 0) {
this.hideOverlay();
this.$emit('clear');
}
else {
if (query.length >= this.minLength) {
this.timeout = setTimeout(() => {
this.search(event, query, 'input');
}, this.delay);
}
else {
this.hidePanel();
}
}
},
focus: event => {
this.focused = true;
this.$emit('focus', event);
},
blur: event => {
this.focused = false;
this.$emit('blur', event);
}
};
},
containerClass() {
return ['p-autocomplete p-component', {
'p-autocomplete-dd': this.dropdown,
'p-autocomplete-multiple': this.multiple,
'p-inputwrapper-filled': this.filled,
'p-inputwrapper-focus': this.focused
}];
},
inputClass() {
return ['p-autocomplete-input p-inputtext p-component', {
'p-autocomplete-dd-input': this.dropdown,
'p-disabled': this.disabled
}];
},
inputValue() {
if (this.value) {
if (this.field) {
const resolvedFieldData = ObjectUtils.resolveFieldData(this.value, this.field);
return resolvedFieldData != null ? resolvedFieldData : this.value;
}
else
return value;
}
else {
return '';
}
}
}
}
</script>

View File

@ -1,6 +1,7 @@
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import AutoComplete from './components/autocomplete/AutoComplete';
import Accordion from './components/accordion/Accordion';
import AccordionTab from './components/accordion/AccordionTab';
import Button from './components/button/Button';
@ -39,6 +40,7 @@ Vue.config.productionTip = false;
Vue.component('Accordion', Accordion);
Vue.component('AccordionTab', AccordionTab);
Vue.component('AutoComplete', AutoComplete);
Vue.component('Button', Button);
Vue.component('Card', Card);
Vue.component('Chart', Chart);

View File

@ -16,6 +16,11 @@ export default new Router({
name: 'accordion',
component: () => import('./views/accordion/AccordionDemo.vue')
},
{
path: '/autocomplete',
name: 'autocomplete',
component: () => import('./views/autocomplete/AutoCompleteDemo.vue')
},
{
path: '/button',
name: 'button',

View File

@ -0,0 +1,8 @@
import axios from 'axios'
export default class CountryService {
getCountries() {
return axios.get('demo/data/countries.json').then(res => res.data.data);
}
}

View File

@ -0,0 +1,51 @@
<template>
<div>
<div class="content-section introduction">
<div class="feature-intro">
<h1>AutoComplete</h1>
<p>AutoComplete is an input component that provides real-time suggestions when being typed.</p>
</div>
</div>
<div class="content-section implementation">
<h3 class="first">Basic</h3>
<AutoComplete v-model="country" :suggestions="countriesBasic" @complete="searchCountryBasic($event)" field="name" />
<span style="marginLeft: .5em">Country: {{country || 'none'}}</span>
</div>
</div>
</template>
<script>
import CountryService from '../../service/CountryService';
export default {
data() {
return {
countries: null,
country: null,
countriesBasic: null
}
},
countryService: null,
created() {
this.countryService = new CountryService();
},
mounted() {
this.countryService.getCountries().then(data => this.countries = data);
},
methods: {
searchCountryBasic(event) {
setTimeout(() => {
let results = this.countries.filter((country) => {
return country.name.toLowerCase().startsWith(event.query.toLowerCase());
});
this.countriesBasic = results;
}, 250);
}
}
}
</script>
<style>
</style>