1 | import { Component, ViewContainerRef, ChangeDetectorRef, Input, ContentChildren, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, ViewChild, Output, NgModule } from '@angular/core';
|
2 | import { CommonModule } from '@angular/common';
|
3 | import { TooltipModule } from 'primeng/tooltip';
|
4 | import { RippleModule } from 'primeng/ripple';
|
5 | import { PrimeTemplate, SharedModule } from 'primeng/api';
|
6 | import { DomHandler } from 'primeng/dom';
|
7 |
|
8 | let idx = 0;
|
9 | class TabPanel {
|
10 | constructor(viewContainer, cd) {
|
11 | this.viewContainer = viewContainer;
|
12 | this.cd = cd;
|
13 | this.cache = true;
|
14 | this.tooltipPosition = 'top';
|
15 | this.tooltipPositionStyle = 'absolute';
|
16 | this.id = `p-tabpanel-${idx++}`;
|
17 | }
|
18 | ngAfterContentInit() {
|
19 | this.templates.forEach((item) => {
|
20 | switch (item.getType()) {
|
21 | case 'header':
|
22 | this.headerTemplate = item.template;
|
23 | break;
|
24 | case 'content':
|
25 | this.contentTemplate = item.template;
|
26 | break;
|
27 | default:
|
28 | this.contentTemplate = item.template;
|
29 | break;
|
30 | }
|
31 | });
|
32 | }
|
33 | get selected() {
|
34 | return this._selected;
|
35 | }
|
36 | set selected(val) {
|
37 | this._selected = val;
|
38 | if (!this.loaded) {
|
39 | this.cd.detectChanges();
|
40 | }
|
41 | this.loaded = true;
|
42 | }
|
43 | ngOnDestroy() {
|
44 | this.view = null;
|
45 | }
|
46 | }
|
47 | TabPanel.decorators = [
|
48 | { type: Component, args: [{
|
49 | selector: 'p-tabPanel',
|
50 | template: `
|
51 | <div [attr.id]="id" class="p-tabview-panel" [hidden]="!selected"
|
52 | role="tabpanel" [attr.aria-hidden]="!selected" [attr.aria-labelledby]="id + '-label'" *ngIf="!closed">
|
53 | <ng-content></ng-content>
|
54 | <ng-container *ngIf="contentTemplate && (cache ? loaded : selected)">
|
55 | <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
|
56 | </ng-container>
|
57 | </div>
|
58 | `
|
59 | },] }
|
60 | ];
|
61 | TabPanel.ctorParameters = () => [
|
62 | { type: ViewContainerRef },
|
63 | { type: ChangeDetectorRef }
|
64 | ];
|
65 | TabPanel.propDecorators = {
|
66 | header: [{ type: Input }],
|
67 | disabled: [{ type: Input }],
|
68 | closable: [{ type: Input }],
|
69 | headerStyle: [{ type: Input }],
|
70 | headerStyleClass: [{ type: Input }],
|
71 | leftIcon: [{ type: Input }],
|
72 | rightIcon: [{ type: Input }],
|
73 | cache: [{ type: Input }],
|
74 | tooltip: [{ type: Input }],
|
75 | tooltipPosition: [{ type: Input }],
|
76 | tooltipPositionStyle: [{ type: Input }],
|
77 | tooltipStyleClass: [{ type: Input }],
|
78 | templates: [{ type: ContentChildren, args: [PrimeTemplate,] }],
|
79 | selected: [{ type: Input }]
|
80 | };
|
81 | class TabView {
|
82 | constructor(el, cd) {
|
83 | this.el = el;
|
84 | this.cd = cd;
|
85 | this.orientation = 'top';
|
86 | this.onChange = new EventEmitter();
|
87 | this.onClose = new EventEmitter();
|
88 | this.activeIndexChange = new EventEmitter();
|
89 | }
|
90 | ngAfterContentInit() {
|
91 | this.initTabs();
|
92 | this.tabPanels.changes.subscribe(_ => {
|
93 | this.initTabs();
|
94 | });
|
95 | }
|
96 | ngAfterViewChecked() {
|
97 | if (this.tabChanged) {
|
98 | this.updateInkBar();
|
99 | this.tabChanged = false;
|
100 | }
|
101 | }
|
102 | initTabs() {
|
103 | this.tabs = this.tabPanels.toArray();
|
104 | let selectedTab = this.findSelectedTab();
|
105 | if (!selectedTab && this.tabs.length) {
|
106 | if (this.activeIndex != null && this.tabs.length > this.activeIndex)
|
107 | this.tabs[this.activeIndex].selected = true;
|
108 | else
|
109 | this.tabs[0].selected = true;
|
110 | this.tabChanged = true;
|
111 | }
|
112 | this.cd.markForCheck();
|
113 | }
|
114 | open(event, tab) {
|
115 | if (tab.disabled) {
|
116 | if (event) {
|
117 | event.preventDefault();
|
118 | }
|
119 | return;
|
120 | }
|
121 | if (!tab.selected) {
|
122 | let selectedTab = this.findSelectedTab();
|
123 | if (selectedTab) {
|
124 | selectedTab.selected = false;
|
125 | }
|
126 | this.tabChanged = true;
|
127 | tab.selected = true;
|
128 | let selectedTabIndex = this.findTabIndex(tab);
|
129 | this.preventActiveIndexPropagation = true;
|
130 | this.activeIndexChange.emit(selectedTabIndex);
|
131 | this.onChange.emit({ originalEvent: event, index: selectedTabIndex });
|
132 | }
|
133 | if (event) {
|
134 | event.preventDefault();
|
135 | }
|
136 | }
|
137 | close(event, tab) {
|
138 | if (this.controlClose) {
|
139 | this.onClose.emit({
|
140 | originalEvent: event,
|
141 | index: this.findTabIndex(tab),
|
142 | close: () => {
|
143 | this.closeTab(tab);
|
144 | }
|
145 | });
|
146 | }
|
147 | else {
|
148 | this.closeTab(tab);
|
149 | this.onClose.emit({
|
150 | originalEvent: event,
|
151 | index: this.findTabIndex(tab)
|
152 | });
|
153 | }
|
154 | event.stopPropagation();
|
155 | }
|
156 | closeTab(tab) {
|
157 | if (tab.disabled) {
|
158 | return;
|
159 | }
|
160 | if (tab.selected) {
|
161 | this.tabChanged = true;
|
162 | tab.selected = false;
|
163 | for (let i = 0; i < this.tabs.length; i++) {
|
164 | let tabPanel = this.tabs[i];
|
165 | if (!tabPanel.closed && !tab.disabled) {
|
166 | tabPanel.selected = true;
|
167 | break;
|
168 | }
|
169 | }
|
170 | }
|
171 | tab.closed = true;
|
172 | }
|
173 | findSelectedTab() {
|
174 | for (let i = 0; i < this.tabs.length; i++) {
|
175 | if (this.tabs[i].selected) {
|
176 | return this.tabs[i];
|
177 | }
|
178 | }
|
179 | return null;
|
180 | }
|
181 | findTabIndex(tab) {
|
182 | let index = -1;
|
183 | for (let i = 0; i < this.tabs.length; i++) {
|
184 | if (this.tabs[i] == tab) {
|
185 | index = i;
|
186 | break;
|
187 | }
|
188 | }
|
189 | return index;
|
190 | }
|
191 | getBlockableElement() {
|
192 | return this.el.nativeElement.children[0];
|
193 | }
|
194 | get activeIndex() {
|
195 | return this._activeIndex;
|
196 | }
|
197 | set activeIndex(val) {
|
198 | this._activeIndex = val;
|
199 | if (this.preventActiveIndexPropagation) {
|
200 | this.preventActiveIndexPropagation = false;
|
201 | return;
|
202 | }
|
203 | if (this.tabs && this.tabs.length && this._activeIndex != null && this.tabs.length > this._activeIndex) {
|
204 | this.findSelectedTab().selected = false;
|
205 | this.tabs[this._activeIndex].selected = true;
|
206 | }
|
207 | }
|
208 | updateInkBar() {
|
209 | let tabHeader = DomHandler.findSingle(this.navbar.nativeElement, 'li.p-highlight');
|
210 | this.inkbar.nativeElement.style.width = DomHandler.getWidth(tabHeader) + 'px';
|
211 | this.inkbar.nativeElement.style.left = DomHandler.getOffset(tabHeader).left - DomHandler.getOffset(this.navbar.nativeElement).left + 'px';
|
212 | }
|
213 | }
|
214 | TabView.decorators = [
|
215 | { type: Component, args: [{
|
216 | selector: 'p-tabView',
|
217 | template: `
|
218 | <div [ngClass]="'p-tabview p-component'" [ngStyle]="style" [class]="styleClass">
|
219 | <ul #navbar class="p-tabview-nav" role="tablist">
|
220 | <ng-template ngFor let-tab [ngForOf]="tabs">
|
221 | <li role="presentation" [ngClass]="{'p-highlight': tab.selected, 'p-disabled': tab.disabled}" [ngStyle]="tab.headerStyle" [class]="tab.headerStyleClass" *ngIf="!tab.closed">
|
222 | <a role="tab" class="p-tabview-nav-link" [attr.id]="tab.id + '-label'" [attr.aria-selected]="tab.selected" [attr.aria-controls]="tab.id" [pTooltip]="tab.tooltip" [tooltipPosition]="tab.tooltipPosition"
|
223 | [attr.aria-selected]="tab.selected" [positionStyle]="tab.tooltipPositionStyle" [tooltipStyleClass]="tab.tooltipStyleClass"
|
224 | (click)="open($event,tab)" (keydown.enter)="open($event,tab)" pRipple [attr.tabindex]="tab.disabled ? null : '0'">
|
225 | <ng-container *ngIf="!tab.headerTemplate">
|
226 | <span class="p-tabview-left-icon" [ngClass]="tab.leftIcon" *ngIf="tab.leftIcon"></span>
|
227 | <span class="p-tabview-title">{{tab.header}}</span>
|
228 | <span class="p-tabview-right-icon" [ngClass]="tab.rightIcon" *ngIf="tab.rightIcon"></span>
|
229 | </ng-container>
|
230 | <ng-container *ngTemplateOutlet="tab.headerTemplate"></ng-container>
|
231 | <span *ngIf="tab.closable" class="p-tabview-close pi pi-times" (click)="close($event,tab)"></span>
|
232 | </a>
|
233 | </li>
|
234 | </ng-template>
|
235 | <li #inkbar class="p-tabview-ink-bar"></li>
|
236 | </ul>
|
237 | <div class="p-tabview-panels">
|
238 | <ng-content></ng-content>
|
239 | </div>
|
240 | </div>
|
241 | `,
|
242 | changeDetection: ChangeDetectionStrategy.OnPush,
|
243 | encapsulation: ViewEncapsulation.None,
|
244 | styles: [".p-tabview-nav{-ms-flex-wrap:wrap;display:-ms-flexbox;display:flex;flex-wrap:wrap;list-style-type:none;margin:0;padding:0}.p-tabview-nav-link{-moz-user-select:none;-ms-flex-align:center;-ms-user-select:none;-webkit-user-select:none;align-items:center;cursor:pointer;display:-ms-flexbox;display:flex;overflow:hidden;position:relative;text-decoration:none;user-select:none}.p-tabview-ink-bar{display:none;z-index:1}.p-tabview-nav-link:focus{z-index:1}.p-tabview-title{line-height:1}.p-tabview-close{z-index:1}"]
|
245 | },] }
|
246 | ];
|
247 | TabView.ctorParameters = () => [
|
248 | { type: ElementRef },
|
249 | { type: ChangeDetectorRef }
|
250 | ];
|
251 | TabView.propDecorators = {
|
252 | orientation: [{ type: Input }],
|
253 | style: [{ type: Input }],
|
254 | styleClass: [{ type: Input }],
|
255 | controlClose: [{ type: Input }],
|
256 | navbar: [{ type: ViewChild, args: ['navbar',] }],
|
257 | inkbar: [{ type: ViewChild, args: ['inkbar',] }],
|
258 | tabPanels: [{ type: ContentChildren, args: [TabPanel,] }],
|
259 | onChange: [{ type: Output }],
|
260 | onClose: [{ type: Output }],
|
261 | activeIndexChange: [{ type: Output }],
|
262 | activeIndex: [{ type: Input }]
|
263 | };
|
264 | class TabViewModule {
|
265 | }
|
266 | TabViewModule.decorators = [
|
267 | { type: NgModule, args: [{
|
268 | imports: [CommonModule, SharedModule, TooltipModule, RippleModule],
|
269 | exports: [TabView, TabPanel, SharedModule],
|
270 | declarations: [TabView, TabPanel]
|
271 | },] }
|
272 | ];
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 | export { TabPanel, TabView, TabViewModule };
|
279 |
|