65.9K
CodeProject 正在变化。 阅读更多。
Home

FormatTextBox jQuery 插件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (9投票s)

2016年4月11日

CPOL

12分钟阅读

viewsIcon

18587

downloadIcon

320

jQuery 插件,使用 jQuery Boilerplate 插件模板强制文本框的格式。

引言

您是否曾经需要限制用户在文本框中输入的内容?也许您只希望用户输入数字,但文本框也接受字母?限制用户输入内容的优点是可以减少错误和验证失败,但这绝不是替代完整的客户端和服务器端验证。 

通过纯 JavaScript 或 jQuery 可以实现强制文本框的格式,但一旦您需要在多个文本框中多次执行此操作,最佳解决方案就是将实现包装成一个 jQuery 插件。我寻找了可以处理一些更常见格式(如整数、浮点数、日期和时间)的 jQuery 插件,但找不到任何符合我需求的插件。有一些插件在实现上更具体,例如强制特定的信用卡格式,但这并不是我想要的,所以我决定自己编写一个。 

在本文的前半部分,我将概述该插件,介绍它的功能和用法。所有格式及其各种设置的详细检查也将在演示 HTML 文件中详细介绍,并提供大量示例。在本文的后半部分,我将展示如何使用 jQuery Boilerplate 的插件模板构建 jQuery 插件,以及所有代码块如何协同工作。 

FormatTextBox 插件

该插件支持以下格式:

  • 整数 - 整数。
  • 浮点数 - 小数。格式由精度和标度定义。
  • 日期 - 短日期(例如 2015/12/31)。
  • 时间 - 时间格式(例如 23:59)。
  • 正则表达式 - 通用格式。使用正则表达式强制执行格式。
$("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" });

该插件可防止字符闪烁,这些字符不符合给定格式。例如,如果插件强制执行整数格式,并且用户单击了一个字母字符,那么该字母将不会出现然后消失(闪烁)。它根本不会出现在文本框中。 

对于大多数格式,用户可以设置一个默认值,当文本框为空时。该插件还会跟踪用户开始输入文本之前文本框中的最后一个值。如果用户输入的文本不符合特定格式,插件将恢复到原始文本。 

该插件处理简写值,这意味着如果用户输入了部分值,它将完成该值以符合给定格式。一些示例:对于浮点数格式,值为“ .12”将被完成为“ 0.123”。对于日期格式,值为“ 311215”将被完成为“ 31/12/2015”。

整数格式

整数格式仅允许在文本框中输入数字。如果数字范围(由 min 和 max 设置定义)小于 0,则允许在文本开头有一个单独的“-”号。带有前导零的数字将被截断。

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

此示例将范围限制在-10到 10 之间的数字。如果文本框为空,则恢复为 1。

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

浮点数格式

浮点数格式仅允许在文本框中输入数字和小数点符号。允许的数字由精度和标度决定。精度决定了数字的最大位数,标度决定了小数点后的位数。如果数字范围(由 min 和 max 设置定义)小于 0,则允许在文本开头有一个单独的“-”号。带有前导零的数字将被截断。

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

此示例将范围限制在-10.123 和 10.456 之间的数字。数字在小数点后有 3 位数字(标度为 3)。如果文本框为空,则恢复为 0.000。

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

解析和格式化数字

该插件有两个适用于整数和浮点数格式的实用函数。parseNumber函数解析文本框中的文本并返回一个 JavaScript 整数/浮点数。formatNumber函数接收文本框中的数字并使用数字分组符号和小数点符号对其进行格式化。这两个函数都考虑了使用的数字分组符号和小数点符号。它们可能非常有用,尤其是在符号不是普通符号的情况下。 此示例具有非普通符号。

$("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");

日期格式

日期格式支持短日期,例如 31/12/2015。该格式允许输入数字和指定的分隔符。日期可以限制在 min 和 max 值之间。

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

这里有一些简单的示例。除非另有说明,否则默认格式为 dd/mm/yyyy。

// 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 
});

此示例使用不同的日期格式 mm.dd.yyyy。

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

解析日期

