Initiated MultiSelect

pull/12/head
cagataycivici 2018-12-30 13:36:20 +03:00
parent cea5b3766b
commit d26fb8196b
7 changed files with 401 additions and 0 deletions

View File

@ -15,6 +15,7 @@
<router-link to="/inputswitch">&#9679; InputSwitch</router-link>
<router-link to="/inputtext">&#9679; InputText</router-link>
<router-link to="/listbox">&#9679; Listbox</router-link>
<router-link to="/multiselect">&#9679; MultiSelect</router-link>
<router-link to="/password">&#9679; Password</router-link>
<router-link to="/radiobutton">&#9679; RadioButton</router-link>
<router-link to="/rating">&#9679; Rating</router-link>

View File

@ -9,6 +9,7 @@
@import '../../components/inputtext/InputText.css';
@import '../../components/inputswitch/InputSwitch.css';
@import '../../components/listbox/Listbox.css';
@import '../../components/multiselect/MultiSelect.css';
@import '../../components/panel/Panel.css';
@import '../../components/password/Password.css';
@import '../../components/progressbar/ProgressBar.css';

View File

@ -0,0 +1,149 @@
/** MultiSelect **/
.p-multiselect {
display: inline-block;
position: relative;
width: auto;
cursor: pointer;
}
.p-multiselect .p-multiselect-trigger {
border-right: none;
border-top: none;
border-bottom: none;
cursor: pointer;
width: 1.5em;
height: 100%;
position: absolute;
right: 0;
top: 0;
padding: 0 .25em;
}
.p-multiselect .p-multiselect-trigger .p-multiselect-trigger-icon {
top: 50%;
left: 50%;
margin-top: -.5em;
margin-left: -.5em;
position: absolute;
}
.p-multiselect .p-multiselect-label-container {
overflow: hidden;
}
.p-multiselect .p-multiselect-label {
display: block;
padding: .25em 2em .25em .25em;
width: auto;
border: none;
cursor: pointer;
text-overflow: ellipsis;
overflow: hidden;
}
.p-multiselect-label-empty {
overflow: hidden;
visibility: hidden;
}
.p-multiselect.p-disabled .p-multiselect-trigger,
.p-multiselect.p-disabled .p-multiselect-label {
cursor: auto
}
.p-multiselect-panel {
padding: 0.2em;
position: absolute;
min-width: 10em;
}
.p-multiselect .p-multiselect-panel {
min-width: 100%;
}
.p-multiselect-panel .p-multiselect-items-wrapper {
overflow: auto;
position: relative;
padding: 0.2em 0;
}
.p-multiselect-panel .p-multiselect-list {
border: 0 none;
}
.p-multiselect-panel .p-multiselect-item {
border: 0 none;
cursor: pointer;
font-weight: normal;
margin: 1px 0;
padding: .125em .25em;
text-align: left;
white-space: nowrap;
display: block;
position: relative;
}
.p-multiselect-panel .p-multiselect-item .p-checkbox {
display: inline-block;
vertical-align: middle;
}
.p-multiselect-panel .p-multiselect-item label {
display: inline-block;
vertical-align: middle;
}
.p-multiselect-header {
margin-bottom: 0.3em;
padding: .25em;
position: relative;
text-align: left;
}
.p-multiselect-header .p-checkbox {
display: inline-block;
vertical-align: middle;
cursor:pointer;
}
.p-multiselect-header .p-multiselect-filter-container {
position: relative;
display: inline-block;
vertical-align: middle;
width: 65%;
}
.p-multiselect-header .p-multiselect-filter-container .p-multiselect-filter-icon {
position: absolute;
top: .25em;
left: .125em;
}
.p-multiselect-header .p-inputtext {
padding: .125em .125em .125em 1.25em;
width: 100%;
}
.p-multiselect-header .p-multiselect-close {
position: absolute;
right: .375em;
top: .375em;
display: block;
border: 0 none;
}
.p-multiselect-header a.p-multiselect-all,
.p-multiselect-header a.p-multiselect-none {
float:left;
margin-right: 10px;
display: block;
}
.p-multiselect-header .p-multiselect-close.p-state-hover {
padding:0px;
}
.p-fluid .p-multiselect {
width: 100%;
box-sizing: border-box;
}

View File

