Задайте нам свой вопрос и мы свяжемся с вами в ближайшее время
Заявка на расчёт
Задайте нам свой вопрос и мы свяжемся с вами в ближайшее время
Ваша заявка отправлена
Мы получили ваши данные и свяжемся с вами в близжайшее время
tags.
*
* CONFIGURATION
* -----------------------------------------------------------------------
* Edit the CONFIG object below to match your country's phone format
* or your field's identifying attributes.
*/
(function () {
'use strict';
var CONFIG = {
// Max digits accepted (10 = US/CA without country code)
maxDigits: 10,
// How to format the digits as the user types.
// Receives a string of raw digits (already truncated to maxDigits)
// and returns the display string.
format: function (digits) {
var len = digits.length;
if (len === 0) return '';
if (len < 4) return '(' + digits;
if (len < 7) return '(' + digits.slice(0, 3) + ') ' + digits.slice(3);
return '(' + digits.slice(0, 3) + ') ' + digits.slice(3, 6) + '-' + digits.slice(6);
},
// CSS selectors used to find phone fields. Add/remove as needed —
// this covers classic Elementor Forms (type="tel") and the
// common ways an Atomic Form's Input element ends up marked as
// a phone field (autocomplete="tel", or a name/id containing
// "phone"). A bare *="tel" substring match is intentionally left
// out here — "hotel", "intel", "cartel" etc. would false-positive
// on it — see isLikelyTelField() below for the safer check.
selectors: [
'input[type="tel"]',
'input[autocomplete="tel"]',
'input[name*="phone" i]',
'input[id*="phone" i]',
'.elementor-field-group-tel input'
],
// Word-boundary regex for catching name/id values like "tel",
// "user_tel", "tel-number" without matching "hotel", "intel",
// "hostel", "cartel", etc. CSS attribute selectors can't express
// a word boundary, so this runs as a plain JS check instead.
telWordPattern: /(^|[^a-z])tel([^a-z]|$)/i,
// Add a data attribute once a field is masked, so we never
// attach the listener twice to the same input.
processedAttr: 'data-phone-mask-applied'
};
function digitsOnly(value) {
return (value || '').replace(/\D/g, '').slice(0, CONFIG.maxDigits);
}
function applyMask(input, event) {
var raw = digitsOnly(input.value);
var formatted = CONFIG.format(raw);
// Keep the cursor a sensible distance from the end rather than
// letting it jump to position 0 after reformatting.
// (selectionStart can legitimately be 0, so don't use `||` here —
// that would treat a real 0 as "missing" and fall back to the
// full string length.)
var selStart = typeof input.selectionStart === 'number' ? input.selectionStart : input.value.length;
var caretFromEnd = input.value.length - selStart;
input.value = formatted;
var newPos = Math.max(formatted.length - caretFromEnd, 0);
try {
input.setSelectionRange(newPos, newPos);
} catch (e) {
/* some input states don't support selection ranges; ignore */
}
}
function attach(input) {
if (!input || input.hasAttribute(CONFIG.processedAttr)) return;
input.setAttribute(CONFIG.processedAttr, 'true');
// Nudge the browser toward a numeric keypad on mobile without
// breaking Elementor's own validation (still type="tel"/"text").
if (!input.getAttribute('inputmode')) {
input.setAttribute('inputmode', 'tel');
}
input.addEventListener('input', function (e) {
applyMask(input, e);
});
// Format any pre-filled value (e.g. from a dynamic tag or
// browser autofill) on page load.
if (input.value) {
applyMask(input, null);
}
}
function isLikelyTelField(input) {
var name = input.getAttribute('name') || '';
var id = input.getAttribute('id') || '';
return CONFIG.telWordPattern.test(name) || CONFIG.telWordPattern.test(id);
}
function scan(root) {
var scope = root || document;
CONFIG.selectors.forEach(function (sel) {
scope.querySelectorAll(sel).forEach(attach);
});
scope.querySelectorAll('input').forEach(function (input) {
if (isLikelyTelField(input)) attach(input);
});
}
function init() {
scan(document);
// Elementor's Atomic Form (and popups/AJAX forms) can render
// fields after the initial page load, so keep watching the DOM.
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (m) {
m.addedNodes.forEach(function (node) {
if (node.nodeType !== 1) return; // element nodes only
var matchesSelector = node.matches && CONFIG.selectors.some(function (sel) {
return node.matches(sel);
});
if (matchesSelector || (node.tagName === 'INPUT' && isLikelyTelField(node))) {
attach(node);
}
scan(node);
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();