How to use _updateSelectionAfterDeletionContent method in Testcafe

Best JavaScript code snippet using testcafe

Run Testcafe automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

type-char.js

Source: type-char.js Github

copy
1import hammerhead from '../../deps/hammerhead';
2import testCafeCore from '../../deps/testcafe-core';
3import nextTick from '../../utils/next-tick';
4
5var browserUtils   = hammerhead.utils.browser;
6var eventSimulator = hammerhead.eventSandbox.eventSimulator;
7var listeners      = hammerhead.eventSandbox.listeners;
8
9var domUtils        = testCafeCore.domUtils;
10var contentEditable = testCafeCore.contentEditable;
11var textSelection   = testCafeCore.textSelection;
12
13
14function _getSelectionInElement (element) {
15    var currentSelection   = textSelection.getSelectionByElement(element);
16    var isInverseSelection = textSelection.hasInverseSelectionContentEditable(element);
17
18    if (textSelection.hasElementContainsSelection(element))
19        return contentEditable.getSelection(element, currentSelection, isInverseSelection);
20
21    // NOTE: if we type text to an element that doesn't contain selection we
22    // assume the selectionStart and selectionEnd positions are null in this
23    // element. So we calculate the necessary start and end nodes and offsets
24    return {
25        startPos: contentEditable.calculateNodeAndOffsetByPosition(element, 0),
26        endPos:   contentEditable.calculateNodeAndOffsetByPosition(element, 0)
27    };
28}
29
30function _updateSelectionAfterDeletionContent (element, selection) {
31    var startNode      = selection.startPos.node;
32    var hasStartParent = startNode.parentNode && startNode.parentElement;
33
34    if (browserUtils.isWebKit || !hasStartParent || !domUtils.isElementContainsNode(element, startNode)) {
35        selection = _getSelectionInElement(element);
36
37        if (textSelection.hasInverseSelectionContentEditable(element)) {
38            selection = {
39                startPos: selection.endPos,
40                endPos:   selection.startPos
41            };
42        }
43    }
44
45    selection.endPos.offset = selection.startPos.offset;
46
47    return selection;
48}
49
50function _typeCharInElementNode (elementNode, text) {
51    var nodeForTyping  = document.createTextNode(text);
52    var textLength     = text.length;
53    var selectPosition = { node: nodeForTyping, offset: textLength };
54
55    if (domUtils.getTagName(elementNode) === 'br')
56        elementNode.parentNode.insertBefore(nodeForTyping, elementNode);
57    else
58        elementNode.appendChild(nodeForTyping);
59
60    textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
61}
62
63function _excludeInvisibleSymbolsFromSelection (selection) {
64    var startNode   = selection.startPos.node;
65    var startOffset = selection.startPos.offset;
66    var endOffset   = selection.endPos.offset;
67
68    var firstNonWhitespaceSymbolIndex = contentEditable.getFirstNonWhitespaceSymbolIndex(startNode.nodeValue);
69    var lastNonWhitespaceSymbolIndex  = contentEditable.getLastNonWhitespaceSymbolIndex(startNode.nodeValue);
70
71    if (startOffset < firstNonWhitespaceSymbolIndex && startOffset !== 0) {
72        selection.startPos.offset = firstNonWhitespaceSymbolIndex;
73        selection.endPos.offset   = endOffset + firstNonWhitespaceSymbolIndex - startOffset;
74    }
75    else if (endOffset > lastNonWhitespaceSymbolIndex && endOffset !== startNode.nodeValue.length) {
76        selection.startPos.offset = startNode.nodeValue.length;
77        selection.endPos.offset   = endOffset + startNode.nodeValue.length - startOffset;
78    }
79
80    return selection;
81}
82
83function _typeCharToContentEditable (element, text) {
84    var currentSelection = _getSelectionInElement(element);
85    var startNode        = currentSelection.startPos.node;
86    var endNode          = currentSelection.endPos.node;
87
88    // NOTE: some browsers raise the 'input' event after the element
89    // content is changed, but in others we should do it manually.
90    var inputEventRaised = false;
91
92    var onInput = () => {
93        inputEventRaised = true;
94    };
95
96    var afterContentChanged = () => {
97        nextTick()
98            .then(() => {
99                if (!inputEventRaised)
100                    eventSimulator.input(element);
101
102                listeners.removeInternalEventListener(window, 'input', onInput);
103            });
104    };
105
106    listeners.addInternalEventListener(window, ['input'], onInput);
107
108    if (!startNode || !endNode || !domUtils.isContentEditableElement(startNode) ||
109        !domUtils.isContentEditableElement(endNode))
110        return;
111
112    if (!domUtils.isTheSameNode(startNode, endNode)) {
113        textSelection.deleteSelectionContents(element);
114
115        // NOTE: after deleting the selection contents we should refresh the stored startNode because
116        // contentEditable element's content could change and we can no longer find parent elements
117        // of the nodes. In MSEdge, 'parentElement' for the deleted element isn't undefined
118        currentSelection = _updateSelectionAfterDeletionContent(element, currentSelection);
119        startNode        = currentSelection.startPos.node;
120    }
121
122    if (!startNode || !domUtils.isContentEditableElement(startNode) || !domUtils.isRenderedNode(startNode))
123        return;
124
125    // NOTE: we can type only to the text nodes; for nodes with the 'element-node' type, we use a special behavior
126    if (domUtils.isElementNode(startNode)) {
127        _typeCharInElementNode(startNode, text);
128
129        afterContentChanged();
130        return;
131    }
132
133    currentSelection = _excludeInvisibleSymbolsFromSelection(currentSelection);
134    startNode        = currentSelection.startPos.node;
135
136    var startOffset    = currentSelection.startPos.offset;
137    var endOffset      = currentSelection.endPos.offset;
138    var nodeValue      = startNode.nodeValue;
139    var selectPosition = { node: startNode, offset: startOffset + text.length };
140
141    startNode.nodeValue = nodeValue.substring(0, startOffset) + text +
142                          nodeValue.substring(endOffset, nodeValue.length);
143
144    textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
145
146    afterContentChanged();
147}
148
149function _typeCharToTextEditable (element, text) {
150    var elementValue      = element.value;
151    var textLength        = text.length;
152    var startSelection    = textSelection.getSelectionStart(element);
153    var endSelection      = textSelection.getSelectionEnd(element);
154    var isInputTypeNumber = domUtils.isInputElement(element) && element.type === 'number';
155
156    // NOTE: the 'maxlength' attribute doesn't work in all browsers. IE still doesn't support input with the 'number' type
157    var elementMaxLength = !browserUtils.isIE && isInputTypeNumber ? null : parseInt(element.maxLength, 10);
158
159    if (elementMaxLength < 0)
160        elementMaxLength = browserUtils.isIE ? 0 : null;
161
162    if (elementMaxLength === null || isNaN(elementMaxLength) || elementMaxLength > elementValue.length) {
163        // NOTE: B254013
164        if (isInputTypeNumber && browserUtils.isIOS && elementValue[elementValue.length - 1] === '.') {
165            startSelection += 1;
166            endSelection += 1;
167        }
168
169        element.value = elementValue.substring(0, startSelection) + text +
170                        elementValue.substring(endSelection, elementValue.length);
171
172        textSelection.select(element, startSelection + textLength, startSelection + textLength);
173    }
174
175    // NOTE: We should simulate the 'input' event after typing a char (B253410, T138385)
176    eventSimulator.input(element);
177}
178
179export default function (element, text) {
180    if (domUtils.isContentEditableElement(element))
181        _typeCharToContentEditable(element, text === ' ' ? String.fromCharCode(160) : text);
182
183    if (domUtils.isTextEditableElementAndEditingAllowed(element))
184        _typeCharToTextEditable(element, text);
185}
186
Full Screen

