Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
tsv2013 committed Aug 30, 2023
1 parent ddb54d2 commit a688529
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 43 deletions.
2 changes: 1 addition & 1 deletion src/actions/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,11 +448,11 @@ export class Action extends BaseAction implements IAction, ILocalizableOwner {
return this._component;
}
public dispose(): void {
this.action = undefined;
super.dispose();
if (this.popupModel) {
this.popupModel.dispose();
}
this.action = undefined;
if (!!this.locTitleValue) {
this.locTitleValue.onStringChanged.remove(this.locTitleChanged);
this.locTitleChanged = undefined;
Expand Down
12 changes: 10 additions & 2 deletions src/knockout/components/popup/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ import { ImplementorBase } from "../../kobase";
const template = require("html-loader?interpolate!val-loader!./popup.html");

export class PopupViewModel {
private _popupImplementor: ImplementorBase;
private _popupModelImplementor: ImplementorBase;
constructor(public popupViewModel: PopupBaseViewModel) {
new ImplementorBase(popupViewModel.model);
new ImplementorBase(popupViewModel);
this._popupModelImplementor = new ImplementorBase(popupViewModel.model);
this._popupImplementor = new ImplementorBase(popupViewModel);
popupViewModel.model.onVisibilityChanged.add(this.visibilityChangedHandler);
}
dispose() {
this._popupModelImplementor.dispose();
this._popupModelImplementor = undefined;
this._popupImplementor.dispose();
this._popupImplementor = undefined;
this.popupViewModel.resetComponentElement();
this.popupViewModel.model.onVisibilityChanged.remove(this.visibilityChangedHandler);
this.popupViewModel.dispose();
this.visibilityChangedHandler = undefined;
}
visibilityChangedHandler = (s: any, option: { isVisible: boolean }) => {
if (option.isVisible) {
Expand Down
67 changes: 37 additions & 30 deletions src/popup-dropdown-view-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { settings } from "./settings";

export class PopupDropdownViewModel extends PopupBaseViewModel {
private scrollEventCallBack = (event: any) => {
if(this.isOverlay && IsTouch) {
if (this.isOverlay && IsTouch) {
event.stopPropagation();
event.preventDefault();
return;
}
this.hidePopup();
}
private static readonly tabletSizeBreakpoint = 600;
private calculateIsTablet (windowWidth: number, windowHeight: number) {
private calculateIsTablet(windowWidth: number, windowHeight: number) {
const width = Math.min(windowWidth, windowHeight);
this.isTablet = width >= PopupDropdownViewModel.tabletSizeBreakpoint;
}
Expand All @@ -25,7 +25,7 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
document.documentElement.style.setProperty("--sv-popup-overlay-height", `${visualViewport.height * visualViewport.scale}px`);
}
private resizeWindowCallback = () => {
if(!this.isOverlay) {
if (!this.isOverlay) {
this.updatePosition(true, false);
}
};
Expand All @@ -39,10 +39,10 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
}

private _updatePosition() {
if(!this.targetElement) return;
if (!this.targetElement) return;
const targetElementRect = this.targetElement.getBoundingClientRect();
const popupContainer = <HTMLElement>this.container?.querySelector(this.containerSelector);
if(!popupContainer) return;
if (!popupContainer) return;
const fixedPopupContainer = <HTMLElement>this.container?.querySelector(this.fixedPopupContainer) as HTMLElement;
const scrollContent = <HTMLElement>popupContainer.querySelector(this.scrollingContentSelector);
const popupComputedStyle = window.getComputedStyle(popupContainer);
Expand Down Expand Up @@ -109,7 +109,7 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
}
}
}
if(!!fixedPopupContainer) {
if (!!fixedPopupContainer) {
const rect = fixedPopupContainer.getBoundingClientRect();
pos.top -= rect.top;
pos.left -= rect.left;
Expand All @@ -135,10 +135,10 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
protected getActualHorizontalPosition(): "left" | "center" | "right" {
let actualHorizontalPosition = this.model.horizontalPosition;
let isRtl = !!document && document.defaultView.getComputedStyle(document.body).direction == "rtl";
if(isRtl) {
if(this.model.horizontalPosition === "left") {
if (isRtl) {
if (this.model.horizontalPosition === "left") {
actualHorizontalPosition = "right";
} else if(this.model.horizontalPosition === "right") {
} else if (this.model.horizontalPosition === "right") {
actualHorizontalPosition = "left";
}
}
Expand All @@ -162,23 +162,23 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
@property({ defaultValue: "left" }) popupDirection: string;
@property({ defaultValue: { left: "0px", top: "0px" } }) pointerTarget: IPosition;

private onRecalculatePosition = (_: any, options: { isResetHeight: boolean }) => {
if(!this.isOverlay) {
this.updatePosition(options.isResetHeight);
}
};
private recalculatePositionHandler: (_: any, options: { isResetHeight: boolean }) => void;

constructor(model: PopupModel, public targetElement?: HTMLElement) {
super(model);
this.model.onRecalculatePosition.add(this.onRecalculatePosition);
this.model.onRecalculatePosition.add(this.recalculatePositionHandler);
}
public setComponentElement(componentRoot: HTMLElement, targetElement?: HTMLElement | null): void {
super.setComponentElement(componentRoot);

if(!!componentRoot && !!componentRoot.parentElement && !this.isModal) {
if (!!componentRoot && !!componentRoot.parentElement && !this.isModal) {
this.targetElement = targetElement || componentRoot.parentElement;
}
}
public resetComponentElement() {
super.resetComponentElement();
this.targetElement = undefined;
}
public updateOnShowing(): void {
const { root } = settings.environment;
this.prevActiveElement = <HTMLElement>root.activeElement;
Expand All @@ -191,9 +191,9 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {

this.switchFocus();
window.addEventListener("resize", this.resizeWindowCallback);
if(this.shouldCreateResizeCallback) {
if (this.shouldCreateResizeCallback) {
window.visualViewport.addEventListener("resize", this.resizeEventCallback);
if(this.container) {
if (this.container) {
this.container.addEventListener("touchstart", this.touchStartEventCallback);
this.container.addEventListener("touchmove", this.touchMoveEventCallback);
}
Expand All @@ -207,11 +207,11 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
}

public updatePosition(isResetHeight: boolean, isDelayUpdating = true): void {
if(isResetHeight) {
if (isResetHeight) {
this.height = "auto";
}

if(isDelayUpdating) {
if (isDelayUpdating) {
setTimeout(() => {
this._updatePosition();
}, 1);
Expand All @@ -223,16 +223,16 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
public updateOnHiding(): void {
super.updateOnHiding();
window.removeEventListener("resize", this.resizeWindowCallback);
if(this.shouldCreateResizeCallback) {
if (this.shouldCreateResizeCallback) {
window.visualViewport.removeEventListener("resize", this.resizeEventCallback);
if(this.container) {
if (this.container) {
this.container.removeEventListener("touchstart", this.touchStartEventCallback);
this.container.removeEventListener("touchmove", this.touchMoveEventCallback);
}
}
window.removeEventListener("scroll", this.scrollEventCallBack);

if(!this.isDisposed) {
if (!this.isDisposed) {
this.top = undefined;
this.left = undefined;
this.height = undefined;
Expand All @@ -242,20 +242,27 @@ export class PopupDropdownViewModel extends PopupBaseViewModel {
}

protected onModelChanging(newModel: PopupModel) {
if(!!this.model) {
this.model.onRecalculatePosition.remove(this.onRecalculatePosition);
if (!!this.model) {
this.model.onRecalculatePosition.remove(this.recalculatePositionHandler);
}
if (!this.recalculatePositionHandler) {
this.recalculatePositionHandler = (_: any, options: { isResetHeight: boolean }) => {
if (!this.isOverlay) {
this.updatePosition(options.isResetHeight);
}
};
}
super.onModelChanging(newModel);
newModel.onRecalculatePosition.add(this.onRecalculatePosition);
newModel.onRecalculatePosition.add(this.recalculatePositionHandler);
}

public dispose(): void {
super.dispose();
this.updateOnHiding();
if(!!this.model) {
this.model.onRecalculatePosition.remove(this.onRecalculatePosition);
this.onRecalculatePosition = undefined;
if (!!this.model) {
this.model.onRecalculatePosition.remove(this.recalculatePositionHandler);
this.recalculatePositionHandler = undefined;
}
this.targetElement = undefined;
this.resetComponentElement();
}
}
21 changes: 11 additions & 10 deletions src/popup-view-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class PopupBaseViewModel extends Base {
private createdContainer: HTMLElement;

public getLocale(): string {
if(!!this.locale) return this.locale;
if (!!this.locale) return this.locale;
return super.getLocale();
}
protected hidePopup(): void {
Expand Down Expand Up @@ -103,7 +103,7 @@ export class PopupBaseViewModel extends Base {
return this._model;
}
public set model(model: PopupModel) {
if(this.model) {
if (this.model) {
this.model.unRegisterFunctionOnPropertiesValueChanged(["isVisible"], "PopupBaseViewModel");
}
this.setupModel(model);
Expand Down Expand Up @@ -151,7 +151,7 @@ export class PopupBaseViewModel extends Base {
return this.getLocalizationString("modalCancelButtonText");
}
public get footerToolbar(): ActionContainer {
if(!this.footerToolbarValue) {
if (!this.footerToolbarValue) {
this.createFooterActionBar();
}
return this.footerToolbarValue;
Expand Down Expand Up @@ -182,9 +182,9 @@ export class PopupBaseViewModel extends Base {
}

public switchFocus(): void {
if(this.isFocusedContent) {
if (this.isFocusedContent) {
this.focusFirstInput();
} else if(this.isFocusedContainer) {
} else if (this.isFocusedContainer) {
this.focusContainer();
}
}
Expand Down Expand Up @@ -227,17 +227,17 @@ export class PopupBaseViewModel extends Base {
}
public dispose(): void {
super.dispose();
if(this.model) {
if (this.model) {
this.model.unRegisterFunctionOnPropertiesValueChanged(["isVisible"], "PopupBaseViewModel");
}
if(!!this.createdContainer) {
if (!!this.createdContainer) {
this.createdContainer.remove();
this.createdContainer = undefined;
}
if(!!this.footerToolbarValue) {
if (!!this.footerToolbarValue) {
this.footerToolbarValue.dispose();
}
this.containerElement = undefined;
this.resetComponentElement();
}
public initializePopupContainer(): void {
if (!this.container) {
Expand All @@ -247,12 +247,13 @@ export class PopupBaseViewModel extends Base {
}
}
public setComponentElement(componentRoot: HTMLElement, targetElement?: HTMLElement | null): void {
if(!!componentRoot) {
if (!!componentRoot) {
this.containerElement = componentRoot;
}
}
public resetComponentElement(): void {
this.containerElement = undefined;
this.prevActiveElement = undefined;
}
protected preventScrollOuside(event: any, deltaY: number): void {
let currentElement = event.target;
Expand Down
4 changes: 4 additions & 0 deletions src/react/components/popup/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class Popup extends SurveyElementBase<IPopupProps, any> {
super.componentDidUpdate(prevProps, prevState);
this.setTargetElement();
}
componentWillUnmount(): void {
super.componentWillUnmount();
this.popup.resetComponentElement();
}
shouldComponentUpdate(nextProps: IPopupProps, nextState: any) {
if (!super.shouldComponentUpdate(nextProps, nextState)) return false;
const isNeedUpdate = nextProps.model !== this.popup.model;
Expand Down
1 change: 1 addition & 0 deletions src/utils/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class TooltipManager {
}
dispose() {
this.targetElement.removeEventListener("mousemove", this.onMouseMoveCallback);
this.targetElement = undefined;
}

private onMouseMoveCallback = (e: any) => {
Expand Down

0 comments on commit a688529

Please sign in to comment.