Как сделать маску (шаблон) в input при вводе номера телефона для WooCommerce?

Дано: Интернет-магазин на WordPress+WooCommerce

Задача: На странице оформления заказа в поле для ввода номера телефона задать предустановленную схему номера в формате пригодному для русскоязычного сегмента

+7 xxx-xxx-xx-xx (или вариант через 8-ку)

Решение: Выполнять поставленную задачу мы будем на JavaScript, в первом случае — на базе библиотеки jQuery, которая поставляется с WordPress и доступна «из коробки» и во-втором — решение на нативном JS (то есть без зависимостей от сторонних библиотек, в частности jQuery)

Мне встретилось в интернете уже готовое решение, поэтому придерживаясь принципа: «Зачем писать то, что уже написано», я взял его за пример. Единственное, нужно проинспектировать нашу форму отправления заказа и выяснить идентификатор нашего «инпута» для указания номера телефона.

Давайте взглянем на форму при оформлении заказа в WooCommerce.

Если требуется добавить в поле подсказку какой формат ввода номера телефона мы ожидаем от пользователя, то поможет нам в этом специальный фильтр, который отвечает за возможность изменения информации в полях. В документации есть подходящий для решения нашей под-задачи пример

// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );

// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
    $fields['order']['order_comments']['placeholder'] = 'My new placeholder';
    $fields['order']['order_comments']['label']       = 'My new label';
    return $fields;
}

	

В примерах из документации можно найти все названия полей. В нашем случае идентификатор нашего поля billing_phone (смотреть рисунок выше, с исследованием элемента) и он относится к группе Billing (эта информация получена тут). Поэтому наш код будет выглядеть следующим образом:

// Hook in
add_filter( 'woocommerce_checkout_fields', 'poet_override_checkout_fields' );
   
function poet_override_checkout_fields( $fields ) {
    $fields['billing']['billing_phone']['placeholder'] = '+7 (123) 456-78-90';
    $fields['billing']['billing_phone']['maxlength'] = 10; // ожидаем ввода 10 основных символов номера телефона
    return $fields;
}

Выполнение данного кода привнесло в поле нашей формы подсказку-заполнитель

placeholder

Естественно, мы не можем ручаться что именно так будет осуществлён ввод данных пользователем. Поэтому напишем вторую функцию, которая будет задавать правильное форматирование при вводе благодаря шаблону, который мы реализуем.

В WooCommerce для этого есть удобная функция wc_enqueue_js(), которая добавляет пользовательский код в вывод в нижней части сайта перед закрывающим тегом </body>. Вывод справедлив если страница каким то образом относится к WooCommerce. То есть на одиночной странице записи этого вывода не будет.

Вывод скрипта

Найти функцию можно от корня вашего сайта в wp-contents/plugins/woocommerce/includes/wc-core-functions.php

plugins/woocommerce/includes/wc-core-functions.php

Она позволяет добавлять в глобальную переменную (global $wc_queued_js) произвольный код. А её вызов можно увидеть чуть ниже по коду:

Обратите внимание, что обёртка для jQuery уже присутствует и можно просто пользоваться её методами. И вот изящное решение, от Rodolfo Melogli можно увидеть ниже.

/**
 * @snippet       Phone Mask @ WooCommerce Checkout
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 5
 * @community     https://businessbloomer.com/club/
 */
 
add_filter( 'woocommerce_checkout_fields', 'bbloomer_checkout_phone_us_format' );
   
function bbloomer_checkout_phone_us_format( $fields ) {
    $fields['billing']['billing_phone']['placeholder'] = '123-456-7890';
    $fields['billing']['billing_phone']['maxlength'] = 12; // 123-456-7890 is 12 chars long
    return $fields;
}
 
add_action( 'woocommerce_after_checkout_form', 'bbloomer_phone_mask_us' );
 
