Skip to content

Instantly share code, notes, and snippets.

@Qubadi
Last active August 20, 2025 12:48
Show Gist options
  • Select an option

  • Save Qubadi/ac7a99a26331afc8b38c69a9ea3c570d to your computer and use it in GitHub Desktop.

Select an option

Save Qubadi/ac7a99a26331afc8b38c69a9ea3c570d to your computer and use it in GitHub Desktop.
Jetformbuilder form, A custom code for auto detect country and land code phone ( New style and new version ).
UPDATED: 18.08.2025
Copy the following PHP and create a PHP snippet using your snippet plugins.
Paste the code into the plugin and save it.
_____________________________________________
/**
* JetFormBuilder: Phone field with flag + dial code, auto-detect country (no API key).
* Detection order: saved value → time zone → browser language/region → fallback US.
*/
add_action('wp_footer', function () { ?>
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
<link rel="preload" href="https://cdn.jsdelivr.net/npm/intl-tel-input@23.7.4/build/css/intlTelInput.css" as="style">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/intl-tel-input@23.7.4/build/js/intlTelInput.min.js" as="script">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/intl-tel-input@23.7.4/build/css/intlTelInput.css" />
<script src="https://cdn.jsdelivr.net/npm/intl-tel-input@23.7.4/build/js/intlTelInput.min.js"></script>
<script>
(() => {
"use strict";
const STORAGE_KEY = 'jfb_tel_cc';
const itiMap = new WeakMap();
// Time zone -> country (no external requests)
const TZ2CC = {
'Europe/Oslo':'NO','Europe/Stockholm':'SE','Europe/Copenhagen':'DK','Europe/Helsinki':'FI','Atlantic/Reykjavik':'IS',
'Europe/Berlin':'DE','Europe/Vienna':'AT','Europe/Zurich':'CH','Europe/Brussels':'BE','Europe/Amsterdam':'NL','Europe/Luxembourg':'LU',
'Europe/London':'GB','Europe/Dublin':'IE',
'Europe/Paris':'FR','Europe/Madrid':'ES','Europe/Rome':'IT','Europe/Lisbon':'PT','Atlantic/Madeira':'PT','Atlantic/Azores':'PT',
'Europe/Warsaw':'PL','Europe/Prague':'CZ','Europe/Bratislava':'SK','Europe/Budapest':'HU',
'Europe/Athens':'GR','Europe/Bucharest':'RO','Europe/Sofia':'BG','Europe/Zagreb':'HR','Europe/Belgrade':'RS',
'Europe/Sarajevo':'BA','Europe/Skopje':'MK','Europe/Tirane':'AL','Europe/Ljubljana':'SI',
'Europe/Tallinn':'EE','Europe/Riga':'LV','Europe/Vilnius':'LT',
'America/New_York':'US','America/Detroit':'US','America/Toronto':'CA','America/Montreal':'CA',
'America/Chicago':'US','America/Winnipeg':'CA','America/Edmonton':'CA','America/Denver':'US',
'America/Los_Angeles':'US','America/Vancouver':'CA','America/Phoenix':'US','America/Anchorage':'US','Pacific/Honolulu':'US',
'America/Sao_Paulo':'BR','America/Buenos_Aires':'AR','America/Bogota':'CO','America/Lima':'PE','America/Santiago':'CL','America/Montevideo':'UY',
'Asia/Dubai':'AE','Asia/Jerusalem':'IL','Europe/Istanbul':'TR','Asia/Riyadh':'SA','Asia/Tehran':'IR','Asia/Qatar':'QA','Asia/Kuwait':'KW',
'Africa/Cairo':'EG','Africa/Johannesburg':'ZA','Africa/Nairobi':'KE','Africa/Lagos':'NG','Africa/Casablanca':'MA','Africa/Algiers':'DZ','Africa/Tunis':'TN',
'Asia/Tokyo':'JP','Asia/Seoul':'KR','Asia/Shanghai':'CN','Asia/Hong_Kong':'HK','Asia/Taipei':'TW',
'Asia/Singapore':'SG','Asia/Kuala_Lumpur':'MY','Asia/Bangkok':'TH','Asia/Jakarta':'ID','Asia/Manila':'PH','Asia/Ho_Chi_Minh':'VN',
'Asia/Kolkata':'IN',
'Australia/Sydney':'AU','Australia/Melbourne':'AU','Australia/Brisbane':'AU','Australia/Perth':'AU','Australia/Adelaide':'AU',
'Pacific/Auckland':'NZ'
};
function detectCountry() {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved && /^[A-Z]{2}$/.test(saved)) return saved;
const langs = [
...(navigator.languages || []),
navigator.language,
document.documentElement?.lang || ''
].filter(Boolean).map(String);
try {
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (tz && TZ2CC[tz]) return TZ2CC[tz];
} catch (_) {}
for (const l of langs) {
const m = l.match(/-([A-Za-z]{2})$/);
if (m) return m[1].toUpperCase();
}
let weak = null;
for (const l of langs) {
try {
if (window.Intl && Intl.Locale) {
const r = new Intl.Locale(l).maximize().region;
if (r) { weak = r.toUpperCase(); break; }
}
} catch (_) {}
}
if (!weak && langs.length) {
const map = {nb:'NO',nn:'NO',sv:'SE',da:'DK',fi:'FI',de:'DE',fr:'FR',es:'ES',it:'IT',nl:'NL',pl:'PL',pt:'PT',ru:'RU',
tr:'TR',el:'GR',cs:'CZ',sk:'SK',hu:'HU',ro:'RO',bg:'BG',hr:'HR',sl:'SI',lt:'LT',lv:'LV',et:'EE',en:'GB'};
weak = map[langs[0].slice(0,2).toLowerCase()] || weak;
}
return weak || 'US';
}
function syncDialColor(input) {
try {
const wrap = input.closest('.iti'); if (!wrap) return;
const phColor = getComputedStyle(input, '::placeholder').color;
const dc = wrap.querySelector('.iti__selected-dial-code');
if (dc && phColor) dc.style.color = phColor;
} catch (_) {}
}
function initTel(input) {
if (!window.intlTelInput || input.dataset.itiReady) return;
input.dataset.itiReady = '1';
try {
const iti = window.intlTelInput(input, {
initialCountry: detectCountry().toLowerCase(),
separateDialCode: true, // shows +CC immediately
nationalMode: true,
autoPlaceholder: 'polite',
dropdownContainer: document.body, // dropdown only overlays when open
// utilsScript loads async; not needed for the initial flag/dial code
utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@23.7.4/build/js/utils.js"
});
itiMap.set(input, iti);
input.addEventListener('countrychange', () => {
const d = iti.getSelectedCountryData();
if (d?.iso2) localStorage.setItem(STORAGE_KEY, d.iso2.toUpperCase());
syncDialColor(input);
});
input.style.width = '100%';
const wrap = input.closest('.iti'); if (wrap) wrap.style.width = '100%';
syncDialColor(input);
} catch(_) {}
}
const initNow = () => {
document.querySelectorAll('.jet-form-builder input[type="tel"]').forEach(initTel);
};
if (document.readyState !== 'loading') {
initNow();
} else {
document.addEventListener('DOMContentLoaded', initNow, { once:true });
}
// SUBMIT (capture): ensure +<dial><local> BEFORE JFB serializes the form
function normalizeOnSubmit(input, iti) {
const data = iti.getSelectedCountryData() || {};
const dial = String(data.dialCode || '').replace(/\D/g, '');
let raw = String(input.value || '').trim();
if (raw.startsWith('00')) raw = '+' + raw.slice(2);
let cleaned = raw.replace(/(?!^\+)[^\d]/g, '');
const digits = cleaned.replace(/^\+/, '');
const local = dial ? digits.replace(new RegExp('^' + dial), '') : digits;
let e164 = null;
try { e164 = iti.getNumber(); } catch(_) { e164 = null; }
const built = '+' + dial + local;
const finalVal = (e164 && /^\+\d{4,}$/.test(e164)) ? e164 : built;
if (finalVal && finalVal !== input.value) input.value = finalVal;
}
document.addEventListener('submit', (e) => {
const form = e.target;
if (!(form instanceof HTMLFormElement)) return;
form.querySelectorAll('.jet-form-builder input[type="tel"]').forEach(inp => {
if (!inp.dataset.itiReady) initTel(inp); // ensure iti exists
const iti = itiMap.get(inp);
if (iti) normalizeOnSubmit(inp, iti);
});
}, true); // capture=true so it runs before JFB
})();
</script>
<style>
/* Respect the form’s placeholder color (no hardcoding) */
.jet-form-builder input[type="tel"]::placeholder,
.jet-form-builder .iti input[type="tel"]::placeholder { color: inherit; opacity: inherit; }
.jet-form-builder input[type="tel"]::-webkit-input-placeholder,
.jet-form-builder input[type="tel"]::-moz-placeholder,
.jet-form-builder input[type="tel"]:-ms-input-placeholder,
.jet-form-builder input[type="tel"]::-ms-input-placeholder { color: inherit; opacity: inherit; }
.jet-form-builder .iti__flag-container { z-index: auto !important; }
.jet-form-builder .iti { z-index: auto !important; }
.iti--container { position: absolute; z-index: 9999; }
/* Layout helper */
.jet-form-builder .iti { width: 100%; }
</style>
<?php });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment