1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

フォームのバリデーションのバリエーション

Last updated at Posted at 2025-07-12

wordpressのContact Form 7用jQueryバリデーションコード例です。

基本的なバリデーション

  • 必須項目チェック
  • メールアドレス形式チェック
  • 文字数制限チェック
  • 電話番号・郵便番号形式チェック

リアルタイムバリデーション

  • 入力時即座チェック
  • パスワード強度チェック
  • 日本語入力チェック

高度なバリデーション

  • 文字数カウント表示
  • 数値範囲チェック
  • 日付バリデーション
  • ファイルバリデーション

Contact Form 7 統合

  • CF7送信前バリデーション
  • CF7送信後処理
  • CF7エラーハンドリング
  • リアルタイムエラー表示クリア

CF7のイベントフック

Contact Form 7は以下のタイミングでイベントを発火

  • wpcf7beforesubmit: 送信前(バリデーション追加に最適)
  • wpcf7mailsent: 送信成功時(成功処理)
  • wpcf7mailfailed: 送信失敗時(エラー処理)
  • wpcf7invalid: バリデーションエラー時(エラー表示)
  • wpcf7spam: スパム検出時(スパム対処)

複合バリデーション

  • 複数フィールド相互チェック
  • 条件付きバリデーション
  • 動的フィールド追加時のバリデーション
  • 全フィールド一括バリデーション

ヘルパー関数

何度も使用される処理を関数として切り出したものです。

  • エラー・成功・警告メッセージ表示
  • バリデーション状態管理
  • 文字変換(全角半角、ひらがなカタカナ)
  • 入力制限(数値のみ、日本語のみ、英数字のみ)
<script>
// ===== 基本的なバリデーション =====

// 1. 必須項目チェック
$('input[name="your-name"]').on('blur', function() {
    if ($(this).val().trim() === '') {
        $(this).addClass('wpcf7-not-valid');
        showError($(this), '名前を入力してください');
    } else {
        $(this).removeClass('wpcf7-not-valid');
        hideError($(this));
    }
});

// 2. メールアドレス形式チェック
$('input[name="your-email"]').on('blur', function() {
    const email = $(this).val().trim();
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    
    if (!emailRegex.test(email)) {
        $(this).addClass('wpcf7-not-valid');
        showError($(this), '正しいメールアドレスを入力してください');
    } else {
        $(this).removeClass('wpcf7-not-valid');
        hideError($(this));
    }
});

// 3. 文字数制限チェック
$('input[name="your-name"]').on('input', function() {
    const value = $(this).val();
    const minLength = 2;
    const maxLength = 50;
    
    if (value.length < minLength) {
        showError($(this), `名前は${minLength}文字以上で入力してください`);
    } else if (value.length > maxLength) {
        showError($(this), `名前は${maxLength}文字以下で入力してください`);
    } else {
        hideError($(this));
    }
});

// 4. 電話番号形式チェック
$('input[name="your-tel"]').on('input', function() {
    const tel = $(this).val().replace(/[^\d-]/g, '');
    const telRegex = /^0\d{1,4}-\d{1,4}-\d{4}$/;
    
    if (tel && !telRegex.test(tel)) {
        showError($(this), '正しい電話番号を入力してください(例: 03-1234-5678)');
    } else {
        hideError($(this));
    }
});

// 5. 郵便番号チェック
$('input[name="your-zip"]').on('input', function() {
    const zip = $(this).val().replace(/[^\d-]/g, '');
    const zipRegex = /^\d{3}-\d{4}$/;
    
    if (zip && !zipRegex.test(zip)) {
        showError($(this), '郵便番号は123-4567の形式で入力してください');
    } else {
        hideError($(this));
    }
});

// ===== リアルタイムバリデーション =====

// 6. 入力時即座チェック
$('input[name="your-name"]').on('input', function() {
    const value = $(this).val().trim();
    
    if (value.length === 0) {
        clearValidation($(this));
    } else if (value.length < 2) {
        showError($(this), '名前は2文字以上で入力してください');
    } else if (!/^[ぁ-んァ-ヶー一-龠\s]+$/.test(value)) {
        showError($(this), '日本語で入力してください');
    } else {
        showSuccess($(this), '正しく入力されています');
    }
});

