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>
|
10 | import DomHandler from '../utils/DomHandler';
|
11 | import TieredMenuSub from './TieredMenuSub';
|
12 |
|
13 | export 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 |