Skip to content

Commit 3a0119e

Browse files
committed
fix(*): check for window and document to allow ssr loading
Fixes gh-499
1 parent 186315a commit 3a0119e

File tree

6 files changed

+56
-34
lines changed

6 files changed

+56
-34
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
---
88

9-
Panzoom is a small library (~3.6kb gzipped) to add panning and zooming functionality to an element.
9+
Panzoom is a small library (~3.7kb gzipped) to add panning and zooming functionality to an element.
1010
Rather than using absolute positioning or setting width and height, Panzoom uses CSS transforms to take advantage of hardware/GPU acceleration in the browser, which means the element can be _anything_: an image, a video, an iframe, a canvas, text, WHATEVER.
1111

1212
For common support questions, see [the FAQ](https://github.com/timmywil/panzoom#faq).

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
"release": "cross-env HUSKY_SKIP_HOOKS=1 semantic-release",
1919
"sizeup": "echo \"gzipped size: \" && gzip-size dist/panzoom.min.js",
2020
"start": "webpack-dev-server",
21-
"test": "npm run lint && npm run test:unit",
21+
"test": "npm run lint && npm run test:unit && npm run test:node",
2222
"test:unit": "karma start",
23+
"test:node": "npm run build && node test/test-node.js",
2324
"test:watch": "karma start --singleRun=false --autoWatch",
2425
"type-check": "tsc -p tsconfig.json --noEmit"
2526
},

src/css.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import { CurrentValues, PanzoomOptions } from './types'
22

3-
const isIE = !!(document as any).documentMode
3+
const isIE = typeof document !== 'undefined' && !!(document as any).documentMode
4+
5+
/**
6+
* Lazy creation of a CSS style declaration
7+
*/
8+
let divStyle: CSSStyleDeclaration
9+
function createStyle() {
10+
if (divStyle) {
11+
return divStyle
12+
}
13+
return (divStyle = document.createElement('div').style)
14+
}
415

516
/**
617
* Proper prefixing for cross-browser compatibility
718
*/
8-
const divStyle = document.createElement('div').style
919
const prefixes = ['webkit', 'moz', 'ms']
1020
const prefixCache: { [key: string]: string } = {}
1121
function getPrefixedName(name: string) {
1222
if (prefixCache[name]) {
1323
return prefixCache[name]
1424
}
25+
const divStyle = createStyle()
1526
if (name in divStyle) {
1627
return (prefixCache[name] = name)
1728
}

src/events.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
let events: { down: string; move: string; up: string }
2-
if (typeof window.PointerEvent === 'function') {
3-
events = {
4-
down: 'pointerdown',
5-
move: 'pointermove',
6-
up: 'pointerup pointerleave pointercancel'
7-
}
8-
} else if (typeof window.TouchEvent === 'function') {
9-
events = {
10-
down: 'touchstart',
11-
move: 'touchmove',
12-
up: 'touchend touchcancel'
13-
}
14-
} else {
15-
events = {
16-
down: 'mousedown',
17-
move: 'mousemove',
18-
up: 'mouseup mouseleave'
1+
let events = {
2+
down: 'mousedown',
3+
move: 'mousemove',
4+
up: 'mouseup mouseleave'
5+
}
6+
7+
if (typeof window !== 'undefined') {
8+
if (typeof window.PointerEvent === 'function') {
9+
events = {
10+
down: 'pointerdown',
11+
move: 'pointermove',
12+
up: 'pointerup pointerleave pointercancel'
13+
}
14+
} else if (typeof window.TouchEvent === 'function') {
15+
events = {
16+
down: 'touchstart',
17+
move: 'touchmove',
18+
up: 'touchend touchcancel'
19+
}
1920
}
2021
}
2122

src/polyfills.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
/* eslint-disable no-var */
2-
// Support: IE11 only
3-
if (window.NodeList && !NodeList.prototype.forEach) {
4-
NodeList.prototype.forEach = Array.prototype.forEach
5-
}
6-
// Support: IE11 only
7-
// CustomEvent is an object instead of a constructor
8-
if (typeof window.CustomEvent !== 'function') {
9-
window.CustomEvent = function CustomEvent(event, params) {
10-
params = params || { bubbles: false, cancelable: false, detail: null }
11-
var evt = document.createEvent('CustomEvent')
12-
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
13-
return evt
2+
if (typeof window !== 'undefined') {
3+
// Support: IE11 only
4+
if (window.NodeList && !NodeList.prototype.forEach) {
5+
NodeList.prototype.forEach = Array.prototype.forEach
6+
}
7+
// Support: IE11 only
8+
// CustomEvent is an object instead of a constructor
9+
if (typeof window.CustomEvent !== 'function') {
10+
window.CustomEvent = function CustomEvent(event, params) {
11+
params = params || { bubbles: false, cancelable: false, detail: null }
12+
var evt = document.createEvent('CustomEvent')
13+
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
14+
return evt
15+
}
1416
}
1517
}

test/test-node.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Ensures panzoom can be loaded in node,
3+
* where there is no window.
4+
* This allows loading in SSR, but Panzoom
5+
* should still only be initialized on the front-end.
6+
*/
7+
require('../dist/panzoom')

0 commit comments

Comments
 (0)