Skip to content

Commit

Permalink
resolve #7857 Move all calls with document and window into separate f…
Browse files Browse the repository at this point in the history
…ile and add a rule to eslint
  • Loading branch information
OlgaLarina committed Mar 7, 2024
1 parent ddb86f5 commit 190db6d
Show file tree
Hide file tree
Showing 40 changed files with 316 additions and 155 deletions.
22 changes: 22 additions & 0 deletions src/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"rules": {
"no-restricted-properties": [
"error",
{
"object": "window",
"property": "document"
}
],
"no-restricted-globals": [
"error",
{
"name": "document",
"message": "Do not use document into survey-core. Use methods from DomDocumentHelper"
},
{
"name": "window",
"message": "Do not use window into survey-core. Use method from DomWindowHelper"
}
]
}
}
9 changes: 7 additions & 2 deletions src/dragdrop/choices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ImageItemValue } from "../question_imagepicker";
import { ItemValue } from "../itemvalue";
import { QuestionSelectBase } from "../question_baseselect";
import { DragDropCore } from "./core";
import { DomDocumentHelper } from "../global_variables_utils";

export class DragDropChoices extends DragDropCore<QuestionSelectBase> {
private imagepickerControlsNode: HTMLElement;
Expand All @@ -19,7 +20,9 @@ export class DragDropChoices extends DragDropCore<QuestionSelectBase> {
if (this.parentElement.getType() === "imagepicker") {
return this.createImagePickerShortcut(this.draggedElement, text, draggedElementNode, event);
}
const draggedElementShortcut: any = document.createElement("div");
const draggedElementShortcut: any = DomDocumentHelper.createElement("div");
if(!draggedElementShortcut) return;

// draggedElementShortcut.innerText = text;
draggedElementShortcut.style.cssText = `
cursor: grabbing;
Expand Down Expand Up @@ -66,7 +69,9 @@ export class DragDropChoices extends DragDropCore<QuestionSelectBase> {
}

private createImagePickerShortcut(item: ImageItemValue, text: string, draggedElementNode: HTMLElement, event: PointerEvent) {
const draggedElementShortcut: any = document.createElement("div");
const draggedElementShortcut: any = DomDocumentHelper.createElement("div");
if(!draggedElementShortcut) return;

draggedElementShortcut.style.cssText = `
cursor: grabbing;
position: absolute;
Expand Down
13 changes: 9 additions & 4 deletions src/dragdrop/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IShortcutText, ISurvey, ISurveyElement } from "../base-interfaces";
import { DragTypeOverMeEnum } from "../survey-element";
import { IDragDropEngine } from "./engine";
import { DragDropDOMAdapter, IDragDropDOMAdapter } from "./dom-adapter";
import { DomDocumentHelper } from "../global_variables_utils";

export abstract class DragDropCore<T> implements IDragDropEngine {
private _isBottom: boolean = null;
Expand Down Expand Up @@ -78,9 +79,11 @@ export abstract class DragDropCore<T> implements IDragDropEngine {
draggedElementNode?: HTMLElement,
event?: PointerEvent
): HTMLElement {
const draggedElementShortcut = document.createElement("div");
draggedElementShortcut.innerText = text;
draggedElementShortcut.className = this.getDraggedElementClass();
const draggedElementShortcut = DomDocumentHelper.createElement("div");
if(!!draggedElementShortcut) {
draggedElementShortcut.innerText = text;
draggedElementShortcut.className = this.getDraggedElementClass();
}
return draggedElementShortcut;
}

Expand Down Expand Up @@ -116,7 +119,9 @@ export abstract class DragDropCore<T> implements IDragDropEngine {
const displayProp = this.domAdapter.draggedElementShortcut.style.display;
//this.domAdapter.draggedElementShortcut.hidden = true;
this.domAdapter.draggedElementShortcut.style.display = "none";
let dragOverNode = <HTMLElement>document.elementFromPoint(clientX, clientY);

if(!DomDocumentHelper.isAvailable()) return null;
let dragOverNode = <HTMLElement>DomDocumentHelper.getDocument().elementFromPoint(clientX, clientY);
// this.domAdapter.draggedElementShortcut.hidden = false;
this.domAdapter.draggedElementShortcut.style.display = displayProp || "block";

Expand Down
1 change: 1 addition & 0 deletions src/dragdrop/dom-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
import { findScrollableParent, isShadowDOM } from "../utils/utils";
import { IsMobile, IsTouch } from "../utils/devices";
import { settings, ISurveyEnvironment } from "../settings";
Expand Down
17 changes: 13 additions & 4 deletions src/dragdrop/matrix-rows.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DomDocumentHelper } from "../global_variables_utils";
import { MatrixDropdownRowModelBase } from "../question_matrixdropdownbase";
import { QuestionMatrixDynamicModel } from "../question_matrixdynamic";
import { DragDropCore } from "./core";
Expand All @@ -9,16 +10,21 @@ export class DragDropMatrixRows extends DragDropCore<QuestionMatrixDynamicModel>
protected restoreUserSelectValue: string;

protected onStartDrag(): void {
this.restoreUserSelectValue = document.body.style.userSelect;
document.body.style.userSelect = "none";
const _body = DomDocumentHelper.getBody();
if(!!_body) {
this.restoreUserSelectValue = _body.style.userSelect;
_body.style.userSelect = "none";
}
}

protected createDraggedElementShortcut(
text: string,
draggedElementNode: HTMLElement,
event: PointerEvent
): HTMLElement {
const draggedElementShortcut: any = document.createElement("div");
const draggedElementShortcut: any = DomDocumentHelper.createElement("div");
if(!draggedElementShortcut) return;

// draggedElementShortcut.innerText = text;
draggedElementShortcut.style.cssText = `
cursor: grabbing;
Expand Down Expand Up @@ -173,7 +179,10 @@ export class DragDropMatrixRows extends DragDropCore<QuestionMatrixDynamicModel>
this.parentElement.clearOnDrop();
this.fromIndex = null;
this.toIndex = null;
document.body.style.userSelect = this.restoreUserSelectValue || "initial";
const _body = DomDocumentHelper.getBody();
if(!!_body) {
_body.style.userSelect = this.restoreUserSelectValue || "initial";
}
super.clear();
}
}
5 changes: 4 additions & 1 deletion src/dragdrop/ranking-choices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ItemValue } from "../itemvalue";
import { DragDropChoices } from "./choices";
import { CssClassBuilder } from "../utils/cssClassBuilder";
import { IsMobile } from "../utils/devices";
import { DomDocumentHelper } from "../global_variables_utils";
export class DragDropRankingChoices extends DragDropChoices {
protected get draggedElementType(): string {
return "ranking-item";
Expand All @@ -12,7 +13,9 @@ export class DragDropRankingChoices extends DragDropChoices {
draggedElementNode: HTMLElement,
event: PointerEvent
): HTMLElement {
const draggedElementShortcut: any = document.createElement("div");
const draggedElementShortcut: any = DomDocumentHelper.createElement("div");
if(!draggedElementShortcut) return;

draggedElementShortcut.className = this.shortcutClass + " sv-ranking-shortcut";
draggedElementShortcut.style.cssText = `
cursor: grabbing;
Expand Down
5 changes: 2 additions & 3 deletions src/dropdownListModel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IAction } from "./actions/action";
import { Base } from "./base";
import { DomDocumentHelper } from "./global_variables_utils";
import { ItemValue } from "./itemvalue";
import { property } from "./jsonobject";
import { ListModel } from "./list";
Expand Down Expand Up @@ -351,9 +352,7 @@ export class DropdownListModel extends Base {
};
constructor(protected question: Question, protected onSelectionChanged?: (item: IAction, ...params: any[]) => void) {
super();
if ("undefined" !== typeof document) {
this.htmlCleanerElement = document.createElement("div");
}
this.htmlCleanerElement = DomDocumentHelper.createElement("div") as HTMLDivElement;
question.onPropertyChanged.add(this.qustionPropertyChangedHandler);
this.showInputFieldComponent = this.question.showInputFieldComponent;

Expand Down
4 changes: 3 additions & 1 deletion src/element-helper.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { DomDocumentHelper } from "./global_variables_utils";

export class ElementHelper {
static focusElement(element: Element) {
element && (<HTMLElement>element).focus();
}
static visibility(node: Element): boolean {
var style = window.getComputedStyle(node);
var style = DomDocumentHelper.getComputedStyle(node);
if (style.display === "none" || style.visibility === "hidden") return false;
return node.parentElement ? this.visibility(node.parentElement) : true;
}
Expand Down
7 changes: 5 additions & 2 deletions src/entries/chunks/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// import "../../main.scss";
//import "../../modern.scss";

import { DomWindowHelper } from "../../global_variables_utils";

export var Version: string;
export var ReleaseDate: string;
Version = `${process.env.VERSION}`;
Expand Down Expand Up @@ -57,8 +59,9 @@ function checkPrefix(prefix: string): boolean {
if (index < 0) return true;
const ds = prefix.substring(index + s.length).toLowerCase().split(",");
if (!Array.isArray(ds) || ds.length === 0) return true;
if (typeof window !== "undefined" && !!window.location && !!window.location.hostname) {
const hn = window.location.hostname.toLowerCase();
const location = DomWindowHelper.getLocation();
if (!!location && !!location.hostname) {
const hn = location.hostname.toLowerCase();
ds.push("localhost");
for (let i = 0; i < ds.length; i++) {
if (hn.indexOf(ds[i]) > -1) return true;
Expand Down
14 changes: 6 additions & 8 deletions src/flowpanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IElement, IQuestion } from "./base-interfaces";
import { PanelModel } from "./panel";
import { LocalizableString } from "./localizablestring";
import { Question } from "./question";
import { DomWindowHelper } from "./global_variables_utils";

/**
* The flow panel object. It is a container with flow layout where you can mix questions with markdown text.
Expand Down Expand Up @@ -113,17 +114,14 @@ export class FlowPanelModel extends PanelModel {
}
}
private insertTextAtCursor(text: string, prevName: string = null): boolean {
if (
!this.isDesignMode ||
typeof document === "undefined" ||
!window.getSelection
)
return false;
let sel = window.getSelection();
if (!this.isDesignMode || !DomWindowHelper.isAvailable()) return false;

let sel = DomWindowHelper.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
let range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(text));
const textElement = new Text(text);
range.insertNode(textElement);
var self = <any>this;
if (self.getContent) {
var str = self.getContent(prevName);
Expand Down
102 changes: 102 additions & 0 deletions src/global_variables_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* eslint-disable no-restricted-globals */
export class DomWindowHelper {
public static isAvailable(): boolean {
return "undefined" !== typeof window;
}
public static isFileReaderAvailable(): boolean {
if (!DomWindowHelper.isAvailable()) return false;
return !!(<any>window)["FileReader"];
}
public static getLocation(): Location {
if (!DomWindowHelper.isAvailable()) return;
return window.location;
}
public static getVisualViewport(): VisualViewport | null {
if(!DomWindowHelper.isAvailable()) return null;
return window.visualViewport;
}
public static getInnerWidth(): number {
if(!DomWindowHelper.isAvailable()) return;
return window.innerWidth;
}
public static getInnerHeight(): number {
if(!DomWindowHelper.isAvailable()) return null;
return window.innerHeight;
}
public static getWindow(): Window {
if(!DomWindowHelper.isAvailable()) return;
return window;
}
public static hasOwn(propertyName: string): boolean {
if(!DomWindowHelper.isAvailable()) return;
return propertyName in window;
}
public static getSelection(): Selection | null {
if (DomWindowHelper.isAvailable() && window.getSelection) {
return window.getSelection();
}
}
public static requestAnimationFrame(callback: FrameRequestCallback): number {
if (DomWindowHelper.isAvailable()) {
return window.requestAnimationFrame(callback);
}
}
public static addEventListener(type: string, listener: (e?: any) => void): void {
if(!DomWindowHelper.isAvailable()) return;
document.addEventListener(type, listener);
}
public static removeEventListener(type: string, listener: (e?: any) => void): void {
if(!DomWindowHelper.isAvailable()) return;
document.removeEventListener(type, listener);
}
}

export class DomDocumentHelper {
public static isAvailable(): boolean {
return "undefined" !== typeof document;
}
public static getBody(): HTMLElement {
if(!DomDocumentHelper.isAvailable()) return;
return document.body;
}
public static getDocumentElement(): HTMLElement {
if(!DomDocumentHelper.isAvailable()) return;
return document.documentElement;
}
public static getDocument(): Document {
if(!DomDocumentHelper.isAvailable()) return;
return document;
}
public static getCookie(): string {
if(!DomDocumentHelper.isAvailable()) return;
return document.cookie;
}
public static setCookie(newCookie: string): void {
if(!DomDocumentHelper.isAvailable()) return;
document.cookie = newCookie;
}
public static activeElementBlur(): Document {
if(!DomDocumentHelper.isAvailable()) return;

const activeElement = document.activeElement;
if(!!activeElement && !!(<any>activeElement).blur) {
(<any>activeElement).blur();
}
}
public static createElement(tagName: string): HTMLElement {
if(!DomDocumentHelper.isAvailable()) return;
return document.createElement(tagName);
}
public static getComputedStyle(elt: Element): CSSStyleDeclaration {
if(!DomDocumentHelper.isAvailable()) return new CSSStyleDeclaration();
return document.defaultView.getComputedStyle(elt);
}
public static addEventListener(type: string, listener: (e?: any) => void): void {
if(!DomDocumentHelper.isAvailable()) return;
document.addEventListener(type, listener);
}
public static removeEventListener(type: string, listener: (e?: any) => void): void {
if(!DomDocumentHelper.isAvailable()) return;
document.removeEventListener(type, listener);
}
}
1 change: 1 addition & 0 deletions src/knockout/components/string-editor/string-editor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
import * as ko from "knockout";
import { LocalizableString } from "survey-core";
const template = require("./string-editor.html");
Expand Down
1 change: 1 addition & 0 deletions src/knockout/components/title/title-element.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
import * as ko from "knockout";
import { SurveyElementCore } from "survey-core";

Expand Down
3 changes: 2 additions & 1 deletion src/knockout/koflowpanel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
import * as ko from "knockout";
import { FlowPanelModel } from "survey-core";
import { Question } from "survey-core";
Expand Down Expand Up @@ -88,7 +89,7 @@ ko.components.register("f-panel", {
self.isContentUpdating = false;
};
question.getContent = self.getContent = function (deletedName: string) {
var content = document.createElement("DIV");
var content = document.createElement("div");
content.innerHTML = self.element.innerHTML;
var cps = content.querySelectorAll('span[question="true"]');
for (var i = 0; i < cps.length; i++) {
Expand Down
1 change: 1 addition & 0 deletions src/knockout/kosurvey.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
import * as ko from "knockout";
import { Base, SurveyModel, SvgRegistry, doKey2ClickDown, doKey2ClickUp, doKey2ClickBlur, IAttachKey2clickOptions, settings } from "survey-core";
import { SurveyElement } from "survey-core";
Expand Down
7 changes: 4 additions & 3 deletions src/panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ActionContainer } from "./actions/container";
import { SurveyModel } from "./survey";
import { DragDropPanelHelperV1 } from "./drag-drop-panel-helper-v1";
import { DragDropInfo } from "./drag-drop-helper-v1";
import { DomDocumentHelper, DomWindowHelper } from "./global_variables_utils";

export class QuestionRowModel extends Base {
private static rowCounter = 100;
Expand All @@ -41,11 +42,11 @@ export class QuestionRowModel extends Base {
protected _scrollableParent: any = undefined;
protected _updateVisibility: any = undefined;
public startLazyRendering(rowContainerDiv: HTMLElement, findScrollableContainer = findScrollableParent): void {
if ("undefined" === typeof document) return;
if (!DomDocumentHelper.isAvailable()) return;
this._scrollableParent = findScrollableContainer(rowContainerDiv);
// if this._scrollableParent is html the scroll event isn't fired, so we should use window
if (this._scrollableParent === document.documentElement) {
this._scrollableParent = window;
if (this._scrollableParent === DomDocumentHelper.getDocumentElement()) {
this._scrollableParent = DomWindowHelper.getWindow();
}
const hasScroll = this._scrollableParent.scrollHeight > this._scrollableParent.clientHeight;
this.isNeedRender = !hasScroll;
Expand Down
Loading

0 comments on commit 190db6d

Please sign in to comment.