turbogui-angular
Version:
A library that tries to help with the most common user interface elements on several frameworks and platforms
1 lines • 284 kB
Source Map (JSON)
{"version":3,"file":"turbogui-angular.mjs","sources":["../../../projects/turbogui-angular/src/main/view/directives/ElementClickOutsideDirective.ts","../../../projects/turbogui-angular/src/main/view/directives/ElementCreatedDirective.ts","../../../projects/turbogui-angular/src/main/view/directives/ElementDestroyedDirective.ts","../../../projects/turbogui-angular/src/main/view/directives/AutoFocusOnDisplayDirective.ts","../../../projects/turbogui-angular/src/main/view/directives/AutoSelectTextOnFocusDirective.ts","../../../projects/turbogui-angular/src/main/model/modules/turbogui-angular.module.ts","../../../projects/turbogui-angular/src/main/model/classes/SingletoneStrictClass.ts","../../../projects/turbogui-angular/src/main/controller/notification.service.ts","../../../projects/turbogui-angular/src/main/controller/globalerror.service.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-base/dialog-base.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-error/dialog-error.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-error/dialog-error.component.html","../../../projects/turbogui-angular/src/main/view/animations/fade.animation.ts","../../../projects/turbogui-angular/src/main/view/components/busy-state-base/busy-state-base.component.ts","../../../projects/turbogui-angular/src/main/view/components/busy-state-base/busy-state-base.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-iframe/dialog-iframe.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-iframe/dialog-iframe.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-image/dialog-image.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-image/dialog-image.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-blob/dialog-blob.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-blob/dialog-blob.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-date-selection/dialog-date-selection.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-date-selection/dialog-date-selection.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-single-option/dialog-single-option.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-single-option/dialog-single-option.component.html","../../../projects/turbogui-angular/src/main/controller/dialog.service.ts","../../../projects/turbogui-angular/src/main/controller/http.service.ts","../../../projects/turbogui-angular/src/main/controller/httpservice/HTTPServiceGetRequest.ts","../../../projects/turbogui-angular/src/main/controller/httpservice/HTTPServicePostRequest.ts","../../../projects/turbogui-angular/src/main/controller/browser.service.ts","../../../projects/turbogui-angular/src/main/controller/turbo-api.service.ts","../../../projects/turbogui-angular/src/main/controller/router-base.service.ts","../../../projects/turbogui-angular/src/main/managers/TranslationManager.ts","../../../projects/turbogui-angular/src/main/controller/locales-base.service.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-two-option/dialog-two-option.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-two-option/dialog-two-option.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-multiple-option/dialog-multiple-option.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-multiple-option/dialog-multiple-option.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-single-selection-list/dialog-single-selection-list.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-single-selection-list/dialog-single-selection-list.component.html","../../../projects/turbogui-angular/src/main/view/components/dialog-single-input/dialog-single-input.component.ts","../../../projects/turbogui-angular/src/main/view/components/dialog-single-input/dialog-single-input.component.html","../../../projects/turbogui-angular/src/main/view/components/button-base/button-base.component.ts","../../../projects/turbogui-angular/src/main/view/components/button-image/button-image.component.ts","../../../projects/turbogui-angular/src/main/view/components/button-image/button-image.component.html","../../../projects/turbogui-angular/src/main/view/components/button-container/button-container.component.ts","../../../projects/turbogui-angular/src/main/view/components/button-container/button-container.component.html","../../../projects/turbogui-angular/src/main/model/classes/GUINotification.ts","../../../projects/turbogui-angular/src/main/model/classes/View.ts","../../../projects/turbogui-angular/src/main/model/classes/ViewService.ts","../../../projects/turbogui-angular/src/main/managers/DelayedMethodCallManager.ts","../../../projects/turbogui-angular/src/main/view/forms/ValidatorsPlus.ts","../../../projects/turbogui-angular/src/public_api.ts","../../../projects/turbogui-angular/src/turbogui-angular.ts"],"sourcesContent":["/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Directive, ElementRef, Output, EventEmitter, HostListener } from '@angular/core';\r\n\r\n\r\n/**\r\n * It is necessary to import TurboGuiAngularModule at the component that uses this directive\r\n * \r\n * This directive is used to execute an action when the user clicks outside of an element.\r\n * \r\n * If we set the elementClickOutside tag to the html element and set the clickOutsideElement event to a function: <element elementClickOutside (clickOutsideElement)=\"clickOutsideElement()\" ...,\r\n * this function will be executed when the user clicks outside of the element.\r\n */\r\n@Directive({\r\n selector: '[elementClickOutside]',\r\n standalone: false\r\n})\r\n\r\n\r\n\r\nexport class ElementClickOutsideDirective {\r\n \r\n \r\n @Output() clickOutsideElement = new EventEmitter<void>();\r\n \r\n\r\n constructor(private readonly elementRef: ElementRef) {\r\n \r\n }\r\n \r\n\r\n @HostListener('document:click', ['$event.target']) onClick(targetElement: HTMLElement): void {\r\n \r\n const clickedInside = this.elementRef.nativeElement.contains(targetElement);\r\n \r\n if (!clickedInside) {\r\n \r\n this.clickOutsideElement.emit();\r\n }\r\n } \r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Directive, EventEmitter, Output, OnInit } from '@angular/core';\r\n\r\n\r\n/** This directive is used to listen for onInit events on raw html elements */\r\n@Directive({\n selector: '[elementCreated]',\n standalone: false\n})\r\n\r\n\r\n/**\r\n * This directive is used to listen for onInit events on raw html elements\r\n * If we place (elementCreated)=\"someMethod()\" on the element at the html template part, when the element\r\n * that uses this directive is visually created, someMethod() will be called.\r\n */\r\nexport class ElementCreatedDirective implements OnInit {\r\n\r\n\r\n /**\r\n * Event that will be dispatched once element is created\r\n */\r\n @Output() elementCreated: EventEmitter<ElementCreatedDirective> = new EventEmitter();\r\n\r\n\r\n /**\r\n * Listen for the on init event\r\n */\r\n ngOnInit() {\r\n\r\n this.elementCreated.next(this);\r\n }\r\n\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Directive, OnDestroy, EventEmitter, Output } from '@angular/core';\r\n\r\n\r\n/** This directive is used to listen for onDestroy events on raw html elements */\r\n@Directive({\n selector: '[elementDestroyed]',\n standalone: false\n})\r\n\r\n\r\n/**\r\n * This directive is used to listen for onDestroy events on raw html elements\r\n * If we place (elementDestroyed)=\"someMethod()\" on the element at the html template part, when the element\r\n * that uses this directive is visually destroyed from the screen, someMethod() will be called.\r\n */\r\nexport class ElementDestroyedDirective implements OnDestroy {\r\n\r\n\r\n /**\r\n * Event that will be dispatched once element is destroyed\r\n */\r\n @Output() elementDestroyed: EventEmitter<ElementDestroyedDirective> = new EventEmitter();\r\n\r\n\r\n /**\r\n * Listen for the on destroy event\r\n */\r\n ngOnDestroy() {\r\n\r\n this.elementDestroyed.next(this);\r\n }\r\n\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Directive, ElementRef, NgZone, Renderer2, AfterContentInit } from '@angular/core';\r\n\r\n\r\n/** This directive is used to perform an autofocus on an element every time it is displayed */\r\n@Directive({\n selector: '[autoFocusOnDisplay]',\n standalone: false\n})\r\n\r\n\r\n/**\r\n * This directive is used to perform an autofocus on an element every time it is displayed\r\n * If we set the autoFocusOnDisplay tag to the html element, it will be automatically focused after it is shown.\r\n */\r\nexport class AutoFocusOnDisplayDirective implements AfterContentInit {\r\n \r\n \r\n constructor(private readonly el: ElementRef, private readonly zone: NgZone, private readonly renderer: Renderer2) {\r\n \r\n if (!el.nativeElement['focus']) {\r\n \r\n throw new Error('Element does not accept focus');\r\n }\r\n }\r\n \r\n ngAfterContentInit() {\r\n \r\n this.zone.runOutsideAngular(() => setTimeout(() => {\r\n \r\n this.renderer.selectRootElement(this.el.nativeElement).focus();\r\n \r\n }, 0));\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';\r\n\r\n\r\n/** This directive is used to perform an automatic select all text on an element every time it is focused */\r\n@Directive({\n selector: '[autoSelectTextOnFocus]',\n standalone: false\n})\r\n\r\n\r\n/**\r\n * This directive is used to perform an an automatic select all text on an element every time it is focused.\r\n * If we set the autoSelectTextOnFocus tag to the html element, its text will be automatically selected after it gets the focus.\r\n */\r\nexport class AutoSelectTextOnFocusDirective {\r\n \r\n \r\n constructor(private readonly el: ElementRef, private readonly renderer: Renderer2) {\r\n \r\n if (!el.nativeElement['select']) {\r\n \r\n throw new Error('Element does not accept select');\r\n }\r\n }\r\n \r\n \r\n @HostListener('focus', ['$event']) onFocus() {\r\n \r\n this.renderer.selectRootElement(this.el.nativeElement).select();\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { NgModule } from '@angular/core';\r\nimport { ElementClickOutsideDirective } from '../../view/directives/ElementClickOutsideDirective';\r\nimport { ElementCreatedDirective } from '../../view/directives/ElementCreatedDirective';\r\nimport { ElementDestroyedDirective } from '../../view/directives/ElementDestroyedDirective';\r\nimport { AutoFocusOnDisplayDirective } from '../../view/directives/AutoFocusOnDisplayDirective';\r\nimport { AutoSelectTextOnFocusDirective } from '../../view/directives/AutoSelectTextOnFocusDirective';\r\n\r\n\r\n/**\r\n * This file contains the root module that contains all the library declarations and exports.\r\n */\r\n@NgModule({\r\n\r\n imports: [\r\n ],\r\n\r\n declarations: [\r\n ElementClickOutsideDirective,\r\n ElementCreatedDirective,\r\n ElementDestroyedDirective,\r\n AutoFocusOnDisplayDirective,\r\n AutoSelectTextOnFocusDirective\r\n ],\r\n\r\n providers: [\r\n ],\r\n\r\n exports: [\r\n ElementClickOutsideDirective,\r\n ElementCreatedDirective,\r\n ElementDestroyedDirective,\r\n AutoFocusOnDisplayDirective,\r\n AutoSelectTextOnFocusDirective\r\n ]\r\n})\r\n\r\nexport class TurboGuiAngularModule { }\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Type, inject } from \"@angular/core\";\r\n\r\n\r\n/**\r\n * Defines a base class that can be used to create singleton services which cannot be instantiated more than one time\r\n * during the whole application lifetime.\r\n * \r\n * To use it, simply extend this class and pass the parent class type to this constructor via super() \r\n */\r\nexport class SingletoneStrictClass {\r\n \r\n\tconstructor(classType: Type<any>) {\r\n\t\t\r\n\t const parent = inject(classType, { skipSelf: true, optional: true});\r\n\t \r\n\t if (parent) {\r\n\t\t\t\r\n\t throw Error(`[${classType.name}]: Can not create more than one instance`);\r\n\t }\r\n\t}\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Injectable } from '@angular/core';\r\nimport { Subject, Subscription } from 'rxjs';\r\nimport { GUINotification } from '../model/classes/GUINotification';\r\nimport { SingletoneStrictClass } from '../model/classes/SingletoneStrictClass';\n\r\n\r\n/**\r\n * This is the main application event bus.\r\n * All global events that happen on the application are broadcasted by this service, and\r\n * can be listened by any application element who previously subscribed\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class NotificationService extends SingletoneStrictClass {\r\n\r\n\r\n /**\r\n * The Observable instance that handles subscriptions and notifications\r\n */\r\n private readonly _notifications = new Subject<GUINotification>();\r\n\r\n\r\n\tconstructor(){\r\n\t\t\r\n\t\tsuper(NotificationService);\r\n\t}\r\n\t\r\n\r\n /**\r\n * used by other services or components to subscribe to all notifications that are generated by this service\r\n *\r\n * @param notificationHandler A method that will be used to receive each notification as a GUINotification instance\r\n *\r\n * @returns The new subscription object. Make sure to unsubscribe when not required anymore\r\n */\r\n subscribe(notificationHandler: (notification: GUINotification) => any) {\r\n\r\n return this._notifications.subscribe(notificationHandler);\r\n }\r\n\r\n\r\n /**\r\n * Launch a notification to anyone who may be listening\r\n *\r\n * @param notification A notification instance to launch\r\n */\r\n send(notification: GUINotification) {\r\n\r\n this._notifications.next(notification);\r\n }\r\n\r\n\r\n /**\r\n * End a previously initiated subscription\r\n *\r\n * @param subscription A previously created subscription instance from which we want to unsubscribe\r\n */\r\n unsubscribe(subscription: Subscription) {\r\n\r\n return subscription.unsubscribe();\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Injectable, ErrorHandler } from '@angular/core';\r\nimport { SingletoneStrictClass } from '../model/classes/SingletoneStrictClass';\r\n\r\n\r\n/**\r\n * Captures all the application exceptions and performs any required action.\r\n * It also contains multiple general error management features.\r\n *\r\n * To define this class as your application error handler, you must add the following to your\r\n * Application providers:\r\n * {\r\n * provide: ErrorHandler,\r\n * useClass: GlobalErrorService\r\n * },\r\n * GlobalErrorService\r\n *\r\n * You cannot access the error handler at runtime. If you need to modify any of the behaviours\r\n * or implement your custom ones, you must extend this class and set your new one as the error\r\n * handler provider.\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class GlobalErrorService extends SingletoneStrictClass implements ErrorHandler {\r\n\r\n\r\n /**\r\n * Enables or disables the error notification to user via an alert box\r\n * Extend this class and override this value on your custom error handle to change it\r\n */\r\n private readonly showExceptionsToUser = true;\r\n\r\n\r\n /**\r\n * Enables or disables the error notification to user via an alert box\r\n * Extend this class and override this value on your custom error handle to change it\r\n */\r\n private readonly showExceptionsOnConsole = true;\r\n\r\n\r\n /**\r\n * Defines the text that will be used for the alert that is shown to the user when an exception happens\r\n * and showExceptionsToUser is true\r\n * Extend this class and override this value on your custom error handle to change it\r\n */\r\n private readonly errorAlertMessage = 'Application exception:\\n\\n';\r\n\r\n\r\n\tconstructor(){\r\n\t\t\r\n\t\tsuper(GlobalErrorService);\r\n\t}\r\n\r\n /**\r\n * Show an alert with the received error detail and also log it to the js console.\r\n *\r\n * Angular expects at least this method to be implemented on any class that is used as a global exception handler.\r\n *\r\n * @param error An error instance\r\n */\r\n handleError(error: any) {\r\n\r\n if (this.showExceptionsToUser) {\r\n\r\n alert(this.errorAlertMessage + (error as string));\r\n }\r\n\r\n if (this.showExceptionsOnConsole) {\r\n\r\n console.log(error);\r\n }\r\n\r\n throw error;\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\n\r\nimport { AfterViewInit, Component, ElementRef } from '@angular/core';\nimport { MatDialogRef } from '@angular/material/dialog';\r\n\r\n\r\n/**\r\n * This is the base class for all the dialog components that can be loaded by the dialog service class\r\n */\r\n@Component({\n template: '',\n standalone: false\n})\r\nexport abstract class DialogBaseComponent implements AfterViewInit {\r\n\r\n\r\n /*\r\n * The name of the superclass must be set into this constant as it is required by the dialog service to identify dialogs as different.\r\n * \r\n * When you extend the dialog base class, simply declare this static constant with the exact same name as your class and you're done.\r\n * If this value is not set on the extended dialog component, a runtime exception will happen when trying to show the dialog.\r\n * \r\n * The root cause of this requirement is that when apps are compiled for production, class names are minified and this causes problems \r\n * when creating a dialog hash to uniquely identify a dialog instance. Therefore, a hardcoded class name is necesary.\r\n */ \r\n static readonly DIALOG_CLASS_NAME:string = '';\r\n\r\n\r\n\tconstructor(public elementRef: ElementRef,\r\n\t\t\t\tpublic dialogRef: MatDialogRef<DialogBaseComponent>) {\r\n \r\n }\r\n\r\n\r\n ngAfterViewInit() {\r\n\t \r\n\t // Assign the component HTML identifier if it is specifically assigned to the dialogref instance\r\n\t if(this.dialogRef.id !== undefined && this.dialogRef.id !== ''){\r\n \r\n\t\t\tthis.elementRef.nativeElement.id = this.dialogRef.id;\r\n\t\t}\r\n\t}\r\n\r\n \r\n /**\r\n * Method to be called by the dialogs that extend this base component when they want to close themselves.\r\n * It will perform the close of that dialog and also send an object to the addDialog() callback with the index and value\r\n * that the user may have selected.\r\n *\r\n * @param index The numeric index of the user option selection. It will be specific for each dialog and it's different available options\r\n * @param value Any value that may be provided to the callback regarding the user selected option.\r\n *\r\n * @return void\r\n */\r\n closeDialog(index:number, value:any = null){\r\n \r\n this.dialogRef.close({index: index, value: value});\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { MatButtonModule } from '@angular/material/button';\nimport { CommonModule } from '@angular/common';\n\r\n\r\n@Component({\n selector: 'tg-dialog-error',\n imports: [CommonModule, MatButtonModule],\n providers: [],\n templateUrl: './dialog-error.component.html',\n styleUrls: ['./dialog-error.component.scss']\n})\r\n\r\n\r\n/**\r\n * A dialog component with a single option button, to be used for error notifications\r\n */\r\nexport class DialogErrorComponent extends DialogBaseComponent {\r\n\r\n\r\n static readonly DIALOG_CLASS_NAME = 'DialogErrorComponent';\r\n \r\n\r\n constructor(public elementRef: ElementRef, public dialogRef: MatDialogRef<DialogBaseComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {\r\n\r\n super(elementRef, dialogRef);\r\n \r\n if (data.texts.length < 1) {\r\n\r\n throw new Error('DialogErrorComponent expects 2 texts: The title and optionally a description');\r\n }\r\n\r\n if (data.options.length !== 1) {\r\n\r\n throw new Error('DialogErrorComponent expects only one option');\r\n }\r\n \r\n if(data.texts.length > 1){\r\n\t\t\t\r\n\t\t\tdata.texts[1] = data.texts[1].replace(/\\n/g, \"<br/>\");\r\n\t\t}\r\n }\r\n}\r\n","<div class=\"titleAndIconContainer\">\r\n <h3>\r\n {{data.texts[0]}}\r\n </h3>\r\n \r\n <!-- error icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\">\r\n <path d=\"M0 0h24v24H0z\" fill=\"none\"/>\r\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\" fill=\"#ff0000\" />\r\n </svg>\r\n \r\n</div>\r\n\r\n<div class=\"textContainer\">\r\n <p *ngIf=\"data.texts.length > 1\" [innerHTML]=\"data.texts[1]\">\r\n </p>\r\n</div>\r\n\r\n<button mat-raised-button color=\"warn\"\r\n (click)=\"closeDialog(0)\">\r\n \r\n {{data.options[0]}}\r\n \r\n</button>","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Injectable } from '@angular/core';\r\nimport { trigger, animate, transition, style } from '@angular/animations';\r\n\r\n\r\n/**\r\n * Fade animations\r\n */\r\n@Injectable()\r\nexport class FadeAnimationClass {\r\n\r\n /**\r\n * Get a custom trigger to create fade animations when components are added or removed from the application\r\n *\r\n * @param triggerName The name for the trigger we want to create\r\n * @param enter The time and easing that we want to use for the enter state\r\n * @param leave The time and easing that we want to use for the leave state\r\n */\r\n static getTrigger(triggerName: string, enter = '1s ease', leave = '300ms ease') {\r\n\r\n return trigger(triggerName, [\r\n transition('void => *', [style({opacity: 0}), animate(enter, style({ opacity: 1 }))]),\r\n transition('* => void', [animate(leave, style({opacity: 0}))])\r\n ]);\r\n }\r\n}\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, HostBinding } from '@angular/core';\r\nimport { FadeAnimationClass } from '../../animations/fade.animation';\r\n\r\n\r\n@Component({\n selector: 'tg-busy-state-base',\n imports: [],\n providers: [],\n templateUrl: './busy-state-base.component.html',\n animations: [FadeAnimationClass.getTrigger('busyStateBaseFade', '1s ease', '400ms ease')],\n styleUrls: ['./busy-state-base.component.scss']\n})\r\n\r\n\r\n/**\r\n * This component is used by turboGUI angular library to show the busy state to the user.\r\n * It is used to block all the user input and progressively shows a busy cursor to notify that the application\r\n * is waiting for something.\r\n *\r\n * We can (should) override this component with our own one to adapt its visual appearance to our application.\r\n * We can then set dialogService.busyStateComponentClass to our component class at the application start to to\r\n * override the default one.\r\n */\r\nexport class BusyStateBaseComponent {\r\n\r\n\r\n /**\r\n * This is used to attach the fade animation directly to this component so it fades in and out when created and removed from the app\r\n */\r\n @HostBinding('@busyStateBaseFade') busyStateBaseFade = true;\r\n}\r\n","<div class=\"darkBg\">\r\n\r\n</div>\r\n\r\n<svg width=\"38\" height=\"38\" viewBox=\"0 0 38 38\" xmlns=\"http://www.w3.org/2000/svg\" stroke=\"#fff\">\r\n <g fill=\"none\" fill-rule=\"evenodd\">\r\n <g transform=\"translate(1 1)\" stroke-width=\"1\">\r\n <circle stroke-opacity=\".2\" cx=\"18\" cy=\"18\" r=\"18\"/>\r\n <path d=\"M36 18c0-9.94-8.06-18-18-18\">\r\n <animateTransform\r\n attributeName=\"transform\"\r\n type=\"rotate\"\r\n from=\"0 18 18\"\r\n to=\"360 18 18\"\r\n dur=\"1s\"\r\n repeatCount=\"indefinite\"/>\r\n </path>\r\n </g>\r\n </g>\r\n</svg>\r\n","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';\r\n\r\n\r\n@Component({\r\n selector: 'tg-dialog-iframe',\r\n imports: [CommonModule],\r\n providers: [],\r\n templateUrl: './dialog-iframe.component.html',\r\n styleUrls: ['./dialog-iframe.component.scss']\r\n})\r\n\r\n\r\n/**\r\n * A dialog component with an iframe that can be used to display any url or content.\r\n * \r\n * We must specify the url in the data parameter when opening the dialog, and we can also specify the title \r\n * by placing it at the first position of the texts array.\r\n */\r\nexport class DialogIFrameComponent extends DialogBaseComponent {\r\n\r\n\r\n static readonly DIALOG_CLASS_NAME = 'DialogIFrameComponent';\r\n \r\n \r\n title = '';\r\n \r\n \r\n safeUrl: SafeResourceUrl;\r\n \r\n \r\n constructor(public elementRef: ElementRef,\r\n public dialogRef: MatDialogRef<DialogBaseComponent>,\r\n private readonly sanitizer: DomSanitizer,\r\n @Inject(MAT_DIALOG_DATA) public data: any) {\r\n \r\n super(elementRef, dialogRef);\r\n \r\n if(data.texts.length > 0) {\r\n \r\n this.title = data.texts[0];\r\n }\r\n \r\n this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(data.data);\r\n }\r\n}\r\n","<h2 *ngIf=\"title !== ''\">{{title}}</h2>\r\n\r\n<iframe [src]=\"safeUrl\" title=\"title\"></iframe>","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';\r\n\r\n\r\n@Component({\r\n selector: 'tg-dialog-image',\r\n imports: [CommonModule],\r\n providers: [],\r\n templateUrl: './dialog-image.component.html',\r\n styleUrls: ['./dialog-image.component.scss']\r\n})\r\n\r\n\r\n/**\r\n * A dialog component with an image that can be used to display any picture url\r\n * \r\n * We must specify the url in the data parameter when opening the dialog, and we can also specify the title \r\n * by placing it at the first position of the texts array.\r\n */\r\nexport class DialogImageComponent extends DialogBaseComponent {\r\n\r\n\r\n static readonly DIALOG_CLASS_NAME = 'DialogImageComponent';\r\n \r\n \r\n title = '';\r\n \r\n \r\n safeUrl: SafeResourceUrl;\r\n \r\n \r\n constructor(public elementRef: ElementRef,\r\n public dialogRef: MatDialogRef<DialogBaseComponent>,\r\n private readonly sanitizer: DomSanitizer,\r\n @Inject(MAT_DIALOG_DATA) public data: any) {\r\n \r\n super(elementRef, dialogRef);\r\n \r\n if(data.texts.length > 0) {\r\n \r\n this.title = data.texts[0];\r\n }\r\n \r\n this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(data.data);\r\n }\r\n}\r\n","<h2 *ngIf=\"title !== ''\">{{title}}</h2>\r\n\r\n<img [src]=\"safeUrl\" title=\"title\" alt=\"{{title}}\" />","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject, OnDestroy, OnInit } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';\n\r\n\r\n@Component({\r\n selector: 'tg-dialog-blob',\r\n imports: [CommonModule],\r\n providers: [],\r\n templateUrl: './dialog-blob.component.html',\r\n styleUrls: ['./dialog-blob.component.scss']\r\n})\r\n\r\n\r\n/**\r\n * A dialog component that shows a blob (pdf, image, etc) inside an iframe.\r\n * \r\n * We must specify the blol in the data parameter when opening the dialog, and we can also specify the title \r\n * by placing it at the first position of the texts array.\r\n */\r\nexport class DialogBlobComponent extends DialogBaseComponent implements OnInit, OnDestroy {\r\n\r\n\r\n static readonly DIALOG_CLASS_NAME = 'DialogBlobComponent';\r\n \r\n \r\n title = '';\r\n \r\n \r\n mimeType = '';\r\n \r\n \r\n objectUrl = '';\r\n \r\n \r\n blobUrl: SafeResourceUrl = '';\r\n \r\n \r\n constructor(public elementRef: ElementRef,\r\n private readonly sanitizer: DomSanitizer,\r\n public dialogRef: MatDialogRef<DialogBaseComponent>,\r\n @Inject(MAT_DIALOG_DATA) public data: any) {\r\n \r\n super(elementRef, dialogRef);\r\n \r\n if(data.texts.length > 0) {\r\n \r\n this.title = data.texts[0];\r\n }\r\n }\r\n \r\n \r\n ngOnInit() {\r\n \r\n let blob:Blob|null = null;\r\n let blobInput = this.data?.data?.blob;\r\n \r\n this.mimeType = this.data?.data?.mimeType || 'application/octet-stream'; \r\n\r\n if (typeof blobInput === 'string') {\r\n \r\n blob = new Blob([blobInput], { type: this.mimeType });\r\n \r\n } else if (blobInput instanceof Blob) {\r\n \r\n blob = blobInput; \r\n }\r\n\r\n if (blob instanceof Blob) {\r\n \r\n this.objectUrl = URL.createObjectURL(blob);\r\n this.blobUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.objectUrl);\r\n }\r\n }\r\n\r\n \r\n ngOnDestroy() {\r\n \r\n if(this.blobUrl !== ''){\r\n \r\n URL.revokeObjectURL(this.objectUrl);\r\n }\r\n }\r\n}\r\n","<h2 *ngIf=\"title !== ''\">{{title}}</h2>\r\n\r\n<!-- For images -->\r\n<img *ngIf=\"mimeType.startsWith('image/')\" [src]=\"blobUrl\" [alt]=\"title\" />\r\n\r\n<!-- For PDFs and other types -->\r\n<iframe *ngIf=\"!mimeType.startsWith('image/')\" [src]=\"blobUrl\" [title]=\"title\"></iframe>","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { MatDatepickerModule } from '@angular/material/datepicker';\r\nimport { MatNativeDateModule } from '@angular/material/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n\r\n@Component({\r\n selector: 'tg-dialog-date-selection',\r\n imports: [CommonModule, MatDatepickerModule, MatNativeDateModule],\r\n providers: [],\r\n templateUrl: './dialog-date-selection.component.html',\r\n styleUrls: ['./dialog-date-selection.component.scss']\r\n})\r\n\r\n\r\n/**\r\n * A dialog component with a calendar that allows us to select a single date value\r\n */\r\nexport class DialogDateSelectionComponent extends DialogBaseComponent {\r\n\r\n\r\n static readonly DIALOG_CLASS_NAME = 'DialogDateSelectionComponent';\r\n \r\n \r\n selectedDate:Date;\r\n\r\n\r\n constructor(public elementRef: ElementRef, public dialogRef: MatDialogRef<DialogBaseComponent>,\r\n @Inject(MAT_DIALOG_DATA) public data: any) {\r\n \r\n super(elementRef, dialogRef);\r\n }\r\n}\r\n","<h2>{{data.texts[0]}}</h2>\r\n\r\n<mat-calendar #calendar\r\n (selectedChange)=\"closeDialog(0, $event)\">\r\n</mat-calendar>","/**\r\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\r\n *\r\n * Website : -> http://www.turbogui.org\r\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\r\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\r\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\r\n */\r\n\r\nimport { Component, ElementRef, Inject } from '@angular/core';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { DialogBaseComponent } from '../dialog-base/dialog-base.component';\r\nimport { MatButtonModule } from '@angular/material/button';\nimport { CommonModule } from '@angular/common';\n\r\n\r\n/**\r\n * A dialog component with a single option button, to be used with dialog service\r\n */\r\n@Component({\n selector: 'tg-dialog-single-option',\n imports: [CommonModule, MatButtonModule],\n providers: [],\n templateUrl: './dialog-single-option.component.html',\n styleUrls: ['./dialog-single-option.component.scss']\n})\r\n\r\n\r\nexport class DialogSingleOptionComponent extends DialogBaseComponent {\r\n\r\n \r\n static readonly DIALOG_CLASS_NAME = 'DialogSingleOptionComponent';\r\n \r\n\r\n constructor(public elementRef: ElementRef, public dialogRef: MatDialogRef<DialogBaseComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {\r\n\r\n super(elementRef, dialogRef);\r\n \r\n if (data.texts.length < 1) {\r\n\r\n throw new Error('DialogSingleOptionComponent expects 2 texts: The title and optionally a description');\r\n }\r\n\r\n if (data.options.length !== 1) {\r\n\r\n throw new Error('DialogSingleOptionComponent expects only one option');\r\n }\r\n }\r\n}\r\n","<h3>\r\n {{data.texts[0]}}\r\n</h3>\r\n\r\n<p *ngIf=\"data.texts.length > 1\">\r\n {{data.texts[1]}}\r\n</p>\r\n\r\n<button mat-raised-button color=\"primary\"\r\n (click)=\"closeDialog(0)\">\r\n \r\n {{data.options[0]}}\r\n \r\n</button>","/**\n * TurboGUI is A library that helps with the most common and generic UI elements and functionalities\n *\n * Website : -> http://www.turbogui.org\n * License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.\n * License Url : -> http://www.apache.org/licenses/LICENSE-2.0\n * CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com\n */\n\nimport { take } from 'rxjs/operators';\nimport { ArrayUtils, NumericUtils } from 'turbocommons-ts';\nimport { Type, Injectable, Injector, ApplicationRef, Renderer2, RendererFactory2, ViewContainerRef, EnvironmentInjector } from '@angular/core';\nimport { MatDialog, MatDialogRef } from '@angular/material/dialog';\nimport { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';\nimport { BusyStateBaseComponent } from '../view/components/busy-state-base/busy-state-base.component';\nimport { ComponentPortal, DomPortalOutlet } from '@angular/cdk/portal';\nimport { DialogBaseComponent } from '../view/components/dialog-base/dialog-base.component';\nimport { DialogErrorComponent } from '../view/components/dialog-error/dialog-error.component';\nimport { DialogIFrameComponent } from '../view/components/dialog-iframe/dialog-iframe.component';\nimport { DialogImageComponent } from '../view/components/dialog-image/dialog-image.component';\nimport { DialogBlobComponent } from '../view/components/dialog-blob/dialog-blob.component';\nimport { DialogDateSelectionComponent } from '../view/components/dialog-date-selection/dialog-date-selection.component';\nimport { SingletoneStrictClass } from '../model/classes/SingletoneStrictClass';\nimport { DialogSingleOptionComponent } from '../view/components/dialog-single-option/dialog-single-option.component';\n\n\n/**\n * Defines a File object that may contain its data loaded.\n */\nexport interface FileWithData extends File {\n \n data?: any;\n}\n\n/**\n * Manages the application modal and non modal floating elements\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class DialogService extends SingletoneStrictClass {\n\n\n /**\n * Used to modify the busy state component that is shown by default by the addModalBusyState() method.\n *\n * @see this.addModalBusyState()\n */\n customBusyStateComponentClass: Type<BusyStateBaseComponent> = BusyStateBaseComponent;\n\n\n /**\n * Check public getter for docs\n */\n private _isEnabled = true;\n\n\n /**\n * Tells if the main application is currently showing a busy state that blocks all user interaction\n */\n private _isShowingBusyState = false;\n\n\n /**\n * A reference to the modal busy state component that is initialized only the first time it is called.\n *\n * (To append the busy state dynamically, we use the Portal concept from the angular material library)\n */\n private _componentPortal: ComponentPortal<BusyStateBaseComponent> | null = null;\n\n\n /**\n * A reference to the modal busy state container where the component will be added\n */\n private _modalBusyStateHost: DomPortalOutlet | null = null;\n\n \n /**\n * Used to store the previous document body overflow values when scroll locks are added\n */\n private readonly _scrollLockSavedOverflowStates: string[] = [];\n \n\n /**\n * Tells if the manager is currently showing a snackbar element or not\n */\n private _isShowingSnackBar = false;\n\n\n /**\n * Contains a list of the dialogs (MODAL AND NON MODAL) that are currently visible to the user.\n * Each item in this list is a hash that is computed when dialog is created to uniquely identify it.\n *\n * Empty list means no dialogs are currently visible\n */\n private _activeDialogs: string[] = [];\n\n\n /**\n * Contains a list with all the MatDialog instances that are currently visible to the user.\n * The list uses the same order as the list of _activeDialogs hash values\n */\n private _activeDialogInstances: MatDialogRef<DialogBaseComponent>[] = [];\n\n\n /**\n * Counts the number of dialogs that are currently open and that can be closed by the user by navigating with the browser\n */\n private _activeCloseableDialogs = 0;\n\n\n /**\n * Used to store the initialized Renderer 2 instance that is used by this class\n */\n private readonly _renderer: Renderer2;\n\n\n /**\n * Method that is used to delete the window beforeunload event listener once not used anymore\n */\n private _windowBeforeUnloadUnListen: (() => void) | null = null;\n\n\n /**\n * Method that is used to delete the document keydown event listener once not used anymore\n */\n private _documentKeydownUnlisten: (() => void) | null = null;\n\n\n /**\n * Method that is used to delete the document mousedown event listener once not used anymore\n */\n private _documentMousedownUnlisten: (() => void) | null = null;\n\n\n /**\n * Method that is used to delete the document pointerdown event listener once not used anymore\n */\n private _documentPointerdownUnlisten: (() => void) | null = null;\n\n\n constructor(rendererFactory: RendererFactory2,\n private readonly matSnackBar: MatSnackBar,\n private readonly matDialog: MatDialog,\n private readonly injector: Injector,\n private readonly applicationRef: ApplicationRef,\n private readonly environmentInjector: EnvironmentInjector) {\n\n\t\tsuper(DialogService);\n\n this._renderer = rendererFactory.createRenderer(null, null);\n }\n\n\n /**\n * Tells if this dialog service is enabled or not. If dialog service is disabled, none of it's features will work\n * This is used to block all dialog features normally when shutting down the application\n *\n * Use with caution. When this is set to false, dialog service stops working.\n */\n set isEnabled(v: boolean) {\n\n if (v === this._isEnabled) {\n\n return;\n }\n\n this._isEnabled = v;\n }\n\n\n /**\n * Enables a warning that will be shown to the user when he/she tries to close the application.\n * This warning will prompt the user to continue with the exit process or cancel it.\n * The specific texts of this message are a generic ones and cannot be changed.\n *\n * IMPORTANT: This method must be called after the main application has been initialized in order to work,\n * otherwise it will do nothing.\n */\n addCloseApplicationWarning() {\n\n this._windowBeforeUnloadUnListen ??= this._renderer.listen('window', 'beforeunload', (event) => event.returnValue = true);\n }\n\n\n /**\n * Remove the close application warning message if previously assigned\n */\n removeCloseApplicationWarning() {\n\n if (this._windowBeforeUnloadUnListen !== null) {\n\n this._windowBeforeUnloadUnListen();\n this._windowBeforeUnloadUnListen = null;\n }\n }\n \n \n /**\n * Disable application scroll by setting document body overflow to hidden.\n * Each call to this method must be matched with a call to removeScrollLock() to restore it back to previous state.\n * If multiple calls to addScrollLock() are done, multiple calls to removeScrollLock() will be required to restore\n * the original scroll state.\n */\n addScrollLock() {\n this._scrollL