ucbuilder
Version:
For Developing Applications with multiple form/usercontrols etc.. In Single BrowserWindow...
259 lines (214 loc) • 8.41 kB
text/typescript
import { uniqOpt, controlOpt, objectOpt, arrayOpt } from "ucbuilder/build/common";
import { CommonEvent } from "ucbuilder/global/commonEvent";
import { transferDataNode,TransferDataNode } from "ucbuilder/global/drag/transferation";
import { newObjectOpt } from "ucbuilder/global/objectOpt";
interface DragElementEventRow {
dragenter: string;
drop: string;
dragleave: string;
dragover: string;
dragNumber: number;
}
type DragEventType = "dragenter" | "drop" | "dragleave" | "dragover";
export type DragEventCaller = (evt: DragEvent) => any;
//type DragingEvent = <K extends keyof HTMLElementEventMap>(eventList: K, handlerCallback: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any)=> void;
export class DragRow {
elements: HTMLElement[] = [];
event = new CommonEvent();
clear(): void {
this.elements.length = 0;
}
}
class DragNode {
source: any = {};
elementList: HTMLElement[] = [];
callback: Function = undefined;
hasBound = false;
generateEvent(elementList: HTMLElement[], callback: Function): void {
if (callback == undefined) {
this.callback = callback;
this.hasBound = true;
}
this.elementList.length = 0;
if (elementList != undefined)
this.elementList.push(...elementList);
}
reFill(htAr: HTMLElement[], clearOldIfExists: boolean, bindEvent: boolean): void {
if (clearOldIfExists)
this.elementList = [];
this.elementList.push(...htAr);
if (bindEvent)
this.addEvent(htAr);
}
addEvent(elements = this.elementList): void {
let _this = this;
elements.forEach(element =>
element.addEventListener(_this.eventName, _this.eventCaller));
}
removeEvent(elements = this.elementList): void {
let _this = this;
elements.forEach(element =>
element.removeEventListener(_this.eventName, _this.eventCaller));
}
fireEvent(ev: DragEvent): void {
if (this.hasBound) {
this.callback(ev);
}
}
main: DragHelper = undefined;
eventName: DragEventType = "dragenter";
eventCaller: DragEventCaller = undefined;
init(main: DragHelper, eventName: DragEventType, eventCaller: DragEventCaller): void {
this.main = main;
this.eventName = eventName;
this.eventCaller = eventCaller;
}
}
const ATTR = Object.freeze({
dragTag: "dragTag"
});
export class DragHelper {
static dragNumberCounter = 0;
static activeDragTag = "";
node = {
drop: new DragNode(),
enter: new DragNode(),
leave: new DragNode(),
over: new DragNode(),
added: false,
addEvent: (): void => {
let nd = this.node;
if (nd.added) return;
nd.drop.addEvent();
nd.enter.addEvent();
nd.leave.addEvent();
nd.over.addEvent();
nd.added = true;
},
removeEvent: (): void => {
let nd = this.node;
if (!nd.added) return;
nd.drop.removeEvent();
nd.enter.removeEvent();
nd.leave.removeEvent();
nd.over.removeEvent();
nd.added = false;
},
init: (): void => {
let nd = this.node;
nd.drop.init(this, "drop", this._drop_EVENT);
nd.enter.init(this, "dragenter", this._dragenter_EVENT);
nd.leave.init(this, "dragleave", this._dragleave_EVENT);
nd.over.init(this, "dragover", this._dragover_EVENT);
}
}
tagName = "";
dragNumber: number = 0;
constructor() {
DragHelper.dragNumberCounter++;
this.dragNumber = DragHelper.dragNumberCounter;
this.tagName = uniqOpt.guidAs_;
this.node.init();
}
//static dragEventCallback = (ev: DragEvent): void => { };
pushElements(htEleAr: HTMLElement[], clearOldIfExists = true): DragHelper {
this.node.enter.reFill(htEleAr, clearOldIfExists, this.node.added);
this.node.leave.reFill(htEleAr, clearOldIfExists, this.node.added);
this.node.over.reFill(htEleAr, clearOldIfExists, this.node.added);
this.node.drop.reFill(htEleAr, clearOldIfExists, this.node.added);
return this;
}
lastDragEvent: DragEvent = undefined;
dragEnter = (callback: DragEventCaller, htEleAr: HTMLElement[]): DragHelper => {
this.node.enter.generateEvent(htEleAr, callback);
return this;
}
dragDrop = (callback: DragEventCaller, htEleAr: HTMLElement[]): DragHelper => {
this.node.drop.generateEvent(htEleAr, callback);
return this;
}
dragLeave = (callback: DragEventCaller, htEleAr: HTMLElement[]): DragHelper => {
this.node.leave.generateEvent(htEleAr, callback);
return this;
}
dragOver = (callback: DragEventCaller, htEleAr: HTMLElement[]): DragHelper => {
this.node.over.generateEvent(htEleAr, callback);
return this;
}
static ON_START = (onStart: DragEventCaller, onEnd?: DragEventCaller): void => {
this._dragstart.on(onStart);
this._dragend.on(onEnd);
// return this;
}
static _dragend = new CommonEvent<(/*ele:HTMLElement,*/ev:DragEvent)=>void>();
static _dragstart = new CommonEvent<(/*ele:HTMLElement,/*/ev:DragEvent)=>void>();
static draggedData = objectOpt.clone(transferDataNode);
static dragResult = false;
start(): void {
this.node.addEvent();
}
stop(): void {
this.node.removeEvent();
}
static DRAG_ME(elements: HTMLElement | HTMLElement[],
callOnDragStart: (evt: DragEvent) => TransferDataNode =
(evt: DragEvent) => {
return {
type: "unknown",
data: undefined,
}
},
callOnDragEnd: (evt: DragEvent) => void = (evt: DragEvent) => { }): void {
let dragstartEventListner = (ev: DragEvent) => {
//this.lastDragEvent = ev;
DragHelper.draggedData = callOnDragStart(ev);
DragHelper._dragstart.fire([/*ev.currentTarget as HTMLElement,*/ev]);
};
// dragHelper._dragend.assign(callOnDragEnd);
let dragendEventListner = (ev: DragEvent) => {
//this.lastDragEvent = ev;
DragHelper._dragend.fire([/*ev.currentTarget as HTMLElement,*/ev]);
callOnDragEnd(ev);
DragHelper.dragResult = false;
};
let ar: HTMLElement[] = controlOpt.getArray(elements);
ar.forEach(element => {
element.addEventListener("dragstart", dragstartEventListner);
element.addEventListener("dragend", dragendEventListner);
});
}
isEntered: boolean = false;
RES: DragElementEventRow = undefined;
lastEnteredElement: any = undefined;
_dragenter_EVENT = (/*ele: HTMLElement, */ev: DragEvent): any => {
this.lastDragEvent = ev;
this.node.enter.fireEvent(ev);
}
_dragover_EVENT = (/*ele: HTMLElement, */ev: DragEvent): any => {
ev.preventDefault();
this.lastDragEvent = ev;
this.node.over.fireEvent(ev);
ev.dataTransfer.dropEffect = "move";
}
_dragleave_EVENT = (/*ele: HTMLElement, */ev: DragEvent): any => {
this.lastDragEvent = ev;
this.node.leave.fireEvent(ev);
}
_drop_EVENT = (/*ele: HTMLElement, */ev: DragEvent): any => {
this.isEntered = false;
this.lastDragEvent = ev;
this.node.drop.fireEvent(ev);
}
getDTag(ele: HTMLElement, eventName: DragEventType): string {
let dTAg = ele.data(ATTR.dragTag);
if (dTAg != undefined) {
if (dTAg.dragNumber != this.dragNumber) dTAg = undefined;
else return dTAg[eventName];
}
if (dTAg == undefined) {
let pe = ele.parentElement;
if (pe != undefined) return this.getDTag(pe, eventName);
}
return dTAg;
}
}