PageSourceSearch

https://www.teach4taiwan.org/wp-content/themes/clean-journal/js/form-verification.js

js teach4taiwan.org collected 2026-10-03 22:49:22 UTC 22,714 bytes, 629 lines download raw bytes

1$ = jQuery;
2
3/*
4 * 在input後插入錯誤提示文字
5 *
6 *  @param text {string} 為錯誤提示文字
7 *  @param name {bool} 是否為姓名類型輸入(兩欄式)
8 *  @return 錯誤提示文字div
9 */
10function error_prompt(text, name) {
11  var error_div = '';
12  if (name) {
13    error_div += '<div class="error-prompt hide">';
14    error_div += warning_img_area;
15    error_div += '<div>' + text + '</div></div>';
16    return error_div;
17  }
18
19  error_div += '<div class="outOfPanelContent">';
20  error_div += '<div class="error-prompt hide">';
21  error_div += warning_img_area;
22  error_div += '<div>' + text + '</div></div></div>';
23  return error_div;
24}
25
26/*
27 * 一般單欄式的檢核錯誤模板
28 *
29 *  @param input_verification {object} 檢核物件
30 *  @paran $form {object} jQuery選取表單物件
31 *  @return no_error {bool}  是否沒有錯誤,無錯誤回傳1,有回傳0
32 */
33function generalErrorTemplate(input_verification, $form) {
34  var $input;
35  if (!input_verification.isSelect) {
36    $input = $form.find('.' + input_verification.input_name + ' > input:visible');
37  } else {
38    $input = $form.find('.' + input_verification.input_name + ' > select:visible');
39  }
40  if ($input.length == 0) {
41    return 1
42  }
43  var $input_val = $input.val() ? $input.val() : "";
44  var format_error = false;
45  /* determine whether input has format error */
46  if (input_verification.input_format_func && $input_val.length != 0) {
47    format_error = input_verification.input_format_func($input_val);
48  }
49  /* generate error prompt */
50  var error_div = format_error ? error_prompt(input_verification.input_err_format, false) : error_prompt(input_verification.input_err_general, false);
51  if (!$input.parent().next().find('.error-prompt').length) {
52    $input.parent().after(error_div);
53  } else {
54    var error_text = format_error ? input_verification.input_err_format : input_verification.input_err_general;
55    $input.parent().next().find('.error-prompt > div').text(error_text);
56  }
57  var $errro_div = $input.parent().next().find('.error-prompt');
58  /* no error*/
59  if (!format_error && $input_val.length != 0) {
60    $errro_div.addClass('hide');
61    return true;
62  }
63  /* has error */
64  else {
65    $errro_div.removeClass('hide');
66    console.log('valid fail:', input_verification.input_name, 'format-error', format_error);
67    return false;
68  }
69}
70
71/*
72 * 性別檢核錯誤模板
73 *
74 *  @param input_verification {object} 檢核物件
75 *  @paran $form {object} jQuery選取表單物件
76 *  @return no_error {bool}  是否沒有錯誤,無錯誤回傳1,有回傳0
77 */
78function genderErrorTemplate(input_verification, $form) {
79  var $inputs;
80  if (!input_verification.isSelect) {
81    $inputs = $form.find('.' + input_verification.input_name + ' > input:visible');
82  } else {
83    $inputs = $form.find('.' + input_verification.input_name + ' > select:visible');
84  }
85  if ($inputs.length == 0) {
86    return 1
87  }
88  var isChecked = false;
89  for (var i = 0; i < $inputs.length; ++i) {
90    if ($inputs.eq(i).is(':checked')) {
91      isChecked = true;
92    }
93  }
94  var $error_prompt = $inputs.parent().parent().find('.error-prompt');
95  if ($error_prompt.length) {
96    var err_seperator_text = ($error_prompt.find('div').text().match('輸入') || $error_prompt.find('div').text().match('格式'))? '/': '';
97    var err_text = $error_prompt.find('div').text() + err_seperator_text + input_verification.input_err_general;
98    if (!isChecked) {
99      $error_prompt.find('div').text(err_text);
100    }
101  } else {
102    var error_div = error_prompt(input_verification.input_err_general, name = true);
103    if (!isChecked) {
104      $inputs.parent().parent().append(error_div);
105    }
106  }
107  var $errro_div = $inputs.parent().parent().find('.error-prompt');
108  /* no error */
109  if (isChecked) {
110    if (!$errro_div.hasClass('hasError')) {
111      $errro_div.addClass('hide');
112    }
113    return true;
114  } else { /* has error */
115    $errro_div.removeClass('hasError')
116    $errro_div.removeClass('hide');
117    console.log('valid fail: ', input_verification.input_name);
118    return false;
119  }
120}
121
122/*
123 * 雙欄式錯誤模板
124 *
125 *  @param input_verification {object} 檢核物件
126 *  @paran $form {object} jQuery選取表單物件
127 *  @return no_error {bool}  是否沒有錯誤,無錯誤回傳1,有回傳0
128 */
129function dualInputErrorTemplate(input_verification, $form, isSelect) {
130  var $inputs = [];
131  var $input_vals = [];
132  var format_errors = [];
133  var has_errors = [];
134
135  for (var i = 0; i < input_verification.inputs.length; ++i) {
136    var $input;
137    if (!isSelect) {
138      $input = $form.find('.' + input_verification.inputs[i].input_name + ' > input:visible');
139    } else {
140      $input = $form.find('.' + input_verification.inputs[i].input_name + ' > select:visible');
141    }
142    if ($input.length == 0) {
143      return 1
144    }
145    $inputs.push($input);
146    if (!isSelect) {
147      var $input_val = $input.val();
148      var format_error = false;
149      $input_vals.push($input_val);
150      if (input_verification.inputs[i].input_format_func && $input_val.length != 0) {
151        format_error = input_verification.inputs[i].input_format_func($input_val);
152        format_errors.push(format_error);
153      }
154      has_errors.push((format_error || $input_val.length == 0));
155    } else {
156      has_errors.push($input.find('option:selected').index() == 0);
157    }
158  }
159  /* both input has error */
160  var error_div;
161  var error_text = '';
162  if (has_errors[0] && has_errors[1]) {
163    error_div = error_prompt(input_verification.inputs_err_general, name = !isSelect);
164    error_text = input_verification.inputs_err_general;
165  } else { /* only one input has error */
166    for (var i = 0; i < input_verification.inputs.length; ++i) {
167      if (has_errors[i]) {
168        error_text = format_errors[i] ? input_verification.inputs[i].input_err_format : input_verification.inputs[i].input_err_general;
169        error_div = error_prompt(error_text, name = !isSelect);
170        // error_text = input_verification.inputs[i].input_err_general;
171      }
172    }
173  }
174
175  /* generate error prompt */
176  var $input = $inputs[$inputs.length - 1];
177  var $errro_div;
178  var $input_parent = $input.parent().parent();
179  if (isSelect) {
180    /* doesnt exist error prompt, append it*/
181    if (!$input_parent.next().find('.error-prompt').length) {
182      $input_parent.after(error_div);
183    } else { /* exist error prompt, change text*/
184      $input_parent.next().find('.error-prompt > div').text(error_text);
185    }
186    $errro_div = $input_parent.next().find('.error-prompt');
187  } else {
188    /* doesnt exist error prompt, append it*/
189    if (!$input_parent.next().find('.error-prompt').length) {
190      $input_parent.next().append(error_div);
191    } else { /* exist error prompt, change text*/
192      $input_parent.next().find('.error-prompt > div').text(error_text);
193    }
194    $errro_div = $input_parent.next().find('.error-prompt');
195  }
196
197  /* no error*/
198  if (!(has_errors[0] || has_errors[1])) {
199    $errro_div.addClass('hide');
200    $errro_div.removeClass('hasError');
201    return true;
202  } else { /* has error */
203    $errro_div.removeClass('hide');
204    $errro_div.addClass('hasError');
205    console.log('valid fail: ', input_verification.inputs_err_general, 'format-error', format_error);
206    return false;
207  }
208}
209
210/*
211 * 密碼類型錯誤模板
212 *
213 *  @param input_verification {object} 檢核物件
214 *  @paran $form {object} jQuery選取表單物件
215 *  @return no_error {bool}  是否沒有錯誤,無錯誤回傳1,有回傳0
216 */
217function confirmPasswordTemplate(input_verification, $form) {
218  var $pwdConfirm = $form.find('.' + input_verification.input_name + ' > input:visible');
219  if ($pwdConfirm.length) {
220    var error_div;
221    var format_error = false;
222    if ($pwdConfirm.val().length == 0) {
223      error_div = error_prompt(input_verification.input_err_general, false);
224    } else {
225      var newPwd = $form.find('.valid-new-pwd > input').val();
226      if ($pwdConfirm.val() != newPwd) {
227        error_div = error_prompt(input_verification.input_err_format, false);
228        format_error = true;
229      }
230    }
231    if (!$pwdConfirm.parent().next().find('.error-prompt').length) {
232      $pwdConfirm.parent().after(error_div);
233    } else {
234      var error_text = format_error ? input_verification.input_err_format : input_verification.input_err_general;
235      $pwdConfirm.parent().next().find('.error-prompt > div').text(error_text);
236    }
237    var $errro_div = $pwdConfirm.parent().next().find('.error-prompt');
238    /* no error*/
239    if (!format_error && $pwdConfirm.val().length != 0) {
240      $errro_div.addClass('hide');
241      return true;
242    } else { /* has error */
243      console.log(input_verification, 'error');
244      $errro_div.removeClass('hide');
245      return false;
246    }
247  } else {
248    return true;
249  }
250}
251
252/*
253 * 檢核函數
254 *
255 *  @param className {string} 欲檢核之表單class或Id
256 *  @paran callback {function} callback函數
257 *  @return noError {bool}  是否沒有錯誤,無錯誤回傳1,有回傳0
258 */
259function verifyFrom(className, callback) {
260  /*
261  * 檢核項目格式
262  *
263  *  isSelect {bool} 是否為select
264  *  input_name {string}檢核欄位parent的class
265  *  input_err_general {string} 一般未填值時的錯誤文字
266  *  input_err_format {string} 格式錯誤時的錯誤文字
267  *  input_format_func {function} 格式錯誤檢查函數,有錯誤回傳1,無則0
268  *  verification_callback {function} 選擇呼叫的檢核錯誤模板function
269  *
270  */
271  $(className).each(function () {
272    $(this).submit(function (e) {
273      /* 一般的單欄檢核項目 */
274      var input_verification = [
275        {
276          isSelect: false,
277          input_name: 'valid-uid-individual',
278          input_err_general: '請輸入身份證字號',
279          input_err_format: '身分證字號(或居留證)格式錯誤',
280          input_format_func: function(uid){
281            var reg = /^(([A-Za-z]{1}[1-2]{1}[0-9]{8})|([0-9]{8})|([A-Za-z]{1}[A-Da-d]{1}[0-9]{8}))$/;
282            return !reg.test(uid);
283          },
284          verification_callback: generalErrorTemplate
285        },
286        {
287          isSelect: false,
288          input_name: 'valid-uid-group',
289          input_err_general: '請輸入企業統一編號',
290          input_err_format: '企業編號格式錯誤',
291          input_format_func: function (uid) {
292            var reg = /^[0-9]{8}$/;
293            return !reg.test(uid)
294          },
295          verification_callback: generalErrorTemplate
296        },
297        {
298          isSelect: false,
299          input_name: 'valid-group-title',
300          input_err_general: '請輸入單位名稱',
301          input_err_format: '',
302          input_format_func: null,
303          verification_callback: generalErrorTemplate
304        },
305        {
306          isSelect: false,
307          input_name: 'valid-birthday',
308          input_err_general: '請輸入日期',
309          input_err_format: '日期格式錯誤',
310          input_format_func: function (date) {
311            var regex = /^[0-9]{4}[-\/]?[0-9]{1,2}[-\/]?[0-9]{1,2}$/;
312            return (!regex.test(date))
313          },
314          verification_callback: generalErrorTemplate
315        },
316        {
317          isSelect: false,
318          input_name: 'valid-email',
319          input_err_general: '請輸入電子信箱',
320          input_err_format: '電子信箱格式錯誤',
321          input_format_func: function (email) {
322            return !/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(email)
323          },
324          verification_callback: generalErrorTemplate
325        },
326        {
327          isSelect: false,
328          input_name: 'valid-phone',
329          input_err_general: '請輸入聯絡電話',
330          input_err_format: '聯絡電話格式錯誤',
331          input_format_func: function (phone) {
332            var reg = /^[0-9-#]{6,14}$/;
333            return !reg.test(phone)
334          },
335          verification_callback: generalErrorTemplate
336        },
337        {
338          isSelect: false,
339          input_name: 'valid-amount',
340          input_err_general: '請輸入數字',
341          input_err_format: '金額請大於100',
342          input_format_func: function (amount) {
343            amount = amount.replace(/\$/gi, "");
344            amount = amount.replace(/\,/gi, "");
345            amount = amount.replace(/\ /gi, "");
346            var num_reg = /^[0-9]*$/;
347            if (!num_reg.test(amount)) {
348              return true;
349            } else {
350              amount = parseInt(amount);
351              return amount < 100;
352            }
353          },
354          verification_callback: generalErrorTemplate
355        },
356        {
357          isSelect: true,
358          input_name: 'valid-order-type',
359          input_err_general: '請選擇捐款方式',
360          input_err_format: '',
361          input_format_func: null,
362          verification_callback: generalErrorTemplate
363        },
364        {
365          isSelect: false,
366          input_name: 'valid-old-pwd',
367          input_err_general: '請選輸入舊密碼',
368          input_err_format: '',
369          input_format_func: null,
370          verification_callback: generalErrorTemplate
371        },
372        {
373          isSelect: false,
374          input_name: 'valid-old-pwd',
375          input_err_general: '請選輸入舊密碼',
376          input_err_format: '',
377          input_format_func: null,
378          verification_callback: generalErrorTemplate
379        },
380        {
381          isSelect: false,
382          input_name: 'valid-new-pwd',
383          input_err_general: '請選輸入新密碼',
384          input_err_format: '請設定含英數八位數以上密碼',
385          input_format_func: function(pwd){
386            var regex = /^[A-Za-z0-9._%+-]{8,32}$/;
387            return !(regex.test(pwd));
388          },
389          verification_callback: generalErrorTemplate
390        },
391        {
392          isSelect: false,
393          input_name: 'valid-gender',
394          input_err_general: '請選擇性別',
395          input_err_format: '',
396          input_format_func: null,
397          verification_callback: genderErrorTemplate
398        },
399        {
400          isSelect: false,
401          input_name: 'valid-display-name',
402          input_err_general: '請選擇顯示名稱',
403          input_err_format: '',
404          input_format_func: null,
405          verification_callback: genderErrorTemplate
406        },
407        {
408          isSelect: false,
409          input_name: 'valid-credit-card-No',
410          input_err_general: '請輸入信用卡號',
411          input_err_format: '信用卡號格式錯誤',
412          input_format_func: function (num) {
413            var reg = /^[0-9]{16}$/;
414            return !reg.test(num);
415          },
416          verification_callback: generalErrorTemplate
417        },
418        {
419          isSelect: false,
420          input_name: 'valid-name',
421          input_err_general: '請輸入姓名',
422          input_err_format: '名字格式錯誤',
423          input_format_func: function (name) {
424            return (!/[\u4e00-\u9fa5_a-zA-Z-]/.test(name) || !/^([^0-9]*)$/.test(name));
425          },
426          verification_callback: generalErrorTemplate
427        },
428        {
429          isSelect: false,
430          input_name: 'valid-credit-card-expire',
431          input_err_general: '請輸入有效月份年份',
432          input_err_format: '有效月份年份格式錯誤',
433          input_format_func: function (s) {
434            var cy = (new Date).getFullYear();
435            var cm = (new Date).getMonth()+1;
436            var ey = Number('20' + s.substring(2,4));
437            var em = Number(s.substring(0,2));
438
439            if (cy > ey) {
440              return true;
441            } else if ((cy == ey) && (cm > em)) {
442              return true;
443            } else {
444              var regex = /^(0[1-9]|1[0-2])[0-9][0-9]$/;
445              return (!regex.test(s))
446            }
447          },
448          verification_callback: generalErrorTemplate
449        }
450      ];
451
452      /* 一般的雙欄式的檢核項目 */
453      var dual_input_verification = [
454        {
455          isSelect: false,
456          inputs: [
457            {
458              input_name: 'valid-last-name',
459              input_err_general: '請輸入姓氏',
460              input_err_format: '姓氏格式錯誤',
461              input_format_func: function (name) {
462                return (!/[\u4e00-\u9fa5_a-zA-Z-]/.test(name) || !/^([^0-9]*)$/.test(name));
463              },
464            },
465            {
466              input_name: 'valid-first-name',
467              input_err_general: '請輸入名字',
468              input_err_format: '名字格式錯誤',
469              input_format_func: function (name) {
470                return (!/[\u4e00-\u9fa5_a-zA-Z-]/.test(name) || !/^([^0-9]*)$/.test(name));
471              },
472            },
473          ],
474          inputs_err_general: '請輸入姓氏和名字',
475          verification_callback: dualInputErrorTemplate
476        },
477      ];
478
479      /* 密碼的檢核項目 */
480      var pwd_confirm_verification = [{
481        isSelect: false,
482        input_name: 'valid-confirm-pwd',
483        input_err_general: '請選輸入確認密碼',
484        input_err_format: '確認密碼格式錯誤',
485        verification_callback: confirmPasswordTemplate
486      }];
487
488      /* 判斷收據地址必填與否邏輯,新增地址相關檢核 */
489      /* 寄送方式為:寄送單筆紙本收據、寄送年度紙本收據時,必填 */
490      var $invoice = $(this).find('.valid-invoice-type > select:visible');
491      if ($invoice.length) {
492        if ($invoice.val() == 'Single_paper' || $invoice.val() == 'Year_paper') {
493          input_verification.push({
494            input_name: 'valid-address',
495            input_err_general: '請輸入聯絡人完整地址',
496            input_err_format: '請輸入完整地址',
497            input_format_func: function (addr) {
498              return (addr.toString().length < 4)
499            },
500            verification_callback: generalErrorTemplate
501          });
502          input_verification.push({
503            isSelect: false,
504            input_name: 'valid-invoice-title',
505            input_err_general: '請輸入收據寄發抬頭',
506            input_err_format: '',
507            input_format_func: null,
508            verification_callback: generalErrorTemplate
509          });
510          dual_input_verification.push(
511            {
512              isSelect: true,
513              inputs: [
514                {
515                  input_name: 'valid-county',
516                  input_err_general: '請選擇聯絡人縣市',
517                  input_err_format: '',
518                  input_format_func: null
519                },
520                {
521                  input_name: 'valid-city',
522                  input_err_general: '請選擇聯絡人鄉鎮地區',
523                  input_err_format: '',
524                  input_format_func: null
525                }
526              ],
527              inputs_err_general: '請選擇聯絡人縣市和聯絡人鄉鎮地區',
528              verification_callback: dualInputErrorTemplate
529            }
530          );
531        } else if ($invoice.val() == 'Single_e' || $invoice.val() == 'Year_e') {
532          input_verification.push({
533            isSelect: false,
534            input_name: 'valid-invoice-contact-id',
535            input_err_general: '請輸入收據寄發統編/身分證字號',
536            input_err_format: '',
537            input_format_func: null,
538            verification_callback: generalErrorTemplate,
539          },
540          {
541            isSelect: false,
542            input_name: 'valid-invoice-title',
543            input_err_general: '請輸入收據寄發抬頭',
544            input_err_format: '',
545            input_format_func: null,
546            verification_callback: generalErrorTemplate
547          });
548        }
549      } else {
550        input_verification.push({
551          input_name: 'valid-address',
552          input_err_general: '請輸入聯絡人完整地址',
553          input_err_format: '請輸入聯絡人完整地址',
554          input_format_func: function (addr) {
555            return (addr.toString().length < 4)
556          },
557          verification_callback: generalErrorTemplate
558        });
559        dual_input_verification.push(
560          {
561            isSelect: true,
562            inputs: [
563              {
564                input_name: 'valid-county',
565                input_err_general: '請選擇聯絡人縣市',
566                input_err_format: '',
567                input_format_func: null
568              },
569              {
570                input_name: 'valid-city',
571                input_err_general: '請選擇聯絡人鄉鎮地區',
572                input_err_format: '',
573                input_format_func: null
574              }
575            ],
576            inputs_err_general: '請選擇聯絡人縣市和聯絡人鄉鎮地區',
577            verification_callback: dualInputErrorTemplate
578          }
579        );
580      }
581      /* hide error prompt */
582      $(this).find('.error-prompt').addClass('hide');
583      /* 檢核是否正確回傳值 */
584      var noError = true;
585
586      /* 兩欄式輸入確認檢核 */
587      for (var i = 0; i < dual_input_verification.length; ++i) {
588        noError = noError & dual_input_verification[i].verification_callback(dual_input_verification[i], $(this), dual_input_verification[i].isSelect);
589      }
590      /* 單欄式輸入確認檢核 */
591      for (var i = 0; i < input_verification.length; ++i) {
592        noError = noError & input_verification[i].verification_callback(input_verification[i], $(this));
593      }
594      /* 新密碼確認檢核 */
595      for (var i = 0; i < pwd_confirm_verification.length; ++i) {
596        noError = noError & pwd_confirm_verification[i].verification_callback(pwd_confirm_verification[i], $(this));
597      }
598      console.log($(this), noError);
599      if (callback) {
600        callback(noError);
601      } else {
602        if (!noError) {
603          e.preventDefault();
604          if ($('.error-submit-prompt').length) {
605            $(this).find('.error-submit-prompt').removeClass('hide');
606          } else {
607            $('.edit_area_button .submit-btn').parent().after(plzfill_img_area);
608          }
609          return false;
610        } else {
611          if ($('.error-submit-prompt').length) {
612            $(this).find('.error-submit-prompt').addClass('hide');
613          }
614          return true;
615        }
616      }
617      return false;
618    })
619  });
620}
621
622var warning_img_area;
623var plzfill_img_area;
624$(document).ready(function () {
625  warning_img_area = '<img class="small-icon-img" src="' + SITE_ROOT + '/wp-content/uploads/2018/06/32_32alert.png"/>';
626  plzfill_img_area = '<div class="center-row ml250px mt10px error-submit-prompt"><div class="font16px"><img class="small-icon-img" src="' + SITE_ROOT + '/wp-content/uploads/2018/06/32_32alert.png"> 請輸入必填欄位</div></div>';
627
628  verifyFrom('.verification-form', null);
629});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.