Skip to content

Commit a8fd2db

Browse files
committed
Adapt restoreSelection to work for *all* activeElements
1 parent 6b17090 commit a8fd2db

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

Diff for: src/renderers/dom/client/ReactInputSelection.js

+61-17
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,39 @@ function getFocusedElement() {
3535
return focusedElem;
3636
}
3737

38+
function getElementsWithSelections(acc, win) {
39+
acc = acc || [];
40+
win = win || window;
41+
var doc;
42+
try {
43+
doc = win.document;
44+
} catch (e) {
45+
return acc;
46+
}
47+
var element = null;
48+
if (win.getSelection) {
49+
var selection = win.getSelection();
50+
var startNode = selection.anchorNode;
51+
var endNode = selection.focusNode;
52+
var startOffset = selection.anchorOffset;
53+
var endOffset = selection.focusOffset;
54+
if (startNode.childNodes.length) {
55+
if (startNode.childNodes[startOffset] === endNode.childNodes[endOffset]) {
56+
element = startNode.childNodes[startOffset];
57+
}
58+
} else {
59+
element = startNode;
60+
}
61+
} else if (doc.selection) {
62+
var range = doc.selection.createRange();
63+
element = range.parentElement();
64+
}
65+
if (ReactInputSelection.hasSelectionCapabilities(element)) {
66+
acc = acc.concat(element);
67+
}
68+
return Array.prototype.reduce.call(win.frames, getElementsWithSelections, acc);
69+
}
70+
3871
/**
3972
* @ReactInputSelection: React input selection module. Based on Selection.js,
4073
* but modified to be suitable for react and has a couple of bug fixes (doesn't
@@ -53,13 +86,15 @@ var ReactInputSelection = {
5386
},
5487

5588
getSelectionInformation: function() {
56-
var focusedElem = getFocusedElement();
89+
var focusedElement = getFocusedElement();
5790
return {
58-
focusedElem: focusedElem,
59-
selectionRange:
60-
ReactInputSelection.hasSelectionCapabilities(focusedElem) ?
61-
ReactInputSelection.getSelection(focusedElem) :
62-
null,
91+
focusedElement: focusedElement,
92+
activeElements: getElementsWithSelections().map(function(element) {
93+
return {
94+
element: element,
95+
selectionRange: ReactInputSelection.getSelection(element),
96+
};
97+
}),
6398
};
6499
},
65100

@@ -69,18 +104,27 @@ var ReactInputSelection = {
69104
* nodes and place them back in, resulting in focus being lost.
70105
*/
71106
restoreSelection: function(priorSelectionInformation) {
72-
var curFocusedElem = getFocusedElement();
73-
var priorFocusedElem = priorSelectionInformation.focusedElem;
74-
var priorSelectionRange = priorSelectionInformation.selectionRange;
75-
if (curFocusedElem !== priorFocusedElem &&
76-
isInDocument(priorFocusedElem)) {
77-
if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
78-
ReactInputSelection.setSelection(
79-
priorFocusedElem,
80-
priorSelectionRange
81-
);
107+
priorSelectionInformation.activeElements.forEach(function(activeElement) {
108+
var element = activeElement.element;
109+
if (!isInDocument(element) ||
110+
getActiveElement(element.ownerDocument) === element) {
111+
return;
82112
}
83-
focusNode(priorFocusedElem);
113+
if (!ReactInputSelection.hasSelectionCapabilities(element)) {
114+
return;
115+
}
116+
ReactInputSelection.setSelection(
117+
element,
118+
activeElement.selectionRange
119+
);
120+
focusNode(element);
121+
});
122+
123+
var curFocusedElement = getFocusedElement();
124+
var priorFocusedElement = priorSelectionInformation.focusedElement;
125+
if (curFocusedElement !== priorFocusedElement &&
126+
isInDocument(priorFocusedElement)) {
127+
focusNode(priorFocusedElement);
84128
}
85129
},
86130

Diff for: src/renderers/dom/client/__tests__/ReactInputSelection-test.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,9 @@ describe('ReactInputSelection', () => {
157157
input.selectionStart = 1;
158158
input.selectionEnd = 10;
159159
var selectionInfo = ReactInputSelection.getSelectionInformation();
160-
expect(selectionInfo.focusedElem).toBe(input);
161-
expect(selectionInfo.selectionRange).toEqual({start: 1, end: 10});
160+
expect(selectionInfo.focusedElement).toBe(input);
161+
expect(selectionInfo.activeElements[0].element).toBe(input);
162+
expect(selectionInfo.activeElements[0].selectionRange).toEqual({start: 1, end: 10});
162163
expect(document.activeElement).toBe(input);
163164
input.setSelectionRange(0, 0);
164165
document.body.removeChild(input);

0 commit comments

Comments
 (0)