If you really want a change event for input controls, then here's a jQuery plug-in method I wrote a little while ago that does this and works for nearly all ways that the content of the input control can be changed including drag/drop, copy/paste, typing, etc... It takes advantage of newer events that help with this if they exist, otherwise it falls back to listening for lots of other events and looking to see if the data has changed.
(function($) {
var isIE = false;
// conditional compilation which tells us if this is IE
/*@cc_on
isIE = true;
@*/
// Events to monitor if 'input' event is not supported
// The boolean value is whether we have to
// re-check after the event with a setTimeout()
var events = [
"keyup", false,
"blur", false,
"focus", false,
"drop", true,
"change", false,
"input", false,
"textInput", false,
"paste", true,
"cut", true,
"copy", true,
"contextmenu", true
];
// Test if the input event is supported
// It's too buggy in IE so we never rely on it in IE
if (!isIE) {
var el = document.createElement("input");
var gotInput = ("oninput" in el);
if (!gotInput) {
el.setAttribute("oninput", 'return;');
gotInput = typeof el["oninput"] == 'function';
}
el = null;
// if 'input' event is supported, then use a smaller
// set of events
if (gotInput) {
events = [
"input", false,
"textInput", false
];
}
}
$.fn.userChange = function(fn, data) {
function checkNotify(e, delay) {
var self = this;
var this$ = $(this);
if (this.value !== this$.data("priorValue")) {
this$.data("priorValue", this.value);
fn.call(this, e, data);
} else if (delay) {
// The actual data change happens aftersome events
// so we queue a check for after
// We need a copy of e for setTimeout() because the real e
// may be overwritten before the setTimeout() fires
var eCopy = $.extend({}, e);
setTimeout(function() {checkNotify.call(self, eCopy, false)}, 1);
}
}
// hook up event handlers for each item in this jQuery object
// and remember initial value
this.each(function() {
var this$ = $(this).data("priorValue", this.value);
for (var i = 0; i < events.length; i+=2) {
(function(i) {
this$.on(events[i], function(e) {
checkNotify.call(this, e, events[i+1]);
});
})(i);
}
});
}
})(jQuery);
Then, your code would look like this:
$(document).ready(function(){
$('#code').userChange(function(){
//on change animate a width of +16px increase.
$(this).animate({width: '+=16'});
});
});
In looking at your code, you are increasing the width of the input control by 16px on every change. You probably should be looking at the number of characters in the control and assessing what to do about the width based on that because this will make things wider event if the user hits the backspace key. I'd probably do something like this that grows the item as content is added, but doesn't shrink it:
$(document).ready(function(){
$('#code').userChange(function(){
// on change animate width as chars are added
// only grow it when the width needs to be larger than it is currently
var item = $(this);
var origWidth = item.data("initialWidth");
var curWidth = item.width();
if (!origWidth) {
origWidth = curWidth;
item.data("initialWidth", origWidth);
}
var newWidth = origWidth + (8 * item.val().length);
if (newWidth > curWidth) {
item.stop(true, true).animate({width: newWidth}, 500);
}
});
});
Working code example: http://jsfiddle.net/jfriend00/BEDcR/
If you want the userChange method to execute when you programmatically set the value with .val()
, then you can make your own method for that:
$(document).ready(function(){
function updateWidth() {
// on change animate width as chars are added
// only grow it when the width needs to be larger than it is currently
var item = $(this);
var origWidth = item.data("initialWidth");
var curWidth = item.width();
if (!origWidth) {
origWidth = curWidth;
item.data("initialWidth", origWidth);
}
var newWidth = origWidth + (8 * item.val().length);
if (newWidth > curWidth) {
item.stop(true, true).animate({width: newWidth}, 500);
}
}
$('#code').userChange(updateWidth);
$.fn.valNotify = function(value) {
this.val(value);
this.each(function() {
updateWidth.call(this);
});
return this;
}
});
Then, you can change your values with this and it will automatically resize too:
$("#code").valNotify("foo");