Skip to content

Commit

Permalink
fix(datepicker): fix datepicker style bug
Browse files Browse the repository at this point in the history
fix datepicker panel to flex style
  • Loading branch information
luchunyu committed Nov 14, 2018
1 parent cb2e611 commit 1c6ebbb
Show file tree
Hide file tree
Showing 6 changed files with 467 additions and 3 deletions.
7 changes: 7 additions & 0 deletions src/components/datepicker/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
background: color(var(--white));
padding: 1em;
font-size: 14px;
display: flex;
padding-bottom: 4em;

&.is-sm {
font-size: 12px;
Expand Down Expand Up @@ -106,6 +108,10 @@
.c-datepicker__text {
text-align: center;
margin: 0.5em 0;
position: absolute;
bottom: 1em;
padding-right: 2em;
width: 100%;
}

.c-datepicker__btns {
Expand All @@ -121,6 +127,7 @@
padding-top: 6px;
background-color: #fff;
overflow: auto;
width: 6em;
}

.c-datepicker__sidebar ul {
Expand Down
8 changes: 5 additions & 3 deletions src/components/datepicker/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
:class="className"
)
c-icon(name="x-circle")
.c-datepicker__icon(:clas="className")
.c-datepicker__icon(:class="className")
c-icon(name="calendar")
c-input(
v-if="type == 'daterange' || type == 'monthrange'"
Expand Down Expand Up @@ -81,6 +81,7 @@ import './index.css'
import validatable from '@scripts/mixins/validatable'
import resettable from '@scripts/mixins/resettable'
import ZIndexManager from '@scripts/utils/zIndexManager.js'
import { getScrollBarSize } from '@util'
import Icon from '../icon/index.vue'
import Input from '../input/index.vue'
Expand Down Expand Up @@ -285,10 +286,11 @@ export default {
const clientY = clientRect.y
const compTop = windowH - droplistHeight - scrollHeight
const marginRight = 15 // scrollbar width
const left = droplistWidth + clientRect.left + window.pageXOffset > windowW ? windowW - droplistWidth - marginRight : clientRect.left + window.pageXOffset
const marginRight = getScrollBarSize() + 5 // scrollbar width
const left = droplistWidth + clientRect.left + marginRight + window.pageXOffset > windowW ? windowW - droplistWidth - marginRight : clientRect.left + window.pageXOffset
const top = droplistHeight + clientHeight + clientY + scrollHeight > windowH ? compTop : defaultTop
const zIndex = ZIndexManager.next()
return `
position: absolute;
top: ${top}px;
Expand Down
104 changes: 104 additions & 0 deletions src/components/timepicker/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* c-timepicker
*/
@import url('../../styles/variables.css');

.c-timepicker {
display: inline-block;
position: relative;
border-radius: 0.2em;
width: 15em;

& .c-input-wrap {
width: 100%;
}

& input {
margin: 0;
width: 100%;
}

& .c-timepicker__icon {
position: absolute;
right: 0.5em;
top: 50%;
transform: translateY(-50%);
color: color(var(--text-color) l(65%));
}

& .c-timepicker__hovericon {
z-index: -1;
opacity: 0;
}

&:hover .c-timepicker__hovericon + .c-timepicker__icon {
z-index: -1;
opacity: 0;
}

&:hover .c-timepicker__hovericon {
z-index: 2;
opacity: 1;
}
}

.c-timepicker__panel {
display: flex;
width: 12em;

& li {
list-style: none;
color: color(var(--text-color));
-webkit-box-sizing: content-box;
box-sizing: content-box;
margin: 0;
padding: 0 0 0 12px;
width: 100%;
height: 2em;
line-height: 2em;
text-align: left;
cursor: pointer;
}

& li.active {
font-weight: bold;
color: color(var(--text-color));
background: color(var(--gray) l(95%));
}
}
.c-timepicker__wrap {
display: none;
background: #fff;
border: 1px solid #d4d9db;
overflow: hidden;

& ul {
list-style: none;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0 0 12em;
text-align: center;
margin: 0;
}

& .c-timepicker__item {
flex: 1;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
position: relative;
max-height: 14em;

&:hover {
overflow-y: auto;
}
}

& .c-timepicker__item + .c-timepicker__item {
border-left: 1px solid color(var(--gray) l(85%));
}
}
.show {
display: block;
}
50 changes: 50 additions & 0 deletions src/components/timepicker/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Timepicker
route: /component/timepicker
layout: component
---

# Timepicker

选择或者输入时间

## 基本用法

```html
<c-timepicker
v-model="time"
:disabled="disabled"
:defaultValue="defaultTime"
@change="timeChange"
></c-timepicker>

<script>
export default {
data () {
return {
disabled: false,
time: '',
defaultTime: '12:23:45'
}
},
methods: {
timeChange (time) {
this.time = time
console.log('time changed')
}
}
}
</script>
```

## API

### 属性

| 属性 | 类型 | 默认值 | 说明 |
|-----|------|-------|-----|
| placeholder | String | 请选择时间 | 未进行选择时的提示 |
| disabled | Boolean | false | 时间框是否被禁用 |
| format | String | hh:mm:ss | 时间格式,如果使用12小时制,可设置'hh:mm:ss a' |
| size | String | | 尺寸大小 |
| defaultValue | moment | | 默认显示的时间 |
169 changes: 169 additions & 0 deletions src/components/timepicker/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<template lang="pug">
.c-timepicker(@click="openTimePanel")
.c-timepicker__icon.c-timepicker__hovericon(:class="sizeClassName"
v-if="!disabled")
c-icon(name="x-circle")
.c-timepicker__icon(:class="sizeClassName")
c-icon(type="feather" name="clock")
c-input(
v-model="showValue"
:placeholder="placeholder"
:disabled="disabled"
:size="size"
@change="valueChange"
)
.c-timepicker__wrap(
ref="timepickerPanel"
:class="{show: isOpen}"
)
c-timepanel(
:isShown="isOpen"
:hour="hour"
:minute="minute"
:second="second"
:defaultValue="defaultValue"
@change="timeChange"
)
</template>

<script>
import { VueTypes } from '@util'
import './index.css'
import { getScrollBarSize } from '@util'
import ZIndexManager from '../../scripts/utils/zIndexManager.js'
export default {
name: 'c-timepicker',
props: {
value: String,
size: String,
format: {
type: String,
default: 'hh:mm:ss'
},
disabled: Boolean,
placeholder: {
type: String,
default: '请输入时间'
},
defaultValue: [String, Date]
},
data () {
return {
timepickerPanel: '',
showValue: '',
isOpen: false,
hour: '',
minute: '',
second: '',
lastValue: ''
}
},
computed: {
sizeClassName () {
return this.size ? `is-size-${this.size}` : ''
}
},
watch: {
isOpen () {
if (this.isOpen) {
this.resize()
this.lastValue = this.showValue
window.addEventListener('mouseup', this.onBodyClick, true)
} else {
this.checkValue()
window.removeEventListener('mouseup', this.onBodyClick, true)
}
},
value (newVal) {
if (newVal !== this.showValue) {
this.showValue = newVal
[this.hour, this.minute, this.second] = this.showValue ? this.showValue.split(':') : ['', '', '']
}
}
},
mounted () {
this.showValue = this.value
if (this.showValue) {
[this.hour, this.minute, this.second] = this.showValue.split(':')
}
if (typeof document === 'object') {
this.timepickerPanel = this.$el.querySelector('.c-timepicker__wrap')
document.body.appendChild(this.timepickerPanel)
this.resize()
window.addEventListener('resize', this.resize, false)
}
},
methods: {
valueChange (value) {
console.log(value)
if (this.showValue) {
[this.hour, this.minute, this.second] = this.showValue.split(':')
} else {
this.hour = ''
this.minute = ''
this.second = ''
}
},
checkValue () {
console.log('check')
if (this.second > 59 || this.minute > 59 || this.hour > 23) {
this.showValue = this.lastValue
// [this.hour, this.minute, this.second] = this.lastValue.split(':')
}
},
timeChange ({ hour, minute, second }) {
this.hour = hour
this.minute = minute
this.second = second
this.showValue = `${this.hour}:${this.minute}:${this.second}`
},
onBodyClick (e) {
const isInPicker = this.$el.contains(e.target)
const isInPanel = this.timepickerPanel.contains(e.target)
if (!isInPicker && !isInPanel) {
this.$emit('change', this.showValue)
this.close()
this.$el.focus()
}
},
close () {
this.isOpen = false
},
openTimePanel () {
if (this.disabled) return
this.isOpen = true
console.log('open time')
},
getStyle () {
const clientRect = this.$el.getBoundingClientRect()
const windowH = window.innerHeight
const windowW = window.innerWidth
const marginTop = 2
const scrollHeight = document.body.scrollWidth > window.innerWidth ? 20 : 0
const droplistHeight = this.timepickerPanel.clientHeight
const droplistWidth = this.timepickerPanel.clientWidth
const defaultTop = clientRect.top + clientRect.height + marginTop + window.pageYOffset
const clientHeight = clientRect.height + marginTop
const clientY = clientRect.y
const compTop = windowH - droplistHeight - scrollHeight
const marginRight = getScrollBarSize() + 5 // scrollbar width
const left = droplistWidth + clientRect.left + marginRight + window.pageXOffset > windowW ? windowW - droplistWidth - marginRight : clientRect.left + window.pageXOffset
const top = droplistHeight + clientHeight + clientY + scrollHeight > windowH ? compTop : defaultTop
const zIndex = ZIndexManager.next()
return `
position: absolute;
top: ${top}px;
left: ${left}px;
z-index: ${zIndex};
`
},
resize () {
this.$nextTick(() => {
this.timepickerPanel.style.cssText = this.getStyle()
})
}
}
}
</script>
Loading

0 comments on commit 1c6ebbb

Please sign in to comment.