mirror of https://github.com/ElemeFE/element
commit
d4ec462340
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
.PHONY: dist
|
.PHONY: dist test
|
||||||
default: help
|
default: help
|
||||||
|
|
||||||
# build all theme
|
# build all theme
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
const Popover = require('./src/main');
|
const Popover = require('./src/main');
|
||||||
|
const directive = require('./src/directive').default;
|
||||||
|
const Vue = require('vue');
|
||||||
|
|
||||||
|
Vue.directive('popover', directive);
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
Popover.install = function(Vue) {
|
Popover.install = function(Vue) {
|
||||||
|
Vue.directive('popover', directive);
|
||||||
Vue.component(Popover.name, Popover);
|
Vue.component(Popover.name, Popover);
|
||||||
};
|
};
|
||||||
|
Popover.directive = directive;
|
||||||
|
|
||||||
module.exports = Popover;
|
module.exports = Popover;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export default {
|
||||||
|
bind(el, binding, vnode) {
|
||||||
|
vnode.context.$refs[binding.arg].$refs.reference = el;
|
||||||
|
}
|
||||||
|
};
|
|
@ -17,15 +17,8 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Popper from 'element-ui/src/utils/vue-popper';
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
import Vue from 'vue';
|
|
||||||
import { on, off } from 'wind-dom/src/event';
|
import { on, off } from 'wind-dom/src/event';
|
||||||
|
|
||||||
Vue.directive('popover', {
|
|
||||||
bind(el, binding, vnode) {
|
|
||||||
vnode.context.$refs[binding.arg].$refs.reference = el;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'el-popover',
|
name: 'el-popover',
|
||||||
|
|
||||||
|
@ -52,11 +45,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
let _timer;
|
let reference = this.reference || this.$refs.reference;
|
||||||
const reference = this.reference || this.$refs.reference || this.$slots.reference[0].elm;
|
|
||||||
const popper = this.popper || this.$refs.popper;
|
const popper = this.popper || this.$refs.popper;
|
||||||
|
|
||||||
this.$nextTick(() => {
|
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
|
||||||
|
reference = this.$slots.reference[0].elm;
|
||||||
|
}
|
||||||
if (this.trigger === 'click') {
|
if (this.trigger === 'click') {
|
||||||
on(reference, 'click', () => { this.showPopper = !this.showPopper; });
|
on(reference, 'click', () => { this.showPopper = !this.showPopper; });
|
||||||
on(document, 'click', (e) => {
|
on(document, 'click', (e) => {
|
||||||
|
@ -69,21 +63,17 @@ export default {
|
||||||
this.showPopper = false;
|
this.showPopper = false;
|
||||||
});
|
});
|
||||||
} else if (this.trigger === 'hover') {
|
} else if (this.trigger === 'hover') {
|
||||||
on(reference, 'mouseenter', () => {
|
on(reference, 'mouseenter', this.handleMouseEnter);
|
||||||
this.showPopper = true;
|
on(popper, 'mouseenter', this.handleMouseEnter);
|
||||||
clearTimeout(_timer);
|
on(reference, 'mouseleave', this.handleMouseLeave);
|
||||||
});
|
on(popper, 'mouseleave', this.handleMouseLeave);
|
||||||
on(reference, 'mouseleave', () => {
|
|
||||||
_timer = setTimeout(() => {
|
|
||||||
this.showPopper = false;
|
|
||||||
}, 200);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
if ([].slice.call(reference.children).length) {
|
if ([].slice.call(reference.children).length) {
|
||||||
const children = reference.childNodes;
|
const children = reference.childNodes;
|
||||||
|
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
if (children[i].nodeName === 'INPUT') {
|
if (children[i].nodeName === 'INPUT' ||
|
||||||
|
children[i].nodeName === 'TEXTAREA') {
|
||||||
on(children[i], 'focus', () => { this.showPopper = true; });
|
on(children[i], 'focus', () => { this.showPopper = true; });
|
||||||
on(children[i], 'blur', () => { this.showPopper = false; });
|
on(children[i], 'blur', () => { this.showPopper = false; });
|
||||||
break;
|
break;
|
||||||
|
@ -100,7 +90,18 @@ export default {
|
||||||
on(reference, 'mouseup', () => { this.showPopper = false; });
|
on(reference, 'mouseup', () => { this.showPopper = false; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleMouseEnter() {
|
||||||
|
this.showPopper = true;
|
||||||
|
clearTimeout(this._timer);
|
||||||
|
},
|
||||||
|
handleMouseLeave() {
|
||||||
|
this._timer = setTimeout(() => {
|
||||||
|
this.showPopper = false;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
|
|
@ -19,8 +19,8 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 5
|
default: 5
|
||||||
},
|
},
|
||||||
reference: Object,
|
reference: {},
|
||||||
popper: Object,
|
popper: {},
|
||||||
offset: {
|
offset: {
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
|
@ -73,7 +73,6 @@ export default {
|
||||||
const reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference || this.$slots.reference[0].elm;
|
const reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference || this.$slots.reference[0].elm;
|
||||||
|
|
||||||
if (!popper || !reference) return;
|
if (!popper || !reference) return;
|
||||||
|
|
||||||
if (this.visibleArrow) this.appendArrow(popper);
|
if (this.visibleArrow) this.appendArrow(popper);
|
||||||
if (this.appendToBody) document.body.appendChild(this.popperElm);
|
if (this.appendToBody) document.body.appendChild(this.popperElm);
|
||||||
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
|
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
import { createVue, triggerEvent, createTest } from '../util';
|
||||||
|
import Popover, { directive } from 'packages/popover';
|
||||||
|
|
||||||
|
describe('Popover', () => {
|
||||||
|
describe('trigger', () => {
|
||||||
|
const createVM = (trigger) => {
|
||||||
|
return createVue(`
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover"
|
||||||
|
trigger="${trigger}"
|
||||||
|
content="content">
|
||||||
|
<button slot="reference">trigger ${trigger}</button>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
`, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('click', () => {
|
||||||
|
const vm = createVM('click');
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
|
||||||
|
vm.$el.querySelector('button').click();
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
document.body.click();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hover', done => {
|
||||||
|
const vm = createVM('hover');
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
const button = vm.$el.querySelector('button');
|
||||||
|
|
||||||
|
triggerEvent(button, 'mouseenter');
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
triggerEvent(button, 'mouseleave');
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
done();
|
||||||
|
}, 250); // 代码里是 200ms
|
||||||
|
});
|
||||||
|
|
||||||
|
it('focus input in children node', () => {
|
||||||
|
const vm = createVue(`
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover"
|
||||||
|
trigger="focus"
|
||||||
|
content="content">
|
||||||
|
<div slot="reference">
|
||||||
|
<input type="text" value="trigger focus" />
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
`, true);
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
const input = vm.$el.querySelector('input');
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
input.blur();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('focus textarea in children node', () => {
|
||||||
|
const vm = createVue(`
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover"
|
||||||
|
trigger="focus"
|
||||||
|
content="content">
|
||||||
|
<div slot="reference">
|
||||||
|
<textarea></textarea>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
`, true);
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
const textarea = vm.$el.querySelector('textarea');
|
||||||
|
|
||||||
|
textarea.focus();
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
textarea.blur();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('focus input', () => {
|
||||||
|
const vm = createVue(`
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover"
|
||||||
|
trigger="focus"
|
||||||
|
content="content">
|
||||||
|
<input type="text" slot="reference" value="trigger focus" />
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
`, true);
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
const input = vm.$el.querySelector('input');
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
input.blur();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('focus button', () => {
|
||||||
|
const vm = createVM('focus');
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
const button = vm.$el.querySelector('button');
|
||||||
|
|
||||||
|
triggerEvent(button, 'mousedown');
|
||||||
|
expect(compo.showPopper).to.true;
|
||||||
|
triggerEvent(button, 'mouseup');
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create by directive', () => {
|
||||||
|
const vm = createVue({
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover1"
|
||||||
|
trigger="click"
|
||||||
|
content="content">
|
||||||
|
</el-popover>
|
||||||
|
<button v-popover:popover1>create by directive</button>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
|
||||||
|
directives: {
|
||||||
|
Popover: directive
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const compo = vm.$refs.popover1;
|
||||||
|
|
||||||
|
it('render', () => {
|
||||||
|
expect(vm.$el.querySelector('.el-popover')).to.have.deep.property('textContent').include('content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggering click', done => {
|
||||||
|
vm.$el.querySelector('button').click();
|
||||||
|
expect(compo.popperElm).to.not.exist;
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(compo).to.have.deep.property('popperElm.style.display').not.equal('none');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('click outside', () => {
|
||||||
|
document.body.click();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create by slot', () => {
|
||||||
|
const vm = createVue(`
|
||||||
|
<div>
|
||||||
|
<el-popover
|
||||||
|
ref="popover"
|
||||||
|
trigger="click"
|
||||||
|
content="content">
|
||||||
|
<button slot="reference">create by slot</button>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
`, true);
|
||||||
|
const compo = vm.$refs.popover;
|
||||||
|
|
||||||
|
it('render', () => {
|
||||||
|
expect(vm.$el.querySelector('.el-popover')).to.have.deep.property('textContent').include('content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggering click', done => {
|
||||||
|
vm.$el.querySelector('button').click();
|
||||||
|
expect(compo.popperElm).to.not.exist;
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(compo).to.have.deep.property('popperElm.style.display').not.equal('none');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('click outside', () => {
|
||||||
|
document.body.click();
|
||||||
|
expect(compo.showPopper).to.false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('destroy event', () => {
|
||||||
|
const vm = createTest(Popover, {
|
||||||
|
reference: document.createElement('div'),
|
||||||
|
popper: document.createElement('div')
|
||||||
|
});
|
||||||
|
expect(() => vm.$destroy(true)).not.throw();
|
||||||
|
});
|
||||||
|
});
|
|
@ -7,8 +7,7 @@ describe('Tooltip', () => {
|
||||||
<button>click</button>
|
<button>click</button>
|
||||||
</el-tooltip>`);
|
</el-tooltip>`);
|
||||||
|
|
||||||
expect(vm.$el.querySelector('.el-tooltip__popper')).to.exist;
|
expect(vm.$el.querySelector('.el-tooltip__popper')).to.have.property('textContent', '提示文字');
|
||||||
expect(vm.$el.querySelector('.el-tooltip__popper').textContent).to.equal('提示文字');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hover', done => {
|
it('hover', done => {
|
||||||
|
@ -24,14 +23,13 @@ describe('Tooltip', () => {
|
||||||
|
|
||||||
expect(tooltip.popperElm).to.not.exist;
|
expect(tooltip.popperElm).to.not.exist;
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(tooltip.popperElm).to.exist;
|
expect(tooltip).to.have.deep.property('popperElm.style.display').not.equal('none');
|
||||||
expect(tooltip.popperElm.style.display).to.not.equal('none');
|
|
||||||
|
|
||||||
// trigger mouseleave
|
// trigger mouseleave
|
||||||
tooltip.handleClosePopper();
|
tooltip.handleClosePopper();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(tooltip.popperElm.style.display).to.equal('none');
|
expect(tooltip).to.have.deep.property('popperElm.style.display', 'none');
|
||||||
done();
|
done();
|
||||||
}, 500);
|
}, 500);
|
||||||
}, 150);
|
}, 150);
|
||||||
|
|
|
@ -46,3 +46,19 @@ exports.createTest = function(Compo, propsData = {}, mounted = false) {
|
||||||
const Ctor = Vue.extend(Compo);
|
const Ctor = Vue.extend(Compo);
|
||||||
return new Ctor({ propsData }).$mount(mounted === false ? null : elm);
|
return new Ctor({ propsData }).$mount(mounted === false ? null : elm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发一个事件
|
||||||
|
* mouseenter, mouseleave, mouseover 等
|
||||||
|
* @param {Element} elm
|
||||||
|
* @param {EventName} name
|
||||||
|
* @param {options} opts
|
||||||
|
*/
|
||||||
|
exports.triggerEvent = function(elm, name, opts) {
|
||||||
|
const evt = document.createEvent('MouseEvents');
|
||||||
|
|
||||||
|
evt.initEvent(name, ...opts);
|
||||||
|
elm.dispatchEvent
|
||||||
|
? elm.dispatchEvent(evt)
|
||||||
|
: elm.fireEvent('on' + name, evt);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue