Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

few SSR fixes #35339

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,18 @@
"unicorn/prefer-query-selector": "off",
"unicorn/prefer-spread": "off",
"unicorn/prevent-abbreviations": "off"
}
},
"overrides": [
{
"files": "js/src/**/*.js",
"plugins": ["ssr-friendly"],
"extends": [
"plugin:ssr-friendly/recommended"
],
"rules": {
"ssr-friendly/no-dom-globals-in-react-cc-render": "off",
"ssr-friendly/no-dom-globals-in-react-fc": "off"
}
}
]
}
6 changes: 5 additions & 1 deletion js/src/base-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import Data from './dom/data'
import {
executeAfterTransition,
getElement
getElement,
getWindow,
getDocument
} from './util/index'
import EventHandler from './dom/event-handler'

Expand All @@ -31,6 +33,8 @@ class BaseComponent {
}

this._element = element
this._window = getWindow()
this._document = getDocument()
Data.set(this._element, this.constructor.DATA_KEY, this)
}

Expand Down
4 changes: 2 additions & 2 deletions js/src/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/

import { defineJQueryPlugin } from './util/index'
import { defineJQueryPlugin, getDocument } from './util/index'
import EventHandler from './dom/event-handler'
import BaseComponent from './base-component'

Expand Down Expand Up @@ -54,7 +54,7 @@ class Button extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
event.preventDefault()

const button = event.target.closest(SELECTOR_DATA_TOGGLE)
Expand Down
12 changes: 7 additions & 5 deletions js/src/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import {
isVisible,
reflow,
triggerTransitionEnd,
typeCheckConfig
typeCheckConfig,
getDocument,
getWindow
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
Expand Down Expand Up @@ -127,7 +129,7 @@ class Carousel extends BaseComponent {
nextWhenVisible() {
// Don't call next when the page isn't visible
// or the carousel or its parent isn't visible
if (!document.hidden && isVisible(this._element)) {
if (!this._document.hidden && isVisible(this._element)) {
this.next()
}
}
Expand Down Expand Up @@ -164,7 +166,7 @@ class Carousel extends BaseComponent {
this._updateInterval()

this._interval = setInterval(
(document.visibilityState ? this.nextWhenVisible : this.next).bind(this),
(this._document.visibilityState ? this.nextWhenVisible : this.next).bind(this),
this._config.interval
)
}
Expand Down Expand Up @@ -509,9 +511,9 @@ class Carousel extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler)
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler)

EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)

