Revert codestyle changes (#40)

* Revert "7f7efbb94bab8574e42d942ad82d414e007b2970"

Code style changes should probably be part of a PR
This commit is contained in:
Eliot Partridge
2019-08-30 10:53:14 -05:00
committed by GitHub
parent eefd9e9a2c
commit caf70a864f
446 changed files with 70667 additions and 70655 deletions
@@ -1,12 +1,12 @@
import { Directive, AfterViewInit, ElementRef } from '@angular/core';
@Directive({
selector: '[agAutoFocus]'
selector: '[agAutoFocus]'
})
export class AgAutoFocus implements AfterViewInit {
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
setTimeout(() => this.element.nativeElement.focus(), 100);
}
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
setTimeout(() => this.element.nativeElement.focus(), 100);
}
}
+113 -113
View File
@@ -3,138 +3,138 @@ import { noop } from 'lodash';
import { getButton, getX, getY, AnyEvent } from '../../../common/utils';
export interface AgDragEvent {
event: AnyEvent;
type: 'start' | 'drag' | 'end';
x: number;
y: number;
dx: number;
dy: number;
event: AnyEvent;
type: 'start' | 'drag' | 'end';
x: number;
y: number;
dx: number;
dy: number;
}
export interface AgDragOptions {
relative?: 'self' | 'parent';
prevent?: boolean;
relative?: 'self' | 'parent';
prevent?: boolean;
}
export function handleDrag(element: HTMLElement, emit: (event: AgDragEvent) => void, options: AgDragOptions = {}) {
// typeof PointerEvent !== 'undefined'
const eventSets = window.navigator.pointerEnabled ? [
{ down: 'pointerdown', move: 'pointermove', up: 'pointerup' }, // , up2: 'pointercancel' },
] : [
{ down: 'mousedown', move: 'mousemove', up: 'mouseup' },
{ down: 'touchstart', move: 'touchmove', up: 'touchend', up2: 'touchcancel' },
];
const emptyRect = { left: 0, top: 0 };
let rect = emptyRect;
let scrollLeft = 0;
let scrollTop = 0;
let startX = 0;
let startY = 0;
let button = 0;
let dragging = false;
let lastEvent: any;
// typeof PointerEvent !== 'undefined'
const eventSets = window.navigator.pointerEnabled ? [
{ down: 'pointerdown', move: 'pointermove', up: 'pointerup' }, // , up2: 'pointercancel' },
] : [
{ down: 'mousedown', move: 'mousemove', up: 'mouseup' },
{ down: 'touchstart', move: 'touchmove', up: 'touchend', up2: 'touchcancel' },
];
const emptyRect = { left: 0, top: 0 };
let rect = emptyRect;
let scrollLeft = 0;
let scrollTop = 0;
let startX = 0;
let startY = 0;
let button = 0;
let dragging = false;
let lastEvent: any;
function setupScrollAndRect() {
// TODO: fix issue with scroll
switch (options.relative) {
case 'self':
rect = element.getBoundingClientRect();
scrollLeft = -(window.scrollX || window.pageXOffset || 0);
scrollTop = -(window.scrollY || window.pageYOffset || 0);
break;
case 'parent':
rect = element.parentElement!.getBoundingClientRect();
scrollLeft = element.parentElement!.scrollLeft;
scrollTop = element.parentElement!.scrollTop;
break;
default:
rect = emptyRect;
scrollLeft = 0;
scrollTop = 0;
}
}
function setupScrollAndRect() {
// TODO: fix issue with scroll
switch (options.relative) {
case 'self':
rect = element.getBoundingClientRect();
scrollLeft = -(window.scrollX || window.pageXOffset || 0);
scrollTop = -(window.scrollY || window.pageYOffset || 0);
break;
case 'parent':
rect = element.parentElement!.getBoundingClientRect();
scrollLeft = element.parentElement!.scrollLeft;
scrollTop = element.parentElement!.scrollTop;
break;
default:
rect = emptyRect;
scrollLeft = 0;
scrollTop = 0;
}
}
function send(event: AnyEvent, type: 'start' | 'drag' | 'end') {
const x = getX(event);
const y = getY(event);
function send(event: AnyEvent, type: 'start' | 'drag' | 'end') {
const x = getX(event);
const y = getY(event);
emit({
event,
type,
x: x - rect.left + scrollLeft,
y: y - rect.top + scrollTop,
dx: x - startX,
dy: y - startY,
});
}
emit({
event,
type,
x: x - rect.left + scrollLeft,
y: y - rect.top + scrollTop,
dx: x - startX,
dy: y - startY,
});
}
const handlers = eventSets.map(events => {
function move(e: any) {
lastEvent = e;
e.preventDefault();
send(e, 'drag');
}
const handlers = eventSets.map(events => {
function move(e: any) {
lastEvent = e;
e.preventDefault();
send(e, 'drag');
}
function up(e: any) {
if (getButton(e) === button) {
// touchend event does not have x, y coordinates, use last touchmove event instead
if (e.type !== 'touchend' && e.type !== 'touchcancel') {
lastEvent = e;
}
end();
}
}
function up(e: any) {
if (getButton(e) === button) {
// touchend event does not have x, y coordinates, use last touchmove event instead
if (e.type !== 'touchend' && e.type !== 'touchcancel') {
lastEvent = e;
}
end();
}
}
function end() {
send(lastEvent, 'end');
window.removeEventListener(events.move, move);
window.removeEventListener(events.up, up);
events.up2 && window.removeEventListener(events.up2, up);
window.removeEventListener('blur', end);
dragging = false;
}
function end() {
send(lastEvent, 'end');
window.removeEventListener(events.move, move);
window.removeEventListener(events.up, up);
events.up2 && window.removeEventListener(events.up2, up);
window.removeEventListener('blur', end);
dragging = false;
}
function handler(e: any) {
if (!dragging) {
setupScrollAndRect();
dragging = true;
button = getButton(e);
startX = getX(e);
startY = getY(e);
send(e, 'start');
lastEvent = e;
function handler(e: any) {
if (!dragging) {
setupScrollAndRect();
dragging = true;
button = getButton(e);
startX = getX(e);
startY = getY(e);
send(e, 'start');
lastEvent = e;
window.addEventListener(events.move, move);
window.addEventListener(events.up, up);
events.up2 && window.addEventListener(events.up2, up);
window.addEventListener('blur', end);
e.stopPropagation();
window.addEventListener(events.move, move);
window.addEventListener(events.up, up);
events.up2 && window.addEventListener(events.up2, up);
window.addEventListener('blur', end);
e.stopPropagation();
if (options.prevent) {
e.preventDefault();
}
}
}
if (options.prevent) {
e.preventDefault();
}
}
}
element.addEventListener(events.down, handler);
return () => element.removeEventListener(events.down, handler);
});
element.addEventListener(events.down, handler);
return () => element.removeEventListener(events.down, handler);
});
return () => handlers.forEach(f => f());
return () => handlers.forEach(f => f());
}
@Directive({ selector: '[agDrag]' })
export class AgDrag implements OnInit, OnDestroy {
@Input('agDragRelative') relative: 'self' | 'parent' | undefined = undefined;
@Input('agDragPrevent') prevent = false;
@Output('agDrag') drag = new EventEmitter<AgDragEvent>();
private unsubscribe = noop;
constructor(private element: ElementRef) {
}
ngOnInit() {
this.unsubscribe = handleDrag(this.element.nativeElement, e => this.drag.emit(e), this);
}
ngOnDestroy() {
this.unsubscribe();
}
@Input('agDragRelative') relative: 'self' | 'parent' | undefined = undefined;
@Input('agDragPrevent') prevent = false;
@Output('agDrag') drag = new EventEmitter<AgDragEvent>();
private unsubscribe = noop;
constructor(private element: ElementRef) {
}
ngOnInit() {
this.unsubscribe = handleDrag(this.element.nativeElement, e => this.drag.emit(e), this);
}
ngOnDestroy() {
this.unsubscribe();
}
}
+10 -10
View File
@@ -1,17 +1,17 @@
import { Directive, OnInit, ElementRef } from '@angular/core';
@Directive({
selector: 'a[href]'
selector: 'a[href]'
})
export class Anchor implements OnInit {
constructor(private element: ElementRef) {
}
ngOnInit() {
const a = this.element.nativeElement as HTMLAnchorElement;
constructor(private element: ElementRef) {
}
ngOnInit() {
const a = this.element.nativeElement as HTMLAnchorElement;
if (/^(https?|mailto):/.test(a.href) && !a.target) {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer');
}
}
if (/^(https?|mailto):/.test(a.href) && !a.target) {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer');
}
}
}
@@ -2,29 +2,29 @@ import { Directive, Input, Optional } from '@angular/core';
import { NgModel } from '@angular/forms';
@Directive({
selector: '[btnHighlight]',
host: {
'[class.btn-default]': '!on',
'[class.btn-primary]': 'on',
},
selector: '[btnHighlight]',
host: {
'[class.btn-default]': '!on',
'[class.btn-primary]': 'on',
},
})
export class BtnHighlight {
@Input() btnHighlight?: boolean = undefined;
constructor(@Optional() private model?: NgModel) {
}
get on() {
const value = this.btnHighlight;
return (value === true || value === false || !this.model) ? value : !!this.model.value;
}
@Input() btnHighlight?: boolean = undefined;
constructor(@Optional() private model?: NgModel) {
}
get on() {
const value = this.btnHighlight;
return (value === true || value === false || !this.model) ? value : !!this.model.value;
}
}
@Directive({
selector: '[btnHighlightDanger]',
host: {
'[class.btn-default]': '!btnHighlightDanger',
'[class.btn-danger]': 'btnHighlightDanger',
},
selector: '[btnHighlightDanger]',
host: {
'[class.btn-default]': '!btnHighlightDanger',
'[class.btn-danger]': 'btnHighlightDanger',
},
})
export class BtnHighlightDanger {
@Input() btnHighlightDanger = false;
@Input() btnHighlightDanger = false;
}
+169 -169
View File
@@ -6,202 +6,202 @@ import { rect } from '../../../common/rect';
@Injectable({ providedIn: 'root' })
export class DraggableService {
root?: ElementRef;
draggedItem?: any;
activeDropZone?: DraggableDrop<any>;
dropZones: DraggableDrop<any>[] = [];
get rootElement(): HTMLElement {
return this.root ? this.root.nativeElement : document.body;
}
setActiveDropZone(dropZone: DraggableDrop<any> | undefined) {
if (this.activeDropZone !== dropZone) {
if (this.activeDropZone) {
this.activeDropZone.setActive(false);
}
root?: ElementRef;
draggedItem?: any;
activeDropZone?: DraggableDrop<any>;
dropZones: DraggableDrop<any>[] = [];
get rootElement(): HTMLElement {
return this.root ? this.root.nativeElement : document.body;
}
setActiveDropZone(dropZone: DraggableDrop<any> | undefined) {
if (this.activeDropZone !== dropZone) {
if (this.activeDropZone) {
this.activeDropZone.setActive(false);
}
this.activeDropZone = dropZone;
this.activeDropZone = dropZone;
if (this.activeDropZone) {
this.activeDropZone.setActive(true);
}
}
}
startMove(element: HTMLElement, item: any) {
this.setActiveDropZone(undefined);
this.rootElement.appendChild(element);
this.draggedItem = item;
this.initRects();
}
endMove() {
if (this.activeDropZone) {
this.activeDropZone.drop.emit(this.draggedItem);
this.setActiveDropZone(undefined);
}
if (this.activeDropZone) {
this.activeDropZone.setActive(true);
}
}
}
startMove(element: HTMLElement, item: any) {
this.setActiveDropZone(undefined);
this.rootElement.appendChild(element);
this.draggedItem = item;
this.initRects();
}
endMove() {
if (this.activeDropZone) {
this.activeDropZone.drop.emit(this.draggedItem);
this.setActiveDropZone(undefined);
}
this.draggedItem = undefined;
}
addDropZone(dropZone: DraggableDrop<any>) {
this.dropZones.push(dropZone);
this.draggedItem = undefined;
}
addDropZone(dropZone: DraggableDrop<any>) {
this.dropZones.push(dropZone);
if (this.draggedItem) {
this.initRects();
}
}
removeDropZone(dropZone: DraggableDrop<any>) {
removeItem(this.dropZones, dropZone);
if (this.draggedItem) {
this.initRects();
}
}
removeDropZone(dropZone: DraggableDrop<any>) {
removeItem(this.dropZones, dropZone);
if (this.draggedItem) {
this.initRects();
}
if (this.draggedItem) {
this.initRects();
}
if (this.activeDropZone === dropZone) {
this.setActiveDropZone(undefined);
}
}
updateHover(x: number, y: number) {
if (this.draggedItem) {
for (const zone of this.dropZones) {
if (pointInRect(x, y, zone.rect)) {
this.setActiveDropZone(zone);
return;
}
}
if (this.activeDropZone === dropZone) {
this.setActiveDropZone(undefined);
}
}
updateHover(x: number, y: number) {
if (this.draggedItem) {
for (const zone of this.dropZones) {
if (pointInRect(x, y, zone.rect)) {
this.setActiveDropZone(zone);
return;
}
}
this.setActiveDropZone(undefined);
}
}
private initRects() {
this.dropZones.forEach(i => i.initRect());
}
this.setActiveDropZone(undefined);
}
}
private initRects() {
this.dropZones.forEach(i => i.initRect());
}
}
@Component({
selector: 'draggable-outlet',
template: `<div></div>`,
styles: [`:host { position: fixed; top: 0; left: 0; z-index: 10000; }`],
selector: 'draggable-outlet',
template: `<div></div>`,
styles: [`:host { position: fixed; top: 0; left: 0; z-index: 10000; }`],
})
export class DraggableOutlet {
constructor(element: ElementRef, service: DraggableService) {
service.root = element;
}
constructor(element: ElementRef, service: DraggableService) {
service.root = element;
}
}
@Directive({ selector: '[draggableDrop]' })
export class DraggableDrop<T> implements OnInit, OnDestroy {
@Input('draggablePad') pad = 0;
@Output('draggableDrop') drop = new EventEmitter<T>();
rect = rect(0, 0, 0, 0);
constructor(private element: ElementRef, private service: DraggableService) {
}
ngOnInit() {
this.service.addDropZone(this);
}
ngOnDestroy() {
this.service.removeDropZone(this);
}
setActive(active: boolean) {
const element = this.element.nativeElement as HTMLElement;
@Input('draggablePad') pad = 0;
@Output('draggableDrop') drop = new EventEmitter<T>();
rect = rect(0, 0, 0, 0);
constructor(private element: ElementRef, private service: DraggableService) {
}
ngOnInit() {
this.service.addDropZone(this);
}
ngOnDestroy() {
this.service.removeDropZone(this);
}
setActive(active: boolean) {
const element = this.element.nativeElement as HTMLElement;
if (active) {
element.classList.add('draggable-hover');
} else {
element.classList.remove('draggable-hover');
}
}
initRect() {
const element = this.element.nativeElement as HTMLElement;
const clientBounds = element.getBoundingClientRect();
this.rect.x = clientBounds.left - this.pad;
this.rect.y = clientBounds.top - this.pad;
this.rect.w = clientBounds.width + 2 * this.pad;
this.rect.h = clientBounds.height + 2 * this.pad;
}
if (active) {
element.classList.add('draggable-hover');
} else {
element.classList.remove('draggable-hover');
}
}
initRect() {
const element = this.element.nativeElement as HTMLElement;
const clientBounds = element.getBoundingClientRect();
this.rect.x = clientBounds.left - this.pad;
this.rect.y = clientBounds.top - this.pad;
this.rect.w = clientBounds.width + 2 * this.pad;
this.rect.h = clientBounds.height + 2 * this.pad;
}
}
@Directive({
selector: '[draggableItem]',
host: {
'[style.touch-action]': `touchAction`,
}
selector: '[draggableItem]',
host: {
'[style.touch-action]': `touchAction`,
}
})
export class DraggableItem<T> implements OnInit, OnDestroy {
@Input('draggableItem') item: T | undefined;
@Output('draggableDrag') dragStarted = new EventEmitter<void>();
private startX = 0;
private startY = 0;
private draggable?: HTMLElement;
private width = 0;
private height = 0;
private unsubscribeDrag = noop;
private _disabled = false;
constructor(private element: ElementRef, private service: DraggableService) {
}
ngOnInit() {
this.setupDragEvents();
}
ngOnDestroy() {
this.unsubscribeDrag();
}
get touchAction() {
return this.disabled ? 'inherit' : 'none';
}
@Input('draggableDisabled') get disabled() {
return this._disabled;
}
set disabled(value) {
if (this._disabled !== value) {
this._disabled = value;
this.setupDragEvents();
}
}
private setupDragEvents() {
this.unsubscribeDrag();
this.unsubscribeDrag = noop;
@Input('draggableItem') item: T | undefined;
@Output('draggableDrag') dragStarted = new EventEmitter<void>();
private startX = 0;
private startY = 0;
private draggable?: HTMLElement;
private width = 0;
private height = 0;
private unsubscribeDrag = noop;
private _disabled = false;
constructor(private element: ElementRef, private service: DraggableService) {
}
ngOnInit() {
this.setupDragEvents();
}
ngOnDestroy() {
this.unsubscribeDrag();
}
get touchAction() {
return this.disabled ? 'inherit' : 'none';
}
@Input('draggableDisabled') get disabled() {
return this._disabled;
}
set disabled(value) {
if (this._disabled !== value) {
this._disabled = value;
this.setupDragEvents();
}
}
private setupDragEvents() {
this.unsubscribeDrag();
this.unsubscribeDrag = noop;
if (!this.disabled) {
this.unsubscribeDrag = handleDrag(this.element.nativeElement, e => this.drag(e), { prevent: true });
}
}
drag(e: AgDragEvent) {
if (this.item && !this.disabled && !this.draggable && (Math.abs(e.dx) > 5 || Math.abs(e.dy) > 5)) {
const element = this.element.nativeElement as HTMLElement;
const rect = element.getBoundingClientRect();
this.startX = rect.left;
this.startY = rect.top;
this.draggable = element.cloneNode(true) as HTMLElement;
this.draggable.style.position = 'absolute';
this.draggable.style.width = `${rect.width}px`;
this.draggable.style.height = `${rect.height}px`;
this.draggable.style.margin = '0';
this.draggable.classList.add('draggable-dragging');
this.width = rect.width;
this.height = rect.height;
if (!this.disabled) {
this.unsubscribeDrag = handleDrag(this.element.nativeElement, e => this.drag(e), { prevent: true });
}
}
drag(e: AgDragEvent) {
if (this.item && !this.disabled && !this.draggable && (Math.abs(e.dx) > 5 || Math.abs(e.dy) > 5)) {
const element = this.element.nativeElement as HTMLElement;
const rect = element.getBoundingClientRect();
this.startX = rect.left;
this.startY = rect.top;
this.draggable = element.cloneNode(true) as HTMLElement;
this.draggable.style.position = 'absolute';
this.draggable.style.width = `${rect.width}px`;
this.draggable.style.height = `${rect.height}px`;
this.draggable.style.margin = '0';
this.draggable.classList.add('draggable-dragging');
this.width = rect.width;
this.height = rect.height;
const src = element.querySelectorAll('canvas') as NodeListOf<HTMLCanvasElement>;
const dst = this.draggable.querySelectorAll('canvas') as NodeListOf<HTMLCanvasElement>;
const src = element.querySelectorAll('canvas') as NodeListOf<HTMLCanvasElement>;
const dst = this.draggable.querySelectorAll('canvas') as NodeListOf<HTMLCanvasElement>;
for (let i = 0; i < src.length; i++) {
const context = dst.item(i).getContext('2d');
context && context.drawImage(src.item(i), 0, 0);
}
for (let i = 0; i < src.length; i++) {
const context = dst.item(i).getContext('2d');
context && context.drawImage(src.item(i), 0, 0);
}
this.service.startMove(this.draggable, this.item!);
this.dragStarted.emit();
}
this.service.startMove(this.draggable, this.item!);
this.dragStarted.emit();
}
if (this.draggable) {
if (e.type === 'end') {
this.draggable!.parentNode!.removeChild(this.draggable!);
this.draggable = undefined;
this.service.endMove();
} else {
const x = clamp(this.startX + e.dx, 0, window.innerWidth - this.width);
const y = clamp(this.startY + e.dy, 0, window.innerHeight - this.height);
setTransform(this.draggable, `translate3d(${x}px, ${y}px, 0px)`);
this.service.updateHover(e.x, e.y);
}
}
}
if (this.draggable) {
if (e.type === 'end') {
this.draggable!.parentNode!.removeChild(this.draggable!);
this.draggable = undefined;
this.service.endMove();
} else {
const x = clamp(this.startX + e.dx, 0, window.innerWidth - this.width);
const y = clamp(this.startY + e.dy, 0, window.innerHeight - this.height);
setTransform(this.draggable, `translate3d(${x}px, ${y}px, 0px)`);
this.service.updateHover(e.x, e.y);
}
}
}
}
export const draggableComponents = [DraggableOutlet, DraggableItem, DraggableDrop];
+179 -179
View File
@@ -1,227 +1,227 @@
import {
Directive, HostListener, Input, Output, EventEmitter, TemplateRef, ViewContainerRef, ContentChild,
Renderer2, ElementRef, EmbeddedViewRef, Component, Injectable
Directive, HostListener, Input, Output, EventEmitter, TemplateRef, ViewContainerRef, ContentChild,
Renderer2, ElementRef, EmbeddedViewRef, Component, Injectable
} from '@angular/core';
import { uniqueId } from 'lodash';
import { focusFirstElement } from '../../../client/htmlUtils';
@Injectable({ providedIn: 'root' })
export class DropdownOutletService {
viewContainer?: ViewContainerRef;
rootElement?: HTMLElement;
viewContainer?: ViewContainerRef;
rootElement?: HTMLElement;
}
@Component({
selector: 'dropdown-outlet',
template: `<ng-template></ng-template>`,
selector: 'dropdown-outlet',
template: `<ng-template></ng-template>`,
})
export class DropdownOutlet {
constructor(service: DropdownOutletService, viewContainer: ViewContainerRef, element: ElementRef) {
service.viewContainer = viewContainer;
service.rootElement = element.nativeElement.parentElement;
}
constructor(service: DropdownOutletService, viewContainer: ViewContainerRef, element: ElementRef) {
service.viewContainer = viewContainer;
service.rootElement = element.nativeElement.parentElement;
}
}
@Directive({
selector: '[dropdownMenu]',
selector: '[dropdownMenu]',
})
export class DropdownMenu {
ref?: EmbeddedViewRef<any>;
id = uniqueId('dropdown-menu-');
private onClose?: () => void;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private renderer: Renderer2,
private service: DropdownOutletService,
) {
}
private get root(): HTMLElement {
return this.ref && this.ref.rootNodes[0];
}
open(useOutlet: boolean, rootElement: HTMLElement) {
if (!this.ref) {
if (useOutlet) {
this.ref = this.service.viewContainer!.createEmbeddedView(this.templateRef);
} else {
this.ref = this.viewContainer.createEmbeddedView(this.templateRef);
}
ref?: EmbeddedViewRef<any>;
id = uniqueId('dropdown-menu-');
private onClose?: () => void;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private renderer: Renderer2,
private service: DropdownOutletService,
) {
}
private get root(): HTMLElement {
return this.ref && this.ref.rootNodes[0];
}
open(useOutlet: boolean, rootElement: HTMLElement) {
if (!this.ref) {
if (useOutlet) {
this.ref = this.service.viewContainer!.createEmbeddedView(this.templateRef);
} else {
this.ref = this.viewContainer.createEmbeddedView(this.templateRef);
}
const { renderer, root } = this;
const { renderer, root } = this;
renderer.addClass(root, 'show');
renderer.setAttribute(root, 'id', this.id);
renderer.addClass(root, 'show');
renderer.setAttribute(root, 'id', this.id);
if (useOutlet) {
const positionMenu = () => {
const rect = rootElement.getBoundingClientRect();
const menuRect = root.getBoundingClientRect();
let transform: string;
if (useOutlet) {
const positionMenu = () => {
const rect = rootElement.getBoundingClientRect();
const menuRect = root.getBoundingClientRect();
let transform: string;
if ((rect.bottom + menuRect.height) > window.innerHeight) {
transform = `translate3d(${Math.round(rect.left)}px, ${Math.round(rect.top - menuRect.height)}px, 0)`;
renderer.addClass(root, 'dropdown-menu-up');
} else {
transform = `translate3d(${Math.round(rect.left)}px, ${Math.round(rect.bottom)}px, 0)`;
renderer.removeClass(root, 'dropdown-menu-up');
}
if ((rect.bottom + menuRect.height) > window.innerHeight) {
transform = `translate3d(${Math.round(rect.left)}px, ${Math.round(rect.top - menuRect.height)}px, 0)`;
renderer.addClass(root, 'dropdown-menu-up');
} else {
transform = `translate3d(${Math.round(rect.left)}px, ${Math.round(rect.bottom)}px, 0)`;
renderer.removeClass(root, 'dropdown-menu-up');
}
renderer.setStyle(root, 'transform', transform);
};
renderer.setStyle(root, 'transform', transform);
};
renderer.addClass(root, 'dropdown-in-outlet');
positionMenu();
renderer.addClass(root, 'dropdown-in-outlet');
positionMenu();
const closeDropdown = () => {
this.close();
};
const closeDropdown = () => {
this.close();
};
document.addEventListener('scroll', closeDropdown, true);
window.addEventListener('resize', closeDropdown, true);
document.addEventListener('scroll', closeDropdown, true);
window.addEventListener('resize', closeDropdown, true);
this.onClose = () => {
document.removeEventListener('scroll', closeDropdown, true);
window.removeEventListener('resize', closeDropdown, true);
};
}
}
}
close() {
if (this.ref) {
this.ref.destroy();
this.ref = undefined;
}
this.onClose = () => {
document.removeEventListener('scroll', closeDropdown, true);
window.removeEventListener('resize', closeDropdown, true);
};
}
}
}
close() {
if (this.ref) {
this.ref.destroy();
this.ref = undefined;
}
if (this.onClose) {
this.onClose();
this.onClose = undefined;
}
}
checkTarget(e: Event) {
return this.root && this.root.contains(e.target as any);
}
focusFirstElement() {
if (this.root) {
focusFirstElement(this.root);
}
}
if (this.onClose) {
this.onClose();
this.onClose = undefined;
}
}
checkTarget(e: Event) {
return this.root && this.root.contains(e.target as any);
}
focusFirstElement() {
if (this.root) {
focusFirstElement(this.root);
}
}
}
@Directive({
selector: '[dropdown]',
exportAs: 'ag-dropdown',
host: {
'[class.show]': 'isOpen',
},
selector: '[dropdown]',
exportAs: 'ag-dropdown',
host: {
'[class.show]': 'isOpen',
},
})
export class Dropdown {
dropdownToggle?: DropdownToggle;
@ContentChild(DropdownMenu, { static: false }) menu!: DropdownMenu;
@Input() autoClose: boolean | 'outsideClick' = true;
@Input() preventAutoCloseOnOutlet = false;
@Input() hookToCanvas = false;
@Input() focusOnOpen = true;
@Input() focusOnClose = true;
@Input() useOutlet = false;
@Input() isOpen = false;
@Output() isOpenChange = new EventEmitter<boolean>();
get menuId() {
return this.isOpen ? this.menu.id : '';
}
constructor(private element: ElementRef, private service: DropdownOutletService) {
}
open() {
if (!this.isOpen) {
this.isOpen = true;
this.isOpenChange.emit(true);
this.menu.open(this.useOutlet, this.element.nativeElement);
dropdownToggle?: DropdownToggle;
@ContentChild(DropdownMenu, { static: false }) menu!: DropdownMenu;
@Input() autoClose: boolean | 'outsideClick' = true;
@Input() preventAutoCloseOnOutlet = false;
@Input() hookToCanvas = false;
@Input() focusOnOpen = true;
@Input() focusOnClose = true;
@Input() useOutlet = false;
@Input() isOpen = false;
@Output() isOpenChange = new EventEmitter<boolean>();
get menuId() {
return this.isOpen ? this.menu.id : '';
}
constructor(private element: ElementRef, private service: DropdownOutletService) {
}
open() {
if (!this.isOpen) {
this.isOpen = true;
this.isOpenChange.emit(true);
this.menu.open(this.useOutlet, this.element.nativeElement);
setTimeout(() => {
document.addEventListener('click', this.closeHandler);
document.addEventListener('keydown', this.closeHandler);
setTimeout(() => {
document.addEventListener('click', this.closeHandler);
document.addEventListener('keydown', this.closeHandler);
if (this.focusOnOpen) {
this.menu.focusFirstElement();
}
if (this.focusOnOpen) {
this.menu.focusFirstElement();
}
if (this.hookToCanvas) {
const canvas = document.getElementById('canvas');
if (this.hookToCanvas) {
const canvas = document.getElementById('canvas');
if (canvas) {
canvas.addEventListener('touchstart', this.canvasCloseHandler);
canvas.addEventListener('mousedown', this.canvasCloseHandler);
}
}
});
}
}
close() {
if (this.isOpen) {
this.isOpen = false;
this.isOpenChange.emit(false);
this.menu.close();
if (canvas) {
canvas.addEventListener('touchstart', this.canvasCloseHandler);
canvas.addEventListener('mousedown', this.canvasCloseHandler);
}
}
});
}
}
close() {
if (this.isOpen) {
this.isOpen = false;
this.isOpenChange.emit(false);
this.menu.close();
if (this.focusOnClose && this.dropdownToggle) {
this.dropdownToggle.focus();
}
if (this.focusOnClose && this.dropdownToggle) {
this.dropdownToggle.focus();
}
document.removeEventListener('click', this.closeHandler);
document.removeEventListener('keydown', this.closeHandler);
document.removeEventListener('click', this.closeHandler);
document.removeEventListener('keydown', this.closeHandler);
if (this.hookToCanvas) {
const canvas = document.getElementById('canvas');
if (this.hookToCanvas) {
const canvas = document.getElementById('canvas');
if (canvas) {
canvas.removeEventListener('touchstart', this.canvasCloseHandler);
canvas.removeEventListener('mousedown', this.canvasCloseHandler);
}
}
}
}
toggle() {
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
private closeHandler: any = (e: KeyboardEvent) => {
if (
!e.keyCode
&& (this.autoClose || (this.dropdownToggle && this.dropdownToggle.checkTarget(e)))
&& !(this.preventAutoCloseOnOutlet && this.service.rootElement && this.service.rootElement.contains(e.target as any))
&& !(this.autoClose === 'outsideClick' && this.menu.checkTarget(e))
) {
this.close();
} else if (this.autoClose && e.keyCode === 27) { // esc
this.close();
}
}
private canvasCloseHandler: any = () => this.close();
if (canvas) {
canvas.removeEventListener('touchstart', this.canvasCloseHandler);
canvas.removeEventListener('mousedown', this.canvasCloseHandler);
}
}
}
}
toggle() {
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
private closeHandler: any = (e: KeyboardEvent) => {
if (
!e.keyCode
&& (this.autoClose || (this.dropdownToggle && this.dropdownToggle.checkTarget(e)))
&& !(this.preventAutoCloseOnOutlet && this.service.rootElement && this.service.rootElement.contains(e.target as any))
&& !(this.autoClose === 'outsideClick' && this.menu.checkTarget(e))
) {
this.close();
} else if (this.autoClose && e.keyCode === 27) { // esc
this.close();
}
}
private canvasCloseHandler: any = () => this.close();
}
@Directive({
selector: '[dropdownToggle]',
host: {
'aria-haspopup': 'true',
'[attr.aria-expanded]': 'dropdown.isOpen',
'[attr.aria-controls]': 'dropdown.isOpen ? dropdown.menuId : undefined',
},
selector: '[dropdownToggle]',
host: {
'aria-haspopup': 'true',
'[attr.aria-expanded]': 'dropdown.isOpen',
'[attr.aria-controls]': 'dropdown.isOpen ? dropdown.menuId : undefined',
},
})
export class DropdownToggle {
constructor(private element: ElementRef, public dropdown: Dropdown) {
dropdown.dropdownToggle = this;
}
@HostListener('click')
click() {
this.dropdown.toggle();
}
checkTarget(e: Event) {
return this.element.nativeElement.contains(e.target);
}
focus() {
this.element.nativeElement.focus();
}
constructor(private element: ElementRef, public dropdown: Dropdown) {
dropdown.dropdownToggle = this;
}
@HostListener('click')
click() {
this.dropdown.toggle();
}
checkTarget(e: Event) {
return this.element.nativeElement.contains(e.target);
}
focus() {
this.element.nativeElement.focus();
}
}
export const dropdownDirectives = [Dropdown, DropdownToggle, DropdownMenu, DropdownOutlet];
+15 -15
View File
@@ -1,22 +1,22 @@
import { Directive, ElementRef, Input, HostListener, HostBinding, Output, EventEmitter } from '@angular/core';
@Directive({
selector: '[fixToTop]',
selector: '[fixToTop]',
})
export class FixToTop {
@Input() fixToTopOffset = 0;
@Output() fixToTop = new EventEmitter<boolean>();
@HostBinding('class.fixed-to-top') fixed = false;
constructor(private element: ElementRef) {
}
@HostListener('window:scroll')
scroll() {
const element = this.element.nativeElement as HTMLElement;
const { top } = element.getBoundingClientRect();
@Input() fixToTopOffset = 0;
@Output() fixToTop = new EventEmitter<boolean>();
@HostBinding('class.fixed-to-top') fixed = false;
constructor(private element: ElementRef) {
}
@HostListener('window:scroll')
scroll() {
const element = this.element.nativeElement as HTMLElement;
const { top } = element.getBoundingClientRect();
if (this.fixed !== top < this.fixToTopOffset) {
this.fixed = top < this.fixToTopOffset;
this.fixToTop.emit(this.fixed);
}
}
if (this.fixed !== top < this.fixToTopOffset) {
this.fixed = top < this.fixToTopOffset;
this.fixToTop.emit(this.fixed);
}
}
}
@@ -1,15 +1,15 @@
import { Directive, AfterViewInit, ElementRef } from '@angular/core';
@Directive({
selector: '[focusTitle]',
host: {
'tabindex': '-1',
},
selector: '[focusTitle]',
host: {
'tabindex': '-1',
},
})
export class FocusTitle implements AfterViewInit {
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
setTimeout(() => this.element.nativeElement.focus());
}
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
setTimeout(() => this.element.nativeElement.focus());
}
}
@@ -3,55 +3,55 @@ import { isParentOf, focusFirstElement, findFocusableElements } from '../../../c
import { isMobile } from '../../../client/data';
@Directive({
selector: '[focusTrap]',
selector: '[focusTrap]',
})
export class FocusTrap implements OnInit, OnDestroy {
private on = true;
private lastActiveElement?: HTMLElement;
@Input() set focusTrap(value: boolean) {
if (this.on !== value) {
this.on = value;
this.update();
}
}
constructor(private element: ElementRef) {
}
ngOnInit() {
this.update();
}
ngOnDestroy() {
this.focusTrap = false;
}
private update() {
if (!isMobile) {
if (this.on) {
this.lastActiveElement = document.activeElement as HTMLElement;
document.addEventListener('focusin', this.focus);
private on = true;
private lastActiveElement?: HTMLElement;
@Input() set focusTrap(value: boolean) {
if (this.on !== value) {
this.on = value;
this.update();
}
}
constructor(private element: ElementRef) {
}
ngOnInit() {
this.update();
}
ngOnDestroy() {
this.focusTrap = false;
}
private update() {
if (!isMobile) {
if (this.on) {
this.lastActiveElement = document.activeElement as HTMLElement;
document.addEventListener('focusin', this.focus);
if (!isParentOf(this.element.nativeElement, this.lastActiveElement)) {
setTimeout(() => this.lastActiveElement = focusFirstElement(this.element.nativeElement));
}
} else {
this.lastActiveElement = undefined;
document.removeEventListener('focusin', this.focus);
}
}
}
private focus = (e: Event) => {
if (isParentOf(this.element.nativeElement, e.target as any)) {
this.lastActiveElement = e.target as any;
} else {
const focusable = findFocusableElements(this.element.nativeElement);
if (!isParentOf(this.element.nativeElement, this.lastActiveElement)) {
setTimeout(() => this.lastActiveElement = focusFirstElement(this.element.nativeElement));
}
} else {
this.lastActiveElement = undefined;
document.removeEventListener('focusin', this.focus);
}
}
}
private focus = (e: Event) => {
if (isParentOf(this.element.nativeElement, e.target as any)) {
this.lastActiveElement = e.target as any;
} else {
const focusable = findFocusableElements(this.element.nativeElement);
if (focusable.length) {
if (this.lastActiveElement === focusable[0]) {
this.lastActiveElement = focusable[focusable.length - 1];
} else {
this.lastActiveElement = focusable[0];
}
if (focusable.length) {
if (this.lastActiveElement === focusable[0]) {
this.lastActiveElement = focusable[focusable.length - 1];
} else {
this.lastActiveElement = focusable[0];
}
this.lastActiveElement.focus();
}
}
}
this.lastActiveElement.focus();
}
}
}
}
@@ -4,57 +4,57 @@ import { hasFeatureFlag, featureFlagsChanged } from '../../../client/clientUtils
import { Model } from '../../services/model';
@Directive({
selector: '[hasFeature]',
selector: '[hasFeature]',
})
export class HasFeature implements AfterViewInit, OnDestroy {
private subscriptions: Subscription[] = [];
private showing = false;
private _flag: string | undefined = undefined;
private _orMod = false;
private _alsoIf = true;
private ref?: EmbeddedViewRef<any>;
constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef, private model: Model) {
}
ngAfterViewInit() {
this.subscriptions.push(featureFlagsChanged.subscribe(() => this.update()));
this.subscriptions.push(this.model.accountChanged.subscribe(() => this.update()));
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
@Input()
set hasFeature(value: string | undefined) {
if (this._flag !== value) {
this._flag = value;
this.update();
}
}
@Input()
set hasFeatureOrMod(value: boolean) {
if (this._orMod !== value) {
this._orMod = value;
this.update();
}
}
@Input()
set hasFeatureAlso(value: boolean) {
if (this._alsoIf !== value) {
this._alsoIf = value;
this.update();
}
}
private update() {
const show = this._alsoIf && (hasFeatureFlag(this._flag as any) || (this._orMod && this.model.isMod));
private subscriptions: Subscription[] = [];
private showing = false;
private _flag: string | undefined = undefined;
private _orMod = false;
private _alsoIf = true;
private ref?: EmbeddedViewRef<any>;
constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef, private model: Model) {
}
ngAfterViewInit() {
this.subscriptions.push(featureFlagsChanged.subscribe(() => this.update()));
this.subscriptions.push(this.model.accountChanged.subscribe(() => this.update()));
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
@Input()
set hasFeature(value: string | undefined) {
if (this._flag !== value) {
this._flag = value;
this.update();
}
}
@Input()
set hasFeatureOrMod(value: boolean) {
if (this._orMod !== value) {
this._orMod = value;
this.update();
}
}
@Input()
set hasFeatureAlso(value: boolean) {
if (this._alsoIf !== value) {
this._alsoIf = value;
this.update();
}
}
private update() {
const show = this._alsoIf && (hasFeatureFlag(this._flag as any) || (this._orMod && this.model.isMod));
if (this.showing !== show) {
this.showing = show;
if (this.showing !== show) {
this.showing = show;
if (show) {
this.ref = this.ref || this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
this.ref = undefined;
}
}
}
if (show) {
this.ref = this.ref || this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
this.ref = undefined;
}
}
}
}
@@ -3,19 +3,19 @@ import { uniqueId } from 'lodash';
import { findParentElement } from '../../../client/htmlUtils';
@Directive({
selector: '[labelledBy]',
selector: '[labelledBy]',
})
export class LabelledBy implements OnInit {
@Input('labelledBy') selector!: string;
constructor(private element: ElementRef) {
}
ngOnInit() {
const element = this.element.nativeElement as HTMLElement;
const target = findParentElement(element, this.selector);
const id = element.id = element.id || uniqueId('labelled-by-');
@Input('labelledBy') selector!: string;
constructor(private element: ElementRef) {
}
ngOnInit() {
const element = this.element.nativeElement as HTMLElement;
const target = findParentElement(element, this.selector);
const id = element.id = element.id || uniqueId('labelled-by-');
if (target) {
target.setAttribute('aria-labelledby', id);
}
}
if (target) {
target.setAttribute('aria-labelledby', id);
}
}
}
@@ -2,13 +2,13 @@ import { Directive, HostBinding } from '@angular/core';
import { RouterLinkActive } from '@angular/router';
@Directive({
selector: '[linkCurrent]',
selector: '[linkCurrent]',
})
export class LinkCurrent {
constructor(private routerLinkActive: RouterLinkActive) {
}
@HostBinding('attr.aria-current')
get current() {
return this.routerLinkActive.isActive ? 'true' : undefined;
}
constructor(private routerLinkActive: RouterLinkActive) {
}
@HostBinding('attr.aria-current')
get current() {
return this.routerLinkActive.isActive ? 'true' : undefined;
}
}
@@ -2,11 +2,11 @@ import { Directive, Input, HostBinding } from '@angular/core';
import { getUrl } from '../../../client/rev';
@Directive({
selector: '[revSrc]',
selector: '[revSrc]',
})
export class RevSrc {
@HostBinding() get src() {
return this.revSrc && getUrl(this.revSrc);
}
@Input() revSrc?: string;
@HostBinding() get src() {
return this.revSrc && getUrl(this.revSrc);
}
@Input() revSrc?: string;
}
@@ -4,23 +4,23 @@ import { Tabset } from '../tabset/tabset';
import { StorageService } from '../../services/storageService';
@Directive({
selector: '[saveActiveTab]',
selector: '[saveActiveTab]',
})
export class SaveActiveTab implements OnInit, OnDestroy {
@Input('saveActiveTab') key!: string;
private subscription?: Subscription;
constructor(@Host() private tabset: Tabset, private storage: StorageService) {
}
ngOnInit() {
// this.tabset.activeIndex = parseInt(this.storage.getItem(this.key) || '0', 10);
this.tabset.select(parseInt(this.storage.getItem(this.key) || '0', 10));
this.subscription = this.tabset.activeIndexChange.subscribe((i: number) => {
this.storage.setItem(this.key, i.toString());
});
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
@Input('saveActiveTab') key!: string;
private subscription?: Subscription;
constructor(@Host() private tabset: Tabset, private storage: StorageService) {
}
ngOnInit() {
// this.tabset.activeIndex = parseInt(this.storage.getItem(this.key) || '0', 10);
this.tabset.select(parseInt(this.storage.getItem(this.key) || '0', 10));
this.subscription = this.tabset.activeIndexChange.subscribe((i: number) => {
this.storage.setItem(this.key, i.toString());
});
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}