UNPKG

14.7 kBJavaScriptView Raw
1import { Component, ViewEncapsulation, Inject, forwardRef, ChangeDetectorRef, Renderer2, Input, ChangeDetectionStrategy, ElementRef, NgModule } from '@angular/core';
2import { trigger, transition, style, animate } from '@angular/animations';
3import { CommonModule } from '@angular/common';
4import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom';
5import { RippleModule } from 'primeng/ripple';
6import { RouterModule } from '@angular/router';
7
8class TieredMenuSub {
9 constructor(tieredMenu, cf, renderer) {
10 this.cf = cf;
11 this.renderer = renderer;
12 this.autoZIndex = true;
13 this.baseZIndex = 0;
14 this.tieredMenu = tieredMenu;
15 }
16 get parentActive() {
17 return this._parentActive;
18 }
19 set parentActive(value) {
20 this._parentActive = value;
21 if (!value) {
22 this.activeItem = null;
23 }
24 }
25 ngAfterViewInit() {
26 if (this.root && !this.tieredMenu.popup) {
27 this.bindDocumentClickListener();
28 }
29 }
30 onItemMouseEnter(event, item, menuitem) {
31 if (this.tieredMenu.popup || (!this.root || this.activeItem)) {
32 if (menuitem.disabled) {
33 return;
34 }
35 this.activeItem = item;
36 let nextElement = item.children[0].nextElementSibling;
37 if (nextElement) {
38 let sublist = nextElement.children[0];
39 if (this.autoZIndex) {
40 sublist.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
41 }
42 sublist.style.zIndex = String(++DomHandler.zindex);
43 sublist.style.top = '0px';
44 sublist.style.left = DomHandler.getOuterWidth(item.children[0]) + 'px';
45 }
46 }
47 }
48 itemClick(event, item, menuitem) {
49 if (menuitem.disabled) {
50 event.preventDefault();
51 return true;
52 }
53 if (!menuitem.url) {
54 event.preventDefault();
55 }
56 if (menuitem.command) {
57 menuitem.command({
58 originalEvent: event,
59 item: menuitem
60 });
61 }
62 if (this.root && !this.activeItem && !this.tieredMenu.popup) {
63 this.activeItem = item;
64 let nextElement = item.children[0].nextElementSibling;
65 if (nextElement) {
66 let sublist = nextElement.children[0];
67 if (this.autoZIndex) {
68 sublist.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
69 }
70 sublist.style.zIndex = String(++DomHandler.zindex);
71 sublist.style.top = '0px';
72 sublist.style.left = DomHandler.getOuterWidth(item.children[0]) + 'px';
73 this.rootItemClick = true;
74 }
75 }
76 if (!menuitem.items && this.tieredMenu.popup) {
77 this.tieredMenu.hide();
78 }
79 }
80 listClick(event) {
81 if (!this.rootItemClick) {
82 this.activeItem = null;
83 }
84 }
85 bindDocumentClickListener() {
86 if (!this.documentClickListener) {
87 const documentTarget = this.tieredMenu && this.tieredMenu.el ? this.tieredMenu.el.nativeElement.ownerDocument : 'document';
88 this.documentClickListener = this.renderer.listen(documentTarget, 'click', () => {
89 if (!this.rootItemClick) {
90 this.parentActive = false;
91 this.activeItem = null;
92 this.cf.markForCheck();
93 }
94 this.rootItemClick = false;
95 });
96 }
97 }
98 unbindDocumentClickListener() {
99 if (this.documentClickListener) {
100 this.documentClickListener();
101 this.documentClickListener = null;
102 }
103 }
104 ngOnDestroy() {
105 if (this.root && !this.tieredMenu.popup) {
106 this.unbindDocumentClickListener();
107 }
108 }
109}
110TieredMenuSub.decorators = [
111 { type: Component, args: [{
112 selector: 'p-tieredMenuSub',
113 template: `
114 <ul [ngClass]="{'p-submenu-list': !root}" (click)="listClick($event)" role="menubar">
115 <ng-template ngFor let-child [ngForOf]="(root ? item : item.items)">
116 <li *ngIf="child.separator" class="p-menu-separator" [ngClass]="{'p-hidden': child.visible === false}" role="separator">
117 <li *ngIf="!child.separator" #listItem [ngClass]="{'p-menuitem':true,'p-menuitem-active':listItem==activeItem,'p-hidden': child.visible === false}"
118 [class]="child.styleClass" [ngStyle]="child.style" role="none"
119 (mouseenter)="onItemMouseEnter($event, listItem, child)">
120 <a *ngIf="!child.routerLink" [attr.href]="child.url" class="p-menuitem-link" [attr.target]="child.target" [attr.tabindex]="child.disabled ? null : '0'" [attr.title]="child.title" [attr.id]="child.id"
121 [ngClass]="{'p-disabled':child.disabled}" (click)="itemClick($event, listItem, child)" role="menuitem" [attr.aria-haspopup]="item.items != null" [attr.aria-expanded]="item === activeItem" pRipple>
122 <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon"></span>
123 <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlLabel">{{child.label}}</span>
124 <ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
125 <span class="p-submenu-icon pi pi-angle-right" *ngIf="child.items"></span>
126 </a>
127 <a *ngIf="child.routerLink" [routerLink]="child.routerLink" role="menuitem" [queryParams]="child.queryParams" [routerLinkActive]="'p-menuitem-link-active'" role="menuitem" [attr.tabindex]="child.disabled ? null : '0'"
128 [routerLinkActiveOptions]="child.routerLinkActiveOptions||{exact:false}"
129 class="p-menuitem-link" [attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id"
130 [ngClass]="{'p-disabled':child.disabled}" (click)="itemClick($event, listItem, child)" pRipple
131 [fragment]="child.fragment" [queryParamsHandling]="child.queryParamsHandling" [preserveFragment]="child.preserveFragment" [skipLocationChange]="child.skipLocationChange" [replaceUrl]="child.replaceUrl" [state]="child.state">
132 <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon"></span>
133 <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlRouteLabel">{{child.label}}</span>
134 <ng-template #htmlRouteLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
135 <span class="p-submenu-icon pi pi-angle-right" *ngIf="child.items"></span>
136 </a>
137 <p-tieredMenuSub [item]="child" *ngIf="child.items" [baseZIndex]="baseZIndex" [parentActive]="listItem==activeItem" [autoZIndex]="autoZIndex"></p-tieredMenuSub>
138 </li>
139 </ng-template>
140 </ul>
141 `,
142 encapsulation: ViewEncapsulation.None,
143 styles: [".p-tieredmenu-overlay{position:absolute}.p-tieredmenu ul{list-style:none;margin:0;padding:0}.p-tieredmenu .p-submenu-list{display:none;min-width:100%;position:absolute;z-index:1}.p-tieredmenu .p-menuitem-link{-ms-flex-align:center;align-items:center;cursor:pointer;display:-ms-flexbox;display:flex;overflow:hidden;position:relative;text-decoration:none}.p-tieredmenu .p-menuitem-text{line-height:1}.p-tieredmenu .p-menuitem{position:relative}.p-tieredmenu .p-menuitem-link .p-submenu-icon{margin-left:auto}.p-tieredmenu .p-menuitem-active>p-tieredmenusub>.p-submenu-list{display:block;left:100%;top:0}"]
144 },] }
145];
146TieredMenuSub.ctorParameters = () => [
147 { type: undefined, decorators: [{ type: Inject, args: [forwardRef(() => TieredMenu),] }] },
148 { type: ChangeDetectorRef },
149 { type: Renderer2 }
150];
151TieredMenuSub.propDecorators = {
152 item: [{ type: Input }],
153 root: [{ type: Input }],
154 autoZIndex: [{ type: Input }],
155 baseZIndex: [{ type: Input }],
156 parentActive: [{ type: Input }]
157};
158class TieredMenu {
159 constructor(el, renderer, cd) {
160 this.el = el;
161 this.renderer = renderer;
162 this.cd = cd;
163 this.autoZIndex = true;
164 this.baseZIndex = 0;
165 this.showTransitionOptions = '.12s cubic-bezier(0, 0, 0.2, 1)';
166 this.hideTransitionOptions = '.1s linear';
167 }
168 toggle(event) {
169 if (this.visible)
170 this.hide();
171 else
172 this.show(event);
173 this.preventDocumentDefault = true;
174 }
175 show(event) {
176 this.target = event.currentTarget;
177 this.visible = true;
178 this.parentActive = true;
179 this.preventDocumentDefault = true;
180 this.cd.markForCheck();
181 }
182 onOverlayAnimationStart(event) {
183 switch (event.toState) {
184 case 'visible':
185 if (this.popup) {
186 this.container = event.element;
187 this.moveOnTop();
188 this.appendOverlay();
189 DomHandler.absolutePosition(this.container, this.target);
190 this.bindDocumentClickListener();
191 this.bindDocumentResizeListener();
192 this.bindScrollListener();
193 }
194 break;
195 case 'void':
196 this.onOverlayHide();
197 break;
198 }
199 }
200 appendOverlay() {
201 if (this.appendTo) {
202 if (this.appendTo === 'body')
203 document.body.appendChild(this.container);
204 else
205 DomHandler.appendChild(this.container, this.appendTo);
206 }
207 }
208 restoreOverlayAppend() {
209 if (this.container && this.appendTo) {
210 this.el.nativeElement.appendChild(this.container);
211 }
212 }
213 moveOnTop() {
214 if (this.autoZIndex) {
215 this.container.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
216 }
217 }
218 hide() {
219 this.visible = false;
220 this.parentActive = false;
221 this.cd.markForCheck();
222 }
223 onWindowResize() {
224 this.hide();
225 }
226 bindDocumentClickListener() {
227 if (!this.documentClickListener) {
228 const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
229 this.documentClickListener = this.renderer.listen(documentTarget, 'click', () => {
230 if (!this.preventDocumentDefault && this.popup) {
231 this.hide();
232 }
233 this.preventDocumentDefault = false;
234 });
235 }
236 }
237 unbindDocumentClickListener() {
238 if (this.documentClickListener) {
239 this.documentClickListener();
240 this.documentClickListener = null;
241 }
242 }
243 bindDocumentResizeListener() {
244 this.documentResizeListener = this.onWindowResize.bind(this);
245 window.addEventListener('resize', this.documentResizeListener);
246 }
247 unbindDocumentResizeListener() {
248 if (this.documentResizeListener) {
249 window.removeEventListener('resize', this.documentResizeListener);
250 this.documentResizeListener = null;
251 }
252 }
253 bindScrollListener() {
254 if (!this.scrollHandler) {
255 this.scrollHandler = new ConnectedOverlayScrollHandler(this.target, () => {
256 if (this.visible) {
257 this.hide();
258 }
259 });
260 }
261 this.scrollHandler.bindScrollListener();
262 }
263 unbindScrollListener() {
264 if (this.scrollHandler) {
265 this.scrollHandler.unbindScrollListener();
266 }
267 }
268 onOverlayHide() {
269 this.unbindDocumentClickListener();
270 this.unbindDocumentResizeListener();
271 this.unbindScrollListener();
272 this.preventDocumentDefault = false;
273 this.target = null;
274 }
275 ngOnDestroy() {
276 if (this.popup) {
277 if (this.scrollHandler) {
278 this.scrollHandler.destroy();
279 this.scrollHandler = null;
280 }
281 this.restoreOverlayAppend();
282 this.onOverlayHide();
283 }
284 }
285}
286TieredMenu.decorators = [
287 { type: Component, args: [{
288 selector: 'p-tieredMenu',
289 template: `
290 <div [ngClass]="{'p-tieredmenu p-component':true, 'p-tieredmenu-overlay':popup}" [class]="styleClass" [ngStyle]="style"
291 [@overlayAnimation]="{value: 'visible', params: {showTransitionParams: showTransitionOptions, hideTransitionParams: hideTransitionOptions}}" [@.disabled]="popup !== true"
292 (@overlayAnimation.start)="onOverlayAnimationStart($event)" (click)="preventDocumentDefault=true" *ngIf="!popup || visible">
293 <p-tieredMenuSub [item]="model" root="root" [parentActive]="parentActive" [baseZIndex]="baseZIndex" [autoZIndex]="autoZIndex"></p-tieredMenuSub>
294 </div>
295 `,
296 animations: [
297 trigger('overlayAnimation', [
298 transition(':enter', [
299 style({ opacity: 0, transform: 'scaleY(0.8)' }),
300 animate('{{showTransitionParams}}')
301 ]),
302 transition(':leave', [
303 animate('{{hideTransitionParams}}', style({ opacity: 0 }))
304 ])
305 ])
306 ],
307 changeDetection: ChangeDetectionStrategy.OnPush,
308 encapsulation: ViewEncapsulation.None
309 },] }
310];
311TieredMenu.ctorParameters = () => [
312 { type: ElementRef },
313 { type: Renderer2 },
314 { type: ChangeDetectorRef }
315];
316TieredMenu.propDecorators = {
317 model: [{ type: Input }],
318 popup: [{ type: Input }],
319 style: [{ type: Input }],
320 styleClass: [{ type: Input }],
321 appendTo: [{ type: Input }],
322 autoZIndex: [{ type: Input }],
323 baseZIndex: [{ type: Input }],
324 showTransitionOptions: [{ type: Input }],
325 hideTransitionOptions: [{ type: Input }]
326};
327class TieredMenuModule {
328}
329TieredMenuModule.decorators = [
330 { type: NgModule, args: [{
331 imports: [CommonModule, RouterModule, RippleModule],
332 exports: [TieredMenu, RouterModule],
333 declarations: [TieredMenu, TieredMenuSub]
334 },] }
335];
336
337/**
338 * Generated bundle index. Do not edit.
339 */
340
341export { TieredMenu, TieredMenuModule, TieredMenuSub };
342//# sourceMappingURL=primeng-tieredmenu.js.map