Skip to content

Commit

Permalink
feat(exclude): add exclude option; change clickableClass to excludeClass
Browse files Browse the repository at this point in the history
Close gh-411
  • Loading branch information
timmywil committed Oct 29, 2019
1 parent c4bcd87 commit da72c32
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -106,8 +106,8 @@ Object elements can eat up events, making it so they never reach Panzoom. To fix

3\. My links aren't working! How do I enable an anchor within a panzoom element?

Add class `options.clickableClass` (default is `"clickable"`) to whatever element you want to be clickable. Panzoom will check for this class before handling the event.
Alternatively, call `event.stopImmediatePropagation()` in an event handler on the clickable element.
Add class `options.excludeClass` (default is `"panzoom-exclude"`) to whatever element you want to be clickable. Panzoom will check for this class before handling the event.
Alternatively, add a reference to the element to the `exclude` option, or call `event.stopImmediatePropagation()` in an event handler on the clickable element.

---

Expand Down
7 changes: 6 additions & 1 deletion demo/Demo.tsx
Expand Up @@ -9,7 +9,12 @@ interface Props {
export default function Demo({ title, code, children }: Props) {
return (
<div className="demo">
<h2>{title}</h2>
<a
id={title}
href={`/#${encodeURIComponent(title)}`}
style={{ textDecoration: 'none', color: 'black' }}>
<h2>{title}</h2>
</a>
{code}
<div className="live-example">{children}</div>
</div>
Expand Down
78 changes: 78 additions & 0 deletions demo/examples/Exclude.tsx
@@ -0,0 +1,78 @@
import React, { CSSProperties, useEffect, useRef } from 'react'
import Panzoom from '../../src/panzoom'
import Code from '../Code'
import Demo from '../Demo'

const code = (
<Code>{`\
Panzoom(elem, {
// Can add an element reference
exclude: [document.getElementById('link')],
// ...or set a class on the element
excludeClass: 'custom-excluded-class'
})`}</Code>
)

const ANCHOR_TOP = 20

const anchorStyle: CSSProperties = {
position: 'absolute',
top: ANCHOR_TOP,
left: 0,
right: 0,
padding: '10px 0',
textAlign: 'center',
fontSize: 20,
color: '#baffc1',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderWidth: 1,
borderColor: '#dd33aa'
}

const lastAnchorStyle = {
...anchorStyle,
top: ANCHOR_TOP + 50
}

export default function Exclude() {
const elem = useRef<HTMLDivElement>(null)
const elemTwo = useRef<HTMLDivElement>(null)
useEffect(() => {
Panzoom(elem.current, {
exclude: [document.getElementById('link')],
excludeClass: 'custom-excluded-class'
})
Panzoom(elemTwo.current)
}, [])
return (
<Demo title="Exclude elements within the Panzoom element from event handling" code={code}>
<div className="panzoom-parent">
<div
className="panzoom"
ref={elem}
style={{
width: '400px',
border: '2px dotted',
margin: '0 auto'
}}>
<img style={{ width: '100%', height: '100%' }} src="awesome_tiger.svg" />
<a style={anchorStyle} target="_blank" id="link" href="https://timmywil.com/panzoom/">
This link will handle the click
</a>
<a style={lastAnchorStyle}>This one will pass through the event.</a>
<div
ref={elemTwo}
style={{
width: '200px',
margin: '0 auto',
padding: 20,
backgroundColor: '#DD3333',
color: 'white'
}}>
This is a Panzoom element within another Panzoom element. This works by default.
</div>
</div>
</div>
</Demo>
)
}
2 changes: 2 additions & 0 deletions demo/index.tsx
Expand Up @@ -4,6 +4,7 @@ import './demo.css'
import ContainInside from './examples/ContainInside'
import ContainOutside from './examples/ContainOutside'
import DisabledYAxis from './examples/DisabledYAxis'
import Exclude from './examples/Exclude'
import Focal from './examples/Focal'
import Standard from './examples/Standard'
import SVG from './examples/SVG'
Expand All @@ -25,6 +26,7 @@ function Demos() {
<Standard />
<Focal />
<SVG />
<Exclude />
<ContainInside />
<ContainOutside />
<DisabledYAxis />
Expand Down
11 changes: 8 additions & 3 deletions src/panzoom.ts
Expand Up @@ -18,14 +18,15 @@ import { PanOptions, PanzoomEvent, PanzoomObject, PanzoomOptions, ZoomOptions }

const defaultOptions: PanzoomOptions = {
animate: false,
clickableClass: 'clickable',
cursor: 'move',
disablePan: false,
disableZoom: false,
disableXAxis: false,
disableYAxis: false,
duration: 200,
easing: 'ease-in-out',
exclude: [],
excludeClass: 'panzoom-exclude',
maxScale: 4,
minScale: 0.125,
panOnlyWhenZoomed: false,
Expand Down Expand Up @@ -334,8 +335,12 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz
const pointers: PointerEvent[] = []

function handleDown(event: PointerEvent) {
// Don't handle this event if the target is a clickable
if (event.target && (event.target as Element).classList.contains(options.clickableClass)) {
// Don't handle this event if the target is excluded
if (
event.target &&
((event.target as Element).classList.contains(options.excludeClass) ||
options.exclude.indexOf(event.target as Element) > -1)
) {
return
}
addPointer(pointers, event)
Expand Down
13 changes: 10 additions & 3 deletions src/types.ts
Expand Up @@ -12,10 +12,17 @@ interface MiscOptions {
/** Whether to animate transitions */
animate?: boolean
/**
* Add this class to any element within the panzoom element
* that you want to be clickable and not initiate the drag
* Add elements to this array that should be excluded
* from Panzoom handling.
* e.g. links and buttons that should not propagate the click event.
*/
clickableClass?: string
exclude?: Element[]
/**
* Add this class to any element within the Panzoom element
* that you want to exclude from Panzoom handling.
* e.g. links and buttons that should not propagate the click event.
*/
excludeClass?: string
/** Duration of the transition (ms) */
duration?: number
/** CSS Easing used for transitions */
Expand Down

0 comments on commit da72c32

Please sign in to comment.