Merge branch 'master' of https://github.com/iview/iview into carousel
Conflicts: src/styles/components/index.less test/app.vue test/main.js
This commit is contained in:
commit
50f4ac7088
27 changed files with 463 additions and 249 deletions
|
@ -21,7 +21,7 @@
|
|||
width: `${this.width}px`,
|
||||
height: `${this.height}`,
|
||||
left: `${this.left}px`
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
|
|
|
@ -24,12 +24,13 @@
|
|||
</template>
|
||||
<script>
|
||||
import Icon from '../icon/icon.vue';
|
||||
import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist';
|
||||
import { getStyle } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-carousel';
|
||||
|
||||
export default {
|
||||
name: 'Carousel',
|
||||
components: { Icon },
|
||||
props: {
|
||||
arrow: {
|
||||
type: String,
|
||||
|
@ -74,7 +75,7 @@
|
|||
slideInstances: [],
|
||||
timer: null,
|
||||
ready: false
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
|
@ -93,13 +94,13 @@
|
|||
return [
|
||||
`${prefixCls}-arrow`,
|
||||
`${prefixCls}-arrow-${this.arrow}`
|
||||
]
|
||||
];
|
||||
},
|
||||
dotsClasses () {
|
||||
return [
|
||||
`${prefixCls}-dots`,
|
||||
`${prefixCls}-dots-${this.dots}`
|
||||
]
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -127,7 +128,7 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
updateSlides (init, slot = false) {
|
||||
updateSlides (init ) {
|
||||
let slides = [];
|
||||
let index = 1;
|
||||
|
||||
|
@ -173,12 +174,10 @@
|
|||
index += offset;
|
||||
while (index < 0) index += this.slides.length;
|
||||
index = index % this.slides.length;
|
||||
this.$emit('on-change', this.currentIndex, index);
|
||||
this.currentIndex = index;
|
||||
},
|
||||
dotsEvent (event, n) {
|
||||
if (event === this.trigger && this.currentIndex !== n) {
|
||||
this.$emit('on-change', this.currentIndex, n);
|
||||
this.currentIndex = n;
|
||||
}
|
||||
},
|
||||
|
@ -208,6 +207,7 @@
|
|||
this.setAutoplay();
|
||||
},
|
||||
currentIndex (val, oldVal) {
|
||||
this.$emit('on-change', oldVal, val);
|
||||
this.updateOffset();
|
||||
},
|
||||
height () {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label">{{ label }}</label>
|
||||
<div :class="[prefixCls + '-content']" :style="contentStyles">
|
||||
<slot></slot>
|
||||
<div transition="fade" :class="[prefixCls + '-error-tip']" v-if="validateState === 'error'">{{ validateMessage }}</div>
|
||||
<div transition="fade" :class="[prefixCls + '-error-tip']" v-if="validateState === 'error' && showMessage && form.showMessage">{{ validateMessage }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -61,6 +61,10 @@
|
|||
},
|
||||
validateStatus: {
|
||||
type: Boolean
|
||||
},
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
|
|
@ -144,32 +144,52 @@
|
|||
preventDefault (e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
up () {
|
||||
if (this.upDisabled) {
|
||||
up (e) {
|
||||
const targetVal = Number(e.target.value);
|
||||
if (this.upDisabled && isNaN(targetVal)) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('up');
|
||||
this.changeStep('up', e);
|
||||
},
|
||||
down () {
|
||||
if (this.downDisabled) {
|
||||
down (e) {
|
||||
const targetVal = Number(e.target.value);
|
||||
if (this.downDisabled && isNaN(targetVal)) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('down');
|
||||
this.changeStep('down', e);
|
||||
},
|
||||
changeStep (type) {
|
||||
changeStep (type, e) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetVal = Number(e.target.value);
|
||||
let val = Number(this.value);
|
||||
const step = Number(this.step);
|
||||
if (isNaN(val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == 'up') {
|
||||
// input a number, and key up or down
|
||||
if (!isNaN(targetVal)) {
|
||||
if (type === 'up') {
|
||||
if (addNum(targetVal, step) <= this.max) {
|
||||
val = targetVal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (type === 'down') {
|
||||
if (addNum(targetVal, -step) >= this.min) {
|
||||
val = targetVal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'up') {
|
||||
val = addNum(val, step);
|
||||
} else if (type == 'down') {
|
||||
} else if (type === 'down') {
|
||||
val = addNum(val, -step);
|
||||
}
|
||||
this.setValue(val);
|
||||
|
@ -190,10 +210,10 @@
|
|||
keyDown (e) {
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault();
|
||||
this.up();
|
||||
this.up(e);
|
||||
} else if (e.keyCode === 40) {
|
||||
e.preventDefault();
|
||||
this.down();
|
||||
this.down(e);
|
||||
}
|
||||
},
|
||||
change (event) {
|
||||
|
@ -230,7 +250,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
compiled () {
|
||||
this.changeVal(this.value);
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -5,12 +5,20 @@
|
|||
<Icon type="ios-arrow-down" :class="[prefixCls + '-submenu-title-icon']"></Icon>
|
||||
</div>
|
||||
<ul :class="[prefixCls]" v-if="mode === 'vertical'" v-show="opened"><slot></slot></ul>
|
||||
<Drop v-else v-show="opened" placement="bottom" transition="slide-up" v-ref:drop><slot></slot></Drop>
|
||||
<Drop
|
||||
v-else
|
||||
v-show="opened"
|
||||
placement="bottom"
|
||||
transition="slide-up"
|
||||
v-ref:drop
|
||||
:style="dropStyle"><slot></slot></Drop>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
import Drop from '../select/dropdown.vue';
|
||||
import Icon from '../icon/icon.vue';
|
||||
import { getStyle } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-menu';
|
||||
|
||||
export default {
|
||||
|
@ -30,7 +38,8 @@
|
|||
return {
|
||||
prefixCls: prefixCls,
|
||||
active: false,
|
||||
opened: false
|
||||
opened: false,
|
||||
dropWidth: parseFloat(getStyle(this.$el, 'width'))
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -49,6 +58,12 @@
|
|||
},
|
||||
accordion () {
|
||||
return this.$parent.accordion;
|
||||
},
|
||||
dropStyle () {
|
||||
let style = {};
|
||||
|
||||
if (this.dropWidth) style.minWidth = `${this.dropWidth}px`;
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -94,6 +109,8 @@
|
|||
opened (val) {
|
||||
if (this.mode === 'vertical') return;
|
||||
if (val) {
|
||||
// set drop a width to fixed when menu has fixed position
|
||||
this.dropWidth = parseFloat(getStyle(this.$el, 'width'));
|
||||
this.$refs.drop.update();
|
||||
} else {
|
||||
this.$refs.drop.destroy();
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
:class="[prefixCls + '-rel']"
|
||||
v-el:reference
|
||||
@click="handleClick"
|
||||
@mousedown="handleFocus"
|
||||
@mouseup="handleBlur">
|
||||
@mousedown="handleFocus(false)"
|
||||
@mouseup="handleBlur(false)">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-popper']" :style="styles" transition="fade" v-el:popper v-show="visible">
|
||||
|
@ -91,7 +91,8 @@
|
|||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
showTitle: true
|
||||
showTitle: true,
|
||||
isInput: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -133,14 +134,14 @@
|
|||
}
|
||||
this.visible = false;
|
||||
},
|
||||
handleFocus () {
|
||||
if (this.trigger !== 'focus' || this.confirm) {
|
||||
handleFocus (fromInput = true) {
|
||||
if (this.trigger !== 'focus' || this.confirm || (this.isInput && !fromInput)) {
|
||||
return false;
|
||||
}
|
||||
this.visible = true;
|
||||
},
|
||||
handleBlur () {
|
||||
if (this.trigger !== 'focus' || this.confirm) {
|
||||
handleBlur (fromInput = true) {
|
||||
if (this.trigger !== 'focus' || this.confirm || (this.isInput && !fromInput)) {
|
||||
return false;
|
||||
}
|
||||
this.visible = false;
|
||||
|
@ -164,12 +165,41 @@
|
|||
ok () {
|
||||
this.visible = false;
|
||||
this.$emit('on-ok');
|
||||
},
|
||||
getInputChildren () {
|
||||
const $input = this.$els.reference.querySelectorAll('input');
|
||||
const $textarea = this.$els.reference.querySelectorAll('textarea');
|
||||
let $children = null;
|
||||
|
||||
if ($input.length) {
|
||||
$children = $input[0];
|
||||
} else if ($textarea.length) {
|
||||
$children = $textarea[0];
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
compiled () {
|
||||
if (!this.confirm) {
|
||||
this.showTitle = this.$els.title.innerHTML != `<div class="${prefixCls}-title-inner"></div>`;
|
||||
}
|
||||
// if trigger and children is input or textarea,listen focus & blur event
|
||||
if (this.trigger === 'focus') {
|
||||
const $children = this.getInputChildren();
|
||||
if ($children) {
|
||||
$children.addEventListener('focus', this.handleFocus, false);
|
||||
$children.addEventListener('blur', this.handleBlur, false);
|
||||
this.isInput = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
const $children = this.getInputChildren();
|
||||
if ($children) {
|
||||
$children.removeEventListener('focus', this.handleFocus, false);
|
||||
$children.removeEventListener('blur', this.handleBlur, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
2
src/components/rate/index.js
Normal file
2
src/components/rate/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Rate from './rate.vue';
|
||||
export default Rate;
|
127
src/components/rate/rate.vue
Normal file
127
src/components/rate/rate.vue
Normal file
|
@ -0,0 +1,127 @@
|
|||
<template>
|
||||
<div :class="classes" @mouseleave="handleMouseleave">
|
||||
<div
|
||||
v-for="item in count"
|
||||
:class="starCls(item)"
|
||||
@mousemove="handleMousemove(item, $event)"
|
||||
@click="handleClick(item)">
|
||||
<span :class="[prefixCls + '-star-content']" type="half"></span>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-text']" v-if="showText" v-show="value > 0">
|
||||
<slot>{{ value }} <template v-if="value <= 1">{{ t('i.rate.star') }}</template><template v-else>{{ t('i.rate.stars') }}</template></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Locale from '../../mixins/locale';
|
||||
|
||||
const prefixCls = 'ivu-rate';
|
||||
|
||||
export default {
|
||||
mixins: [ Locale ],
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
allowHalf: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showText: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
hoverIndex: -1,
|
||||
isHover: false,
|
||||
isHalf: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler (val) {
|
||||
this.setHalf(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
starCls (value) {
|
||||
const hoverIndex = this.hoverIndex;
|
||||
const currentIndex = this.isHover ? hoverIndex : this.value;
|
||||
|
||||
let full = false;
|
||||
let isLast = false;
|
||||
|
||||
if (currentIndex > value) full = true;
|
||||
|
||||
if (this.isHover) {
|
||||
isLast = currentIndex === value + 1;
|
||||
} else {
|
||||
isLast = Math.ceil(this.value) === value + 1;
|
||||
}
|
||||
|
||||
return [
|
||||
`${prefixCls}-star`,
|
||||
{
|
||||
[`${prefixCls}-star-full`]: (!isLast && full) || (isLast && !this.isHalf),
|
||||
[`${prefixCls}-star-half`]: isLast && this.isHalf,
|
||||
[`${prefixCls}-star-zero`]: !full
|
||||
}
|
||||
];
|
||||
},
|
||||
handleMousemove(value, event) {
|
||||
if (this.disabled) return;
|
||||
|
||||
this.isHover = true;
|
||||
if (this.allowHalf) {
|
||||
const type = event.target.getAttribute('type') || false;
|
||||
this.isHalf = type === 'half';
|
||||
} else {
|
||||
this.isHalf = false;
|
||||
}
|
||||
this.hoverIndex = value + 1;
|
||||
},
|
||||
handleMouseleave () {
|
||||
if (this.disabled) return;
|
||||
|
||||
this.isHover = false;
|
||||
this.setHalf(this.value);
|
||||
this.hoverIndex = -1;
|
||||
},
|
||||
setHalf (val) {
|
||||
this.isHalf = val.toString().indexOf('.') >= 0;
|
||||
},
|
||||
handleClick (value) {
|
||||
if (this.disabled) return;
|
||||
value++;
|
||||
if (this.isHalf) value -= 0.5;
|
||||
this.value = value;
|
||||
this.$emit('on-change', value);
|
||||
this.$dispatch('on-form-change', value);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -55,7 +55,8 @@
|
|||
this.isFocus = false;
|
||||
},
|
||||
queryChange (val) {
|
||||
this.hidden = !new RegExp(val, 'i').test(this.searchLabel);
|
||||
const parsedQuery = val.replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, '\\$1');
|
||||
this.hidden = !new RegExp(parsedQuery, 'i').test(this.searchLabel);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
|
|
|
@ -28,6 +28,7 @@ import Page from './components/page';
|
|||
import Poptip from './components/poptip';
|
||||
import Progress from './components/progress';
|
||||
import Radio from './components/radio';
|
||||
import Rate from './components/rate';
|
||||
import Slider from './components/slider';
|
||||
import Spin from './components/spin';
|
||||
import Steps from './components/steps';
|
||||
|
@ -86,6 +87,7 @@ const iview = {
|
|||
Progress,
|
||||
Radio,
|
||||
RadioGroup: Radio.Group,
|
||||
Rate,
|
||||
Row,
|
||||
iSelect: Select,
|
||||
Slider,
|
||||
|
|
|
@ -83,6 +83,10 @@ export default {
|
|||
page: '/page',
|
||||
goto: 'Goto',
|
||||
p: ''
|
||||
},
|
||||
rate: {
|
||||
star: 'Star',
|
||||
stars: 'Stars'
|
||||
}
|
||||
}
|
||||
};
|
|
@ -83,6 +83,10 @@ export default {
|
|||
page: '条/页',
|
||||
goto: '跳至',
|
||||
p: '页'
|
||||
},
|
||||
rate: {
|
||||
star: '星',
|
||||
stars: '星'
|
||||
}
|
||||
}
|
||||
};
|
|
@ -83,6 +83,10 @@ export default {
|
|||
page: '條/頁',
|
||||
goto: '跳至',
|
||||
p: '頁'
|
||||
},
|
||||
rate: {
|
||||
star: '星',
|
||||
stars: '星'
|
||||
}
|
||||
}
|
||||
};
|
|
@ -35,4 +35,5 @@
|
|||
@import "date-picker";
|
||||
@import "time-picker";
|
||||
@import "form";
|
||||
@import "carousel";
|
||||
@import "carousel";
|
||||
@import "rate";
|
||||
|
|
72
src/styles/components/rate.less
Normal file
72
src/styles/components/rate.less
Normal file
|
@ -0,0 +1,72 @@
|
|||
@rate-prefix-cls: ~"@{css-prefix}rate";
|
||||
|
||||
.@{rate-prefix-cls} {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
vertical-align: middle;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
&-disabled &-star {
|
||||
&:before,
|
||||
&-content:before {
|
||||
cursor: default;
|
||||
}
|
||||
&:hover {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
&-star {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
font-family: 'Ionicons';
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
&:before,
|
||||
&-content:before {
|
||||
color: #e9e9e9;
|
||||
cursor: pointer;
|
||||
content: "\F4B3";
|
||||
transition: all @transition-time @ease-in-out;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
&:before {
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&-half &-content:before,
|
||||
&-full:before {
|
||||
color: @rate-star-color;
|
||||
}
|
||||
|
||||
&-half:hover &-content:before,
|
||||
&-full:hover:before {
|
||||
color: tint(@rate-star-color, 20%);
|
||||
}
|
||||
}
|
||||
&-text {
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
font-size: @font-size-small;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
@selected-color : fade(@primary-color, 90%);
|
||||
@tooltip-color : #fff;
|
||||
@subsidiary-color : #9ea7b4;
|
||||
@rate-star-color : #f5a623;
|
||||
|
||||
// Base
|
||||
@body-background : #fff;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue