Skip to content

Commit

Permalink
1
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKamaev committed Apr 11, 2018
1 parent 87ff50b commit 2bc8b23
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 9 deletions.
31 changes: 22 additions & 9 deletions src/client/automation/playback/type/type-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function _typeTextToContentEditable (element, text) {
var currentSelection = _getSelectionInElement(element);
var startNode = currentSelection.startPos.node;
var endNode = currentSelection.endPos.node;
var needRaiseInput = true;

// NOTE: some browsers raise the 'input' event after the element
// content is changed, but in others we should do it manually.
Expand All @@ -95,13 +96,17 @@ function _typeTextToContentEditable (element, text) {
inputEventRaised = true;
};

var beforeContentChanged = () => {
needRaiseInput = !eventSimulator.textInput || eventSimulator.textInput(element, text);
};

var afterContentChanged = () => {
nextTick()
.then(() => {
if (!inputEventRaised)
if (!inputEventRaised && needRaiseInput)
eventSimulator.input(element);

listeners.removeInternalEventListener(window, 'input', onInput);
listeners.removeInternalEventListener(window, ['input'], onInput);
});
};

Expand Down Expand Up @@ -135,15 +140,23 @@ function _typeTextToContentEditable (element, text) {
currentSelection = _excludeInvisibleSymbolsFromSelection(currentSelection);
startNode = currentSelection.startPos.node;

var startOffset = currentSelection.startPos.offset;
var endOffset = currentSelection.endPos.offset;
var nodeValue = startNode.nodeValue;
var selectPosition = { node: startNode, offset: startOffset + text.length };
beforeContentChanged();

startNode.nodeValue = nodeValue.substring(0, startOffset) + text +
nodeValue.substring(endOffset, nodeValue.length);
if (needRaiseInput) {
if (!domUtils.isElementContainsNode(element, startNode)) {
currentSelection = _excludeInvisibleSymbolsFromSelection(_getSelectionInElement(element));
startNode = currentSelection.startPos.node;
}

textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
const startOffset = currentSelection.startPos.offset;
const endOffset = currentSelection.endPos.offset;
const nodeValue = startNode.nodeValue;
const selectPosition = { node: startNode, offset: startOffset + text.length };

startNode.nodeValue = nodeValue.substring(0, startOffset) + text + nodeValue.substring(endOffset, nodeValue.length);

textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
}

afterContentChanged();
}
Expand Down
121 changes: 121 additions & 0 deletions test/functional/fixtures/regression/gh-1956/pages/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<html>
<head><title>Edit test</title></head>
<body>

<div id="root"></div>

<script src="https://unpkg.com/react@15/dist/react.js"></script>
<script src="./react-dom.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom-server.js"></script>
<script src="https://unpkg.com/immutable/dist/immutable.js"></script>
<script src="./slate.js"></script>
<script src="./slate-react.js"></script>
<script>

// document.addEventListener('keypress', function (event) {
// // alert('keypress')
// }, true);
//
document.addEventListener('textInput', function (event) {
debugger;
modifyInput(event)
// event.preventDefault();
}, true);

// document.addEventListener('input', function (event) {
// // debugger
//
// alert('input:' + event.target.innerText)
// }, true);
//
// document.addEventListener('beforeinput', function (event) {
// // alert('beforeinput')
// }, true);
//
// document.onselectionchange = function () {
// // debugger;
// }
//
// function onInput (event) {
// var el = document.getElementById('editor');
// el.innerHTML = el.innerHTML;
// }

const initialValue = Slate.Value.fromJSON({
document: {
nodes: [
{
kind: 'block',
type: 'paragraph',
nodes: [
{
kind: 'text',
leaves: [
{
text: ''
}
]
}
]
}
]
}
})
class App extends React.Component {
constructor() {
super()
this.state = {
value: initialValue
};

window.value = () => this.state.value;
}
onChange({value}) {
// debugger

if(value.selection.anchorOffset === 32) {
debugger;
}
this.setState({value})
}
render() {
// debugger
return React.createElement(SlateReact.Editor, {value: this.state.value, onChange: this.onChange.bind(this) })
}
}
ReactDOM.render(React.createElement(App), document.getElementById('root'))

setInterval(function() { console.log(window.value().selection.anchorOffset) }, 0)

</script>

<!--<div data-reactroot="" data-slate-editor="true" data-key="1" contenteditable="true" autocorrect="on" spellcheck="true" role="textbox" data-gramm="false" style="outline: none; white-space: pre-wrap; word-wrap: break-word; -webkit-user-modify: read-write-plaintext-only;"><div data-key="2" style="position: relative;"><span data-key="3"><span data-offset-key="3:0">A line of text in a paragraph.</span></span></div></div>-->

<style>
div {
/*background-color: red;*/
}
span {
background-color: yellow;
}

</style>


<div data-reactroot="" data-slate-editor="true" data-key="1a" contenteditable="true" autocorrect="on" spellcheck="true" role="textbox" data-gramm="false" style="outline: none; white-space: pre-wrap; word-wrap: break-word; -webkit-user-modify: read-write-plaintext-only;"><div data-key="2a" style="position: relative;"><span data-key="3a"><span data-offset-key="3:0a">A line of text in a paragraph.</span></span></div></div>

<div id="editor" style="width: 200px; height: 40px; border: 1px solid black;" contenteditable="true" oninput="onInput(event)"></div>

input

<script>
function modifyInput (e) {
debugger
e.target.value += 'bc';
}
</script>

<input value="a" type="text"/>

</body>
</html>
48 changes: 48 additions & 0 deletions test/functional/fixtures/regression/gh-1956/pages/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<html>
<head><title>Edit test</title></head>
<script type="text/javascript">
function onTextInput (event) {
if (event.target.id === 'input1')
onTextInput1(event);
if (event.target.id === 'input2')
onTextInput2(event);
}

function onTextInput1 (event) {
event.target.childNodes[0].childNodes[0].nodeValue += event.data;
event.preventDefault();
}

function onTextInput2 (event) {
if (window.preventNextElementReplacement)
return;

window.preventNextElementReplacement = true;

var div = document.getElementById('input2');
var paragraph = div.childNodes[0];
var textNode = paragraph.childNodes[0];
var newParagraph = document.createElement("P");

newParagraph.innerHTML = 'X';

div.removeChild(paragraph);
div.appendChild(newParagraph);
newParagraph.focus();
}

function onInput (event) {
if (event.target.id === 'input1')
throw new Error('Input on `input1` should be prevented');
}

document.addEventListener('textInput', onTextInput, true);
document.addEventListener('textinput', onTextInput, true);
document.addEventListener('input', onInput, true);

</script>
<body>
<div contenteditable="true" id="input1"><p>A</p></div>
<div contenteditable="true" id="input2"><p>C</p></div>
</body>
</html>
11 changes: 11 additions & 0 deletions test/functional/fixtures/regression/gh-1956/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
describe('[Regression](GH-1956)', function () {
it('Shadow element should not appear in user event handler', function () {
return runTests('testcafe-fixtures/index.js', 'Input should be prevented on TextInput event', { only: 'chrome' });
});

it('Shadow element should not appear in user event handler', function () {
return runTests('testcafe-fixtures/index.js', 'Should type correctly event if startNode of selection was removed on TextInput');
});
});


Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Selector } from 'testcafe';

fixture('test')
.page `http://localhost:3000/fixtures/regression/gh-1956/pages/test.html`;

const input1 = Selector('#input1');
const input2 = Selector('#input2');

test('Input should be prevented on TextInput event', async t => {
await t
.typeText(input1, 'Hello')
.expect(input1.textContent).eql('AHello');
});

test('Should type correctly event if startNode of selection was removed on TextInput', async t => {
await t
.typeText(input2, 'Hello')
.expect(input2.textContent).eql('HelloX');
});

0 comments on commit 2bc8b23

Please sign in to comment.