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:
Rijn 2017-01-17 17:31:51 -06:00
commit 50f4ac7088
27 changed files with 463 additions and 249 deletions

View file

@ -21,7 +21,7 @@
width: `${this.width}px`,
height: `${this.height}`,
left: `${this.left}px`
}
};
}
},
compiled () {

View file

@ -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 () {

View file

@ -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 () {

View file

@ -28,6 +28,10 @@
inline: {
type: Boolean,
default: false
},
showMessage: {
type: Boolean,
default: true
}
},
data () {

View file

@ -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: {

View file

@ -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();

View file

@ -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>

View file

@ -0,0 +1,2 @@
import Rate from './rate.vue';
export default Rate;

View 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>

View file

@ -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 () {

View file

@ -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,

View file

@ -83,6 +83,10 @@ export default {
page: '/page',
goto: 'Goto',
p: ''
},
rate: {
star: 'Star',
stars: 'Stars'
}
}
};

View file

@ -83,6 +83,10 @@ export default {
page: '条/页',
goto: '跳至',
p: '页'
},
rate: {
star: '星',
stars: '星'
}
}
};

View file

@ -83,6 +83,10 @@ export default {
page: '條/頁',
goto: '跳至',
p: '頁'
},
rate: {
star: '星',
stars: '星'
}
}
};

View file

@ -35,4 +35,5 @@
@import "date-picker";
@import "time-picker";
@import "form";
@import "carousel";
@import "carousel";
@import "rate";

View 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;
}
}

View file

@ -14,6 +14,7 @@
@selected-color : fade(@primary-color, 90%);
@tooltip-color : #fff;
@subsidiary-color : #9ea7b4;
@rate-star-color : #f5a623;
// Base
@body-background : #fff;