Input field caret position not getting set correctly - javascript

I have this directive down below for a <input type="text> field
myApp.directive('onlyDecimal', function ()
{
return {
require: '?ngModel',
link: function(scope, element, attrs, ngModelCtrl)
{
if(!ngModelCtrl)
{
return;
}
ngModelCtrl.$parsers.push(function(val)
{
if (angular.isUndefined(val))
{
var val = "";
}
var clean = "";
if(val !== null)
{
clean = val.replace(/[^0-9\.]/g, "");
}
var start = element[0].selectionStart;
var end = element[0].selectionEnd + clean.length - val.length;
var negativeCheck = clean.split("-");
var decimalCheck = clean.split(".");
if(!angular.isUndefined(negativeCheck[1]))
{
negativeCheck[1] = negativeCheck[1].slice(0, negativeCheck[1].length);
clean = negativeCheck[0] + '-' + negativeCheck[1];
if(negativeCheck[0].length > 0)
{
clean = negativeCheck[0];
}
}
if(!angular.isUndefined(decimalCheck[1]))
{
decimalCheck[1] = decimalCheck[1].slice(0,2);
clean = decimalCheck[0] + "." + decimalCheck[1];
}
if (val !== clean)
{
ngModelCtrl.$setViewValue(clean);
ngModelCtrl.$render();
}
element[0].setSelectionRange(start, end);
return clean;
});
element.bind("keypress", function(event)
{
if(event.keyCode === 32)
{
event.preventDefault();
}
});
var decimalCount = 2;
var decimalPoint = ".";
ngModelCtrl.$render = function()
{
if (ngModelCtrl.$modelValue != null && ngModelCtrl.$modelValue >= 0)
{
if (typeof decimalCount === "number")
{
element.val(ngModelCtrl.$modelValue.toFixed(decimalCount).toString().replace(".", ","));
}
else
{
element.val(ngModelCtrl.$modelValue.toString().replace(".", ","));
}
}
}
element.on("change", function(e)
{
var floatValue = parseFloat(element.val().replace(",", "."));
if (!isNaN(floatValue) && typeof decimalCount === "number")
{
if (decimalCount === 0)
{
element.val(parseInt(floatValue));
}
else
{
var strValue = floatValue.toFixed(decimalCount);
element.val(strValue.replace(".", decimalPoint));
}
}
});
}
};
});
The purpose of this directive is to only allow numbers and 1 decimal in the field.
Let's say I have a value of 50.00 I then set the caret before the value which would be position 0 and I enter an invalid value of the key b. I set a console.log before I set the selection range and I get these values:
START: 0 END: 1
START: 0 END: 0
It runs twice and it seems to still move the caret to the next position.

There are at least two issues in your code that are causing problematic behavior:
In ngModelCtrl.$render, you are checking the type of decimalCount to determine if the $modelValue is a number or a string. As soon as you start typing, ngModelCtrl.$modelValue becomes a string, but your logic still attempts to call .toFixed() on it, causing render to throw an exception, and preventing setSelectionRange from being called by the parser.
Your logic that is swapping commas for decimals is not being used in your formatter. A value with a comma will come in, and the regex creating clean will remove it because it is expecting a decimal. Once you fix that, you will have to also fix the comparison between val and clean at the end to swap decimals back to commas in clean.
Overall, I would propose the following:
Swap if (typeof decimalCount === "number") to if (typeof ngModelCtrl.$modelValue === "number")
Replace all commas with decimals before generating clean
Replace all decimals with commas in clean before comparing it back to the original val.

Related

Masking With Phone Number Formats With Spaces

