You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2017/11/07 13:57:35 UTC
ambari git commit: AMBARI-22374 Log Search UI: button with caret
doesn't toggle dropdown is some cases. (Istvan Tobias via ababiichuk)
Repository: ambari
Updated Branches:
refs/heads/trunk ec3f1e4dc -> f74b2f873
AMBARI-22374 Log Search UI: button with caret doesn't toggle dropdown is some cases. (Istvan Tobias via ababiichuk)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f74b2f87
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f74b2f87
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f74b2f87
Branch: refs/heads/trunk
Commit: f74b2f873b147e7c5639e2a342fc0627b8335f47
Parents: ec3f1e4
Author: Istvan Tobias <to...@gmail.com>
Authored: Tue Nov 7 15:27:38 2017 +0200
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Tue Nov 7 15:27:38 2017 +0200
----------------------------------------------------------------------
.../menu-button/menu-button.component.html | 17 +--
.../menu-button/menu-button.component.less | 22 ++-
.../menu-button/menu-button.component.ts | 144 ++++++++++++++++---
3 files changed, 154 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/f74b2f87/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.html
index ca70927..5e2b15f 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.html
@@ -15,14 +15,15 @@
limitations under the License.
-->
-<div #dropdown [ngClass]="{'dropdown': hasSubItems, 'text-center': true}">
- <a [ngClass]="iconClass + ' icon'" (mousedown)="onMouseDown($event)" (mouseup)="onMouseUp($event)"
- (click)="$event.stopPropagation()"></a>
- <a #dropdownToggle class="dropdown-toggle caret" data-toggle="dropdown" *ngIf="hasCaret"></a>
- <br>
- <a *ngIf="label" (mousedown)="onMouseDown($event)" [ngClass]="labelClass" (mouseup)="onMouseUp($event)"
- (click)="$event.stopPropagation()">{{label}}</a>
- <ul data-component="dropdown-list" *ngIf="hasSubItems" [items]="subItems" (selectedItemChange)="updateValue($event)"
+<div #dropdown [ngClass]="{'dropdown': hasSubItems, 'text-center': true, 'open': dropdownIsOpen}">
+ <a class="dropdown-toggle" [ngClass]="(labelClass || '') + (hasCaret ? ' has-caret' : '')"
+ (click)="onMouseClick($event)"
+ (mousedown)="onMouseDown($event)">
+ <i *ngIf="iconClass" [ngClass]="['icon', iconClass]"></i>
+ <i *ngIf="hasCaret" [ngClass]="['fa ', caretClass ]"></i>
+ <span *ngIf="label" class="menu-button-label">{{label}}</span>
+ </a>
+ <ul data-component="dropdown-list" *ngIf="hasSubItems" [items]="subItems" (selectedItemChange)="onDropdownItemChange($event)"
[isMultipleChoice]="isMultipleChoice" [additionalLabelComponentSetter]="additionalLabelComponentSetter"
[ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}"></ul>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f74b2f87/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
index 615db24..0207561 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
@@ -21,14 +21,26 @@
cursor: pointer;
display: inline-block;
position: relative;
- a:hover, a:focus {
+ a {
+ text-align: center;
text-decoration: none;
+ i {
+ color: @link-color;
+ display: inline-block;
+ position: relative;
+ &.fa-caret-down {
+ padding: 0 .25em;
+ }
+ }
+ .menu-button-label {
+ display: block;
+ }
}
-
- .icon {
- padding: @icon-padding;
+ a:hover, a:focus {
+ i {
+ color: @link-hover-color;
+ }
}
-
.unstyled-link {
color: inherit;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f74b2f87/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts
index 0aa7c7e..5932e1b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts
@@ -19,7 +19,6 @@
import {Component, Input, ViewChild, ElementRef} from '@angular/core';
import {ListItem} from '@app/classes/list-item';
import {ComponentActionsService} from '@app/services/component-actions.service';
-import * as $ from 'jquery';
@Component({
selector: 'menu-button',
@@ -64,6 +63,37 @@ export class MenuButtonComponent {
@Input()
badge: string;
+ @Input()
+ caretClass: string = 'fa-caret-down';
+
+ /**
+ * The minimum time to handle a mousedown as a longclick. Default is 500 ms (0.5sec)
+ * @default 500
+ * @type {number}
+ */
+ @Input()
+ minLongClickDelay: number = 500;
+
+ /**
+ * The maximum milliseconds to wait for longclick ends. The default is 0 which means no upper limit.
+ * @default 0
+ * @type {number}
+ */
+ @Input()
+ maxLongClickDelay: number = 0;
+
+ /**
+ * This is a private property to indicate the mousedown timestamp, so that we can check it when teh click event
+ * has been triggered.
+ */
+ private mouseDownTimestamp: number;
+
+ /**
+ * Indicates if the dropdown list is open or not. So that we use internal state to display or hide the dropdown.
+ * @type {boolean}
+ */
+ private dropdownIsOpen: boolean = false;
+
get hasSubItems(): boolean {
return Boolean(this.subItems && this.subItems.length);
}
@@ -72,26 +102,108 @@ export class MenuButtonComponent {
return this.hasSubItems && !this.hideCaret;
}
- private clickStartTime: number;
-
- private readonly longClickInterval = 1000;
-
- onMouseDown(event: MouseEvent): void {
- if (this.action && event.button === 0) {
- this.clickStartTime = (new Date()).getTime();
+ /**
+ * Handling the click event on the component element.
+ * Two goal:
+ * - check if we have a 'longclick' event and open the dropdown (if any) when longclick event happened
+ * - trigger the action or the dropdown open depending on the target element (caret will open the dropdown otherwise
+ * trigger the action.
+ * @param {MouseEvent} event
+ */
+ onMouseClick(event: MouseEvent): void {
+ let el = <HTMLElement>event.target;
+ let now = Date.now();
+ let mdt = this.mouseDownTimestamp; // mousedown time
+ let isLongClick = mdt && mdt + this.minLongClickDelay <= now && (
+ !this.maxLongClickDelay || mdt + this.maxLongClickDelay >= now
+ );
+ let openDropdown = this.hasSubItems && (
+ el.classList.contains(this.caretClass) || isLongClick || !this.actions[this.action]
+ );
+ if (openDropdown && this.dropdown) {
+ if (this.toggleDropdown()) {
+ this.listenToClickOut();
+ }
+ } else if (this.action) {
+ this.actions[this.action]();
}
+ this.mouseDownTimestamp = 0;
+ event.preventDefault();
}
- onMouseUp(event: MouseEvent): void {
- if (event.button === 0) {
- const clickEndTime = (new Date()).getTime();
- if (this.hasSubItems && (!this.action || clickEndTime - this.clickStartTime >= this.longClickInterval)) {
- $(this.dropdown.nativeElement).toggleClass('open');
- } else if (this.action) {
- this.actions[this.action]();
+ /**
+ * Listening the click event on the document so that we can hide our dropdown list if the event source is not the
+ * component.
+ */
+ private listenToClickOut = (): void => {
+ this.dropdownIsOpen && document.addEventListener('click', this.onDocumentMouseClick);
+ };
+
+ /**
+ * Handling the click event on the document to hide the dropdown list if it needs.
+ * @param {MouseEvent} event
+ */
+ private onDocumentMouseClick = (event: MouseEvent): void => {
+ let el = <HTMLElement>event.target;
+ if (!this.dropdown.nativeElement.contains(el)) {
+ this.closeDropdown();
+ this.removeDocumentClickListener()
+ }
+ };
+
+ /**
+ * Handling the mousedown event, so that we can check the long clicks and open the dropdown if any.
+ * @param {MouseEvent} event
+ */
+ onMouseDown = (event: MouseEvent): void => {
+ if (this.hasSubItems) {
+ let el = <HTMLElement>event.target;
+ if (!el.classList.contains(this.caretClass)) {
+ this.mouseDownTimestamp = Date.now();
}
- event.stopPropagation();
}
+ };
+
+ /**
+ * The goal is to have one and only one place where we open the dropdown. So that later if we need to change the way
+ * how we do, it will be easier.
+ */
+ private openDropdown():void {
+ this.dropdownIsOpen = true;
+ }
+
+ /**
+ * The goal is to have one and only one place where we close the dropdown. So that later if we need to change the way
+ * how we do, it will be easier.
+ */
+ private closeDropdown():void {
+ this.dropdownIsOpen = false;
+ }
+
+ /**
+ * Just a simple helper method to make the dropdown toggle more easy.
+ * @returns {boolean} It will return the open state of the dropdown;
+ */
+ private toggleDropdown(): boolean {
+ this[this.dropdownIsOpen ? 'closeDropdown' : 'openDropdown']();
+ return this.dropdownIsOpen;
+ }
+
+ /**
+ * The goal is to simply remove the click event listeners from the document.
+ */
+ private removeDocumentClickListener(): void {
+ document.removeEventListener('click', this.onDocumentMouseClick);
+ }
+
+ /**
+ * The main goal if this function is tho handle the item change event on the child dropdown list.
+ * Should update the value and close the dropdown if it is not multiple choice type.
+ * @param {ListItem} options The selected item(s) from the dropdown list.
+ */
+ onDropdownItemChange(options: ListItem) {
+ this.updateValue(options);
+ !this.isMultipleChoice && this.closeDropdown();
}
updateValue(options: ListItem) {