Skip to content

Commit

Permalink
#5925 Raise onDragDropAllow event when user tries to drag into collap…
Browse files Browse the repository at this point in the history
…sed panel (#5926)

* #5925 Raise onDragDropAllow event when user tries to drag into collapsed panel
Fixes #5925

* #5849 Toolbox. Shows a submenu on the button hover.
Fixes #5849

* #5925 - add new event

* #5925 - change event spec

* #5925 - add test and fix

* #5925 - fixed unit test
  • Loading branch information
novikov82 authored Oct 11, 2024
1 parent 5475e77 commit 74ee9b9
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 10 deletions.
10 changes: 9 additions & 1 deletion packages/survey-creator-core/src/components/question.scss
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,15 @@ svc-question,
&>sv-ng-file-question {
display: none;
}

.svc-question__drop-indicator {
display: block;
}
.svc-question__drag-area {
display: flex;
}
.svc-content-wrapper {
display: flex;
}
.sd-element {
&>*:not(.sd-element__header) {
display: none;
Expand Down
3 changes: 3 additions & 0 deletions packages/survey-creator-core/src/creator-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,8 @@ export class SurveyCreatorModel extends Base
*/
public onDragDropAllow: EventBase<SurveyCreatorModel, DragDropAllowEvent> = this.addCreatorEvent<SurveyCreatorModel, DragDropAllowEvent>();

public onDragOverLocationCalculating: EventBase<SurveyCreatorModel, any> = this.addCreatorEvent<SurveyCreatorModel, any>();

/**
* An event that allows you to create a custom message panel.
*
Expand Down Expand Up @@ -1878,6 +1880,7 @@ export class SurveyCreatorModel extends Base
settings.dragDrop.restrictDragQuestionBetweenPages;
this.dragDropSurveyElements = new DragDropSurveyElements(null, this);
this.dragDropSurveyElements.onGetMaxNestedPanels = (): number => { return this.maxNestedPanels; };
this.dragDropSurveyElements.onDragOverLocationCalculating = (options) => { this.onDragOverLocationCalculating.fire(this, options); };
let isDraggedFromToolbox = false;
this.dragDropSurveyElements.onDragStart.add((sender, options) => {
isDraggedFromToolbox = !sender.draggedElement.parent && !sender.draggedElement.isPage;
Expand Down
1 change: 1 addition & 0 deletions packages/survey-creator-core/src/entries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export * from "../presets/presets";
export * from "../presets/presets-properties";
export * from "../presets/presets-tabs";
export * from "../presets/presets-toolbox";
export * from "../survey-elements";

require("../components/property-panel/property-panel-item.scss");
require("../components/property-panel/property-panel.scss");
Expand Down
33 changes: 29 additions & 4 deletions packages/survey-creator-core/src/survey-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,26 @@ export function calculateIsSide(dropTargetNode: HTMLElement, clientX: number) {
const rect = dropTargetNode.getBoundingClientRect();
return clientX - rect.left <= DragDropSurveyElements.edgeHeight || rect.right - clientX <= DragDropSurveyElements.edgeHeight;
}
export function calculateDragOverLocation(clientX: number, clientY: number, dropTargetNode: HTMLElement, dragBeforeOrAfterOnly = false): DragTypeOverMeEnum {
const rect = dropTargetNode.getBoundingClientRect();

export function calculateDragOverLocation(clientX: number, clientY: number, rect: DOMRectInit, direction: "top-bottom" | "left-right" = null): DragTypeOverMeEnum {
const tg = rect.height / rect.width;
const dx = clientX - rect.x;
const dy = clientY - rect.y;

if (dragBeforeOrAfterOnly) {
if (direction == "top-bottom") {
if (dy >= rect.height / 2) {
return DragTypeOverMeEnum.Bottom;
} else {
return DragTypeOverMeEnum.Top;
}
}
if (direction == "left-right") {
if (dx >= rect.width / 2) {
return DragTypeOverMeEnum.Right;
} else {
return DragTypeOverMeEnum.Left;
}
}

if (dy >= tg * dx) {
if (dy >= - tg * dx + rect.height) {
Expand Down Expand Up @@ -68,6 +75,7 @@ export class DragDropSurveyElements extends DragDropCore<any> {
}
protected isDraggedElementSelected: boolean = false;
public onGetMaxNestedPanels: () => number;
public onDragOverLocationCalculating: (options: any) => void;
public get maxNestedPanels(): number { return this.onGetMaxNestedPanels ? this.onGetMaxNestedPanels() : -1; }

// private isRight: boolean;
Expand Down Expand Up @@ -356,12 +364,29 @@ export class DragDropSurveyElements extends DragDropCore<any> {
const dropTarget = this.getDropTargetByNode(dropTargetNode, event);

if (!!oldInsideContainer != !!this.insideContainer) dropTarget.dragTypeOverMe = null;
let dragOverLocation = calculateDragOverLocation(event.clientX, event.clientY, dropTargetNode, !settings.dragDrop.allowDragToTheSameLine || (!!this.draggedElement && this.draggedElement.isPage));
const dropTargetRect = dropTargetNode.getBoundingClientRect();
const calcDirection = !settings.dragDrop.allowDragToTheSameLine || (!!this.draggedElement && this.draggedElement.isPage) ? "top-bottom" : null;
let dragOverLocation = calculateDragOverLocation(event.clientX, event.clientY, dropTargetRect, calcDirection);
if (dropTarget && ((dropTarget.isPanel || dropTarget.isPage) && dropTarget.elements.length === 0 || isPanelDynamic(dropTarget) && dropTarget.template.elements.length == 0)) {
if (dropTarget.isPage || this.insideContainer) {
dragOverLocation = DragTypeOverMeEnum.InsideEmptyPanel;
}
}
const options = {
survey: this.survey,
draggedSurveyElement: this.draggedElement,
dragOverSurveyElement: dropTarget,
clientX: event.clientX,
clientY: event.clientY,
dragOverRect: dropTargetRect,
insideContainer: this.insideContainer,
dragOverLocation
};
if (this.onDragOverLocationCalculating) {
this.onDragOverLocationCalculating(options);
dragOverLocation = options.dragOverLocation;
this.insideContainer = options.insideContainer;
}
const isDropTargetValid = this.isDropTargetValid(
dropTarget,
dropTargetNode,
Expand Down
8 changes: 4 additions & 4 deletions packages/survey-creator-core/tests/components.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -984,15 +984,15 @@ test("QuestionRatingAdornerViewModel allowAdd allowRemove on property readonly",
});

test("calculateDragOverLocation", () => {
let location = calculateDragOverLocation(150, 120, <any>{ getBoundingClientRect: () => ({ x: 100, y: 100, width: 300, height: 100 }) });
let location = calculateDragOverLocation(150, 120, { x: 100, y: 100, width: 300, height: 100 });
expect(location).toBe(DragTypeOverMeEnum.Left);
// creatorSettings.dragDrop.allowDragToTheSameLine = false;
location = calculateDragOverLocation(150, 120, <any>{ getBoundingClientRect: () => ({ x: 100, y: 100, width: 300, height: 100 }) }, true);
location = calculateDragOverLocation(150, 120, { x: 100, y: 100, width: 300, height: 100 }, "top-bottom");
expect(location).toBe(DragTypeOverMeEnum.Top);
location = calculateDragOverLocation(350, 170, <any>{ getBoundingClientRect: () => ({ x: 100, y: 100, width: 300, height: 100 }) }, true);
location = calculateDragOverLocation(350, 170, { x: 100, y: 100, width: 300, height: 100 }, "top-bottom");
expect(location).toBe(DragTypeOverMeEnum.Bottom);
// creatorSettings.dragDrop.allowDragToTheSameLine = true;
location = calculateDragOverLocation(350, 170, <any>{ getBoundingClientRect: () => ({ x: 100, y: 100, width: 300, height: 100 }) });
location = calculateDragOverLocation(350, 170, { x: 100, y: 100, width: 300, height: 100 });
expect(location).toBe(DragTypeOverMeEnum.Right);
});

Expand Down
65 changes: 64 additions & 1 deletion packages/survey-creator-core/tests/dragdrop-elements.tests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DragTypeOverMeEnum, Question, QuestionTextModel, SurveyModel } from "survey-core";
import { DragDropSurveyElements, calculateIsEdge, calculateIsSide } from "../src/survey-elements";
import { DragDropSurveyElements, calculateDragOverLocation, calculateIsEdge, calculateIsSide } from "../src/survey-elements";
import { CreatorTester } from "./creator-tester";

test("calculateVerticalMiddleOfHTMLElement", () => {
Expand Down Expand Up @@ -1141,6 +1141,69 @@ test("Support onDragDropAllow, Bug#4572", (): any => {
expect(counter).toBe(2);
expect(ddHelper["allowDropHere"]).toBeTruthy();
});
test("Test onDragOverLocationCalculating", (): any => {
const creator = new CreatorTester();
creator.JSON = {
"logoPosition": "right",
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
}
]
},
{
"name": "page2",
"elements": [
{
"type": "text",
"name": "question2"
}
]
},
{
"name": "page2",
"elements": [
{
"type": "text",
"name": "question3"
}
]
}
]
};
creator.onDragOverLocationCalculating.add((sender, options) => {
if (options.draggedSurveyElement.name == "question2" && options.insideContainer) {
options.insideContainer = false;
options.dragOverLocation = calculateDragOverLocation(options.clientX, options.clientY, options.dragOverRect, "top-bottom");
}
});
const ddHelper: any = creator.dragDropSurveyElements;
const q1 = creator.survey.getQuestionByName("question1");
const q2 = creator.survey.getQuestionByName("question2");
const q3 = creator.survey.getQuestionByName("question3");
ddHelper.draggedElement = q2;
ddHelper["allowDropHere"] = true;
ddHelper["findDropTargetNodeFromPoint"] = () => ({ getBoundingClientRect: () => ({ x: 10, y: 10, width: 200, height: 100 }) });
ddHelper["getDropTargetByNode"] = () => q1;
ddHelper["isDropTargetValid"] = () => true;
ddHelper.dragOver({ clientX: 40, clientY: 50 });
expect(ddHelper.dragOverLocation).toBe(DragTypeOverMeEnum.Top);
expect(ddHelper.insideContainer).toBeFalsy();
ddHelper.dragOver({ clientX: 100, clientY: 90 });
expect(ddHelper.dragOverLocation).toBe(DragTypeOverMeEnum.Bottom);
expect(ddHelper.insideContainer).toBeFalsy();
ddHelper.draggedElement = q3;
ddHelper.dragOver({ clientX: 40, clientY: 50 });
expect(ddHelper.dragOverLocation).toBe(DragTypeOverMeEnum.Left);
expect(ddHelper.insideContainer).toBeTruthy();
ddHelper.dragOver({ clientX: 100, clientY: 90 });
expect(ddHelper.dragOverLocation).toBe(DragTypeOverMeEnum.Bottom);
expect(ddHelper.insideContainer).toBeTruthy();
});
test("Support onDragDropAllow&allowDropNextToAnother, #5621", (): any => {
const creator = new CreatorTester();
creator.JSON = {
Expand Down

0 comments on commit 74ee9b9

Please sign in to comment.