1 | import { ɵɵdefineInjectable, Injectable, Component, ChangeDetectionStrategy, Input, Directive, ElementRef, Renderer2, ViewContainerRef, Output, NgModule } from '@angular/core';
|
2 | import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
|
3 | import { getBsVer, parseTriggers } from 'ngx-bootstrap/utils';
|
4 | import { PlacementForBs5, checkMargins, PositioningService } from 'ngx-bootstrap/positioning';
|
5 | import { timer } from 'rxjs';
|
6 | import { CommonModule } from '@angular/common';
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | class PopoverConfig {
|
15 | constructor() {
|
16 |
|
17 | this.adaptivePosition = true;
|
18 | |
19 |
|
20 |
|
21 | this.placement = 'top';
|
22 | |
23 |
|
24 |
|
25 |
|
26 | this.triggers = 'click';
|
27 | this.outsideClick = false;
|
28 |
|
29 | this.delay = 0;
|
30 | }
|
31 | }
|
32 | PopoverConfig.ɵprov = ɵɵdefineInjectable({ factory: function PopoverConfig_Factory() { return new PopoverConfig(); }, token: PopoverConfig, providedIn: "root" });
|
33 | PopoverConfig.decorators = [
|
34 | { type: Injectable, args: [{
|
35 | providedIn: 'root'
|
36 | },] }
|
37 | ];
|
38 |
|
39 | class PopoverContainerComponent {
|
40 | constructor(config) {
|
41 | this._placement = 'top';
|
42 | Object.assign(this, config);
|
43 | }
|
44 | set placement(value) {
|
45 | if (!this._bsVersions.isBs5) {
|
46 | this._placement = value;
|
47 | }
|
48 | else {
|
49 | this._placement = PlacementForBs5[value];
|
50 | }
|
51 | }
|
52 | ;
|
53 | get _bsVersions() {
|
54 | return getBsVer();
|
55 | }
|
56 | checkMarginNecessity() {
|
57 | return checkMargins(this._placement);
|
58 | }
|
59 | }
|
60 | PopoverContainerComponent.decorators = [
|
61 | { type: Component, args: [{
|
62 | selector: 'popover-container',
|
63 | changeDetection: ChangeDetectionStrategy.OnPush,
|
64 |
|
65 | host: {
|
66 | '[attr.id]': 'popoverId',
|
67 | '[class]': '"popover in popover-" + _placement + " " + "bs-popover-" + _placement + " " + _placement + " " + containerClass + checkMarginNecessity()',
|
68 | '[class.show]': '!_bsVersions.isBs3',
|
69 | '[class.bs3]': '_bsVersions.isBs3',
|
70 | role: 'tooltip',
|
71 | style: 'display:block;'
|
72 | },
|
73 | template: "<div class=\"popover-arrow arrow\"></div>\n<h3 class=\"popover-title popover-header\" *ngIf=\"title\">{{ title }}</h3>\n<div class=\"popover-content popover-body\">\n <ng-content></ng-content>\n</div>\n",
|
74 | styles: [`
|
75 | :host.bs3.popover-top {
|
76 | margin-bottom: 10px;
|
77 | }
|
78 | :host.bs3.popover.top>.arrow {
|
79 | margin-left: -2px;
|
80 | }
|
81 | :host.bs3.popover.top {
|
82 | margin-bottom: 10px;
|
83 | }
|
84 | :host.popover.bottom>.arrow {
|
85 | margin-left: -4px;
|
86 | }
|
87 | :host.bs3.bs-popover-left {
|
88 | margin-right: .5rem;
|
89 | }
|
90 | :host.bs3.bs-popover-right .arrow, :host.bs3.bs-popover-left .arrow{
|
91 | margin: .3rem 0;
|
92 | }
|
93 | `]
|
94 | },] }
|
95 | ];
|
96 | PopoverContainerComponent.ctorParameters = () => [
|
97 | { type: PopoverConfig }
|
98 | ];
|
99 | PopoverContainerComponent.propDecorators = {
|
100 | placement: [{ type: Input }],
|
101 | title: [{ type: Input }]
|
102 | };
|
103 |
|
104 | let id = 0;
|
105 |
|
106 |
|
107 |
|
108 | class PopoverDirective {
|
109 | constructor(_config, _elementRef, _renderer, _viewContainerRef, cis, _positionService) {
|
110 | this._elementRef = _elementRef;
|
111 | this._renderer = _renderer;
|
112 | this._positionService = _positionService;
|
113 |
|
114 | this.popoverId = id++;
|
115 |
|
116 | this.adaptivePosition = true;
|
117 | |
118 |
|
119 |
|
120 | this.placement = 'top';
|
121 | |
122 |
|
123 |
|
124 | this.outsideClick = false;
|
125 | |
126 |
|
127 |
|
128 |
|
129 | this.triggers = 'click';
|
130 | |
131 |
|
132 |
|
133 | this.containerClass = '';
|
134 | |
135 |
|
136 |
|
137 | this.delay = 0;
|
138 | this._isInited = false;
|
139 | this._popover = cis
|
140 | .createLoader(_elementRef, _viewContainerRef, _renderer)
|
141 | .provide({ provide: PopoverConfig, useValue: _config });
|
142 | Object.assign(this, _config);
|
143 | this.onShown = this._popover.onShown;
|
144 | this.onHidden = this._popover.onHidden;
|
145 |
|
146 | if (typeof window !== 'undefined') {
|
147 | _elementRef.nativeElement.addEventListener('click', function () {
|
148 | try {
|
149 | _elementRef.nativeElement.focus();
|
150 | }
|
151 | catch (err) {
|
152 | return;
|
153 | }
|
154 | });
|
155 | }
|
156 | }
|
157 | |
158 |
|
159 |
|
160 | get isOpen() {
|
161 | return this._popover.isShown;
|
162 | }
|
163 | set isOpen(value) {
|
164 | if (value) {
|
165 | this.show();
|
166 | }
|
167 | else {
|
168 | this.hide();
|
169 | }
|
170 | }
|
171 | |
172 |
|
173 |
|
174 |
|
175 | setAriaDescribedBy() {
|
176 | this._ariaDescribedby = this.isOpen ? `ngx-popover-${this.popoverId}` : void 0;
|
177 | if (this._ariaDescribedby) {
|
178 | if (this._popover.instance) {
|
179 | this._popover.instance.popoverId = this._ariaDescribedby;
|
180 | }
|
181 | this._renderer.setAttribute(this._elementRef.nativeElement, 'aria-describedby', this._ariaDescribedby);
|
182 | }
|
183 | else {
|
184 | this._renderer.removeAttribute(this._elementRef.nativeElement, 'aria-describedby');
|
185 | }
|
186 | }
|
187 | |
188 |
|
189 |
|
190 |
|
191 | show() {
|
192 | if (this._popover.isShown || !this.popover || this._delayTimeoutId) {
|
193 | return;
|
194 | }
|
195 | this._positionService.setOptions({
|
196 | modifiers: {
|
197 | flip: {
|
198 | enabled: this.adaptivePosition
|
199 | },
|
200 | preventOverflow: {
|
201 | enabled: this.adaptivePosition
|
202 | }
|
203 | }
|
204 | });
|
205 | const showPopover = () => {
|
206 | if (this._delayTimeoutId) {
|
207 | this._delayTimeoutId = undefined;
|
208 | }
|
209 | this._popover
|
210 | .attach(PopoverContainerComponent)
|
211 | .to(this.container)
|
212 | .position({ attachment: this.placement })
|
213 | .show({
|
214 | content: this.popover,
|
215 | context: this.popoverContext,
|
216 | placement: this.placement,
|
217 | title: this.popoverTitle,
|
218 | containerClass: this.containerClass
|
219 | });
|
220 | if (!this.adaptivePosition && this._popover._componentRef) {
|
221 | this._positionService.calcPosition();
|
222 | this._positionService.deletePositionElement(this._popover._componentRef.location);
|
223 | }
|
224 | this.isOpen = true;
|
225 | this.setAriaDescribedBy();
|
226 | };
|
227 | const cancelDelayedTooltipShowing = () => {
|
228 | if (this._popoverCancelShowFn) {
|
229 | this._popoverCancelShowFn();
|
230 | }
|
231 | };
|
232 | if (this.delay) {
|
233 | const _timer = timer(this.delay).subscribe(() => {
|
234 | showPopover();
|
235 | cancelDelayedTooltipShowing();
|
236 | });
|
237 | if (this.triggers) {
|
238 | parseTriggers(this.triggers)
|
239 | .forEach((trigger) => {
|
240 | if (!trigger.close) {
|
241 | return;
|
242 | }
|
243 | this._popoverCancelShowFn = this._renderer.listen(this._elementRef.nativeElement, trigger.close, () => {
|
244 | _timer.unsubscribe();
|
245 | cancelDelayedTooltipShowing();
|
246 | });
|
247 | });
|
248 | }
|
249 | }
|
250 | else {
|
251 | showPopover();
|
252 | }
|
253 | }
|
254 | |
255 |
|
256 |
|
257 |
|
258 | hide() {
|
259 | if (this._delayTimeoutId) {
|
260 | clearTimeout(this._delayTimeoutId);
|
261 | this._delayTimeoutId = undefined;
|
262 | }
|
263 | if (this.isOpen) {
|
264 | this._popover.hide();
|
265 | this.setAriaDescribedBy();
|
266 | this.isOpen = false;
|
267 | }
|
268 | }
|
269 | |
270 |
|
271 |
|
272 |
|
273 | toggle() {
|
274 | if (this.isOpen) {
|
275 | return this.hide();
|
276 | }
|
277 | this.show();
|
278 | }
|
279 | ngOnInit() {
|
280 |
|
281 |
|
282 |
|
283 | if (this._isInited) {
|
284 | return;
|
285 | }
|
286 | this._isInited = true;
|
287 | this._popover.listen({
|
288 | triggers: this.triggers,
|
289 | outsideClick: this.outsideClick,
|
290 | show: () => this.show(),
|
291 | hide: () => this.hide()
|
292 | });
|
293 | }
|
294 | ngOnDestroy() {
|
295 | this._popover.dispose();
|
296 | }
|
297 | }
|
298 | PopoverDirective.decorators = [
|
299 | { type: Directive, args: [{ selector: '[popover]', exportAs: 'bs-popover' },] }
|
300 | ];
|
301 | PopoverDirective.ctorParameters = () => [
|
302 | { type: PopoverConfig },
|
303 | { type: ElementRef },
|
304 | { type: Renderer2 },
|
305 | { type: ViewContainerRef },
|
306 | { type: ComponentLoaderFactory },
|
307 | { type: PositioningService }
|
308 | ];
|
309 | PopoverDirective.propDecorators = {
|
310 | adaptivePosition: [{ type: Input }],
|
311 | popover: [{ type: Input }],
|
312 | popoverContext: [{ type: Input }],
|
313 | popoverTitle: [{ type: Input }],
|
314 | placement: [{ type: Input }],
|
315 | outsideClick: [{ type: Input }],
|
316 | triggers: [{ type: Input }],
|
317 | container: [{ type: Input }],
|
318 | containerClass: [{ type: Input }],
|
319 | isOpen: [{ type: Input }],
|
320 | delay: [{ type: Input }],
|
321 | onShown: [{ type: Output }],
|
322 | onHidden: [{ type: Output }]
|
323 | };
|
324 |
|
325 | class PopoverModule {
|
326 | static forRoot() {
|
327 | return {
|
328 | ngModule: PopoverModule,
|
329 | providers: [ComponentLoaderFactory, PositioningService]
|
330 | };
|
331 | }
|
332 | }
|
333 | PopoverModule.decorators = [
|
334 | { type: NgModule, args: [{
|
335 | imports: [CommonModule],
|
336 | declarations: [PopoverDirective, PopoverContainerComponent],
|
337 | exports: [PopoverDirective],
|
338 | entryComponents: [PopoverContainerComponent]
|
339 | },] }
|
340 | ];
|
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 | export { PopoverConfig, PopoverContainerComponent, PopoverDirective, PopoverModule };
|
347 |
|