Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81155 views
1
/**
2
* Copyright 2013-2014, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule ReactInputSelection
10
*/
11
12
"use strict";
13
14
var ReactDOMSelection = require('ReactDOMSelection');
15
16
var containsNode = require('containsNode');
17
var focusNode = require('focusNode');
18
var getActiveElement = require('getActiveElement');
19
20
function isInDocument(node) {
21
return containsNode(document.documentElement, node);
22
}
23
24
/**
25
* @ReactInputSelection: React input selection module. Based on Selection.js,
26
* but modified to be suitable for react and has a couple of bug fixes (doesn't
27
* assume buttons have range selections allowed).
28
* Input selection module for React.
29
*/
30
var ReactInputSelection = {
31
32
hasSelectionCapabilities: function(elem) {
33
return elem && (
34
(elem.nodeName === 'INPUT' && elem.type === 'text') ||
35
elem.nodeName === 'TEXTAREA' ||
36
elem.contentEditable === 'true'
37
);
38
},
39
40
getSelectionInformation: function() {
41
var focusedElem = getActiveElement();
42
return {
43
focusedElem: focusedElem,
44
selectionRange:
45
ReactInputSelection.hasSelectionCapabilities(focusedElem) ?
46
ReactInputSelection.getSelection(focusedElem) :
47
null
48
};
49
},
50
51
/**
52
* @restoreSelection: If any selection information was potentially lost,
53
* restore it. This is useful when performing operations that could remove dom
54
* nodes and place them back in, resulting in focus being lost.
55
*/
56
restoreSelection: function(priorSelectionInformation) {
57
var curFocusedElem = getActiveElement();
58
var priorFocusedElem = priorSelectionInformation.focusedElem;
59
var priorSelectionRange = priorSelectionInformation.selectionRange;
60
if (curFocusedElem !== priorFocusedElem &&
61
isInDocument(priorFocusedElem)) {
62
if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
63
ReactInputSelection.setSelection(
64
priorFocusedElem,
65
priorSelectionRange
66
);
67
}
68
focusNode(priorFocusedElem);
69
}
70
},
71
72
/**
73
* @getSelection: Gets the selection bounds of a focused textarea, input or
74
* contentEditable node.
75
* -@input: Look up selection bounds of this input
76
* -@return {start: selectionStart, end: selectionEnd}
77
*/
78
getSelection: function(input) {
79
var selection;
80
81
if ('selectionStart' in input) {
82
// Modern browser with input or textarea.
83
selection = {
84
start: input.selectionStart,
85
end: input.selectionEnd
86
};
87
} else if (document.selection && input.nodeName === 'INPUT') {
88
// IE8 input.
89
var range = document.selection.createRange();
90
// There can only be one selection per document in IE, so it must
91
// be in our element.
92
if (range.parentElement() === input) {
93
selection = {
94
start: -range.moveStart('character', -input.value.length),
95
end: -range.moveEnd('character', -input.value.length)
96
};
97
}
98
} else {
99
// Content editable or old IE textarea.
100
selection = ReactDOMSelection.getOffsets(input);
101
}
102
103
return selection || {start: 0, end: 0};
104
},
105
106
/**
107
* @setSelection: Sets the selection bounds of a textarea or input and focuses
108
* the input.
109
* -@input Set selection bounds of this input or textarea
110
* -@offsets Object of same form that is returned from get*
111
*/
112
setSelection: function(input, offsets) {
113
var start = offsets.start;
114
var end = offsets.end;
115
if (typeof end === 'undefined') {
116
end = start;
117
}
118
119
if ('selectionStart' in input) {
120
input.selectionStart = start;
121
input.selectionEnd = Math.min(end, input.value.length);
122
} else if (document.selection && input.nodeName === 'INPUT') {
123
var range = input.createTextRange();
124
range.collapse(true);
125
range.moveStart('character', start);
126
range.moveEnd('character', end - start);
127
range.select();
128
} else {
129
ReactDOMSelection.setOffsets(input, offsets);
130
}
131
}
132
};
133
134
module.exports = ReactInputSelection;
135
136