parseDate 是一个适用于日期格式的实用函数。此函数解析文本框中的文本并返回一个 JavaScript Date 对象。它考虑了日期的格式和日期分隔符。

$("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");

时间格式

时间格式支持短时间格式,不带秒,例如 23:59。它不限于 24 小时制。该格式允许输入数字和“ :”分隔符。时间可以限制在 min 和 max 值之间。

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

一些示例。

// 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 
});

解析时间

parseTime 是一个适用于时间格式的实用函数。此函数解析文本框中的文本,并返回一个 JavaScript Date 对象,该对象为 1900/01/01 并加上小时和分钟。

$("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.pattern 是文本模式。设置为 null 时,正则表达式模式将默认为 .*,允许所有模式。regex.chars 确定允许哪些按键,最好用方括号表示,例如 [0-9a-zA-Z]。设置为 null 时,允许所有按键通过。regex.length 是允许的最大文本长度。设置为 null 时,禁用。regex.empty 确定文本框是否可以为空。regex.patternregex.chars 可以是字符串或 RegExp 对象。

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

此示例强制执行字母数字格式,其中第一个字符必须是字母。

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

此示例强制执行强密码。至少 16 个字符。包含大写字母。包含小写字母。包含数字。包含符号。

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

命名格式

用户可以作为键值对将格式注册到插件,其中键是用户指定的格式名称,值是选项对象。可以利用此机制在任意数量的文本框上注册所有格式,然后再使用它们。注册通过静态函数 namedFormat 进行,这是一个 getter/setter 函数。namedFormat 不是递归的,注册另一个命名格式将不起作用。

// 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" });

回调

该插件支持用户可以注册的几个回调。回调的触发顺序是:onBeforeFocusonFocusonBeforeKeypressonKeypressonBeforeBluronEmptyonValidationErroronBlur。事件参数是 jQuery 标准化事件对象。数据参数是初始化格式时作为选项传递的数据。 this 引用输入 DOM 控件。

焦点回调

onBeforeFocusonFocus 回调在插件处理焦点事件之前和之后触发。这是插件在用户开始在文本框中输入之前保存当前文本的时候。onBeforeFocus 是用户可以在处理之前更改输入文本的地方。onFocus 数据参数包含焦点事件发生时的输入文本。当 options.clearOnFocus = true 时,此数据参数很有用,因为焦点事件结束时输入是空的,用户无法通过 $.val() 获取它。

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

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

该插件为焦点事件上的常见操作提供了一些选项,因此用户无需使用焦点回调来实现它们。clearOnFocus 会在输入控件获得焦点后清除文本。selectOnFocus 会在输入控件获得焦点后选择所有文本。这两个选项都可以接受布尔值或函数。

$("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");
    }
});
按键回调

onBeforeKeypressonKeypress 回调在插件处理按键之前和之后触发。onBeforeKeypress 是您可以通过调用 event.preventDefault() 来阻止按键事件继续的地方。数据参数包含键的字符代码以及按键是否被阻止或接受。data.charCode 与 event.which 相同。data.isPrevented 与调用 event.isDefaultPrevented() 相同。

$("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
    }
});

该插件提供了一些预定义的按键字符代码,用户可以通过 $.fn.formatTextBox.keypressCodes 访问。此示例显示如何阻止波浪线(~)按键。

$("input:text").formatTextBox({ 
    onBeforeKeypress: function (event, data) { 
        if (data.charCode == $.fn.formatTextBox.keypressCodes.Tilde) // ~
            event.preventDefault();
    }
});
失去焦点回调

onBeforeBluronBlur 回调在插件处理失去焦点事件之前和之后触发。这是插件检查文本框中的文本是否符合其格式的时候。如果不符合,它将恢复到文本框中的原始文本。onEmpty 回调在文本框为空时触发。onValidationError 回调在文本框中的文本不符合格式时触发。onValidationError 数据参数包含被拒绝的文本。 
clearOnError 会在文本不符合格式时清除文本,而不是检索原始文本。此选项可以接受布尔值或函数。

$("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 != "");
    }
});