// 7. メールアドレスリアルタイム
$('input[name="your-email"]').on('input', function() {
    const email = $(this).val().trim();
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    
    if (email.length === 0) {
        clearValidation($(this));
    } else if (!emailRegex.test(email)) {
        showError($(this), '正しいメールアドレス形式ではありません');
    } else {
        showSuccess($(this), '正しいメールアドレスです');
    }
});

// 8. パスワード強度チェック
$('input[name="your-password"]').on('input', function() {
    const password = $(this).val();
    const strength = calculatePasswordStrength(password);
    
    if (password.length === 0) {
        clearValidation($(this));
    } else if (strength < 3) {
        showError($(this), 'パスワードが弱すぎます');
    } else if (strength < 5) {
        showWarning($(this), 'パスワードの強度は普通です');
    } else {
        showSuccess($(this), '強固なパスワードです');
    }
});

// ===== もうちょっと踏み込んだバリデーション =====

// 9. 文字数カウント表示
$('textarea[name="your-message"]').on('input', function() {
    const value = $(this).val();
    const maxLength = 500;
    const currentLength = value.length;
    
    // カウンター表示
    const counter = $(this).next('.char-counter');
    if (counter.length === 0) {
        $(this).after(`<div class="char-counter">${currentLength}/${maxLength}</div>`);
    } else {
        counter.text(`${currentLength}/${maxLength}`);
    }
    
    // 制限チェック
    if (currentLength > maxLength) {
        $(this).addClass('wpcf7-not-valid');
        showError($(this), `文字数が上限を超えています(${currentLength}/${maxLength})`);
    } else {
        $(this).removeClass('wpcf7-not-valid');
        hideError($(this));
    }
});

// 10. 数値範囲チェック
$('input[name="your-age"]').on('input', function() {
    const value = parseInt($(this).val());
    const min = 18;
    const max = 100;
    
    if (isNaN(value)) {
        showError($(this), '数値を入力してください');
    } else if (value < min || value > max) {
        showError($(this), `年齢は${min}歳から${max}歳の範囲で入力してください`);
    } else {
        showSuccess($(this), '正しい年齢です');
    }
});

// 11. 日付バリデーション
$('input[name="your-date"]').on('change', function() {
    const selectedDate = new Date($(this).val());
    const today = new Date();
    const minDate = new Date();
    minDate.setFullYear(today.getFullYear() - 1);
    
    if (selectedDate < minDate) {
        showError($(this), '1年以内の日付を選択してください');
    } else if (selectedDate > today) {
        showError($(this), '今日以前の日付を選択してください');
    } else {
        showSuccess($(this), '正しい日付です');
    }
});

// 12. ファイルバリデーション
$('input[name="your-file"]').on('change', function() {
    const file = this.files[0];
    const maxSize = 5 * 1024 * 1024; // 5MB
    const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];
    
    if (!file) {
        clearValidation($(this));
        return;
    }
    
    if (file.size > maxSize) {
        showError($(this), 'ファイルサイズは5MB以下にしてください');
    } else if (!allowedTypes.includes(file.type)) {
        showError($(this), '許可されていないファイル形式です');
    } else {
        showSuccess($(this), 'ファイルが正常に選択されました');
    }
});

// ===== Contact Form 7 統合 =====

// 13. CF7送信前バリデーション
document.addEventListener('wpcf7beforesubmit', function(event) {
    const form = event.target;
    let isValid = true;
    
    // カスタムバリデーション
    const nameField = form.querySelector('input[name="your-name"]');
    if (nameField && nameField.value.trim().length < 2) {
        nameField.classList.add('wpcf7-not-valid');
        isValid = false;
    }
    
    const emailField = form.querySelector('input[name="your-email"]');
    if (emailField && !validateEmail(emailField.value)) {
        emailField.classList.add('wpcf7-not-valid');
        isValid = false;
    }
    
    if (!isValid) {
        event.preventDefault();
    }
}, false);

