prometheus

Форк
0
/
jquery.selection.js 
354 строки · 12.6 Кб
1
/*!
2
 * jQuery.selection - jQuery Plugin
3
 *
4
 * Copyright (c) 2010-2014 IWASAKI Koji (@madapaja).
5
 * http://blog.madapaja.net/
6
 * Under The MIT License
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining
9
 * a copy of this software and associated documentation files (the
10
 * "Software"), to deal in the Software without restriction, including
11
 * without limitation the rights to use, copy, modify, merge, publish,
12
 * distribute, sublicense, and/or sell copies of the Software, and to
13
 * permit persons to whom the Software is furnished to do so, subject to
14
 * the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be
17
 * included in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 */
27
(function($, win, doc) {
28
    /**
29
     * get caret status of the selection of the element
30
     *
31
     * @param   {Element}   element         target DOM element
32
     * @return  {Object}    return
33
     * @return  {String}    return.text     selected text
34
     * @return  {Number}    return.start    start position of the selection
35
     * @return  {Number}    return.end      end position of the selection
36
     */
37
    var _getCaretInfo = function(element){
38
        var res = {
39
            text: '',
40
            start: 0,
41
            end: 0
42
        };
43

44
        if (!element.value) {
45
            /* no value or empty string */
46
            return res;
47
        }
48

49
        try {
50
            if (win.getSelection) {
51
                /* except IE */
52
                res.start = element.selectionStart;
53
                res.end = element.selectionEnd;
54
                res.text = element.value.slice(res.start, res.end);
55
            } else if (doc.selection) {
56
                /* for IE */
57
                element.focus();
58

59
                var range = doc.selection.createRange(),
60
                    range2 = doc.body.createTextRange();
61

62
                res.text = range.text;
63

64
                try {
65
                    range2.moveToElementText(element);
66
                    range2.setEndPoint('StartToStart', range);
67
                } catch (e) {
68
                    range2 = element.createTextRange();
69
                    range2.setEndPoint('StartToStart', range);
70
                }
71

72
                res.start = element.value.length - range2.text.length;
73
                res.end = res.start + range.text.length;
74
            }
75
        } catch (e) {
76
            /* give up */
77
        }
78

79
        return res;
80
    };
81

82
    /**
83
     * caret operation for the element
84
     * @type {Object}
85
     */
86
    var _CaretOperation = {
87
        /**
88
         * get caret position
89
         *
90
         * @param   {Element}   element         target element
91
         * @return  {Object}    return
92
         * @return  {Number}    return.start    start position for the selection
93
         * @return  {Number}    return.end      end position for the selection
94
         */
95
        getPos: function(element) {
96
            var tmp = _getCaretInfo(element);
97
            return {start: tmp.start, end: tmp.end};
98
        },
99

100
        /**
101
         * set caret position
102
         *
103
         * @param   {Element}   element         target element
104
         * @param   {Object}    toRange         caret position
105
         * @param   {Number}    toRange.start   start position for the selection
106
         * @param   {Number}    toRange.end     end position for the selection
107
         * @param   {String}    caret           caret mode: any of the following: "keep" | "start" | "end"
108
         */
109
        setPos: function(element, toRange, caret) {
110
            caret = this._caretMode(caret);
111

112
            if (caret === 'start') {
113
                toRange.end = toRange.start;
114
            } else if (caret === 'end') {
115
                toRange.start = toRange.end;
116
            }
117

118
            element.focus();
119
            try {
120
                if (element.createTextRange) {
121
                    var range = element.createTextRange();
122

123
                    if (win.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
124
                        toRange.start = element.value.substr(0, toRange.start).replace(/\r/g, '').length;
125
                        toRange.end = element.value.substr(0, toRange.end).replace(/\r/g, '').length;
126
                    }
127

128
                    range.collapse(true);
129
                    range.moveStart('character', toRange.start);
130
                    range.moveEnd('character', toRange.end - toRange.start);
131

132
                    range.select();
133
                } else if (element.setSelectionRange) {
134
                    element.setSelectionRange(toRange.start, toRange.end);
135
                }
136
            } catch (e) {
137
                /* give up */
138
            }
139
        },
140

141
        /**
142
         * get selected text
143
         *
144
         * @param   {Element}   element         target element
145
         * @return  {String}    return          selected text
146
         */
147
        getText: function(element) {
148
            return _getCaretInfo(element).text;
149
        },
150

151
        /**
152
         * get caret mode
153
         *
154
         * @param   {String}    caret           caret mode
155
         * @return  {String}    return          any of the following: "keep" | "start" | "end"
156
         */
157
        _caretMode: function(caret) {
158
            caret = caret || "keep";
159
            if (caret === false) {
160
                caret = 'end';
161
            }
162

163
            switch (caret) {
164
                case 'keep':
165
                case 'start':
166
                case 'end':
167
                    break;
168

169
                default:
170
                    caret = 'keep';
171
            }
172

173
            return caret;
174
        },
175

176
        /**
177
         * replace selected text
178
         *
179
         * @param   {Element}   element         target element
180
         * @param   {String}    text            replacement text
181
         * @param   {String}    caret           caret mode: any of the following: "keep" | "start" | "end"
182
         */
183
        replace: function(element, text, caret) {
184
            var tmp = _getCaretInfo(element),
185
                orig = element.value,
186
                pos = $(element).scrollTop(),
187
                range = {start: tmp.start, end: tmp.start + text.length};
188

189
            element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.end);
190

191
            $(element).scrollTop(pos);
192
            this.setPos(element, range, caret);
193
        },
194

195
        /**
196
         * insert before the selected text
197
         *
198
         * @param   {Element}   element         target element
199
         * @param   {String}    text            insertion text
200
         * @param   {String}    caret           caret mode: any of the following: "keep" | "start" | "end"
201
         */
202
        insertBefore: function(element, text, caret) {
203
            var tmp = _getCaretInfo(element),
204
                orig = element.value,
205
                pos = $(element).scrollTop(),
206
                range = {start: tmp.start + text.length, end: tmp.end + text.length};
207

208
            element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.start);
209

210
            $(element).scrollTop(pos);
211
            this.setPos(element, range, caret);
212
        },
213

214
        /**
215
         * insert after the selected text
216
         *
217
         * @param   {Element}   element         target element
218
         * @param   {String}    text            insertion text
219
         * @param   {String}    caret           caret mode: any of the following: "keep" | "start" | "end"
220
         */
221
        insertAfter: function(element, text, caret) {
222
            var tmp = _getCaretInfo(element),
223
                orig = element.value,
224
                pos = $(element).scrollTop(),
225
                range = {start: tmp.start, end: tmp.end};
226

227
            element.value = orig.substr(0, tmp.end) + text + orig.substr(tmp.end);
228

229
            $(element).scrollTop(pos);
230
            this.setPos(element, range, caret);
231
        }
232
    };