I have already a code that format it to the correct number format but the problem is
1.The position of the number input after the first and second hyphen don't have correct position. Sample. When i Input 12345 after the first (-) it will be 123465 The position got swap.
2. The user cannot add in the middle of the number if it already reach the maximum number which. What is happening right now is if i click on the middle of the text box i can add numbers and all the last parts are replaced.
JSFIDDLE CODE
HTML + JS
Telephone: <input type="text" value="____-___-___" data-mask="____-___-___"/><br/>
Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask);
function applyDataMask(field) {
var mask = field.dataset.mask.split('');
// For now, this just strips everything that's not a number
function stripMask(maskedData) {
function isDigit(char) {
return /\d/.test(char);
}
return maskedData.split('').filter(isDigit);
}
// Replace `_` characters with characters from `data`
function applyMask(data) {
return mask.map(function(char) {
if (char != '_') return char;
if (data.length == 0) return char;
return data.shift();
}).join('')
}
function reapplyMask(data) {
return applyMask(stripMask(data));
}
function changed() {
var oldStart = field.selectionStart;
var oldEnd = field.selectionEnd;
field.value = reapplyMask(field.value);
field.selectionStart = oldStart;
field.selectionEnd = oldEnd;
}
field.addEventListener('click', changed)
field.addEventListener('keyup', changed)
}
HTML:
<input id="txtPhone" data-mask="(___) ___-____" type="text" />
Javascript:
Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask);
function applyDataMask(field) {
var mask = field.dataset.mask.split('');
// For now, this just strips everything that's not a number
function stripMask(maskedData) {
function isDigit(char) {
return /\d/.test(char);
}
return maskedData.split('').filter(isDigit);
}
// Replace `_` characters with characters from `data`
function applyMask(data) {
return mask.map(function (char) {
if (char != '_') return char;
if (data.length == 0) return char;
return data.shift();
}).join('')
}
function reapplyMask(data) {
return applyMask(stripMask(data));
}
function changed(e) {
var i = field.value.indexOf('_');
if (e.keyCode == undefined) {
i = 0;
}
field.value = reapplyMask(field.value);
field.selectionStart = i;
field.selectionEnd = i;
}
field.addEventListener('click', changed)
field.addEventListener('keyup', changed);
}

comma format as typing in angular

In jqxwidget
http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxnumberinput/index.htm
by default the comma’s are already in place and separated by underscore.
what i want is to have the field empty and as soon as user starts typing the comma should come as and when similarly to F2 cell render-er.
so when typed 100 is should show 100
when typed 10000 ,it should show 10,000
also i have angular in my app as we are using jqxwidget in conjucation with so any angular way is also fine
one plugin i have found does the job but when focus out not when typing
https://www.npmjs.com/package/angular-numeric-directive
Hey I have solved this before by creating a directive that applies a filter to your HTML input. Here is a jsfiddle example
This is the directive. It both formats the user's input and keeps the cursor where the user is typing. My one issue with this is the logic behind where the cursor should be pointed.
fessmodule.directive('format', ['$filter', function ($filter) {
return {
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
var parts = attrs.format.split(':');
attrs.foramtType = parts[0];
attrs.pass = parts[1];
ctrl.$formatters.unshift(function (a) {
return $filter(attrs.foramtType)(ctrl.$modelValue, attrs.pass)
});
ctrl.$parsers.unshift(function (viewValue) {
var cursorPointer = elem.context.selectionStart;
var plainNumber = viewValue.replace(/[^\d|\-+|\.+]/g, '');
elem.val($filter(attrs.foramtType)(plainNumber, attrs.pass));
elem.context.setSelectionRange(cursorPointer, cursorPointer);
return plainNumber;
});
}
};
And the HTML to activate it
<input type="text" ng-model="test" format="number:2" />
Angular already provides pretty basic formatting filters
like
html : {{val | number:0}}
script: $scope.val = 1234.56789;
ref:
https://docs.angularjs.org/api/ng/filter/number
https://docs.angularjs.org/api/ng/filter/currency
https://scotch.io/tutorials/all-about-the-built-in-angularjs-filters
Demo
<input value="100000000" id="testInput" />
Simply apply this .formatInput(numberOfCharactersForSeparator, Separator ); to your input
$(document).ready(function()
{
$("#testInput").formatInput(3,"," );
});
using this plugin that i just made :p
$.fn.formatInput = (function(afterHowManyCharacter,commaType)
{
if(afterHowManyCharacter && commaType != ".")
{
var str = $(this).val();
var comma = commaType != undefined ? commaType : "," ;
var strMod ;
if($(this).val().indexOf(".") == -1)
strMod = replaceAll(comma,"",$(this).val());
else
{
strMod = replaceAll(comma,"",$(this).val());
strMod = strMod.substring(0,strMod.indexOf("."));
}
if($(this).val().indexOf(".") != -1)
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
else
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));
var nowPos = 0;
$(this).on("keyup",function(e)
{
nowPos = doGetCaretPosition($(this)[0]);
var codePressed = e.which ;
if(" 8 37 38 39 40 46 17".indexOf(" "+codePressed) == -1 && !e.ctrlKey)
{
if($(this).val().length >afterHowManyCharacter)
{
strMod ;
if($(this).val().indexOf(".") == -1)
strMod = replaceAll(comma,"",$(this).val());
else
{
strMod = replaceAll(comma,"",$(this).val());
strMod = strMod.substring(0,strMod.indexOf("."));
}
if($(this).val().indexOf(".") != -1)
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
else
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));
if((strMod.length-1)%afterHowManyCharacter == 0)
{
setCursor($(this)[0],nowPos+1);
}
else
{
setCursor($(this)[0],nowPos);
}
}
}
});
}
else if( commaType == ".")
{
console.log("You can't use . as Separator");
}
function splitByLength(str,maxLength)
{
var reg = new RegExp(".{1,"+maxLength+"}","g"); ;
return reverseStringInArray(str.split("").reverse().join("").match(reg).reverse());
}
function replaceAll(find, replace, str) {
return str.replace(new RegExp(find, 'g'), replace);
}
function reverseStringInArray(arr)
{
$.each(arr,function(i,val)
{
arr[i] = arr[i].split("").reverse().join("");
});
return arr ;
}
// Author of setCursor is nemisj
function setCursor(node,pos)
{
node = (typeof node == "string" || node instanceof String) ? document.getElementById(node) : node;
if(!node){
return false;
}else if(node.createTextRange){
var textRange = node.createTextRange();
textRange.collapse(true);
textRange.moveEnd(pos);
textRange.moveStart(pos);
textRange.select();
return true;
}else if(node.setSelectionRange){
node.setSelectionRange(pos,pos);
return true;
}
return false;
}
// Author of setCursor is bezmax
function doGetCaretPosition (oField) {
// Initialize
var iCaretPos = 0;
// IE Support
if (document.selection) {
// Set focus on the element
oField.focus ();
// To get cursor position, get empty selection range
var oSel = document.selection.createRange ();
// Move selection start to 0 position
oSel.moveStart ('character', -oField.value.length);
// The caret position is selection length
iCaretPos = oSel.text.length;
}
// Firefox support
else if (oField.selectionStart || oField.selectionStart == '0')
iCaretPos = oField.selectionStart;
// Return results
return (iCaretPos);
}
});
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('app',[]);
app.controller('myCtrl',function($scope){
$scope.name = "1232.33";
$scope.changeFormat = function(value){
$scope.name = Number(value).toLocaleString('en');
}
});
</script>
<body>
<div ng-app="app" ng-controller="myCtrl">
<p>Input something in the input box:</p>
<p>Number: <input type="text" ng-model="name" placeholder="Enter name here" ng-blur="changeFormat(name)"></p>
<h1>Formatted value {{name}}</h1>
</div>
</body>
</html>
Here is a hackish solution. The idea is to watch for changes in the input text and format the input accordingly.
HTML
<div ng-controller="so">
<input ng-model="salary"></input>
</div>
Javascript
app.controller('so', function($scope) {
$scope.salary = '12567';
$scope.$watch('salary', function(){
// strip out all the commas and dots
var temp = $scope.salary;
if (!temp) return; // ignore empty input box
var lastChar = temp[temp.length-1];
if (lastChar === ',' || lastChar === '.') // skip it/allow commas
return;
var a = temp.replace(/,/g,''); //remove all commas
//console.log(a);
if (isNaN(a))
$scope.salary = temp.substring(0, temp.length-1); // last char was not right
else {
var n = parseInt(a, 10); // the integer part
var f = ''; // decimal part
if (a.indexOf('.') >= 0) // decimal present{
if (lastChar === '0') // 0's after decimal point are OK
return;
f = ('' + parseFloat(a)).substr(a.indexOf('.'));
}
var formatted_salary = '';
var count = 0;
var ns = '' + n; // string of integer part
for (var i=ns.length-1; i>=0; i--) {
if (count%3===0 && count>0)
formatted_salary = ',' + formatted_salary;
formatted_salary = ns[i] + formatted_salary;
count += 1;
}
formatted_salary = formatted_salary + (f ? f : '');
$scope.salary = formatted_salary;
}
})
})
Here is the JSFiddle
It gracefully handles things like
won't allow any characters other than numbers , and .
multiple commas and dots formatted correctly
PS:- you might want to handle the proper positioning of the caret yourself using text range. I haven't included that here.
100 => 100
1000 =>1,000
10000 => 10,000
100000 => 100,000
...
10000000 => 10,000,000
10000000.540 => 10,000,000.540
I use ng-change event to make this example
// on-change event
$scope.ngchanged = function (val) {
$scope.iputval = numberWithCommas(val);
};
function numberWithCommas(n) {
while (n.toString().indexOf(",") != -1)
{
n = n.replace(",", "");
}
var parts = n.toString().split(".");
return parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}
Use it
<input type="text" ng-model="iputval" ng-change="ngchanged(iputval)" />
Updated add demo and code by following link
Full code and demo >> here
Please check out ng-number-input
I think it accomplishes the task easily.
https://www.npmjs.com/package/ng-number-input
I made it for my project and I thought I'd share it with the community.
Source code available on git hub and link is available in npm page.

How to use an input type=text field to accept only digits, minus sign and decimals and nothing more with Angular

I'll be brief and to the point: I have two text boxes with angular.
Here it is:
<div data-ng-controller="customValidationAndNbrsCheckController">
<label class="input">
<number-only-input placeholder="Latitude" input-value="wksLat.number" input-name="wksLat.name" />
</label>
<label>
<number-only-input placeholder="Longitude" input-value="wksLon.number" input-name="wksLon.name" />
</label>
</div>
Here's my directive:
UPDATE: PROBLEM SOLVED... here's the fiddle that shows the EXACT change that fixes the problem. Thanks for reading but I got it. http://jsfiddle.net/vfsHX/
//Numbers only function
angular
.module("isNumber", [])
.directive('isNumber', function () {
return {
require: 'ngModel',
link: function (scope) {
scope.$watch('wksLat.number', function(newValue,oldValue) {
var arr = String(newValue).split("");
if (arr.length === 0) return;
if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.' )) return;
if (arr.length === 2 && newValue === '-.') return;
if (isNaN(newValue)) {
scope.wksLat.number = oldValue;
}
});
scope.$watch('wksLon.number', function (newValue, oldValue) {
var arr = String(newValue).split("");
if (arr.length === 0) return;
if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.')) return;
if (arr.length === 2 && newValue === '-.') return;
if (isNaN(newValue)) {
scope.wksLon.number = oldValue;
}
});
}
};
});
Here's my Service:
(function (app) {
debugger;
var customValidationAndNbrsService = function () {
var customValidationAndNbrsServiceFactory = {};
customValidationAndNbrsServiceFactory.settings = new mainApp.Models.Settings();
customValidationAndNbrsServiceFactory.getSettings = function () {
return customValidationAndNbrsServiceFactory.settings;
};
return customValidationAndNbrsServiceFactory;
};
app.factory("customValidationAndNbrsService", customValidationAndNbrsService);
}(angular.module("mainApp")));
This is from an example I found here on Stack.
PROBLEM: This works GREAT but...
The value in the text box starts out with the number "1"; why?
The text box will 'not' allow dashes, decimals with the numbers but, it does not allow alpha characters. Good.
This is for LAT/LON data restricted to 50 characters which does work as maxlength='50'
What does the "=" sign mean at the end of the inputValue and inputName? Is that a standard? because when I change it to, say a "0", thinking that's why the "1" appears in the text box, the debugger in Chrome shows code failures.
QUESTION: How do I modify the code to "allow" dashes and decimals, since we're entering the LAT LONs as decimal degrees and not DD:MM:SS.
Here's the possible input: 25.2223332 LAT and -45.685464 LON
So I hope the moderators do not delete this question. It's valid and yes, I need a "fix-my-code" help since that's what I believe this site is for.
Thanks, everyone.
1. comes from input-value="wksLon.number"
2. match your value to regex
js
scope.$watch('inputValue', function (newValue, oldValue) {
var arr = String(newValue).split("");
if (arr.length === 0) return;
if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.')) return;
if (arr.length === 2 && newValue === '-.') return;
if (isNaN(newValue)) {
scope.inputValue = oldValue;
}
});
this should be changed to your setup, probably with RegEx
something like that
scope.$watch('inputValue', function (newValue, oldValue) {
var myRegex = /^(-)?\d+(.\d+)$/
if (!myRegex.test(newValue) || newValue.length > 50) {
scope.inputValue = oldValue
}
});
3. extended 2 by 3 with length > 50
4. that's a data binding to same name
<number-only-input placeholder="Longitude" input-value="wksLon.number" input-name="wksLon.name" />
from above element input-value and input-name are binded with the same name
scope: {
inputValue: '=',
inputName: '='
},
but if you want to use different you can do it like:
scope: {
Value: '=inputValue',
Name: '=inputName'
},

Validate input value before it is shown to user

I have an html <input> and some pattern (e.g. -?\d*\.?\d* float-signed value).
I should prevent typing the not matched value.
I did it in next way
jQuery.fn.numeric = function (pattern)
{
var jqElement = $(this), prevValue;
jqElement.keydown(function()
{
prevValue = jqElement.val();
})
jqElement.keyup(function(e)
{
if (!pattern.test(jqElement.val()))
{
jqElement.val(prevValue);
e.preventDefault();
}
prevValue = ""
})
};
JSFiddle DEMO
But in this case, value is shown to user and then corrected to right value.
Is it way to vaidate value before it is shown to user?
I can use pattern attribute from html5
$("#validateMe").on('keydown', function() {
var charBeingTyped = String.fromCharCode(e.charCode || e.which); // get character being typed
var cursorPosition = $(this)[0].selectionStart; // get cursor position
// insert char being typed in our copy of the value of the input at the position of the cursor.
var inValue = $(this).value().substring(0, cursorPosition) + charBeingTyped + $(this).value().substring(cursorPosition, $(this).value().length);
if(inValue.match(/-?\d*\.?\d*/)) return true;
else return false;
});
How about this POJS, I'm using a cross-browser addEvent function instead of jquery and not using any regexs, but I believe it achieves what you are looking for. Pressing + or - changes the sign of the value.
HTML
<input id="test" type="text" />
Javascript
/*jslint maxerr: 50, indent: 4, browser: true */
(function () {
"use strict";
function addEvent(elem, event, fn) {
if (typeof elem === "string") {
elem = document.getElementById(elem);
}
function listenHandler(e) {
var ret = fn.apply(null, arguments);
if (ret === false) {
e.stopPropagation();
e.preventDefault();
}
return ret;
}
function attachHandler() {
window.event.target = window.event.srcElement;
var ret = fn.call(elem, window.event);
if (ret === false) {
window.event.returnValue = false;
window.event.cancelBubble = true;
}
return ret;
}
if (elem.addEventListener) {
elem.addEventListener(event, listenHandler, false);
} else {
elem.attachEvent("on" + event, attachHandler);
}
}
function verify(e) {
var target = e.target, // shouldn't be needed: || e.srcElement;
value = target.value,
char = String.fromCharCode(e.keyCode || e.charCode);
if (value.charAt(0) === "-") {
if (char === "+") {
e.target.value = value.slice(1);
}
} else if (char === "-") {
e.target.value = char + value;
return false;
}
value += char;
return parseFloat(value) === +value;
}
addEvent("test", "keypress", verify);
}());
On jsfiddle
I think I used the correct values keyCode || charCode
but you may want to search and check. A summary of the correct ones are available here
You could use this code to find out what character is pressed. Validate that character and, if it validates, append it to the input field.
Try this code:
jQuery.fn.numeric = function (pattern)
{
$(this).keypress(function(e)
{
var sChar = String.fromCharCode(!e.charCode ? e.which : event.charCode);
e.preventDefault();
var sPrev = $(this).val();
if(!pattern.test(sChar)){
return false;
} else {
sPrev = sPrev + sChar;
}
$(this).val(sPrev);
});
};
$("#validateId").numeric(/^-?\d*\.?\d*$/);
jsfiddle.net/aBNtH/
UPDATE:
My example validates each charachter while typing. If you prefer to check the entire value of the input field instead, I would suggest to validate the value on an other Event, like Input blur().

