Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

FormatTextBox jQuery Plugin

4.91/5 (10 votes)
13 Apr 2016CPOL12 min read 18.2K   294  
jQuery plugin that enforces a format on a text box, using jQuery Boilerplate plugin template

Introduction

Image 1

Did you ever needed to limit what the user can enter in a text box? Maybe you wanted the user to enter just digits but the text box also accepted letters too? The advantage of limiting what the user can enter is that it cuts down on errors and failed validations but it is by no means a replacement of a complete client and server validations. 

Enforcing a format on a text box can be achieved by JavaScript or jQuery solely, but once you need to do it many times for several text boxes, the best solution is to wrapped the implementation in a jQuery plugin. I looked for such jQuery plugin that can handle some of the more frequent formats like integer, float, date & time but couldn't find any or at the least I couldn't find one that suited my needs. There are some plugins that are more particular in their implementation, such as enforcing a specific credit card format, but that's not what I wanted so I decided to write this one myself. 

In the first half of this article I will overview the plugin, what it can do and how to use it. A thorough examination of each format with all their various settings are also detailed in the demo HTML file with plenty of examples. In the second half of this article I will show how the jQuery plugin was built using a plugin template from jQuery Boilerplate and how all the pieces of code fit together.

FormatTextBox Plugin

The plugin supports the following formats:

  • integer - Integer number.
  • float - Decimal number. Format is defined by precision & scale.
  • date - Short date (such as 31/12/2015).
  • time - Time format (such as 23:59).
  • regex - General-purpose format. Enforces a format with the use of regular expressions.
JavaScript
$("input:text").formatTextBox({ formatType: "integer" });
$("input:text").formatTextBox({ formatType: "float" });
$("input:text").formatTextBox({ formatType: "date" });
$("input:text").formatTextBox({ formatType: "time" });
$("input:text").formatTextBox({ formatType: "regex" });

The plugin prevents flickering for characters that are not allowed by the given format. For example if the plugin is enforcing an integer format and the user clicked on a letter character, then that letter will not appear and then disappear (flickering). It will simply not appear in the text box. 

For most of the formats, the user can set a default value when the text box is empty. The plugin also keeps track of the last value that was in the text box before the user started to write to it. If the user entered a text that doesn't confirm to the specific format, the plugin will revert to the original text. 

The plugin handles shorthand values, meaning if the user entered a partial value it will complete it to confirm with the given format. A few examples: For a float format, a value of ".12" will be completed to "0.123". For a date format, a value of "311215" will be completed to "31/12/2015".

Integer Format

The integer format allows only digits in the text box. If the number range (set by min & max settings) is less than 0, it will allow a single - sign at the beginning of the text. Numbers with leading 0 will be truncated.

JavaScript
// defaults
$("input:text").formatTextBox({ 
    formatType: "integer",
    integer: {
        format: {
            digitGroupSymbol: ","
        },
        min: -2147483648,
        max: 2147483647
    },
    valueOnEmpty: null
});

This example limits the range to numbers between -10 and 10. If the text box is empty, it will revert to 1.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "integer",
    integer: {
        min: -10,
        max: 10
    },
    valueOnEmpty: 1
});

Float Format

The float format allows only digits in the text box and the specified decimal symbol. The numbers that are allowed are determined by the precision and the scale. Precision determines the maximum number of digits and the scale determines how many digits are there after the decimal symbol. If the number range (set by min & max settings) is less than 0, it will allow a single - sign at the beginning of the text. Numbers with leading 0 will be truncated.

JavaScript
// defaults
$("input:text").formatTextBox({ 
    formatType: "float",
    float: {
        format: {
            precision: 18,
            scale: 2,
            digitGroupSymbol: ",",
            decimalSymbol: "."
        },
        min: null,
        max: null
    },
    valueOnEmpty: null
});

This example limits the range to numbers between -10.123 and 10.456. A number has 3 digits after the decimal symbol (scale 3). If the text box is empty, it will revert to 0.000.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "float",
    float: {
        format: {
            scale: 3
        },
        min: -10.123,
        max: 10.456
    },
    valueOnEmpty: 0
});

Parse & Format Numbers

The plugin has two utility functions applicable for integer & float formats. parseNumber function parses the text in the text box and returns a JavaScript integer/float number. formatNumber function takes the number in the text box and format it with digit group symbols and decimal symbol. These two functions take into account the digit group symbol and the decimal symbol that were used. They can be very useful especially when the symbols are not the trivial ones. This example has non-trivial symbols.

JavaScript
$("input:text").val(1234.567);

$("input:text").formatTextBox({ 
    formatType: "float", 
    float: { 
        format: { 
            scale: 3,
            digitGroupSymbol: ".", 
            decimalSymbol: "," 
        } 
    }
});

// the text in text box will be "1234,567"
// because the decimal symbol is ","

// parse number: float number 1234.567
$("input:text").formatTextBox("parseNumber");

// format number: string "1.234,567"
$("input:text").formatTextBox("formatNumber");

Date Format

The date format enables a short date, such as 31/12/2015. The format allows for digits and the specified separator. The date can be limited between min and max values.

JavaScript
// defaults
$("input:text").formatTextBox({ 
    formatType: "date",
    date: {
        format: {
            shortDate: "dd/mm/yyyy",
            separator: "/"
        },
        min: null,
        max: null
    },
    nowOnEmpty: false,
    valueOnEmpty: null
});

Here's some simple examples. Unless is stated otherwise, the default format is dd/mm/yyyy.

JavaScript
// limit date to 2014
$("input:text").formatTextBox({ 
    formatType: "date", 
    date: { 
        min: '2014-01-01', 
        max: '2014-12-31' 
    } 
});

// set date to 01/01/1900 when empty
$("input:text").formatTextBox({ 
    formatType: "date", 
    valueOnEmpty: new Date('1900-01-01') 
});

// set date to today when empty
$("input:text").formatTextBox({ 
    formatType: "date", 
    nowOnEmpty: true 
});

This example uses a different date format mm.dd.yyyy.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "date", 
    date: { 
        format: { 
            shortDate: "mm.dd.yyyy",
            separator: "."
        } 
    }
});

Parse Date

parseDate is a utility function applicable for date format. This function parses the text in the text box and returns a JavaScript Date object. It takes into account the format of the date and the date separator.

JavaScript
$("input:text").val("12.31.2015");

$("input:text").formatTextBox({ 
    formatType: "date", 
    date: { 
        format: { 
            shortDate: "mm.dd.yyyy",
            separator: "."
        } 
    }
});

// parse date: Date object 31/12/2015
$("input:text").formatTextBox("parseDate");

Time Format

The time format enables a short time format without seconds, such as 23:59. It is not limited to a 24-hours cycle. The format allows for digits and : separator. The time can be limited between min and max values.

JavaScript
// defaults
$("input:text").formatTextBox({ 
    formatType: "time",
    time: {
        min: null,
        max: null
    },
    nowOnEmpty: false,
    valueOnEmpty: null
});

Some examples.

JavaScript
// limit time to 24 hours
$("input:text").formatTextBox({ 
    formatType: "time", 
    time: { 
        min: "00:00", 
        max: "23:59" 
    } 
});

// set time to 12:00 PM when empty
$("input:text").formatTextBox({ 
    formatType: "time", 
    valueOnEmpty: 1200 
});

// set time to now when empty
$("input:text").formatTextBox({ 
    formatType: "time", 
    nowOnEmpty: true 
});

Parse Time

parseTime is a utility function applicable for time format. This function parses the text in the text box and returns a JavaScript Date object for 01/01/1900 and adding the hours and minutes to it.

JavaScript
$("input:text").val("23:59");

$("input:text").formatTextBox({ formatType: "time" });

// parse time: Date object 01/01/1900 23:59:00.
$("input:text").formatTextBox("parseTime");

Regex Format

The regex format is where the user can realize his own formats through regular expressions. regex.pattern is the text pattern. When set to null, the regex pattern will default to .* to allow all patterns. regex.chars determines which key strokes are allowed, preferably written in a bracket expression, for example [0-9a-zA-Z]. When set to null, allows all key strokes to pass through. regex.length is the maximum allowed length of the text. When set to null, is disabled. regex.empty determines whether the text box can be empty or not. regex.pattern & regex.chars can be string or RegExp object.

JavaScript
// defaults
$("input:text").formatTextBox({ 
    formatType: "regex",
    regex: {
        pattern: null,
        chars: null,
        length: null,
        empty: true
    },
    valueOnEmpty: null
});

This example enforces an alphanumeric format which the first character must be a letter.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "regex", 
    regex: { 
        pattern: "[a-zA-Z].*", 
        chars: "[0-9a-zA-Z]"
    } 
});

