UNPKG

framevuerk

Version:

A RTL and mobile-first Vue.js framevuerk.

203 lines 6.48 kB
import utility from '../../utility' import template from './template.pug' export default ({ template: template, data: ()=>{ return { pShow: false, searchQuery: '', highlightedOption: null } }, props: { options: { type: Array }, value: { required: true }, multiple: { type: Boolean, default: false }, required: { type: Boolean, default: false }, search: { type: Boolean, default: true }, placeholder: { type: String, default : '' } }, methods: { toggle: function(){ this[this.pShow?'close':'open'](); }, open: function(){ this.searchQuery = ''; this.pShow = true; this.$emit('open'); utility.doIt( ()=>{ this.pFocus('select'); }); }, close: function(){ this.pShow = false; this.$emit('close'); }, closeIf: function(event){ utility.doIt( ()=>{ var focusedElem = document.querySelector(':focus'); if( focusedElem !== null && !utility.isDescendant(this.$refs.select.$el, focusedElem) ){ this.close(); } }); }, highlightOption: function(option={index:null}){ this.highlightedOption = option.index; }, pFocus: function(el="input"){ if( el == 'input' ){ this.$refs.inputEl.$el.focus(); } else{ if( this.search ){ this.$refs.searchQueryEl.$el.focus(); } else{ this.$refs.justFocusEl.focus(); } } }, pSetValue: function(value){ this.$emit('input', value); this.$emit('change'); }, pIsSelected: function(option={index:null,value:null}){ if( this.multiple && typeof this.value === 'object' && this.value !== null){ return this.value.indexOf( option.value ) !== -1; } else{ return this.value === option.value; } }, pKeyDown: function(event){ switch(event.which){ case 38: //up this.highlightedOption = this.highlightedOption == null? this.pOptions.length: this.highlightedOption; this.highlightedOption = this.highlightedOption-1 < 0? this.pOptions.length-1: this.highlightedOption-1; break; case 40: // down this.highlightedOption = this.highlightedOption == null? -1: this.highlightedOption; this.highlightedOption = this.highlightedOption+1 >= this.pOptions.length? 0: this.highlightedOption+1; break; case 37: case 39: //left, right break; case 13: // enter event.preventDefault(); if( this.highlightedOption !== null ){ this.clickOption( this.pOptions[ this.highlightedOption ], true ); } else{ this.close(); } break; case 27: //esc this.close(); /* default: this.highlightedOption = null; */ } }, clickOption: function(option={index:null,value:null}, setHighlight = false){ if( option.value === null ){ if( this.multiple ){ this.pSetValue( [] ); } else{ this.pSetValue( null ); } } else if( this.multiple ){ let newValue = this.value; if( this.pIsSelected(option) ){ newValue.splice( newValue.indexOf(option.value) , 1); } else{ newValue.push( option.value ); } this.pSetValue( newValue ); } else{ this.pSetValue( option.value ); } if(setHighlight){ this.pFocus('select'); this.highlightOption( option ); } else{ this.highlightOption(); } }, setStructure: function(){ // bug if( this.multiple ){ this.pSetValue( [] ); this.$emit('change'); } else{ this.pSetValue( null ); } } }, created: function(){ this.setStructure(); }, mounted: function(){ }, computed: { pOptions: function(){ let ret = []; this.options.forEach( (option,index)=>{ let text = typeof option == 'object' && option !== null? option.text: option; let value = typeof option == 'object' && option !== null? option.value: option; if( utility.contains(text, this.searchQuery) || utility.contains(value, this.searchQuery) ){ ret.push({ index: index, text: text, value: value }); } }); return ret; }, displayValue: function(){ let ret = []; for( let i = 0; i < this.pOptions.length; i++ ){ if( this.pIsSelected(this.pOptions[i]) ){ ret.push( this.pOptions[i].text ); } } return ret; } }, watch: { highlightedOption: function(){ if( this.highlightedOption !== null ){ let focusedEl = this.$refs.optionElem[this.highlightedOption]; if( focusedEl ){ if( !utility.isInViewport(focusedEl, 100) ){ focusedEl.scrollIntoView(); } } } } } })