Форма / Forms (с параметрами) для Drupal

Особенности

  1. Основан на библиотеке "jQuery.validator"
  2. Маска телефона.
  3. Маска почты.
  4. Сравнение заполнения 2х полей.
  5. Запрет ввода букв в поле с телефоном.
  6. Лейбл у селектов.
  7. focus и клик по лейблу.
  8. Переименование сообщений об ошибках.
JS
Как юзать
      new Webform({
    formClass: '.webform-submission-send-request-form',
    validator: {
        rules: {
            phone: {
                required: true,
            },
            email: {
                required: true,
            },
            comment: {
                required: true,
            },
        },
        messages: {}, // переопределение сообщений об ошибках
        condition: ['email', 'comment'], // для сравнения указать name из input
    },
});
    
Код
      window.Webform = function(settings) {
    let FORM_CLASS = settings.formClass;
    let FORM = document.querySelector(FORM_CLASS);
    let condition = false;

    this.init = function() {
        this.validatorDefault();
        this.handler();
        this.validator();
        this.submit();
        this.addMaskOnField();
        this.disableLettersInFieldWithPhone();
    }
    this.validatorDefault = function() {
        jQuery.validator.setDefaults({
            debug: false,
            errorElement: "div",
            errorPlacement: function(error, element) {
                error.appendTo( element.parent() );
            },
            rules: {
                email: {
                    email: true,
                    pattern: /^[a-zA-Z0-9\._-]+@[a-zA-Z0-9-]+\.[a-z]{2,6}$/i,
                },
                phone: {
                    // required: false,
                    pattern: /^((8|\+374|\+994|\+995|\+375|\+7|\+380|\+38|\+996|\+998|\+993)[\- ]?)?\(?\d{3,5}\)?[\- ]?\d{1}[\- ]?\d{1}[\- ]?\d{1}[\- ]?\d{1}[\- ]?\d{1}(([\- ]?\d{1})?[\- ]?\d{1})?$/i,
                },
            },
            messages: {
                email: {
                    email: "Пожалуйста, введите корректный адрес электронной почты",
                    pattern: "Пожалуйста, введите корректный адрес электронной почты",
                },
                phone: {
                    pattern: "Неверный номер",
                },
            },
        });
    }
    this.validator = function() {
        // set required label
        Object.entries(settings.validator.rules).forEach(item => {
            if (item[1].required) {
                if (FORM.querySelector(`[name="${item[0]}"]`)) {
                    FORM.querySelector(`[name="${item[0]}"]`).closest('.form-item').querySelector('label').textContent += '*'
                }
            }
        });

        // validate
        jQuery(FORM).validate({
            rules: settings.validator.rules,
            messages: settings.validator.messages,
        });
    }
    this.handler = function() {
        jQuery(FORM).find(".form-item").each(function () {
            jQuery(this).find("input, textarea").on("input", function (e) {
                jQuery(FORM).validate().element(e.currentTarget);
            });
            // jQuery(this).find("input").on("keypress", function (e) {
            //     jQuery(FORM).validate().element(e.currentTarget);
            // });
            // jQuery(this).find("textarea").on("keypress", function (e) {
            //     jQuery(FORM).validate().element(e.currentTarget);
            // });
        });
    }
    this.submit = function() {
        let _self = this;
        if (typeof Drupal !== "undefined" && typeof Drupal.Ajax !== "undefined" && typeof Drupal.Ajax.prototype.beforeSubmitCVOriginal === "undefined") {
            Drupal.Ajax.prototype.beforeSubmitCVOriginal = Drupal.Ajax.prototype.beforeSubmit;
            Drupal.Ajax.prototype.beforeSubmit = function (form_values, element_settings, options) {
                if (options.data._triggering_element_name === "op") {
                    if (typeof this.$form !== "undefined") {
                        _self.condition(this.$form);
                        if (this.$form.valid() && condition) {
                            // console.log("ФОРМА ВАЛИДНА");
                        } else {
                            // console.log("ФОРМА НЕ ВАЛИДНА");
                            this.ajaxing = false;
                            return false;
                        }
                    }
                }
                return this.beforeSubmitCVOriginal(form_values, element_settings, options);
            };
        }
    }
    this.addError = function(field, name) {
        // console.group(name);

        // поле загрузки файла
        if (field.closest('.form-managed-file')) {
            if (field.closest('.form-managed-file').querySelector('.sfi-wrapper')) {
                field.classList.add('error');
                if (!field.closest('.form-managed-file').querySelector('.form-item--error-message')) {
                    field.closest('.form-managed-file').querySelector('.sfi-wrapper').insertAdjacentHTML('afterend', `
${settings.validator.messages[name].required}
`);
                }
            }
        } else {
            // console.log(field);
            jQuery(field).rules("add", {
                required: true,
            });
        }
        // end

        // console.groupEnd();
    }
    this.removeError = function(field, name) {
        // console.group(name);
        if (field.closest('.form-item').querySelector('div.form-item--error-message, div.error')) {
            field.closest('.form-item').querySelector('div.form-item--error-message, div.error').remove();
        }
        // console.groupEnd();
    }
    this.condition = function(form) {
        // console.clear();
        // console.log(form)
        // console.log('заполнено? (до)', condition);
        if (settings.validator.condition) {
            // console.group(settings.formClass);
            // console.log(settings.formClass)
            // console.log(settings.validator.condition)
            let name1 = settings.validator.condition[0];
            let name2 = settings.validator.condition[1];

            // FORM = jQuery(form);
            // console.log(FORM)
            // console.log(form)
            // console.log(FORM[0].querySelector(`[name="${name1}"`))
            // console.log(FORM[0].querySelector(`[name="${name2}"`))

            const field1 = form[0].querySelector(`[name="${name1}"`);
            const field2 = form[0].querySelector(`[name="${name2}"`);

            // console.log('field1', field1);
            // console.log('field2', field2);
            // console.log('field1.value', field1.value);
            // console.log('field2.value', field2.value);

            if (field1 && field2) {
                if (field1.value !== '' || field2.value !== '') {
                    // console.log("Условие успешно выполнено");
                    condition = true;
                    field1 ? this.removeError(field1, name1) : null;
                    field2 ? this.removeError(field2, name2) : null;
                } else {
                    // console.log("Условие не выполнено");
                    condition = false;
                    field1 ? this.addError(field1, name1) : null;
                    field2 ? this.addError(field2, name2) : null;
                }
            }
            // console.groupEnd();
        }
        // console.log('заполнено? (после)', condition);
    }
    this.addMaskOnField = function() {
        jQuery('input[name="phone"]').once().inputmask({
            alias: "+7##########",
            "placeholder": "_",
            clearMaskOnLostFocus: true,
            showMaskOnHover: false,
            showMaskOnFocus: true
        });
        jQuery('input[name="email"]').once().inputmask({
            alias: "email",
            "placeholder": "_",
            clearMaskOnLostFocus: true,
            showMaskOnHover: false,
            showMaskOnFocus: true
        });
    }
    this.disableLettersInFieldWithPhone = function() {
        jQuery("[type='tel'], [name='phone']").keypress(function (event) {
            var key, keyChar;
            if (!event) var event = window.event;
            if (event.keyCode) key = event.keyCode;
            else if (event.which) key = event.which;
            // если нажата одна из следующих клавиш: скобки, плюс, минус, пробел, enter, tab, backspace, del, стрекла влево, стрелка вправо
            // тогда на этом завершаем работу функции, т..к эти клавиши нужны для нормальной работы с полями форм
            if (key == null || key == 40 || key == 41 || key == 43 || key == 45 || key == 32 || key == 0 || key == 8 || key == 13 || key == 37 || key == 39 || key == 46 || key == 9) return true;
            keyChar = String.fromCharCode(key);
            // d - это зарезервированное сокращение в регулярных выражениях, означает любая цифра
            if (!/\d/.test(keyChar)) return false;
        });
    }

    if (FORM) {
        if (!FORM.classList.contains('js-webform')) {
            FORM.classList.add('js-webform');
            this.init();
        }
    }
}

