mirror of
https://github.com/tenrok/vue-select.git
synced 2026-05-17 02:29:37 +03:00
remove wrapper, start add tests
This commit is contained in:
+70
-49
@@ -119,8 +119,8 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="dropdown v-select" :class="dropdownClasses">
|
||||
<div v-el:toggle @mousedown.prevent="toggleDropdown" class="dropdown-toggle clearfix" type="button">
|
||||
<div class="dropdown v-select" :class="dropdownClasses">
|
||||
<div v-el:toggle @mousedown.prevent="toggleDropdown" class="dropdown-toggle clearfix" type="button">
|
||||
<span class="form-control" v-if="!searchable && isValueEmpty">
|
||||
{{ placeholder }}
|
||||
</span>
|
||||
@@ -132,40 +132,38 @@
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<input
|
||||
v-el:search
|
||||
v-show="searchable"
|
||||
v-model="search"
|
||||
@keydown.delete="maybeDeleteValue"
|
||||
@keyup.esc="onEscape"
|
||||
@keyup.up.prevent="typeAheadUp"
|
||||
@keyup.down.prevent="typeAheadDown"
|
||||
@keyup.enter.prevent="typeAheadSelect"
|
||||
@blur="open = false"
|
||||
@focus="open = true"
|
||||
type="search"
|
||||
class="form-control"
|
||||
:placeholder="searchPlaceholder"
|
||||
:style="{ width: isValueEmpty ? '100%' : 'auto' }"
|
||||
>
|
||||
<input
|
||||
v-el:search
|
||||
v-show="searchable"
|
||||
v-model="search"
|
||||
@keydown.delete="maybeDeleteValue"
|
||||
@keyup.esc="onEscape"
|
||||
@keyup.up.prevent="typeAheadUp"
|
||||
@keyup.down.prevent="typeAheadDown"
|
||||
@keyup.enter.prevent="typeAheadSelect"
|
||||
@blur="open = false"
|
||||
@focus="open = true"
|
||||
type="search"
|
||||
class="form-control"
|
||||
:placeholder="searchPlaceholder"
|
||||
:style="{ width: isValueEmpty ? '100%' : 'auto' }"
|
||||
>
|
||||
|
||||
<i v-el:open-indicator role="presentation" class="open-indicator"></i>
|
||||
</div>
|
||||
<i v-el:open-indicator role="presentation" class="open-indicator"></i>
|
||||
</div>
|
||||
|
||||
<div v-el:dropdown-wrapper v-show="open" :transition="transition" class="dropdown-menu" :style="{ 'max-height': maxHeight }">
|
||||
<ul class="options" v-el:dropdown-menu>
|
||||
<li v-for="option in filteredOptions" track-by="$index" :class="{ active: isOptionSelected(option), highlight: $index === typeAheadPointer }" @mouseover="typeAheadPointer = $index">
|
||||
<a @mousedown.prevent="select(option)">
|
||||
{{ getOptionLabel(option) }}
|
||||
</a>
|
||||
</li>
|
||||
<li transition="fade" v-if="!filteredOptions.length" class="divider"></li>
|
||||
<li transition="fade" v-if="!filteredOptions.length" class="text-center">
|
||||
<slot name="no-options">Sorry, no matching options.</slot>
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-el:dropdown-menu v-show="open" :transition="transition" class="dropdown-menu" :style="{ 'max-height': maxHeight }">
|
||||
<li v-for="option in filteredOptions" track-by="$index" :class="{ active: isOptionSelected(option), highlight: $index === typeAheadPointer }" @mouseover="typeAheadPointer = $index">
|
||||
<a @mousedown.prevent="select(option)">
|
||||
{{ getOptionLabel(option) }}
|
||||
</a>
|
||||
</li>
|
||||
<li transition="fade" v-if="!filteredOptions.length" class="divider"></li>
|
||||
<li transition="fade" v-if="!filteredOptions.length" class="text-center">
|
||||
<slot name="no-options">Sorry, no matching options.</slot>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -478,25 +476,52 @@
|
||||
},
|
||||
|
||||
maybeAdjustScrollPosition() {
|
||||
let pointerHeight = this.$els.dropdownMenu.children[this.typeAheadPointer].offsetHeight
|
||||
let pixelsToPointerTop = 0
|
||||
let bounds = this.viewport()
|
||||
let pixelsToPointerTop = this.pixelsToPointerTop()
|
||||
let pixelsToPointerBottom = this.pixelsToPointerBottom()
|
||||
let pointerHeight = this.pointerHeight()
|
||||
|
||||
for ( let i = 0; i < this.typeAheadPointer; i++ ) {
|
||||
if (pixelsToPointerTop <= bounds.top) {
|
||||
return this.scrollTo(pixelsToPointerTop)
|
||||
} else if (pixelsToPointerBottom >= bounds.bottom) {
|
||||
// return this.scrollTo(( this.pixelsToPointerCenter() - this.$els.dropdownMenu.offsetHeight ) + ( pointerHeight / 2))
|
||||
return this.scrollTo(( this.pixelsToPointerCenter() - this.$els.dropdownMenu.offsetHeight ) + pointerHeight)
|
||||
}
|
||||
},
|
||||
|
||||
pixelsToPointerTop() {
|
||||
let pixelsToPointerTop = 0
|
||||
for (let i = 0; i < this.typeAheadPointer; i++) {
|
||||
pixelsToPointerTop += this.$els.dropdownMenu.children[i].offsetHeight
|
||||
}
|
||||
return pixelsToPointerTop
|
||||
},
|
||||
|
||||
let pixelsToPointerBottom = pixelsToPointerTop + pointerHeight
|
||||
pixelsToPointerBottom() {
|
||||
return this.pixelsToPointerTop() + this.pointerHeight()
|
||||
},
|
||||
|
||||
let bounds = {
|
||||
top: this.$els.dropdownWrapper.scrollTop,
|
||||
bottom: this.$els.dropdownWrapper.offsetHeight + this.$els.dropdownWrapper.scrollTop
|
||||
pixelsToPointerCenter() {
|
||||
return this.pixelsToPointerTop() + ( this.pointerHeight() / 2 )
|
||||
},
|
||||
|
||||
pointerHeight() {
|
||||
return this.$els.dropdownMenu.children[this.typeAheadPointer].offsetHeight
|
||||
},
|
||||
|
||||
/**
|
||||
* The viewport is the currently viewable
|
||||
* portion of the dropdown menu
|
||||
*/
|
||||
viewport() {
|
||||
return {
|
||||
top: this.$els.dropdownMenu.scrollTop,
|
||||
bottom: this.$els.dropdownMenu.offsetHeight + this.$els.dropdownMenu.scrollTop
|
||||
}
|
||||
},
|
||||
|
||||
if( pixelsToPointerTop <= bounds.top ) {
|
||||
this.$els.dropdownWrapper.scrollTop = pixelsToPointerTop
|
||||
} else if ( pixelsToPointerBottom >= bounds.bottom) {
|
||||
this.$els.dropdownWrapper.scrollTop = ( pixelsToPointerBottom - this.$els.dropdownWrapper.offsetHeight ) + pointerHeight
|
||||
}
|
||||
scrollTo(position) {
|
||||
return this.$els.dropdownMenu.scrollTop = position
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -547,10 +572,6 @@
|
||||
|
||||
computed: {
|
||||
|
||||
scrollTop() {
|
||||
return [this.$els.dropdownMenu.scrollTop,this.$el.scrollTop]
|
||||
},
|
||||
|
||||
/**
|
||||
* Classes to be output on .dropdown
|
||||
* @return {Object}
|
||||
|
||||
@@ -365,6 +365,79 @@ describe('Select.vue', () => {
|
||||
vm.$children[0].typeAheadDown()
|
||||
expect(vm.$children[0].typeAheadPointer).toEqual(2)
|
||||
})
|
||||
|
||||
it('should check if the scroll position needs to be adjusted on up arrow keyup', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :options="options"></v-select></div>',
|
||||
components: {vSelect},
|
||||
data: {
|
||||
options: ['one', 'two', 'three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].typeAheadPointer = 1
|
||||
spyOn(vm.$children[0], 'maybeAdjustScrollPosition')
|
||||
trigger(vm.$children[0].$els.search, 'keyup', (e) => e.keyCode = 38)
|
||||
expect(vm.$children[0].maybeAdjustScrollPosition).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should check if the scroll position needs to be adjusted on down arrow keyup', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :options="options" max-height="10"></v-select></div>',
|
||||
components: {vSelect},
|
||||
data: {
|
||||
options: ['one', 'two', 'three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
spyOn(vm.$children[0], 'maybeAdjustScrollPosition')
|
||||
|
||||
vm.$children[0].$els.search.focus()
|
||||
|
||||
trigger(vm.$children[0].$els.search, 'keyup', (e) => e.keyCode = 40)
|
||||
expect(vm.$children[0].maybeAdjustScrollPosition).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should scroll up if the new pointer is above the current viewport bounds', () => {
|
||||
|
||||
|
||||
})
|
||||
|
||||
describe('Measuring pixel distances', () => {
|
||||
it('should calculate pixelsToPointerTop as the sum of the height all options above the pointer', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :options="options"></v-select></div>',
|
||||
components: {vSelect},
|
||||
data: {
|
||||
options: ['one', 'two', 'three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].typeAheadPointer = 1
|
||||
let lineHeight = vm.$children[0].$els.dropdownMenu.children[0].offsetHeight
|
||||
expect(vm.$children[0].pixelsToPointerTop()).toEqual( lineHeight * 2 )
|
||||
})
|
||||
it('should calculate pixelsToPointerBottom as the sum of the height all options above the pointer plus the height of the pointer', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :options="options"></v-select></div>',
|
||||
components: {vSelect},
|
||||
data: {
|
||||
options: ['one', 'two', 'three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].typeAheadPointer = 1
|
||||
let lineHeight = vm.$children[0].$els.dropdownMenu.children[0].offsetHeight
|
||||
console.log(lineHeight)
|
||||
expect(vm.$children[0].pixelsToPointerTop()).toEqual( lineHeight * 10 + lineHeight)
|
||||
})
|
||||
it('should calculate pixelsToPointerCenter', () => {
|
||||
|
||||
})
|
||||
it('should calculate pointerHeight', () => {
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Removing values', () => {
|
||||
@@ -611,4 +684,4 @@ describe('Select.vue', () => {
|
||||
})
|
||||
|
||||
// also see example testing a component with mocks at
|
||||
// https://github.com/vuejs/vueify-example/blob/master/test/unit/a.spec.js#L22-L43
|
||||
// http://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html
|
||||
|
||||
Reference in New Issue
Block a user