diff --git a/angular.json b/angular.json index 1624df5..36e4444 100644 --- a/angular.json +++ b/angular.json @@ -134,5 +134,8 @@ } } } + }, + "cli": { + "analytics": false } } \ No newline at end of file diff --git a/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.component.ts b/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.component.ts index ba51e25..a8acd37 100644 --- a/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.component.ts +++ b/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.component.ts @@ -29,6 +29,16 @@ export class NgxTouchKeyboardComponent { debug = false; @Output() closePanel = new EventEmitter(); + //This event that come from the application, and deal with accept click. + //With this event we can declare the method that treatment with this event in the parent app + @Output() acceptClick: EventEmitter; + //This method responsible validate the input text value. + //For example if you wont to accept only numbers input. + validate: ((args: string | undefined) => boolean) | undefined; + //This variable declare for us if We make changing text value after We click on 'accept' button, + //If We click on 'accept' button and We pass the validation then We need to change the final text value + //Otherwise (if We not passing the validation process) then We need to return back to the previous text. + textBeforeAccept: string = ''; private _activeButtonClass = 'active'; private _holdInteractionTimeout!: number; @@ -45,7 +55,10 @@ export class NgxTouchKeyboardComponent { private _sanitizer: DomSanitizer, private _elementRef: ElementRef, @Inject(LOCALE_ID) private _defaultLocale: string - ) {} + ) { + + this.acceptClick = new EventEmitter(); + } // ----------------------------------------------------------------------------------------------------- // @ Accessors @@ -191,8 +204,26 @@ export class NgxTouchKeyboardComponent { // And set focus to input this._focusActiveInput(); + //When we setting + this._activeInputElement.select(); + } + + /** + * Copy the value text from the input text element + */ +setTextBeforeAccept(): void { + this.textBeforeAccept = this._activeInputElement != undefined ? this._activeInputElement.value : ''; +} + + + /** + * Get the active input text element + */ + getActiveInputElement(): HTMLInputElement | HTMLTextAreaElement | null { + return this._activeInputElement; } + /** * Check whether the button is a standard button */ @@ -253,7 +284,30 @@ export class NgxTouchKeyboardComponent { this.layoutName = this.layoutName === 'alphabetic' ? 'shift' : 'alphabetic'; return; - } else if (button === fnButton.DONE) { + } + else if (button === fnButton.DONE) { + //If we click on 'done' button we need to check the value before We close the keyboard panel + if (this.validate) { //If there is validation method declarations + if (this.validate(this._activeInputElement?.value)) { //If the validation pass then + //We accept the value changed + this.textBeforeAccept = this._activeInputElement != undefined ? this._activeInputElement.value : ''; + //We calling to accept method to make any thing you wont and declare at this 'accept' method + this.acceptClick.emit(this); + } + else //If the validation not pass then + { + //We need return to the previous text + //For example if we accept only number and the text value was '222' and we changed him to '222ttg' value + //Then we will return to '222' number + if(this._activeInputElement != null && this._activeInputElement) + this._activeInputElement.value = this.textBeforeAccept; + } + } + else { + //If there is no validation method then we accept any text and setting him and calling to 'accept' method to make any thing you wont + this.textBeforeAccept = this._activeInputElement ? this._activeInputElement.value : ''; + this.acceptClick.emit(this); + } this.closePanel.emit(); return; } diff --git a/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.directive.ts b/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.directive.ts index 4ca28a6..bc61360 100644 --- a/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.directive.ts +++ b/projects/ngx-touch-keyboard/src/lib/ngx-touch-keyboard.directive.ts @@ -2,9 +2,11 @@ import { ComponentRef, Directive, ElementRef, + EventEmitter, Inject, Input, OnDestroy, + Output, } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { ComponentPortal } from '@angular/cdk/portal'; @@ -16,13 +18,17 @@ import { PositionStrategy, } from '@angular/cdk/overlay'; import { NgxTouchKeyboardComponent } from './ngx-touch-keyboard.component'; +import { fnButton } from './Locale/constants'; @Directive({ - selector: 'input[ngxTouchKeyboard], textarea[ngxTouchKeyboard]', + selector: 'input[ngxTouchKeyboard], textarea[ngxTouchKeyboard], div[ngxTouchKeyboard]', exportAs: 'ngxTouchKeyboard', }) export class NgxTouchKeyboardDirective implements OnDestroy { isOpen = false; + @Output() acceptClick: EventEmitter; + + @Input() validate!: ((args: string | undefined) => boolean) | undefined; private _locale!: string; /** locale */ @@ -34,6 +40,26 @@ export class NgxTouchKeyboardDirective implements OnDestroy { this._locale = value; } + private _divMode!: boolean; + /** div mode */ + @Input() + get ngxTouchKeyboardDiv() { + return this._divMode; + } + set ngxTouchKeyboardDiv(value: any) { + this._divMode = coerceBooleanProperty(value); + } + + private _openWithButton!: boolean; + /** open virtual keyboard with button instead of focus on text input*/ + @Input() + get ngxTouchKeyboardOpenWithButton() { + return this._openWithButton; + } + set ngxTouchKeyboardOpenWithButton(value: any) { + this._openWithButton = coerceBooleanProperty(value); + } + private _debugMode!: boolean; /** debug mode */ @Input() @@ -63,8 +89,28 @@ export class NgxTouchKeyboardDirective implements OnDestroy { constructor( private _overlay: Overlay, private _elementRef: ElementRef, + private _elementDivRef: ElementRef, @Inject(DOCUMENT) private _document: any - ) {} + ) { + + this.acceptClick = new EventEmitter(); + + if (this._elementRef.nativeElement.type != undefined) { + this._elementRef.nativeElement.addEventListener('blur', () => { + this.blurEventHandler(); + }); + this._elementRef.nativeElement.addEventListener('focus', () => { + if (!this.ngxTouchKeyboardOpenWithButton) + this.openPanel(); + }); + } + else { + + this.ngxTouchKeyboardDiv = true; + this._declareDivEvents(); + } + + } // ----------------------------------------------------------------------------------------------------- // @ Lifecycle hooks @@ -123,18 +169,40 @@ export class NgxTouchKeyboardDirective implements OnDestroy { this._panelRef.instance.debug = this.ngxTouchKeyboardDebug; this._panelRef.instance.setLocale(this._locale); this._panelRef.instance.setActiveInput(this._elementRef.nativeElement); + //We initialize the text before accept to keep the last change, + //If there is validation process for the text input and the user insert wrong text + //Then We need return to the previous text. + this._panelRef.instance.setTextBeforeAccept(); this.isOpen = true; // Reference the input element this._panelRef.instance.closePanel.subscribe(() => this.closePanel()); + this._panelRef.instance.acceptClick.subscribe((element) => { + this.acceptClick.emit(element); + }); + this._panelRef.instance.validate = this.validate; + + } + blurEventHandler() { + this._panelRef.instance.handleButtonPress(fnButton.DONE); + //this.closePanel(); } /** * Close keyboard panel */ closePanel(): void { + //The problem is that when I want to display the keyboard again + //I have to lose focus from the text input + //(by clicking on the screen outside the text input) and then when + //I click on the text input the keyboard will appear... + //To deal with this problem we makes focus out by calling blur method + this._panelRef.instance.getActiveInputElement()?.blur(); this._overlayRef.detach(); this.isOpen = false; + //We check if We in div mode, then We need to return from input text right to div content + if (this.ngxTouchKeyboardDiv) + this._replaceInputToDivElement(); } /** @@ -253,4 +321,43 @@ export class NgxTouchKeyboardDirective implements OnDestroy { // Return input return element; } + /** + * Create the overlay + * + * @private + */ + private _declareDivEvents(): void { + this._elementDivRef.nativeElement.addEventListener('click', () => { + //When we click on the div element, We need to check if the virtual keyboard is open + //because We wont to prevent from the click listener to action when we press on the virtual keyboard + if (!this.isOpen) { + const element: HTMLInputElement = document.createElement('input'); + this._elementRef.nativeElement = element; + this._elementRef.nativeElement.value = this._elementDivRef.nativeElement.innerHTML; + this._elementDivRef.nativeElement.innerHTML = ''; + this._elementRef.nativeElement.addEventListener('blur', () => { + this.blurEventHandler(); + }); + this._elementRef.nativeElement.addEventListener('focus', () => { + if (!this.ngxTouchKeyboardOpenWithButton) + this.openPanel(); + }); + + this._elementDivRef.nativeElement.appendChild(this._elementRef.nativeElement); + // if (this._elementDivRef.nativeElement.removeAllListeners) + // this._elementDivRef.nativeElement.removeAllListeners('click'); + this._elementRef.nativeElement.focus(); + } + }); + } + + /** + * Create the overlay + * + * @private + */ + private _replaceInputToDivElement(): void { + this._elementDivRef.nativeElement.innerHTML = this._elementRef.nativeElement.value; + this._declareDivEvents(); + } } diff --git a/src/app/app.component.html b/src/app/app.component.html index c8f867f..bfdd334 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -40,6 +40,7 @@