// 14. CF7送信後処理
document.addEventListener('wpcf7mailsent', function(event) {
    // 送信成功時の処理
    const form = event.target;
    
    // フォームリセット
    form.reset();
    
    // 成功メッセージ表示
    showSuccessMessage('メールが正常に送信されました!');
    
    // Google Analytics イベント送信
    if (typeof gtag !== 'undefined') {
        gtag('event', 'form_submit', {
            'event_category': 'contact',
            'event_label': 'contact_form_7'
        });
    }
}, false);

// 15. CF7エラーハンドリング
document.addEventListener('wpcf7invalid', function(event) {
    const form = event.target;
    const invalidFields = form.querySelectorAll('.wpcf7-not-valid');
    
    // 最初のエラーフィールドにフォーカス
    if (invalidFields.length > 0) {
        invalidFields[0].focus();
        invalidFields[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
    
    // カスタムエラーメッセージ
    invalidFields.forEach(field => {
        addCustomErrorMessage(field);
    });
}, false);

// 16. リアルタイムエラー表示クリア
$('.wpcf7-form input, .wpcf7-form textarea, .wpcf7-form select').on('input change', function() {
    $(this).removeClass('wpcf7-not-valid');
    $(this).siblings('.wpcf7-not-valid-tip').remove();
});

// ===== 複合バリデーション =====

// 17. 複数フィールド相互チェック
$('input[name="your-email"], input[name="your-email-confirm"]').on('input', function() {
    const email = $('input[name="your-email"]').val();
    const emailConfirm = $('input[name="your-email-confirm"]').val();
    
    if (email && emailConfirm && email !== emailConfirm) {
        showError($('input[name="your-email-confirm"]'), 'メールアドレスが一致しません');
    } else {
        hideError($('input[name="your-email-confirm"]'));
    }
});

// 18. 条件付きバリデーション
$('select[name="your-inquiry-type"]').on('change', function() {
    const inquiryType = $(this).val();
    const companyField = $('input[name="your-company"]');
    
    if (inquiryType === 'business') {
        companyField.attr('required', true);
        companyField.closest('.form-group').addClass('required');
    } else {
        companyField.removeAttr('required');
        companyField.closest('.form-group').removeClass('required');
    }
});

// 19. 動的フィールド追加時のバリデーション
$('.add-field-btn').on('click', function() {
    const newField = $('<input type="text" name="dynamic-field[]" class="dynamic-field">');
    
    // 新しく追加されたフィールドにバリデーションを適用
    newField.on('input', function() {
        if ($(this).val().trim() === '') {
            showError($(this), 'この項目は必須です');
        } else {
            hideError($(this));
        }
    });
    
    $('.dynamic-fields-container').append(newField);
});

// 20. 全フィールド一括バリデーション
$('.wpcf7-form').on('submit', function(e) {
    let isValid = true;
    const form = $(this);
    
    // すべての必須フィールドをチェック
    form.find('[required]').each(function() {
        if ($(this).val().trim() === '') {
            $(this).addClass('wpcf7-not-valid');
            showError($(this), 'この項目は必須です');
            isValid = false;
        }
    });
    
    // メールアドレスフィールドをチェック
    form.find('input[type="email"]').each(function() {
        if ($(this).val() && !validateEmail($(this).val())) {
            $(this).addClass('wpcf7-not-valid');
            showError($(this), '正しいメールアドレスを入力してください');
            isValid = false;
        }
    });
    
    if (!isValid) {
        e.preventDefault();
    }
});

// ===== ヘルパー関数 =====

// エラーメッセージ表示
function showError(element, message) {
    element.addClass('wpcf7-not-valid');
    element.siblings('.error-message').remove();
    element.after(`<span class="error-message" style="color: red; font-size: 12px;">${message}</span>`);
}

// 成功メッセージ表示
function showSuccess(element, message) {
    element.removeClass('wpcf7-not-valid').addClass('valid');
    element.siblings('.success-message').remove();
    element.after(`<span class="success-message" style="color: green; font-size: 12px;">${message}</span>`);
}

// 警告メッセージ表示
function showWarning(element, message) {
    element.removeClass('wpcf7-not-valid').addClass('warning');
    element.siblings('.warning-message').remove();
    element.after(`<span class="warning-message" style="color: orange; font-size: 12px;">${message}</span>`);
}

// エラーメッセージ非表示
function hideError(element) {
    element.removeClass('wpcf7-not-valid');
    element.siblings('.error-message').remove();
}

// バリデーション状態クリア
function clearValidation(element) {
    element.removeClass('wpcf7-not-valid valid warning');
    element.siblings('.error-message, .success-message, .warning-message').remove();
}

// メールアドレス検証
function validateEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
}

// パスワード強度計算
function calculatePasswordStrength(password) {
    let strength = 0;
    
    if (password.length >= 8) strength++;
    if (password.length >= 12) strength++;
    if (/[a-z]/.test(password)) strength++;
    if (/[A-Z]/.test(password)) strength++;
    if (/[0-9]/.test(password)) strength++;
    if (/[^A-Za-z0-9]/.test(password)) strength++;
    
    return strength;
}

// 全角・半角変換
function toHalfWidth(str) {
    return str.replace(/[A-Za-z0-9]/g, function(s) {
        return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
    });
}

// ひらがな・カタカナ変換
function toKatakana(str) {
    return str.replace(/[ぁ-ゖ]/g, function(match) {
        const chr = match.charCodeAt(0) + 0x60;
        return String.fromCharCode(chr);
    });
}

// 数値のみ入力制限
function numbersOnly(element) {
    element.on('input', function() {
        this.value = this.value.replace(/[^0-9]/g, '');
    });
}

// 日本語のみ入力制限
function japaneseOnly(element) {
    element.on('input', function() {
        const value = this.value;
        const japaneseRegex = /^[ぁ-んァ-ヶー一-龠\s]*$/;
        
        if (!japaneseRegex.test(value)) {
            this.value = value.replace(/[^ぁ-んァ-ヶー一-龠\s]/g, '');
        }
    });
}

// 英数字のみ入力制限
function alphanumericOnly(element) {
    element.on('input', function() {
        this.value = this.value.replace(/[^a-zA-Z0-9]/g, '');
    });
}

// フォーム送信前の最終チェック
function finalValidation(form) {
    let isValid = true;
    const errors = [];
    
    // 必須項目チェック
    form.find('[required]').each(function() {
        if ($(this).val().trim() === '') {
            errors.push($(this).attr('name') + 'は必須項目です');
            isValid = false;
        }
    });
    
    // メールアドレスチェック
    form.find('input[type="email"]').each(function() {
        if ($(this).val() && !validateEmail($(this).val())) {
            errors.push('正しいメールアドレスを入力してください');
            isValid = false;
        }
    });
    
    if (!isValid) {
        alert('以下のエラーを修正してください:\n' + errors.join('\n'));
    }
    
    return isValid;
}

// 成功メッセージ表示
function showSuccessMessage(message) {
    const successDiv = $('<div class="success-notification">')
        .text(message)
        .css({
            position: 'fixed',
            top: '20px',
            right: '20px',
            background: '#4CAF50',
            color: 'white',
            padding: '15px',
            borderRadius: '5px',
            zIndex: 9999
        });
    
    $('body').append(successDiv);
    
    setTimeout(() => {
        successDiv.fadeOut(() => {
            successDiv.remove();
        });
    }, 3000);
}

// カスタムエラーメッセージ追加
function addCustomErrorMessage(field) {
    const fieldName = field.getAttribute('name');
    let customMessage = '';
    
    switch(fieldName) {
        case 'your-name':
            customMessage = 'お名前を正しく入力してください';
            break;
        case 'your-email':
            customMessage = 'メールアドレスの形式が正しくありません';
            break;
        case 'your-tel':
            customMessage = '電話番号を正しく入力してください';
            break;
        default:
            customMessage = 'この項目を正しく入力してください';
    }
    
    // 既存のエラーメッセージを削除
    $(field).siblings('.custom-error').remove();
    
    // カスタムエラーメッセージを追加
    $(field).after(`<span class="custom-error" style="color: red; font-size: 12px; display: block;">${customMessage}</span>`);
}
</script>
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?