if (typeof Drupal !== "undefined") {
    Drupal.behaviors.customDrupalWebform = {
        attach: function (context, settings) {
            init();
        }
    };
} else {
    init();
}

function init() {

    jQuery('select').each(function () {
        const select = jQuery(this);
        select.select2({
            width: '100%'
        });
        select.on('select2:open', function (e) {
            // console.log('select2:open');
            e.currentTarget.closest('.form-item').querySelector('label').classList.add('focus');
            e.currentTarget.nextSibling.classList.add('js-select2-open');
        });
        select.on('select2:close', function (e) {
            // console.log('select2:close');
            e.currentTarget.closest('.form-item').querySelector('label').classList.remove('focus');
            e.currentTarget.nextSibling.classList.remove('js-select2-open');
        });
        select.on('select2:select', function (e) {
            // console.log('select2:select');
            e.currentTarget.closest('.form-item').querySelector('label').classList.add('focused');
            e.currentTarget.nextSibling.classList.add('js-select2-selected');
        });
    });

    const input = jQuery(".form-item textarea, input[type='text'], input[type='email'], input[type='tel'], input[name='phone'], input[name='password'], input[name='pass'], input[name='email'], input[name='number'], input[name='name']");
    input.each(function () {
        if (jQuery(this).val() !== "") {
            jQuery(this).parents(".form-item").find("label").addClass("focused");
        }
        if (jQuery(this).hasClass("error")) {
            jQuery(this).parents(".form-item").find("label").addClass("error");
        }
    });
    input.on("focus", function() {
        jQuery(this).parents(".form-item").find("label").addClass("focus");
    });
    input.on("blur", function () {
        let thisInput = jQuery(this);
        thisInput.parents(".form-item").find("label").removeClass("focused").removeClass("focus");
        if (thisInput.val() !== "") {
            thisInput.parents(".form-item").find("label").addClass("focused");
        }
        setTimeout(function () {
            // console.log(thisInput.hasClass("error"));
            if (thisInput.hasClass("error")) {
                thisInput.parents(".form-item").find("label").addClass("error");
            }
        }, 100);
    });

    // КЛИК ПО ЛЕЙБЛУ
    jQuery("label").on('click', function() {
        // если тип поля "селект"
        if (jQuery(this).parents(".form-item").hasClass("js-form-type-select")) {
            jQuery(this).removeClass("focus").removeClass("focused");
            jQuery(this).parents(".form-item").find('select').select2('open');
        }

        // другие типы полей
        if (!jQuery(this).parents(".form-item").hasClass("js-form-type-checkbox") && !jQuery(this).parents(".form-item").hasClass("js-form-type-radio")) {
            jQuery(this).addClass("focus");
            jQuery(this).next().focus();
        }
    });
}