function bbloomer_phone_mask_us() {
   wc_enqueue_js( "
      $('#billing_phone')
      .keydown(function(e) {
         var key = e.which || e.charCode || e.keyCode || 0;
         var phone = $(this);       
         if (key !== 8 && key !== 9) {
           if (phone.val().length === 3) {
            phone.val(phone.val() + '-'); // add dash after char #3
           }
           if (phone.val().length === 7) {
            phone.val(phone.val() + '-'); // add dash after char #7
           }
         }
         return (key == 8 ||
           key == 9 ||
           key == 46 ||
           (key >= 48 && key <= 57) ||
           (key >= 96 && key <= 105));
        });
         
   " );
}

Оно рабочее. Но зависит от библиотеки jQuery и «заточено» под американский стандарт, так сказать. Так же данное решение не сработает на страницах, которые не относятся к WooCommerce (справедливо для данного кода выше). Ещё мне не нравится пример заполнителя, пользовательский опыт говорит об обратном, вряд ли все будут придерживаться строгого заполнения.

Можно конечно доработать и всё исправить (в случае с примером выше основанным на jQuery), но мне больше понравилась библиотека Cleave.js и её аддон, который заточен под русские стандарты при вводе номера телефона, учитывая с «восьмёрки» или с «плюс, семёрки» начинает набирать пользователь номер.

Поэтому в данном примере мы подключим саму библиотеку и её аддон для страны с кодом RU (в целях уменьшения размера подключаемого кода) и проверим его работу в действии.

К тому же, подключать мы будет стандартной функцией WP для того чтобы решение было универсальным и могло использоваться на разных страницах к разным формам, в том числе популярного плагина Contact Form 7.

Важное примечание! Библиотека с минувшей осени (обращение автора от 25.11.23г) уже не поддерживается по ряду причин, которые описаны в обращении. Она переписана автором на TypeScript и ES6. Пример в статье просто иллюстрирует решение задачи. В целом рекомендуется эта библиотека.

Первым делом задействуем старую добрую функцию WP wp_enqueue_script(), которая будет подключать скрипт библиотеки Cleave.js и её аддон ориентированный на RU. Проверка ! is_checkout() гарантирует подключение только на странице оформления заказа и исключает подключение на прочих страницах

/**
 * Подключаем библиотеку Cleave.js
 * для форматирования содержимого <input/> при вводе текста
 */
function poet_load_scripts() {

	if ( ! is_checkout() ) {
		return;
	}

	wp_enqueue_script(
		'cleave',
		'https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/cleave.min.js',
		array(),
		'1.6.0',
		array(
			'strategy'  => 'defer',
			'in_footer' => true
		)
	);

	wp_enqueue_script(
		'cleave-phone',
		'https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/addons/cleave-phone.ru.js',
		array( 'cleave' ),
		'1.6.0',
		array(
			'strategy'  => 'defer',
			'in_footer' => true
		)
	);

	wp_add_inline_script( 'cleave-phone', "
		const cleave = new Cleave('#billing_phone', {
		    phone: true,
		    phoneRegionCode: 'ru',
		    delimiter: '-'
		});
	" );
	
}

add_action( 'wp_enqueue_scripts', 'poet_load_scripts' );

wp_add_inline_script( ‘cleave-phone’… инициализирует (вызывает функционал) на нужном нам поле с нужными параметрами, а частности разделителем в виде чёрточки.

Результатом выполнения кода будет предопределённая маска, которая не позволит пользователю вводит через чур много символов и будет учитывать начало ввода «+7» или «8»

ввод с +7
ввод с 8

Как подключить маску на других страницах, к другим формам?

Всё очень просто. Решение универсальное в пределах WP.

  1. У нужной формы необходимо понять, как «зацепиться» за нужное поле, или «по айди» или «по классу»
  2. Узнать «айди» страницы, для того чтобы добавить её в условие проверки, дабы не вызывать где не попадя 🙂

Например, у нас есть форма для обратной связи на странице контактов. Первым делом исследуем нужное поле:

Видим подходящий класс. Следовательно, понимаем, как будем делать «селект» — по классу. Далее, узнаем «айдишник» страницы на которой наша форма. В итоге наш код может выглядеть так:

/**
 * Подключаем библиотеку Cleave.js
 * для форматирования содержимого <input/> при вводе текста
 */
function poet_load_scripts() {

	if ( ! is_checkout() && ! is_page( 53 ) ) {
		return;
	}

	wp_enqueue_script(
		'cleave',
		'https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/cleave.min.js',
		array(),
		'1.6.0',
		array(
			'strategy'  => 'defer',
			'in_footer' => true
		)
	);

	wp_enqueue_script(
		'cleave-phone',
		'https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/addons/cleave-phone.ru.js',
		array( 'cleave' ),
		'1.6.0',
		array(
			'strategy'  => 'defer',
			'in_footer' => true
		)
	);

	wp_add_inline_script( 'cleave-phone', "
		const cleave = new Cleave('#billing_phone, .wpcf7-tel', {
		    phone: true,
		    phoneRegionCode: 'ru',
		    delimiter: '-'
		});
	" );

}

add_action( 'wp_enqueue_scripts', 'poet_load_scripts' );

Из примера видно, что мы просто, через запятую, добавили новый селектор по CSS классу. Теперь наша маска применяется к полу телефона созданной плагином Contact Form 7

маска на CF7

Автор

Evgeni

Веб-разработчик, фрилансер и фанат WordPress с 2012 года. На этом сайте делюсь заметками для начинающих по разработке на WordPress. Надеюсь увидеть вас в числе своих подписчиков.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *