1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import {
AfterContentInit,
ContentChild,
ContentChildren,
Directive,
ElementRef,
Input,
OnDestroy,
QueryList,
} from '@angular/core';
import {FlexDirective} from '@angular/flex-layout';
import {Subscription} from 'rxjs';
import {SplitHandleDirective} from './split-handle.directive';
import {SplitAreaDirective} from './split-area.directive';
@Directive({
selector: '[ngxSplit]',
host: {
class: 'ngx-split'
}
})
export class SplitDirective implements AfterContentInit, OnDestroy {
@Input('ngxSplit') direction = 'row';
@ContentChild(SplitHandleDirective) handle: SplitHandleDirective;
@ContentChildren(SplitAreaDirective) areas: QueryList<SplitAreaDirective>;
private watcher: Subscription;
constructor(private elementRef: ElementRef) {}
ngAfterContentInit(): void {
this.watcher = this.handle.drag.subscribe(this.onDrag.bind(this));
}
ngOnDestroy() {
this.watcher.unsubscribe();
}
/**
* While dragging, continually update the `flex.activatedValue` for each area
* managed by the splitter.
*/
onDrag({x, y}: {x: number, y: number}): void {
const dragAmount = (this.direction === 'row') ? x : y;
this.areas.forEach((area, i) => {
// get the cur flex and the % in px
const flex = (area.flex as FlexDirective);
const delta = (i === 0) ? dragAmount : -dragAmount;
const currentValue = flex.activatedValue;
// Update Flex-Layout value to build/inject new flexbox CSS
flex.activatedValue = `${this.calculateSize(currentValue, delta)}`;
});
}
/**
* Use the pixel delta change to recalculate the area size (%)
* Note: flex value may be '', %, px, or '<grow> <shrink> <basis>'
*/
calculateSize(value: string, delta: number): number {
const containerSizePx = this.elementRef.nativeElement.clientWidth;
const elementSizePx = Math.round(valueToPixel(value, containerSizePx));
const elementSize = ((elementSizePx + delta) / containerSizePx) * 100;
return Math.round(elementSize * 100) / 100;
}
}
/** Convert the pixel or percentage value to a raw pixel float value */
function valueToPixel(value: string, parentWidth: number): number {
const size = parseFloat(value);
return !value.includes('px') ? parentWidth * (size / 100) : size;
}