@makstech/vue-bootstrap-select
Version:
A vue version of bootstrap select
571 lines (547 loc) • 17.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue-clickaway')) :
typeof define === 'function' && define.amd ? define(['exports', 'vue-clickaway'], factory) :
(global = global || self, factory(global.VueBootstrapSelect = {}, global.vueClickaway));
}(this, (function (exports, vueClickaway) { 'use strict';
//
var script = {
name: 'VSelect',
mixins: [vueClickaway.mixin],
props: {
disabled: {
type: Boolean,
default: false,
},
disabledProp: {
type: String,
default: 'disabled',
},
labelClass: {
//
},
labelTitle: {
type: String,
default: 'Nothing selected',
},
labelNotFound: {
type: String,
default: 'No results matched',
},
labelSearchPlaceholder: {
type: String,
default: 'Search',
},
options: {
type: Array,
default: function () { return []; },
},
searchable: {
type: Boolean,
default: false,
},
searchClass: {
//
},
showDefaultOption: {
type: Boolean,
default: false,
},
textProp: {
type: String,
default: 'text',
},
value: {
type: [Object, String, Number],
default: null,
},
valueProp: {
type: String,
default: 'value',
},
},
data: function data() {
return {
show: false,
selectedValue: null,
searchValue: '',
typeAheadPointer: -1,
};
},
computed: {
title: function title() {
return this.selectedValue
? this.getOptionLabel(this.selectedValue)
: this.labelTitle;
},
filteredOptions: function filteredOptions() {
var this$1 = this;
if (this.searchable && this.searchValue.length > 0) {
return this.options.filter(function (item) {
if (typeof item === 'object') {
return (
item[this$1.textProp]
.toLowerCase()
.indexOf(this$1.searchValue.toLowerCase()) !== -1
);
} else {
return (
item.toLowerCase().indexOf(this$1.searchValue.toLowerCase()) !== -1
);
}
});
}
return this.options;
},
reversedOptions: function reversedOptions() {
return [].concat( this.filteredOptions ).reverse();
},
lastOptionIndex: function lastOptionIndex() {
return this.filteredOptions.length - 1;
},
},
watch: {
value: {
immediate: true,
handler: function handler(newVal) {
var this$1 = this;
var index = this.options.findIndex(function (op) { return this$1.isEqualOption(op, newVal); }
);
this.onSelect(newVal, index);
},
},
},
methods: {
onSelect: function onSelect(option, index) {
if (option && !option[this.disabledProp]) {
this.selectedValue = option;
this.typeAheadPointer = index;
this.hideDropdown();
this.$emit('input', option, option[this.valueProp], index);
} else if (option === null) {
this.selectedValue = null;
}
},
onEscape: function onEscape() {
this.hideDropdown();
},
typeAheadUp: function typeAheadUp() {
var this$1 = this;
if (!this.show) {
this.show = true;
}
if (this.typeAheadPointer > 0) {
var nextPointer = this.typeAheadPointer - 1;
var option = this.filteredOptions[nextPointer];
var isDisabled = option ? option[this.disabledProp] || false : false;
if (!isDisabled) {
this.typeAheadPointer--;
} else {
this.typeAheadPointer--;
this.typeAheadUp();
}
} else {
var nextEnabledOption = this.reversedOptions.findIndex(
function (o) { return o[this$1.disabledProp] !== true; }
);
this.typeAheadPointer = this.lastOptionIndex - nextEnabledOption;
}
},
typeAheadDown: function typeAheadDown() {
var this$1 = this;
if (!this.show) {
this.show = true;
}
if (this.typeAheadPointer < this.lastOptionIndex) {
var nextPointer = this.typeAheadPointer + 1;
var option = this.filteredOptions[nextPointer];
var isDisabled = option ? option[this.disabledProp] || false : false;
if (!isDisabled) {
this.typeAheadPointer++;
} else {
this.typeAheadPointer++;
this.typeAheadDown();
}
} else {
this.typeAheadPointer = this.filteredOptions.findIndex(
function (o) { return o[this$1.disabledProp] !== true; }
);
}
},
typeAheadSelect: function typeAheadSelect() {
if (this.filteredOptions[this.typeAheadPointer]) {
this.onSelect(
this.filteredOptions[this.typeAheadPointer],
this.typeAheadPointer
);
}
},
hideDropdown: function hideDropdown() {
this.show = false;
this.searchValue = '';
},
getOptionLabel: function getOptionLabel(option) {
if (typeof option === 'object') {
return option[this.textProp];
}
return option;
},
isSelectedOption: function isSelectedOption(option, index) {
if (this.typeAheadPointer === -1 && this.selectedValue) {
return this.isEqualOption(option, this.selectedValue);
}
return this.typeAheadPointer === index;
},
isEqualOption: function isEqualOption(a, b) {
if (a && b && typeof a === 'object' && typeof b === 'object') {
return (
a[this.textProp] === b[this.textProp] &&
a[this.valueProp] === b[this.valueProp]
);
}
return a === b;
},
toggle: function toggle() {
if (!this.disabled) {
this.show = !this.show;
}
},
},
};
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
if (typeof shadowMode !== 'boolean') {
createInjectorSSR = createInjector;
createInjector = shadowMode;
shadowMode = false;
}
// Vue.extend constructor export interop.
var options = typeof script === 'function' ? script.options : script;
// render functions
if (template && template.render) {
options.render = template.render;
options.staticRenderFns = template.staticRenderFns;
options._compiled = true;
// functional template
if (isFunctionalTemplate) {
options.functional = true;
}
}
// scopedId
if (scopeId) {
options._scopeId = scopeId;
}
var hook;
if (moduleIdentifier) {
// server build
hook = function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__;
}
// inject component styles
if (style) {
style.call(this, createInjectorSSR(context));
}
// register component module identifier for async chunk inference
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier);
}
};
// used by ssr in case component is cached and beforeCreate
// never gets called
options._ssrRegister = hook;
}
else if (style) {
hook = shadowMode
? function (context) {
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
}
: function (context) {
style.call(this, createInjector(context));
};
}
if (hook) {
if (options.functional) {
// register for functional component in vue file
var originalRender = options.render;
options.render = function renderWithStyleInjection(h, context) {
hook.call(context);
return originalRender(h, context);
};
}
else {
// inject component registration as beforeCreate hook
var existing = options.beforeCreate;
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
}
}
return script;
}
/* script */
var __vue_script__ = script;
/* template */
var __vue_render__ = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
{
directives: [
{
name: "on-clickaway",
rawName: "v-on-clickaway",
value: _vm.hideDropdown,
expression: "hideDropdown"
}
],
staticClass: "dropdown bootstrap-select",
class: {
disabled: _vm.disabled
},
on: {
keyup: function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k($event.keyCode, "esc", 27, $event.key, ["Esc", "Escape"])
) {
return null
}
return _vm.onEscape($event)
},
keydown: [
function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"])
) {
return null
}
$event.preventDefault();
return _vm.typeAheadUp($event)
},
function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k($event.keyCode, "down", 40, $event.key, [
"Down",
"ArrowDown"
])
) {
return null
}
$event.preventDefault();
return _vm.typeAheadDown($event)
},
function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k($event.keyCode, "enter", 13, $event.key, "Enter")
) {
return null
}
$event.preventDefault();
return _vm.typeAheadSelect($event)
}
]
}
},
[
_c(
"button",
{
staticClass: "dropdown-toggle form-control",
class: _vm.labelClass,
attrs: { type: "button" },
on: {
click: function($event) {
$event.preventDefault();
return _vm.toggle($event)
}
}
},
[_c("span", { domProps: { innerHTML: _vm._s(_vm.title) } })]
),
_vm._v(" "),
_c(
"div",
{
staticClass: "dropdown-menu",
class: {
show: _vm.show
}
},
[
_c(
"div",
{
directives: [
{
name: "show",
rawName: "v-show",
value: _vm.searchable,
expression: "searchable"
}
],
staticClass: "bs-searchbox"
},
[
_c("input", {
directives: [
{
name: "model",
rawName: "v-model",
value: _vm.searchValue,
expression: "searchValue"
}
],
staticClass: "form-control",
class: _vm.searchClass,
attrs: {
placeholder: _vm.labelSearchPlaceholder,
type: "text",
autofocus: ""
},
domProps: { value: _vm.searchValue },
on: {
input: function($event) {
if ($event.target.composing) {
return
}
_vm.searchValue = $event.target.value;
}
}
})
]
),
_vm._v(" "),
_c(
"ul",
{ staticClass: "dropdown-menu inner show" },
[
_c(
"li",
{
directives: [
{
name: "show",
rawName: "v-show",
value: _vm.searchable && _vm.filteredOptions.length === 0,
expression: "searchable && filteredOptions.length === 0"
}
],
staticClass: "v-dropdown-item"
},
[
_vm._v(
"\n " +
_vm._s(_vm.labelNotFound) +
' "' +
_vm._s(_vm.searchValue) +
'"\n '
)
]
),
_vm._v(" "),
_vm.showDefaultOption
? _c(
"li",
{ staticClass: "dropdown-item disabled default-option" },
[_vm._v("\n " + _vm._s(_vm.labelTitle) + "\n ")]
)
: _vm._e(),
_vm._v(" "),
_vm._l(_vm.filteredOptions, function(option, index) {
return _c(
"li",
{
key: "v-select-" + index,
class: {
disabled: option[_vm.disabledProp]
}
},
[
_c("a", {
staticClass: "dropdown-item",
class: {
active: _vm.isSelectedOption(option, index),
disabled: option[_vm.disabledProp]
},
domProps: {
innerHTML: _vm._s(_vm.getOptionLabel(option))
},
on: {
click: function($event) {
$event.preventDefault();
return _vm.onSelect(option, index)
}
}
})
]
)
})
],
2
)
]
)
]
)
};
var __vue_staticRenderFns__ = [];
__vue_render__._withStripped = true;
/* style */
var __vue_inject_styles__ = undefined;
/* scoped */
var __vue_scope_id__ = undefined;
/* module identifier */
var __vue_module_identifier__ = undefined;
/* functional template */
var __vue_is_functional_template__ = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
var __vue_component__ = normalizeComponent(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
__vue_script__,
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
undefined,
undefined,
undefined
);
// Import vue component
// install function executed by Vue.use()
function install(Vue) {
if (install.installed) { return; }
install.installed = true;
Vue.component('VueBootstrapSelect', __vue_component__);
}
// Create module definition for Vue.use()
var plugin = {
install: install,
};
// To auto-install when vue is found
/* global window global */
var GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(plugin);
}
// It's possible to expose named exports when writing components that can
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
// export const RollupDemoDirective = component;
exports.default = __vue_component__;
Object.defineProperty(exports, '__esModule', { value: true });
})));