How do you prevent bad user input on watched input fields in angular?

I have a watched input field on a grid with pagination. Something like X of 28 Pages.
I want the user to be able to change that input, but I also want to prevent bad input.
My checks are >= 1 or <= Max Pages (28 in this case). The input defaults to 1.
I accomplished this by comparing the new value against those constraints, if it fails, revert to the old value. The problem comes when someone wants to type in 20 lets say. This requires they delete the 1, and type 20. As soon as they delete 1, it fails the constraints and reverts back to 1 making impossible to type in 20.
Is there anyway to accomplish this without removing it from the $watch?
You could use a combination of <input type="number"> and your own directive that has a parser and a listener for the blur event. That way your watch will only get executed when the page number is a valid page, or once with null when the input is invalid, but the user can input whatever until the blur event fires. Something like this:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
<script>
angular.module('myApp', []).controller('Ctrl', function($scope) {
$scope.pageNumber = 1;
})
.directive('myPagenumber', function() {
return {
require: 'ngModel',
link: function($scope, elem, attrs, ctrl) {
$scope.$watch(attrs.ngModel, function(val) {
console.log('ng-model value: ' + val);
});
var parsePage = function(val) {
var num = parseInt(val, 10);
if (isNaN(num)) {
return null;
} else if (num > 28 || num < 1) {
return 1;
} else {
return num;
}
}
ctrl.$parsers.push(function(val) {
return parsePage(val);
});
elem.bind('blur', function() {
var page = parsePage(elem.val());
if (page === null)
page = 1;
$scope.$apply(function() {
ctrl.$setViewValue(page);
ctrl.$render();
});
});
}
};
});
</script>
</head>
<body ng-controller="Ctrl">
<input type="number" ng-model="pageNumber" my-pagenumber>
</body>
</html>
I wrote an example for you:
var min = 1;
var max = 28;
$('.page').live('keydown', function (e){
var currentVal = $(this).val();
//enter,tab, shift
if(e.which == 37 || e.which == 39 || e.which == 9 || e.which == 8) {
return;
// key up
} else if(e.which == 38){
if(currentVal < max){
currentVal++;
}
$(this).val(currentVal);
//key down
} else if( e.which == 40) {
if(currentVal > min){
currentVal--;
}
$(this).val(currentVal);
//only numbers
} else if(e.which >= 48 && e.which <= 57){
var val = e.which - 48;
if(e.target.selectionEnd == e.target.selectionStart) {
val = currentVal.insert(e.target.selectionEnd, val);
} else {
val = currentVal.replace(currentVal.substr(getSelectionStart(e.target),getSelectionEnd(e.target)),val);
}
if(min<=val && val <= max) {
$(this).val(val);
}
}
e.preventDefault();
});
// utility functions
//get the start index of the user selection
function getSelectionStart(o) {
if ( typeof o.selectionStart != 'undefined' )
return o.selectionStart;
// IE And FF Support
o.focus();
var range = o.createTextRange();
range.moveToBookmark(document.selection.createRange().getBookmark());
range.moveEnd('character', o.value.length);
return o.value.length - range.text.length;
};
//get the end index of the user selection
function getSelectionEnd(o) {
if ( typeof o.selectionEnd != 'undefined' )
return o.selectionEnd;
// IE And FF Support
o.focus();
var range = o.createTextRange();
range.moveToBookmark(document.selection.createRange().getBookmark());
range.moveStart('character', - o.value.length);
return range.text.length;
};
/*
* Insert Text at a index
*/
String.prototype.insert = function (index, string) {
if (index > 0)
return this.substring(0, index) + string + this.substring(index, this.length);
else
return string + this;
};
animate example: http://jsfiddle.net/PVxqe/1/

Categories

Resources