From 5fe702328dcbee6fe15ec6e57738ec36194f6b28 Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Tue, 27 Mar 2018 14:16:01 +0300 Subject: [PATCH] [WIP]Should type in contenteditable div even if it has invisible child with contenteditable=false (closes #2205) --- src/client/core/utils/content-editable.js | 10 +- src/client/core/utils/style.js | 17 +--- .../regression/gh-2205/pages/index.html | 92 +++++++++++++++++++ .../fixtures/regression/gh-2205/test.js | 5 + .../gh-2205/testcafe-fixtures/index.js | 23 +++++ 5 files changed, 129 insertions(+), 18 deletions(-) create mode 100644 test/functional/fixtures/regression/gh-2205/pages/index.html create mode 100644 test/functional/fixtures/regression/gh-2205/test.js create mode 100644 test/functional/fixtures/regression/gh-2205/testcafe-fixtures/index.js diff --git a/src/client/core/utils/content-editable.js b/src/client/core/utils/content-editable.js index bb639ead888..2f0fa027cae 100644 --- a/src/client/core/utils/content-editable.js +++ b/src/client/core/utils/content-editable.js @@ -1,5 +1,6 @@ import * as domUtils from './dom'; import * as arrayUtils from './array'; +import * as styleUtils from './style'; //nodes utils @@ -397,13 +398,18 @@ export function calculateNodeAndOffsetByPosition (el, offset) { } } else if (domUtils.isElementNode(target)) { - if (point.offset === 0 && !getContentEditableValue(target).length) { + if (!styleUtils.isElementVisible(target)) + return point; + + const isBreakElement = !childNodesLength && domUtils.getTagName(target) === 'br'; + + if (!isBreakElement && point.offset === 0 && !getContentEditableValue(target).length) { point.node = target; return point; } if (!point.node && (isNodeBlockWithBreakLine(el, target) || isNodeAfterNodeBlockWithBreakLine(el, target))) point.offset--; - else if (!childNodesLength && domUtils.isElementNode(target) && domUtils.getTagName(target) === 'br') + else if (isBreakElement) point.offset--; } diff --git a/src/client/core/utils/style.js b/src/client/core/utils/style.js index 7e9ca57fa89..de496e3a610 100644 --- a/src/client/core/utils/style.js +++ b/src/client/core/utils/style.js @@ -12,6 +12,7 @@ export var getElementPadding = hammerhead.utils.style.getElementPadding; export var getElementScroll = hammerhead.utils.style.getElementScroll; export var getOptionHeight = hammerhead.utils.style.getOptionHeight; export var getSelectElementSize = hammerhead.utils.style.getSelectElementSize; +export var isElementVisible = hammerhead.utils.style.isElementVisible; export var isSelectVisibleChild = hammerhead.utils.style.isVisibleChild; export var getWidth = hammerhead.utils.style.getWidth; export var getHeight = hammerhead.utils.style.getHeight; @@ -135,22 +136,6 @@ export function hasDimensions (el) { return el && !(el.offsetHeight <= 0 && el.offsetWidth <= 0); } -export function isElementHidden (el) { - //NOTE: it's like jquery ':hidden' selector - if (get(el, 'display') === 'none' || !hasDimensions(el) || el.type && el.type === 'hidden') - return true; - - var elements = domUtils.findDocument(el).querySelectorAll('*'); - var hiddenElements = []; - - for (var i = 0; i < elements.length; i++) { - if (get(elements[i], 'display') === 'none' || !hasDimensions(elements[i])) - hiddenElements.push(elements[i]); - } - - return domUtils.containsElement(hiddenElements, el); -} - export function set (el, style, value) { if (typeof style === 'string') styleUtils.set(el, style, value); diff --git a/test/functional/fixtures/regression/gh-2205/pages/index.html b/test/functional/fixtures/regression/gh-2205/pages/index.html new file mode 100644 index 00000000000..12f5926bd8a --- /dev/null +++ b/test/functional/fixtures/regression/gh-2205/pages/index.html @@ -0,0 +1,92 @@ + + + + + Title + + + + +

Display: none

+
+
+
+ +

Visibility: hidden

+
+
+
+ +
Type here...
+
Type here...
+ + + + \ No newline at end of file diff --git a/test/functional/fixtures/regression/gh-2205/test.js b/test/functional/fixtures/regression/gh-2205/test.js new file mode 100644 index 00000000000..e947b52eb4e --- /dev/null +++ b/test/functional/fixtures/regression/gh-2205/test.js @@ -0,0 +1,5 @@ +describe('[Regression](GH-2205)', function () { + it('Should type in div if it has an invisible child with contententeditable=false', function () { + return runTests('testcafe-fixtures/index.js'); + }); +}); diff --git a/test/functional/fixtures/regression/gh-2205/testcafe-fixtures/index.js b/test/functional/fixtures/regression/gh-2205/testcafe-fixtures/index.js new file mode 100644 index 00000000000..01d5188e559 --- /dev/null +++ b/test/functional/fixtures/regression/gh-2205/testcafe-fixtures/index.js @@ -0,0 +1,23 @@ +import { Selector } from 'testcafe'; + +fixture `GH-2205 - Should type in div if it has an invisible child with contententeditable=false` + .page `http://localhost:3000/fixtures/regression/gh-2205/pages/index.html`; + +async function typeAndCheck (t, editorId) { + const editor = Selector(editorId); + + await t + .click(editor) + .typeText(editor, 'H') + .expect(editor.innerText).contains('H'); +} + +test(`Click on div with display:none placeholder`, async t => { + await typeAndCheck(t, '#editor1'); +}); + +test(`Click on div with visibility:hidden placeholder`, async t => { + await typeAndCheck(t, '#editor2'); +}); + +