Merge remote-tracking branch 'iview/2.0' into 2.0
This commit is contained in:
commit
82f2344b2a
268 changed files with 8115 additions and 24590 deletions
|
@ -48,6 +48,10 @@
|
|||
},
|
||||
offsetBottom: {
|
||||
type: Number
|
||||
},
|
||||
useCapture: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -78,8 +82,8 @@
|
|||
mounted () {
|
||||
// window.addEventListener('scroll', this.handleScroll, false);
|
||||
// window.addEventListener('resize', this.handleScroll, false);
|
||||
on(window, 'scroll', this.handleScroll);
|
||||
on(window, 'resize', this.handleScroll);
|
||||
on(window, 'scroll', this.handleScroll, this.useCapture);
|
||||
on(window, 'resize', this.handleScroll, this.useCapture);
|
||||
this.$nextTick(() => {
|
||||
this.handleScroll();
|
||||
});
|
||||
|
@ -87,8 +91,8 @@
|
|||
beforeDestroy () {
|
||||
// window.removeEventListener('scroll', this.handleScroll, false);
|
||||
// window.removeEventListener('resize', this.handleScroll, false);
|
||||
off(window, 'scroll', this.handleScroll);
|
||||
off(window, 'resize', this.handleScroll);
|
||||
off(window, 'scroll', this.handleScroll, this.useCapture);
|
||||
off(window, 'resize', this.handleScroll, this.useCapture);
|
||||
},
|
||||
methods: {
|
||||
handleScroll () {
|
||||
|
|
|
@ -168,7 +168,9 @@ export default {
|
|||
this.handleScrollTo();
|
||||
this.handleSetInkTop();
|
||||
this.updateTitleOffset();
|
||||
this.upperFirstTitle = this.scrollElement.scrollTop < this.titlesOffsetArr[0].offset;
|
||||
if (this.titlesOffsetArr[0]) {
|
||||
this.upperFirstTitle = this.scrollElement.scrollTop < this.titlesOffsetArr[0].offset;
|
||||
}
|
||||
on(this.scrollContainer, 'scroll', this.handleScroll);
|
||||
on(window, 'hashchange', this.handleHashChange);
|
||||
});
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
remote
|
||||
auto-complete
|
||||
:remote-method="remoteMethod"
|
||||
@on-change="handleChange"
|
||||
@on-select="handleSelect"
|
||||
@on-clickoutside="handleClickOutside"
|
||||
:transfer="transfer">
|
||||
<slot name="input">
|
||||
<i-input
|
||||
|
@ -87,14 +88,14 @@
|
|||
},
|
||||
placement: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['top', 'bottom']);
|
||||
return oneOf(value, ['top', 'bottom', 'top-start', 'bottom-start', 'top-end', 'bottom-end']);
|
||||
},
|
||||
default: 'bottom'
|
||||
},
|
||||
transfer: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return this.$IVIEW.transfer === '' ? false : this.$IVIEW.transfer;
|
||||
return !this.$IVIEW || this.$IVIEW.transfer === '' ? false : this.$IVIEW.transfer;
|
||||
}
|
||||
},
|
||||
name: {
|
||||
|
@ -113,7 +114,8 @@
|
|||
computed: {
|
||||
inputIcon () {
|
||||
let icon = '';
|
||||
if (this.clearable && this.currentValue) {
|
||||
//#6161 #7
|
||||
if (this.clearable && this.currentValue && !this.disabled) {
|
||||
icon = 'ios-close';
|
||||
} else if (this.icon) {
|
||||
icon = this.icon;
|
||||
|
@ -150,9 +152,10 @@
|
|||
remoteMethod (query) {
|
||||
this.$emit('on-search', query);
|
||||
},
|
||||
handleChange (val) {
|
||||
handleSelect (val) {
|
||||
if (val === undefined || val === null) return;
|
||||
this.currentValue = val;
|
||||
|
||||
this.$refs.input.blur();
|
||||
this.$emit('on-select', val);
|
||||
},
|
||||
|
@ -167,6 +170,11 @@
|
|||
this.currentValue = '';
|
||||
this.$refs.select.reset();
|
||||
this.$emit('on-clear');
|
||||
},
|
||||
handleClickOutside(){
|
||||
this.$nextTick(() => {
|
||||
this.$refs.input.blur();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -67,9 +67,15 @@ const Transition = {
|
|||
export default {
|
||||
name: 'CollapseTransition',
|
||||
functional: true,
|
||||
render(h, { children }) {
|
||||
props: {
|
||||
appear: Boolean
|
||||
},
|
||||
render(h, { children, props }) {
|
||||
const data = {
|
||||
on: Transition
|
||||
on: Transition,
|
||||
props: {
|
||||
appear: props.appear
|
||||
}
|
||||
};
|
||||
|
||||
return h('transition', data, children);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<transition :name="transitionName" @enter="handleEnter" @leave="handleLeave">
|
||||
<transition :name="transitionName" @enter="handleEnter" @leave="handleLeave" appear>
|
||||
<div :class="classes" :style="styles">
|
||||
<template v-if="type === 'notice'">
|
||||
<div :class="contentClasses" ref="content" v-html="content"></div>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
<Icon type="ios-arrow-back"></Icon>
|
||||
</button>
|
||||
<div :class="[prefixCls + '-list']">
|
||||
<div :class="[prefixCls + '-track', showCopyTrack ? '' : 'higher']" :style="trackStyles" ref="originTrack">
|
||||
<div :class="[prefixCls + '-track', showCopyTrack ? '' : 'higher']" :style="trackStyles" ref="originTrack" @click="handlerClickEvent('currentIndex')">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-track', showCopyTrack ? 'higher' : '']" :style="copyTrackStyles" ref="copyTrack" v-if="loop">
|
||||
<div :class="[prefixCls + '-track', showCopyTrack ? 'higher' : '']" :style="copyTrackStyles" @click="handlerClickEvent('copyTrackIndex')" ref="copyTrack" v-if="loop">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" :class="arrowClasses" class="right" @click="arrowEvent(1)">
|
||||
|
@ -113,10 +113,13 @@
|
|||
];
|
||||
},
|
||||
trackStyles () {
|
||||
// #6076
|
||||
const visibleStyle = this.trackIndex === -1 ? 'hidden' : 'visible';
|
||||
return {
|
||||
width: `${this.trackWidth}px`,
|
||||
transform: `translate3d(${-this.trackOffset}px, 0px, 0px)`,
|
||||
transition: `transform 500ms ${this.easing}`
|
||||
transition: `transform 500ms ${this.easing}`,
|
||||
visibility : visibleStyle
|
||||
};
|
||||
},
|
||||
copyTrackStyles () {
|
||||
|
@ -125,7 +128,7 @@
|
|||
transform: `translate3d(${-this.trackCopyOffset}px, 0px, 0px)`,
|
||||
transition: `transform 500ms ${this.easing}`,
|
||||
position: 'absolute',
|
||||
top: 0
|
||||
//top: 0
|
||||
};
|
||||
},
|
||||
arrowClasses () {
|
||||
|
@ -142,6 +145,9 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
handlerClickEvent(type){
|
||||
this.$emit('on-click',this[type]);
|
||||
},
|
||||
// find option component
|
||||
findChild (cb) {
|
||||
const find = function (child) {
|
||||
|
@ -195,8 +201,8 @@
|
|||
child.width = this.listWidth;
|
||||
child.height = typeof this.height === 'number' ? `${this.height}px` : this.height;
|
||||
});
|
||||
|
||||
this.trackWidth = (this.slides.length || 0) * this.listWidth;
|
||||
const slidesLength = this.slides.length || 0;
|
||||
this.trackWidth = slidesLength * this.listWidth;
|
||||
},
|
||||
// use when slot changed
|
||||
slotChange () {
|
||||
|
@ -266,8 +272,10 @@
|
|||
},
|
||||
dotsEvent (event, n) {
|
||||
let curIndex = this.showCopyTrack ? this.copyTrackIndex : this.trackIndex;
|
||||
const oldCurrentIndex = this.currentIndex;
|
||||
if (event === this.trigger && curIndex !== n) {
|
||||
this.updateTrackIndex(n);
|
||||
this.$emit('on-change', oldCurrentIndex, this.currentIndex);
|
||||
this.$emit('input', n);
|
||||
// Reset autoplay timer when trigger be activated
|
||||
this.setAutoplay();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
v-show="filterable && query === ''"
|
||||
@click="handleFocus">{{ displayRender }}</div>
|
||||
<Icon type="ios-close-circle" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon>
|
||||
<Icon type="ios-arrow-down" :class="[prefixCls + '-arrow']"></Icon>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" :class="[prefixCls + '-arrow']"></Icon>
|
||||
</slot>
|
||||
</div>
|
||||
<transition name="transition-drop">
|
||||
|
@ -44,10 +44,11 @@
|
|||
[selectPrefixCls + '-item-disabled']: item.disabled
|
||||
}]"
|
||||
v-for="(item, index) in querySelections"
|
||||
:key="index"
|
||||
@click="handleSelectItem(index)" v-html="item.display"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul v-show="filterable && query !== '' && !querySelections.length" :class="[prefixCls + '-not-found-tip']"><li>{{ localeNotFoundText }}</li></ul>
|
||||
<ul v-show="(filterable && query !== '' && !querySelections.length) || !data.length" :class="[prefixCls + '-not-found-tip']"><li>{{ localeNotFoundText }}</li></ul>
|
||||
</div>
|
||||
</Drop>
|
||||
</transition>
|
||||
|
@ -207,7 +208,7 @@
|
|||
for (let i = 0; i < arr.length; i++) {
|
||||
let item = arr[i];
|
||||
item.__label = label ? label + ' / ' + item.label : item.label;
|
||||
item.__value = value ? value + ',' + item.value : item.value;
|
||||
item.__value = value ? [...value, item.value] : [item.value];
|
||||
|
||||
if (item.children && item.children.length) {
|
||||
getSelections(item.children, item.__label, item.__value);
|
||||
|
@ -232,6 +233,41 @@
|
|||
return item;
|
||||
});
|
||||
return selections;
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-down';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.cascader.arrow) {
|
||||
type = this.$IVIEW.cascader.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.customArrow) {
|
||||
type = this.$IVIEW.cascader.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.arrowSize) {
|
||||
size = this.$IVIEW.cascader.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -241,7 +277,7 @@
|
|||
this.currentValue = this.selected = this.tmpSelected = [];
|
||||
this.handleClose();
|
||||
this.emitValue(this.currentValue, oldVal);
|
||||
// this.$broadcast('on-clear');
|
||||
// this.$broadcast('on-clear');
|
||||
this.broadcast('Caspanel', 'on-clear');
|
||||
},
|
||||
handleClose () {
|
||||
|
@ -293,7 +329,7 @@
|
|||
this.query = '';
|
||||
this.$refs.input.currentValue = '';
|
||||
const oldVal = JSON.stringify(this.currentValue);
|
||||
this.currentValue = item.value.split(',');
|
||||
this.currentValue = item.value;
|
||||
// use setTimeout for #4786, can not use nextTick, because @on-find-selected use nextTick
|
||||
setTimeout(() => {
|
||||
this.emitValue(this.currentValue, oldVal);
|
||||
|
@ -316,7 +352,7 @@
|
|||
if ('__label' in new_item) {
|
||||
delete new_item.__label;
|
||||
}
|
||||
if ('children' in new_item && new_item.children.length) {
|
||||
if (Array.isArray(new_item.children) && new_item.children.length) {
|
||||
new_item.children = new_item.children.map(i => deleteData(i));
|
||||
}
|
||||
return new_item;
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
<template>
|
||||
<li :class="classes">
|
||||
{{ data.label }}
|
||||
<i v-if="showArrow" class="ivu-icon ivu-icon-ios-arrow-forward"></i>
|
||||
<i v-if="showLoading" class="ivu-icon ivu-icon-ios-loading ivu-load-loop"></i>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" v-if="showArrow" />
|
||||
<i v-if="showLoading" class="ivu-icon ivu-icon-ios-loading ivu-load-loop ivu-cascader-menu-item-loading"></i>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon/icon.vue';
|
||||
|
||||
export default {
|
||||
name: 'Casitem',
|
||||
components: { Icon },
|
||||
props: {
|
||||
data: Object,
|
||||
prefixCls: String,
|
||||
|
@ -28,6 +31,41 @@
|
|||
},
|
||||
showLoading () {
|
||||
return 'loading' in this.data && this.data.loading;
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-forward';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.customItemArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.cascader.itemArrow) {
|
||||
type = this.$IVIEW.cascader.itemArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.customItemArrow) {
|
||||
type = this.$IVIEW.cascader.customItemArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cascader.itemArrowSize) {
|
||||
size = this.$IVIEW.cascader.itemArrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,9 +7,18 @@
|
|||
:prefix-cls="prefixCls"
|
||||
:data="item"
|
||||
:tmp-item="tmpItem"
|
||||
@click.native.stop="handleClickItem(item)"
|
||||
@mouseenter.native.stop="handleHoverItem(item)"></Casitem>
|
||||
</ul><Caspanel v-if="sublist && sublist.length" :prefix-cls="prefixCls" :data="sublist" :disabled="disabled" :trigger="trigger" :change-on-select="changeOnSelect"></Caspanel>
|
||||
@click.native.stop="handleClickItem(item, $event)"
|
||||
@mouseenter.native.stop="handleHoverItem(item)"
|
||||
></Casitem>
|
||||
</ul>
|
||||
<Caspanel
|
||||
v-if="sublist && sublist.length"
|
||||
:prefix-cls="prefixCls"
|
||||
:data="sublist"
|
||||
:disabled="disabled"
|
||||
:trigger="trigger"
|
||||
:change-on-select="changeOnSelect">
|
||||
</Caspanel>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -48,15 +57,25 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickItem (item) {
|
||||
isIcon(node){
|
||||
let nodeName = (node.nodeName || '').toLocaleUpperCase();
|
||||
let isIvu = node.classList.contains('ivu-icon');
|
||||
if(nodeName == 'I' && isIvu){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleClickItem (item, ev) {
|
||||
let isIcon = this.isIcon(ev.target);
|
||||
if (this.trigger !== 'click' && item.children && item.children.length) return; // #1922
|
||||
this.handleTriggerItem(item, false, true);
|
||||
this.handleTriggerItem(item, false, true,isIcon);
|
||||
},
|
||||
handleHoverItem (item) {
|
||||
if (this.trigger !== 'hover' || !item.children || !item.children.length) return; // #1922
|
||||
this.handleTriggerItem(item, false, true);
|
||||
this.handleTriggerItem(item, false, true,false);
|
||||
},
|
||||
handleTriggerItem (item, fromInit = false, fromUser = false) {
|
||||
//#6158 -- default fromInit = false to fromInit = true;
|
||||
handleTriggerItem (item, fromInit = true, fromUser = false,isIcon=false) {
|
||||
if (item.disabled) return;
|
||||
|
||||
const cascader = findComponentUpward(this, 'Cascader');
|
||||
|
@ -89,7 +108,7 @@
|
|||
|
||||
if (item.children && item.children.length){
|
||||
this.sublist = item.children;
|
||||
this.dispatch('Cascader', 'on-result-change', {
|
||||
!isIcon && this.dispatch('Cascader', 'on-result-change', {
|
||||
lastValue: false,
|
||||
changeOnSelect: this.changeOnSelect,
|
||||
fromInit: fromInit
|
||||
|
@ -104,7 +123,7 @@
|
|||
}
|
||||
} else {
|
||||
this.sublist = [];
|
||||
this.dispatch('Cascader', 'on-result-change', {
|
||||
!isIcon && this.dispatch('Cascader', 'on-result-change', {
|
||||
lastValue: true,
|
||||
changeOnSelect: this.changeOnSelect,
|
||||
fromInit: fromInit
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
<div class="ivu-cell-arrow" v-if="to">
|
||||
<slot name="arrow">
|
||||
<Icon type="ios-arrow-forward"></Icon>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,6 +83,41 @@
|
|||
}
|
||||
];
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-forward';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cell.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.cell.arrow) {
|
||||
type = this.$IVIEW.cell.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cell.customArrow) {
|
||||
type = this.$IVIEW.cell.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.cell.arrowSize) {
|
||||
size = this.$IVIEW.cell.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickItem (event, new_window) {
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
},
|
||||
methods: {
|
||||
updateModel (update) {
|
||||
this.childrens = findComponentsDownward(this, 'Checkbox');
|
||||
this.childrens = findComponentsDownward(this, 'Checkbox', 'CheckboxGroup');
|
||||
if (this.childrens) {
|
||||
const { value } = this;
|
||||
this.childrens.forEach(child => {
|
||||
|
|
|
@ -42,12 +42,13 @@
|
|||
methods: {
|
||||
setActive () {
|
||||
const activeKey = this.getActiveKey();
|
||||
this.$nextTick(() => {
|
||||
this.$children.forEach((child, index) => {
|
||||
const name = child.name || index.toString();
|
||||
|
||||
this.$children.forEach((child, index) => {
|
||||
const name = child.name || index.toString();
|
||||
|
||||
child.isActive = activeKey.indexOf(name) > -1;
|
||||
child.index = index;
|
||||
child.isActive = activeKey.indexOf(name) > -1;
|
||||
child.index = index;
|
||||
});
|
||||
});
|
||||
},
|
||||
getActiveKey () {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<Icon type="ios-arrow-forward" v-if="!hideArrow"></Icon>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<collapse-transition>
|
||||
<collapse-transition v-if="mounted">
|
||||
<div :class="contentClasses" v-show="isActive">
|
||||
<div :class="boxClasses"><slot name="content"></slot></div>
|
||||
</div>
|
||||
|
@ -31,7 +31,8 @@
|
|||
data () {
|
||||
return {
|
||||
index: 0, // use index for default when name is null
|
||||
isActive: false
|
||||
isActive: false,
|
||||
mounted: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -60,6 +61,9 @@
|
|||
isActive: this.isActive
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.mounted = true;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
:name="name"
|
||||
:value="currentValue"
|
||||
type="hidden">
|
||||
<i :class="arrowClasses"></i>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" :class="arrowClasses"></Icon>
|
||||
<div
|
||||
ref="input"
|
||||
:tabindex="disabled ? undefined : 0"
|
||||
|
@ -125,6 +125,7 @@ import Hue from './hue.vue';
|
|||
import Alpha from './alpha.vue';
|
||||
import iInput from '../input/input.vue';
|
||||
import iButton from '../button/button.vue';
|
||||
import Icon from '../icon/icon.vue';
|
||||
import Locale from '../../mixins/locale';
|
||||
import {oneOf} from '../../utils/assist';
|
||||
import Emitter from '../../mixins/emitter';
|
||||
|
@ -134,7 +135,7 @@ import {changeColor, toRGBAString} from './utils';
|
|||
export default {
|
||||
name: 'ColorPicker',
|
||||
|
||||
components: {Drop, RecommendColors, Saturation, Hue, Alpha, iInput, iButton},
|
||||
components: {Drop, RecommendColors, Saturation, Hue, Alpha, iInput, iButton, Icon},
|
||||
|
||||
directives: {clickOutside, TransferDom},
|
||||
|
||||
|
@ -260,8 +261,6 @@ export default {
|
|||
computed: {
|
||||
arrowClasses() {
|
||||
return [
|
||||
this.iconPrefixCls,
|
||||
`${this.iconPrefixCls}-ios-arrow-down`,
|
||||
`${this.inputPrefixCls}-icon`,
|
||||
`${this.inputPrefixCls}-icon-normal`,
|
||||
];
|
||||
|
@ -352,6 +351,41 @@ export default {
|
|||
[`${this.prefixCls}-confirm-color-editable`]: this.editable
|
||||
}
|
||||
];
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-down';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.colorPicker.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.colorPicker.arrow) {
|
||||
type = this.$IVIEW.colorPicker.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.colorPicker.customArrow) {
|
||||
type = this.$IVIEW.colorPicker.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.colorPicker.arrowSize) {
|
||||
size = this.$IVIEW.colorPicker.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -75,7 +75,10 @@
|
|||
|
||||
return this.calendar(tableYear, tableMonth, (cell) => {
|
||||
// normalize date offset from the dates provided by jsCalendar
|
||||
if (cell.date instanceof Date) cell.date.setTime(cell.date.getTime() + cell.date.getTimezoneOffset() * 60000);
|
||||
// Comment out this code to fix daylight saving time bug
|
||||
// https://www.cnblogs.com/hamsterPP/p/5415472.html
|
||||
if (cell.date instanceof Date) cell.date.setTime(cell.date.getTime() + cell.date.getTimezoneOffset() * 60000 + 480 * 60 * 1000);
|
||||
//if (cell.date instanceof Date) cell.date.setTime(clearHours(cell.date));
|
||||
|
||||
const time = cell.date && clearHours(cell.date);
|
||||
const dateIsInCurrentMonth = cell.date && tableMonth === cell.date.getMonth();
|
||||
|
|
|
@ -296,7 +296,18 @@
|
|||
},
|
||||
changePanelDate(panel, type, increment, updateOtherPanel = true){
|
||||
const current = new Date(this[`${panel}PanelDate`]);
|
||||
current[`set${type}`](current[`get${type}`]() + increment);
|
||||
|
||||
if (this.splitPanels) {
|
||||
// fix #6404
|
||||
current[`set${type}`](current[`get${type}`]() + increment);
|
||||
} else {
|
||||
if (panel === 'left') {
|
||||
current[`set${type}`](current[`get${type}`]() + increment);
|
||||
} else {
|
||||
current[`set${type}`](current[`get${type}`]() + increment);
|
||||
}
|
||||
}
|
||||
|
||||
this[`${panel}PanelDate`] = current;
|
||||
|
||||
if (!updateOtherPanel) return;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<div
|
||||
:class="wrapperClasses"
|
||||
v-click-outside:mousedown.capture="handleClose"
|
||||
v-click-outside:touchstart.capture="handleClose"
|
||||
v-click-outside.capture="handleClose"
|
||||
>
|
||||
<div ref="reference" :class="[prefixCls + '-rel']">
|
||||
|
@ -21,14 +22,13 @@
|
|||
@on-input-change="handleInputChange"
|
||||
@on-focus="handleFocus"
|
||||
@on-blur="handleBlur"
|
||||
@on-click="handleIconClick"
|
||||
@click.native="handleFocus"
|
||||
@keydown.native="handleKeydown"
|
||||
@mouseenter.native="handleInputMouseenter"
|
||||
@mouseleave.native="handleInputMouseleave"
|
||||
|
||||
:icon="iconType"
|
||||
></i-input>
|
||||
>
|
||||
<Icon @click="handleIconClick" :type="arrowType" :custom="customArrowType" :size="arrowSize" slot="suffix" />
|
||||
</i-input>
|
||||
</slot>
|
||||
</div>
|
||||
<transition name="transition-drop">
|
||||
|
@ -79,6 +79,7 @@
|
|||
|
||||
import iInput from '../../components/input/input.vue';
|
||||
import Drop from '../../components/select/dropdown.vue';
|
||||
import Icon from '../../components/icon/icon.vue';
|
||||
import {directive as clickOutside} from 'v-click-outside-x';
|
||||
import TransferDom from '../../directives/transfer-dom';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
@ -120,7 +121,7 @@
|
|||
|
||||
export default {
|
||||
mixins: [ Emitter ],
|
||||
components: { iInput, Drop },
|
||||
components: { iInput, Drop, Icon },
|
||||
directives: { clickOutside, TransferDom },
|
||||
props: {
|
||||
format: {
|
||||
|
@ -267,12 +268,6 @@
|
|||
opened () {
|
||||
return this.open === null ? this.visible : this.open;
|
||||
},
|
||||
iconType () {
|
||||
let icon = 'ios-calendar-outline';
|
||||
if (this.type === 'time' || this.type === 'timerange') icon = 'ios-time-outline';
|
||||
if (this.showClose) icon = 'ios-close-circle';
|
||||
return icon;
|
||||
},
|
||||
transition () {
|
||||
const bottomPlaced = this.placement.match(/^bottom/);
|
||||
return bottomPlaced ? 'slide-up' : 'slide-down';
|
||||
|
@ -282,6 +277,80 @@
|
|||
},
|
||||
isConfirm(){
|
||||
return this.confirm || this.type === 'datetime' || this.type === 'datetimerange' || this.multiple;
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.type === 'time' || this.type === 'timerange') {
|
||||
type = 'ios-time-outline';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.timePicker.customIcon) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.timePicker.icon) {
|
||||
type = this.$IVIEW.timePicker.icon;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type = 'ios-calendar-outline';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.datePicker.customIcon) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.datePicker.icon) {
|
||||
type = this.$IVIEW.datePicker.icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showClose) type = 'ios-close-circle';
|
||||
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (!this.showClose) {
|
||||
if (this.type === 'time' || this.type === 'timerange') {
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.timePicker.customIcon) {
|
||||
type = this.$IVIEW.timePicker.customIcon;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.datePicker.customIcon) {
|
||||
type = this.$IVIEW.datePicker.customIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (!this.showClose) {
|
||||
if (this.type === 'time' || this.type === 'timerange') {
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.timePicker.iconSize) {
|
||||
size = this.$IVIEW.timePicker.iconSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.datePicker.iconSize) {
|
||||
size = this.$IVIEW.datePicker.iconSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -313,6 +382,7 @@
|
|||
this.visible = false;
|
||||
e && e.preventDefault();
|
||||
e && e.stopPropagation();
|
||||
this.$emit('on-clickoutside', e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div v-transfer-dom :data-transfer="transfer">
|
||||
<transition name="fade">
|
||||
<div :class="maskClasses" :style="maskStyle" v-show="visible" v-if="mask" @click="handleMask"></div>
|
||||
<div :class="maskClasses" :style="maskStyle" v-if="mask && visible" @click="handleMask"></div>
|
||||
</transition>
|
||||
<div :class="wrapClasses" @click="handleWrapClick">
|
||||
<transition :name="'move-' + placement">
|
||||
<div :class="classes" :style="mainStyles" v-show="visible">
|
||||
<div :class="classes" :style="mainStyles" v-if="visible">
|
||||
<div :class="contentClasses" ref="content">
|
||||
<a class="ivu-drawer-close" v-if="closable" @click="close">
|
||||
<slot name="close">
|
||||
|
@ -303,6 +303,9 @@
|
|||
if (this.$slots.header === undefined) {
|
||||
this.showHead = !!val;
|
||||
}
|
||||
},
|
||||
width (val) {
|
||||
this.dragWidth = val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,14 +37,10 @@
|
|||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.disabled) return;
|
||||
const $parent = findComponentUpward(this, 'Dropdown');
|
||||
const hasChildren = this.$parent && this.$parent.$options.name === 'Dropdown';
|
||||
|
||||
if (this.disabled) {
|
||||
this.$nextTick(() => {
|
||||
$parent.currentVisible = true;
|
||||
});
|
||||
} else if (hasChildren) {
|
||||
if (hasChildren) {
|
||||
this.$parent.$emit('on-haschild-click');
|
||||
} else {
|
||||
if ($parent && $parent.$options.name === 'Dropdown') {
|
||||
|
|
|
@ -57,6 +57,10 @@
|
|||
transferClassName: {
|
||||
type: String
|
||||
},
|
||||
stopPropagation: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
transition () {
|
||||
|
@ -164,6 +168,7 @@
|
|||
},
|
||||
mounted () {
|
||||
this.$on('on-click', (key) => {
|
||||
if (this.stopPropagation) return;
|
||||
const $parent = this.hasParent();
|
||||
if ($parent) $parent.$emit('on-click', key);
|
||||
});
|
||||
|
|
|
@ -178,33 +178,36 @@
|
|||
return rules.filter(rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1);
|
||||
},
|
||||
validate(trigger, callback = function () {}) {
|
||||
let rules = this.getFilteredRule(trigger);
|
||||
if (!rules || rules.length === 0) {
|
||||
if (!this.required) {
|
||||
callback();
|
||||
return true;
|
||||
}else {
|
||||
rules = [{required: true}];
|
||||
this.$nextTick(() => {
|
||||
let rules = this.getFilteredRule(trigger);
|
||||
if (!rules || rules.length === 0) {
|
||||
if (!this.required) {
|
||||
this.validateState = '';
|
||||
callback();
|
||||
return true;
|
||||
}else {
|
||||
rules = [{required: true}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.validateState = 'validating';
|
||||
this.validateState = 'validating';
|
||||
|
||||
let descriptor = {};
|
||||
descriptor[this.prop] = rules;
|
||||
let descriptor = {};
|
||||
descriptor[this.prop] = rules;
|
||||
|
||||
const validator = new AsyncValidator(descriptor);
|
||||
let model = {};
|
||||
const validator = new AsyncValidator(descriptor);
|
||||
let model = {};
|
||||
|
||||
model[this.prop] = this.fieldValue;
|
||||
model[this.prop] = this.fieldValue;
|
||||
|
||||
validator.validate(model, { firstFields: true }, errors => {
|
||||
this.validateState = !errors ? 'success' : 'error';
|
||||
this.validateMessage = errors ? errors[0].message : '';
|
||||
validator.validate(model, { firstFields: true }, errors => {
|
||||
this.validateState = !errors ? 'success' : 'error';
|
||||
this.validateMessage = errors ? errors[0].message : '';
|
||||
|
||||
callback(this.validateMessage);
|
||||
callback(this.validateMessage);
|
||||
});
|
||||
this.validateDisabled = false;
|
||||
});
|
||||
this.validateDisabled = false;
|
||||
},
|
||||
resetField () {
|
||||
this.validateState = '';
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
@blur="blur"
|
||||
@keydown.stop="keyDown"
|
||||
@input="change"
|
||||
ref="precisionCursor"
|
||||
@mouseup="preventDefault"
|
||||
@change="change"
|
||||
:readonly="readonly || !editable"
|
||||
|
@ -224,7 +225,6 @@
|
|||
if (this.disabled || this.readonly) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetVal = Number(e.target.value);
|
||||
let val = Number(this.currentValue);
|
||||
const step = Number(this.step);
|
||||
|
@ -261,7 +261,8 @@
|
|||
if (val && !isNaN(this.precision)) val = Number(Number(val).toFixed(this.precision));
|
||||
|
||||
const {min, max} = this;
|
||||
if (val!==null) {
|
||||
// #6245
|
||||
if ( val!==null && !this.activeChange ) {
|
||||
if (val > max) {
|
||||
val = max;
|
||||
} else if (val < min) {
|
||||
|
@ -297,6 +298,7 @@
|
|||
}
|
||||
},
|
||||
change (event) {
|
||||
if (event.type == 'change' && this.activeChange) return;
|
||||
|
||||
if (event.type == 'input' && !this.activeChange) return;
|
||||
let val = event.target.value.trim();
|
||||
|
@ -309,15 +311,24 @@
|
|||
this.setValue(null);
|
||||
return;
|
||||
}
|
||||
if (event.type == 'input' && val.match(/^\-?\.?$|\.$/)) return; // prevent fire early if decimal. If no more input the change event will fire later
|
||||
if (event.type == 'input' && val.match(/^\-?\.?$|\.$/g)) return; // prevent fire early if decimal. If no more input the change event will fire later
|
||||
|
||||
//#fixed when setting the precision val, input point cannot show problem
|
||||
const precision = this.precision;
|
||||
let cacheVal = this.currentValue;
|
||||
if( precision ){
|
||||
const valMatchPointArr = (val+'').match(/\./g);
|
||||
if( valMatchPointArr && valMatchPointArr.length >= 2 ){
|
||||
cacheVal = this.currentValue + '.';
|
||||
}
|
||||
}
|
||||
|
||||
val = Number(val);
|
||||
|
||||
if (!isNaN(val)) {
|
||||
if (!isNaN(val) ) {
|
||||
this.currentValue = val;
|
||||
this.setValue(val);
|
||||
} else {
|
||||
event.target.value = this.currentValue;
|
||||
event.target.value = cacheVal;
|
||||
}
|
||||
},
|
||||
changeVal (val) {
|
||||
|
@ -342,6 +353,14 @@
|
|||
},
|
||||
currentValue (val) {
|
||||
this.changeVal(val);
|
||||
//optimization - Solve the problem of cursor positioning inaccuracy
|
||||
this.$nextTick(()=>{
|
||||
if( this.precision ){
|
||||
const currentValueLength = ( this.currentValue || 0 ).toString().length;
|
||||
const precisionCursor = this.$refs.precisionCursor;
|
||||
precisionCursor.selectionStart = precisionCursor.selectionEnd = currentValueLength;
|
||||
}
|
||||
});
|
||||
},
|
||||
min () {
|
||||
this.changeVal(this.currentValue);
|
||||
|
|
|
@ -2,39 +2,41 @@
|
|||
<div :class="wrapClasses">
|
||||
<template v-if="type !== 'textarea'">
|
||||
<div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady"><slot name="prepend"></slot></div>
|
||||
<i class="ivu-icon" :class="['ivu-icon-ios-close-circle', prefixCls + '-icon', prefixCls + '-icon-clear' , prefixCls + '-icon-normal']" v-if="clearable && currentValue && !disabled" @click="handleClear"></i>
|
||||
<i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon', prefixCls + '-icon-normal']" v-else-if="icon" @click="handleIconClick"></i>
|
||||
<i class="ivu-icon ivu-icon-ios-search" :class="[prefixCls + '-icon', prefixCls + '-icon-normal', prefixCls + '-search-icon']" v-else-if="search && enterButton === false" @click="handleSearch"></i>
|
||||
<span class="ivu-input-suffix" v-else-if="showSuffix"><slot name="suffix"><i class="ivu-icon" :class="['ivu-icon-' + suffix]" v-if="suffix"></i></slot></span>
|
||||
<transition name="fade">
|
||||
<i class="ivu-icon ivu-icon-ios-loading ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i>
|
||||
</transition>
|
||||
<input
|
||||
:id="elementId"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
ref="input"
|
||||
:type="type"
|
||||
:class="inputClasses"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
:value="currentValue"
|
||||
:number="number"
|
||||
:autofocus="autofocus"
|
||||
@keyup.enter="handleEnter"
|
||||
@keyup="handleKeyup"
|
||||
@keypress="handleKeypress"
|
||||
@keydown="handleKeydown"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@compositionstart="handleComposition"
|
||||
@compositionupdate="handleComposition"
|
||||
@compositionend="handleComposition"
|
||||
@input="handleInput"
|
||||
@change="handleChange">
|
||||
<div :class="[prefixCls + '-inner-container']">
|
||||
<i class="ivu-icon" :class="['ivu-icon-ios-close-circle', prefixCls + '-icon', prefixCls + '-icon-clear' , prefixCls + '-icon-normal']" v-if="clearable && currentValue && !disabled" @click="handleClear"></i>
|
||||
<i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon', prefixCls + '-icon-normal']" v-else-if="icon" @click="handleIconClick"></i>
|
||||
<i class="ivu-icon ivu-icon-ios-search" :class="[prefixCls + '-icon', prefixCls + '-icon-normal', prefixCls + '-search-icon']" v-else-if="search && enterButton === false" @click="handleSearch"></i>
|
||||
<span class="ivu-input-suffix" v-else-if="showSuffix"><slot name="suffix"><i class="ivu-icon" :class="['ivu-icon-' + suffix]" v-if="suffix"></i></slot></span>
|
||||
<transition name="fade">
|
||||
<i class="ivu-icon ivu-icon-ios-loading ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i>
|
||||
</transition>
|
||||
<input
|
||||
:id="elementId"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
ref="input"
|
||||
:type="type"
|
||||
:class="inputClasses"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
:value="currentValue"
|
||||
:number="number"
|
||||
:autofocus="autofocus"
|
||||
@keyup.enter="handleEnter"
|
||||
@keyup="handleKeyup"
|
||||
@keypress="handleKeypress"
|
||||
@keydown="handleKeydown"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@compositionstart="handleComposition"
|
||||
@compositionupdate="handleComposition"
|
||||
@compositionend="handleComposition"
|
||||
@input="handleInput"
|
||||
@change="handleChange">
|
||||
</div>
|
||||
<div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady"><slot name="append"></slot></div>
|
||||
<div :class="[prefixCls + '-group-append', prefixCls + '-search']" v-else-if="search && enterButton" @click="handleSearch">
|
||||
<i class="ivu-icon ivu-icon-ios-search" v-if="enterButton === true"></i>
|
||||
|
@ -141,9 +143,7 @@
|
|||
default: false
|
||||
},
|
||||
autocomplete: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['on', 'off']);
|
||||
},
|
||||
type: String,
|
||||
default: 'off'
|
||||
},
|
||||
clearable: {
|
||||
|
@ -312,6 +312,7 @@
|
|||
this.$emit('input', '');
|
||||
this.setCurrentValue('');
|
||||
this.$emit('on-change', e);
|
||||
this.$emit('on-clear');
|
||||
},
|
||||
handleSearch () {
|
||||
if (this.disabled) return false;
|
||||
|
|
8
src/components/list/index.js
Normal file
8
src/components/list/index.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import List from './list.vue';
|
||||
import ListItem from './list-item.vue';
|
||||
import ListItemMeta from './list-item-meta.vue';
|
||||
|
||||
List.Item = ListItem;
|
||||
List.Item.Meta = ListItemMeta;
|
||||
|
||||
export default List;
|
35
src/components/list/list-item-meta.vue
Normal file
35
src/components/list/list-item-meta.vue
Normal file
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<div class="ivu-list-item-meta">
|
||||
<div class="ivu-list-item-meta-avatar" v-if="avatar || $slots.avatar">
|
||||
<slot name="avatar">
|
||||
<Avatar :src="avatar" />
|
||||
</slot>
|
||||
</div>
|
||||
<div class="ivu-list-item-meta-content">
|
||||
<div v-if="title || $slots.title" class="ivu-list-item-meta-title"><slot name="title">{{ title }}</slot></div>
|
||||
<div v-if="description || $slots.description" class="ivu-list-item-meta-description"><slot name="description">{{ description }}</slot></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Avatar from '../../components/avatar/avatar.vue';
|
||||
|
||||
export default {
|
||||
name: 'ListItemMeta',
|
||||
components: { Avatar },
|
||||
props: {
|
||||
avatar: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
63
src/components/list/list-item.vue
Normal file
63
src/components/list/list-item.vue
Normal file
|
@ -0,0 +1,63 @@
|
|||
<template>
|
||||
<li class="ivu-list-item" :class="classes">
|
||||
<template v-if="itemLayout === 'vertical' && $slots.extra">
|
||||
<div class="ivu-list-item-main">
|
||||
<slot></slot>
|
||||
<ul class="ivu-list-item-action" v-if="$slots.action">
|
||||
<slot name="action"></slot>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ivu-list-item-extra">
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<slot></slot>
|
||||
<ul class="ivu-list-item-action" v-if="$slots.action">
|
||||
<slot name="action"></slot>
|
||||
</ul>
|
||||
<div class="ivu-list-item-extra">
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
</template>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'ListItem',
|
||||
inject: ['ListInstance'],
|
||||
props: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
itemLayout () {
|
||||
return this.ListInstance.itemLayout;
|
||||
},
|
||||
isItemContainsTextNode () {
|
||||
let result;
|
||||
this.$slots.default.forEach(item => {
|
||||
if (typeof item === 'string') {
|
||||
result = true;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
isFlexMode () {
|
||||
const extra = this.$slots.extra;
|
||||
|
||||
if (this.itemLayout === 'vertical') {
|
||||
return !!extra;
|
||||
}
|
||||
|
||||
return !this.isItemContainsTextNode;
|
||||
},
|
||||
classes () {
|
||||
return [
|
||||
{
|
||||
'ivu-list-item-no-flex': !this.isFlexMode
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
84
src/components/list/list.vue
Normal file
84
src/components/list/list.vue
Normal file
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div class="ivu-list-header" v-if="header || $slots.header"><slot name="header">{{ header }}</slot></div>
|
||||
<div class="ivu-list-container">
|
||||
<ul class="ivu-list-items"><slot></slot></ul>
|
||||
</div>
|
||||
<Spin v-if="loading" fix size="large"><slot name="spin"></slot></Spin>
|
||||
<div class="ivu-list-footer" v-if="footer || $slots.footer"><slot name="footer">{{ footer }}</slot></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-list';
|
||||
|
||||
export default {
|
||||
name: 'List',
|
||||
provide () {
|
||||
return {
|
||||
ListInstance: this
|
||||
};
|
||||
},
|
||||
props: {
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
itemLayout: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['horizontal', 'vertical']);
|
||||
},
|
||||
default: 'horizontal'
|
||||
},
|
||||
// 或 slot
|
||||
header: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 或 slot
|
||||
footer: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 含 slot: spin
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large', 'default']);
|
||||
},
|
||||
default () {
|
||||
return !this.$IVIEW || this.$IVIEW.size === '' ? 'default' : this.$IVIEW.size;
|
||||
}
|
||||
},
|
||||
split: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-${this.size}`,
|
||||
`${prefixCls}-${this.itemLayout}`,
|
||||
{
|
||||
[`${prefixCls}-bordered`]: this.border,
|
||||
[`${prefixCls}-split`]: this.split
|
||||
}
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -2,6 +2,7 @@ import LoadingBar from './loading-bar';
|
|||
|
||||
let loadingBarInstance;
|
||||
let color = 'primary';
|
||||
let duration = 800;
|
||||
let failedColor = 'error';
|
||||
let height = 2;
|
||||
let timer;
|
||||
|
@ -32,7 +33,7 @@ function hide() {
|
|||
percent: 0
|
||||
});
|
||||
}, 200);
|
||||
}, 800);
|
||||
}, duration);
|
||||
}
|
||||
|
||||
function clearTimer() {
|
||||
|
@ -96,6 +97,9 @@ export default {
|
|||
if (options.color) {
|
||||
color = options.color;
|
||||
}
|
||||
if (options.duration) {
|
||||
duration = options.duration;
|
||||
}
|
||||
if (options.failedColor) {
|
||||
failedColor = options.failedColor;
|
||||
}
|
||||
|
|
|
@ -133,9 +133,9 @@
|
|||
}
|
||||
},
|
||||
mounted () {
|
||||
this.updateActiveName();
|
||||
this.openedNames = [...this.openNames];
|
||||
this.updateOpened();
|
||||
this.$nextTick(() => this.updateActiveName());
|
||||
this.$on('on-menu-item-select', (name) => {
|
||||
this.currentActiveName = name;
|
||||
this.$emit('on-select', name);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<li :class="classes" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave">
|
||||
<div :class="[prefixCls + '-submenu-title']" ref="reference" @click.stop="handleClick" :style="titleStyle">
|
||||
<slot name="title"></slot>
|
||||
<Icon type="ios-arrow-down" :class="[prefixCls + '-submenu-title-icon']"></Icon>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" :class="[prefixCls + '-submenu-title-icon']" />
|
||||
</div>
|
||||
<collapse-transition v-if="mode === 'vertical'">
|
||||
<ul :class="[prefixCls]" v-show="opened"><slot></slot></ul>
|
||||
|
@ -75,6 +75,41 @@
|
|||
return this.hasParentSubmenu && this.mode !== 'horizontal' ? {
|
||||
paddingLeft: 43 + (this.parentSubmenuNum - 1) * 24 + 'px'
|
||||
} : {};
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-down';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.menu.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.menu.arrow) {
|
||||
type = this.$IVIEW.menu.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.menu.customArrow) {
|
||||
type = this.$IVIEW.menu.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.menu.arrowSize) {
|
||||
size = this.$IVIEW.menu.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -24,7 +24,8 @@ Modal.newInstance = properties => {
|
|||
buttonLoading: false,
|
||||
scrollable: false,
|
||||
closable: false,
|
||||
autoClose: true
|
||||
autoClose: true,
|
||||
closing: false // 关闭有动画,期间使用此属性避免重复点击
|
||||
}),
|
||||
render (h) {
|
||||
let footerVNodes = [];
|
||||
|
@ -160,12 +161,14 @@ Modal.newInstance = properties => {
|
|||
},
|
||||
methods: {
|
||||
cancel () {
|
||||
if (this.closing) return;
|
||||
this.$children[0].visible = false;
|
||||
this.buttonLoading = false;
|
||||
this.onCancel();
|
||||
this.remove();
|
||||
},
|
||||
ok () {
|
||||
if (this.closing) return;
|
||||
if (this.loading) {
|
||||
this.buttonLoading = true;
|
||||
} else {
|
||||
|
@ -178,13 +181,17 @@ Modal.newInstance = properties => {
|
|||
this.onOk();
|
||||
},
|
||||
remove () {
|
||||
this.closing = true;
|
||||
setTimeout(() => {
|
||||
this.closing = false;
|
||||
this.destroy();
|
||||
}, 300);
|
||||
},
|
||||
destroy () {
|
||||
this.$destroy();
|
||||
document.body.removeChild(this.$el);
|
||||
if( this.$el ){
|
||||
document.body.removeChild(this.$el);
|
||||
}
|
||||
this.onRemove();
|
||||
},
|
||||
onOk () {},
|
||||
|
@ -279,4 +286,4 @@ Modal.newInstance = properties => {
|
|||
};
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
export default Modal;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</transition>
|
||||
<div :class="wrapClasses" :style="wrapStyles" @click="handleWrapClick">
|
||||
<transition :name="transitionNames[0]" @after-leave="animationFinish">
|
||||
<div :class="classes" :style="mainStyles" v-show="visible">
|
||||
<div :class="classes" :style="mainStyles" v-show="visible" @mousedown="handleMousedown">
|
||||
<div :class="contentClasses" ref="content" :style="contentStyles" @click="handleClickModal">
|
||||
<a :class="[prefixCls + '-close']" v-if="closable" @click="close">
|
||||
<slot name="close">
|
||||
|
@ -60,7 +60,9 @@
|
|||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default () {
|
||||
return !this.$IVIEW || this.$IVIEW.modal.maskClosable === '' ? true : this.$IVIEW.modal.maskClosable;
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
|
@ -80,7 +82,10 @@
|
|||
default: false
|
||||
},
|
||||
styles: {
|
||||
type: Object
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
|
@ -142,6 +147,7 @@
|
|||
dragging: false
|
||||
},
|
||||
modalIndex: this.handleGetModalIndex(), // for Esc close the top modal
|
||||
isMouseTriggerIn: false, // #5800
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -203,8 +209,10 @@
|
|||
let style = {};
|
||||
|
||||
if (this.draggable) {
|
||||
if (this.dragData.x !== null) style.left = `${this.dragData.x}px`;
|
||||
if (this.dragData.y !== null) style.top = `${this.dragData.y}px`;
|
||||
let customTop = this.styles.top ? parseFloat(this.styles.top) : 0;
|
||||
let customLeft = this.styles.left ? parseFloat(this.styles.left) : 0;
|
||||
if (this.dragData.x !== null) style.left = `${this.dragData.x - customLeft}px`;
|
||||
if (this.dragData.y !== null) style.top = `${this.dragData.y - customTop}px`;
|
||||
const width = parseInt(this.width);
|
||||
const styleWidth = {
|
||||
width: width <= 100 ? `${width}%` : `${width}px`
|
||||
|
@ -245,10 +253,17 @@
|
|||
}
|
||||
},
|
||||
handleWrapClick (event) {
|
||||
if (this.isMouseTriggerIn) {
|
||||
this.isMouseTriggerIn = false;
|
||||
return;
|
||||
}
|
||||
// use indexOf,do not use === ,because ivu-modal-wrap can have other custom className
|
||||
const className = event.target.getAttribute('class');
|
||||
if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.handleMask();
|
||||
},
|
||||
handleMousedown () {
|
||||
this.isMouseTriggerIn = true;
|
||||
},
|
||||
cancel () {
|
||||
this.close();
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<li
|
||||
:title="t('i.page.prev')"
|
||||
:class="prevClasses"
|
||||
@click="prev">
|
||||
@click.stop="prev">
|
||||
<a><i class="ivu-icon ivu-icon-ios-arrow-back"></i></a>
|
||||
</li>
|
||||
<div :class="simplePagerClasses" :title="currentPage + '/' + allPages">
|
||||
|
@ -21,7 +21,7 @@
|
|||
<li
|
||||
:title="t('i.page.next')"
|
||||
:class="nextClasses"
|
||||
@click="next">
|
||||
@click.stop="next">
|
||||
<a><i class="ivu-icon ivu-icon-ios-arrow-forward"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -32,24 +32,24 @@
|
|||
<li
|
||||
:title="t('i.page.prev')"
|
||||
:class="prevClasses"
|
||||
@click="prev">
|
||||
@click.stop="prev">
|
||||
<a><template v-if="prevText !== ''">{{ prevText }}</template><i v-else class="ivu-icon ivu-icon-ios-arrow-back"></i></a>
|
||||
</li>
|
||||
<li title="1" :class="firstPageClasses" @click="changePage(1)"><a>1</a></li>
|
||||
<li :title="t('i.page.prev5')" v-if="currentPage > 5" :class="[prefixCls + '-item-jump-prev']" @click="fastPrev"><a><i class="ivu-icon ivu-icon-ios-arrow-back"></i></a></li>
|
||||
<li :title="currentPage - 3" v-if="currentPage === 5" :class="[prefixCls + '-item']" @click="changePage(currentPage - 3)"><a>{{ currentPage - 3 }}</a></li>
|
||||
<li :title="currentPage - 2" v-if="currentPage - 2 > 1" :class="[prefixCls + '-item']" @click="changePage(currentPage - 2)"><a>{{ currentPage - 2 }}</a></li>
|
||||
<li :title="currentPage - 1" v-if="currentPage - 1 > 1" :class="[prefixCls + '-item']" @click="changePage(currentPage - 1)"><a>{{ currentPage - 1 }}</a></li>
|
||||
<li title="1" :class="firstPageClasses" @click.stop="changePage(1)"><a>1</a></li>
|
||||
<li :title="t('i.page.prev5')" v-if="currentPage > 5" :class="[prefixCls + '-item-jump-prev']" @click.stop="fastPrev"><a><i class="ivu-icon ivu-icon-ios-arrow-back"></i></a></li>
|
||||
<li :title="currentPage - 3" v-if="currentPage === 5" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage - 3)"><a>{{ currentPage - 3 }}</a></li>
|
||||
<li :title="currentPage - 2" v-if="currentPage - 2 > 1" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage - 2)"><a>{{ currentPage - 2 }}</a></li>
|
||||
<li :title="currentPage - 1" v-if="currentPage - 1 > 1" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage - 1)"><a>{{ currentPage - 1 }}</a></li>
|
||||
<li :title="currentPage" v-if="currentPage != 1 && currentPage != allPages" :class="[prefixCls + '-item',prefixCls + '-item-active']"><a>{{ currentPage }}</a></li>
|
||||
<li :title="currentPage + 1" v-if="currentPage + 1 < allPages" :class="[prefixCls + '-item']" @click="changePage(currentPage + 1)"><a>{{ currentPage + 1 }}</a></li>
|
||||
<li :title="currentPage + 2" v-if="currentPage + 2 < allPages" :class="[prefixCls + '-item']" @click="changePage(currentPage + 2)"><a>{{ currentPage + 2 }}</a></li>
|
||||
<li :title="currentPage + 3" v-if="allPages - currentPage === 4" :class="[prefixCls + '-item']" @click="changePage(currentPage + 3)"><a>{{ currentPage + 3 }}</a></li>
|
||||
<li :title="t('i.page.next5')" v-if="allPages - currentPage >= 5" :class="[prefixCls + '-item-jump-next']" @click="fastNext"><a><i class="ivu-icon ivu-icon-ios-arrow-forward"></i></a></li>
|
||||
<li :title="allPages" v-if="allPages > 1" :class="lastPageClasses" @click="changePage(allPages)"><a>{{ allPages }}</a></li>
|
||||
<li :title="currentPage + 1" v-if="currentPage + 1 < allPages" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage + 1)"><a>{{ currentPage + 1 }}</a></li>
|
||||
<li :title="currentPage + 2" v-if="currentPage + 2 < allPages" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage + 2)"><a>{{ currentPage + 2 }}</a></li>
|
||||
<li :title="currentPage + 3" v-if="allPages - currentPage === 4" :class="[prefixCls + '-item']" @click.stop="changePage(currentPage + 3)"><a>{{ currentPage + 3 }}</a></li>
|
||||
<li :title="t('i.page.next5')" v-if="allPages - currentPage >= 5" :class="[prefixCls + '-item-jump-next']" @click.stop="fastNext"><a><i class="ivu-icon ivu-icon-ios-arrow-forward"></i></a></li>
|
||||
<li :title="allPages" v-if="allPages > 1" :class="lastPageClasses" @click.stop="changePage(allPages)"><a>{{ allPages }}</a></li>
|
||||
<li
|
||||
:title="t('i.page.next')"
|
||||
:class="nextClasses"
|
||||
@click="next">
|
||||
@click.stop="next">
|
||||
<a><template v-if="nextText !== ''">{{ nextText }}</template><i v-else class="ivu-icon ivu-icon-ios-arrow-forward"></i></a>
|
||||
</li>
|
||||
<Options
|
||||
|
|
|
@ -117,6 +117,11 @@
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 3.4.0
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -186,6 +191,8 @@
|
|||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (this.confirm) {
|
||||
this.visible = !this.visible;
|
||||
return true;
|
||||
|
@ -215,6 +222,8 @@
|
|||
}
|
||||
},
|
||||
handleFocus (fromInput = true) {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (this.trigger !== 'focus' || this.confirm || (this.isInput && !fromInput)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -227,6 +236,8 @@
|
|||
this.visible = false;
|
||||
},
|
||||
handleMouseenter () {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (this.trigger !== 'hover' || this.confirm) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div :class="wrapClasses">
|
||||
<div :class="outerClasses">
|
||||
<div :class="innerClasses">
|
||||
<div :class="bgClasses" :style="bgStyle"></div><div :class="successBgClasses" :style="successBgStyle"></div>
|
||||
<div :class="bgClasses" :style="bgStyle"><div class="ivu-progress-inner-text" v-if="textInside">{{ percent }}%</div></div><div :class="successBgClasses" :style="successBgStyle"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="!hideInfo" :class="textClasses">
|
||||
<span v-if="!hideInfo && !textInside" :class="textClasses">
|
||||
<slot>
|
||||
<span v-if="isStatus" :class="textInnerClasses">
|
||||
<Icon :type="statusIcon"></Icon>
|
||||
|
@ -54,7 +54,11 @@
|
|||
default: false
|
||||
},
|
||||
strokeColor: {
|
||||
type: String
|
||||
type: [String, Array]
|
||||
},
|
||||
textInside: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -89,7 +93,11 @@
|
|||
};
|
||||
|
||||
if (this.strokeColor) {
|
||||
style['background-color'] = this.strokeColor;
|
||||
if (typeof this.strokeColor === 'string') {
|
||||
style['background-color'] = this.strokeColor;
|
||||
} else {
|
||||
style['background-image'] = `linear-gradient(to right, ${this.strokeColor[0]} 0%, ${this.strokeColor[1]} 100%)`;
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
|
@ -108,7 +116,7 @@
|
|||
`${prefixCls}`,
|
||||
`${prefixCls}-${this.currentStatus}`,
|
||||
{
|
||||
[`${prefixCls}-show-info`]: !this.hideInfo,
|
||||
[`${prefixCls}-show-info`]: !this.hideInfo && !this.textInside,
|
||||
[`${prefixCls}-vertical`]: this.vertical
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
<template>
|
||||
<div @click="onHeaderClick">
|
||||
<div class="ivu-tag ivu-tag-checked" v-for="item in selectedMultiple">
|
||||
<div @click="onHeaderClick" :class="headCls">
|
||||
<span :class="[prefixCls + '-prefix']" v-if="$slots.prefix || prefix">
|
||||
<slot name="prefix">
|
||||
<Icon :type="prefix" v-if="prefix" />
|
||||
</slot>
|
||||
</span>
|
||||
<div
|
||||
class="ivu-tag ivu-tag-checked"
|
||||
v-for="(item, index) in selectedMultiple"
|
||||
v-if="maxTagCount === undefined || index < maxTagCount">
|
||||
<span class="ivu-tag-text">{{ item.label }}</span>
|
||||
<Icon type="ios-close" @click.native.stop="removeTag(item)"></Icon>
|
||||
</div><div class="ivu-tag ivu-tag-checked" v-if="maxTagCount !== undefined && selectedMultiple.length > maxTagCount">
|
||||
<span class="ivu-tag-text ivu-select-max-tag">
|
||||
<template v-if="maxTagPlaceholder">{{ maxTagPlaceholder(selectedMultiple.length - maxTagCount) }}</template>
|
||||
<template v-else>+ {{ selectedMultiple.length - maxTagCount }}...</template>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
:class="singleDisplayClasses"
|
||||
|
@ -26,7 +39,7 @@
|
|||
|
||||
ref="input">
|
||||
<Icon type="ios-close-circle" :class="[prefixCls + '-arrow']" v-if="resetSelect" @click.native.stop="onClear"></Icon>
|
||||
<Icon type="ios-arrow-down" :class="[prefixCls + '-arrow']" v-if="!resetSelect && !remote && !disabled"></Icon>
|
||||
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" :class="[prefixCls + '-arrow']" v-if="!resetSelect && !remote"></Icon>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -77,6 +90,17 @@
|
|||
queryProp: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
prefix: {
|
||||
type: String
|
||||
},
|
||||
// 3.4.0
|
||||
maxTagCount: {
|
||||
type: Number
|
||||
},
|
||||
// 3.4.0
|
||||
maxTagPlaceholder: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -92,6 +116,7 @@
|
|||
singleDisplayClasses(){
|
||||
const {filterable, multiple, showPlaceholder} = this;
|
||||
return [{
|
||||
[prefixCls + '-head-with-prefix']: this.$slots.prefix || this.prefix,
|
||||
[prefixCls + '-placeholder']: showPlaceholder && !filterable,
|
||||
[prefixCls + '-selected-value']: !showPlaceholder && !multiple && !filterable,
|
||||
}];
|
||||
|
@ -143,6 +168,47 @@
|
|||
},
|
||||
selectedMultiple(){
|
||||
return this.multiple ? this.values : [];
|
||||
},
|
||||
// 使用 prefix 时,在 filterable
|
||||
headCls () {
|
||||
return {
|
||||
[`${prefixCls}-head-flex`]: this.filterable && (this.$slots.prefix || this.prefix)
|
||||
};
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-down';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.select.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.select.arrow) {
|
||||
type = this.$IVIEW.select.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.select.customArrow) {
|
||||
type = this.$IVIEW.select.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.select.arrowSize) {
|
||||
size = this.$IVIEW.select.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -161,8 +227,9 @@
|
|||
this.inputLength = this.$refs.input.value.length * 12 + 20;
|
||||
this.$emit('on-keydown');
|
||||
},
|
||||
handleInputDelete () {
|
||||
if (this.multiple && this.selectedMultiple.length && this.query === '') {
|
||||
handleInputDelete (e) {
|
||||
const targetValue = e.target.value;
|
||||
if (this.multiple && this.selectedMultiple.length && this.query === '' && targetValue === '' ) {
|
||||
this.removeTag(this.selectedMultiple[this.selectedMultiple.length - 1]);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
:class="classes"
|
||||
v-click-outside.capture="onClickOutside"
|
||||
v-click-outside:mousedown.capture="onClickOutside"
|
||||
v-click-outside:touchstart.capture="onClickOutside"
|
||||
>
|
||||
<div
|
||||
ref="reference"
|
||||
|
@ -33,18 +34,23 @@
|
|||
:multiple="multiple"
|
||||
:values="values"
|
||||
:clearable="canBeCleared"
|
||||
:prefix="prefix"
|
||||
:disabled="disabled"
|
||||
:remote="remote"
|
||||
:input-element-id="elementId"
|
||||
:initial-label="initialLabel"
|
||||
:placeholder="placeholder"
|
||||
:query-prop="query"
|
||||
:max-tag-count="maxTagCount"
|
||||
:max-tag-placeholder="maxTagPlaceholder"
|
||||
|
||||
@on-query-change="onQueryChange"
|
||||
@on-input-focus="isFocused = true"
|
||||
@on-input-blur="isFocused = false"
|
||||
@on-clear="clearSingleSelect"
|
||||
/>
|
||||
>
|
||||
<slot name="prefix" slot="prefix"></slot>
|
||||
</select-head>
|
||||
</slot>
|
||||
</div>
|
||||
<transition name="transition-drop">
|
||||
|
@ -57,7 +63,9 @@
|
|||
:transfer="transfer"
|
||||
v-transfer-dom
|
||||
>
|
||||
<ul v-show="showNotFoundLabel" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
|
||||
<ul v-show="showNotFoundLabel && !$slots.empty" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
|
||||
<!--feature #5327-->
|
||||
<ul v-if="showNotFoundLabel && $slots.empty" :class="[prefixCls + '-not-found']" @mousedown.prevent><li><slot name="empty"></slot></li></ul>
|
||||
<ul :class="prefixCls + '-dropdown-list'">
|
||||
<functional-options
|
||||
v-if="(!remote) || (remote && !loading)"
|
||||
|
@ -235,12 +243,24 @@
|
|||
transferClassName: {
|
||||
type: String
|
||||
},
|
||||
// 3.4.0
|
||||
prefix: {
|
||||
type: String
|
||||
},
|
||||
// 3.4.0
|
||||
maxTagCount: {
|
||||
type: Number
|
||||
},
|
||||
// 3.4.0
|
||||
maxTagPlaceholder: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.$on('on-select-selected', this.onOptionClick);
|
||||
|
||||
// set the initial values if there are any
|
||||
if (!this.remote && this.selectOptions.length > 0){
|
||||
if ( this.selectOptions.length > 0){
|
||||
this.values = this.getInitialValue().map(value => {
|
||||
if (typeof value !== 'number' && !value) return null;
|
||||
return this.getOptionData(value);
|
||||
|
@ -268,6 +288,8 @@
|
|||
hasExpectedValue: false,
|
||||
preventRemoteCall: false,
|
||||
filterQueryChange: false, // #4273
|
||||
// #6349
|
||||
hideMenuTimer: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -392,9 +414,8 @@
|
|||
const optionPassesFilter = this.filterable ? this.validateOption(cOptions) : option;
|
||||
if (!optionPassesFilter) continue;
|
||||
}
|
||||
|
||||
optionCounter = optionCounter + 1;
|
||||
selectOptions.push(this.processOption(option, selectedValues, optionCounter === currentIndex));
|
||||
selectOptions.push(this.processOption(option, selectedValues, currentIndex === optionCounter));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,12 +440,14 @@
|
|||
if (query === null) {
|
||||
this.onQueryChange('');
|
||||
this.values = [];
|
||||
// #5620,修复清空搜索关键词后,重新搜索相同的关键词没有触发远程搜索
|
||||
this.lastRemoteQuery = '';
|
||||
}
|
||||
},
|
||||
clearSingleSelect(){ // PUBLIC API
|
||||
this.$emit('on-clear');
|
||||
this.hideMenu();
|
||||
if (this.clearable) this.reset();
|
||||
this.$emit('on-clear'); // #6331
|
||||
},
|
||||
getOptionData(value){
|
||||
const option = this.flatOptions.find(({componentOptions}) => componentOptions.propsData.value === value);
|
||||
|
@ -452,7 +475,6 @@
|
|||
const optionValue = option.componentOptions.propsData.value;
|
||||
const disabled = option.componentOptions.propsData.disabled;
|
||||
const isSelected = values.includes(optionValue);
|
||||
|
||||
const propsData = {
|
||||
...option.componentOptions.propsData,
|
||||
selected: isSelected,
|
||||
|
@ -470,15 +492,18 @@
|
|||
},
|
||||
|
||||
validateOption({children, elm, propsData}){
|
||||
const value = propsData.value;
|
||||
const label = propsData.label || '';
|
||||
const textContent = (elm && elm.textContent) || (children || []).reduce((str, node) => {
|
||||
const nodeText = node.elm ? node.elm.textContent : node.text;
|
||||
return `${str} ${nodeText}`;
|
||||
}, '') || '';
|
||||
const stringValues = JSON.stringify([value, label, textContent]);
|
||||
const stringValues = [label, textContent];
|
||||
const query = this.query.toLowerCase().trim();
|
||||
return stringValues.toLowerCase().includes(query);
|
||||
const findValuesIndex = stringValues.findIndex(item=>{
|
||||
let itemToLowerCase = item.toLowerCase();
|
||||
return itemToLowerCase.includes(query);
|
||||
});
|
||||
return findValuesIndex === -1 ? false : true;
|
||||
},
|
||||
|
||||
toggleMenu (e, force) {
|
||||
|
@ -492,9 +517,22 @@
|
|||
this.broadcast('Drop', 'on-update-popper');
|
||||
}
|
||||
},
|
||||
updateFocusIndex(){
|
||||
this.focusIndex = this.flatOptions.findIndex((opt) => {
|
||||
if (!opt || !opt.componentOptions) return false;
|
||||
return opt.componentOptions.propsData.value === this.publicValue;
|
||||
});
|
||||
},
|
||||
hideMenu () {
|
||||
this.toggleMenu(null, false);
|
||||
setTimeout(() => this.unchangedQuery = true, ANIMATION_TIMEOUT);
|
||||
setTimeout(() =>{
|
||||
this.unchangedQuery = true;
|
||||
// resolve if we use filterable, dropItem not selected #6349
|
||||
this.hideMenuTimer = setTimeout(()=>{
|
||||
this.updateFocusIndex();
|
||||
this.hideMenuTimer = null;
|
||||
});
|
||||
}, ANIMATION_TIMEOUT);
|
||||
},
|
||||
onClickOutside(event){
|
||||
if (this.visible) {
|
||||
|
@ -524,6 +562,7 @@
|
|||
event.preventDefault();
|
||||
this.hideMenu();
|
||||
this.isFocused = true;
|
||||
this.$emit('on-clickoutside', event);
|
||||
} else {
|
||||
this.caretPosition = -1;
|
||||
this.isFocused = false;
|
||||
|
@ -537,31 +576,32 @@
|
|||
this.filterQueryChange = false;
|
||||
},
|
||||
handleKeydown (e) {
|
||||
if (e.key === 'Backspace'){
|
||||
const key = e.key || e.code;
|
||||
if ( key === 'Backspace'){
|
||||
return; // so we don't call preventDefault
|
||||
}
|
||||
|
||||
if (this.visible) {
|
||||
e.preventDefault();
|
||||
if (e.key === 'Tab'){
|
||||
if ( key === 'Tab'){
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// Esc slide-up
|
||||
if (e.key === 'Escape') {
|
||||
if ( key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
this.hideMenu();
|
||||
}
|
||||
// next
|
||||
if (e.key === 'ArrowUp') {
|
||||
if ( key === 'ArrowUp') {
|
||||
this.navigateOptions(-1);
|
||||
}
|
||||
// prev
|
||||
if (e.key === 'ArrowDown') {
|
||||
if ( key === 'ArrowDown') {
|
||||
this.navigateOptions(1);
|
||||
}
|
||||
// enter
|
||||
if (e.key === 'Enter') {
|
||||
if ( key === 'Enter') {
|
||||
if (this.focusIndex === -1) return this.hideMenu();
|
||||
const optionComponent = this.flatOptions[this.focusIndex];
|
||||
|
||||
|
@ -610,7 +650,6 @@
|
|||
},
|
||||
onOptionClick(option) {
|
||||
if (this.multiple){
|
||||
|
||||
// keep the query for remote select
|
||||
if (this.remote) this.lastRemoteQuery = this.lastRemoteQuery || this.query;
|
||||
else this.lastRemoteQuery = '';
|
||||
|
@ -621,25 +660,19 @@
|
|||
} else {
|
||||
this.values = this.values.concat(option);
|
||||
}
|
||||
|
||||
this.isFocused = true; // so we put back focus after clicking with mouse on option elements
|
||||
} else {
|
||||
this.query = String(option.label).trim();
|
||||
this.query = '';
|
||||
this.values = [option];
|
||||
this.lastRemoteQuery = '';
|
||||
this.hideMenu();
|
||||
}
|
||||
|
||||
this.focusIndex = this.flatOptions.findIndex((opt) => {
|
||||
if (!opt || !opt.componentOptions) return false;
|
||||
return opt.componentOptions.propsData.value === option.value;
|
||||
});
|
||||
|
||||
if (this.filterable){
|
||||
const inputField = this.$el.querySelector('input[type="text"]');
|
||||
if (!this.autoComplete) this.$nextTick(() => inputField.focus());
|
||||
}
|
||||
this.broadcast('Drop', 'on-update-popper');
|
||||
this.$emit('on-select', this.publicValue); // # 4441
|
||||
setTimeout(() => {
|
||||
this.filterQueryChange = false;
|
||||
}, ANIMATION_TIMEOUT);
|
||||
|
@ -663,6 +696,9 @@
|
|||
this.query = query;
|
||||
this.unchangedQuery = this.visible;
|
||||
this.filterQueryChange = true;
|
||||
if(this.filterable){
|
||||
this.updateFocusIndex();
|
||||
}
|
||||
},
|
||||
toggleHeaderFocus({type}){
|
||||
if (this.disabled) {
|
||||
|
@ -682,13 +718,13 @@
|
|||
watch: {
|
||||
value(value){
|
||||
const {getInitialValue, getOptionData, publicValue, values} = this;
|
||||
|
||||
this.checkUpdateStatus();
|
||||
|
||||
const vModelValue = (publicValue && this.labelInValue) ?
|
||||
(this.multiple ? publicValue.map(({value}) => value) : publicValue.value) : publicValue;
|
||||
if (value === '') this.values = [];
|
||||
else if (checkValuesNotEqual(value,publicValue,values)) {
|
||||
else if (checkValuesNotEqual(value,vModelValue,values)) {
|
||||
this.$nextTick(() => this.values = getInitialValue().map(getOptionData).filter(Boolean));
|
||||
this.dispatch('FormItem', 'on-form-change', this.publicValue);
|
||||
if (!this.multiple) this.dispatch('FormItem', 'on-form-change', this.publicValue);
|
||||
}
|
||||
},
|
||||
values(now, before){
|
||||
|
@ -750,14 +786,15 @@
|
|||
const optionInstance = findChild(this, ({$options}) => {
|
||||
return $options.componentName === 'select-item' && $options.propsData.value === optionValue;
|
||||
});
|
||||
|
||||
let bottomOverflowDistance = optionInstance.$el.getBoundingClientRect().bottom - this.$refs.dropdown.$el.getBoundingClientRect().bottom;
|
||||
let topOverflowDistance = optionInstance.$el.getBoundingClientRect().top - this.$refs.dropdown.$el.getBoundingClientRect().top;
|
||||
if (bottomOverflowDistance > 0) {
|
||||
this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
|
||||
}
|
||||
if (topOverflowDistance < 0) {
|
||||
this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
|
||||
if(optionInstance && optionInstance.$el ){
|
||||
let bottomOverflowDistance = optionInstance.$el.getBoundingClientRect().bottom - this.$refs.dropdown.$el.getBoundingClientRect().bottom;
|
||||
let topOverflowDistance = optionInstance.$el.getBoundingClientRect().top - this.$refs.dropdown.$el.getBoundingClientRect().top;
|
||||
if (bottomOverflowDistance > 0) {
|
||||
this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
|
||||
}
|
||||
if (topOverflowDistance < 0) {
|
||||
this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
|
||||
}
|
||||
}
|
||||
},
|
||||
dropVisible(open){
|
||||
|
|
16
src/components/slider/marker.js
Normal file
16
src/components/slider/marker.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
export default {
|
||||
name: 'SliderMarker',
|
||||
props: {
|
||||
mark: {
|
||||
type: [String, Object]
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
let label = typeof this.mark === 'string' ? this.mark : [this.mark.label];
|
||||
|
||||
return h('div', {
|
||||
class: 'ivu-slider-marks-item',
|
||||
style: this.mark.style || {}
|
||||
}, label);
|
||||
}
|
||||
};
|
|
@ -7,25 +7,45 @@
|
|||
:max="max"
|
||||
:step="step"
|
||||
:value="exportValue[0]"
|
||||
:disabled="disabled"
|
||||
:disabled="itemDisabled"
|
||||
:active-change="activeChange"
|
||||
@on-change="handleInputChange"></Input-number>
|
||||
<div
|
||||
:class="[prefixCls + '-wrap']"
|
||||
ref="slider" @click.self="sliderClick"
|
||||
>
|
||||
<input type="hidden" :name="name" :value="exportValue">
|
||||
<template v-if="showStops">
|
||||
<div
|
||||
:class="[prefixCls + '-stop']"
|
||||
v-for="item in stops"
|
||||
:style="{ 'left': item + '%' }"
|
||||
@click.self="sliderClick"
|
||||
></div>
|
||||
</template>
|
||||
<div
|
||||
:class="[prefixCls + '-bar']"
|
||||
:style="barStyle"
|
||||
@click.self="sliderClick"></div>
|
||||
<template v-if="showStops">
|
||||
<div
|
||||
:class="[prefixCls + '-stop']"
|
||||
v-for="(item,index) in stops"
|
||||
:key="index"
|
||||
:style="{ 'left': item + '%' }"
|
||||
@click.self="sliderClick"
|
||||
></div>
|
||||
</template>
|
||||
<template v-if="markList.length > 0">
|
||||
<div
|
||||
v-for="(item, key) in markList"
|
||||
:key="key"
|
||||
:class="[prefixCls + '-stop']"
|
||||
:style="{ 'left': item.position + '%' }"
|
||||
@click.self="sliderClick"
|
||||
></div>
|
||||
<div class="ivu-slider-marks">
|
||||
<SliderMarker
|
||||
v-for="(item, key) in markList"
|
||||
:key="key"
|
||||
:mark="item.mark"
|
||||
:style="{ 'left': item.position + '%' }"
|
||||
@click.native="sliderClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
:class="[prefixCls + '-button-wrap']"
|
||||
:style="{left: minPosition + '%'}"
|
||||
|
@ -82,17 +102,19 @@
|
|||
<script>
|
||||
import InputNumber from '../../components/input-number/input-number.vue';
|
||||
import Tooltip from '../../components/tooltip/tooltip.vue';
|
||||
import SliderMarker from './marker';
|
||||
import { getStyle, oneOf } from '../../utils/assist';
|
||||
import { on, off } from '../../utils/dom';
|
||||
import Emitter from '../../mixins/emitter';
|
||||
import mixinsForm from '../../mixins/form';
|
||||
import elementResizeDetectorMaker from 'element-resize-detector';
|
||||
|
||||
const prefixCls = 'ivu-slider';
|
||||
|
||||
export default {
|
||||
name: 'Slider',
|
||||
mixins: [ Emitter ],
|
||||
components: { InputNumber, Tooltip },
|
||||
mixins: [ Emitter, mixinsForm ],
|
||||
components: { InputNumber, Tooltip, SliderMarker },
|
||||
props: {
|
||||
min: {
|
||||
type: Number,
|
||||
|
@ -148,6 +170,15 @@
|
|||
},
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
// 3.4.0
|
||||
activeChange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 3.5.4
|
||||
marks: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -194,7 +225,7 @@
|
|||
{
|
||||
[`${prefixCls}-input`]: this.showInput && !this.range,
|
||||
[`${prefixCls}-range`]: this.range,
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
[`${prefixCls}-disabled`]: this.itemDisabled
|
||||
}
|
||||
];
|
||||
},
|
||||
|
@ -248,6 +279,19 @@
|
|||
}
|
||||
return result;
|
||||
},
|
||||
markList() {
|
||||
if (!this.marks) return [];
|
||||
|
||||
const marksKeys = Object.keys(this.marks);
|
||||
return marksKeys.map(parseFloat)
|
||||
.sort((a, b) => a - b)
|
||||
.filter(point => point <= this.max && point >= this.min)
|
||||
.map(point => ({
|
||||
point,
|
||||
position: (point - this.min) * 100 / (this.max - this.min),
|
||||
mark: this.marks[point]
|
||||
}));
|
||||
},
|
||||
tipDisabled () {
|
||||
return this.tipFormat(this.currentValue[0]) === null || this.showTip === 'never';
|
||||
},
|
||||
|
@ -274,7 +318,7 @@
|
|||
return [min, max];
|
||||
},
|
||||
getCurrentValue (event, type) {
|
||||
if (this.disabled) {
|
||||
if (this.itemDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -298,7 +342,7 @@
|
|||
}
|
||||
},
|
||||
onPointerDown (event, type) {
|
||||
if (this.disabled) return;
|
||||
if (this.itemDisabled) return;
|
||||
event.preventDefault();
|
||||
this.pointerDown = type;
|
||||
|
||||
|
@ -353,10 +397,10 @@
|
|||
this.currentValue = [...value];
|
||||
|
||||
if (!this.dragging) {
|
||||
if (this.currentValue[index] !== this.oldValue[index]) {
|
||||
this.emitChange();
|
||||
this.oldValue[index] = this.currentValue[index];
|
||||
}
|
||||
// if (this.currentValue[index] !== this.oldValue[index]) {
|
||||
this.emitChange();
|
||||
// this.oldValue[index] = this.currentValue[index];
|
||||
// }
|
||||
}
|
||||
},
|
||||
handleDecimal(pos,step){
|
||||
|
@ -380,7 +424,7 @@
|
|||
},
|
||||
|
||||
sliderClick (event) {
|
||||
if (this.disabled) return;
|
||||
if (this.itemDisabled) return;
|
||||
const currentX = this.getPointerX(event);
|
||||
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
|
||||
let newPos = ((currentX - sliderOffsetLeft) / this.sliderWidth * this.valueRange) + this.min;
|
||||
|
@ -431,4 +475,4 @@
|
|||
this.observer.removeListener(this.$refs.slider, this.handleSetSliderWidth);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
|
@ -69,7 +69,10 @@
|
|||
prefix: 'ivu-split',
|
||||
offset: 0,
|
||||
oldOffset: 0,
|
||||
isMoving: false
|
||||
isMoving: false,
|
||||
computedMin: 0,
|
||||
computedMax: 0,
|
||||
currentValue: 0.5
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -98,12 +101,6 @@
|
|||
},
|
||||
offsetSize () {
|
||||
return this.isHorizontal ? 'offsetWidth' : 'offsetHeight';
|
||||
},
|
||||
computedMin () {
|
||||
return this.getComputedThresholdValue('min');
|
||||
},
|
||||
computedMax () {
|
||||
return this.getComputedThresholdValue('max');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -157,22 +154,35 @@
|
|||
this.$emit('on-move-start');
|
||||
},
|
||||
computeOffset(){
|
||||
this.offset = (this.valueIsPx ? this.px2percent(this.value, this.$refs.outerWrapper[this.offsetSize]) : this.value) * 10000 / 100;
|
||||
this.$nextTick(() => {
|
||||
this.computedMin = this.getComputedThresholdValue('min');
|
||||
this.computedMax = this.getComputedThresholdValue('max');
|
||||
let value = this.valueIsPx ? this.px2percent(this.value, this.$refs.outerWrapper[this.offsetSize]) : this.value;
|
||||
let anotherValue = this.getAnotherOffset(value);
|
||||
if (parseFloat(value) <= parseFloat(this.computedMin)) value = this.getMax(value, this.computedMin);
|
||||
if (parseFloat(anotherValue) <= parseFloat(this.computedMax)) value = this.getAnotherOffset(this.getMax(anotherValue, this.computedMax));
|
||||
this.offset = value * 10000 / 100;
|
||||
this.currentValue = value;
|
||||
this.$emit('input', value);
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value () {
|
||||
this.computeOffset();
|
||||
value (val) {
|
||||
if (val !== this.currentValue) {
|
||||
this.currentValue = val;
|
||||
this.computeOffset();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick(() => {
|
||||
this.computeOffset();
|
||||
});
|
||||
|
||||
window.addEventListener('resize', ()=>{
|
||||
this.computeOffset();
|
||||
});
|
||||
on(window, 'resize', this.computeOffset);
|
||||
},
|
||||
beforeDestroy () {
|
||||
off(window, 'resize', this.computeOffset);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
<div :class="[prefixCls + '-tail']"><i></i></div>
|
||||
<div :class="[prefixCls + '-head']">
|
||||
<div :class="[prefixCls + '-head-inner']">
|
||||
<span v-if="!icon && currentStatus != 'finish' && currentStatus != 'error'">{{ stepNumber }}</span>
|
||||
<span v-else :class="iconClasses"></span>
|
||||
<slot name="status">
|
||||
<span v-if="!icon && currentStatus != 'finish' && currentStatus != 'error'">{{ stepNumber }}</span>
|
||||
<span v-else :class="iconClasses"></span>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-main']">
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<span
|
||||
tabindex="0"
|
||||
:class="wrapClasses"
|
||||
:style="wrapStyles"
|
||||
@click="toggle"
|
||||
@keydown.space="toggle"
|
||||
>
|
||||
|
@ -15,9 +16,7 @@
|
|||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import Emitter from '../../mixins/emitter';
|
||||
|
||||
const prefixCls = 'ivu-switch';
|
||||
|
||||
export default {
|
||||
name: 'iSwitch',
|
||||
mixins: [ Emitter ],
|
||||
|
@ -52,7 +51,14 @@
|
|||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
trueColor: {
|
||||
type: String
|
||||
},
|
||||
falseColor: {
|
||||
type: String
|
||||
},
|
||||
beforeChange: Function
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -71,23 +77,45 @@
|
|||
}
|
||||
];
|
||||
},
|
||||
wrapStyles () {
|
||||
let style = {};
|
||||
if (this.trueColor && this.currentValue === this.trueValue) {
|
||||
style['border-color'] = this.trueColor;
|
||||
style['background-color'] = this.trueColor;
|
||||
} else if (this.falseColor && this.currentValue === this.falseValue) {
|
||||
style['border-color'] = this.falseColor;
|
||||
style['background-color'] = this.falseColor;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleToggle () {
|
||||
const checked = this.currentValue === this.trueValue ? this.falseValue : this.trueValue;
|
||||
this.currentValue = checked;
|
||||
this.$emit('input', checked);
|
||||
this.$emit('on-change', checked);
|
||||
this.dispatch('FormItem', 'on-form-change', checked);
|
||||
},
|
||||
toggle (event) {
|
||||
event.preventDefault();
|
||||
if (this.disabled || this.loading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const checked = this.currentValue === this.trueValue ? this.falseValue : this.trueValue;
|
||||
|
||||
this.currentValue = checked;
|
||||
this.$emit('input', checked);
|
||||
this.$emit('on-change', checked);
|
||||
this.dispatch('FormItem', 'on-form-change', checked);
|
||||
if (!this.beforeChange) {
|
||||
return this.handleToggle();
|
||||
}
|
||||
const before = this.beforeChange();
|
||||
if (before && before.then) {
|
||||
before.then(() => {
|
||||
this.handleToggle();
|
||||
});
|
||||
} else {
|
||||
this.handleToggle();
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<table-tr
|
||||
:draggable="draggable"
|
||||
:row="row"
|
||||
:key="row._rowKey"
|
||||
:key="rowKey ? row._rowKey : index"
|
||||
:prefix-cls="prefixCls"
|
||||
@mouseenter.native.stop="handleMouseIn(row._index)"
|
||||
@mouseleave.native.stop="handleMouseOut(row._index)"
|
||||
|
@ -31,7 +31,7 @@
|
|||
</table-tr>
|
||||
<tr v-if="rowExpanded(row._index)" :class="{[prefixCls + '-expanded-hidden']: fixed}">
|
||||
<td :colspan="columns.length" :class="prefixCls + '-expanded-cell'">
|
||||
<Expand :key="row._rowKey" :row="row" :render="expandRender" :index="row._index"></Expand>
|
||||
<Expand :key="rowKey ? row._rowKey : index" :row="row" :render="expandRender" :index="row._index"></Expand>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
@ -63,6 +63,10 @@
|
|||
draggable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rowKey: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<span v-if="!column.renderHeader">{{ column.title || '' }}</span>
|
||||
<render-header v-else :render="column.renderHeader" :column="column" :index="index"></render-header>
|
||||
</template>
|
||||
<template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" :disabled="!data.length" @on-change="selectAll"></Checkbox></template>
|
||||
<template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" :disabled="isSelectDisabled" @on-change="selectAll"></Checkbox></template>
|
||||
<template v-else>
|
||||
<span v-if="!column.renderHeader" :class="{[prefixCls + '-cell-sort']: column.sortable}" @click="handleSortByHead(getColumn(rowIndex, index)._index)">{{ column.title || '#' }}</span>
|
||||
<render-header v-else :render="column.renderHeader" :column="column" :index="index"></render-header>
|
||||
|
@ -61,7 +61,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</th>
|
||||
|
||||
|
||||
<th v-if="$parent.showVerticalScrollBar && rowIndex===0" :class='scrollBarCellClass()' :rowspan="headRows.length"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -121,6 +121,12 @@
|
|||
} else {
|
||||
return [this.columns];
|
||||
}
|
||||
},
|
||||
isSelectDisabled () {
|
||||
let isSelectDisabled = false;
|
||||
if (!this.data.length) isSelectDisabled = true;
|
||||
if (!this.data.find(item => !item._disabled)) isSelectDisabled = true;
|
||||
return isSelectDisabled;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -171,7 +177,8 @@
|
|||
this.$parent.selectAll(status);
|
||||
},
|
||||
handleSort (index, type) {
|
||||
const column = this.columns[index];
|
||||
// 在固定列时,寻找正确的 index #5580
|
||||
const column = this.columns.find(item => item._index === index);
|
||||
const _index = column._index;
|
||||
|
||||
if (column._sortType === type) {
|
||||
|
@ -180,7 +187,8 @@
|
|||
this.$parent.handleSort(_index, type);
|
||||
},
|
||||
handleSortByHead (index) {
|
||||
const column = this.columns[index];
|
||||
// 在固定列时,寻找正确的 index #5580
|
||||
const column = this.columns.find(item => item._index === index);
|
||||
if (column.sortable) {
|
||||
const type = column._sortType;
|
||||
if (type === 'normal') {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
:styleObject="tableStyle"
|
||||
:columns="cloneColumns"
|
||||
:data="rebuildData"
|
||||
:row-key="rowKey"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
|
@ -59,6 +60,7 @@
|
|||
:styleObject="fixedTableStyle"
|
||||
:columns="leftFixedColumns"
|
||||
:data="rebuildData"
|
||||
:row-key="rowKey"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
|
@ -84,6 +86,7 @@
|
|||
:styleObject="fixedRightTableStyle"
|
||||
:columns="rightFixedColumns"
|
||||
:data="rebuildData"
|
||||
:row-key="rowKey"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
|
@ -149,6 +152,10 @@
|
|||
height: {
|
||||
type: [Number, String]
|
||||
},
|
||||
// 3.4.0
|
||||
maxHeight: {
|
||||
type: [Number, String]
|
||||
},
|
||||
stripe: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
@ -196,6 +203,11 @@
|
|||
return oneOf(value, ['dark', 'light']);
|
||||
},
|
||||
default: 'dark'
|
||||
},
|
||||
// #5380 开启后,:key 强制更新,否则使用 index
|
||||
rowKey: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -275,6 +287,10 @@
|
|||
const height = parseInt(this.height);
|
||||
style.height = `${height}px`;
|
||||
}
|
||||
if (this.maxHeight) {
|
||||
const maxHeight = parseInt(this.maxHeight);
|
||||
style.maxHeight = `${maxHeight}px`;
|
||||
}
|
||||
if (this.width) style.width = `${this.width}px`;
|
||||
return style;
|
||||
},
|
||||
|
@ -336,7 +352,11 @@
|
|||
let style = {};
|
||||
if (this.bodyHeight !== 0) {
|
||||
const height = this.bodyHeight;
|
||||
style.height = `${height}px`;
|
||||
if (this.height) {
|
||||
style.height = `${height}px`;
|
||||
} else if (this.maxHeight) {
|
||||
style.maxHeight = `${height}px`;
|
||||
}
|
||||
}
|
||||
return style;
|
||||
},
|
||||
|
@ -548,7 +568,7 @@
|
|||
this.objData[_index]._isExpanded = status;
|
||||
this.$emit('on-expand', JSON.parse(JSON.stringify(this.cloneData[_index])), status);
|
||||
|
||||
if(this.height){
|
||||
if(this.height || this.maxHeight){
|
||||
this.$nextTick(()=>this.fixedBody());
|
||||
}
|
||||
},
|
||||
|
@ -578,12 +598,16 @@
|
|||
},
|
||||
|
||||
fixedHeader () {
|
||||
if (this.height) {
|
||||
if (this.height || this.maxHeight) {
|
||||
this.$nextTick(() => {
|
||||
const titleHeight = parseInt(getStyle(this.$refs.title, 'height')) || 0;
|
||||
const headerHeight = parseInt(getStyle(this.$refs.header, 'height')) || 0;
|
||||
const footerHeight = parseInt(getStyle(this.$refs.footer, 'height')) || 0;
|
||||
this.bodyHeight = this.height - titleHeight - headerHeight - footerHeight;
|
||||
if (this.height) {
|
||||
this.bodyHeight = this.height - titleHeight - headerHeight - footerHeight;
|
||||
} else if (this.maxHeight) {
|
||||
this.bodyHeight = this.maxHeight - titleHeight - headerHeight - footerHeight;
|
||||
}
|
||||
this.$nextTick(()=>this.fixedBody());
|
||||
});
|
||||
} else {
|
||||
|
@ -943,7 +967,9 @@
|
|||
|
||||
this.$on('on-visible-change', (val) => {
|
||||
if (val) {
|
||||
this.handleResize();
|
||||
this.$nextTick(()=>{
|
||||
this.handleResize();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -986,6 +1012,9 @@
|
|||
height () {
|
||||
this.handleResize();
|
||||
},
|
||||
maxHeight () {
|
||||
this.handleResize();
|
||||
},
|
||||
showHorizontalScrollBar () {
|
||||
this.handleResize();
|
||||
},
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
<span :class="[prefixCls + '-nav-prev', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollPrev"><Icon type="ios-arrow-back"></Icon></span>
|
||||
<span :class="[prefixCls + '-nav-next', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollNext"><Icon type="ios-arrow-forward"></Icon></span>
|
||||
<div ref="navScroll" :class="[prefixCls + '-nav-scroll']">
|
||||
<div ref="nav" :class="[prefixCls + '-nav']" class="nav-text" :style="navStyle">
|
||||
<div ref="nav" :class="[prefixCls + '-nav']" :style="navStyle">
|
||||
<div :class="barClasses" :style="barStyle"></div>
|
||||
<div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)">
|
||||
<Icon v-if="item.icon !== ''" :type="item.icon"></Icon>
|
||||
<Render v-if="item.labelType === 'function'" :render="item.label"></Render>
|
||||
<template v-else>{{ item.label }}</template>
|
||||
<Icon v-if="showClose(item)" type="ios-close" @click.native.stop="handleRemove(index)"></Icon>
|
||||
<Icon :class="[prefixCls + '-close']" v-if="showClose(item)" :type="arrowType" :custom="customArrowType" :size="arrowSize" @click.native.stop="handleRemove(index)"></Icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -100,6 +100,13 @@
|
|||
name: {
|
||||
type: String
|
||||
},
|
||||
custContentClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
custContentStyle: {
|
||||
type: Object,
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -133,7 +140,8 @@
|
|||
`${prefixCls}-content`,
|
||||
{
|
||||
[`${prefixCls}-content-animated`]: this.animated
|
||||
}
|
||||
},
|
||||
this.custContentClass
|
||||
];
|
||||
},
|
||||
barClasses () {
|
||||
|
@ -154,6 +162,12 @@
|
|||
transform: `translateX(${p}) translateZ(0px)`
|
||||
};
|
||||
}
|
||||
const { custContentStyle } = this;
|
||||
if (custContentStyle) {
|
||||
for (const key in custContentStyle){
|
||||
style[key] = custContentStyle[key];
|
||||
}
|
||||
}
|
||||
return style;
|
||||
},
|
||||
barStyle () {
|
||||
|
@ -169,6 +183,41 @@
|
|||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-close';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tabs.customCloseIcon) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.tabs.closeIcon) {
|
||||
type = this.$IVIEW.tabs.closeIcon;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tabs.customCloseIcon) {
|
||||
type = this.$IVIEW.tabs.customCloseIcon;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tabs.closeIconSize) {
|
||||
size = this.$IVIEW.tabs.closeIconSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -182,7 +231,7 @@
|
|||
if (item.tab === this.name) {
|
||||
TabPanes.push(item);
|
||||
}
|
||||
} else {
|
||||
}else if (this.$children.includes(item)) { // #6279 #6299
|
||||
TabPanes.push(item);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -235,9 +235,11 @@
|
|||
},
|
||||
handleLeftCheckedKeysChange (keys) {
|
||||
this.leftCheckedKeys = keys;
|
||||
this.handleCheckedKeys();
|
||||
},
|
||||
handleRightCheckedKeysChange (keys) {
|
||||
this.rightCheckedKeys = keys;
|
||||
this.handleCheckedKeys();
|
||||
},
|
||||
handleCheckedKeys () {
|
||||
const sourceSelectedKeys = this.getValidKeys('left');
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<collapse-transition>
|
||||
<collapse-transition :appear="appear">
|
||||
<ul :class="classes">
|
||||
<li>
|
||||
<span :class="arrowClasses" @click="handleExpand">
|
||||
<Icon v-if="showArrow" type="ios-arrow-forward"></Icon>
|
||||
<Icon v-if="showLoading" type="ios-loading" class="ivu-load-loop"></Icon>
|
||||
<Icon v-if="showArrow" :type="arrowType" :custom="customArrowType" :size="arrowSize" />
|
||||
<Icon v-if="showLoading" type="ios-loading" class="ivu-load-loop" />
|
||||
</span>
|
||||
<Checkbox
|
||||
v-if="showCheckbox"
|
||||
|
@ -17,6 +17,7 @@
|
|||
<span v-else :class="titleClasses" @click="handleSelect">{{ data.title }}</span>
|
||||
<Tree-node
|
||||
v-if="data.expand"
|
||||
:appear="appearByClickArrow"
|
||||
v-for="(item, i) in children"
|
||||
:key="i"
|
||||
:data="item"
|
||||
|
@ -61,11 +62,18 @@
|
|||
showCheckbox: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
appear: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls
|
||||
prefixCls: prefixCls,
|
||||
appearByClickArrow: false,
|
||||
// #6139
|
||||
loadingChildrenState : true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -99,7 +107,7 @@
|
|||
];
|
||||
},
|
||||
showArrow () {
|
||||
return (this.data[this.childrenKey] && this.data[this.childrenKey].length) || ('loading' in this.data && !this.data.loading);
|
||||
return (this.data[this.childrenKey] && this.data[this.childrenKey].length) || ('loading' in this.data && !this.data.loading && this.loadingChildrenState);
|
||||
},
|
||||
showLoading () {
|
||||
return 'loading' in this.data && this.data.loading;
|
||||
|
@ -127,6 +135,41 @@
|
|||
},
|
||||
children () {
|
||||
return this.data[this.childrenKey];
|
||||
},
|
||||
// 3.4.0, global setting customArrow 有值时,arrow 赋值空
|
||||
arrowType () {
|
||||
let type = 'ios-arrow-forward';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tree.customArrow) {
|
||||
type = '';
|
||||
} else if (this.$IVIEW.tree.arrow) {
|
||||
type = this.$IVIEW.tree.arrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
customArrowType () {
|
||||
let type = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tree.customArrow) {
|
||||
type = this.$IVIEW.tree.customArrow;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// 3.4.0, global setting
|
||||
arrowSize () {
|
||||
let size = '';
|
||||
|
||||
if (this.$IVIEW) {
|
||||
if (this.$IVIEW.tree.arrowSize) {
|
||||
size = this.$IVIEW.tree.arrowSize;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -134,6 +177,9 @@
|
|||
const item = this.data;
|
||||
if (item.disabled) return;
|
||||
|
||||
// Vue.js 2.6.9 对 transition 的 appear 进行了调整,导致 iView 初始化时无动画,加此方法来判断通过点击箭头展开时,加 appear,否则初始渲染时 appear 为 false
|
||||
this.appearByClickArrow = true;
|
||||
|
||||
// async loading
|
||||
if (item[this.childrenKey].length === 0) {
|
||||
const tree = findComponentUpward(this, 'Tree');
|
||||
|
@ -144,6 +190,8 @@
|
|||
if (children.length) {
|
||||
this.$set(this.data, this.childrenKey, children);
|
||||
this.$nextTick(() => this.handleExpand());
|
||||
}else{
|
||||
this.loadingChildrenState = false;
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
|
|
@ -121,9 +121,9 @@
|
|||
const node = this.flatState[nodeKey].node;
|
||||
const parent = this.flatState[parentKey].node;
|
||||
if (node.checked == parent.checked && node.indeterminate == parent.indeterminate) return; // no need to update upwards
|
||||
|
||||
if (node.checked == true) {
|
||||
this.$set(parent, 'checked', parent[this.childrenKey].every(node => node.checked));
|
||||
// #6121
|
||||
this.$set(parent, 'checked', parent[this.childrenKey].every(node => node.checked || node.disabled !== undefined ));
|
||||
this.$set(parent, 'indeterminate', !parent.checked);
|
||||
} else {
|
||||
this.$set(parent, 'checked', false);
|
||||
|
@ -160,10 +160,16 @@
|
|||
},
|
||||
updateTreeDown(node, changes = {}) {
|
||||
if (this.checkStrictly) return;
|
||||
|
||||
for (let key in changes) {
|
||||
this.$set(node, key, changes[key]);
|
||||
// after #6121
|
||||
if( key === 'checked' && node.disabled ){
|
||||
this.$set(node, key, node.checked);
|
||||
}else{
|
||||
this.$set(node, key, changes[key]);
|
||||
}
|
||||
// before -- this.$set(node, key, changes[key]);
|
||||
}
|
||||
|
||||
if (node[this.childrenKey]) {
|
||||
node[this.childrenKey].forEach(child => {
|
||||
this.updateTreeDown(child, changes);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue