Skip to content

Commit

Permalink
Don't autofocus if the entire react-data-grid is offscreen
Browse files Browse the repository at this point in the history
  • Loading branch information
theunixbeard committed Apr 19, 2017
1 parent e0de090 commit 9c0d2f4
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
20 changes: 18 additions & 2 deletions packages/react-data-grid/src/Cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,23 @@ const Cell = React.createClass({
return !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > dragged.rowIdx;
},

isFocusedOnBody() {
isTableOnScreen(dataGridDOMNode) {
// http://stackoverflow.com/a/11193613
const docViewTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
// http://stackoverflow.com/a/28241682
const docViewBottom = docViewTop + (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight);

const elemTop = dataGridDOMNode.offsetTop;
const elemBottom = elemTop + dataGridDOMNode.offsetHeight;

if ((elemTop >= docViewTop && elemTop <= docViewBottom) || (elemBottom >= docViewTop && elemBottom <= docViewBottom)) return true;
return false;
},

isFocusedOnBody(dataGridDOMNode) {
// Make sure the table is on-screen as prerequisite
if (!this.isTableOnScreen(dataGridDOMNode)) return false;

return document.activeElement == null || (document.activeElement.nodeName && typeof document.activeElement.nodeName === 'string' && document.activeElement.nodeName.toLowerCase() === 'body');
},

Expand All @@ -363,7 +379,7 @@ const Cell = React.createClass({
// Only focus to the current cell if the currently active node in the document is within the data grid.
// Meaning focus should not be stolen from elements that the grid doesnt control.
let dataGridDOMNode = this.props.cellMetaData && this.props.cellMetaData.getDataGridDOMNode ? this.props.cellMetaData.getDataGridDOMNode() : null;
if (this.isFocusedOnCell() || this.isFocusedOnBody() || (dataGridDOMNode && dataGridDOMNode.contains(document.activeElement))) {
if (this.isFocusedOnCell() || this.isFocusedOnBody(dataGridDOMNode) || (dataGridDOMNode && dataGridDOMNode.contains(document.activeElement))) {
let cellDOMNode = ReactDOM.findDOMNode(this);
if (cellDOMNode) {
cellDOMNode.focus();
Expand Down
77 changes: 77 additions & 0 deletions packages/react-data-grid/src/__tests__/Focus.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import ReactDataGrid from '../ReactDataGrid';
import { mount } from 'enzyme';

const createRows = () => {
let rows = [];
for (let i = 1; i < 10; i++) {
rows.push({
id: i,
title: 'Title ' + i,
count: i * 1000
});
}
return rows;
};

const renderContainer = () => {
if (document.getElementById('sandbox') === null) {
let sbox = document.createElement('div');
sbox.id = 'sandbox';
sbox.style.width = '600px';
sbox.style.height = '5000px'; // Big enough to scroll out of range
document.body.appendChild(sbox);
sbox.innerHTML += "<div style='width:600px;height:200px' id='gridContainer'></div>";
}
let gridContainer = document.getElementById('gridContainer');
return gridContainer;
};

const renderComponent = (container, extraProps) => {
let rows = createRows();
let testProps = {
columns: [
{ key: 'id', name: 'ID', editable: true },
{ key: 'title', name: 'Title', editable: true },
{ key: 'count', name: 'Count', editable: true }
],
rowGetter: i => { return rows[i]; },
rowsCount: rows.length,
minHeight: 500,
enableCellSelect: true
};

const wrapper = mount(<ReactDataGrid {...testProps} {...extraProps} />, {attachTo: container});
return wrapper;
};

describe('Focus Tests', () => {
let container;
let testElement;

beforeEach(() => {
container = renderContainer();
});

afterEach(function() {
const elem = document.getElementById('sandbox');
elem.parentNode.removeChild(elem);
});

describe('with current focus on the body', function() {
it('should receive focus when onscreen', function() {
expect(document.activeElement).toBe(document.body);
testElement = renderComponent(container);
expect(document.activeElement).toBe(
testElement.find('.react-grid-Cell').first().node
);
});
it('should not receive focus when offscreen', function() {
expect(document.activeElement).toBe(document.body);
window.scrollTo(0, 2000);
expect(document.activeElement).toBe(document.body);
testElement = renderComponent(container);
expect(document.activeElement).toBe(document.body);
});
});
});

0 comments on commit 9c0d2f4

Please sign in to comment.