Skip to content

Commit

Permalink
find suitable zIndex for the adder
Browse files Browse the repository at this point in the history
resolves #2009
  • Loading branch information
esanzgar committed Oct 12, 2020
1 parent 24bf671 commit 701203c
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 5 deletions.
26 changes: 26 additions & 0 deletions dev-server/documents/html/z-index.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis Client Test</title>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h2>z-index test page</h2>
<p>This has a z-index of 0</p>
<ol style="z-index: 20000; position: relative">
<li style="z-index: 25000; position: relative">This has a z-index of 25000</li>
<li style="z-index: 30000; position: relative">This has a z-index of 30000</li>
<li>This has a z-index of 20000 (from parent)</li>
<li>This has a z-index of 20000 (from parent)</li>
<li>This has a z-index of 20000 (from parent)</li>
</ol>
<p>This has a z-index of 0</p>

{{{hypothesisScript}}}
</body>
</html>
1 change: 1 addition & 0 deletions dev-server/templates/index.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<li><a href="/document/burns">Poems and Songs of Robert Burns</a></li>
<li><a href="/document/doyle">The Disappearance of Lady Carfax, by Arthur Conan Doyle</a></li>
<li><a href="/document/tolstoy">Anna Karenina, by Leo Tolstoy</a></li>
<li><a href="/document/z-index">z-index page</a></li>
</ul>

<h2>Test PDF documents</h2>
Expand Down
54 changes: 49 additions & 5 deletions src/annotator/adder.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ export class Adder {
// take position out of layout flow initially
position: 'absolute',
top: 0,

// Assign a high Z-index so that the adder shows above any content on the
// page
zIndex: 10000,
});

this._view = /** @type {Window} */ (container.ownerDocument.defaultView);
Expand Down Expand Up @@ -193,6 +189,51 @@ export class Adder {
return { top, left, arrowDirection };
}

/**
* Find a Z index value that will cause the adder to appear on top of any
* content in the document when the adder is shown at (left, top).
*
* @param {number} left - Horizontal offset from left edge of viewport.
* @param {number} top - Vertical offset from top edge of viewport.
* @return {number} - greatest zIndex (default value of 1)
*/
_findZindex(left, top) {
if (document.elementsFromPoint === undefined) {
// In case of not being able to use `document.elementsFromPoint`,
// default to the large arbitrary number (2^15)
return 32768;
}

const adderWidth = this._width();
const adderHeight = this._height();

// Find the Z index of all the elements in the screen for five positions
// around the adder (left-top, left-bottom, middle-center, right-top,
// right-bottom) and use the greatest.

// Unique elements so `getComputedStyle` is called the minimum amount of times.
const elements = new Set([
...document.elementsFromPoint(left, top),
...document.elementsFromPoint(left, top + adderHeight),
...document.elementsFromPoint(
left + adderWidth / 2,
top + adderHeight / 2
),
...document.elementsFromPoint(left + adderWidth, top),
...document.elementsFromPoint(left + adderWidth, top + adderHeight),
]);

const zIndexes = [...elements]
.map(element => +getComputedStyle(element).zIndex)
.filter(Number.isInteger);

// Make sure the array contains at least one element,
// otherwise `Math.max(...[])` results in +Infinity
zIndexes.push(0);

return Math.max(...zIndexes) + 1;
}

/**
* Show the adder at the given position and with the arrow pointing in
* `arrowDirection`.
Expand All @@ -210,9 +251,12 @@ export class Adder {
const positionedAncestor = nearestPositionedAncestor(this._container);
const parentRect = positionedAncestor.getBoundingClientRect();

const zIndex = this._findZindex(left, top);

Object.assign(this._container.style, {
top: toPx(top - parentRect.top),
left: toPx(left - parentRect.left),
top: toPx(top - parentRect.top),
zIndex,
});

this._isVisible = true;
Expand Down
91 changes: 91 additions & 0 deletions src/annotator/test/adder-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { act } from 'preact/test-utils';
import { createElement } from 'preact';
import { mount } from 'enzyme';

import { Adder, ARROW_POINTING_UP, ARROW_POINTING_DOWN } from '../adder';

Expand Down Expand Up @@ -217,6 +219,95 @@ describe('Adder', () => {
});
});

describe('adder Z index', () => {
let container;

function getAdderZIndex(left, top) {
adderCtrl.showAt(left, top);
return parseInt(adderEl.style.zIndex);
}

beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(() => {
container.remove();
});

it('returns default hard coded value if `document.elementsFromPoint` is not available', () => {
const elementsFromPointBackup = document.elementsFromPoint;
document.elementsFromPoint = undefined;
assert.strictEqual(getAdderZIndex(0, 0), 32768);
document.elementsFromPoint = elementsFromPointBackup;
});

it('returns default value of 1', () => {
// Even if not elements are found, it returns 1
assert.strictEqual(getAdderZIndex(-100000, -100000), 1);
assert.strictEqual(getAdderZIndex(100000, 100000), 1);
});

it('returns the greatest zIndex', () => {
const createComponent = (left, top, zIndex, attachTo) =>
mount(
<div
style={{
position: 'absolute',
width: 1,
height: 1,
left,
top,
zIndex,
}}
/>,
{ attachTo }
);

const wrapper = createComponent(0, 0, 2, container);
assert.strictEqual(getAdderZIndex(0, 0), 3);

const initLeft = 10;
const initTop = 10;
const adderWidth = adderCtrl._width();
const adderHeight = adderCtrl._height();
const wrapperDOMNode = wrapper.getDOMNode();

// Create first element (left-top)
createComponent(initLeft, initTop, 3, wrapperDOMNode);
assert.strictEqual(getAdderZIndex(initLeft, initTop), 4);

// Create second element (left-bottom)
createComponent(initLeft, initTop + adderHeight, 5, wrapperDOMNode);
assert.strictEqual(getAdderZIndex(initLeft, initTop), 6);

// Create third element (middle-center)
createComponent(
initLeft + adderWidth / 2,
initTop + adderHeight / 2,
6,
wrapperDOMNode
);
assert.strictEqual(getAdderZIndex(initLeft, initTop), 7);

// Create fourth element (right-top)
createComponent(initLeft + adderWidth, initTop, 7, wrapperDOMNode);
assert.strictEqual(getAdderZIndex(initLeft, initTop), 8);

// Create third element (right-bottom)
createComponent(
initLeft + adderWidth,
initTop + adderHeight,
8,
wrapperDOMNode
);
assert.strictEqual(getAdderZIndex(initLeft, initTop), 9);

wrapper.unmount();
});
});

describe('#showAt', () => {
context('when the document and body elements have no offset', () => {
it('shows adder at target position', () => {
Expand Down

0 comments on commit 701203c

Please sign in to comment.