Skip to content

Commit

Permalink
Feature/3217 abandon sortablejs (surveyjs#3227)
Browse files Browse the repository at this point in the history
* surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217

* work for the surveyjs#3217
  • Loading branch information
dmitry-kurmanov authored Aug 30, 2021
1 parent b1fcc2a commit 94715da
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 113 deletions.
27 changes: 16 additions & 11 deletions src/dragdrop/choices.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { ItemValue } from "survey-core";
import { ItemValue } from "../itemvalue";
import { QuestionSelectBase } from "../question_baseselect";
import { DragDropCore } from "./core";

export class DragDropChoices extends DragDropCore {
export class DragDropChoices extends DragDropCore<QuestionSelectBase> {
protected get draggedElementType(): string {
return "item-value";
}

protected getShortcutText(draggedElement: any) {
protected getShortcutText(draggedElement: ItemValue): string {
return draggedElement.text;
}

protected getDropTargetByDataAttributeValue(dataAttributeValue: string) {
protected findDropTargetNodeByDragOverNode(dragOverNode:HTMLElement):HTMLElement {
const result: HTMLElement = dragOverNode.closest(this.dropTargetDataAttributeName);
return result;
}

protected getDropTargetByDataAttributeValue(dataAttributeValue: string): ItemValue {
let dragOverChoice;

dragOverChoice = this.parentElement.choices.filter(
Expand All @@ -20,14 +26,13 @@ export class DragDropChoices extends DragDropCore {
return dragOverChoice;
}

protected isDropTargetValid(dropTarget: any) {
protected isDropTargetValid(dropTarget: ItemValue):boolean {
const choices = this.parentElement.choices;

if (this.dropTarget === this.draggedElement) return false;

// shouldn't allow to drop on "adorners" (selectall, none, other)
if (choices.indexOf(dropTarget) === -1) {
this.banDropHere();
return false;
}
if (choices.indexOf(dropTarget) === -1) return false;

return true;
}
Expand All @@ -40,7 +45,7 @@ export class DragDropChoices extends DragDropCore {
);
}

protected doDrop = () => {
protected doDrop():any {
const isTop = !this.isBottom;
const choices = this.parentElement.choices;
const oldIndex = choices.indexOf(this.draggedElement);
Expand All @@ -56,5 +61,5 @@ export class DragDropChoices extends DragDropCore {
choices.splice(newIndex, 0, this.draggedElement);

return this.parentElement;
};
}
}
73 changes: 42 additions & 31 deletions src/dragdrop/core.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { DragDropInfo } from "src/panel";
import { SurveyModel } from "../survey";
import { Base, EventBase } from "../base";
import { ISurvey } from "../base-interfaces";
import { property } from "../jsonobject";

export abstract class DragDropCore extends Base {
@property({ defaultValue: null, onSet: (val, target: DragDropCore) => {
target.ghostPositionChanged();
} }) isBottom: boolean; //TODO rename isBottom to isShowGhostAtBottomOfDropTarget
export abstract class DragDropCore<T> extends Base {
@property({
defaultValue: null,
onSet: (val, target: DragDropCore<T>) => {
target.ghostPositionChanged();
},
})
isBottom: boolean; //TODO rename isBottom to isShowGhostAtBottomOfDropTarget
public onGhostPositionChanged: EventBase<Base> = new EventBase<Base>();
protected ghostPositionChanged() {
protected ghostPositionChanged(): void {
this.onGhostPositionChanged.fire({}, {});
}

public onBeforeDrop: EventBase<DragDropCore> = new EventBase();
public onAfterDrop: EventBase<DragDropCore> = new EventBase();
public onBeforeDrop: EventBase<DragDropCore<T>> = new EventBase();
public onAfterDrop: EventBase<DragDropCore<T>> = new EventBase();

protected draggedElement: any = null;
protected abstract get draggedElementType(): string;
protected parentElement: any;
protected dropTarget: any = null;
protected get dropTargetDataAttributeName() {
protected parentElement: T;
public dropTarget: any = null;
protected get dropTargetDataAttributeName(): string {
return `[data-sv-drop-target-${this.draggedElementType}]`;
}
protected get survey() {
protected get survey(): SurveyModel {
return this.surveyValue || this.creator.survey;
}

Expand All @@ -39,7 +43,7 @@ export abstract class DragDropCore extends Base {
event: PointerEvent,
draggedElement: any,
parentElement?: any
) {
): void {
this.draggedElement = draggedElement;
this.parentElement = parentElement;

Expand Down Expand Up @@ -77,17 +81,19 @@ export abstract class DragDropCore extends Base {

const isDropTargetValid = this.isDropTargetValid(this.dropTarget, isBottom);

if (this.dropTarget === this.draggedElement || !isDropTargetValid) {
this.doDragOver(dropTargetNode);

if (!isDropTargetValid) {
this.banDropHere();
return;
}

this.allowDropHere = true;
if (this.isDropTargetDoesntChanged(isBottom)) return;

this.isBottom = null; //TODO need for property change trigger with guarantee but it would be better not to watch on isBottom property but reate some event like onValidTargetDragOver
this.isBottom = null; //TODO need for property change trigger with guarantee but it would be better not to watch on isBottom property but have some event like onValidTargetDragOver
this.isBottom = isBottom;
this.doDragOver();
this.afterDragOver(dropTargetNode);
this.prevDropTarget = this.dropTarget;
};

Expand All @@ -101,13 +107,13 @@ export abstract class DragDropCore extends Base {
this.clear();
};

protected isDropTargetDoesntChanged(newIsBottom: boolean) {
protected isDropTargetDoesntChanged(newIsBottom: boolean): boolean {
return (
this.dropTarget === this.prevDropTarget && newIsBottom === this.isBottom
);
}

protected doStartDrag() {}
protected doStartDrag(): void {}
protected abstract getShortcutText(draggedElement: any): string;

private createDraggedElementShortcut(text: string) {
Expand All @@ -118,9 +124,10 @@ export abstract class DragDropCore extends Base {
return draggedElementShortcut;
}

protected doDragOver(): void {}
protected doDragOver(dropTargetNode?: HTMLElement): void {}
protected afterDragOver(dropTargetNode?: HTMLElement): void {}

public getGhostPosition(item: any) {
public getGhostPosition(item: any): string {
if (this.dropTarget !== item) return null;
if (this.isBottom) return "bottom";
return "top";
Expand Down Expand Up @@ -226,15 +233,15 @@ export abstract class DragDropCore extends Base {
this.scrollIntervalId = requestAnimationFrame(repeat);
}

protected banDropHere = () => {
protected banDropHere = (): void => {
this.doBanDropHere();
this.allowDropHere = false;
this.dropTarget = null;
this.draggedElementShortcut.style.cursor = "not-allowed";
this.isBottom = null;
};

protected doBanDropHere = () => {};
protected doBanDropHere = (): void => {};

private getDataAttributeValueByNode(node: HTMLElement) {
let datasetName = "svDropTarget";
Expand All @@ -248,7 +255,7 @@ export abstract class DragDropCore extends Base {
protected getDropTargetByNode(
dropTargetNode: HTMLElement,
event: PointerEvent
) {
): any {
let dataAttributeValue = this.getDataAttributeValueByNode(dropTargetNode);

return this.getDropTargetByDataAttributeValue(
Expand All @@ -264,12 +271,12 @@ export abstract class DragDropCore extends Base {

//TODO adandone unrequired params (survey-elements)
protected abstract getDropTargetByDataAttributeValue(
dataAttributeValue: any,
dataAttributeValue: string,
dropTargetNode?: HTMLElement,
event?: PointerEvent
): any;

protected calculateMiddleOfHTMLElement(HTMLElement: HTMLElement) {
protected calculateMiddleOfHTMLElement(HTMLElement: HTMLElement): number {
const rect = HTMLElement.getBoundingClientRect();
return rect.y + rect.height / 2;
}
Expand All @@ -287,17 +294,21 @@ export abstract class DragDropCore extends Base {
clientY: number
): HTMLElement {
this.draggedElementShortcut.hidden = true;
let dragOverNode = document.elementFromPoint(clientX, clientY);
let dragOverNode = <HTMLElement>document.elementFromPoint(clientX, clientY);
this.draggedElementShortcut.hidden = false;

if (!dragOverNode) return null;

return (
dragOverNode.querySelector(this.dropTargetDataAttributeName) ||
dragOverNode.closest(this.dropTargetDataAttributeName)
);
return this.findDropTargetNodeByDragOverNode(dragOverNode);
}

protected findDropTargetNodeByDragOverNode(dragOverNode:HTMLElement):HTMLElement {
const result: HTMLElement =
dragOverNode.querySelector(this.dropTargetDataAttributeName) ||
dragOverNode.closest(this.dropTargetDataAttributeName);

return result;
}
protected abstract doDrop(): any;

private clear = () => {
Expand All @@ -320,5 +331,5 @@ export abstract class DragDropCore extends Base {
this.scrollIntervalId = null;
};

protected doClear() {}
protected doClear(): void {}
}
23 changes: 12 additions & 11 deletions src/dragdrop/matrix-rows.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ISurvey, QuestionMatrixDropdownRenderedRow } from "survey-core";
import { QuestionMatrixModel, MatrixRowModel } from "../question_matrix";
import { MatrixDropdownRowModelBase, QuestionMatrixDropdownRenderedRow } from "../question_matrixdropdownbase";
import { QuestionMatrixDynamicModel } from "../question_matrixdynamic";
import { DragDropCore } from "./core";
export class DragDropMatrixRows extends DragDropCore {
export class DragDropMatrixRows extends DragDropCore<QuestionMatrixDynamicModel> {
protected get draggedElementType(): string {
return "matrix-row";
}

protected ghostPositionChanged() {
protected ghostPositionChanged(): void {
this.parentElement.renderedTable.rows.forEach(
(renderedRow: QuestionMatrixDropdownRenderedRow) => {
renderedRow.ghostPosition = this.getGhostPosition(
Expand All @@ -17,8 +17,8 @@ export class DragDropMatrixRows extends DragDropCore {
super.ghostPositionChanged();
}

protected getShortcutText(draggedElement: any) {
const matrix = <QuestionMatrixModel>this.parentElement;
protected getShortcutText(draggedElement: any): string {
const matrix = this.parentElement;
const index = matrix.visibleRows.indexOf(draggedElement) + 1;
return (
draggedElement.cells[1].questionValue.value ||
Expand All @@ -29,8 +29,8 @@ export class DragDropMatrixRows extends DragDropCore {

protected getDropTargetByDataAttributeValue(
dataAttributeValue: any
): MatrixRowModel {
const matrix = <QuestionMatrixModel>this.parentElement;
): MatrixDropdownRowModelBase {
const matrix = this.parentElement;
let dropTargetRow;

dropTargetRow = matrix.visibleRows.filter(
Expand All @@ -40,7 +40,8 @@ export class DragDropMatrixRows extends DragDropCore {
return dropTargetRow;
}

protected isDropTargetValid(dropTarget: any) {
protected isDropTargetValid(dropTarget: any): boolean {
if (this.dropTarget === this.draggedElement) return false;
const rows = this.parentElement.visibleRows;
return rows.indexOf(dropTarget) !== -1;
}
Expand All @@ -52,8 +53,8 @@ export class DragDropMatrixRows extends DragDropCore {
);
}

protected doDrop = () => {
const matrix = <QuestionMatrixModel>this.parentElement;
protected doDrop = (): QuestionMatrixDynamicModel => {
const matrix = this.parentElement;
const fromIndex = matrix.visibleRows.indexOf(this.draggedElement);
const toIndex = matrix.visibleRows.indexOf(this.dropTarget);
matrix.moveRowByIndex(fromIndex, toIndex);
Expand Down
44 changes: 44 additions & 0 deletions src/dragdrop/ranking-choices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ItemValue } from "../itemvalue";
import { DragDropChoices } from "./choices";
export class DragDropRankingChoices extends DragDropChoices {
protected getShortcutText(draggedElement: ItemValue): string {
const index = this.parentElement.ran;
return draggedElement.text;
}

protected getDropTargetByDataAttributeValue(
dataAttributeValue: string
): ItemValue {
return this.parentElement.rankingChoices[dataAttributeValue];
}

protected isDropTargetValid(dropTarget: ItemValue): boolean {
const choices = this.parentElement.visibleChoices;

// shouldn't allow to drop on "adorners" (selectall, none, other)
if (choices.indexOf(dropTarget) === -1) return false;

return true;
}

protected afterDragOver(): void {
const choices = this.parentElement.choices;
const dropTargetIndex = choices.indexOf(this.dropTarget);
const draggedElementIndex = choices.indexOf(this.draggedElement);

choices.splice(draggedElementIndex, 1);
choices.splice(dropTargetIndex, 0, this.draggedElement);
this.parentElement.setValue();
}

protected ghostPositionChanged(): void {
this.parentElement.currentDragTarget = this.draggedElement;
super.ghostPositionChanged();
}

protected doDrop = (): any => {
super.doDrop();
this.parentElement.setValue();
return this.parentElement;
};
}
7 changes: 4 additions & 3 deletions src/dragdrop/survey-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { JsonObject, Serializer } from "../jsonobject";
import { PageModel } from "../page";
import { DragDropCore } from "./core";

export class DragDropSurveyElements extends DragDropCore {
export class DragDropSurveyElements extends DragDropCore<any> {
public static newGhostPage: PageModel = null;
public static restrictDragQuestionBetweenPages: boolean = false;
public static edgeHeight: number = 30;
Expand Down Expand Up @@ -78,7 +78,7 @@ export class DragDropSurveyElements extends DragDropCore {
}

// drop to page
let page = this.survey.getPageByName(dataAttributeValue);
let page:any = this.survey.getPageByName(dataAttributeValue);
if (page) {
if (
// TODO we can't drop on not empty page directly for now
Expand Down Expand Up @@ -129,6 +129,7 @@ export class DragDropSurveyElements extends DragDropCore {

protected isDropTargetValid(dropTarget: any, isBottom: boolean) {
if (!dropTarget) return false;
if (this.dropTarget === this.draggedElement) return false;

if (
DragDropSurveyElements.restrictDragQuestionBetweenPages &&
Expand Down Expand Up @@ -187,7 +188,7 @@ export class DragDropSurveyElements extends DragDropCore {
return Math.abs(clientY - middle) >= DragDropSurveyElements.edgeHeight;
}

protected doDragOver() {
protected afterDragOver() {
this.prevIsEdge = this.isEdge;
this.insertGhostElementIntoSurvey();
}
Expand Down
Loading

0 comments on commit 94715da

Please sign in to comment.