Skip to content

Commit

Permalink
fix: check if window, document or navigator are existing
Browse files Browse the repository at this point in the history
  • Loading branch information
hirsch88 committed Oct 20, 2022
1 parent 2b09e10 commit 37ecc10
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { getOverlays } from '../../../utils/overlays/overlays'
import { componentOnReady, getAppRoot } from '../../../utils/helpers'
import { getOverlay } from '../../../utils/overlays/overlays'
import { ModalOptions } from './bal-modal.type'
import { isDocumentDefined } from '../../../utils/browser'

export class BalModalController {
tag = 'bal-modal'
create(options: ModalOptions): Promise<HTMLBalModalElement> {
/* tslint:disable-next-line */
if (typeof customElements !== 'undefined') {
if (typeof customElements !== 'undefined' && isDocumentDefined()) {
return customElements.whenDefined(this.tag).then(() => {
const element = document.createElement(this.tag) as HTMLBalModalElement

Expand All @@ -25,20 +26,28 @@ export class BalModalController {
}

async dismissAll(data?: any, role?: string): Promise<void> {
const overlays = getOverlays(document, this.tag)
await Promise.all(overlays.map(o => o.dismiss(data, role)))
if (isDocumentDefined()) {
const overlays = getOverlays(document, this.tag)
await Promise.all(overlays.map(o => o.dismiss(data, role)))
}
}

dismiss(data?: any, role?: string, id?: string): Promise<boolean> {
const overlay = getOverlay(document, this.tag, id)
if (!overlay) {
return Promise.reject('overlay does not exist')
if (isDocumentDefined()) {
const overlay = getOverlay(document, this.tag, id)
if (!overlay) {
return Promise.reject('overlay does not exist')
}
return overlay.dismiss(data, role)
}
return overlay.dismiss(data, role)
return Promise.resolve(false)
}

async getTop(): Promise<HTMLBalModalElement | undefined> {
return getOverlay(document, this.tag) as any
if (isDocumentDefined()) {
return getOverlay(document, this.tag) as any
}
return
}
}

Expand Down
11 changes: 7 additions & 4 deletions packages/components/src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { balSnackbarController } from './components/notice/bal-snackbar/bal-snac
import { initialize } from './utils/config'
import { setupPlatforms } from './utils/platform'
import { VERSION } from './utils/constants/version.constant'
import { isDocumentDefined, isWindowDefined } from './utils/browser'

export default function () {
if (typeof (window as any) !== 'undefined') {
if (isWindowDefined()) {
const win = window as any
win.BaloiseDesignSystem = win.BaloiseDesignSystem || {}

Expand All @@ -19,9 +20,11 @@ export default function () {

if (win.addEventListener) {
win.addEventListener('balAppLoad', () => {
const body = document.querySelector('.bal-body')
if (body && body.classList) {
body.classList.add('is-ready')
if (isDocumentDefined()) {
const body = document.querySelector('.bal-body')
if (body && body.classList) {
body.classList.add('is-ready')
}
}
})
}
Expand Down
13 changes: 11 additions & 2 deletions packages/components/src/utils/browser.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
export const isWindowDefined = () => typeof window !== 'undefined'
export const isNavigatorDefined = () => typeof navigator !== 'undefined'
export const isDocumentDefined = () => typeof document !== 'undefined'

type Browser = 'Safari' | 'touch' | 'others'

const isSafari = /^((?!chrome|android).)*safari/i.test(getUserAgent())

export const hasTouchSupport = () => !!('ontouchstart' in window || (navigator as any).msMaxTouchPoints)
export const hasTouchSupport = () => {
if (isWindowDefined() && isNavigatorDefined()) {
return !!('ontouchstart' in window || (navigator as any).msMaxTouchPoints)
}
return false
}

export const isBrowser = (browser: Browser): boolean => {
if (browser === 'Safari') {
Expand All @@ -12,7 +21,7 @@ export const isBrowser = (browser: Browser): boolean => {
}

function getUserAgent(): string {
if (typeof (window as any) !== 'undefined') {
if (isWindowDefined() && isNavigatorDefined()) {
return navigator.userAgent ?? ''
}

Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/utils/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isWindowDefined } from '../browser'
import { BALOISE_SESSION_KEY } from './config.const'
import { BalConfig, BalConfigState, BalLanguage, BalRegion } from './config.types'
import { BalConfigObserver } from './observable/observer'
Expand Down Expand Up @@ -115,7 +116,9 @@ export class Config {
}
}

saveConfig(window, this._config)
if (isWindowDefined()) {
saveConfig(window, this._config)
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/utils/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BalConfigObserver } from '../../types'
import { isWindowDefined } from '../browser'
import { Config } from './config'
import { BalConfigState, BalLanguage, BalRegion } from './config.types'

Expand All @@ -18,7 +19,7 @@ export const onBalConfigChange = (callback: BalConfigChangeFn) => {
}

export const useBalConfig = (): Config | undefined => {
if (typeof (window as any) === 'undefined') {
if (!isWindowDefined()) {
return
}

Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/utils/config/initialize.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isWindowDefined } from '../browser'
import { config, configFromSession } from './config'
import { BalConfig, BalConfigState } from './config.types'

Expand All @@ -11,7 +12,7 @@ export const defaultConfig: BalConfigState = {
export const defaultLocale = `${defaultConfig.language}-${defaultConfig.region}`

export const initialize = (userConfig: BalConfig = {}, win = {} as any) => {
if (typeof (window as any) === 'undefined') {
if (!isWindowDefined()) {
return
}

Expand Down
49 changes: 27 additions & 22 deletions packages/components/src/utils/overlays/notice.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HTMLStencilElement } from '@stencil/core/internal'
import { Props } from '../../types'
import { isDocumentDefined } from '../browser'

export interface BalNoticeOptions {
message: string
Expand Down Expand Up @@ -27,19 +28,21 @@ export abstract class BalNoticeController {
constructor(private options: NoticeOptions) {}

create(options: BalNoticeOptions): any {
this.setupContainer()
const clone = this.findClone(options)
if (clone === undefined) {
const el: HTMLNoticeElement = document.createElement(this.options.tag) as unknown as HTMLNoticeElement
Object.assign(el, options)
el.addEventListener('balClose', event => {
this.removeFromQueue((<any>event).detail)
})
this.preQueue.push(el)
this.updateQueue()
return el
if (isDocumentDefined()) {
this.setupContainer()
const clone = this.findClone(options)
if (clone === undefined) {
const el: HTMLNoticeElement = document.createElement(this.options.tag) as unknown as HTMLNoticeElement
Object.assign(el, options)
el.addEventListener('balClose', event => {
this.removeFromQueue((<any>event).detail)
})
this.preQueue.push(el)
this.updateQueue()
return el
}
return clone
}
return clone
}

setQueue(queueLimit: number) {
Expand Down Expand Up @@ -79,19 +82,21 @@ export abstract class BalNoticeController {
}

private setupContainer() {
const containerId = `${this.options.tag}-container`
this.container = document.getElementById(containerId)
if (isDocumentDefined()) {
const containerId = `${this.options.tag}-container`
this.container = document.getElementById(containerId)

if (this.container) return
if (this.container) return

if (!this.container) {
this.container = document.createElement('bal-notices')
this.container.setAttribute('interface', this.options.tag.replace('bal-', ''))
// this.container.className = `bal-notices bal-notices--${this.options.tag.replace('bal-', '')}`
this.container.id = containerId
}
if (!this.container) {
this.container = document.createElement('bal-notices')
this.container.setAttribute('interface', this.options.tag.replace('bal-', ''))
// this.container.className = `bal-notices bal-notices--${this.options.tag.replace('bal-', '')}`
this.container.id = containerId
}

document.body.appendChild(this.container)
document.body.appendChild(this.container)
}
}

private updateQueue() {
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/utils/overlays/overlays.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HTMLStencilElement } from '@stencil/core/internal'
import { isDocumentDefined } from '../browser'
import { addEventListener, removeEventListener } from '../helpers'

type OverlayInterface = any
Expand All @@ -22,7 +23,7 @@ export interface HTMLBalOverlayElement extends HTMLStencilElement {

export const prepareOverlay = (overlay: OverlayInterface) => {
/* tslint:disable-next-line */
if (typeof document !== 'undefined') {
if (isDocumentDefined()) {
connectListeners(document)
}
const overlayIndex = lastId++
Expand Down
4 changes: 3 additions & 1 deletion packages/components/src/utils/platform.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isWindowDefined } from './browser'

export type Platforms = keyof typeof PLATFORMS_MAP

interface IsPlatformSignature {
Expand Down Expand Up @@ -29,7 +31,7 @@ export const isPlatform: IsPlatformSignature = (
}

export const setupPlatforms = (win = {} as any) => {
if (typeof (window as any) === 'undefined') {
if (!isWindowDefined()) {
return []
}

Expand Down
16 changes: 13 additions & 3 deletions packages/components/src/utils/resize.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { hasTouchSupport } from './browser'
import { hasTouchSupport, isWindowDefined } from './browser'

const windowWidth = () => window.innerWidth
const windowWidth = () => {
if (isWindowDefined()) {
return window.innerWidth
}
return 0
}

const windowHeight = () => window.innerHeight
const windowHeight = () => {
if (isWindowDefined()) {
return window.innerHeight
}
return 0
}

const isLandscape = () => windowWidth() > windowHeight()

Expand Down
56 changes: 24 additions & 32 deletions packages/components/src/utils/toggle-scrolling-body.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,43 @@
const getBodyTopOffset = () => {
const doc = document.documentElement
return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
}
import { isDocumentDefined, isWindowDefined } from './browser'

const getBody = () => document.body
const getHtml = () => document.firstChild?.nextSibling as HTMLElement
const getBodyTopOffset = (win: Window, doc: Document) => {
return (win.scrollY || doc.documentElement.scrollTop) - (doc.documentElement.clientTop || 0)
}

const getHtmlStyles = () => getComputedStyle(getHtml())
const getBody = (doc: Document) => doc.body
const getHtml = (doc: Document) => doc.firstChild?.nextSibling as HTMLElement

const hasScrollSmoothOnHtml = () => getHtmlStyles().scrollBehavior === 'smooth'
const getHtmlStyles = (doc: Document) => getComputedStyle(getHtml(doc))

export const disableSmoothScrolling = () => {
const body = getBody()
const hasScrollSmoothOnHtml = (doc: Document) => getHtmlStyles(doc).scrollBehavior === 'smooth'

body.style.scrollBehavior = 'auto'
if (hasScrollSmoothOnHtml()) {
const html = getHtml()
html.style.scrollBehavior = 'auto'
export const BodyScrollBlocker = () => {
if (!isWindowDefined() || !isDocumentDefined()) {
return {
isBlocked: false,
block: () => void 0,
allow: () => void 0,
}
}
}

export const enableSmoothScrolling = () => {
const body = getBody()
const doc = document
const win = window

body.style.scrollBehavior = 'smooth'
if (hasScrollSmoothOnHtml()) {
const html = getHtml()
html.style.scrollBehavior = 'smooth'
}
}

export const BodyScrollBlocker = () => {
const body = getBody()
const html = getHtml()
const body = getBody(doc)
const html = getHtml(doc)
let timer: NodeJS.Timer | undefined = undefined

let isBlocked = false
let bodyTopOffset = getBodyTopOffset()
let bodyTopOffset = getBodyTopOffset(win, doc)

return {
isBlocked: () => isBlocked,
block: () => {
clearTimeout(timer)
isBlocked = true
bodyTopOffset = getBodyTopOffset()
bodyTopOffset = getBodyTopOffset(win, doc)
body.style.scrollBehavior = 'auto'
if (hasScrollSmoothOnHtml()) {
if (hasScrollSmoothOnHtml(doc)) {
html.style.scrollBehavior = 'auto'
}
body.style.position = 'fixed'
Expand All @@ -57,11 +49,11 @@ export const BodyScrollBlocker = () => {
body.style.position = 'static'
body.style.width = 'inherit'
body.style.top = `inherit`
document.documentElement.scrollTop = bodyTopOffset
doc.documentElement.scrollTop = bodyTopOffset
timer = setTimeout(() => {
isBlocked = false
body.style.scrollBehavior = 'smooth'
if (hasScrollSmoothOnHtml()) {
if (hasScrollSmoothOnHtml(doc)) {
html.style.scrollBehavior = 'smooth'
}
}, 0)
Expand Down

0 comments on commit 37ecc10

Please sign in to comment.