@ -0,0 +1,188 @@
<template>
<div :class="containerClass" @click="onClick">
<div class="p-hidden-accessible">
<input ref="focusInput" type="text" role="listbox" readonly :disabled="disabled" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" :tabindex="tabindex"/>
</div>
<div class="p-multiselect-label-container">
<label :class="labelClass">{{label}}</label>
</div>
<div class="p-multiselect-trigger">
<span class="p-multiselect-trigger-icon pi pi-chevron-down p-c"></span>
</div>
</div>
</template>
<script>
export default {
props: {
value: null,
options: Array,
dataKey: null,
filter: Boolean,
optionLabel: null,
optionValue: null,
optionDisabled: null,
disabled: Boolean,
tabindex: String,
editable: Boolean,
placeholder: String,
scrollHeight: {
type: String,
default: '200px'
},
filterPlaceholder: String
},
data() {
return {
focused: false,
filterValue: null,
overlayVisible: false
};
},
outsideClickListener: null,
beforeDestroy() {
this.unbindOutsideClickListener();
},
updated() {
if (this.overlayVisible && this.filterValue) {
this.alignOverlay();
}
},
methods: {
getOptionLabel(option) {
return ObjectUtils.resolveFieldData(option, this.optionLabel);
},
getOptionValue(option) {
return this.optionValue ? ObjectUtils.resolveFieldData(option, this.optionValue) : option;
},
isOptionDisabled(option) {
return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false;
},
onFocus() {
this.focused = true;
},
onBlur() {
this.focused = false;
},
onClick() {
},
onKeyDown(event) {
switch(event.which) {
//down
case 40:
if (this.visibleOptions && this.overlayVisible && event.altKey) {
this.overlayVisible = true;
}
break;
//space
case 32:
if (!this.overlayVisible) {
this.overlayVisible = true;
event.preventDefault();
}
break;
//enter and escape
case 13:
case 27:
if (this.overlayVisible) {
this.hideOverlay();
event.preventDefault();
}
break;
//tab
case 9:
this.hideOverlay();
break;
default:
break;
}
},
bindOutsideClickListener() {
if (!this.outsideClickListener) {
this.outsideClickListener = (event) => {
if (this.$refs.overlay && !this.$refs.overlay.contains(event.target)) {
this.hideOverlay();
}
};
document.addEventListener('click', this.outsideClickListener);
}
},
unbindOutsideClickListener() {
if (this.outsideClickListener) {
document.removeEventListener('click', this.outsideClickListener);
this.outsideClickListener = null;
}
},
hideOverlay() {
this.overlayVisible = false;
this.unbindOutsideClickListener();
},
getLabelByValue(val) {
let label = null;
if (this.options) {
for (let option of this.options) {
let optionValue = this.getOptionValue(option);
if(ObjectUtils.equals(optionValue, val, this.dataKey)) {
label = this.getOptionLabel(option);
break;
}
}
}
return label;
}
},
computed: {
visibleOptions() {
if (this.filterValue)
return this.options.filter(option => this.getOptionLabel(option).toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1);
else
return this.options;
},
containerClass() {
return [
'p-multiselect p-component p-unselectable-text',
{
'p-disabled': this.disabled,
'p-focus': this.focused
}
];
},
labelClass() {
return [
'p-multiselect-label',
{
'p-placeholder': this.label == null && this.placeholder,
'p-multiselect-label-empty': !this.placeholder
}
];
},
label() {
let label;
if (this.value && this.value.length) {
label = '';
for(let i = 0; i < this.value.length; i++) {
if(i !== 0) {
label += ',';
}
label += this.findLabelByValue(this.value[i]);
}
}
else {
label = this.placeholder || 'p-multiselect';
}
return label;
}
}
}
</script>

View File

@ -12,6 +12,7 @@ import Editor from './components/editor/Editor';
import InputSwitch from './components/inputswitch/InputSwitch';
import InputText from './components/inputtext/InputText';
import Fieldset from './components/fieldset/Fieldset';
import MultiSelect from './components/multiselect/MultiSelect';
import Listbox from './components/listbox/Listbox';
import Panel from './components/panel/Panel';
import Password from './components/password/Password';
@ -46,6 +47,7 @@ Vue.component('p-inputSwitch', InputSwitch);
Vue.component('p-inputtext', InputText);
Vue.component('p-listbox', Listbox);
Vue.component('p-fieldset', Fieldset);
Vue.component('p-multiSelect', MultiSelect);
Vue.component('p-panel', Panel);
Vue.component('p-password', Password);
Vue.component('p-progressBar', ProgressBar);

View File

@ -71,6 +71,11 @@ export default new Router({
name: 'listbox',
component: () => import('./views/listbox/ListboxDemo.vue')
},
{
path: '/multiselect',
name: 'multiselect',
component: () => import('./views/multiselect/MultiSelectDemo.vue')
},
{
path: '/panel',
name: 'panel',

View File

@ -0,0 +1,55 @@
<template>
<div>
<div class="content-section introduction">
<div class="feature-intro">
<h1>MultiSelect</h1>
<p>MultiSelect is used to multiple values from a list of options.</p>
</div>
</div>
<div class="content-section implementation">
<h3 class="first">Basic</h3>
<p-multiSelect v-model="selectedCars1" :options="cars" optionLabel="brand" placeholder="Select Brands" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
selectedCars1: null,
selectedCars2: null,
cars: [
{brand: 'Audi', value: 'Audi'},
{brand: 'Bmw', value: 'Bmw'},
{brand: 'Fiat', value: 'Fiat'},
{brand: 'Honda', value: 'Honda'},
{brand: 'Jaguar', value: 'Jaguar'},
{brand: 'Mercedes', value: 'Mercedes'},
{brand: 'Renault', value: 'Renault'},
{brand: 'Volkswagen', value: 'Volkswagen'},
{brand: 'Volvo', value: 'Volvo'}
]
}
}
}
</script>
<style lang="scss">
.p-multiselect {
min-width: 12em;
}
.p-multiselect-car-option {
img {
vertical-align: middle;
margin-right: .5em;
width: 24px;
}
span {
margin-top: .125em;
}
}
</style>