end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

jQuery.validation (javascript)の練習

やはり調べた範囲では、client側のvalidationは jQuery.validation が、よさそ

参考url

html & javascript source

詳細は、src 内のコメントを参照下さい。

src内に記載していない機能も多くありますので、 それらは、 https://jqueryvalidation.org/validate/ を参照下さい。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/jquery-validation@1.19.2/dist/jquery.validate.min.js"></script>
<!--〒→住所変換 by google 日本語入力api-->
<script src="/contact2/common/zip2address.js"></script>
<!--自動フリガナ入力-->
<script src="/contact2/common/jquery.autoKana.js"></script>


<script src="foo.js"></script>
</head>
<body class="catalogForm">
  <form action="" method="post" name="form1" id="form1" class="clearDiv">
    <div>
      <input type="text" name="name"      placeholder="氏名(必須)"/>
      <input type="text" name="name_kana" placeholder="氏名カナ"/>
    </div>
  
    <div>
      <input type="text" name="tel"       placeholder="TEL"/>
    </div>
  
    <div>
      <input type="text" name="mail"      placeholder="mail"/>
      <input type="text" name="mail2"     placeholder="mail確認"/>
    </div>
  
  <input type="text" name="zipcode"   placeholder="郵便番号"/>
  <button type="button" onClick="myform.conv_zip2address()"
          >〒→住所変換</button><br/>
  <input type="text" name="address_pref"  placeholder="都道府県"/>
  <input type="text" name="address_city"  placeholder="区市町村"/>
  <input type="text" name="address_other" placeholder="住所 その他"/><br/>

  <select name="job" style="width:175px;">
    <option value="">職業選択欄</option>
    <option value="会社員">会社員</option>
    <option value="公務員">公務員</option>
    <option value="学生"  >学生</option>
    <option value="その他">その他</option>
  </select>
  <input type="text" name="job_other"
     placeholder="職業=その他の場合、入力"/><br/>

  
  訪問のきっかけ(最大2個選択)<br/>
  <label style="display:inline-block; width:175px;">
    <input type="checkbox" name="visit_trriger" value="tv"/>テレビ
  </label>
  <label style="display:inline-block; width:175px;">
    <input type="checkbox" name="visit_trriger" value="homepage"/>ホームページ
  </label>
  <label style="display:inline-block; width:175px;">
    <input type="checkbox" name="visit_trriger" value="homepage"/>知人の紹介
  </label>
  <br/>

  <textarea name="opinion" style="width:500px; height:50px;"
            >よろしければ、ご意見をお聞かせ下さい(10文字以内)</textarea>
  <br/>
  <button type="button" onClick="myform.validate_all()">VALIDATE</button>
</form>

