/**
 * 表单输入格式检查器第3版。
 * 用法：
 * 给<input>,<select>,<textarea>等输入框的name属性加上一个格式指定的前缀（格式串）即可。
 * 在格式串的开头还可以加上一个“!”号，用来表示必填（不能为空）。
 * 另外可在<title>属性中给出输入错误时的提示，在检查时包含在弹出提示文字中。
 * 如果不想将格式串写在name属性中，也可以写在title属性中，由最后一个“~”符号隔开，之后为格式串，
 * 如 title="请填写电子邮件地址 ~!Email"
 * 示范：
 * <form onsubmit="return checkForm(this)" ...>
 *     姓名(必填)：<input name="!name">
 *     年龄：<input name="int age">
 *     邮箱(必填)：<input name="email" title="请填写电子邮件地址 ~!Email">
 *     爱好(30~50字)：<input name=".{30,50} fond">
 *     ...
 * </form>
 * 如果调用 return checkForm(this,true) 将在验证通过后将提交按钮禁用，以免重复提交
 *
 * 格式串是一个正则表达式，用来规定输入框的文本必须符合的格式。如果没有格式串，则表示不限定。
 * 关于正则式的语法，请参考：
 * http://msdn.microsoft.com/library/shared/deeptree/asp/rightframe.asp?dtcfg=/library/deeptreeconfig.xml&url=/library/en-us/script56/html/js56jsgrpregexpsyntax.asp
 *
 * 对于常用的格式有预定义的简化的格式别名可供使用，如“int”代表“\d*”，
 * 参见下面checkForm()函数中预定义的数组：
 * “formats”，每行格式为“别名 正则式 说明”
 */
function checkForm(fm,disableSubmitter) {
    try {
    var formats = new Array( //预定义格式类型
        "int [+-]?\\d* 整数",
        "long [+-]?\\d* 整数",
        "float [+-]?\\d*\\.?\\d* 小数",
        "double [+-]?\\d*\\.?\\d* 小数",
        "char . 字符",
        "Email \\w+([.]\\w+)*@\\w+([.]\\w+)+ 电子邮件地址",
        "Date \\d{4}-\\d{2}-\\d{2} 日期(yyyy-MM-dd)",
        "Time \\d{2}:\\d{2}:\\d{2} 时间(HH:mm:ss)",
        "Timestamp \\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2} 日期(HH:mm:ss)",
        "IdCard \\d{15}|\\d{17}[0-9xX] 身份证号(15位或18位)",
        "URL http://.* 互联网地址",
        "Chinese [^\\x00-\\xff]* 全中文",
        "");

    for(var i = 0; i < fm.length; i++) {
        var input = fm[i];
        var tag = input.tagName;
        if(tag != 'SELECT' && tag != 'INPUT' && tag != 'TEXTAREA') continue;

        var name = input.name; name = name.replace(/^\s*|\s*$/g,''); // 实现trim()方法
        var value = input.value;
        var title = input.title; if(title == null) title = '';

        //先获取格式串
        var k = name.indexOf(" ");
        var fmt = '';
        if(k > 0) {
            fmt = name.substring(0,k);
            name = name.substring(k+1);

        } else if(name.charAt(0) == '!') {
            fmt = "!";
            name = name.substring(1);

        } else { //name属性中不含格式串，找一下title中的“~”
            k = title.indexOf("~");
            if(k < 0) continue; //此输入项无格式控制，跳过
            fmt = title.substring(k+1);
            title = title.substring(0,k);
        }

        var allowEmpty = fmt.charAt(0) != '!';
        //非空检查
        if(!allowEmpty) {
            fmt = fmt.substring(1);

            if(input.type == 'radio' || input.type == 'checkbox') {
                var choices = fm[input.name];
                var choosed = false;
                if(typeof(choices.length) == 'undefined') { //只有一个选项
                    choices = [choices]; //变成只有一个元素的数组
                }

                for(var j = 0; j < choices.length; j++) {
                    var choice = choices[j];
                    if(choice.checked) {
                        choosed = true;
                        break;
                    }
                }
                if(!choosed) return error(input,name,'必须选择一项！',title);

            } else if(value.replace(/^\s*|\s*$/g,'') == '') {
                return error(input,name,'不能为空！',title);
            }
        }

        if(fmt == '') continue; //无其它格式限制

        var desc = '';

        //检查预定义类型
        for(var j = 0; j < formats.length; j++) {
            var format = formats[j];
            var k = format.indexOf(" ");
            if(k < 0) continue;
            var alias = format.substring(0,k);
            format = format.substring(k+1);

            if(fmt == alias) { //找到对应的预定义类型
                k = format.indexOf(" ");
                fmt = format.substring(0,k);
                desc = format.substring(k+1);
                break;
            }
        }
        if(value != "" && !new RegExp("^("+fmt.replace(/\\n|\\r/g,"")+")$").test(value.replace(/\n|\r/g," ").replace(/([^\x00-\xff])/g,'$1$1'))) {
            return error(input,name,desc != '' ? "格式不对，应该输入 "+desc
                : "不符合要求( "+fmt+" )，\n可能含非法字符或者少于或超出规定字符数等等\n（注意一个中文相当于两个字符）\n\n当前输入内容长度(字符数): "+checkForm$len(value),title);
        }
    }

    //全部检查通过，返回成功信息
    if(disableSubmitter) for(var i = 0; i < fm.length; i++) {
        var input = fm[i];
        if(input.tagName=='INPUT' && (input.type=='submit' || input.type=='image')) {
            input.disabled=true;
            input.value='请稍候...';
        }
    }

    return true;

    } catch(e) {
        alert(e);
        return false;
    }

    /** 显示输入出错提示 */
    function error(input,name,msg,title) {
        var bgColor = input.style.backgroundColor;
        input.style.backgroundColor = bgColor.search(/red|#?FF0000/) < 0 ? 'red' : 'blue';
        try {
            input.focus();
            input.select();
        } catch(e) {}

        msg = "输入项 "+name+" "+msg;
        if(title != null && title != '') msg = title+"\n\n详细提示：\n"+msg;
        alert(msg);
        input.style.backgroundColor = bgColor;
        return false;
    }

}

/** 一个取字串字符数长度的方法（一个中文算两个字符），方便外部获取 */
function checkForm$len(s) {
    return s.replace(/[^\x00-\xff]/g,'\0\0').length;
}

