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

Commit

Permalink
Merge pull request #10165 from brave/10133
Browse files Browse the repository at this point in the history
do not rely on classList for event target checks
  • Loading branch information
bsclifton authored Aug 1, 2017
2 parents 4009260 + 8bf67b8 commit a562475
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 14 deletions.
2 changes: 1 addition & 1 deletion app/renderer/components/bookmarks/addEditBookmarkHanger.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class AddEditBookmarkHanger extends React.Component {
}

render () {
return <Dialog className={cx({
return <Dialog bookmarkHanger className={cx({
bookmarkDialog: this.props.isModal,
bookmarkHanger: !this.props.isModal,
[css(styles.bookmarkHanger)]: !this.props.isModal
Expand Down
1 change: 1 addition & 0 deletions app/renderer/components/common/browserButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class BrowserButton extends ImmutableComponent {
render () {
return <button
disabled={this.props.disabled}
data-extension-button={this.props.extensionButton}
data-l10n-id={this.props.l10nId}
data-test-id={this.props.testId}
data-test2-id={this.props.test2Id}
Expand Down
1 change: 1 addition & 0 deletions app/renderer/components/common/contextMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ class ContextMenu extends React.Component {
}

return <div
data-context-menu
ref={(node) => { this.node = node }}
className={cx({
contextMenu: true,
Expand Down
12 changes: 7 additions & 5 deletions app/renderer/components/common/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ class Dialog extends ImmutableComponent {
}

render () {
return <div className={cx({
[css(styles.dialog)]: true,
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
[this.props.className]: !!this.props.className
})}
return <div
data-bookmark-hanger={this.props.bookmarkHanger}
className={cx({
[css(styles.dialog)]: true,
[css(styles.dialog_isNotClickDismiss)]: !this.props.isClickDismiss,
[this.props.className]: !!this.props.className
})}
data-test-id={this.props.testId}
data-test2-id={this.props.test2Id}
tabIndex='-1'
Expand Down
17 changes: 9 additions & 8 deletions app/renderer/components/main/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -478,18 +478,19 @@ class Main extends React.Component {
}

onMouseDown (e) {
// TODO(bsclifton): update this to use eventUtil.eventElHasAncestorWithClasses
let node = e.target
const datasets = [
'popupWindow',
'contextMenu',
'extensionButton',
'menubarItem',
'bookmarkHanger'
]
while (node) {
if (node.classList &&
(node.matches('[class^="popupWindow"]') ||
node.classList.contains('contextMenu') ||
node.matches('[class*="extensionButton_"]') ||
node.classList.contains('menubarItem') ||
node.classList.contains('bookmarkHanger'))) {
if (eventUtil.elementHasDataset(node, datasets)) {
// Middle click (on context menu) needs to fire the click event.
// We need to prevent the default "Auto-Scrolling" behavior.
if (node.classList.contains('contextMenu') && e.button === 1) {
if (eventUtil.elementHasDataset(node, 'contextMenu') && e.button === 1) {
e.preventDefault()
}
// Click event is handled downstream
Expand Down
1 change: 1 addition & 0 deletions app/renderer/components/main/popupWindow.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class PopupWindow extends React.Component {
}

return <div
data-popup-window
className={css(
styles.popupWindow,
style.right !== undefined && styles.reverseExpand
Expand Down
1 change: 1 addition & 0 deletions app/renderer/components/navigation/browserAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class BrowserAction extends React.Component {
// TODO(bridiver) should have some visual notification of hover/press
return <div className={css(styles.browserActionButton)}>
<BrowserButton
extensionButton
extensionItem
l10nId='browserActionButton'
testId='extensionBrowserAction'
Expand Down
1 change: 1 addition & 0 deletions app/renderer/components/navigation/menuBarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class MenuBarItem extends React.Component {

render () {
return <span
data-menubar-item
className={'menubarItem' + (this.props.selected ? ' selected' : '')}
onClick={this.onClick}
onMouseOver={this.onMouseOver}
Expand Down
23 changes: 23 additions & 0 deletions js/lib/eventUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ module.exports.isForSecondaryAction = (e) =>
e.button === 1

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

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

return false
}

/**
* Checks if a given node dataset matches a given dataset or array of datasets
* @param {Object} The node to check if dataset is included
* @param {Array|String} the dataset value to check against
* @returns {Boolean} Whether or not the given dataset is included in the check
*/
module.exports.elementHasDataset = (node, datasetArray) => {
if (!node.dataset) {
return false
}

const datasetToMatch = Array.isArray(datasetArray) ? datasetArray : [datasetArray]
const elementDataset = Object.keys(node.dataset)

return elementDataset.some(dataset => datasetToMatch.includes(dataset))
}
38 changes: 38 additions & 0 deletions test/unit/js/lib/eventUtilTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe, it */

const eventUtil = require('../../../../js/lib/eventUtil')
const assert = require('assert')

require('../../braveUnit')

describe('eventUtil', function () {
describe('elementHasDataset', function () {
let datasetToTest
let node = { dataset: { nespresso: true } }

it('returns false if node dataset do not match', function () {
datasetToTest = ['starbucks', 'keurig']
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
})
it('returns true if node dataset match the provided dataset array', function () {
datasetToTest = ['wow', 'such', 'nespresso', 'very', 'amazing']
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
})
it('can accept strings for the dataset to match against', function () {
datasetToTest = 'nespresso'
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), true)
})
it('can not accept partial string match', function () {
datasetToTest = ['nespressomnibox']
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
})
it('returns false if node do not provide a dataset', function () {
node = delete node.dataset
datasetToTest = ['nespresso']
assert.equal(eventUtil.elementHasDataset(node, datasetToTest), false)
})
})
})

0 comments on commit a562475

Please sign in to comment.