This example enforces a strong password. At least 16 characters. Has uppercase letters. Has lowercase letters. Has numbers. Has symbols.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "regex", 
    regex: { 
        pattern: /(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[-+_=!@#$%^&*|.,:;~?`'"(){}[\]<>\\/]).{16,}/,
        chars: /[0-9a-zA-Z-+_=!@#$%^&*|.,:;~?`'\"(){}[\]<>\\/]/ 
    }
});

Named Formats

The user can register formats with the plugin as a key-value pair where the key is the user-given name of the format and the value is the options object. This mechanism can be leveraged to register all the formats before using them on any number of text boxes. The registration is done by the static function namedFormat, which is a getter/setter function. namedFormat is not recursive, registering another named format won't work.

JavaScript
// register Y2K format
$.fn.formatTextBox.namedFormat("Y2K", { 
    formatType: "integer", 
    integer: { min: 2000, max: 2999 },
    valueOnEmpty: 2000
});

// get Y2K format
$.fn.formatTextBox.namedFormat("Y2K");

// use Y2K format
$("input:text").formatTextBox({ formatType: "Y2K" });

Callbacks

The plugin supports several callbacks that the user can register to. The callbacks, in firing order, are onBeforeFocus, onFocus, onBeforeKeypress, onKeypress, onBeforeBlur, onEmpty, onValidationError, onBlur. The event argument is a jQuery normalized event object. The data argument is the data that was passed as an option when the format was initialized. this references the input DOM control.

Focus Callbacks

onBeforeFocus and onFocus callbacks fire before and after the plugin handles the focus event. This is when the plugin essentially setting aside the current text before the user starts to write in the text box. onBeforeFocus is where the user can change the input text before it is processed. onFocus data argument holds the input text when the focus event occurs. This data argument is useful when options.clearOnFocus = true because the input is empty at the end of the focus event and the user can't get it through $.val().

JavaScript
$("input:text").formatTextBox({ 
    onBeforeFocus: function (event, data) { 
    },

    onFocus: function (event, data) {
        data.value; // text box value
    }
});

The plugin provides some options for common actions on focus event, so the user won't need to implement them with the focus callbacks. clearOnFocus will clear the text once the input control gains focus. selectOnFocus will select all the text once the input control gains focus. Both options can take a boolean or a function.

JavaScript
$("input:text").formatTextBox({ 
    formatType: "integer",
    clearOnFocus: true,
    selectOnFocus: true
});

// clear if the text is 0, otherwise select all the text
$("input:text").formatTextBox({ 
    formatType: "integer",
    clearOnFocus: function(text) {
        return (text == "0");
    },
    selectOnFocus: function(text) {
        return (text != "0");
    }
});
Keypress Callbacks

onBeforeKeypress and onKeypress callbacks fire before and after the plugin processes the pressed key. onBeforeKeypress is where you can prevent the Keypress event to continue by calling to event.preventDefault(). data argument holds the char code of the key and whether the pressed key was prevented or accepted. data.charCode is the same as event.which. data.isPrevented is the same as calling event.isDefaultPrevented().

JavaScript
$("input:text").formatTextBox({ 
    onBeforeKeypress: function (event, data) { 
        data.charCode; // key pressed
        event.preventDefault(); // stop key press
    },

    onKeypress: function (event, data) {
        data.charCode; // key pressed
        data.isPrevented; // whether the pressed key was accepted or rejected
    }
});

The plugin provides some predefined keypress char codes that the user can access through $.fn.formatTextBox.keypressCodes. This examples shows how to prevent a tilde (~) key stroke.

JavaScript
$("input:text").formatTextBox({ 
    onBeforeKeypress: function (event, data) { 
        if (data.charCode == $.fn.formatTextBox.keypressCodes.Tilde) // ~
            event.preventDefault();
    }
});
Blur Callbacks

onBeforeBlur and onBlur callbacks fire before and after the plugin handles the blur event. This is when the plugin examines the text in the text box and sees if it confirms to its format. If not, it will revert back to the original text. onEmpty callback fires if the text box is empty. onValidationError callback fires if the text in the text box doesn't confirm with the format. onValidationError data argument holds the rejected text. 
clearOnError will clear the text when the text doesn't confirm with the format instead of retrieving the original text. This option can take a boolean or a function.

JavaScript
$("input:text").formatTextBox({ 
    onBeforeBlur: function (event, data) { 
    },

    onEmpty: function (event, data) { 
    },

    onValidationError: function (event, data) {
        data.value; // rejected text
    },

    onBlur: function (event, data) { 
    },

    clearOnError: false,
    // or
    clearOnError: function(text) {
        return (text != "");
    }
});

This example demonstrates how to use onBeforeBlur callback and data option to leverage an auto-complete feature on an email format. If the email has no host, it will auto-complete it with "gmail.com". The auto-complete is implemented with the onBeforeBlur callback and not with the onBlur callback because we want to verify that the text that was auto-completed confirm with the email regex pattern.

JavaScript
$("input:text").formatTextBox({
    formatType: "regex",
    regex: {
        pattern: /([a-zA-Z0-9'_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+/,
        keystrokePattern: /[^@]+@?[^@]*/,
        chars: "[0-9A-Za-z'-.@_]"
    },
    data: {
        host: "gmail.com"
    },
    onBeforeBlur: function (event, data) {
        if (data != null && data.host != null && data.host.toString() != "") {
            var $elem = $(this);
            var value = $elem.val();
            if (value != "") {
                var index = value.lastIndexOf("@");
                if (index == -1) {
                    value += "@" + data.host;
                    $elem.val(value);
                } else if (index == value.length - 1) {
                    value += data.host;
                    $elem.val(value);
                }
            }
        }
    }
});

jQuery Boilerplate Plugin Template

We start with a template plugin from jQuery Boilerplate. This site has various templates aimed at simple and advanced use cases. It also has widget templates aimed at jQuery UI. These templates represent cumulation of authoring best practices. The intent is to prevent from the user to reinvent the wheel and let him focus on the plugin core and main logic. The template that FormatTextBox plugin uses is Highly Configurable Pattern. On top of this pattern, it also uses Extending jQuery Boilerplate to provide access to public prototype methods and prevent against multiple plugin instantiations. So we start with this template.

JavaScript
; (function ($, window, document, undefined) {

    /* private plugin members */

    var pluginName = "nameOfThePlugin",

        // instance of the Plugin object
        Plugin = function (elem, options) {
            this.elem = elem;
            this.$elem = $(elem);
            this.options = options;
            this._name = pluginName;

            this.init();
        };

    /* Plugin object prototype */

    Plugin.prototype = {
        defaults: { },

        init: function () { },
        destroy: function () { }

        // plugin functions here

    };

    Plugin.defaults = Plugin.prototype.defaults;

    /* register plugin with jQuery */

    $.fn[pluginName] = function (options) {
        var args = arguments;

        // instantiate a new instance of the plugin
        if (options === undefined || typeof options === "object") {
            return this.filter("*").each(function () {
                if (!$.data(this, "plugin_" + pluginName))
                    $.data(this, "plugin_" + pluginName, new Plugin(this, options));
            });

        // call to a public method
        } else if (typeof options === "string" && options[0] !== "_" && options !== "init") {
            // cache the method call
            var returns;

            this.filter("*").each(function () {
                var instance = $.data(this, "plugin_" + pluginName);

                // call the method
                if (instance instanceof Plugin && typeof instance[options] === "function")
                    returns = 
                        instance[options].apply(instance, Array.prototype.slice.call(args, 1));

                // allow instances to be destroyed via the "destroy" method
                if (options === "destroy")
                    $.data(this, "plugin_" + pluginName, null);
            });

            // if the cached method call didn't returned a value
            // return this to preserve chainability
            return (returns !== undefined ? returns : this);
        }
    };

})(jQuery, window, document);

When the plugin is called on a DOM object, it first checks if the DOM object is associated with a Plugin object instance (using jQuery $.data()). If there is already an instance, then the plugin was already called and initialized. In that case nothing is done and there are no multiple instantiations. If it's the first call, the plugin will create a new Plugin object instance and associate it with the DOM object. If we look at the Plugin object constructor, we can see that it keeps references to the DOM object (this.elem), its jQuery object (this.$elem) and the options (this.options) that were passed in the call. The constructor then calls init for the first and only time and at that, the plugin is instanced and initialized. 

If we want to call a plugin public function, the name of the function must come as the first argument and the rest of the arguments are options to that function. The name of the function must not start with an underscore (_) because that's a private function and we can't call init again. The plugin retrieves the function, which is located in the Plugin instance, and execute it with the options if there are any. 

When we call destroy, first the function is executed like any other public plugin function. This is where we want to remove any event handlers that we attached to the DOM object and make any other clean operations to restore the DOM object back to its original state. Then, the DOM object is disassociated with its Plugin instance. That signifies that the plugin is no longer operating on the DOM object and subsequent calls on this object are possible. 

You can also notice that the template has this.filter("*") clause. The filter is intended to prevent from the plugin to operate on the wrong types of DOM objects. With FormatTextBox, the filter will be this.filter("input:text") because the plugin only works on text boxes.

Plugin Implementation

init function is where we hook up the 3 events, focus, keypress & blur, to the text box. destroy function is where we unhook these events. When we hook the event handler, we use $.proxy() to make sure that this is always pointing to the Plugin object instance.

JavaScript
Plugin.prototype = {

    init: function () {
        this.settings = $.extend(true, {}, this.defaults, this.options);

        if (this.settings.formatType == "integer") {
            this.$elem
                .on("focus.formatTextBox", $.proxy(this._integerFocus, this))
                .on("keypress.formatTextBox", $.proxy(this._integerKeypress, this))
                .on("blur.formatTextBox", $.proxy(this._integerBlur, this));
        }
        else if (this.settings.formatType == "float") { }
        else if (this.settings.formatType == "date") { }
        else if (this.settings.formatType == "time") { }
        else if (this.settings.formatType == "regex") { }

        return this;
    },

    destroy: function () {
        this.$elem.off(".formatTextBox");
    }
};
Focus

Now we want to put some meat on the plugin. From now on we will concentrate on implementing the integer format, All the functions will be declared in the Plugin.prototype object. We start with the focus event handler. The purpose of focus is to save the current text aside, before it is being changed, so later it would be possible to revert back to it if necessary. The focus event also takes care of clearing the text box or selecting all the text in it.

JavaScript
_integerFocus: function (event) {
    // save the current text
    this.currentValue = this.$elem.val();

    // clear the text box
    if (this.settings.clearOnFocus)
        this.$elem.val("");

    // select all the text
    if (this.settings.selectOnFocus) 
        this.$elem.select();
}
Keypress

The keypress event handler determines whether a keystroke is valid or not. For the integer format we want to allow only digits and minus sign at the beginning of the text. Every other key stroke is not allowed and is prevented.

JavaScript
_integerKeypress: function (event) {
    // jQuery event.which normalizes event.keyCode and event.charCode
    var charCode = event.which;

    // if the event was suppressed before, don't do anything
    if (event.isDefaultPrevented())
        return false;

    // keystrokes allowed: control keys, digits, minus sign
    if (!(
        charCode == 0 || // arrows
        charCode == 8 || // backspace
        charCode == 9 || // tab 
        charCode == 13 || // enter
        charCode == 27 || // escape
        (48 <= charCode && charCode <= 57) || // 0-9
        charCode == 45 // -
    )) {
        event.preventDefault();
        return false;
    }

    // minus sign at the beginning of the text
    if (charCode == 45) {
        var txtFieldPosition = this._getTextFieldPosition(this.elem);
        var caretPosition = 
            txtFieldPosition.caretPosition - txtFieldPosition.selectionLength;

        if (this.elem.value.charAt(0) == '-') {
            // already contains -
            if (caretPosition != 0) {
                event.preventDefault();
                return false;
            }
        } else {
            // allow only in the beginning of the text
            if (caretPosition != 0) {
                event.preventDefault();
                return false;
            }
        }
    }

    return true;
}

getTextFieldPosition function returns the caret position and the selection length of the text box. It is very useful when you want to allow certain characters at very specific location, such as beginning or end, in the text box.

JavaScript
_getTextFieldPosition: function (elem) {
    var caretPosition = 0;
    var selectionLength = 0;

    // IE
    if (document.selection) {
        elem.focus();
        var selection = document.selection.createRange();
        selectionLength = selection.text.length;
        selection.moveStart('character', -elem.value.length);
        caretPosition = selection.text.length;
    }
    // Firefox
    else if (elem.selectionStart || elem.selectionStart == '0') {
        caretPosition = elem.selectionEnd;
        selectionLength = elem.selectionEnd - elem.selectionStart;
    }

    return {
        caretPosition: caretPosition,
        selectionLength: selectionLength
    };
}
Blur

The blur event handler determines whether the text is valid and confirm the given format. If not, it will revert back to the previous text that was in the text box. The blur event handler also takes care of auto-complete scenarios. If the user entered partial input, the function will complete the text to confirm to the format. An example of that is when the format is decimal with two 0s after the decimal point and the user entered an integer, the blur event handler will complete it with ".00" at the end of the text. In the case of the integer format, the auto-complete will take care of leading 0s.

JavaScript
var INTEGER_REGEX_1 = /^\d*$|^-\d+$/,       // empty, 123, -123
    INTEGER_REGEX_2 = /^-?0+$/,             // 000, -000
    INTEGER_REGEX_3 = /^-?0+[1-9][0-9]*$/;  // 000123, -000123

_integerBlur: function (event) {
    // the current text
    var value = this.$elem.val();

    // auto complete
    value = this._integerAutoComplete(value, this.settings);

    // validation
    if (!!value.match(INTEGER_REGEX_1)) {

        // empty value
        if (value == null || value.toString() == "") {

            // specific value when empty, set by the user in the options
            if (this.settings.valueOnEmpty != null) {
                var valueOnEmpty = 
                    this._integerAutoComplete(this.settings.valueOnEmpty, this.settings);
                if (!!valueOnEmpty.match(INTEGER_REGEX_1))
                    this.$elem.val(valueOnEmpty);
                else
                    this.$elem.val(value);
            } else {
                this.$elem.val(value);
            }
        } else {

            // parse the text to integer
            var intValue = this._parseNumber(value, false, 
                this.settings.integer.format.digitGroupSymbol, 
                this.settings.integer.format.decimalSymbol
            );

            // validate that the integer is between min and max values, 
            // if they are specificed by the user in the options
            var inMinRange = (intValue != null && 
                (this.settings.integer.min == null || this.settings.integer.min <= intValue));
            var inMaxRange = (intValue != null && 
                (this.settings.integer.max == null || intValue <= this.settings.integer.max));

            if (inMinRange && inMaxRange)
                this.$elem.val(value); // validation succeeded
            else
                this._validationError(event, value); // validation error
        }
    } else {
        this._validationError(event, value); // validation error
    }
}

// integer auto complete
_integerAutoComplete: function (value, settings) {
    value = value.toString();

    if (!!value.match(INTEGER_REGEX_2)) {
        value = "0";
    } else if (!!value.match(INTEGER_REGEX_3)) {
        value = this._parseNumber(value, false, 
            settings.integer.format.digitGroupSymbol, 
            settings.integer.format.decimalSymbol
        ).toString(10);
    }

    return value;
}
Callbacks

Now that the 3 events, focus, keypress & blur are implemented, we want to integrate callbacks into the code. The callbacks are defined as empty functions by default. The _onCallback function is a private function which is responsible for making the actual triggering of the callback function and all the events refer to _onCallback for its execution.

JavaScript
// callbacks defined as empty functions
defaults: {
	onBeforeFocus: $.noop,
	onFocus: $.noop,
	onBeforeKeypress: $.noop,
	onKeypress: $.noop,
	onBeforeBlur: $.noop,
	onEmpty: $.noop,
	onValidationError: $.noop,
	onBlur: $.noop
},

// execute callback
_onCallback: function (callbackName, event, data) {
	if ($.isFunction(this.settings[callbackName]) && event) {
		data = $.extend(true, {}, data, this.settings.data || {});
		this.settings[callbackName].call(this.elem, event, data);
	}
},

// events
_onBeforeFocus:     function (event, data) { this._onCallback("onBeforeFocus", event, data); },
_onFocus:           function (event, data) { this._onCallback("onFocus", event, data); },
_onBeforeKeypress:  function (event, data) { this._onCallback("onBeforeKeypress", event, data); },
_onKeypress:        function (event, data) { this._onCallback("onKeypress", event, data); },
_onBeforeBlur:      function (event, data) { this._onCallback("onBeforeBlur", event, data); },
_onEmpty:           function (event, data) { this._onCallback("onEmpty", event, data); },
_onValidationError: function (event, data) { this._onCallback("onValidationError", event, data); },
_onBlur:            function (event, data) { this._onCallback("onBlur", event, data); }

// focus
_integerFocus: function (event) {
	this._onBeforeFocus(event);

	// focus code
	
	this._onFocus(event, { 
        value: this.currentValue 
    });
},

// keypress
_integerKeypress: function (event) {
	var charCode = event.which;
	
    this._onBeforeKeypress(event, { 
        charCode: charCode 
    });

	// keypress code
	
	this._onKeypress(event, { 
        charCode: charCode, 
        isPrevented: false 
    });

	return true;
},

// blur
_integerBlur: function (event) {
	this._onBeforeBlur(event);

	var value = this.$elem.val();

	// if value is empty
	this._onEmpty(event);
	
	// if value is not valid
	this._validationError(event, value);
	
	this._onBlur(event);
}

History

14/04/2016: Firefox bugfix. Couldn't delete text in Firefox.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)