/** * https://github.com/garyharan/jQuery-caret-utilities * * Licensed under the incredibly permissive MIT License. */ (function($){ $.fn.insertAtCaret = function(text, opts) { var element = $(this).get(0); if (document.selection) { element.focus(); var orig = element.value.replace(/\r\n/g, "\n"); var range = document.selection.createRange(); if (range.parentElement() != element) { return false; } range.text = text; var actual = tmp = element.value.replace(/\r\n/g, "\n"); for (var diff = 0; diff < orig.length; diff++) { if (orig.charAt(diff) != actual.charAt(diff)) break; } for (var index = 0, start = 0; tmp.match(text) && (tmp = tmp.replace(text, "")) && index <= diff; index = start + text.length ) { start = actual.indexOf(text, index); } } else if (typeof element.selectionStart !== 'undefined') { var start = element.selectionStart; var end = element.selectionEnd; element.value = element.value.substr(0, start) + text + element.value.substr(end, element.value.length); } else if (document.getSelection() && document.getSelection().anchorNode) { // Selection of contenteditable elements (divs) element.focus(); anchorNode = document.getSelection().anchorNode; focusNode = document.getSelection().focusNode; // Ignore selection over multiple nodes (TODO?) if (! $(anchorNode).closest(element).length || anchorNode != focusNode) { return false; } origContent = anchorNode.textContent; anchorOffset = document.getSelection().anchorOffset || 0; focusOffset = document.getSelection().focusOffset || 0; if (anchorOffset == focusOffset) { // No selection: insert at caret position anchorNode.textContent = [origContent.slice(0, anchorOffset), text, origContent.slice(anchorOffset)].join(''); } else { // Selection within the same node: replace selection anchorNode.textContent = [origContent.slice(0, anchorOffset), text, origContent.slice(focusOffset)].join(''); } // Don't need to position caret return this; } if (typeof start !== 'undefined') { setCaretTo(element, start + text.length); } else { element.value = text + element.value; } return this; } $.fn.setCaretPosition = function(start, end) { var element = $(this).get(0); element.focus(); setCaretTo(element, start, end); return this; } $.fn.getCaretPosition = function() { var element = $(this).get(0); $(element).focus(); return getCaretPosition(element); } $.fn.getSelectedText = function() { var element = $(this).get(0); // workaround for firefox because window.getSelection does not work inside inputs if (typeof element.selectionStart !== 'undefined') { return $(element).val().substr(element.selectionStart, element.selectionEnd - element.selectionStart); } else if (document.getSelection) { return document.getSelection(); } else if (window.getSelection) { return window.getSelection(); } } // privates function setCaretTo(element, start, end) { if (typeof element.createTextRange !== 'undefined') { var range = element.createTextRange(); range.moveStart('character', start); range.moveEnd('character', (end || start)); range.select(); } else if (typeof element.selectionStart !== 'undefined') { element.focus(); element.setSelectionRange(start, (end || start)); } } function getCaretPosition(element) { if (typeof element.selectionStart !== 'undefined') { return element.selectionStart; } else if (document.selection) { var range = document.selection.createRange(); var rangeLength = range.text.length; range.moveStart('character', -element.value.length); return range.text.length - rangeLength; } } })(jQuery);