From 2c977e2b66ced314a4f51121801f62fe5c3c05e4 Mon Sep 17 00:00:00 2001 From: Skip Wonnell Date: Thu, 1 Mar 2018 08:30:15 -0600 Subject: Initial seed code contribution for CDT Issue-ID: APPC-682 Change-Id: I0331ffce2a430195c29d0d1b2295966f9eb28699 Signed-off-by: Skip Wonnell --- src/app/shared/directives/collapse.component.ts | 94 +++++++++++++ .../directives/drop-down-toggle.directive.spec.ts | 36 +++++ .../directives/drop-down-toggle.directive.ts | 46 +++++++ src/app/shared/directives/dropdown.ts | 92 +++++++++++++ .../shared/directives/dropdownnotclosablezone.ts | 45 +++++++ src/app/shared/directives/dropdownopen.ts | 147 +++++++++++++++++++++ 6 files changed, 460 insertions(+) create mode 100644 src/app/shared/directives/collapse.component.ts create mode 100644 src/app/shared/directives/drop-down-toggle.directive.spec.ts create mode 100644 src/app/shared/directives/drop-down-toggle.directive.ts create mode 100644 src/app/shared/directives/dropdown.ts create mode 100644 src/app/shared/directives/dropdownnotclosablezone.ts create mode 100644 src/app/shared/directives/dropdownopen.ts (limited to 'src/app/shared/directives') diff --git a/src/app/shared/directives/collapse.component.ts b/src/app/shared/directives/collapse.component.ts new file mode 100644 index 0000000..bf9c306 --- /dev/null +++ b/src/app/shared/directives/collapse.component.ts @@ -0,0 +1,94 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +import {Directive, HostBinding, Input} from '@angular/core'; + + +@Directive({selector: '[collapse]'}) +export class Collapse { + // style + @HostBinding('style.height') + private height: string; + // shown + @HostBinding('class.in') + @HostBinding('attr.aria-expanded') + private isExpanded: boolean = true; + // hidden + @HostBinding('attr.aria-hidden') + private isCollapsed: boolean = false; + // stale state + @HostBinding('class.collapse') + private isCollapse: boolean = true; + // animation state + @HostBinding('class.collapsing') + private isCollapsing: boolean = false; + + constructor() { + } + + private get collapse(): boolean { + return this.isExpanded; + } + + @Input() + private set collapse(value: boolean) { + this.isExpanded = value; + this.toggle(); + } + + toggle() { + if (this.isExpanded) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.isCollapse = false; + this.isCollapsing = true; + + this.isExpanded = false; + this.isCollapsed = true; + setTimeout(() => { + this.height = '0'; + this.isCollapse = true; + this.isCollapsing = false; + }, 4); + } + + show() { + this.isCollapse = false; + this.isCollapsing = true; + + this.isExpanded = true; + this.isCollapsed = false; + setTimeout(() => { + this.height = 'auto'; + + this.isCollapse = true; + this.isCollapsing = false; + }, 4); + } +} diff --git a/src/app/shared/directives/drop-down-toggle.directive.spec.ts b/src/app/shared/directives/drop-down-toggle.directive.spec.ts new file mode 100644 index 0000000..b08d334 --- /dev/null +++ b/src/app/shared/directives/drop-down-toggle.directive.spec.ts @@ -0,0 +1,36 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +/* tslint:disable:no-unused-variable */ + +import {DropDownToggleDirective} from './drop-down-toggle.directive'; +import {ElementRef} from '@angular/core'; + + +describe('DropDownToggleDirective', () => { + it('should create an instance', () => { + const directive = new DropDownToggleDirective(new ElementRef('')); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/app/shared/directives/drop-down-toggle.directive.ts b/src/app/shared/directives/drop-down-toggle.directive.ts new file mode 100644 index 0000000..7bf9fa8 --- /dev/null +++ b/src/app/shared/directives/drop-down-toggle.directive.ts @@ -0,0 +1,46 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +import {Directive, ElementRef, Input, OnInit} from '@angular/core'; + +@Directive({ + selector: '[appDropDownToggle]' +}) +export class DropDownToggleDirective implements OnInit { + @Input() type: string; + + constructor(private el: ElementRef) { + + + } + + ngOnInit() { + + if (this.type == 'dropdown') + this.el.nativeElement.setAttribute('data-toggle', 'dropdown'); + + + } + +} diff --git a/src/app/shared/directives/dropdown.ts b/src/app/shared/directives/dropdown.ts new file mode 100644 index 0000000..9057302 --- /dev/null +++ b/src/app/shared/directives/dropdown.ts @@ -0,0 +1,92 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +import {ContentChild, Directive, ElementRef, EventEmitter, Input, Output} from '@angular/core'; +import {DropdownNotClosableZone} from './dropdownnotclosablezone'; + +@Directive({ + selector: '[dropdown]', + exportAs: 'dropdown' +}) +export class Dropdown { + + // ------------------------------------------------------------------------- + // Inputs / Outputs + // ------------------------------------------------------------------------- + + @Input('dropdownToggle') + toggleClick = true; + + @Input('dropdownFocusActivate') + activateOnFocus = false; + + @Output() + onOpen = new EventEmitter(); + + @Output() + onClose = new EventEmitter(); + + // ------------------------------------------------------------------------- + // Properties + // ------------------------------------------------------------------------- + + @ContentChild(DropdownNotClosableZone) + notClosableZone: DropdownNotClosableZone; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(private elementRef: ElementRef) { + } + + // ------------------------------------------------------------------------- + // Public Methods + // ------------------------------------------------------------------------- + + open() { + const element: HTMLElement = this.elementRef.nativeElement; + element.classList.add('open'); + this.onOpen.emit(undefined); + } + + close() { + const element: HTMLElement = this.elementRef.nativeElement; + element.classList.remove('open'); + this.onClose.emit(undefined); + } + + isOpened() { + const element: HTMLElement = this.elementRef.nativeElement; + return element.classList.contains('open'); + } + + isInClosableZone(element: HTMLElement) { + if (!this.notClosableZone) + return false; + + return this.notClosableZone.contains(element); + } + +} \ No newline at end of file diff --git a/src/app/shared/directives/dropdownnotclosablezone.ts b/src/app/shared/directives/dropdownnotclosablezone.ts new file mode 100644 index 0000000..9ad351a --- /dev/null +++ b/src/app/shared/directives/dropdownnotclosablezone.ts @@ -0,0 +1,45 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +import {Directive, ElementRef, Input} from '@angular/core'; + +@Directive({ + selector: '[dropdown-not-closable-zone]' +}) +export class DropdownNotClosableZone { + + @Input('dropdown-not-closable-zone') + dropdownNotClosabledZone: boolean; + + constructor(private elementRef: ElementRef) { + } + + contains(element: HTMLElement) { + if (this.dropdownNotClosabledZone === false) + return false; + + const thisElement: HTMLElement = this.elementRef.nativeElement; + return thisElement.contains(element); + } +} \ No newline at end of file diff --git a/src/app/shared/directives/dropdownopen.ts b/src/app/shared/directives/dropdownopen.ts new file mode 100644 index 0000000..ea2858b --- /dev/null +++ b/src/app/shared/directives/dropdownopen.ts @@ -0,0 +1,147 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software 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. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + + +import {Directive, ElementRef, Host, HostListener, OnDestroy} from '@angular/core'; +import {Dropdown} from './dropdown'; + +@Directive({ + selector: '[dropdown-open]', + exportAs: 'dropdownOpen' +}) +export class DropdownOpen implements OnDestroy { + + // ------------------------------------------------------------------------- + // Private Properties + // ------------------------------------------------------------------------- + + /** + * This hack is needed for dropdown not to open and instantly closed + */ + private openedByFocus: boolean = false; + + private closeDropdownOnOutsideClick: (event: Event) => void; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(@Host() public dropdown: Dropdown, + private elementRef: ElementRef) { + const _this = this; + this.closeDropdownOnOutsideClick = function closeDropdownOnOutsideClick(event: MouseEvent) { + _this.closeIfInClosableZone(event); + }; + } + + // ------------------------------------------------------------------------- + // Public Methods + // ------------------------------------------------------------------------- + + toggle() { + if (this.dropdown.isOpened()) { + this.close(); + } else { + this.open(); + } + } + + open() { + if (this.dropdown.isOpened()) + return; + + this.dropdown.open(); + document.addEventListener('click', this.closeDropdownOnOutsideClick, true); + } + + close() { + if (!this.dropdown.isOpened()) + return; + + this.dropdown.close(); + document.removeEventListener('click', this.closeDropdownOnOutsideClick, true); + } + + @HostListener('click') + openDropdown() { + if (this.dropdown.activateOnFocus && this.openedByFocus) { + this.openedByFocus = false; + return; + } + + if (this.dropdown.isOpened() && this.dropdown.toggleClick) { + this.close(); + } else { + this.open(); + } + } + + @HostListener('keydown', ['$event']) + dropdownKeydown(event: KeyboardEvent) { + if (event.keyCode === 40) { // down + this.openDropdown(); + } + } + + @HostListener('focus') + onFocus() { + if (!this.dropdown.activateOnFocus) return; + this.openedByFocus = true; + this.dropdown.open(); + document.addEventListener('click', this.closeDropdownOnOutsideClick, true); + } + + @HostListener('blur', ['$event']) + onBlur(event: FocusEvent) { + if (!this.dropdown.activateOnFocus) return; + if (event.relatedTarget && + !this.dropdown.isInClosableZone( event.relatedTarget) && + event.relatedTarget !== this.elementRef.nativeElement) { + + this.dropdown.close(); + document.removeEventListener('click', this.closeDropdownOnOutsideClick, true); + } + } + + // ------------------------------------------------------------------------- + // Lifecycle Methods + // ------------------------------------------------------------------------- + + ngOnDestroy() { + document.removeEventListener('click', this.closeDropdownOnOutsideClick, true); + } + + // ------------------------------------------------------------------------- + // Private Methods + // ------------------------------------------------------------------------- + + private closeIfInClosableZone(event: Event) { + if (!this.dropdown.isInClosableZone( event.target) + && event.target !== this.elementRef.nativeElement + && !this.elementRef.nativeElement.contains(event.target)) { + this.dropdown.close(); + document.removeEventListener('click', this.closeDropdownOnOutsideClick, true); + } + } + +} \ No newline at end of file -- cgit 1.2.3-korg