Skip to content

Commit

Permalink
Merge d2a9987 into ab693a2
Browse files Browse the repository at this point in the history
  • Loading branch information
QingWei-Li committed Oct 20, 2016
2 parents ab693a2 + d2a9987 commit 8ed2602
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: dist
.PHONY: dist test
default: help

# build all theme
Expand Down
6 changes: 6 additions & 0 deletions packages/popover/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
const Popover = require('./src/main');
const directive = require('./src/directive').default;
const Vue = require('vue');

Vue.directive('popover', directive);

/* istanbul ignore next */
Popover.install = function(Vue) {
Vue.directive('popover', directive);
Vue.component(Popover.name, Popover);
};
Popover.directive = directive;

module.exports = Popover;
5 changes: 5 additions & 0 deletions packages/popover/src/directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
bind(el, binding, vnode) {
vnode.context.$refs[binding.arg].$refs.reference = el;
}
};
101 changes: 51 additions & 50 deletions packages/popover/src/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,8 @@

<script>
import Popper from 'element-ui/src/utils/vue-popper';
import Vue from 'vue';
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 {
name: 'el-popover',
Expand All @@ -52,55 +45,63 @@ export default {
},
mounted() {
let _timer;
const reference = this.reference || this.$refs.reference || this.$slots.reference[0].elm;
let reference = this.reference || this.$refs.reference;
const popper = this.popper || this.$refs.popper;
this.$nextTick(() => {
if (this.trigger === 'click') {
on(reference, 'click', () => { this.showPopper = !this.showPopper; });
on(document, 'click', (e) => {
if (!this.$el ||
!reference ||
this.$el.contains(e.target) ||
reference.contains(e.target) ||
!popper ||
popper.contains(e.target)) return;
this.showPopper = false;
});
} else if (this.trigger === 'hover') {
on(reference, 'mouseenter', () => {
this.showPopper = true;
clearTimeout(_timer);
});
on(reference, 'mouseleave', () => {
_timer = setTimeout(() => {
this.showPopper = false;
}, 200);
});
} else {
if ([].slice.call(reference.children).length) {
const children = reference.childNodes;
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
reference = this.$slots.reference[0].elm;
}
if (this.trigger === 'click') {
on(reference, 'click', () => { this.showPopper = !this.showPopper; });
on(document, 'click', (e) => {
if (!this.$el ||
!reference ||
this.$el.contains(e.target) ||
reference.contains(e.target) ||
!popper ||
popper.contains(e.target)) return;
this.showPopper = false;
});
} else if (this.trigger === 'hover') {
on(reference, 'mouseenter', this.handleMouseEnter);
on(popper, 'mouseenter', this.handleMouseEnter);
on(reference, 'mouseleave', this.handleMouseLeave);
on(popper, 'mouseleave', this.handleMouseLeave);
} else {
if ([].slice.call(reference.children).length) {
const children = reference.childNodes;
for (let i = 0; i < children.length; i++) {
if (children[i].nodeName === 'INPUT') {
on(children[i], 'focus', () => { this.showPopper = true; });
on(children[i], 'blur', () => { this.showPopper = false; });
break;
}
for (let i = 0; i < children.length; i++) {
if (children[i].nodeName === 'INPUT' ||
children[i].nodeName === 'TEXTAREA') {
on(children[i], 'focus', () => { this.showPopper = true; });
on(children[i], 'blur', () => { this.showPopper = false; });
break;
}
} else if (
reference.nodeName === 'INPUT' ||
reference.nodeName === 'TEXTAREA'
) {
on(reference, 'focus', () => { this.showPopper = true; });
on(reference, 'blur', () => { this.showPopper = false; });
} else {
on(reference, 'mousedown', () => { this.showPopper = true; });
on(reference, 'mouseup', () => { this.showPopper = false; });
}
} else if (
reference.nodeName === 'INPUT' ||
reference.nodeName === 'TEXTAREA'
) {
on(reference, 'focus', () => { this.showPopper = true; });
on(reference, 'blur', () => { this.showPopper = false; });
} else {
on(reference, 'mousedown', () => { this.showPopper = true; });
on(reference, 'mouseup', () => { this.showPopper = false; });
}
});
}
},
methods: {
handleMouseEnter() {
this.showPopper = true;
clearTimeout(this._timer);
},
handleMouseLeave() {
this._timer = setTimeout(() => {
this.showPopper = false;
}, 200);
}
},
destroyed() {
Expand Down
5 changes: 2 additions & 3 deletions src/utils/vue-popper.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export default {
type: Number,
default: 5
},
reference: Object,
popper: Object,
reference: {},
popper: {},
offset: {
default: 0
},
Expand Down Expand Up @@ -73,7 +73,6 @@ export default {
const reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference || this.$slots.reference[0].elm;

if (!popper || !reference) return;

if (this.visibleArrow) this.appendArrow(popper);
if (this.appendToBody) document.body.appendChild(this.popperElm);
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
Expand Down
196 changes: 196 additions & 0 deletions test/unit/specs/popover.spec.js
Original file line number Diff line number Diff line change
@@ -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();
});
});
8 changes: 3 additions & 5 deletions test/unit/specs/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ describe('Tooltip', () => {
<button>click</button>
</el-tooltip>`);

expect(vm.$el.querySelector('.el-tooltip__popper')).to.exist;
expect(vm.$el.querySelector('.el-tooltip__popper').textContent).to.equal('提示文字');
expect(vm.$el.querySelector('.el-tooltip__popper')).to.have.property('textContent', '提示文字');
});

it('hover', done => {
Expand All @@ -24,14 +23,13 @@ describe('Tooltip', () => {

expect(tooltip.popperElm).to.not.exist;
setTimeout(_ => {
expect(tooltip.popperElm).to.exist;
expect(tooltip.popperElm.style.display).to.not.equal('none');
expect(tooltip).to.have.deep.property('popperElm.style.display').not.equal('none');

// trigger mouseleave
tooltip.handleClosePopper();

setTimeout(_ => {
expect(tooltip.popperElm.style.display).to.equal('none');
expect(tooltip).to.have.deep.property('popperElm.style.display', 'none');
done();
}, 500);
}, 150);
Expand Down
Loading

0 comments on commit 8ed2602

Please sign in to comment.