Merge pull request #6937 from opf/fix/generalize_resizer_component

extract resizing functionality into separate component
pull/6941/head
Henriette Dinger 6 years ago committed by GitHub
commit 2866b0f2e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 74
      frontend/src/app/components/resizer/main-menu-resizer.component.ts
  2. 5
      frontend/src/app/modules/common/openproject-common.module.ts
  3. 4
      frontend/src/app/modules/common/resizer/resizer.component.html
  4. 118
      frontend/src/app/modules/common/resizer/resizer.component.ts

@ -32,11 +32,17 @@ import {Subscription} from 'rxjs';
import {untilComponentDestroyed} from 'ng2-rx-componentdestroyed';
import {MainMenuToggleService} from "core-components/resizer/main-menu-toggle.service";
import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
import {ResizeDelta} from "core-app/modules/common/resizer/resizer.component";
@Component({
selector: 'main-menu-resizer',
template: `
<div class="main-menu--resizer">
<resizer class="main-menu--resizer"
[customHandler]="true"
[cursorClass]="'col-resize'"
(end)="resizeEnd()"
(start)="resizeStart()"
(move)="resizeMove($event)">
<a href="#"
[attr.title]="toggleTitle"
class="main-menu--navigation-toggler"
@ -44,7 +50,7 @@ import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
<i class="icon-resizer-vertical-lines"
aria-hidden="true"></i>
</a>
</div>
</resizer>
`
})
@ -54,8 +60,6 @@ export class MainMenuResizerComponent implements OnInit, OnDestroy {
private localStorageKey:string;
private elementWidth:number;
private oldPosition:number;
private mouseMoveHandler:any;
private mainMenu = jQuery('#main-menu')[0];
public moving:boolean = false;
@ -86,71 +90,17 @@ export class MainMenuResizerComponent implements OnInit, OnDestroy {
this.subscription.unsubscribe();
}
@HostListener('mousedown', ['$event'])
private handleMouseDown(e:MouseEvent) {
// ignore event if it is a click on the collapse/expand handle
var toggler = jQuery('.main-menu--navigation-toggler i')[0];
if (e.target === toggler) {
return;
}
e.preventDefault();
e.stopPropagation();
// Only on left mouse click the resizing is started
if (e.buttons === 1 || e.which === 1) {
// Getting starting position
this.oldPosition = e.clientX;
public resizeStart() {
this.elementWidth = this.mainMenu.clientWidth;
this.moving = true;
// Necessary to encapsulate this to be able to remove the event listener later
this.mouseMoveHandler = this.resizeElement.bind(this, this.mainMenu);
// Change cursor icon
// This is handled via JS to ensure
// that the cursor stays the same even when the mouse leaves the actual resizer.
document.getElementsByTagName("body")[0].setAttribute('style',
'cursor: col-resize !important');
// Enable mouse move
window.addEventListener('mousemove', this.mouseMoveHandler);
}
}
@HostListener('window:mouseup', ['$event'])
private handleMouseUp(e:MouseEvent):boolean {
if (!this.moving) {
return true;
public resizeMove(deltas:ResizeDelta) {
this.toggleService.saveWidth(this.elementWidth + deltas.x);
}
// Disable mouse move
window.removeEventListener('mousemove', this.mouseMoveHandler);
// Change cursor icon back
document.body.style.cursor = 'auto';
this.moving = false;
// save new width in service
this.toggleService.saveWidth();
// Send a event that we resized this element
public resizeEnd() {
const event = new Event(this.resizeEvent);
window.dispatchEvent(event);
return false;
}
private resizeElement(element:HTMLElement, e:MouseEvent) {
e.preventDefault();
e.stopPropagation();
let delta = e.clientX - this.oldPosition;
this.oldPosition = e.clientX;
this.elementWidth = this.elementWidth + delta;
this.toggleService.saveWidth(this.elementWidth);
}
}

@ -60,6 +60,7 @@ import {ColorsAutocompleter} from "core-app/modules/common/colors/colors-autocom
import {DynamicCssService} from "./dynamic-css/dynamic-css.service";
import {MultiToggledSelectComponent} from "core-app/modules/common/multi-toggled-select/multi-toggled-select.component";
import {BannersService} from "core-app/modules/common/enterprise/banners.service";
import {ResizerComponent} from "core-app/modules/common/resizer/resizer.component";
import {TablePaginationComponent} from 'core-components/table-pagination/table-pagination.component';
import {SortHeaderDirective} from 'core-components/wp-table/sort-header/sort-header.directive';
import {ZenModeButtonComponent} from 'core-components/wp-buttons/zen-mode-toggle-button/zen-mode-toggle-button.component';
@ -129,6 +130,8 @@ export function bootstrapModule(injector:Injector) {
// Multi select component
MultiToggledSelectComponent,
ResizerComponent,
TablePaginationComponent,
SortHeaderDirective,
@ -170,6 +173,8 @@ export function bootstrapModule(injector:Injector) {
MultiToggledSelectComponent,
ResizerComponent,
TablePaginationComponent,
SortHeaderDirective,

@ -0,0 +1,4 @@
<div class="resizer"
*ngIf="!customHandler">
</div>
<ng-content></ng-content>

@ -0,0 +1,118 @@
import {
Component,
OnDestroy,
EventEmitter,
Output,
Input,
HostListener} from "@angular/core";
export interface ResizeDelta {
x:number;
y:number;
}
@Component({
selector: 'resizer',
templateUrl: './resizer.component.html'
})
export class ResizerComponent implements OnDestroy {
private oldX:number;
private oldY:number;
private newX:number;
private newY:number;
private mouseMoveHandler:EventListener;
private mouseUpHandler:EventListener;
private resizing = false;
@Output() end:EventEmitter<ResizeDelta> = new EventEmitter();
@Output() start:EventEmitter<null> = new EventEmitter();
@Output() move:EventEmitter<ResizeDelta> = new EventEmitter();
@Input() customHandler = false;
@Input() cursorClass = 'nwse-resize';
ngOnDestroy() {
this.removeEventListener();
}
@HostListener('mousedown', ['$event'])
public startResize(event:MouseEvent) {
event.preventDefault();
event.stopPropagation();
// Only on left mouse click the resizing is started
if (event.buttons === 1 || event.which === 1) {
// Getting starting position
this.oldX = event.clientX;
this.oldY = event.clientY;
this.newX = event.clientX;
this.newY = event.clientY;
this.resizing = true;
this.setResizeCursor();
this.bindEventListener(event);
}
this.start.emit();
}
private onMouseUp(element:HTMLElement, event:MouseEvent) {
this.setAutoCursor();
this.removeEventListener();
let deltas = {
x: this.newX - this.oldX,
y: this.newY - this.oldY
};
this.end.emit(deltas);
}
private onMouseMove(element:HTMLElement, event:MouseEvent) {
event.preventDefault();
event.stopPropagation();
this.newX = event.clientX;
this.newY = event.clientY;
let deltas = {
x: this.newX - this.oldX,
y: this.newY - this.oldY
};
this.move.emit(deltas);
}
// Necessary to encapsulate this to be able to remove the event listener later
private bindEventListener(event:MouseEvent) {
this.mouseMoveHandler = this.onMouseMove.bind(this, event.currentTarget);
this.mouseUpHandler = this.onMouseUp.bind(this, event.currentTarget);
window.addEventListener('mousemove', this.mouseMoveHandler);
window.addEventListener('mouseup', this.mouseUpHandler);
}
private removeEventListener() {
window.removeEventListener('mousemove', this.mouseMoveHandler);
window.removeEventListener('mouseup', this.mouseUpHandler);
}
private setResizeCursor() {
this.setCursor(`${this.cursorClass} !important`);
}
private setAutoCursor() {
this.setCursor('auto');
}
// Change cursor icon
// This is handled via JS to ensure
// that the cursor stays the same even when the mouse leaves the actual resizer.
private setCursor(style:string) {
document.getElementsByTagName("body")[0].setAttribute('style',
`cursor: ${style}`);
}
}
Loading…
Cancel
Save