type-text.js

Source: type-text.js Github

copy
1import hammerhead from '../../deps/hammerhead';
2import testCafeCore from '../../deps/testcafe-core';
3import nextTick from '../../utils/next-tick';
4
5var browserUtils   = hammerhead.utils.browser;
6var eventSimulator = hammerhead.eventSandbox.eventSimulator;
7var listeners      = hammerhead.eventSandbox.listeners;
8
9var domUtils        = testCafeCore.domUtils;
10var contentEditable = testCafeCore.contentEditable;
11var textSelection   = testCafeCore.textSelection;
12
13
14function _getSelectionInElement (element) {
15    var currentSelection   = textSelection.getSelectionByElement(element);
16    var isInverseSelection = textSelection.hasInverseSelectionContentEditable(element);
17
18    if (textSelection.hasElementContainsSelection(element))
19        return contentEditable.getSelection(element, currentSelection, isInverseSelection);
20
21    // NOTE: if we type text to an element that doesn't contain selection we
22    // assume the selectionStart and selectionEnd positions are null in this
23    // element. So we calculate the necessary start and end nodes and offsets
24    return {
25        startPos: contentEditable.calculateNodeAndOffsetByPosition(element, 0),
26        endPos:   contentEditable.calculateNodeAndOffsetByPosition(element, 0)
27    };
28}
29
30function _updateSelectionAfterDeletionContent (element, selection) {
31    var startNode      = selection.startPos.node;
32    var hasStartParent = startNode.parentNode && startNode.parentElement;
33
34    var browserRequiresSelectionUpdating = browserUtils.isChrome && browserUtils.version < 58 || browserUtils.isSafari;
35
36    if (browserRequiresSelectionUpdating || !hasStartParent || !domUtils.isElementContainsNode(element, startNode)) {
37        selection = _getSelectionInElement(element);
38
39        if (textSelection.hasInverseSelectionContentEditable(element)) {
40            selection = {
41                startPos: selection.endPos,
42                endPos:   selection.startPos
43            };
44        }
45    }
46
47    selection.endPos.offset = selection.startPos.offset;
48
49    return selection;
50}
51
52function _typeTextInElementNode (elementNode, text) {
53    var nodeForTyping  = document.createTextNode(text);
54    var textLength     = text.length;
55    var selectPosition = { node: nodeForTyping, offset: textLength };
56
57    if (domUtils.getTagName(elementNode) === 'br')
58        elementNode.parentNode.insertBefore(nodeForTyping, elementNode);
59    else
60        elementNode.appendChild(nodeForTyping);
61
62    textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
63}
64
65function _excludeInvisibleSymbolsFromSelection (selection) {
66    var startNode   = selection.startPos.node;
67    var startOffset = selection.startPos.offset;
68    var endOffset   = selection.endPos.offset;
69
70    var firstNonWhitespaceSymbolIndex = contentEditable.getFirstNonWhitespaceSymbolIndex(startNode.nodeValue);
71    var lastNonWhitespaceSymbolIndex  = contentEditable.getLastNonWhitespaceSymbolIndex(startNode.nodeValue);
72
73    if (startOffset < firstNonWhitespaceSymbolIndex && startOffset !== 0) {
74        selection.startPos.offset = firstNonWhitespaceSymbolIndex;
75        selection.endPos.offset   = endOffset + firstNonWhitespaceSymbolIndex - startOffset;
76    }
77    else if (endOffset > lastNonWhitespaceSymbolIndex && endOffset !== startNode.nodeValue.length) {
78        selection.startPos.offset = startNode.nodeValue.length;
79        selection.endPos.offset   = endOffset + startNode.nodeValue.length - startOffset;
80    }
81
82    return selection;
83}
84
85function _typeTextToContentEditable (element, text) {
86    var currentSelection = _getSelectionInElement(element);
87    var startNode        = currentSelection.startPos.node;
88    var endNode          = currentSelection.endPos.node;
89
90    // NOTE: some browsers raise the 'input' event after the element
91    // content is changed, but in others we should do it manually.
92    var inputEventRaised = false;
93
94    var onInput = () => {
95        inputEventRaised = true;
96    };
97
98    var afterContentChanged = () => {
99        nextTick()
100            .then(() => {
101                if (!inputEventRaised)
102                    eventSimulator.input(element);
103
104                listeners.removeInternalEventListener(window, 'input', onInput);
105            });
106    };
107
108    listeners.addInternalEventListener(window, ['input'], onInput);
109
110    if (!startNode || !endNode || !domUtils.isContentEditableElement(startNode) ||
111        !domUtils.isContentEditableElement(endNode))
112        return;
113
114    if (!domUtils.isTheSameNode(startNode, endNode)) {
115        textSelection.deleteSelectionContents(element);
116
117        // NOTE: after deleting the selection contents we should refresh the stored startNode because
118        // contentEditable element's content could change and we can no longer find parent elements
119        // of the nodes. In MSEdge, 'parentElement' for the deleted element isn't undefined
120        currentSelection = _updateSelectionAfterDeletionContent(element, currentSelection);
121        startNode        = currentSelection.startPos.node;
122    }
123
124    if (!startNode || !domUtils.isContentEditableElement(startNode) || !domUtils.isRenderedNode(startNode))
125        return;
126
127    // NOTE: we can type only to the text nodes; for nodes with the 'element-node' type, we use a special behavior
128    if (domUtils.isElementNode(startNode)) {
129        _typeTextInElementNode(startNode, text);
130
131        afterContentChanged();
132        return;
133    }
134
135    currentSelection = _excludeInvisibleSymbolsFromSelection(currentSelection);
136    startNode        = currentSelection.startPos.node;
137
138    var startOffset    = currentSelection.startPos.offset;
139    var endOffset      = currentSelection.endPos.offset;
140    var nodeValue      = startNode.nodeValue;
141    var selectPosition = { node: startNode, offset: startOffset + text.length };
142
143    startNode.nodeValue = nodeValue.substring(0, startOffset) + text +
144                          nodeValue.substring(endOffset, nodeValue.length);
145
146    textSelection.selectByNodesAndOffsets(selectPosition, selectPosition);
147
148    afterContentChanged();
149}
150
151function _typeTextToTextEditable (element, text) {
152    var elementValue      = domUtils.getElementValue(element);
153    var textLength        = text.length;
154    var startSelection    = textSelection.getSelectionStart(element);
155    var endSelection      = textSelection.getSelectionEnd(element);
156    var isInputTypeNumber = domUtils.isInputElement(element) && element.type === 'number';
157
158    // NOTE: the 'maxlength' attribute doesn't work in all browsers. IE still doesn't support input with the 'number' type
159    var elementMaxLength = !browserUtils.isIE && isInputTypeNumber ? null : parseInt(element.maxLength, 10);
160
161    if (elementMaxLength < 0)
162        elementMaxLength = browserUtils.isIE ? 0 : null;
163
164    if (elementMaxLength === null || isNaN(elementMaxLength) || elementMaxLength > elementValue.length) {
165        // NOTE: B254013
166        if (isInputTypeNumber && browserUtils.isIOS && elementValue[elementValue.length - 1] === '.') {
167            startSelection += 1;
168            endSelection += 1;
169        }
170
171        domUtils.setElementValue(element, elementValue.substring(0, startSelection) + text +
172                          elementValue.substring(endSelection, elementValue.length));
173
174        textSelection.select(element, startSelection + textLength, startSelection + textLength);
175    }
176
177    // NOTE: We should simulate the 'input' event after typing a char (B253410, T138385)
178    eventSimulator.input(element);
179}
180
181function _typeTextToNonTextEditable (element, text, caretPos) {
182    if (caretPos !== null) {
183        var elementValue = domUtils.getElementValue(element);
184
185        domUtils.setElementValue(element, elementValue.substr(0, caretPos) + text + elementValue.substr(caretPos + text.length));
186    }
187    else
188        domUtils.setElementValue(element, text);
189
190    eventSimulator.change(element);
191    eventSimulator.input(element);
192}
193
194export default function (element, text, caretPos) {
195    if (domUtils.isContentEditableElement(element))
196        _typeTextToContentEditable(element, text === ' ' ? String.fromCharCode(160) : text);
197
198    if (!domUtils.isElementReadOnly(element)) {
199        if (domUtils.isTextEditableElement(element))
200            _typeTextToTextEditable(element, text);
201
202        else if (domUtils.isInputElement(element))
203            _typeTextToNonTextEditable(element, text, caretPos);
204    }
205}
206
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Testcafe on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)