Skip to content

Commit

Permalink
Merge pull request #375 from dnbexperience/develop
Browse files Browse the repository at this point in the history
fix: enhance politeness of touch device detection
  • Loading branch information
tujoworker committed Nov 27, 2019
2 parents f2e18e6 + e76b5ae commit 24d26d2
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 41 deletions.
11 changes: 6 additions & 5 deletions packages/dnb-ui-lib/src/components/modal/Modal.js
Expand Up @@ -492,9 +492,6 @@ class ModalContent extends PureComponent {
this._id = props.content_id || makeUniqueId()
}
componentDidMount() {
// since touch devices works diffrent, and we also use preventScreenReaderPossibility
// we dont set the tabindex by using removeFocusPossibility
this.isTouchDevice = isTouchDevice()
this.removeScrollPossibility()
this.preventScreenReaderPossibility()
this.removeFocusPossibility()
Expand Down Expand Up @@ -555,7 +552,9 @@ class ModalContent extends PureComponent {
}

removeFocusPossibility() {
if (typeof document === 'undefined' || this.isTouchDevice) {
// since touch devices works diffrent, and we also use preventScreenReaderPossibility
// we dont set the tabindex by using removeFocusPossibility
if (typeof document === 'undefined' || isTouchDevice()) {
return
}
const modalNodes = Array.from(
Expand Down Expand Up @@ -588,7 +587,9 @@ class ModalContent extends PureComponent {
}

revertFocusPossibility() {
if (!this.nonModalNodes || this.isTouchDevice) {
// since touch devices works diffrent, and we also use preventScreenReaderPossibility
// we dont set the tabindex by using removeFocusPossibility
if (!this.nonModalNodes || isTouchDevice()) {
return
}
// restore or remove tabindex from nodes
Expand Down
13 changes: 6 additions & 7 deletions packages/dnb-ui-lib/src/components/slider/Slider.js
Expand Up @@ -174,7 +174,6 @@ export default class Slider extends PureComponent {
super(props)
this._id = props.id || makeUniqueId() // cause we need an id anyway
this._trackRef = React.createRef()
this.isTouch = isTouchDevice()
this.state = {
_listenForPropChanges: true,
value: Slider.getValue(props) // so on_state_update not gets called
Expand Down Expand Up @@ -401,7 +400,7 @@ export default class Slider extends PureComponent {

componentDidMount() {
if (
(this.isTouch || isTrue(this.props.use_scrollwheel)) &&
(isTouchDevice() || isTrue(this.props.use_scrollwheel)) &&
this._trackRef.current
) {
this._trackRef.current.addEventListener(
Expand Down Expand Up @@ -545,18 +544,18 @@ export default class Slider extends PureComponent {

if (label) {
rangeParams['aria-labelledby'] = id + '-label'
if (this.isTouch) {
if (isTouchDevice()) {
trackParams['aria-labelledby'] = id + '-label'
}
}
if (showStatus) {
rangeParams['aria-describedby'] = id + '-status'
if (this.isTouch) {
if (isTouchDevice()) {
trackParams['aria-describedby'] = id + '-status'
}
}

if (this.isTouch) {
if (isTouchDevice()) {
trackParams.role = 'slider'
trackParams['aria-valuenow'] = this.roundValue(value)
trackParams['aria-valuemin'] = min
Expand Down Expand Up @@ -623,7 +622,7 @@ export default class Slider extends PureComponent {
style={inlineThumbStyles}
>
{/* Keep the possibility open to use a native slider inside */}
{!this.isTouch && (
{!isTouchDevice() && (
<input
type="range"
className="dnb-slider__helper"
Expand All @@ -640,7 +639,7 @@ export default class Slider extends PureComponent {
variant="secondary"
tabIndex="-1"
onMouseDown={this.onMouseDownHandler}
{...(this.isTouch
{...(isTouchDevice()
? rangeParams
: { 'aria-hidden': true })}
/>
Expand Down
111 changes: 82 additions & 29 deletions packages/dnb-ui-lib/src/shared/component-helper.js
Expand Up @@ -32,11 +32,89 @@ export const isMac = () =>
* Check if device is touch device or not
*/

let IS_TOUCH_DEVICE = undefined
export function isTouchDevice() {
if (typeof isTouchDevice.result !== 'undefined') {
return isTouchDevice.result
if (typeof IS_TOUCH_DEVICE !== 'undefined') {
if (typeof window !== 'undefined') {
window.IS_TOUCH_DEVICE = IS_TOUCH_DEVICE
}
return IS_TOUCH_DEVICE
}
let result = undefined

return IS_TOUCH_DEVICE
}

/**
* Detects if device supports touches
*
* @param {[type]} [interactive=true}] [Makes it posible that the state changes interactive]
* @return {[type]} [void]
*/
export function defineIsTouch({ interactive = true } = {}) {
const handleDefineTouch = () => {
if (typeof document === 'undefined' || typeof window === 'undefined') {
return
}

// to give it a change to have isTouch from the very beginning
if (unsafeIsTouchDeviceCheck()) {
document.documentElement.setAttribute('data-is-touch', true)
}

window.addEventListener(
'touchstart',
function onFirstTouch() {
try {
if (IS_TOUCH_DEVICE !== true) {
document.documentElement.setAttribute('data-is-touch', true)
}
IS_TOUCH_DEVICE = true
} catch (e) {
console.warn('Could not apply "touch attribute"', e)
}
if (!interactive) {
window.removeEventListener('touchstart', onFirstTouch, false)
}
},
false
)

window.addEventListener(
'mouseover',
function onFirstHover() {
try {
if (IS_TOUCH_DEVICE === true) {
document.documentElement.removeAttribute('data-is-touch')
}
IS_TOUCH_DEVICE = false
} catch (e) {
console.warn('Could not apply "touch attribute"', e)
}
if (!interactive) {
window.removeEventListener('mouseover', onFirstHover, false)
}
},
false
)

document.removeEventListener('DOMContentLoaded', handleDefineTouch)
}

if (
typeof document !== 'undefined' &&
document.readyState === 'loading'
) {
document.addEventListener('DOMContentLoaded', handleDefineTouch)
} else {
handleDefineTouch()
}
}

function unsafeIsTouchDeviceCheck() {
if (typeof document === 'undefined' || typeof window === 'undefined') {
return false
}
let result = false

try {
if (window.PointerEvent && 'maxTouchPoints' in navigator) {
Expand All @@ -61,32 +139,7 @@ export function isTouchDevice() {
result = false
}

return (isTouchDevice.result = result)
}

export function defineIsTouch() {
const handleDefineTouch = () => {
if (typeof document === 'undefined' || typeof window === 'undefined')
return
try {
if (isTouchDevice()) {
document.documentElement.setAttribute('data-is-touch', true)
}
} catch (e) {
console.warn('Could not apply "touch attribute"', e)
}

document.removeEventListener('DOMContentLoaded', handleDefineTouch)
}

if (
typeof document !== 'undefined' &&
document.readyState === 'loading'
) {
document.addEventListener('DOMContentLoaded', handleDefineTouch)
} else {
handleDefineTouch()
}
return result
}

export function defineNavigator() {
Expand Down

0 comments on commit 24d26d2

Please sign in to comment.