Skip to content
This repository was archived by the owner on Dec 11, 2019. It is now read-only.

Commit 988f187

Browse files
committed
Merge pull request #10165 from brave/10133
do not rely on classList for event target checks
1 parent d38edb4 commit 988f187

File tree

10 files changed

+83
-14
lines changed

10 files changed

+83
-14
lines changed

app/renderer/components/bookmarks/addEditBookmarkHanger.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class AddEditBookmarkHanger extends React.Component {
113113
}
114114

115115
render () {
116-
return <Dialog className={cx({
116+
return <Dialog bookmarkHanger className={cx({
117117
bookmarkDialog: this.props.isModal,
118118
bookmarkHanger: !this.props.isModal,
119119
[css(styles.bookmarkHanger)]: !this.props.isModal

app/renderer/components/common/browserButton.js

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class BrowserButton extends ImmutableComponent {
5959
render () {
6060
return <button
6161
disabled={this.props.disabled}
62+
data-extension-button={this.props.extensionButton}
6263
data-l10n-id={this.props.l10nId}
6364
data-test-id={this.props.testId}
6465
data-test2-id={this.props.test2Id}

app/renderer/components/common/contextMenu.js

+1
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ class ContextMenu extends React.Component {
509509
}
510510

511511
return <div
512+
data-context-menu
512513
ref={(node) => { this.node = node }}
513514
className={cx({
514515
contextMenu: true,

app/renderer/components/common/dialog.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ class Dialog extends ImmutableComponent {
4141
}
4242

4343
render () {
44-
return <div className={cx({
45-
[css(styles.dialog)]: true,
46-
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
47-
[this.props.className]: !!this.props.className
48-
})}
44+
return <div
45+
data-bookmark-hanger={this.props.bookmarkHanger}
46+
className={cx({
47+
[css(styles.dialog)]: true,
48+
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
49+
[this.props.className]: !!this.props.className
50+
})}
4951
data-test-id={this.props.testId}
5052
data-test2-id={this.props.test2Id}
5153
tabIndex='-1'

app/renderer/components/main/main.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -478,18 +478,19 @@ class Main extends React.Component {
478478
}
479479

480480
onMouseDown (e) {
481-
// TODO(bsclifton): update this to use eventUtil.eventElHasAncestorWithClasses
482481
let node = e.target
482+
const datasets = [
483+
'popupWindow',
484+
'contextMenu',
485+
'extensionButton',
486+
'menubarItem',
487+
'bookmarkHanger'
488+
]
483489
while (node) {
484-
if (node.classList &&
485-
(node.matches('[class^="popupWindow"]') ||
486-
node.classList.contains('contextMenu') ||
487-
node.matches('[class*="extensionButton_"]') ||
488-
node.classList.contains('menubarItem') ||
489-
node.classList.contains('bookmarkHanger'))) {
490+
if (eventUtil.elementHasDataset(node, datasets)) {
490491
// Middle click (on context menu) needs to fire the click event.
491492
// We need to prevent the default "Auto-Scrolling" behavior.
492-
if (node.classList.contains('contextMenu') && e.button === 1) {
493+
if (eventUtil.elementHasDataset(node, 'contextMenu') && e.button === 1) {
493494
e.preventDefault()
494495
}
495496
// Click event is handled downstream

app/renderer/components/main/popupWindow.js

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class PopupWindow extends React.Component {
118118
}
119119

120120
return <div
121+
data-popup-window
121122
className={css(
122123
styles.popupWindow,
123124
style.right !== undefined && styles.reverseExpand

app/renderer/components/navigation/browserAction.js

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class BrowserAction extends React.Component {
8181
// TODO(bridiver) should have some visual notification of hover/press
8282
return <div className={css(styles.browserActionButton)}>
8383
<BrowserButton
84+
extensionButton
8485
extensionItem
8586
l10nId='browserActionButton'
8687
testId='extensionBrowserAction'

app/renderer/components/navigation/menuBarItem.js

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class MenuBarItem extends React.Component {
6767

6868
render () {
6969
return <span
70+
data-menubar-item
7071
className={'menubarItem' + (this.props.selected ? ' selected' : '')}
7172
onClick={this.onClick}
7273
onMouseOver={this.onMouseOver}

js/lib/eventUtil.js

+23
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ module.exports.isForSecondaryAction = (e) =>
1010
e.button === 1
1111

1212
module.exports.eventElHasAncestorWithClasses = (e, classesToCheck) => {
13+
// DO NOT ADD NEW CHECKS USING THIS METHOD
14+
// classNames are changed from dev to prod by Aphrodite est. v1.2.3
15+
// and new code will not work. Consider using dataset attribute instead.
16+
// See issue #10029 for a breaking example.
17+
// ....
18+
// TODO deprecate this method.
1319
let node = e.target
1420

1521
while (node) {
@@ -28,3 +34,20 @@ module.exports.eventElHasAncestorWithClasses = (e, classesToCheck) => {
2834

2935
return false
3036
}
37+
38+
/**
39+
* Checks if a given node dataset matches a given dataset or array of datasets
40+
* @param {Object} The node to check if dataset is included
41+
* @param {Array|String} the dataset value to check against
42+
* @returns {Boolean} Whether or not the given dataset is included in the check
43+
*/
44+
module.exports.elementHasDataset = (node, datasetArray) => {
45+
if (!node.dataset) {
46+
return false
47+
}
48+
49+
const datasetToMatch = Array.isArray(datasetArray) ? datasetArray : [datasetArray]
50+
const elementDataset = Object.keys(node.dataset)
51+
52+
return elementDataset.some(dataset => datasetToMatch.includes(dataset))
53+
}

test/unit/js/lib/eventUtilTest.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
/* global describe, it */
5+
6+
const eventUtil = require('../../../../js/lib/eventUtil')
7+
const assert = require('assert')
8+
9+
require('../../braveUnit')
10+
11+
describe('eventUtil', function () {
12+
describe('elementHasDataset', function () {
13+
let datasetToTest
14+
let node = { dataset: { nespresso: true } }
15+
16+
it('returns false if node dataset do not match', function () {
17+
datasetToTest = ['starbucks', 'keurig']
18+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
19+
})
20+
it('returns true if node dataset match the provided dataset array', function () {
21+
datasetToTest = ['wow', 'such', 'nespresso', 'very', 'amazing']
22+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
23+
})
24+
it('can accept strings for the dataset to match against', function () {
25+
datasetToTest = 'nespresso'
26+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
27+
})
28+
it('can not accept partial string match', function () {
29+
datasetToTest = ['nespressomnibox']
30+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
31+
})
32+
it('returns false if node do not provide a dataset', function () {
33+
node = delete node.dataset
34+
datasetToTest = ['nespresso']
35+
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
36+
})
37+
})
38+
})

0 commit comments

Comments
 (0)