2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-07 07:12:23 +03:00

Merge branch 'feature/custom-filter'

# Conflicts:
#	dev.html
#	yarn.lock
This commit is contained in:
Jeff
2018-01-15 20:02:51 -08:00
8 changed files with 282 additions and 120 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
language: node_js
node_js:
- "5"
- "5.1"
- node
- 8
- 6
after_success:
- codeclimate-test-reporter < ./test/unit/coverage/lcov.info
+8 -1
View File
@@ -31,6 +31,7 @@
<div id="app">
<v-select placeholder="default" :options="options"></v-select>
<v-select placeholder="default, RTL" :options="options" dir="rtl"></v-select>
<v-select placeholder="default, options=[1,5,10]" :options="[1,5,10]"></v-select>
<v-select placeholder="multiple" multiple :options="options"></v-select>
<v-select placeholder="multiple, taggable" multiple taggable :options="options" no-drop></v-select>
<v-select placeholder="multiple, taggable, push-tags" multiple push-tags taggable :options="[{label: 'Foo', value: 'foo'}]"></v-select>
@@ -47,8 +48,14 @@
</template>
</v-select>
<v-select placeholder="disabled" disabled value="disabled"></v-select>
<v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select>
<v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select>
<v-select placeholder="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select>
<v-select placeholder="filtering with fuse.js" label="title" :options="fuseSearchOptions" :filter="fuseSearch">
<template slot="option" scope="option">
<strong>{{ option.title }}</strong><br>
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
</template>
</v-select>
</div>
</body>
+1
View File
@@ -40,6 +40,7 @@
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.4",
"function-bind": "^1.0.2",
"fuse.js": "^3.2.0",
"gh-pages": "^0.11.0",
"gitbook-plugin-codepen": "^0.1.2",
"gitbook-plugin-edit-link": "^2.0.2",
+42 -22
View File
@@ -525,21 +525,6 @@
}
},
/**
* Callback to filter the search result the label text.
* @type {Function}
* @param {Object || String} option
* @param {String} label
* @param {String} search
* @return {Boolean}
*/
filterFunction: {
type: Function,
default(option, label, search) {
return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1
}
},
/**
* An optional callback function that is called each time the selected
* value(s) change. When integrating with Vuex, use this callback to trigger
@@ -593,6 +578,47 @@
default: true
},
/**
* Callback to determine if the provided option should
* match the current search text. Used to determine
* if the option should be displayed.
* @type {Function}
* @param {Object || String} option
* @param {String} label
* @param {String} search
* @return {Boolean}
*/
filterBy: {
type: Function,
default(option, label, search) {
return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1
}
},
/**
* Callback to filter results when search text
* is provided. Default implementation loops
* each option, and returns the result of
* this.filterBy.
* @type {Function}
* @param {Array} list of options
* @param {String} search text
* @param {Object} vSelect instance
* @return {Boolean}
*/
filter: {
"type": Function,
default(options, search) {
return options.filter((option) => {
let label = this.getOptionLabel(option)
if (typeof label === 'number') {
label = label.toString()
}
return this.filterBy(option, label, search)
});
}
},
/**
* User defined function for adding Options
* @type {Function}
@@ -988,13 +1014,7 @@
if (!this.filterable && !this.taggable) {
return this.mutableOptions.slice()
}
let options = this.mutableOptions.filter((option) => {
let label = this.getOptionLabel(option)
if (typeof label === 'number') {
label = label.toString()
}
return this.filterFunction(option, label, this.search)
})
let options = this.search.length ? this.filter(this.mutableOptions, this.search, this) : this.mutableOptions;
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
options.unshift(this.search)
}
+15 -7
View File
@@ -1,8 +1,10 @@
import Vue from 'vue'
import vSelect from './components/Select.vue'
import countries from 'docs/data/advanced.js'
import Fuse from 'fuse.js'
import debounce from 'lodash/debounce'
import resource from 'vue-resource'
import vSelect from './components/Select.vue'
import countries from 'docs/data/advanced.js'
import fuseSearchOptions from './fuseSearchOptions'
Vue.use(resource)
@@ -18,11 +20,12 @@ new Vue({
value: null,
options: countries,
ajaxRes: [],
people: []
people: [],
fuseSearchOptions
},
methods: {
search(search, loading) {
loading(true)
loading(true);
this.getRepositories(search, loading, this)
},
searchPeople(search, loading) {
@@ -37,9 +40,14 @@ new Vue({
}, 250),
getRepositories: debounce((search, loading, vm) => {
vm.$http.get(`https://api.github.com/search/repositories?q=${search}`).then(res => {
vm.ajaxRes = res.data.items
vm.ajaxRes = res.data.items;
loading(false)
})
}, 250)
}, 250),
fuseSearch(options, search) {
return new Fuse(options, {
keys: ['title', 'author.firstName', 'author.lastName'],
}).search(search);
}
}
})
});
+163
View File
@@ -0,0 +1,163 @@
export default [
{
title: "Old Man's War",
author: {
firstName: "John",
lastName: "Scalzi"
}
},
{
title: "The Lock Artist",
author: {
firstName: "Steve",
lastName: "Hamilton"
}
},
{
title: "HTML5",
author: {
firstName: "Remy",
lastName: "Sharp"
}
},
{
title: "Right Ho Jeeves",
author: {
firstName: "P.D",
lastName: "Woodhouse"
}
},
{
title: "The Code of the Wooster",
author: {
firstName: "P.D",
lastName: "Woodhouse"
}
},
{
title: "Thank You Jeeves",
author: {
firstName: "P.D",
lastName: "Woodhouse"
}
},
{
title: "The DaVinci Code",
author: {
firstName: "Dan",
lastName: "Brown"
}
},
{
title: "Angels & Demons",
author: {
firstName: "Dan",
lastName: "Brown"
}
},
{
title: "The Silmarillion",
author: {
firstName: "J.R.R",
lastName: "Tolkien"
}
},
{
title: "Syrup",
author: {
firstName: "Max",
lastName: "Barry"
}
},
{
title: "The Lost Symbol",
author: {
firstName: "Dan",
lastName: "Brown"
}
},
{
title: "The Book of Lies",
author: {
firstName: "Brad",
lastName: "Meltzer"
}
},
{
title: "Lamb",
author: {
firstName: "Christopher",
lastName: "Moore"
}
},
{
title: "Fool",
author: {
firstName: "Christopher",
lastName: "Moore"
}
},
{
title: "Incompetence",
author: {
firstName: "Rob",
lastName: "Grant"
}
},
{
title: "Fat",
author: {
firstName: "Rob",
lastName: "Grant"
}
},
{
title: "Colony",
author: {
firstName: "Rob",
lastName: "Grant"
}
},
{
title: "Backwards, Red Dwarf",
author: {
firstName: "Rob",
lastName: "Grant"
}
},
{
title: "The Grand Design",
author: {
firstName: "Stephen",
lastName: "Hawking"
}
},
{
title: "The Book of Samson",
author: {
firstName: "David",
lastName: "Maine"
}
},
{
title: "The Preservationist",
author: {
firstName: "David",
lastName: "Maine"
}
},
{
title: "Fallen",
author: {
firstName: "David",
lastName: "Maine"
}
},
{
title: "Monster 1959",
author: {
firstName: "David",
lastName: "Maine"
}
}
]
+32 -2
View File
@@ -322,9 +322,9 @@ describe('Select.vue', () => {
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]))
})
it('can use a custom filterFunction passed via props', ()=>{
it('can determine if a given option should match the current search text', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :filterFunction="customFn" :options="[{label: 'Aoo', value: 'foo'}, {label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]" v-model="value"></v-select></div>`,
template: `<div><v-select ref="select" :filter-by="customFn" :options="[{label: 'Aoo', value: 'foo'}, {label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]" v-model="value"></v-select></div>`,
data: {value: 'foo'},
methods:{
customFn: (option, label, search) => label.match(new RegExp('^' + search, 'i'))
@@ -333,6 +333,35 @@ describe('Select.vue', () => {
vm.$refs.select.search = 'a'
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Aoo', value: 'foo'}]))
})
it('can use a custom filtering method', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :filter="customFn" :options="options" v-model="value"></v-select></div>`,
data: {
options: ['foo','bar','baz'],
value: 'foo'
},
methods:{
customFn(options, search, vm) {
return options.filter(option => option.indexOf(search) > 0)
}
}
}).$mount()
vm.$refs.select.search = 'a'
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify(['bar','baz']))
})
it('can filter arrays of numbers', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :options="options"></v-select></div>`,
data: {
options: [1,5,10],
value: 'foo'
},
}).$mount()
vm.$refs.select.search = '5'
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([5]))
})
})
describe('Toggling Dropdown', () => {
@@ -780,6 +809,7 @@ describe('Select.vue', () => {
const vm = new Vue({
template: '<div><v-select :options="[{}]"></v-select></div>',
}).$mount()
vm.$children[0].open = true
Vue.nextTick(() => {
expect(console.warn).toHaveBeenCalledWith(
'[vue-select warn]: Label key "option.label" does not exist in options object {}.' +
+18 -86
View File
@@ -1009,8 +1009,8 @@ caniuse-api@^1.5.2:
lodash.uniq "^4.5.0"
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000792"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000792.tgz#a7dac6dc9f5181b675fd69e5cb06fefb523157f8"
version "1.0.30000789"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000789.tgz#5cf3fec75480041ab162ca06413153141e234325"
caseless@~0.11.0:
version "0.11.0"
@@ -1076,16 +1076,6 @@ change-case@3.0.x:
upper-case "^1.1.1"
upper-case-first "^1.1.0"
cheerio@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
dependencies:
css-select "~1.0.0"
dom-serializer "~0.1.0"
entities "~1.1.1"
htmlparser2 "~3.8.1"
lodash "^3.2.0"
cheerio@^0.20.0:
version "0.20.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35"
@@ -1244,7 +1234,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
commander@2.12.x:
commander@2.12.x, commander@^2.9.0, commander@~2.12.1:
version "2.12.2"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555"
@@ -1260,10 +1250,6 @@ commander@2.9.0, commander@2.9.x:
dependencies:
graceful-readlink ">= 1.0.0"
commander@^2.9.0, commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -1428,15 +1414,6 @@ css-select@^1.1.0, css-select@~1.2.0:
domutils "1.5.1"
nth-check "~1.0.1"
css-select@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0"
dependencies:
boolbase "~1.0.0"
css-what "1.0"
domutils "1.4"
nth-check "~1.0.0"
css-selector-tokenizer@^0.5.1:
version "0.5.4"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.5.4.tgz#139bafd34a35fd0c1428487049e0699e6f6a2c21"
@@ -1452,10 +1429,6 @@ css-selector-tokenizer@^0.7.0:
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css-what@1.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c"
css-what@2.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
@@ -1601,14 +1574,10 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
depd@1.1.1:
depd@1.1.1, depd@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
depd@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
@@ -1679,12 +1648,6 @@ domutils@1.1:
dependencies:
domelementtype "1"
domutils@1.4:
version "1.4.3"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.4.3.tgz#0865513796c6b306031850e175516baf80b72a6f"
dependencies:
domelementtype "1"
domutils@1.5, domutils@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
@@ -2168,6 +2131,10 @@ function-bind@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
fuse.js@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.2.0.tgz#f0448e8069855bf2a3e683cdc1d320e7e2a07ef4"
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -2227,22 +2194,6 @@ gh-pages@^0.11.0:
q-io "1.13.2"
wrench "1.5.8"
gitbook-plugin-codepen@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/gitbook-plugin-codepen/-/gitbook-plugin-codepen-0.1.2.tgz#64fb5ba9be9734328a44bab2214422c044a85f16"
dependencies:
cheerio "^0.19.0"
underscore "^1.8.3"
url-parse "^1.0.0"
gitbook-plugin-edit-link@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/gitbook-plugin-edit-link/-/gitbook-plugin-edit-link-2.0.2.tgz#d8fcd927eced81e7a662a72d59db609eafd7e72f"
gitbook-plugin-github@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/gitbook-plugin-github/-/gitbook-plugin-github-3.0.0.tgz#67457df98a57ea8ef9b2518b88340db370a5317b"
glob-base@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -3371,7 +3322,7 @@ lodash.words@^3.0.0:
dependencies:
lodash._root "^3.0.0"
lodash@^3.2.0, lodash@^3.8.0:
lodash@^3.8.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
@@ -3766,10 +3717,6 @@ normalize-url@^1.4.0:
query-string "^4.1.0"
sort-keys "^1.0.0"
normalize.css@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-7.0.0.tgz#abfb1dd82470674e0322b53ceb1aaf412938e4bf"
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
@@ -3779,7 +3726,7 @@ normalize.css@^7.0.0:
gauge "~2.7.3"
set-blocking "~2.0.0"
nth-check@~1.0.0, nth-check@~1.0.1:
nth-check@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
dependencies:
@@ -4418,10 +4365,6 @@ querystring@0.2.0, querystring@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
querystringify@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb"
randomatic@^1.1.3:
version "1.1.7"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
@@ -4484,7 +4427,7 @@ readable-stream@1.1:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.3.3:
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
@@ -4730,7 +4673,7 @@ require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
requires-port@1.x.x, requires-port@~1.0.0:
requires-port@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -5045,12 +4988,12 @@ stream-browserify@^2.0.1:
readable-stream "^2.0.2"
stream-http@^2.3.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10"
version "2.7.2"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad"
dependencies:
builtin-status-codes "^3.0.0"
inherits "^2.0.1"
readable-stream "^2.3.3"
readable-stream "^2.2.6"
to-arraybuffer "^1.0.0"
xtend "^4.0.0"
@@ -5302,10 +5245,10 @@ uglify-js@2.6.x:
yargs "~3.10.0"
uglify-js@3.3.x:
version "3.3.7"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.7.tgz#28463e7c7451f89061d2b235e30925bf5625e14d"
version "3.3.5"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.5.tgz#4c4143dfe08e8825746675cc49a6874a933b543e"
dependencies:
commander "~2.13.0"
commander "~2.12.1"
source-map "~0.6.1"
uglify-js@^2.6:
@@ -5338,10 +5281,6 @@ ultron@1.0.x:
version "1.0.2"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
underscore@^1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
underscore@~1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
@@ -5387,13 +5326,6 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"
url-parse@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986"
dependencies:
querystringify "~1.0.0"
requires-port "~1.0.0"
url-to-options@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"