UNPKG

13.7 kBJavaScriptView Raw
1import { Component, ViewEncapsulation, Inject, forwardRef, Input, EventEmitter, ChangeDetectionStrategy, ElementRef, Renderer2, NgZone, Output, ViewChild, NgModule } from '@angular/core';
2import { CommonModule } from '@angular/common';
3import { DomHandler } from 'primeng/dom';
4import { RippleModule } from 'primeng/ripple';
5import { RouterModule } from '@angular/router';
6
7class ContextMenuSub {
8 constructor(contextMenu) {
9 this.contextMenu = contextMenu;
10 }
11 get parentActive() {
12 return this._parentActive;
13 }
14 set parentActive(value) {
15 this._parentActive = value;
16 if (!value) {
17 this.activeItem = null;
18 }
19 }
20 onItemMouseEnter(event, item, menuitem) {
21 if (this.hideTimeout) {
22 clearTimeout(this.hideTimeout);
23 this.hideTimeout = null;
24 }
25 if (menuitem.disabled) {
26 return;
27 }
28 this.activeItem = item;
29 let nextElement = item.children[0].nextElementSibling;
30 if (nextElement) {
31 let sublist = nextElement.children[0];
32 sublist.style.zIndex = ++DomHandler.zindex;
33 this.position(sublist, item);
34 }
35 }
36 itemClick(event, item) {
37 if (item.disabled) {
38 event.preventDefault();
39 return;
40 }
41 if (item.command) {
42 item.command({
43 originalEvent: event,
44 item: item
45 });
46 event.preventDefault();
47 }
48 if (item.items)
49 event.preventDefault();
50 else
51 this.contextMenu.hide();
52 }
53 listClick(event) {
54 this.activeItem = null;
55 }
56 position(sublist, item) {
57 this.containerOffset = DomHandler.getOffset(item.parentElement);
58 let viewport = DomHandler.getViewport();
59 let sublistWidth = sublist.offsetParent ? sublist.offsetWidth : DomHandler.getHiddenElementOuterWidth(sublist);
60 let itemOuterWidth = DomHandler.getOuterWidth(item.children[0]);
61 let itemOuterHeight = DomHandler.getOuterHeight(item.children[0]);
62 let sublistHeight = sublist.offsetHeight ? sublist.offsetHeight : DomHandler.getHiddenElementOuterHeight(sublist);
63 if ((parseInt(this.containerOffset.top) + itemOuterHeight + sublistHeight) > (viewport.height - DomHandler.calculateScrollbarHeight())) {
64 sublist.style.removeProperty('top');
65 sublist.style.bottom = '0px';
66 }
67 else {
68 sublist.style.removeProperty('bottom');
69 sublist.style.top = '0px';
70 }
71 if ((parseInt(this.containerOffset.left) + itemOuterWidth + sublistWidth) > (viewport.width - DomHandler.calculateScrollbarWidth())) {
72 sublist.style.left = -sublistWidth + 'px';
73 }
74 else {
75 sublist.style.left = itemOuterWidth + 'px';
76 }
77 }
78}
79ContextMenuSub.decorators = [
80 { type: Component, args: [{
81 selector: 'p-contextMenuSub',
82 template: `
83 <ul [ngClass]="{'p-submenu-list':!root}">
84 <ng-template ngFor let-child [ngForOf]="(root ? item : item.items)">
85 <li *ngIf="child.separator" class="p-menu-separator" [ngClass]="{'p-hidden': child.visible === false}" role="separator">
86 <li *ngIf="!child.separator" #item [ngClass]="{'p-menuitem':true,'p-menuitem-active':item==activeItem,'p-hidden': child.visible === false}"
87 (mouseenter)="onItemMouseEnter($event,item,child)" role="none">
88 <a *ngIf="!child.routerLink" [attr.href]="child.url ? child.url : null" [attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id" [attr.tabindex]="child.disabled ? null : '0'" (click)="itemClick($event, child)"
89 [ngClass]="{'p-menuitem-link':true,'p-disabled':child.disabled}" [ngStyle]="child.style" [class]="child.styleClass" pRipple
90 [attr.aria-haspopup]="item.items != null" [attr.aria-expanded]="item === activeItem">
91 <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon"></span>
92 <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlLabel">{{child.label}}</span>
93 <ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
94 <span class="p-submenu-icon pi pi-angle-right" *ngIf="child.items"></span>
95 </a>
96 <a *ngIf="child.routerLink" [routerLink]="child.routerLink" [queryParams]="child.queryParams" [routerLinkActive]="'p-menuitem-link-active'" role="menuitem"
97 [routerLinkActiveOptions]="child.routerLinkActiveOptions||{exact:false}" [attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id" [attr.tabindex]="child.disabled ? null : '0'"
98 (click)="itemClick($event, child)" [ngClass]="{'p-menuitem-link':true,'p-disabled':child.disabled}"
99 [ngStyle]="child.style" [class]="child.styleClass" pRipple
100 [fragment]="child.fragment" [queryParamsHandling]="child.queryParamsHandling" [preserveFragment]="child.preserveFragment" [skipLocationChange]="child.skipLocationChange" [replaceUrl]="child.replaceUrl" [state]="child.state">
101 <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon"></span>
102 <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlRouteLabel">{{child.label}}</span>
103 <ng-template #htmlRouteLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
104 <span class="p-submenu-icon pi pi-angle-right" *ngIf="child.items"></span>
105 </a>
106 <p-contextMenuSub [parentActive]="item==activeItem" [item]="child" *ngIf="child.items"></p-contextMenuSub>
107 </li>
108 </ng-template>
109 </ul>
110 `,
111 encapsulation: ViewEncapsulation.None
112 },] }
113];
114ContextMenuSub.ctorParameters = () => [
115 { type: undefined, decorators: [{ type: Inject, args: [forwardRef(() => ContextMenu),] }] }
116];
117ContextMenuSub.propDecorators = {
118 item: [{ type: Input }],
119 root: [{ type: Input }],
120 parentActive: [{ type: Input }]
121};
122class ContextMenu {
123 constructor(el, renderer, zone) {
124 this.el = el;
125 this.renderer = renderer;
126 this.zone = zone;
127 this.autoZIndex = true;
128 this.baseZIndex = 0;
129 this.triggerEvent = 'contextmenu';
130 this.onShow = new EventEmitter();
131 this.onHide = new EventEmitter();
132 }
133 ngAfterViewInit() {
134 if (this.global) {
135 const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
136 this.triggerEventListener = this.renderer.listen(documentTarget, this.triggerEvent, (event) => {
137 this.show(event);
138 event.preventDefault();
139 });
140 }
141 else if (this.target) {
142 this.triggerEventListener = this.renderer.listen(this.target, this.triggerEvent, (event) => {
143 this.show(event);
144 event.preventDefault();
145 event.stopPropagation();
146 });
147 }
148 if (this.appendTo) {
149 if (this.appendTo === 'body')
150 document.body.appendChild(this.containerViewChild.nativeElement);
151 else
152 DomHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo);
153 }
154 }
155 show(event) {
156 this.position(event);
157 this.moveOnTop();
158 this.containerViewChild.nativeElement.style.display = 'block';
159 this.parentActive = true;
160 DomHandler.fadeIn(this.containerViewChild.nativeElement, 250);
161 this.bindGlobalListeners();
162 if (event) {
163 event.preventDefault();
164 }
165 this.onShow.emit();
166 }
167 hide() {
168 this.containerViewChild.nativeElement.style.display = 'none';
169 this.parentActive = false;
170 this.unbindGlobalListeners();
171 this.onHide.emit();
172 }
173 moveOnTop() {
174 if (this.autoZIndex) {
175 this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
176 }
177 }
178 toggle(event) {
179 if (this.containerViewChild.nativeElement.offsetParent)
180 this.hide();
181 else
182 this.show(event);
183 }
184 position(event) {
185 if (event) {
186 let left = event.pageX + 1;
187 let top = event.pageY + 1;
188 let width = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.containerViewChild.nativeElement);
189 let height = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetHeight : DomHandler.getHiddenElementOuterHeight(this.containerViewChild.nativeElement);
190 let viewport = DomHandler.getViewport();
191 //flip
192 if (left + width - document.body.scrollLeft > viewport.width) {
193 left -= width;
194 }
195 //flip
196 if (top + height - document.body.scrollTop > viewport.height) {
197 top -= height;
198 }
199 //fit
200 if (left < document.body.scrollLeft) {
201 left = document.body.scrollLeft;
202 }
203 //fit
204 if (top < document.body.scrollTop) {
205 top = document.body.scrollTop;
206 }
207 this.containerViewChild.nativeElement.style.left = left + 'px';
208 this.containerViewChild.nativeElement.style.top = top + 'px';
209 }
210 }
211 bindGlobalListeners() {
212 if (!this.documentClickListener) {
213 const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
214 this.documentClickListener = this.renderer.listen(documentTarget, 'click', (event) => {
215 if (this.containerViewChild.nativeElement.offsetParent && this.isOutsideClicked(event) && event.button !== 2) {
216 this.hide();
217 }
218 });
219 }
220 this.zone.runOutsideAngular(() => {
221 if (!this.windowResizeListener) {
222 this.windowResizeListener = this.onWindowResize.bind(this);
223 window.addEventListener('resize', this.windowResizeListener);
224 }
225 });
226 }
227 unbindGlobalListeners() {
228 if (this.documentClickListener) {
229 this.documentClickListener();
230 this.documentClickListener = null;
231 }
232 if (this.windowResizeListener) {
233 window.removeEventListener('resize', this.windowResizeListener);
234 this.windowResizeListener = null;
235 }
236 }
237 onWindowResize(event) {
238 if (this.containerViewChild.nativeElement.offsetParent) {
239 this.hide();
240 }
241 }
242 isOutsideClicked(event) {
243 return !(this.containerViewChild.nativeElement.isSameNode(event.target) || this.containerViewChild.nativeElement.contains(event.target));
244 }
245 ngOnDestroy() {
246 this.unbindGlobalListeners();
247 if (this.triggerEventListener) {
248 this.triggerEventListener();
249 }
250 if (this.appendTo) {
251 this.el.nativeElement.appendChild(this.containerViewChild.nativeElement);
252 }
253 }
254}
255ContextMenu.decorators = [
256 { type: Component, args: [{
257 selector: 'p-contextMenu',
258 template: `
259 <div #container [ngClass]="'p-contextmenu p-component'"
260 [class]="styleClass" [ngStyle]="style">
261 <p-contextMenuSub [item]="model" [parentActive]="parentActive" root="root"></p-contextMenuSub>
262 </div>
263 `,
264 changeDetection: ChangeDetectionStrategy.OnPush,
265 encapsulation: ViewEncapsulation.None,
266 styles: [".p-contextmenu{display:none;position:absolute}.p-contextmenu ul{list-style:none;margin:0;padding:0}.p-contextmenu .p-submenu-list{display:none;min-width:100%;position:absolute;z-index:1}.p-contextmenu .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-contextmenu .p-menuitem-text{line-height:1}.p-contextmenu .p-menuitem{position:relative}.p-contextmenu .p-menuitem-link .p-submenu-icon{margin-left:auto}.p-contextmenu .p-menuitem-active>p-contextmenusub>.p-submenu-list{display:block!important}"]
267 },] }
268];
269ContextMenu.ctorParameters = () => [
270 { type: ElementRef },
271 { type: Renderer2 },
272 { type: NgZone }
273];
274ContextMenu.propDecorators = {
275 model: [{ type: Input }],
276 global: [{ type: Input }],
277 target: [{ type: Input }],
278 style: [{ type: Input }],
279 styleClass: [{ type: Input }],
280 appendTo: [{ type: Input }],
281 autoZIndex: [{ type: Input }],
282 baseZIndex: [{ type: Input }],
283 triggerEvent: [{ type: Input }],
284 onShow: [{ type: Output }],
285 onHide: [{ type: Output }],
286 containerViewChild: [{ type: ViewChild, args: ['container',] }]
287};
288class ContextMenuModule {
289}
290ContextMenuModule.decorators = [
291 { type: NgModule, args: [{
292 imports: [CommonModule, RouterModule, RippleModule],
293 exports: [ContextMenu, RouterModule],
294 declarations: [ContextMenu, ContextMenuSub]
295 },] }
296];
297
298/**
299 * Generated bundle index. Do not edit.
300 */
301
302export { ContextMenu, ContextMenuModule, ContextMenuSub };
303//# sourceMappingURL=primeng-contextmenu.js.map