From 96f2c697c6d4008bec87719e3fd5c7d064890fb3 Mon Sep 17 00:00:00 2001 From: johnnyq Date: Wed, 26 Aug 2026 13:53:27 -0400 Subject: [PATCH] use intl js lib across all phone number fields --- .../vendor_template/vendor_template_add.php | 4 +- .../vendor_template/vendor_template_edit.php | 4 +- admin/settings_company.php | 6 +- agent/modals/client/client_add.php | 18 +- agent/modals/contact/contact_add.php | 25 +- agent/modals/contact/contact_edit.php | 25 +- agent/modals/location/location_add.php | 10 +- agent/modals/location/location_edit.php | 10 +- agent/modals/vendor/vendor_add.php | 4 +- agent/modals/vendor/vendor_edit.php | 4 +- css/itflow_custom.css | 51 + includes/footer.php | 2 +- includes/header.php | 8 +- includes/settings_localization_array.php | 207 ++ js/app.js | 147 ++ libs/intl-tel-input/css/flag-offsets.css | 253 --- libs/intl-tel-input/css/intlTelInput.css | 558 ----- libs/intl-tel-input/css/intlTelInput.min.css | 1 + .../css/intlTelInputWithAssets.css | 7 - libs/intl-tel-input/css/styles.d.ts | 2 - libs/intl-tel-input/img/flags.webp | Bin 0 -> 38636 bytes libs/intl-tel-input/img/flags@2x.webp | Bin 0 -> 88662 bytes libs/intl-tel-input/js/constants.ts | 213 -- libs/intl-tel-input/js/core/countrySearch.ts | 148 -- libs/intl-tel-input/js/core/icons.ts | 64 - libs/intl-tel-input/js/core/numerals.ts | 64 - libs/intl-tel-input/js/core/options.ts | 466 ----- libs/intl-tel-input/js/core/ui.ts | 1442 ------------- libs/intl-tel-input/js/data.ts | 1531 -------------- libs/intl-tel-input/js/data/country-data.ts | 168 -- .../intl-tel-input/js/data/intl-regionless.ts | 20 - .../intl-tel-input/js/data/nanp-regionless.ts | 37 - libs/intl-tel-input/js/format/caret.ts | 32 - libs/intl-tel-input/js/format/formatting.ts | 48 - libs/intl-tel-input/js/helpers/dom.ts | 26 - libs/intl-tel-input/js/helpers/string.ts | 10 - libs/intl-tel-input/js/intlTelInput.ts | 1805 ----------------- .../js/intlTelInputWithUtils.min.js | 7 + .../js/intlTelInputWithUtils.ts | 4 - libs/intl-tel-input/js/locale/ar.ts | 34 - libs/intl-tel-input/js/locale/bg.ts | 24 - libs/intl-tel-input/js/locale/bn.ts | 24 - libs/intl-tel-input/js/locale/bs.ts | 37 - libs/intl-tel-input/js/locale/ca.ts | 24 - .../js/locale/country-names/bs.ts | 253 --- .../js/locale/country-names/hy.ts | 253 --- .../js/locale/country-names/is.ts | 253 --- .../js/locale/country-names/mk.ts | 253 --- .../js/locale/country-names/sq.ts | 253 --- .../js/locale/country-names/uz.ts | 253 --- libs/intl-tel-input/js/locale/cs.ts | 29 - libs/intl-tel-input/js/locale/da.ts | 24 - libs/intl-tel-input/js/locale/de.ts | 24 - libs/intl-tel-input/js/locale/el.ts | 24 - libs/intl-tel-input/js/locale/en.ts | 24 - libs/intl-tel-input/js/locale/es.ts | 24 - libs/intl-tel-input/js/locale/et.ts | 24 - libs/intl-tel-input/js/locale/fa.ts | 21 - libs/intl-tel-input/js/locale/fi.ts | 24 - libs/intl-tel-input/js/locale/fil.ts | 21 - libs/intl-tel-input/js/locale/fr.ts | 24 - libs/intl-tel-input/js/locale/he.ts | 24 - libs/intl-tel-input/js/locale/hi.ts | 24 - libs/intl-tel-input/js/locale/hr.ts | 36 - libs/intl-tel-input/js/locale/hu.ts | 21 - libs/intl-tel-input/js/locale/hy.ts | 25 - libs/intl-tel-input/js/locale/id.ts | 21 - libs/intl-tel-input/js/locale/index.ts | 55 - libs/intl-tel-input/js/locale/is.ts | 30 - libs/intl-tel-input/js/locale/it.ts | 24 - libs/intl-tel-input/js/locale/ja.ts | 21 - libs/intl-tel-input/js/locale/kn.ts | 24 - libs/intl-tel-input/js/locale/ko.ts | 21 - libs/intl-tel-input/js/locale/lt.ts | 38 - libs/intl-tel-input/js/locale/lv.ts | 34 - libs/intl-tel-input/js/locale/mk.ts | 30 - libs/intl-tel-input/js/locale/mr.ts | 24 - libs/intl-tel-input/js/locale/ms.ts | 21 - libs/intl-tel-input/js/locale/nl.ts | 24 - libs/intl-tel-input/js/locale/no.ts | 24 - libs/intl-tel-input/js/locale/pl.ts | 34 - libs/intl-tel-input/js/locale/pt.ts | 24 - libs/intl-tel-input/js/locale/ro.ts | 30 - libs/intl-tel-input/js/locale/ru.ts | 35 - libs/intl-tel-input/js/locale/sk.ts | 27 - libs/intl-tel-input/js/locale/sl.ts | 39 - libs/intl-tel-input/js/locale/sq.ts | 25 - libs/intl-tel-input/js/locale/sr.ts | 35 - libs/intl-tel-input/js/locale/sv.ts | 21 - libs/intl-tel-input/js/locale/sw.ts | 24 - libs/intl-tel-input/js/locale/ta.ts | 24 - libs/intl-tel-input/js/locale/te.ts | 24 - libs/intl-tel-input/js/locale/th.ts | 21 - libs/intl-tel-input/js/locale/tr.ts | 21 - libs/intl-tel-input/js/locale/types.ts | 17 - libs/intl-tel-input/js/locale/uk.ts | 35 - libs/intl-tel-input/js/locale/ur.ts | 24 - libs/intl-tel-input/js/locale/uz.ts | 22 - libs/intl-tel-input/js/locale/vi.ts | 21 - libs/intl-tel-input/js/locale/zh-hk.ts | 20 - libs/intl-tel-input/js/locale/zh.ts | 21 - libs/intl-tel-input/js/types/events.ts | 20 - .../js/types/forEachInstanceArgsMap.ts | 6 - libs/intl-tel-input/js/types/public-api.ts | 171 -- libs/intl-tel-input/js/types/utils.d.ts | 6 - libs/intl-tel-input/js/utils.js | 223 -- setup/index.php | 2 +- 107 files changed, 492 insertions(+), 10356 deletions(-) delete mode 100644 libs/intl-tel-input/css/flag-offsets.css delete mode 100644 libs/intl-tel-input/css/intlTelInput.css create mode 100644 libs/intl-tel-input/css/intlTelInput.min.css delete mode 100644 libs/intl-tel-input/css/intlTelInputWithAssets.css delete mode 100644 libs/intl-tel-input/css/styles.d.ts create mode 100644 libs/intl-tel-input/img/flags.webp create mode 100644 libs/intl-tel-input/img/flags@2x.webp delete mode 100644 libs/intl-tel-input/js/constants.ts delete mode 100644 libs/intl-tel-input/js/core/countrySearch.ts delete mode 100644 libs/intl-tel-input/js/core/icons.ts delete mode 100644 libs/intl-tel-input/js/core/numerals.ts delete mode 100644 libs/intl-tel-input/js/core/options.ts delete mode 100644 libs/intl-tel-input/js/core/ui.ts delete mode 100644 libs/intl-tel-input/js/data.ts delete mode 100644 libs/intl-tel-input/js/data/country-data.ts delete mode 100644 libs/intl-tel-input/js/data/intl-regionless.ts delete mode 100644 libs/intl-tel-input/js/data/nanp-regionless.ts delete mode 100644 libs/intl-tel-input/js/format/caret.ts delete mode 100644 libs/intl-tel-input/js/format/formatting.ts delete mode 100644 libs/intl-tel-input/js/helpers/dom.ts delete mode 100644 libs/intl-tel-input/js/helpers/string.ts delete mode 100644 libs/intl-tel-input/js/intlTelInput.ts create mode 100644 libs/intl-tel-input/js/intlTelInputWithUtils.min.js delete mode 100644 libs/intl-tel-input/js/intlTelInputWithUtils.ts delete mode 100644 libs/intl-tel-input/js/locale/ar.ts delete mode 100644 libs/intl-tel-input/js/locale/bg.ts delete mode 100644 libs/intl-tel-input/js/locale/bn.ts delete mode 100644 libs/intl-tel-input/js/locale/bs.ts delete mode 100644 libs/intl-tel-input/js/locale/ca.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/bs.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/hy.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/is.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/mk.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/sq.ts delete mode 100644 libs/intl-tel-input/js/locale/country-names/uz.ts delete mode 100644 libs/intl-tel-input/js/locale/cs.ts delete mode 100644 libs/intl-tel-input/js/locale/da.ts delete mode 100644 libs/intl-tel-input/js/locale/de.ts delete mode 100644 libs/intl-tel-input/js/locale/el.ts delete mode 100644 libs/intl-tel-input/js/locale/en.ts delete mode 100644 libs/intl-tel-input/js/locale/es.ts delete mode 100644 libs/intl-tel-input/js/locale/et.ts delete mode 100644 libs/intl-tel-input/js/locale/fa.ts delete mode 100644 libs/intl-tel-input/js/locale/fi.ts delete mode 100644 libs/intl-tel-input/js/locale/fil.ts delete mode 100644 libs/intl-tel-input/js/locale/fr.ts delete mode 100644 libs/intl-tel-input/js/locale/he.ts delete mode 100644 libs/intl-tel-input/js/locale/hi.ts delete mode 100644 libs/intl-tel-input/js/locale/hr.ts delete mode 100644 libs/intl-tel-input/js/locale/hu.ts delete mode 100644 libs/intl-tel-input/js/locale/hy.ts delete mode 100644 libs/intl-tel-input/js/locale/id.ts delete mode 100644 libs/intl-tel-input/js/locale/index.ts delete mode 100644 libs/intl-tel-input/js/locale/is.ts delete mode 100644 libs/intl-tel-input/js/locale/it.ts delete mode 100644 libs/intl-tel-input/js/locale/ja.ts delete mode 100644 libs/intl-tel-input/js/locale/kn.ts delete mode 100644 libs/intl-tel-input/js/locale/ko.ts delete mode 100644 libs/intl-tel-input/js/locale/lt.ts delete mode 100644 libs/intl-tel-input/js/locale/lv.ts delete mode 100644 libs/intl-tel-input/js/locale/mk.ts delete mode 100644 libs/intl-tel-input/js/locale/mr.ts delete mode 100644 libs/intl-tel-input/js/locale/ms.ts delete mode 100644 libs/intl-tel-input/js/locale/nl.ts delete mode 100644 libs/intl-tel-input/js/locale/no.ts delete mode 100644 libs/intl-tel-input/js/locale/pl.ts delete mode 100644 libs/intl-tel-input/js/locale/pt.ts delete mode 100644 libs/intl-tel-input/js/locale/ro.ts delete mode 100644 libs/intl-tel-input/js/locale/ru.ts delete mode 100644 libs/intl-tel-input/js/locale/sk.ts delete mode 100644 libs/intl-tel-input/js/locale/sl.ts delete mode 100644 libs/intl-tel-input/js/locale/sq.ts delete mode 100644 libs/intl-tel-input/js/locale/sr.ts delete mode 100644 libs/intl-tel-input/js/locale/sv.ts delete mode 100644 libs/intl-tel-input/js/locale/sw.ts delete mode 100644 libs/intl-tel-input/js/locale/ta.ts delete mode 100644 libs/intl-tel-input/js/locale/te.ts delete mode 100644 libs/intl-tel-input/js/locale/th.ts delete mode 100644 libs/intl-tel-input/js/locale/tr.ts delete mode 100644 libs/intl-tel-input/js/locale/types.ts delete mode 100644 libs/intl-tel-input/js/locale/uk.ts delete mode 100644 libs/intl-tel-input/js/locale/ur.ts delete mode 100644 libs/intl-tel-input/js/locale/uz.ts delete mode 100644 libs/intl-tel-input/js/locale/vi.ts delete mode 100644 libs/intl-tel-input/js/locale/zh-hk.ts delete mode 100644 libs/intl-tel-input/js/locale/zh.ts delete mode 100644 libs/intl-tel-input/js/types/events.ts delete mode 100644 libs/intl-tel-input/js/types/forEachInstanceArgsMap.ts delete mode 100644 libs/intl-tel-input/js/types/public-api.ts delete mode 100644 libs/intl-tel-input/js/types/utils.d.ts delete mode 100644 libs/intl-tel-input/js/utils.js diff --git a/admin/modals/vendor_template/vendor_template_add.php b/admin/modals/vendor_template/vendor_template_add.php index 08399f004..175dc9ce8 100644 --- a/admin/modals/vendor_template/vendor_template_add.php +++ b/admin/modals/vendor_template/vendor_template_add.php @@ -75,8 +75,8 @@ ob_start();
- - + +
diff --git a/admin/modals/vendor_template/vendor_template_edit.php b/admin/modals/vendor_template/vendor_template_edit.php index b6b6d4049..6599c8415 100644 --- a/admin/modals/vendor_template/vendor_template_edit.php +++ b/admin/modals/vendor_template/vendor_template_edit.php @@ -119,8 +119,8 @@ ob_start();
- - + +
diff --git a/admin/settings_company.php b/admin/settings_company.php index 16c75144d..9f7b0048f 100644 --- a/admin/settings_company.php +++ b/admin/settings_company.php @@ -96,7 +96,7 @@ $company_initials = escapeHtml(initials($company_name)); @@ -108,8 +108,8 @@ $company_initials = escapeHtml(initials($company_name));
- - + +
diff --git a/agent/modals/client/client_add.php b/agent/modals/client/client_add.php index 3157b37f9..609473bd0 100644 --- a/agent/modals/client/client_add.php +++ b/agent/modals/client/client_add.php @@ -182,7 +182,7 @@ ob_start(); @@ -195,8 +195,8 @@ ob_start();
- - + +
@@ -213,8 +213,8 @@ ob_start();
- - + +
@@ -246,8 +246,8 @@ ob_start();
- - + +
@@ -264,8 +264,8 @@ ob_start();
- - + +
diff --git a/agent/modals/contact/contact_add.php b/agent/modals/contact/contact_add.php index 19476e43e..94b419f43 100644 --- a/agent/modals/contact/contact_add.php +++ b/agent/modals/contact/contact_add.php @@ -12,6 +12,20 @@ if ($client_id) { $sql_tags_select = mysqli_query($mysqli, "SELECT tag_id, tag_name FROM tags WHERE tag_type = 3 ORDER BY tag_name ASC"); +// A contact's phone belongs to the CLIENT's country, not the company's. The +// client's country lives on its primary location; falls through to the +// company default when the client has none. +$client_phone_iso2 = ''; +if ($client_id) { + $sql_client_country = mysqli_query($mysqli, "SELECT location_country FROM locations + WHERE location_client_id = $client_id AND location_primary = 1 LIMIT 1"); + $row_client_country = mysqli_fetch_assoc($sql_client_country); + if ($row_client_country) { + $client_phone_iso2 = $country_iso2_array[$row_client_country['location_country']] ?? ''; + } +} + + ob_start(); ?> @@ -20,7 +34,8 @@ ob_start(); -
+ @@ -121,8 +136,8 @@ ob_start();
- - + +
diff --git a/agent/modals/contact/contact_edit.php b/agent/modals/contact/contact_edit.php index b7106f050..e8a7eb08d 100644 --- a/agent/modals/contact/contact_edit.php +++ b/agent/modals/contact/contact_edit.php @@ -18,6 +18,20 @@ $sql = mysqli_query($mysqli, "SELECT contact_archived_at, contact_billing, conta $row = mysqli_fetch_assoc($sql); $client_id = intval($row['contact_client_id']); + +// A contact's phone belongs to the CLIENT's country, not the company's. The +// client's country lives on its primary location; falls through to the +// company default when the client has none. +$client_phone_iso2 = ''; +if ($client_id) { + $sql_client_country = mysqli_query($mysqli, "SELECT location_country FROM locations + WHERE location_client_id = $client_id AND location_primary = 1 LIMIT 1"); + $row_client_country = mysqli_fetch_assoc($sql_client_country); + if ($row_client_country) { + $client_phone_iso2 = $country_iso2_array[$row_client_country['location_country']] ?? ''; + } +} + $contact_name = escapeHtml($row['contact_name']); $contact_title = escapeHtml($row['contact_title']); $contact_department = escapeHtml($row['contact_department']); @@ -59,7 +73,8 @@ ob_start(); - + @@ -119,8 +134,8 @@ ob_start();
- " placeholder="+" maxlength="4"> - + "> +
@@ -137,8 +152,8 @@ ob_start();
- " placeholder="+" maxlength="4"> - + "> +
diff --git a/agent/modals/location/location_add.php b/agent/modals/location/location_add.php index ab50ce223..da96ea507 100644 --- a/agent/modals/location/location_add.php +++ b/agent/modals/location/location_add.php @@ -131,7 +131,7 @@ ob_start(); @@ -168,8 +168,8 @@ ob_start();
- - + +
@@ -186,8 +186,8 @@ ob_start();
- - + +
diff --git a/agent/modals/location/location_edit.php b/agent/modals/location/location_edit.php index aaa359f47..3105f1366 100644 --- a/agent/modals/location/location_edit.php +++ b/agent/modals/location/location_edit.php @@ -152,7 +152,7 @@ ob_start(); @@ -195,8 +195,8 @@ ob_start();
- - + +
@@ -213,8 +213,8 @@ ob_start();
- - + +
diff --git a/agent/modals/vendor/vendor_add.php b/agent/modals/vendor/vendor_add.php index d0a3b9348..f17f8d5b8 100644 --- a/agent/modals/vendor/vendor_add.php +++ b/agent/modals/vendor/vendor_add.php @@ -76,8 +76,8 @@ ob_start();
- - + +
diff --git a/agent/modals/vendor/vendor_edit.php b/agent/modals/vendor/vendor_edit.php index f75954352..801d611c9 100644 --- a/agent/modals/vendor/vendor_edit.php +++ b/agent/modals/vendor/vendor_edit.php @@ -124,8 +124,8 @@ ob_start();
- - + +
diff --git a/css/itflow_custom.css b/css/itflow_custom.css index 431303a65..b92f4f9d0 100644 --- a/css/itflow_custom.css +++ b/css/itflow_custom.css @@ -1175,6 +1175,57 @@ a:focus { --lte-primary-color-rgb: 0, 0, 0; } +/* --- intl-tel-input -------------------------------------------------------- + The library wraps the input in a .iti container, which inside an + .input-group becomes the flex item instead of the input. Bootstrap sizes its + children with `.input-group > .form-control { flex: 1 1 auto; width: 1% }`, + and that selector no longer matches the now-nested input - so without these + the wrapper collapses to its content width and the field sits detached from + the addon beside it. + + The wrapper takes the sizing the input used to get, and the input inside it + is squared off on the left because .iti draws the country button there and + the addon draws the rounded edge. */ +.input-group > .iti { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .iti > .form-control { + width: 100%; +} +.input-group > .iti:not(:last-child) > .form-control { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > .iti:not(:first-child) > .form-control, +.iti--separate-dial-code .form-control { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +/* the country button is chrome, not a control - keep it on the form-control + palette so it does not read as a raised button in either mode */ +.iti__selected-country { + background-color: var(--bs-tertiary-bg); + border: var(--bs-border-width) solid var(--bs-border-color); + border-right: 0; + border-radius: var(--bs-border-radius) 0 0 var(--bs-border-radius); +} +.iti__country-list, +.iti__dropdown-content { + background-color: var(--bs-body-bg); + color: var(--bs-body-color); + border: var(--bs-border-width) solid var(--bs-border-color); +} +.iti__country.iti__highlight, +.iti__country:hover { + background-color: var(--bs-secondary-bg); +} +.iti__dial-code { + color: var(--bs-secondary-color); +} + /* --- Print ---------------------------------------------------------------- AdminLTE 3 bundled Bootstrap 4, whose print reboot shrank every printout by declaring `@page { size: a3 }` and letting the browser scale that oversized diff --git a/includes/footer.php b/includes/footer.php index 2ef9b3966..1331ac4a0 100644 --- a/includes/footer.php +++ b/includes/footer.php @@ -41,7 +41,7 @@ if (basename(dirname($_SERVER['REQUEST_URI'])) === 'guest') { ?> - + diff --git a/includes/header.php b/includes/header.php index 61d41c4c6..19dd5709a 100644 --- a/includes/header.php +++ b/includes/header.php @@ -44,6 +44,12 @@ header("X-Frame-Options: DENY"); - + so it does not add to the + CSP unsafe-inline debt. Empty when the company has no country set, + which js/app.js reads as "let the library decide". */ ?> +
diff --git a/includes/settings_localization_array.php b/includes/settings_localization_array.php index 6555e2da5..d55a253c5 100644 --- a/includes/settings_localization_array.php +++ b/includes/settings_localization_array.php @@ -773,3 +773,210 @@ $locales_array = [ 'zu_ZA' => 'Zulu (South Africa)', 'zu' => 'Zulu', ]; + +// Country name -> ISO 3166-1 alpha-2, keyed by the exact strings in +// $countries_array above. intl-tel-input identifies countries by ISO2, so +// this is what turns the stored company_country into an initialCountry for +// the phone inputs. Sixteen of the names above do not match the library's +// own spelling and are aliased here rather than in JS: "Colombi" (a typo in +// the list), the "Saint X" / "St. X" pair, "Swaziland" -> Eswatini, +// "Macedonia" -> North Macedonia, "Serbia and Montenegro" -> Serbia, and +// the two Koreas. Keep this in step with $countries_array - a name here +// with no entry there is dead, and one there with no entry here falls back +// to the library default. +$country_iso2_array = array( + "Afghanistan" => "af", + "Albania" => "al", + "Algeria" => "dz", + "Andorra" => "ad", + "Angola" => "ao", + "Antigua and Barbuda" => "ag", + "Argentina" => "ar", + "Armenia" => "am", + "Australia" => "au", + "Austria" => "at", + "Azerbaijan" => "az", + "Bahamas" => "bs", + "Bahrain" => "bh", + "Bangladesh" => "bd", + "Barbados" => "bb", + "Belarus" => "by", + "Belgium" => "be", + "Belize" => "bz", + "Benin" => "bj", + "Bhutan" => "bt", + "Bolivia" => "bo", + "Bosnia and Herzegovina" => "ba", + "Botswana" => "bw", + "Brazil" => "br", + "Brunei" => "bn", + "Bulgaria" => "bg", + "Burkina Faso" => "bf", + "Burundi" => "bi", + "Cambodia" => "kh", + "Cameroon" => "cm", + "Canada" => "ca", + "Cape Verde" => "cv", + "Central African Republic" => "cf", + "Chad" => "td", + "Chile" => "cl", + "China" => "cn", + "Colombi" => "co", + "Comoros" => "km", + "Congo (Brazzaville)" => "cg", + "Congo" => "cd", + "Costa Rica" => "cr", + "Cote d'Ivoire" => "ci", + "Croatia" => "hr", + "Cuba" => "cu", + "Cyprus" => "cy", + "Czech Republic" => "cz", + "Denmark" => "dk", + "Djibouti" => "dj", + "Dominica" => "dm", + "Dominican Republic" => "do", + "East Timor (Timor Timur)" => "tl", + "Ecuador" => "ec", + "Egypt" => "eg", + "El Salvador" => "sv", + "Equatorial Guinea" => "gq", + "Eritrea" => "er", + "Estonia" => "ee", + "Ethiopia" => "et", + "Fiji" => "fj", + "Finland" => "fi", + "France" => "fr", + "Gabon" => "ga", + "Gambia, The" => "gm", + "Georgia" => "ge", + "Germany" => "de", + "Ghana" => "gh", + "Gibraltar" => "gi", + "Greece" => "gr", + "Grenada" => "gd", + "Guatemala" => "gt", + "Guinea" => "gn", + "Guinea-Bissau" => "gw", + "Guyana" => "gy", + "Haiti" => "ht", + "Honduras" => "hn", + "Hungary" => "hu", + "Iceland" => "is", + "India" => "in", + "Indonesia" => "id", + "Iran" => "ir", + "Iraq" => "iq", + "Ireland" => "ie", + "Israel" => "il", + "Italy" => "it", + "Jamaica" => "jm", + "Japan" => "jp", + "Jordan" => "jo", + "Kazakhstan" => "kz", + "Kenya" => "ke", + "Kiribati" => "ki", + "Korea, North" => "kp", + "Korea, South" => "kr", + "Kuwait" => "kw", + "Kyrgyzstan" => "kg", + "Laos" => "la", + "Latvia" => "lv", + "Lebanon" => "lb", + "Lesotho" => "ls", + "Liberia" => "lr", + "Libya" => "ly", + "Liechtenstein" => "li", + "Lithuania" => "lt", + "Luxembourg" => "lu", + "Macedonia" => "mk", + "Madagascar" => "mg", + "Malawi" => "mw", + "Malaysia" => "my", + "Maldives" => "mv", + "Mali" => "ml", + "Malta" => "mt", + "Marshall Islands" => "mh", + "Mauritania" => "mr", + "Mauritius" => "mu", + "Mexico" => "mx", + "Micronesia" => "fm", + "Moldova" => "md", + "Monaco" => "mc", + "Mongolia" => "mn", + "Morocco" => "ma", + "Mozambique" => "mz", + "Myanmar" => "mm", + "Namibia" => "na", + "Nauru" => "nr", + "Nepal" => "np", + "Netherlands" => "nl", + "New Zealand" => "nz", + "Nicaragua" => "ni", + "Niger" => "ne", + "Nigeria" => "ng", + "Norway" => "no", + "Oman" => "om", + "Pakistan" => "pk", + "Palau" => "pw", + "Panama" => "pa", + "Papua New Guinea" => "pg", + "Paraguay" => "py", + "Peru" => "pe", + "Philippines" => "ph", + "Poland" => "pl", + "Portugal" => "pt", + "Qatar" => "qa", + "Romania" => "ro", + "Russia" => "ru", + "Rwanda" => "rw", + "Saint Kitts and Nevis" => "kn", + "Saint Lucia" => "lc", + "Saint Vincent" => "vc", + "Samoa" => "ws", + "San Marino" => "sm", + "Sao Tome and Principe" => "st", + "Saudi Arabia" => "sa", + "Senegal" => "sn", + "Serbia and Montenegro" => "rs", + "Seychelles" => "sc", + "Sierra Leone" => "sl", + "Singapore" => "sg", + "Slovakia" => "sk", + "Slovenia" => "si", + "Solomon Islands" => "sb", + "Somalia" => "so", + "South Africa" => "za", + "Spain" => "es", + "Sri Lanka" => "lk", + "Sudan" => "sd", + "Suriname" => "sr", + "Swaziland" => "sz", + "Sweden" => "se", + "Switzerland" => "ch", + "Syria" => "sy", + "Taiwan" => "tw", + "Tajikistan" => "tj", + "Tanzania" => "tz", + "Thailand" => "th", + "Togo" => "tg", + "Tonga" => "to", + "Trinidad and Tobago" => "tt", + "Tunisia" => "tn", + "Turkey" => "tr", + "Turkmenistan" => "tm", + "Tuvalu" => "tv", + "Uganda" => "ug", + "Ukraine" => "ua", + "United Arab Emirates" => "ae", + "United Kingdom" => "gb", + "United States" => "us", + "Uruguay" => "uy", + "Uzbekistan" => "uz", + "Vanuatu" => "vu", + "Vatican City" => "va", + "Venezuela" => "ve", + "Vietnam" => "vn", + "Yemen" => "ye", + "Zambia" => "zm", + "Zimbabwe" => "zw", +); diff --git a/js/app.js b/js/app.js index 835ddb079..b221774d8 100644 --- a/js/app.js +++ b/js/app.js @@ -613,6 +613,9 @@ function itflowInit() { itflowStep('datatables', function () { new DataTable('.dataTables'); }); + + // Phone inputs + itflowStep('phone-inputs', initPhoneInputs); } // modal_footer.php re-loads this file on every ajax modal open, so run now if @@ -963,3 +966,147 @@ function itflowWatchNetworkIp(networkId, ipId) { input.addEventListener('blur', check); } + + +/** + * intl-tel-input on every phone field. + * + * ITFlow stores the dial code and the number in separate columns + * (contact_phone_country_code / contact_phone and friends), so the library runs + * in separateDialCode mode: its dropdown owns the dial code, the visible input + * holds only the national number. That keeps the existing schema, the API and + * every render site untouched. + * + * Markup contract: + * + * + * + * Which country a field starts on, most specific first: + * 1. data-itflow-phone-country-select on the input names a is currently on. + * + * Each