MOBILE-3565 components: Implement show-password component
This commit is contained in:
		
							parent
							
								
									727db6c4ea
								
							
						
					
					
						commit
						072c05c268
					
				| @ -13,15 +13,19 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||||
|  | 
 | ||||||
| import { CoreIconComponent } from './icon/icon'; | import { CoreIconComponent } from './icon/icon'; | ||||||
|  | import { CoreShowPasswordComponent } from './show-password/show-password'; | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|     declarations: [ |     declarations: [ | ||||||
|         CoreIconComponent, |         CoreIconComponent, | ||||||
|  |         CoreShowPasswordComponent, | ||||||
|     ], |     ], | ||||||
|     imports: [], |     imports: [], | ||||||
|     exports: [ |     exports: [ | ||||||
|         CoreIconComponent, |         CoreIconComponent, | ||||||
|  |         CoreShowPasswordComponent, | ||||||
|     ], |     ], | ||||||
| }) | }) | ||||||
| export class CoreComponentsModule {} | 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