MOBILE-3565 components: Implement show-password component
This commit is contained in:
		
							parent
							
								
									727db6c4ea
								
							
						
					
					
						commit
						072c05c268
					
				| @ -13,15 +13,19 @@ | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { NgModule } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreIconComponent } from './icon/icon'; | ||||
| import { CoreShowPasswordComponent } from './show-password/show-password'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreIconComponent, | ||||
|         CoreShowPasswordComponent, | ||||
|     ], | ||||
|     imports: [], | ||||
|     exports: [ | ||||
|         CoreIconComponent, | ||||
|         CoreShowPasswordComponent, | ||||
|     ], | ||||
| }) | ||||
| export class CoreComponentsModule {} | ||||
|  | ||||
							
								
								
									
										4
									
								
								src/app/components/show-password/core-show-password.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/app/components/show-password/core-show-password.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| <ng-content></ng-content> | ||||
| <ion-button icon-only clear [attr.aria-label]="label | translate" [core-suppress-events] (onClick)="toggle($event)"> | ||||
|     <core-icon [name]="iconName"></core-icon> | ||||
| </ion-button> | ||||
							
								
								
									
										38
									
								
								src/app/components/show-password/show-password.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/app/components/show-password/show-password.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| ion-app.app-root core-show-password { | ||||
|     padding: 0px; | ||||
|     width: 100%; | ||||
|     position: relative; | ||||
| 
 | ||||
|     ion-input input.text-input { | ||||
|         // @todo @include padding(null, 47px, null, null); | ||||
|     } | ||||
| 
 | ||||
|     .button[icon-only] { | ||||
|         background: transparent; | ||||
|         // @todo padding: 0 ($content-padding / 2); | ||||
|         position: absolute; | ||||
|         // @todo @include position(null, 0, $content-padding / 2, null); | ||||
|         margin-top: 0; | ||||
|         margin-bottom: 0; | ||||
|     } | ||||
| 
 | ||||
|     .core-ioninput-password { | ||||
|         padding-top: 0; | ||||
|         padding-bottom: 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ion-app.app-root.md { | ||||
|     .item-label-stacked core-show-password .button[icon-only] { | ||||
|         bottom: 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ion-app.app-root.ios { | ||||
|     .item-label-stacked core-show-password .button[icon-only] { | ||||
|         bottom: -5px; | ||||
|     } | ||||
|     core-show-password .button[icon-only] { | ||||
|         bottom: 0; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										136
									
								
								src/app/components/show-password/show-password.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/app/components/show-password/show-password.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,136 @@ | ||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Component, OnInit, AfterViewInit, Input, ElementRef, ContentChild } from '@angular/core'; | ||||
| import { IonInput } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| 
 | ||||
| /** | ||||
|  * Component to allow showing and hiding a password. The affected input MUST have a name to identify it. | ||||
|  * | ||||
|  * @description | ||||
|  * This directive needs to surround the input with the password. | ||||
|  * | ||||
|  * You need to supply the name of the input. | ||||
|  * | ||||
|  * Example: | ||||
|  * | ||||
|  * <core-show-password item-content [name]="'password'"> | ||||
|  *     <ion-input type="password" name="password"></ion-input> | ||||
|  * </core-show-password> | ||||
|  */ | ||||
| @Component({ | ||||
|     selector: 'core-show-password', | ||||
|     templateUrl: 'core-show-password.html', | ||||
|     styleUrls: ['show-password.scss'], | ||||
| }) | ||||
| export class CoreShowPasswordComponent implements OnInit, AfterViewInit { | ||||
| 
 | ||||
|     @Input() name: string; // Name of the input affected.
 | ||||
|     @Input() initialShown?: boolean | string; // Whether the password should be shown at start.
 | ||||
|     @ContentChild(IonInput) ionInput: IonInput; | ||||
| 
 | ||||
|     shown: boolean; // Whether the password is shown.
 | ||||
|     label: string; // Label for the button to show/hide.
 | ||||
|     iconName: string; // Name of the icon of the button to show/hide.
 | ||||
|     selector = ''; // Selector to identify the input.
 | ||||
| 
 | ||||
|     protected input: HTMLInputElement; // Input affected.
 | ||||
|     protected element: HTMLElement; // Current element.
 | ||||
| 
 | ||||
|     constructor(element: ElementRef) { | ||||
|         this.element = element.nativeElement; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Component being initialized. | ||||
|      */ | ||||
|     ngOnInit(): void { | ||||
|         this.shown = CoreUtils.instance.isTrueOrOne(this.initialShown); | ||||
|         this.selector = 'input[name="' + this.name + '"]'; | ||||
|         this.setData(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * View has been initialized. | ||||
|      */ | ||||
|     ngAfterViewInit(): void { | ||||
|         this.searchInput(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Search the input to show/hide. | ||||
|      */ | ||||
|     protected async searchInput(): Promise<void> { | ||||
|         if (this.ionInput) { | ||||
|             // It's an ion-input, use it to get the native element.
 | ||||
|             this.input = await this.ionInput.getInputElement(); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Search the input.
 | ||||
|         this.input = this.element.querySelector(this.selector); | ||||
| 
 | ||||
|         if (this.input) { | ||||
|             // Input found. Set the right type.
 | ||||
|             this.input.type = this.shown ? 'text' : 'password'; | ||||
| 
 | ||||
|             // By default, don't autocapitalize and autocorrect.
 | ||||
|             if (!this.input.getAttribute('autocorrect')) { | ||||
|                 this.input.setAttribute('autocorrect', 'off'); | ||||
|             } | ||||
|             if (!this.input.getAttribute('autocapitalize')) { | ||||
|                 this.input.setAttribute('autocapitalize', 'none'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set label, icon name and input type. | ||||
|      */ | ||||
|     protected setData(): void { | ||||
|         this.label = this.shown ? 'core.hide' : 'core.show'; | ||||
|         this.iconName = this.shown ? 'eye-off' : 'eye'; | ||||
|         if (this.input) { | ||||
|             this.input.type = this.shown ? 'text' : 'password'; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Toggle show/hide password. | ||||
|      * | ||||
|      * @param event The mouse event. | ||||
|      */ | ||||
|     toggle(event: Event): void { | ||||
|         event.preventDefault(); | ||||
|         event.stopPropagation(); | ||||
| 
 | ||||
|         const isFocused = document.activeElement === this.input; | ||||
| 
 | ||||
|         this.shown = !this.shown; | ||||
|         this.setData(); | ||||
| 
 | ||||
|         if (isFocused && CoreApp.instance.isAndroid()) { | ||||
|             // In Android, the keyboard is closed when the input type changes. Focus it again.
 | ||||
|             setTimeout(() => { | ||||
|                 CoreDomUtils.instance.focusElement(this.input); | ||||
|             }, 400); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user