<script> $(document).ready( function(){ myform.init_input_page(); }); </script>
</body>
</html>
(function() {
    var MyForm = function() {};
    MyForm.prototype = {
        
        validate_rule: {
            "rules" :
            {"name"      :{"required" : true,
                           "rangelength": [1,50] },
             //「is_katakana」は独自作成のrule
             "name_kana" :{"required" : true, is_katakana:true},
             "mail"      :{email: true },
             "mail2"     :{email: true, equalTo: 'input[name="mail"]' },
             // 「職業=その他」を選択した場合、text欄に入力
             "job_other" :{
                 "required":{"depends":function(element) {
                     return true ? $('select[name="job"]').val()=="その他": false;
                 }}},
             // checkbox選択数のvalidation
             "visit_trriger":{"rangelength": [0, 2] }, //checkboxも選択数を指定可
             "opinion"      :{"rangelength": [0,10] }
            },
            messages:
            {"name"     :{"required" :"氏名は必須項目です",
                          "maxlength":"氏名は50文字以内で入力下さい"},
             "name_kana":{"required" :"氏名(カナ)は必須項目です",
                          "is_katakana": "氏名(カナ)はカタカナで入力下さい"},
             "mail"     :{"email"    :"@ のあるメールアドレス形式で入力下さい"},
             "mail2"    :{"email"    :"@ のあるメールアドレス形式で入力下さい",
                          "equalTo"  :"同じメールアドレスを2箇所へ入力下さい" },
             "job_other":{"required" :"職業(その他)の場合、入力下さい"},
             "visit_trriger":{"rangelength":"訪問のきっかけは2個まで選択可能です"},
             "opinion"  :{"maxlength":"10文字以内で入力下さい"}
            },
        },

        validate_opt_rule: {
            // validation後のtagやclass等
            errorElement: "span", // validation NG 時の要素が label->span
            errorClass:   "validate_NG",// validation NG 時のclass
            validClass:   "validate_OK",// validation OK 時のclass
            //validation実行のタイミング
            onsubmit  :false,
            onfocusout:false,
            onkeyup   :false,
            onclick   :false
        },
        
        init_input_page: function(){
            // jquery.validation の有効化
            $("#form1").validate(Object.assign(this.validate_rule,
                                               this.validate_opt_rule));
            // jquery.validation の独自ruleの追加
            this.add_opt_validate_method();

            $('input[type="text"]').attr("autocomplete","off");
            
            //氏名→氏名カナ の自動入力
            $.fn.autoKana('input[name="name"]',
                          'input[name="name_kana"]',
                          {katakana:true });
        },
        
        add_opt_validate_method:function(){
            var this_obj = this;
            // カタカナ validationの独自rule
            // 内部でカタカナ化の変換を行っていますが
            // 別method & 別タイミングで行った方がいいかも
            jQuery.validator.addMethod("is_katakana", function(value, element) {
                if(this.optional(element)) return true; //未入力はcheckしない

                value = this_obj.conv_zenkaku_ascii_to_han(value);
                value = this_obj.conv_zenkaku_hira_to_kana(value);
                value = this_obj.conv_hankaku_kana_to_zen(value);
                $(element).val(value);
                
                //「カナ」に加え、半角英数字記号もOKとしています
                re_pat = '^(['+'ァ-ヶー'+'a-zA-Z0-9!-/:-@¥[-`{-~'+']+)$';
                var re = new RegExp(re_pat,'');
                return re.test(value);
            });
        },

        validate_all: function(){
            alert("result of validate_all:"+ $('#form1').valid() );
        },

        // refer to https://github.com/hokaccha/js-zip2address
        conv_zip2address: function(){
            var zipcode = $('input[name="zipcode"]').val().trim();
            zipcode = this.conv_zenkaku_ascii_to_han(zipcode);
            $('input[name="zipcode"]').val(zipcode);
            
            zip2address(zipcode, function(address) {
                if (! address) {
                    return null;
                }

                // google日本語入力API が、区市町村+町 で返す為、parse
                var address_city = address.city.match(/^.+?[区市町村]/);
                var address_pref_city = address.pref+address_city;
                var address_other = address.all;
                address_other = address_other.replace(address_pref_city, '');
                
                $('input[name="address_pref"]').val(address.pref);
                $('input[name="address_city"]').val(address_city);
                $('input[name="address_other"]').val(address_other);
            });
        },

        // 全角英数字記号->半角
        conv_zenkaku_ascii_to_han: function(org_str){
            var half_str =
                org_str.replace(
                    /[!-~]/g,
                    function( tmp_str ) {
                        return String.fromCharCode(tmp_str.charCodeAt(0) - 0xFEE0);
                    }
                );
            // 上記のcode shiftで変換NG文字の変換
            return half_str.replace(/”/g, "\"")
                .replace(/’/g, "'")
                .replace(/‘/g, "`")
                .replace(/¥/g, "\\")
                .replace(/ /g, " ")
                .replace(/〜/g, "~");
            return half_str;
        },
        // 全角ひらがな->カナ
        conv_zenkaku_hira_to_kana: function(org_str){
            
            new_str = org_str.replace(/[\u3041-\u3096]/g, function(match) {
                var chr = match.charCodeAt(0) + 0x60;
                return String.fromCharCode(chr);
            });
            return new_str;
        },
        
        // 半角カナ->全角
        conv_hankaku_kana_to_zen: function(org_str){
            var kana_map ={
                // 濁音や半濁音は先に定義
                'ガ': 'ガ', 'ギ': 'ギ', 'グ': 'グ', 'ゲ': 'ゲ', 'ゴ': 'ゴ',
                'ザ': 'ザ', 'ジ': 'ジ', 'ズ': 'ズ', 'ゼ': 'ゼ', 'ゾ': 'ゾ',
                'ダ': 'ダ', 'ヂ': 'ヂ', 'ヅ': 'ヅ', 'デ': 'デ', 'ド': 'ド',
                'バ': 'バ', 'ビ': 'ビ', 'ブ': 'ブ', 'ベ': 'ベ', 'ボ': 'ボ',
                'パ': 'パ', 'ピ': 'ピ', 'プ': 'プ', 'ペ': 'ペ', 'ポ': 'ポ',
                'ヴ': 'ヴ', 'ヷ': 'ヷ', 'ヺ': 'ヺ',
                'ア': 'ア', 'イ': 'イ', 'ウ': 'ウ', 'エ': 'エ', 'オ': 'オ',
                'カ': 'カ', 'キ': 'キ', 'ク': 'ク', 'ケ': 'ケ', 'コ': 'コ',
                'サ': 'サ', 'シ': 'シ', 'ス': 'ス', 'セ': 'セ', 'ソ': 'ソ',
                'タ': 'タ', 'チ': 'チ', 'ツ': 'ツ', 'テ': 'テ', 'ト': 'ト',
                'ナ': 'ナ', 'ニ': 'ニ', 'ヌ': 'ヌ', 'ネ': 'ネ', 'ノ': 'ノ',
                'ハ': 'ハ', 'ヒ': 'ヒ', 'フ': 'フ', 'ヘ': 'ヘ', 'ホ': 'ホ',
                'マ': 'マ', 'ミ': 'ミ', 'ム': 'ム', 'メ': 'メ', 'モ': 'モ',
                'ヤ': 'ヤ', 'ユ': 'ユ', 'ヨ': 'ヨ',
                'ラ': 'ラ', 'リ': 'リ', 'ル': 'ル', 'レ': 'レ', 'ロ': 'ロ',
                'ワ': 'ワ', 'ヲ': 'ヲ', 'ン': 'ン',
                'ァ': 'ァ', 'ィ': 'ィ', 'ゥ': 'ゥ', 'ェ': 'ェ', 'ォ': 'ォ',
                'ッ': 'ッ', 'ャ': 'ャ', 'ュ': 'ュ', 'ョ': 'ョ',
                '。': '。', '、': '、', 'ー': 'ー', '「': '「', '」': '」', '・': '・'};

            var re = new RegExp('('+Object.keys(kana_map).join('|')+')','g');
            return org_str.replace(re, function (match) {
                return kana_map[match];
            }).replace(/゙/g, '゛').replace(/゚/g, '゜');
        }
    };

    window.myform = new MyForm();
    
})();