for (const carousel of carousels) {
Expand Down
5 changes: 3 additions & 2 deletions js/src/collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
getElementFromSelector,
getSelectorFromElement,
reflow,
typeCheckConfig
typeCheckConfig,
getDocument
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
Expand Down Expand Up @@ -289,7 +290,7 @@ class Collapse extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
// preventDefault only for <a> elements (which change the URL) not inside the collapsible element
if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {
event.preventDefault()
Expand Down
6 changes: 3 additions & 3 deletions js/src/dom/event-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/

import { getjQuery } from '../util/index'
import { getjQuery, getDocument } from '../util/index'

/**
* Constants
Expand Down Expand Up @@ -150,7 +150,7 @@ function normalizeParams(originalTypeEvent, handler, delegationFn) {
}

function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
if (typeof originalTypeEvent !== 'string' || !element) {
if (typeof originalTypeEvent !== 'string' || !element || !element.addEventListener) {
return
}

Expand Down Expand Up @@ -302,7 +302,7 @@ const EventHandler = {
}

if (isNative) {
evt = document.createEvent('HTMLEvents')
evt = getDocument().createEvent('HTMLEvents')
evt.initEvent(typeEvent, bubbles, true)
} else {
evt = new CustomEvent(event, { bubbles, cancelable: true })
Expand Down
7 changes: 5 additions & 2 deletions js/src/dom/manipulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* --------------------------------------------------------------------------
*/

import { getWindow } from '../util/index'

function normalizeData(val) {
if (val === 'true') {
return true
Expand Down Expand Up @@ -61,10 +63,11 @@ const Manipulator = {

offset(element) {
const rect = element.getBoundingClientRect()
const windowRef = getWindow()

return {
top: rect.top + window.pageYOffset,
left: rect.left + window.pageXOffset
top: rect.top + windowRef.pageYOffset,
left: rect.left + windowRef.pageXOffset
}
},

Expand Down
6 changes: 3 additions & 3 deletions js/src/dom/selector-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/

import { isDisabled, isVisible } from '../util/index'
import { getDocument, isDisabled, isVisible } from '../util/index'

/**
* Constants
Expand All @@ -14,11 +14,11 @@ import { isDisabled, isVisible } from '../util/index'
const NODE_TEXT = 3

const SelectorEngine = {
find(selector, element = document.documentElement) {
find(selector, element = getDocument().documentElement) {
return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
},

findOne(selector, element = document.documentElement) {
findOne(selector, element = getDocument().documentElement) {
return Element.prototype.querySelector.call(element, selector)
},

Expand Down
19 changes: 11 additions & 8 deletions js/src/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
isRTL,
isVisible,
noop,
typeCheckConfig
typeCheckConfig,
getDocument
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
Expand Down Expand Up @@ -144,8 +145,8 @@ class Dropdown extends BaseComponent {
// empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {
for (const elem of [].concat(...document.body.children)) {
if ('ontouchstart' in this._document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {
for (const elem of [].concat(...this._document.body.children)) {
EventHandler.on(elem, 'mouseover', noop)
}
}
Expand Down Expand Up @@ -468,11 +469,13 @@ class Dropdown extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
const documentRef = getDocument()

EventHandler.on(documentRef, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
EventHandler.on(documentRef, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
EventHandler.on(documentRef, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
EventHandler.on(documentRef, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
EventHandler.on(documentRef, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
event.preventDefault()
Dropdown.getOrCreateInstance(this).toggle()
})
Expand Down
15 changes: 8 additions & 7 deletions js/src/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
isRTL,
isVisible,
reflow,
typeCheckConfig
typeCheckConfig,
getDocument
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
Expand Down Expand Up @@ -212,7 +213,7 @@ class Modal extends BaseComponent {

if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
// Don't move modal's DOM position
document.body.append(this._element)
this._document.body.append(this._element)
}

this._element.style.display = 'block'
Expand Down Expand Up @@ -275,7 +276,7 @@ class Modal extends BaseComponent {
this._element.removeAttribute('role')
this._isTransitioning = false
this._backdrop.hide(() => {
document.body.classList.remove(CLASS_NAME_OPEN)
this._document.body.classList.remove(CLASS_NAME_OPEN)
this._resetAdjustments()
this._scrollBar.reset()
EventHandler.trigger(this._element, EVENT_HIDDEN)
Expand Down Expand Up @@ -314,7 +315,7 @@ class Modal extends BaseComponent {
}

const { classList, scrollHeight, style } = this._element
const isModalOverflowing = scrollHeight > document.documentElement.clientHeight
const isModalOverflowing = scrollHeight > this._document.documentElement.clientHeight

// return if the following background transition hasn't yet completed
if ((!isModalOverflowing && style.overflowY === 'hidden') || classList.contains(CLASS_NAME_STATIC)) {
Expand Down Expand Up @@ -343,7 +344,7 @@ class Modal extends BaseComponent {
*/

_adjustDialog() {
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight
const isModalOverflowing = this._element.scrollHeight > this._document.documentElement.clientHeight
const scrollbarWidth = this._scrollBar.getWidth()
const isBodyOverflowing = scrollbarWidth > 0

Expand Down Expand Up @@ -383,7 +384,7 @@ class Modal extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
const target = getElementFromSelector(this)

if (['A', 'AREA'].includes(this.tagName)) {
Expand All @@ -403,7 +404,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
})
})

// avoid conflict when clicking moddal toggler while another one is open
// avoid conflict when clicking modal toggler while another one is open
const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)
if (allReadyOpen) {
Modal.getInstance(allReadyOpen).hide()
Expand Down
8 changes: 5 additions & 3 deletions js/src/offcanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
getElementFromSelector,
isDisabled,
isVisible,
typeCheckConfig
typeCheckConfig,
getDocument,
getWindow
} from './util/index'
import ScrollBarHelper from './util/scrollbar'
import EventHandler from './dom/event-handler'
Expand Down Expand Up @@ -218,7 +220,7 @@ class Offcanvas extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
const target = getElementFromSelector(this)

if (['A', 'AREA'].includes(this.tagName)) {
Expand Down Expand Up @@ -246,7 +248,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
data.toggle(this)
})

EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
for (const el of SelectorEngine.find(OPEN_SELECTOR)) {
Offcanvas.getOrCreateInstance(el).show()
}
Expand Down
13 changes: 7 additions & 6 deletions js/src/scrollspy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
defineJQueryPlugin,
getElement,
getSelectorFromElement,
typeCheckConfig
typeCheckConfig,
getWindow
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
Expand Down Expand Up @@ -63,7 +64,7 @@ const DefaultType = {
class ScrollSpy extends BaseComponent {
constructor(element, config) {
super(element)
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
this._scrollElement = this._element.tagName === 'BODY' ? this._window : this._element
this._config = this._getConfig(config)
this._offsets = []
this._targets = []
Expand Down Expand Up @@ -157,14 +158,14 @@ class ScrollSpy extends BaseComponent {

_getScrollHeight() {
return this._scrollElement.scrollHeight || Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight
this._document.body.scrollHeight,
this._document.documentElement.scrollHeight
)
}

_getOffsetHeight() {
return this._scrollElement === window ?
window.innerHeight :
this._window.innerHeight :
this._scrollElement.getBoundingClientRect().height
}

Expand Down Expand Up @@ -271,7 +272,7 @@ class ScrollSpy extends BaseComponent {
* Data API implementation
*/

EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
EventHandler.on(getWindow(), EVENT_LOAD_DATA_API, () => {
for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
new ScrollSpy(spy) // eslint-disable-line no-new
}
Expand Down
5 changes: 3 additions & 2 deletions js/src/tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
defineJQueryPlugin,
getElementFromSelector,
isDisabled,
reflow
reflow,
getDocument
} from './util/index'
import EventHandler from './dom/event-handler'
import SelectorEngine from './dom/selector-engine'
Expand Down Expand Up @@ -184,7 +185,7 @@ class Tab extends BaseComponent {
* Data API implementation
*/

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
EventHandler.on(getDocument(), EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
if (['A', 'AREA'].includes(this.tagName)) {
event.preventDefault()
}
Expand Down
Loading