优化input/button/date组件;完成select组件
parent
f2cb1beecf
commit
4ac76f3e54
|
@ -41,6 +41,9 @@
|
||||||
&:active {
|
&:active {
|
||||||
border-color: nth($cgr, 1);
|
border-color: nth($cgr, 1);
|
||||||
}
|
}
|
||||||
|
&::-moz-focus-inner {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
|
|
|
@ -343,6 +343,7 @@ export default class Input {
|
||||||
}
|
}
|
||||||
items.forEach((it, i) => {
|
items.forEach((it, i) => {
|
||||||
if (i === this.props.mvidx) {
|
if (i === this.props.mvidx) {
|
||||||
|
this.__LIST__.firstElementChild.scrollTop = it.offsetTop - 150
|
||||||
it.setAttribute('focus', '')
|
it.setAttribute('focus', '')
|
||||||
} else {
|
} else {
|
||||||
it.removeAttribute('focus')
|
it.removeAttribute('focus')
|
||||||
|
@ -475,7 +476,6 @@ export default class Input {
|
||||||
unbind(this.__INPUT__, 'input', this._handleChange)
|
unbind(this.__INPUT__, 'input', this._handleChange)
|
||||||
unbind(this, 'click', this._bubbleFn)
|
unbind(this, 'click', this._bubbleFn)
|
||||||
unbind(document, 'click', this._inactiveFn)
|
unbind(document, 'click', this._inactiveFn)
|
||||||
unbind(this.__INPUT__, 'blur', this._handleBlur)
|
|
||||||
unbind(this.__LIST__, 'click', this._handleSelect)
|
unbind(this.__LIST__, 'click', this._handleSelect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ li {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -136,7 +137,6 @@ li {
|
||||||
dt {
|
dt {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: nth($cgr, 1);
|
color: nth($cgr, 1);
|
||||||
cursor: default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dd {
|
dd {
|
||||||
|
@ -149,6 +149,11 @@ li {
|
||||||
&[sub] {
|
&[sub] {
|
||||||
text-indent: 1em;
|
text-indent: 1em;
|
||||||
}
|
}
|
||||||
|
&[disabled] {
|
||||||
|
color: nth($cgr, 1);
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,16 +222,28 @@ import '../scroll/index'
|
||||||
import '../icon/index'
|
import '../icon/index'
|
||||||
import { nextTick, ebind, bind, unbind } from '../utils'
|
import { nextTick, ebind, bind, unbind } from '../utils'
|
||||||
|
|
||||||
function parseOptions(list) {
|
function parseOptions(arr, props) {
|
||||||
let html = ''
|
let html = ''
|
||||||
for (let it of list) {
|
for (let it of arr) {
|
||||||
if (it.list) {
|
if (it.list) {
|
||||||
html += `<dt>${it.name}</dt>`
|
html += `<dt>${it.name}</dt>`
|
||||||
for (let _ of it.list) {
|
for (let _ of it.list) {
|
||||||
html += `<dd sub data-value="${_.value}">${_.label}</dd>`
|
props.DICT[_.value] = _
|
||||||
|
if (!_.disabled) {
|
||||||
|
props.LIST.push(_)
|
||||||
|
}
|
||||||
|
html += `<dd sub ${
|
||||||
|
_.disabled ? 'disabled' : `data-idx="${props.LIST.length - 1}"`
|
||||||
|
} ${_.value === props.value ? 'focus' : ''}>${_.label}</dd>`
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
html += `<dd data-value="${it.value}">${it.label}</dd>`
|
if (!it.disabled) {
|
||||||
|
props.LIST.push(it)
|
||||||
|
}
|
||||||
|
props.DICT[it.value] = it
|
||||||
|
html += `<dd ${
|
||||||
|
it.disabled ? 'disabled' : `data-idx="${props.LIST.length - 1}"`
|
||||||
|
} ${it.value === props.value ? 'focus' : ''}>${it.label}</dd>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return html
|
return html
|
||||||
|
@ -237,7 +254,8 @@ export default class Select {
|
||||||
label: '',
|
label: '',
|
||||||
placeholder: '',
|
placeholder: '',
|
||||||
multi: '',
|
multi: '',
|
||||||
options: [],
|
value: '',
|
||||||
|
options: '',
|
||||||
mvidx: null, //下拉列表光标的索引ID
|
mvidx: null, //下拉列表光标的索引ID
|
||||||
disabled: false
|
disabled: false
|
||||||
}
|
}
|
||||||
|
@ -275,11 +293,67 @@ export default class Select {
|
||||||
}
|
}
|
||||||
|
|
||||||
get value() {
|
get value() {
|
||||||
return this.__INPUT__.value
|
return this.props.value
|
||||||
}
|
}
|
||||||
|
|
||||||
set value(val) {
|
set value(val) {
|
||||||
this.__INPUT__.value = val
|
var { DICT } = this.props
|
||||||
|
this.props.value = val
|
||||||
|
this.__INPUT__.value = (DICT && DICT[val] && DICT[val].label) || val
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderOptions(options) {
|
||||||
|
this.props.DICT = {}
|
||||||
|
this.props.LIST = []
|
||||||
|
var elem = this.__OPTG__.firstElementChild.firstElementChild
|
||||||
|
|
||||||
|
elem.innerHTML = parseOptions(options, this.props)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动光标选择下拉选项
|
||||||
|
_moveSelect(ev) {
|
||||||
|
var { LIST, DICT } = this.props
|
||||||
|
if (LIST && LIST.length) {
|
||||||
|
ev.preventDefault()
|
||||||
|
var step = ev.keyCode === 38 ? -1 : 1
|
||||||
|
var items = Array.from(
|
||||||
|
this.__OPTG__.firstElementChild.firstElementChild.children
|
||||||
|
).filter(it => {
|
||||||
|
return it.tagName === 'DD' && !it.hasAttribute('disabled')
|
||||||
|
})
|
||||||
|
if (this.props.mvidx === null) {
|
||||||
|
this.props.mvidx = 0
|
||||||
|
} else {
|
||||||
|
this.props.mvidx += step
|
||||||
|
}
|
||||||
|
if (this.props.mvidx < 0) {
|
||||||
|
this.props.mvidx = 0
|
||||||
|
} else if (this.props.mvidx > items.length - 1) {
|
||||||
|
this.props.mvidx = items.length - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
items.forEach((it, i) => {
|
||||||
|
if (i === this.props.mvidx) {
|
||||||
|
this.__OPTG__.firstElementChild.scrollTop = it.offsetTop - 150
|
||||||
|
it.setAttribute('focus', '')
|
||||||
|
} else {
|
||||||
|
it.removeAttribute('focus')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发列表选择
|
||||||
|
_fetchSelect(idx, ev) {
|
||||||
|
var item = this.props.LIST[idx]
|
||||||
|
this.value = item.value
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent('select', {
|
||||||
|
detail: item
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this.props.active = false
|
||||||
|
this.__OPTG__.classList.remove('show')
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -301,24 +375,60 @@ export default class Select {
|
||||||
this.__OUTER__.setAttribute('append', '')
|
this.__OUTER__.setAttribute('append', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initPos() {
|
||||||
|
var { x, y, width } = this.getBoundingClientRect()
|
||||||
|
this.props.active = true
|
||||||
|
this.__OPTG__.style.cssText = `left:${x}px;top:${y +
|
||||||
|
50}px;width:${width}px;`
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------- */
|
||||||
|
/* ----------------- 各种事件 ------------------ */
|
||||||
|
/* ---------------------------------------------------- */
|
||||||
|
|
||||||
|
// 键盘事件
|
||||||
|
this._handleKeydown = ebind(this.__INPUT__, 'keydown', ev => {
|
||||||
|
if (this.disabled || this.readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// up: 38, down: 40
|
||||||
|
if (ev.keyCode === 38 || ev.keyCode === 40) {
|
||||||
|
if (!this.props.active) {
|
||||||
|
initPos.call(this)
|
||||||
|
this.__OPTG__.classList.toggle('show', true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return this._moveSelect(ev)
|
||||||
|
}
|
||||||
|
// 回车触发select事件
|
||||||
|
if (ev.keyCode === 13) {
|
||||||
|
if (this.props.mvidx !== null) {
|
||||||
|
return this._fetchSelect(this.props.mvidx, ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 渲染建议列表
|
// 渲染建议列表
|
||||||
this._parseOptGroup = bind(this.__INPUT__, 'click', ev => {
|
this._activeFn = bind(this.__INPUT__, 'click', ev => {
|
||||||
var { options: list } = this.props
|
var { options } = this.props
|
||||||
let { x, y, width } = this.getBoundingClientRect()
|
|
||||||
log(list, this.props)
|
initPos.call(this)
|
||||||
if (list && list.length) {
|
this.__OPTG__.classList.toggle('show', true)
|
||||||
this.__OPTG__.firstElementChild.firstElementChild.innerHTML = parseOptions(
|
})
|
||||||
list
|
|
||||||
)
|
// 选择选项
|
||||||
this.__OPTG__.classList.toggle('show', true)
|
this._handleSelect = bind(this.__OPTG__, 'click', ev => {
|
||||||
this.__OPTG__.style.cssText = `left:${x}px;top:${y +
|
if (ev.target.tagName === 'DD' && !ev.target.hasAttribute('disabled')) {
|
||||||
50}px;width:${width}px;`
|
this._fetchSelect(ev.target.dataset.idx, ev)
|
||||||
} else {
|
this.dispatchEvent(new CustomEvent('input'))
|
||||||
this.__OPTG__.classList.toggle('show', false)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this._bubbleFn = ebind(this, 'click')
|
this._bubbleFn = ebind(this, 'click')
|
||||||
|
this._inactiveFn = bind(document, 'click', ev => {
|
||||||
|
this.__OPTG__.classList.toggle('show', false)
|
||||||
|
this.props.active = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(name, old, val) {
|
watch(name, old, val) {
|
||||||
|
@ -335,8 +445,9 @@ export default class Select {
|
||||||
case 'options':
|
case 'options':
|
||||||
if (val) {
|
if (val) {
|
||||||
try {
|
try {
|
||||||
this.props.options = JSON.parse(val)
|
this._renderOptions(JSON.parse(val))
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
|
this.removeAttribute('options')
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -352,5 +463,13 @@ export default class Select {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unmount() {
|
||||||
|
unbind(this.__INPUT__, 'keydown', this._handleKeydown)
|
||||||
|
unbind(this.__INPUT__, 'click', this._activeFn)
|
||||||
|
unbind(this, 'click', this._bubbleFn)
|
||||||
|
unbind(document, 'click', this._inactiveFn)
|
||||||
|
unbind(this.__OPTG__, 'click', this._handleSelect)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -553,16 +553,20 @@ export default class DatePicker {
|
||||||
if (ev.target.tagName === 'SPAN') {
|
if (ev.target.tagName === 'SPAN') {
|
||||||
let { calendar, last } = this.props
|
let { calendar, last } = this.props
|
||||||
let item = calendar.list[ev.target.dataset.idx]
|
let item = calendar.list[ev.target.dataset.idx]
|
||||||
if (
|
if (item.disabled) {
|
||||||
item.disabled ||
|
|
||||||
(last &&
|
|
||||||
calendar.year === last.year &&
|
|
||||||
calendar.month === last.month &&
|
|
||||||
item.day === last.day)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 日期未变化时, 直接隐藏, 不作处理
|
||||||
|
if (
|
||||||
|
last &&
|
||||||
|
calendar.year === last.year &&
|
||||||
|
calendar.month === last.month &&
|
||||||
|
item.day === last.day
|
||||||
|
) {
|
||||||
|
return this._inactiveFn()
|
||||||
|
}
|
||||||
|
|
||||||
this._updateValue(item._, true)
|
this._updateValue(item._, true)
|
||||||
nextTick(_ => this.dispatchEvent(new CustomEvent('input')))
|
nextTick(_ => this.dispatchEvent(new CustomEvent('input')))
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
|
|
|
@ -94,7 +94,16 @@ export default class Scroll {
|
||||||
}
|
}
|
||||||
|
|
||||||
set scrollTop(n) {
|
set scrollTop(n) {
|
||||||
// this.__BOX__.scrollTop
|
n = +n
|
||||||
|
if (n === n) {
|
||||||
|
var { sh, oh, yh } = this.props
|
||||||
|
|
||||||
|
this.__BOX__.scrollTop = n
|
||||||
|
var fixedY = (this.__BOX__.scrollTop / (sh - oh)) * (oh - yh)
|
||||||
|
this.props.thumbY = fixedY
|
||||||
|
|
||||||
|
this.__Y__.style.transform = `translateY(${fixedY}px)`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get scrollLeft() {
|
get scrollLeft() {
|
||||||
|
@ -102,7 +111,16 @@ export default class Scroll {
|
||||||
}
|
}
|
||||||
|
|
||||||
set scrollLeft(val) {
|
set scrollLeft(val) {
|
||||||
// this.__BOX__.scrollLeft
|
n = +n
|
||||||
|
if (n === n) {
|
||||||
|
var { sw, ow, xw } = this.props
|
||||||
|
|
||||||
|
this.__BOX__.scrollLeft = n
|
||||||
|
var fixedX = (this.__BOX__.scrollLeft / (sw - ow)) * (ow - xw)
|
||||||
|
this.props.thumbX = fixedX
|
||||||
|
|
||||||
|
this.__X__.style.transform = `translateX(${fixedX}px)`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get scrollHeight() {
|
get scrollHeight() {
|
||||||
|
@ -110,7 +128,7 @@ export default class Scroll {
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchScrollX(moveX) {
|
_fetchScrollX(moveX) {
|
||||||
var { sw, ow, xw, sh, oh, yh } = this.props
|
var { sw, ow, xw } = this.props
|
||||||
|
|
||||||
if (moveX < 0) {
|
if (moveX < 0) {
|
||||||
moveX = 0
|
moveX = 0
|
||||||
|
@ -124,7 +142,7 @@ export default class Scroll {
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchScrollY(moveY) {
|
_fetchScrollY(moveY) {
|
||||||
var { sw, ow, xw, sh, oh, yh } = this.props
|
var { sh, oh, yh } = this.props
|
||||||
|
|
||||||
if (moveY < 0) {
|
if (moveY < 0) {
|
||||||
moveY = 0
|
moveY = 0
|
||||||
|
|
Reference in New Issue