Skip to content

Commit

Permalink
refactoring popup model (#8168)
Browse files Browse the repository at this point in the history
* refactoring popup model

* refactoring popup model

---------

Co-authored-by: OlgaLarina <[email protected]>
  • Loading branch information
OlgaLarina and OlgaLarina authored May 3, 2024
1 parent ae5bd0e commit a36740d
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 75 deletions.
13 changes: 7 additions & 6 deletions src/actions/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ export function createDropdownActionModelAdvanced(actionOptions: IAction, listOp
);
listModel.locOwner = locOwner;
listModel.setOnFilterStringChangedCallback(listOptions.onFilterStringChangedCallback);
const innerPopupModel: PopupModel = new PopupModel("sv-list", { model: listModel }, popupOptions?.verticalPosition, popupOptions?.horizontalPosition, popupOptions?.showPointer, popupOptions?.isModal, popupOptions?.onCancel, popupOptions?.onApply, popupOptions?.onHide, popupOptions?.onShow, popupOptions?.cssClass, popupOptions?.title, () => {
listModel.dispose();
});

const options = popupOptions || {};
options.onDispose = () => { listModel.dispose(); };
const innerPopupModel: PopupModel = new PopupModel("sv-list", { model: listModel }, options);
innerPopupModel.displayMode = popupOptions?.displayMode as any;

const newActionOptions = Object.assign({}, actionOptions, {
Expand All @@ -202,7 +203,7 @@ export function getActionDropdownButtonTarget(container: HTMLElement): HTMLEleme

export abstract class BaseAction extends Base implements IAction {
private static renderedId = 1;
private static getNextRendredId(): number { return BaseAction.renderedId ++; }
private static getNextRendredId(): number { return BaseAction.renderedId++; }
private cssClassesValue: any;
private rendredIdValue = BaseAction.getNextRendredId();
private ownerValue: ILocalizableOwner;
Expand Down Expand Up @@ -235,7 +236,7 @@ export abstract class BaseAction extends Base implements IAction {
public get renderedId(): number { return this.rendredIdValue; }
public get owner(): ILocalizableOwner { return this.ownerValue; }
public set owner(val: ILocalizableOwner) {
if(val !== this.owner) {
if (val !== this.owner) {
this.ownerValue = val;
this.locStrsChanged();
}
Expand Down Expand Up @@ -350,7 +351,7 @@ export class Action extends BaseAction implements IAction, ILocalizableOwner {
//Object.assign(this, item) to support IE11
if (!!innerItem) {
for (var key in innerItem) {
if(key === "locTitle" || key === "title" && !!this.locTitle && !!this.title) continue;
if (key === "locTitle" || key === "title" && !!this.locTitle && !!this.title) continue;
(<any>this)[key] = (<any>innerItem)[key];
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/dropdownListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DomDocumentHelper } from "./global_variables_utils";
import { ItemValue } from "./itemvalue";
import { property } from "./jsonobject";
import { ListModel } from "./list";
import { PopupModel } from "./popup";
import { IPopupOptionsBase, PopupModel } from "./popup";
import { Question } from "./question";
import { QuestionDropdownModel } from "./question_dropdown";
import { settings } from "./settings";
Expand Down Expand Up @@ -87,7 +87,8 @@ export class DropdownListModel extends Base {
}

protected createPopup(): void {
this._popupModel = new PopupModel("sv-list", { model: this.listModel }, "bottom", "center", false);
const popupOptions: IPopupOptionsBase = { verticalPosition: "bottom", horizontalPosition: "center", showPointer: false };
this._popupModel = new PopupModel("sv-list", { model: this.listModel }, popupOptions);
this._popupModel.displayMode = IsTouch ? "overlay" : "popup";
this._popupModel.positionMode = "fixed";
this._popupModel.isFocusedContainer = false;
Expand Down Expand Up @@ -153,7 +154,6 @@ export class DropdownListModel extends Base {
protected onHidePopup(): void {
this.resetFilterString();
this.question.suggestedItem = null;
this.listModel.refresh();
}

protected getAvailableItems(): Array<ItemValue> {
Expand Down
24 changes: 8 additions & 16 deletions src/popup-utils.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import { DomDocumentHelper } from "./global_variables_utils";
import { IDialogOptions, PopupModel } from "./popup";
import { IDialogOptions, IPopupOptionsBase, PopupModel } from "./popup";
import { PopupDropdownViewModel } from "./popup-dropdown-view-model";
import { PopupModalViewModel } from "./popup-modal-view-model";
import { PopupBaseViewModel } from "./popup-view-model";

export function createPopupModalViewModel(options: IDialogOptions, rootElement?: HTMLElement): PopupBaseViewModel {
const popupModel = new PopupModel(
options.componentName,
options.data,
"top",
"left",
false,
true,
options.onCancel,
options.onApply,
options.onHide,
options.onShow,
options.cssClass,
options.title
);
popupModel.displayMode = options.displayMode || "popup";
const popupOptions: IPopupOptionsBase = { ...options };
popupOptions.verticalPosition = "top";
popupOptions.horizontalPosition = "left";
popupOptions.showPointer = false;
popupOptions.isModal = true;
popupOptions.displayMode = options.displayMode || "popup";
const popupModel = new PopupModel(options.componentName, options.data, popupOptions);
popupModel.isFocusedContent = options.isFocusedContent ?? true;
const popupViewModel: PopupBaseViewModel = new PopupModalViewModel(popupModel);
if(!!rootElement && !!rootElement.appendChild) {
Expand Down
51 changes: 19 additions & 32 deletions src/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { ConsoleWarnings } from "./console-warnings";
export interface IPopupOptionsBase {
onHide?: () => void;
onShow?: () => void;
onApply?: () => boolean;
onCancel?: () => void;
onDispose?: () => void;
cssClass?: string;
title?: string;
verticalPosition?: VerticalPosition;
Expand All @@ -23,28 +23,25 @@ export interface IDialogOptions extends IPopupOptionsBase {
onApply: () => boolean;
isFocusedContent?: boolean;
}
export interface IPopupModel<T = any> extends IDialogOptions {
contentComponentName: string;
contentComponentData: T;
}

export class PopupModel<T = any> extends Base {
export class PopupModel<T = any> extends Base implements IPopupOptionsBase {
public setWidthByTarget: boolean;
public focusFirstInputSelector = "";
public locale: string;
public onCancel: () => void = () => { };
public onApply: () => boolean = () => { return true; };
public onHide: () => void = () => { };
public onShow: () => void = () => { };
public onDispose: () => void = () => { };

@property() contentComponentName: string;
@property() contentComponentData: T;
@property({ defaultValue: "bottom" }) verticalPosition: VerticalPosition;
@property({ defaultValue: "left" }) horizontalPosition: HorizontalPosition;
@property({ defaultValue: false }) showPointer: boolean;
@property({ defaultValue: true }) showPointer: boolean;
@property({ defaultValue: false }) isModal: boolean;
@property({ defaultValue: true }) isFocusedContent: boolean;
@property({ defaultValue: true }) isFocusedContainer: boolean;
@property({ defaultValue: () => { } }) onCancel: () => void;
@property({ defaultValue: () => { return true; } }) onApply: () => boolean;
@property({ defaultValue: () => { } }) onHide: () => void;
@property({ defaultValue: () => { } }) onShow: () => void;
@property({ defaultValue: "" }) cssClass: string;
@property({ defaultValue: "" }) title: string;
@property({ defaultValue: "auto" }) overlayDisplayMode: "auto" | "overlay" | "dropdown-overlay";
Expand All @@ -63,31 +60,21 @@ export class PopupModel<T = any> extends Base {
constructor(
contentComponentName: string,
contentComponentData: T,
verticalPosition: VerticalPosition = "bottom",
horizontalPosition: HorizontalPosition = "left",
showPointer: boolean = true,
isModal: boolean = false,
onCancel = () => { },
onApply = () => { return true; },
onHide = () => { },
onShow = () => { },
cssClass: string = "",
title: string = "",
private onDispose = () => { }
option1?: IPopupOptionsBase | any,
option2?: any
) {
super();
this.contentComponentName = contentComponentName;
this.contentComponentData = contentComponentData;
this.verticalPosition = verticalPosition;
this.horizontalPosition = horizontalPosition;
this.showPointer = showPointer;
this.isModal = isModal;
this.onCancel = onCancel;
this.onApply = onApply;
this.onHide = onHide;
this.onShow = onShow;
this.cssClass = cssClass;
this.title = title;
if (!!option1 && typeof option1 === "string") {
this.verticalPosition = option1 as VerticalPosition;
this.horizontalPosition = option2;
} else if (!!option1) {
const popupOptions = option1 as IPopupOptionsBase;
for (var key in popupOptions) {
(<any>this)[key] = (<any>popupOptions)[key];
}
}
}
public get isVisible(): boolean {
return this.getPropertyValue("isVisible", false);
Expand Down
2 changes: 1 addition & 1 deletion tests/components/actionbartests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ QUnit.test("Action title in list model", (assert) => {
locTooltipName: "previewText"
});
const list = new ListModel([action1], () => { }, true);
const popupModel = new PopupModel("sv-list", list, "bottom", "center");
const popupModel = new PopupModel("sv-list", list, { verticalPosition: "bottom", horizontalPosition: "center" });
survey.addNavigationItem({ id: "action1", title: "test", popupModel: popupModel });
assert.equal(action1.locTitle.text, "Select All", "take text from en localization");
assert.equal(action1.title, "Select All", "Update action title en localization");
Expand Down
34 changes: 17 additions & 17 deletions tests/components/popuptests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PopupUtils } from "../../src/utils/popup";
import { PopupModel } from "../../src/popup";
import { IPopupOptionsBase, PopupModel } from "../../src/popup";
import { PopupBaseViewModel } from "../../src/popup-view-model";
import { createPopupViewModel } from "../../src/popup-utils";
import { surveyLocalization } from "../../src/surveyStrings";
Expand Down Expand Up @@ -1123,7 +1123,7 @@ QUnit.test("PopupModel and locale", (assert) => {
});

QUnit.test("PopupModel top+center position calculate", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center", showPointer: true });
const targetElement: HTMLElement = document.createElement("button");

targetElement.style.position = "absolute";
Expand Down Expand Up @@ -1153,7 +1153,7 @@ QUnit.test("PopupModel top+center position calculate", (assert) => {
});

QUnit.test("PopupModel top+left position calculate", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "top", "left", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "left", showPointer: true });
const targetElement: HTMLElement = document.createElement("button");

targetElement.style.position = "absolute";
Expand Down Expand Up @@ -1183,7 +1183,7 @@ QUnit.test("PopupModel top+left position calculate", (assert) => {
});

QUnit.test("Fixed PopupModel width calculate setWidthByTarget = false", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = false;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1218,7 +1218,7 @@ QUnit.test("Fixed PopupModel width calculate setWidthByTarget = false", (assert)
});

QUnit.test("Fixed PopupModel width calculate if short content setWidthByTarget = false", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = false;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1253,7 +1253,7 @@ QUnit.test("Fixed PopupModel width calculate if short content setWidthByTarget =
});

QUnit.test("Fixed PopupModel width calculate and overflow content position calculate setWidthByTarget = false", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = false;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1288,7 +1288,7 @@ QUnit.test("Fixed PopupModel width calculate and overflow content position calcu
});

QUnit.test("Fixed PopupModel width calculate", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = true;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1323,7 +1323,7 @@ QUnit.test("Fixed PopupModel width calculate", (assert) => {
});

QUnit.test("Fixed PopupModel width calculate if short content", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = true;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1358,7 +1358,7 @@ QUnit.test("Fixed PopupModel width calculate if short content", (assert) => {
});

QUnit.test("Fixed PopupModel width calculate and overflow content position calculate", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
model.setWidthByTarget = true;
const targetElement: HTMLElement = document.createElement("button");
Expand Down Expand Up @@ -1393,7 +1393,7 @@ QUnit.test("Fixed PopupModel width calculate and overflow content position calcu
});

QUnit.test("PopupViewModel updateOnHiding", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
model.positionMode = "fixed";
const targetElement: HTMLElement = document.createElement("button");

Expand Down Expand Up @@ -1453,7 +1453,7 @@ QUnit.test("PopupViewModel updateOnHiding", (assert) => {
});

QUnit.test("PopupViewModel calculate tablet mode", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
const targetElement: HTMLElement = document.createElement("button");
const viewModel: PopupDropdownViewModel = createPopupViewModel(model, targetElement) as PopupDropdownViewModel;
viewModel["calculateIsTablet"](300, 300);
Expand All @@ -1472,7 +1472,7 @@ QUnit.test("PopupViewModel calculate tablet mode", (assert) => {
targetElement.remove();
});
QUnit.test("PopupViewModel updateOnHiding displayMode = overlay", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "bottom", "center", true);
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "bottom", horizontalPosition: "center", showPointer: true });
const targetElement: HTMLElement = document.createElement("button");

targetElement.style.position = "absolute";
Expand Down Expand Up @@ -1614,7 +1614,7 @@ QUnit.test("Check that modal popup prevents scroll outside", (assert) => {
container.remove();
});
QUnit.test("PopupModel into modal window with translate/transform", (assert) => {
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center");
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center" });
const targetElement: HTMLElement = document.createElement("button");

targetElement.style.position = "absolute";
Expand Down Expand Up @@ -1682,7 +1682,7 @@ QUnit.test("PopupViewModel: check animation's onEnter, onLeave are called correc
settings.animationEnabled = true;
const oldQueueMicrotask = window.queueMicrotask;
window.queueMicrotask = (cb) => cb();
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center");
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center" });
model.onVisibilityChanged.add((_: PopupModel, options: { isVisible: boolean }) => {
logger.log += `->model:isVisible:${options.isVisible}`;
});
Expand All @@ -1707,7 +1707,7 @@ QUnit.test("PopupViewModel: check animation's onEnter, onLeave are called correc

QUnit.test("PopupViewModel: check popupViewModel without container is working correctly", (assert) => {
const logger = { log: "" };
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center");
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center" });
model.onVisibilityChanged.add((_: PopupModel, options: { isVisible: boolean }) => {
logger.log += `->model:isVisible:${options.isVisible}`;
});
Expand All @@ -1725,7 +1725,7 @@ QUnit.test("PopupViewModel: check popupViewModel without container is working co

QUnit.test("PopupViewModel: check popupViewModel is working correctly when shouldRunAnimation is false", (assert) => {
const logger = { log: "" };
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center");
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center" });
model.onVisibilityChanged.add((_: PopupModel, options: { isVisible: boolean }) => {
logger.log += `->model:isVisible:${options.isVisible}`;
});
Expand All @@ -1746,7 +1746,7 @@ QUnit.test("PopupViewModel: check popupViewModel is working correctly when shoul

QUnit.test("PopupViewModel: check getShouldRunAnimation method", (assert) => {
settings.animationEnabled = true;
const model: PopupModel = new PopupModel("sv-list", {}, "top", "center");
const model: PopupModel = new PopupModel("sv-list", {}, { verticalPosition: "top", horizontalPosition: "center" });
const viewModel: TestAnimationPopupViewModel = new TestAnimationPopupViewModel(model);
assert.ok(viewModel.isAnimationEnabled());
model.displayMode = "overlay";
Expand Down

0 comments on commit a36740d

Please sign in to comment.