此示例演示如何使用 onBeforeBlur 回调和 data 选项来实现电子邮件格式的自动完成功能。如果电子邮件没有主机,它将自动完成为“ gmail.com”。自动完成是通过 onBeforeBlur 回调而不是 onBlur 回调实现的,因为我们想验证自动完成的文本是否符合电子邮件正则表达式模式。

$("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 插件模板

我们从 jQuery Boilerplate 的一个模板插件开始。该网站提供各种模板,适用于简单和高级用例。它还提供针对 jQuery UI 的小部件模板。这些模板代表了作者最佳实践的积累。目的是避免用户重复造轮子,让他们专注于插件的核心和主要逻辑。FormatTextBox 插件使用的模板是 高度可配置模式。在此模式的基础上,它还使用了 扩展 jQuery Boilerplate 来提供对公共原型方法的访问,并防止插件被多次实例化。 所以我们从这个模板开始。

; (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);

当插件在 DOM 对象上调用时,它首先检查 DOM 对象是否与插件对象实例关联(使用 jQuery $.data())。如果已存在实例,则插件已被调用和初始化。在这种情况下,不会执行任何操作,也不会发生多次实例化。如果是第一次调用,插件将创建一个新的插件对象实例并将其与 DOM 对象关联。如果我们查看插件对象的构造函数,我们可以看到它保留了对 DOM 对象(this.elem)、其 jQuery 对象(this.$elem)以及调用中传递的选项(this.options)的引用。然后,构造函数第一次且唯一一次调用 init,此时,插件将被实例化和初始化。 

如果我们想调用插件的公共函数,函数名必须作为第一个参数,其余参数是该函数的选项。函数名不能以“_”开头,因为那是私有函数,我们不能再次调用 init。插件检索位于插件实例中的函数,并用选项(如果存在)执行它。 

当我们调用 destroy 时,首先像任何其他公共插件函数一样执行该函数。这是我们想要删除我们附加到 DOM 对象的任何事件处理程序,并进行任何其他清理操作以将 DOM 对象恢复到其原始状态的地方。然后,DOM 对象与其插件实例解除关联。这表示插件不再操作 DOM 对象,并且随后可以对此对象进行调用。 

您还可以注意到模板中包含 this.filter("*") 子句。该过滤器旨在防止插件操作错误的 DOM 对象类型。对于 FormatTextBox,过滤器将是 this.filter("input:text") ,因为该插件仅适用于文本框。

插件实现

init 函数是我们为文本框挂钩 3 个事件:焦点、按键和失去焦点。 destroy 函数是我们取消挂钩这些事件的地方。当我们挂钩事件处理程序时,我们使用 $.proxy() 来确保 this 始终指向 Plugin 对象实例。 

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");
    }
};
焦点

现在我们想为插件添加一些实质内容。从现在开始,我们将专注于实现整数格式。所有函数都将在 Plugin.prototype 对象中声明。我们从焦点事件处理程序开始。焦点的目的是在文本被更改之前将其保存起来,以便以后可以在必要时恢复它。焦点事件还负责清除文本框或选择其中的所有文本。

_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();
}
按键

按键事件处理程序确定按键是否有效。对于整数格式,我们只希望在文本开头允许输入数字和减号。任何其他按键都是不允许的,并且会被阻止。

_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 函数返回文本框的光标位置和选择长度。当您希望在特定位置(例如文本框的开头或结尾)允许某些字符时,它非常有用。

_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
    };
}
失去焦点

失去焦点事件处理程序确定文本是否有效并符合给定格式。如果不符合,它将恢复到文本框中的先前文本。失去焦点事件处理程序还负责自动完成场景。如果用户输入了部分输入,该函数将完成文本以符合格式。一个例子是,当格式是小数点后有两个 0 的十进制数,而用户输入了一个整数时,失去焦点事件处理程序将在文本末尾添加“.00”。对于整数格式,自动完成将处理前导零。

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;
}
回调

现在 3 个事件(焦点、按键和失去焦点)都已实现,我们希望将回调集成到代码中。回调默认定义为空函数。 _onCallback 函数是一个私有函数,负责实际触发回调函数,所有事件都引用 _onCallback 来执行。

// 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);
}

历史

2016/04/14:Firefox bug 修复。在 Firefox 中无法删除文本。

© . All rights reserved.