/*! * a-tools 1.4.1 * * Copyright (c) 2009 Andrey Kramarev(andrey.kramarev[at]ampparit.com), Ampparit Inc. (www.ampparit.com) * Licensed under the MIT license. * http://www.ampparit.fi/a-tools/license.txt * * Basic usage: // Get current selection var sel = $("textarea").getSelection() // Replace current selection $("input").replaceSelection("foo"); // Count characters alert($("textarea").countCharacters()); // Set max length without callback function $("textarea").setMaxLength(7); // Set max length with callback function which will be called when limit is exceeded $("textarea").setMaxLength(10, function() { alert("hello") }); // Removing limit: $("textarea").setMaxLength(-1); // Insert text at current caret position $("#textarea").insertAtCaretPos("hello"); // Set caret position (1 = beginning, -1 = end) $("#textArea").setCaretPos(10); // Set Selection $("#textArea").setSelection(10,15); */ var caretPositionAmp; jQuery.fn.extend({ getSelection: function() { // function for getting selection, and position of the selected text var input = this.jquery ? this[0] : this; var start; var end; var part; var number = 0; input.onmousedown = function() { // for IE because it loses caret position when focus changed if (document.selection && typeof(input.selectionStart) != "number") { document.selection.empty(); } else { window.getSelection().removeAllRanges(); } } if (document.selection) { // part for IE and Opera var s = document.selection.createRange(); var minus = 0; var position = 0; var minusEnd = 0; var re; var rc; if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } if (s.text) { part = s.text; // OPERA support if (typeof(input.selectionStart) == "number") { start = input.selectionStart; end = input.selectionEnd; // return null if the selected text not from the needed area if (start == end) { return { start: start, end: end, text: s.text, length: end - start }; } } else { // IE support var firstRe; var secondRe; re = input.createTextRange(); rc = re.duplicate(); firstRe = re.text; re.moveToBookmark(s.getBookmark()); secondRe = re.text; rc.setEndPoint("EndToStart", re); // return null if the selectyed text not from the needed area if (firstRe == secondRe && firstRe != s.text) { return this; } start = rc.text.length; end = rc.text.length + s.text.length; } // remove all EOL to have the same start and end positons as in MOZILLA if (number > 0) { for (var i = 0; i <= number; i++) { var w = input.value.indexOf("\n", position); if (w != -1 && w < start) { position = w + 1; minus++; minusEnd = minus; } else if (w != -1 && w >= start && w <= end) { if (w == start + 1) { minus--; minusEnd--; position = w + 1; continue; } position = w + 1; minusEnd++; } else { i = number; } } } if (s.text.indexOf("\n", 0) == 1) { minusEnd = minusEnd + 2; } start = start - minus; end = end - minusEnd; return { start: start, end: end, text: s.text, length: end - start }; } input.focus (); if (typeof(input.selectionStart) == "number") { start = input.selectionStart; } else { s = document.selection.createRange(); re = input.createTextRange(); rc = re.duplicate(); re.moveToBookmark(s.getBookmark()); rc.setEndPoint("EndToStart", re); start = rc.text.length; } if (number > 0) { for (var i = 0; i <= number; i++) { var w = input.value.indexOf("\n", position); if (w != -1 && w < start) { position = w + 1; minus++; } else { i = number; } } } start = start - minus; return { start: start, end: start, text: s.text, length: 0 }; } else if (typeof(input.selectionStart) == "number" ) { start = input.selectionStart; end = input.selectionEnd; part = input.value.substring(input.selectionStart, input.selectionEnd); return { start: start, end: end, text: part, length: end - start }; } else { return { start: undefined, end: undefined, text: undefined, length: undefined }; } }, // function for the replacement of the selected text replaceSelection: function(inputStr) { var input = this.jquery ? this[0] : this; //part for IE and Opera var start; var end; var position = 0; var rc; var re; var number = 0; var minus = 0; var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop; if (document.selection && typeof(input.selectionStart) != "number") { var s = document.selection.createRange(); // IE support if (typeof(input.selectionStart) != "number") { // return null if the selected text not from the needed area var firstRe; var secondRe; re = input.createTextRange(); rc = re.duplicate(); firstRe = re.text; re.moveToBookmark(s.getBookmark()); secondRe = re.text; rc.setEndPoint("EndToStart", re); if (firstRe == secondRe && firstRe != s.text) { return this; } } if (s.text) { part = s.text; if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } // IE support start = rc.text.length; // remove all EOL to have the same start and end positons as in MOZILLA if (number > 0) { for (var i = 0; i <= number; i++) { var w = input.value.indexOf("\n", position); if (w != -1 && w < start) { position = w + 1; minus++; } else { i = number; } } } s.text = inputStr; caretPositionAmp = rc.text.length + inputStr.length; re.move("character", caretPositionAmp); document.selection.empty(); input.blur(); } return this; } else if (typeof(input.selectionStart) == "number" && // MOZILLA support input.selectionStart != input.selectionEnd) { start = input.selectionStart; end = input.selectionEnd; input.value = input.value.substr(0, start) + inputStr + input.value.substr(end); position = start + inputStr.length; input.setSelectionRange(position, position); input.scrollTop = mozScrollFix; return this; } return this; }, //Set Selection in text setSelection: function(startPosition, endPosition) { startPosition = parseInt(startPosition); endPosition = parseInt(endPosition); var input = this.jquery ? this[0] : this; input.focus (); if (typeof(input.selectionStart) != "number") { re = input.createTextRange(); if (re.text.length < endPosition) { endPosition = re.text.length+1; } } if (endPosition < startPosition) { return this; } if (document.selection) { var number = 0; var plus = 0; var position = 0; var plusEnd = 0; if (typeof(input.selectionStart) != "number") { // IE re.collapse(true); re.moveEnd('character', endPosition); re.moveStart('character', startPosition); re.select(); return this; } else if (typeof(input.selectionStart) == "number") { // Opera if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } if (number > 0) { for (var i = 0; i <= number; i++) { var w = input.value.indexOf("\n", position); if (w != -1 && w < startPosition) { position = w + 1; plus++; plusEnd = plus; } else if (w != -1 && w >= startPosition && w <= endPosition) { if (w == startPosition + 1) { plus--; plusEnd--; position = w + 1; continue; } position = w + 1; plusEnd++; } else { i = number; } } } startPosition = startPosition +plus; endPosition = endPosition + plusEnd; input.selectionStart = startPosition; input.selectionEnd = endPosition; return this; } else { return this; } } else if (input.selectionStart) { // MOZILLA support input.focus (); input.selectionStart = startPosition; input.selectionEnd = endPosition; return this; } }, // insert text at current caret position insertAtCaretPos: function(inputStr) { var input = this.jquery ? this[0] : this; var start; var end; var position; var s; var re; var rc; var point; var minus = 0; var number = 0; var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop; input.focus(); if (document.selection && typeof(input.selectionStart) != "number") { if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } point = parseInt(caretPositionAmp); if (number > 0) { for (var i = 0; i <= number; i++) { var w = input.value.indexOf("\n", position); if (w != -1 && w <= point) { position = w + 1; point = point - 1; minus++; } } } } caretPositionAmp = parseInt(caretPositionAmp); // IE input.onmouseup = function() { // for IE because it loses caret position when focus changed if (document.selection && typeof(input.selectionStart) != "number") { input.focus(); s = document.selection.createRange(); re = input.createTextRange(); rc = re.duplicate(); re.moveToBookmark(s.getBookmark()); rc.setEndPoint("EndToStart", re); caretPositionAmp = rc.text.length; } } if (document.selection && typeof(input.selectionStart) != "number") { s = document.selection.createRange(); if (s.text.length != 0) { return this; } re = input.createTextRange(); textLength = re.text.length; rc = re.duplicate(); re.moveToBookmark(s.getBookmark()); rc.setEndPoint("EndToStart", re); start = rc.text.length; if (caretPositionAmp > 0 && start ==0) { minus = caretPositionAmp - minus; re.move("character", minus); re.select(); s = document.selection.createRange(); caretPositionAmp += inputStr.length; } else if (!(caretPositionAmp >= 0) && textLength ==0) { s = document.selection.createRange(); caretPositionAmp = inputStr.length + textLength; } else if (!(caretPositionAmp >= 0) && start ==0) { re.move("character", textLength); re.select(); s = document.selection.createRange(); caretPositionAmp = inputStr.length + textLength; } else if (!(caretPositionAmp >= 0) && start > 0) { re.move("character", 0); document.selection.empty(); re.select(); s = document.selection.createRange(); caretPositionAmp = start + inputStr.length; } else if (caretPositionAmp >= 0 && caretPositionAmp == textLength) { if (textLength != 0) { re.move("character", textLength); re.select(); } else { re.move("character", 0); } s = document.selection.createRange(); caretPositionAmp = inputStr.length + textLength; } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp >= start) { minus = caretPositionAmp - start; re.move("character", minus); document.selection.empty(); re.select(); s = document.selection.createRange(); caretPositionAmp = caretPositionAmp + inputStr.length; } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp < start) { re.move("character", 0); document.selection.empty(); re.select(); s = document.selection.createRange(); caretPositionAmp = caretPositionAmp + inputStr.length; } else { document.selection.empty(); re.select(); s = document.selection.createRange(); caretPositionAmp = caretPositionAmp + inputStr.length; } s.text = inputStr; input.focus(); return this; } else if (typeof(input.selectionStart) == "number" && // MOZILLA support input.selectionStart == input.selectionEnd) { position = input.selectionStart + inputStr.length; start = input.selectionStart; end = input.selectionEnd; input.value = input.value.substr(0, start) + inputStr + input.value.substr(end); input.setSelectionRange(position, position); input.scrollTop = mozScrollFix; return this; } return this; }, // Set caret position setCaretPos: function(inputStr) { var input = this.jquery ? this[0] : this; var s; var re; var position; var number = 0; var minus = 0; var w; input.focus(); if (parseInt(inputStr) == 0) { return this; } //if (document.selection && typeof(input.selectionStart) == "number") { if (parseInt(inputStr) > 0) { inputStr = parseInt(inputStr) - 1; if (document.selection && typeof(input.selectionStart) == "number" && input.selectionStart == input.selectionEnd) { if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } if (number > 0) { for (var i = 0; i <= number; i++) { w = input.value.indexOf("\n", position); if (w != -1 && w <= inputStr) { position = w + 1; inputStr = parseInt(inputStr) + 1; } } } } } else if (parseInt(inputStr) < 0) { inputStr = parseInt(inputStr) + 1; if (document.selection && typeof(input.selectionStart) != "number") { inputStr = input.value.length + parseInt(inputStr); if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } if (number > 0) { for (var i = 0; i <= number; i++) { w = input.value.indexOf("\n", position); if (w != -1 && w <= inputStr) { position = w + 1; inputStr = parseInt(inputStr) - 1; minus += 1; } } inputStr = inputStr + minus - number; } } else if (document.selection && typeof(input.selectionStart) == "number") { inputStr = input.value.length + parseInt(inputStr); if (input.value.match(/\n/g) != null) { number = input.value.match(/\n/g).length;// number of EOL simbols } if (number > 0) { inputStr = parseInt(inputStr) - number; for (var i = 0; i <= number; i++) { w = input.value.indexOf("\n", position); if (w != -1 && w <= (inputStr)) { position = w + 1; inputStr = parseInt(inputStr) + 1; minus += 1; } } } } else { inputStr = input.value.length + parseInt(inputStr); } } else { return this; } // IE if (document.selection && typeof(input.selectionStart) != "number") { s = document.selection.createRange(); if (s.text != 0) { return this; } re = input.createTextRange(); re.collapse(true); re.moveEnd('character', inputStr); re.moveStart('character', inputStr); re.select(); caretPositionAmp = inputStr; return this; } else if (typeof(input.selectionStart) == "number" && // MOZILLA support input.selectionStart == input.selectionEnd) { input.setSelectionRange(inputStr, inputStr); return this; } return this; }, countCharacters: function(str) { var input = this.jquery ? this[0] : this; if (input.value.match(/\r/g) != null) { return input.value.length - input.value.match(/\r/g).length; } return input.value.length; }, setMaxLength: function(max, f) { this.each(function() { var input = this.jquery ? this[0] : this; var type = input.type; var isSelected; var maxCharacters; // remove limit if input is a negative number if (parseInt(max) < 0) { max=100000000; } if (type == "text") { input.maxLength = max; } if (type == "textarea" || type == "text") { input.onkeypress = function(e) { var spacesR = input.value.match(/\r/g); maxCharacters = max; if (spacesR != null) { maxCharacters = parseInt(maxCharacters) + spacesR.length; } // get event var key = e || event; var keyCode = key.keyCode; // check if any part of text is selected if (document.selection) { isSelected = document.selection.createRange().text.length > 0; } else { isSelected = input.selectionStart != input.selectionEnd; } if (input.value.length >= maxCharacters && (keyCode > 47 || keyCode == 32 || keyCode == 0 || keyCode == 13) && !key.ctrlKey && !key.altKey && !isSelected) { input.value = input.value.substring(0,maxCharacters); if (typeof(f) == "function") { f() } //callback function return false; } } input.onkeyup = function() { var spacesR = input.value.match(/\r/g); var plus = 0; var position = 0; maxCharacters = max; if (spacesR != null) { for (var i = 0; i <= spacesR.length; i++) { if (input.value.indexOf("\n", position) <= parseInt(max)) { plus++; position = input.value.indexOf("\n", position) + 1; } } maxCharacters = parseInt(max) + plus; } if (input.value.length > maxCharacters) { input.value = input.value.substring(0, maxCharacters); if (typeof(f) == "function") { f() } return this; } } } else { return this; } }) return this; } });