Skip to content

Commit

Permalink
Merge pull request #91 from cocopon/improve-picker-trigger-button
Browse files Browse the repository at this point in the history
Toggle picker by clicking trigger button
  • Loading branch information
cocopon committed Sep 21, 2020
2 parents c0f1163 + 49fd1c4 commit 81a05a7
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 10 deletions.
22 changes: 17 additions & 5 deletions src/main/js/controller/input/color-picker.ts
@@ -1,5 +1,5 @@
import {NumberFormatter} from '../../formatter/number';
import {TypeUtil} from '../../misc/type-util';
import * as DomUtil from '../../misc/dom-util';
import {Color} from '../../model/color';
import {Foldable} from '../../model/foldable';
import {InputValue} from '../../model/input-value';
Expand Down Expand Up @@ -30,6 +30,7 @@ export class ColorPickerInputController implements InputController<Color> {
public readonly foldable: Foldable;
public readonly pickedColor: PickedColor;
public readonly view: ColorPickerInputView;
public triggerElement: HTMLElement | null = null;
private alphaIcs_: {
palette: APaletteInputController;
text: TextInputController<number>;
Expand Down Expand Up @@ -121,12 +122,23 @@ export class ColorPickerInputController implements InputController<Color> {
return this.pickedColor.value;
}

private onFocusableElementBlur_(e: FocusEvent): void {
private onFocusableElementBlur_(ev: FocusEvent): void {
const elem = this.view.element;
const nextTarget: HTMLElement | null = TypeUtil.forceCast(e.relatedTarget);
if (!nextTarget || !elem.contains(nextTarget)) {
this.foldable.expanded = false;
const nextTarget = DomUtil.findNextTarget(ev);
if (nextTarget && elem.contains(nextTarget)) {
// Next target is in the picker
return;
}
if (
nextTarget &&
nextTarget === this.triggerElement &&
!DomUtil.supportsTouch(elem.ownerDocument)
) {
// Next target is the trigger button
return;
}

this.foldable.expanded = false;
}

private onKeyDown_(ev: KeyboardEvent): void {
Expand Down
1 change: 1 addition & 0 deletions src/main/js/controller/input/color-swatch.ts
Expand Up @@ -42,6 +42,7 @@ export class ColorSwatchInputController implements InputController<Color> {
});
this.view.buttonElement.addEventListener('blur', this.onButtonBlur_);
this.view.buttonElement.addEventListener('click', this.onButtonClick_);
this.pickerIc_.triggerElement = this.view.buttonElement;
}

private onButtonBlur_(e: FocusEvent) {
Expand Down
1 change: 1 addition & 0 deletions src/main/js/controller/input/point-2d-pad-text.ts
Expand Up @@ -59,6 +59,7 @@ export class Point2dPadTextInputController implements InputController<Point2d> {
'click',
this.onPadButtonClick_,
);
this.padIc_.triggerElement = this.view.padButtonElement;
}

private onPadButtonBlur_(e: FocusEvent) {
Expand Down
22 changes: 17 additions & 5 deletions src/main/js/controller/input/point-2d-pad.ts
@@ -1,8 +1,8 @@
import {Point2dConstraint} from '../../constraint/point-2d';
import * as DomUtil from '../../misc/dom-util';
import {NumberUtil} from '../../misc/number-util';
import {PointerHandler, PointerHandlerEvents} from '../../misc/pointer-handler';
import {PointerData} from '../../misc/pointer-handler';
import {TypeUtil} from '../../misc/type-util';
import {Foldable} from '../../model/foldable';
import {InputValue} from '../../model/input-value';
import {Point2d} from '../../model/point-2d';
Expand All @@ -25,6 +25,7 @@ export class Point2dPadInputController implements InputController<Point2d> {
public readonly foldable: Foldable;
public readonly value: InputValue<Point2d>;
public readonly view: Point2dPadInputView;
public triggerElement: HTMLElement | null = null;
private readonly ptHandler_: PointerHandler;
private readonly invertsY_: boolean;
private readonly maxValue_: number;
Expand Down Expand Up @@ -118,12 +119,23 @@ export class Point2dPadInputController implements InputController<Point2d> {
);
}

private onFocusableElementBlur_(e: FocusEvent): void {
private onFocusableElementBlur_(ev: FocusEvent): void {
const elem = this.view.element;
const nextTarget: HTMLElement | null = TypeUtil.forceCast(e.relatedTarget);
if (!nextTarget || !elem.contains(nextTarget)) {
this.foldable.expanded = false;
const nextTarget = DomUtil.findNextTarget(ev);
if (nextTarget && elem.contains(nextTarget)) {
// Next target is in the picker
return;
}
if (
nextTarget &&
nextTarget === this.triggerElement &&
!DomUtil.supportsTouch(elem.ownerDocument)
) {
// Next target is the trigger button
return;
}

this.foldable.expanded = false;
}

private onKeyDown_(ev: KeyboardEvent): void {
Expand Down
15 changes: 15 additions & 0 deletions src/main/js/misc/dom-util.ts
Expand Up @@ -83,3 +83,18 @@ export function indexOfChildElement(element: Element): number {
const children: Element[] = Array.prototype.slice.call(parentElem.children);
return children.indexOf(element);
}

export function findNextTarget(ev: FocusEvent): HTMLElement | null {
if (ev.relatedTarget) {
return TypeUtil.forceCast(ev.relatedTarget);
}
// Workaround for Firefox
if ('explicitOriginalTarget' in ev) {
return (ev as any).explicitOriginalTarget;
}
// TODO: Workaround for Safari
// Safari doesn't set next target for some elements
// (e.g. button, input[type=checkbox], etc.)

return null;
}

0 comments on commit 81a05a7

Please sign in to comment.