/** * jQuery Selections plugin * * Provides text input utilities * * Note that most functions act only on the first of * the given elements, since browsers can only have * one in focus at a time * * Copyright (C) 2010, Jordi Boggiano * http://seld.be/ - j.boggiano@seld.be * * Licensed under the new BSD License * See the LICENSE file for details * * Source on Github http://github.com/Seldaek/jquery-selections */ (function($) { /** * sets the caret position * * @param int index * @see $.fn.setSelection */ $.fn.setCaret = function(index) { this.setSelection(index, index); }; /** * returns the caret position, or 0 if the element has no caret * * @return int */ $.fn.getCaret = function() { var elem, range, elemRange, elemRangeCopy, value, caret, pos, match; elem = this.get(0); value = $(elem).val(); // standard browsers if (elem.selectionStart) { caret = elem.selectionStart; } else if (document.selection) { // old IE handling elem.focus(); range = document.selection.createRange(); // handle input texts if (elem.nodeName === 'INPUT') { elemRange = elem.createTextRange(); elemRangeCopy = elemRange.duplicate(); elemRange.moveToBookmark(range.getBookmark()); elemRangeCopy.setEndPoint('EndToStart', elemRange); caret = elemRangeCopy.text.length; } else { // handle textareas elemRangeCopy = range.duplicate(); elemRangeCopy.moveToElementText(elem); pos = 0; if (range.text.length > 1) { pos = Math.max(0, pos - range.text.length); } caret = -1 + pos; elemRangeCopy .moveStart('character', pos); while (elemRangeCopy.inRange(range)) { elemRangeCopy.moveStart('character'); caret++; } } } else { caret = 0; } if ($.browser.opera) { match = value.replace(/\r?\n/g, "\r\n").substr(0, caret).match(/\r\n/g); if (match) { caret -= match.length; } } return caret; }; /** * selects a range of text * * @param int start index of the beginning of the selection * @param int end index of the end of the selection * @return object chainable */ $.fn.setSelection = function(start, end) { var elem, range, match; elem = this.get(0); end = end || start; // standard browsers if (elem.setSelectionRange) { elem.focus(); if ($.browser.opera) { match = this.val().replace(/\r?\n/g, "\n").substr(0, start).match(/\n/g); if (match) { start += match.length; } match = this.val().replace(/\r?\n/g, "\n").substr(0, end).match(/\n/g); if (match) { end += match.length; } } elem.setSelectionRange(start, end); } else if (elem.createTextRange) { // old IE handling range = elem.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', start); range.select(); } return this; }; /** * reads the text the user selected * * @param int start index of the beginning of the selection * @param int end index of the end of the selection * @return string */ $.fn.getSelectedText = function() { var elem = this.get(0); // standard browsers if (elem.selectionStart) { return elem.value.substring(elem.selectionStart, elem.selectionEnd); } // old IE if (document.selection) { elem.focus(); return document.selection.createRange().text; } return ''; }; /** * injects the given text in place of the current selection * * @param string text * @return object chainable */ $.fn.replaceSelection = function(text) { var elem = this.get(0); // standard browsers if (elem.selectionStart) { elem.value = elem.value.substr(0, elem.selectionStart) + text + elem.value.substr(elem.selectionEnd); return this; } // old IE if (document.selection) { elem.focus(); document.selection.createRange().text = text; return this; } return this; }; /** * injects the given text at the current caret position * * @param string text * @return object chainable */ $.fn.injectText = function(text) { var $elem, caret; $elem = this.first(); caret = $elem.getCaret(); $elem.val(function(idx, val) { return val.substring(0, caret) + text + val.substring(caret); }); $elem.setCaret(caret + text.length); return this; }; }(jQuery));