233

234
    /* add jQuery.selection */
235
    $.extend({
236
        /**
237
         * get selected text on the window
238
         *
239
         * @param   {String}    mode            selection mode: any of the following: "text" | "html"
240
         * @return  {String}    return
241
         */
242
        selection: function(mode) {
243
            var getText = ((mode || 'text').toLowerCase() === 'text');
244

245
            try {
246
                if (win.getSelection) {
247
                    if (getText) {
248
                        // get text
249
                        return win.getSelection().toString();
250
                    } else {
251
                        // get html
252
                        var sel = win.getSelection(), range;
253

254
                        if (sel.getRangeAt) {
255
                            range = sel.getRangeAt(0);
256
                        } else {
257
                            range = doc.createRange();
258
                            range.setStart(sel.anchorNode, sel.anchorOffset);
259
                            range.setEnd(sel.focusNode, sel.focusOffset);
260
                        }
261

262
                        return $('<div></div>').append(range.cloneContents()).html();
263
                    }
264
                } else if (doc.selection) {
265
                    if (getText) {
266
                        // get text
267
                        return doc.selection.createRange().text;
268
                    } else {
269
                        // get html
270
                        return doc.selection.createRange().htmlText;
271
                    }
272
                }
273
            } catch (e) {
274
                /* give up */
275
            }
276

277
            return '';
278
        }
279
    });
280

281
    /* add selection */
282
    $.fn.extend({
283
        selection: function(mode, opts) {
284
            opts = opts || {};
285

286
            switch (mode) {
287
                /**
288
                 * selection('getPos')
289
                 * get caret position
290
                 *
291
                 * @return  {Object}    return
292
                 * @return  {Number}    return.start    start position for the selection
293
                 * @return  {Number}    return.end      end position for the selection
294
                 */
295
                case 'getPos':
296
                    return _CaretOperation.getPos(this[0]);
297

298
                /**
299
                 * selection('setPos', opts)
300
                 * set caret position
301
                 *
302
                 * @param   {Number}    opts.start      start position for the selection
303
                 * @param   {Number}    opts.end        end position for the selection
304
                 */
305
                case 'setPos':
306
                    return this.each(function() {
307
                        _CaretOperation.setPos(this, opts);
308
                    });
309

310
                /**
311
                 * selection('replace', opts)
312
                 * replace the selected text
313
                 *
314
                 * @param   {String}    opts.text            replacement text
315
                 * @param   {String}    opts.caret           caret mode: any of the following: "keep" | "start" | "end"
316
                 */
317
                case 'replace':
318
                    return this.each(function() {
319
                        _CaretOperation.replace(this, opts.text, opts.caret);
320
                    });
321

322
                /**
323
                 * selection('insert', opts)
324
                 * insert before/after the selected text
325
                 *
326
                 * @param   {String}    opts.text            insertion text
327
                 * @param   {String}    opts.caret           caret mode: any of the following: "keep" | "start" | "end"
328
                 * @param   {String}    opts.mode            insertion mode: any of the following: "before" | "after"
329
                 */
330
                case 'insert':
331
                    return this.each(function() {
332
                        if (opts.mode === 'before') {
333
                            _CaretOperation.insertBefore(this, opts.text, opts.caret);
334
                        } else {
335
                            _CaretOperation.insertAfter(this, opts.text, opts.caret);
336
                        }
337
                    });
338

339
                /**
340
                 * selection('get')
341
                 * get selected text
342
                 *
343
                 * @return  {String}    return
344
                 */
345
                case 'get':
346
                /* falls through */
347
                default:
348
                    return _CaretOperation.getText(this[0]);
349
            }
350

351
            return this;
352
        }
353
    });
354
})(jQuery, window, window.document);
355

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.