Daniel@0
|
1 /**
|
Daniel@0
|
2 * jquery-textrange
|
Daniel@0
|
3 * A jQuery plugin for getting, setting and replacing the selected text in input fields and textareas.
|
Daniel@0
|
4 * See the [README](https://github.com/dwieeb/jquery-textrange/blob/1.x/README.md) for usage and examples.
|
Daniel@0
|
5 *
|
Daniel@0
|
6 * (c) 2012-2014 Daniel Imhoff <dwieeb@gmail.com> - danielimhoff.com
|
Daniel@0
|
7 */
|
Daniel@0
|
8
|
Daniel@0
|
9 (function(factory) {
|
Daniel@0
|
10
|
Daniel@0
|
11 if (typeof define === 'function' && define.amd) {
|
Daniel@0
|
12 define(['jquery'], factory);
|
Daniel@0
|
13 } else if (typeof exports === 'object') {
|
Daniel@0
|
14 factory(require('jquery'));
|
Daniel@0
|
15 } else {
|
Daniel@0
|
16 factory(jQuery);
|
Daniel@0
|
17 }
|
Daniel@0
|
18
|
Daniel@0
|
19 })(function($) {
|
Daniel@0
|
20
|
Daniel@0
|
21 var browserType,
|
Daniel@0
|
22
|
Daniel@0
|
23 textrange = {
|
Daniel@0
|
24
|
Daniel@0
|
25 /**
|
Daniel@0
|
26 * $().textrange() or $().textrange('get')
|
Daniel@0
|
27 *
|
Daniel@0
|
28 * Retrieves an object containing the start and end location of the text range, the length of the range and the
|
Daniel@0
|
29 * substring of the range.
|
Daniel@0
|
30 *
|
Daniel@0
|
31 * @param (optional) property
|
Daniel@0
|
32 * @return An object of properties including position, start, end, length, and text or a specific property.
|
Daniel@0
|
33 */
|
Daniel@0
|
34 get: function(property) {
|
Daniel@0
|
35 return _textrange[browserType].get.apply(this, [property]);
|
Daniel@0
|
36 },
|
Daniel@0
|
37
|
Daniel@0
|
38 /**
|
Daniel@0
|
39 * $().textrange('set')
|
Daniel@0
|
40 *
|
Daniel@0
|
41 * Sets the selected text of an object by specifying the start and length of the selection.
|
Daniel@0
|
42 *
|
Daniel@0
|
43 * The start and length parameters are identical to PHP's substr() function with the following changes:
|
Daniel@0
|
44 * - excluding start will select all the text in the field.
|
Daniel@0
|
45 * - passing 0 for length will set the cursor at start. See $().textrange('setcursor')
|
Daniel@0
|
46 *
|
Daniel@0
|
47 * @param (optional) start
|
Daniel@0
|
48 * @param (optional) length
|
Daniel@0
|
49 *
|
Daniel@0
|
50 * @see http://php.net/manual/en/function.substr.php
|
Daniel@0
|
51 */
|
Daniel@0
|
52 set: function(start, length) {
|
Daniel@0
|
53 var s = parseInt(start),
|
Daniel@0
|
54 l = parseInt(length),
|
Daniel@0
|
55 e;
|
Daniel@0
|
56
|
Daniel@0
|
57 if (typeof start === 'undefined') {
|
Daniel@0
|
58 s = 0;
|
Daniel@0
|
59 } else if (start < 0) {
|
Daniel@0
|
60 s = this[0].value.length + s;
|
Daniel@0
|
61 }
|
Daniel@0
|
62
|
Daniel@0
|
63 if (typeof length !== 'undefined') {
|
Daniel@0
|
64 if (length >= 0) {
|
Daniel@0
|
65 e = s + l;
|
Daniel@0
|
66 } else {
|
Daniel@0
|
67 e = this[0].value.length + l;
|
Daniel@0
|
68 }
|
Daniel@0
|
69 }
|
Daniel@0
|
70
|
Daniel@0
|
71 _textrange[browserType].set.apply(this, [s, e]);
|
Daniel@0
|
72
|
Daniel@0
|
73 return this;
|
Daniel@0
|
74 },
|
Daniel@0
|
75
|
Daniel@0
|
76 /**
|
Daniel@0
|
77 * $().textrange('setcursor')
|
Daniel@0
|
78 *
|
Daniel@0
|
79 * Sets the cursor at a position of the text field.
|
Daniel@0
|
80 *
|
Daniel@0
|
81 * @param position
|
Daniel@0
|
82 */
|
Daniel@0
|
83 setcursor: function(position) {
|
Daniel@0
|
84 return this.textrange('set', position, 0);
|
Daniel@0
|
85 },
|
Daniel@0
|
86
|
Daniel@0
|
87 /**
|
Daniel@0
|
88 * $().textrange('replace')
|
Daniel@0
|
89 * Replaces the selected text in the input field or textarea with text.
|
Daniel@0
|
90 *
|
Daniel@0
|
91 * @param text The text to replace the selection with.
|
Daniel@0
|
92 */
|
Daniel@0
|
93 replace: function(text) {
|
Daniel@0
|
94 _textrange[browserType].replace.apply(this, [String(text)]);
|
Daniel@0
|
95
|
Daniel@0
|
96 return this;
|
Daniel@0
|
97 },
|
Daniel@0
|
98
|
Daniel@0
|
99 /**
|
Daniel@0
|
100 * Alias for $().textrange('replace')
|
Daniel@0
|
101 */
|
Daniel@0
|
102 insert: function(text) {
|
Daniel@0
|
103 return this.textrange('replace', text);
|
Daniel@0
|
104 }
|
Daniel@0
|
105 },
|
Daniel@0
|
106
|
Daniel@0
|
107 _textrange = {
|
Daniel@0
|
108 xul: {
|
Daniel@0
|
109 get: function(property) {
|
Daniel@0
|
110 var props = {
|
Daniel@0
|
111 position: this[0].selectionStart,
|
Daniel@0
|
112 start: this[0].selectionStart,
|
Daniel@0
|
113 end: this[0].selectionEnd,
|
Daniel@0
|
114 length: this[0].selectionEnd - this[0].selectionStart,
|
Daniel@0
|
115 text: this.val().substring(this[0].selectionStart, this[0].selectionEnd)
|
Daniel@0
|
116 };
|
Daniel@0
|
117
|
Daniel@0
|
118 return typeof property === 'undefined' ? props : props[property];
|
Daniel@0
|
119 },
|
Daniel@0
|
120
|
Daniel@0
|
121 set: function(start, end) {
|
Daniel@0
|
122 if (typeof end === 'undefined') {
|
Daniel@0
|
123 end = this[0].value.length;
|
Daniel@0
|
124 }
|
Daniel@0
|
125
|
Daniel@0
|
126 this[0].selectionStart = start;
|
Daniel@0
|
127 this[0].selectionEnd = end;
|
Daniel@0
|
128 },
|
Daniel@0
|
129
|
Daniel@0
|
130 replace: function(text) {
|
Daniel@0
|
131 var start = this[0].selectionStart;
|
Daniel@0
|
132 var end = this[0].selectionEnd;
|
Daniel@0
|
133 var val = this.val();
|
Daniel@0
|
134 this.val(val.substring(0, start) + text + val.substring(end, val.length));
|
Daniel@0
|
135 this[0].selectionStart = start;
|
Daniel@0
|
136 this[0].selectionEnd = start + text.length;
|
Daniel@0
|
137 }
|
Daniel@0
|
138 },
|
Daniel@0
|
139
|
Daniel@0
|
140 msie: {
|
Daniel@0
|
141 get: function(property) {
|
Daniel@0
|
142 var range = document.selection.createRange();
|
Daniel@0
|
143
|
Daniel@0
|
144 if (typeof range === 'undefined') {
|
Daniel@0
|
145 var props = {
|
Daniel@0
|
146 position: 0,
|
Daniel@0
|
147 start: 0,
|
Daniel@0
|
148 end: this.val().length,
|
Daniel@0
|
149 length: this.val().length,
|
Daniel@0
|
150 text: this.val()
|
Daniel@0
|
151 };
|
Daniel@0
|
152
|
Daniel@0
|
153 return typeof property === 'undefined' ? props : props[property];
|
Daniel@0
|
154 }
|
Daniel@0
|
155
|
Daniel@0
|
156 var start = 0;
|
Daniel@0
|
157 var end = 0;
|
Daniel@0
|
158 var length = this[0].value.length;
|
Daniel@0
|
159 var lfValue = this[0].value.replace(/\r\n/g, '\n');
|
Daniel@0
|
160 var rangeText = this[0].createTextRange();
|
Daniel@0
|
161 var rangeTextEnd = this[0].createTextRange();
|
Daniel@0
|
162 rangeText.moveToBookmark(range.getBookmark());
|
Daniel@0
|
163 rangeTextEnd.collapse(false);
|
Daniel@0
|
164
|
Daniel@0
|
165 if (rangeText.compareEndPoints('StartToEnd', rangeTextEnd) === -1) {
|
Daniel@0
|
166 start = -rangeText.moveStart('character', -length);
|
Daniel@0
|
167 start += lfValue.slice(0, start).split('\n').length - 1;
|
Daniel@0
|
168
|
Daniel@0
|
169 if (rangeText.compareEndPoints('EndToEnd', rangeTextEnd) === -1) {
|
Daniel@0
|
170 end = -rangeText.moveEnd('character', -length);
|
Daniel@0
|
171 end += lfValue.slice(0, end).split('\n').length - 1;
|
Daniel@0
|
172 } else {
|
Daniel@0
|
173 end = length;
|
Daniel@0
|
174 }
|
Daniel@0
|
175 } else {
|
Daniel@0
|
176 start = length;
|
Daniel@0
|
177 end = length;
|
Daniel@0
|
178 }
|
Daniel@0
|
179
|
Daniel@0
|
180 var props = {
|
Daniel@0
|
181 position: start,
|
Daniel@0
|
182 start: start,
|
Daniel@0
|
183 end: end,
|
Daniel@0
|
184 length: length,
|
Daniel@0
|
185 text: range.text
|
Daniel@0
|
186 };
|
Daniel@0
|
187
|
Daniel@0
|
188 return typeof property === 'undefined' ? props : props[property];
|
Daniel@0
|
189 },
|
Daniel@0
|
190
|
Daniel@0
|
191 set: function(start, end) {
|
Daniel@0
|
192 var range = this[0].createTextRange();
|
Daniel@0
|
193
|
Daniel@0
|
194 if (typeof range === 'undefined') {
|
Daniel@0
|
195 return;
|
Daniel@0
|
196 }
|
Daniel@0
|
197
|
Daniel@0
|
198 if (typeof end === 'undefined') {
|
Daniel@0
|
199 end = this[0].value.length;
|
Daniel@0
|
200 }
|
Daniel@0
|
201
|
Daniel@0
|
202 var ieStart = start - (this[0].value.slice(0, start).split("\r\n").length - 1);
|
Daniel@0
|
203 var ieEnd = end - (this[0].value.slice(0, end).split("\r\n").length - 1);
|
Daniel@0
|
204
|
Daniel@0
|
205 range.collapse(true);
|
Daniel@0
|
206
|
Daniel@0
|
207 range.moveEnd('character', ieEnd);
|
Daniel@0
|
208 range.moveStart('character', ieStart);
|
Daniel@0
|
209
|
Daniel@0
|
210 range.select();
|
Daniel@0
|
211 },
|
Daniel@0
|
212
|
Daniel@0
|
213 replace: function(text) {
|
Daniel@0
|
214 document.selection.createRange().text = text;
|
Daniel@0
|
215 }
|
Daniel@0
|
216 }
|
Daniel@0
|
217 };
|
Daniel@0
|
218
|
Daniel@0
|
219 $.fn.textrange = function(method) {
|
Daniel@0
|
220 if (typeof this[0] === 'undefined') {
|
Daniel@0
|
221 return this;
|
Daniel@0
|
222 }
|
Daniel@0
|
223
|
Daniel@0
|
224 if (typeof browserType === 'undefined') {
|
Daniel@0
|
225 browserType = 'selectionStart' in this[0] ? 'xul' : document.selection ? 'msie' : 'unknown';
|
Daniel@0
|
226 }
|
Daniel@0
|
227
|
Daniel@0
|
228 // I don't know how to support this browser. :c
|
Daniel@0
|
229 if (browserType === 'unknown') {
|
Daniel@0
|
230 return this;
|
Daniel@0
|
231 }
|
Daniel@0
|
232
|
Daniel@0
|
233 // Focus on the element before operating upon it.
|
Daniel@0
|
234 if (document.activeElement !== this[0]) {
|
Daniel@0
|
235 this[0].focus();
|
Daniel@0
|
236 }
|
Daniel@0
|
237
|
Daniel@0
|
238 if (typeof method === 'undefined' || typeof method !== 'string') {
|
Daniel@0
|
239 return textrange.get.apply(this);
|
Daniel@0
|
240 } else if (typeof textrange[method] === 'function') {
|
Daniel@0
|
241 return textrange[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
Daniel@0
|
242 } else {
|
Daniel@0
|
243 $.error("Method " + method + " does not exist in jQuery.textrange");
|
Daniel@0
|
244 }
|
Daniel@0
|
245 };
|
Daniel@0
|
246 });
|