1 | import Vue from 'vue';
|
2 | import {
|
3 | PopupManager
|
4 | } from 'element-ui/src/utils/popup';
|
5 |
|
6 | const PopperJS = Vue.prototype.$isServer ? function() {} : require('./popper');
|
7 | const stop = e => e.stopPropagation();
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | export default {
|
18 | props: {
|
19 | transformOrigin: {
|
20 | type: [Boolean, String],
|
21 | default: true
|
22 | },
|
23 | placement: {
|
24 | type: String,
|
25 | default: 'bottom'
|
26 | },
|
27 | boundariesPadding: {
|
28 | type: Number,
|
29 | default: 5
|
30 | },
|
31 | reference: {},
|
32 | popper: {},
|
33 | offset: {
|
34 | default: 0
|
35 | },
|
36 | value: Boolean,
|
37 | visibleArrow: Boolean,
|
38 | arrowOffset: {
|
39 | type: Number,
|
40 | default: 35
|
41 | },
|
42 | appendToBody: {
|
43 | type: Boolean,
|
44 | default: true
|
45 | },
|
46 | popperOptions: {
|
47 | type: Object,
|
48 | default() {
|
49 | return {
|
50 | gpuAcceleration: false
|
51 | };
|
52 | }
|
53 | }
|
54 | },
|
55 |
|
56 | data() {
|
57 | return {
|
58 | showPopper: false,
|
59 | currentPlacement: ''
|
60 | };
|
61 | },
|
62 |
|
63 | watch: {
|
64 | value: {
|
65 | immediate: true,
|
66 | handler(val) {
|
67 | this.showPopper = val;
|
68 | this.$emit('input', val);
|
69 | }
|
70 | },
|
71 |
|
72 | showPopper(val) {
|
73 | if (this.disabled) return;
|
74 | val ? this.updatePopper() : this.destroyPopper();
|
75 | this.$emit('input', val);
|
76 | }
|
77 | },
|
78 |
|
79 | methods: {
|
80 | createPopper() {
|
81 | if (this.$isServer) return;
|
82 | this.currentPlacement = this.currentPlacement || this.placement;
|
83 | if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.currentPlacement)) {
|
84 | return;
|
85 | }
|
86 |
|
87 | const options = this.popperOptions;
|
88 | const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper;
|
89 | let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference;
|
90 |
|
91 | if (!reference &&
|
92 | this.$slots.reference &&
|
93 | this.$slots.reference[0]) {
|
94 | reference = this.referenceElm = this.$slots.reference[0].elm;
|
95 | }
|
96 |
|
97 | if (!popper || !reference) return;
|
98 | if (this.visibleArrow) this.appendArrow(popper);
|
99 | if (this.appendToBody) document.body.appendChild(this.popperElm);
|
100 | if (this.popperJS && this.popperJS.destroy) {
|
101 | this.popperJS.destroy();
|
102 | }
|
103 |
|
104 | options.placement = this.currentPlacement;
|
105 | options.offset = this.offset;
|
106 | options.arrowOffset = this.arrowOffset;
|
107 | this.popperJS = new PopperJS(reference, popper, options);
|
108 | this.popperJS.onCreate(_ => {
|
109 | this.$emit('created', this);
|
110 | this.resetTransformOrigin();
|
111 | this.$nextTick(this.updatePopper);
|
112 | });
|
113 | if (typeof options.onUpdate === 'function') {
|
114 | this.popperJS.onUpdate(options.onUpdate);
|
115 | }
|
116 | this.popperJS._popper.style.zIndex = PopupManager.nextZIndex();
|
117 | this.popperElm.addEventListener('click', stop);
|
118 | },
|
119 |
|
120 | updatePopper() {
|
121 | const popperJS = this.popperJS;
|
122 | if (popperJS) {
|
123 | popperJS.update();
|
124 | if (popperJS._popper) {
|
125 | popperJS._popper.style.zIndex = PopupManager.nextZIndex();
|
126 | }
|
127 | } else {
|
128 | this.createPopper();
|
129 | }
|
130 | },
|
131 |
|
132 | doDestroy(forceDestroy) {
|
133 |
|
134 | if (!this.popperJS || (this.showPopper && !forceDestroy)) return;
|
135 | this.popperJS.destroy();
|
136 | this.popperJS = null;
|
137 | },
|
138 |
|
139 | destroyPopper() {
|
140 | if (this.popperJS) {
|
141 | this.resetTransformOrigin();
|
142 | }
|
143 | },
|
144 |
|
145 | resetTransformOrigin() {
|
146 | if (!this.transformOrigin) return;
|
147 | let placementMap = {
|
148 | top: 'bottom',
|
149 | bottom: 'top',
|
150 | left: 'right',
|
151 | right: 'left'
|
152 | };
|
153 | let placement = this.popperJS._popper.getAttribute('x-placement').split('-')[0];
|
154 | let origin = placementMap[placement];
|
155 | this.popperJS._popper.style.transformOrigin = typeof this.transformOrigin === 'string'
|
156 | ? this.transformOrigin
|
157 | : ['top', 'bottom'].indexOf(placement) > -1 ? `center ${ origin }` : `${ origin } center`;
|
158 | },
|
159 |
|
160 | appendArrow(element) {
|
161 | let hash;
|
162 | if (this.appended) {
|
163 | return;
|
164 | }
|
165 |
|
166 | this.appended = true;
|
167 |
|
168 | for (let item in element.attributes) {
|
169 | if (/^_v-/.test(element.attributes[item].name)) {
|
170 | hash = element.attributes[item].name;
|
171 | break;
|
172 | }
|
173 | }
|
174 |
|
175 | const arrow = document.createElement('div');
|
176 |
|
177 | if (hash) {
|
178 | arrow.setAttribute(hash, '');
|
179 | }
|
180 | arrow.setAttribute('x-arrow', '');
|
181 | arrow.className = 'popper__arrow';
|
182 | element.appendChild(arrow);
|
183 | }
|
184 | },
|
185 |
|
186 | beforeDestroy() {
|
187 | this.doDestroy(true);
|
188 | if (this.popperElm && this.popperElm.parentNode === document.body) {
|
189 | this.popperElm.removeEventListener('click', stop);
|
190 | document.body.removeChild(this.popperElm);
|
191 | }
|
192 | },
|
193 |
|
194 |
|
195 | deactivated() {
|
196 | this.$options.beforeDestroy[0].call(this);
|
197 | }
|
198 | };
|