UNPKG

5.75 kBPlain TextView Raw
1<template>
2 <transition name="p-input-overlay" @enter="onEnter" @leave="onLeave">
3 <div ref="container" :class="containerClass" v-if="popup ? visible : true">
4 <TieredMenuSub :model="model" :root="true" :popup="popup" @leaf-click="onLeafClick"/>
5 </div>
6 </transition>
7</template>
8
9<script>
10import DomHandler from '../utils/DomHandler';
11import TieredMenuSub from './TieredMenuSub';
12
13export default {
14 props: {
15 popup: {
16 type: Boolean,
17 default: false
18 },
19 model: {
20 type: Array,
21 default: null
22 },
23 appendTo: {
24 type: String,
25 default: null
26 },
27 autoZIndex: {
28 type: Boolean,
29 default: true
30 },
31 baseZIndex: {
32 type: Number,
33 default: 0
34 }
35 },
36 target: null,
37 outsideClickListener: null,
38 resizeListener: null,
39 data() {
40 return {
41 visible: false
42 };
43 },
44 beforeDestroy() {
45 this.restoreAppend();
46 this.unbindResizeListener();
47 this.unbindOutsideClickListener();
48 this.target = null;
49 },
50 methods: {
51 itemClick(event) {
52 const item = event.item;
53 if (item.command) {
54 item.command(event);
55 event.originalEvent.preventDefault();
56 }
57 this.hide();
58 },
59 toggle(event) {
60 if (this.visible)
61 this.hide();
62 else
63 this.show(event);
64 },
65 show(event) {
66 this.visible = true;
67 this.target = event.currentTarget;
68 },
69 hide() {
70 this.visible = false;
71 },
72 onEnter() {
73 this.appendContainer();
74 this.alignOverlay();
75 this.bindOutsideClickListener();
76 this.bindResizeListener();
77
78 if (this.autoZIndex) {
79 this.$refs.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
80 }
81 },
82 onLeave() {
83 this.unbindOutsideClickListener();
84 this.unbindResizeListener();
85 },
86 alignOverlay() {
87 DomHandler.absolutePosition(this.$refs.container, this.target);
88 },
89 bindOutsideClickListener() {
90 if (!this.outsideClickListener) {
91 this.outsideClickListener = (event) => {
92 if (this.visible && this.$refs.container && !this.$refs.container.contains(event.target) && !this.isTargetClicked(event)) {
93 this.hide();
94 }
95 };
96 document.addEventListener('click', this.outsideClickListener);
97 }
98 },
99 unbindOutsideClickListener() {
100 if (this.outsideClickListener) {
101 document.removeEventListener('click', this.outsideClickListener);
102 this.outsideClickListener = null;
103 }
104 },
105 bindResizeListener() {
106 if (!this.resizeListener) {
107 this.resizeListener = () => {
108 if (this.visible) {
109 this.hide();
110 }
111 };
112 window.addEventListener('resize', this.resizeListener);
113 }
114 },
115 unbindResizeListener() {
116 if (this.resizeListener) {
117 window.removeEventListener('resize', this.resizeListener);
118 this.resizeListener = null;
119 }
120 },
121 isTargetClicked() {
122 return this.target && (this.target === event.target || this.target.contains(event.target));
123 },
124 appendContainer() {
125 if (this.appendTo) {
126 if (this.appendTo === 'body')
127 document.body.appendChild(this.$refs.container);
128 else
129 document.getElementById(this.appendTo).appendChild(this.$refs.container);
130 }
131 },
132 restoreAppend() {
133 if (this.$refs.container && this.appendTo) {
134 if (this.appendTo === 'body')
135 document.body.removeChild(this.$refs.container);
136 else
137 document.getElementById(this.appendTo).removeChild(this.$refs.container);
138 }
139 },
140 onLeafClick() {
141 if (this.popup) {
142 this.hide();
143 }
144 }
145 },
146 computed: {
147 containerClass() {
148 return ['p-tieredmenu p-component', {
149 'p-tieredmenu-dynamic p-menu-overlay': this.popup
150 }];
151 }
152 },
153 components: {
154 'TieredMenuSub': TieredMenuSub
155 }
156}
157</script>
158
159<style>
160.p-tieredmenu {
161 width: 12.5em;
162 padding: .25em;
163}
164
165.p-tieredmenu.p-tieredmenu-dynamic {
166 position: absolute;
167}
168
169.p-tieredmenu .p-menu-separator {
170 border-width: 1px 0 0 0;
171}
172
173.p-tieredmenu ul {
174 list-style: none;
175 margin: 0;
176 padding: 0;
177}
178
179.p-tieredmenu .p-submenu-list {
180 display: none;
181 position: absolute;
182 width: 12.5em;
183 padding: .25em;
184 z-index: 1;
185}
186
187.p-tieredmenu .p-menuitem-link {
188 padding: .25em;
189 display: block;
190 position: relative;
191 text-decoration: none;
192}
193
194.p-tieredmenu .p-menuitem-icon {
195 margin-right: .25em;
196 vertical-align: middle;
197}
198
199.p-tieredmenu .p-menuitem-text {
200 vertical-align: middle;
201}
202
203.p-tieredmenu .p-menuitem {
204 position: relative;
205 margin: .125em 0;
206}
207
208.p-tieredmenu .p-menuitem-link .p-submenu-icon {
209 position: absolute;
210 margin-top: -.5em;
211 right: 0;
212 top: 50%;
213}
214
215.p-tieredmenu .p-menuitem-active > .p-submenu-list {
216 display: block;
217 left: 100%;
218 top: 0;
219}
220</style>
\No newline at end of file