1 2var framework = framework || {} 3 4framework.fetchify = { 5 6 apiKey: null, 7 addressPlaceholder: null, 8 countries: null, 9 10 countryPhoneCodes: { "BD": "880", "BE": "32", "BF": "226", "BG": "359", "BA": "387", "BB": "+1-246", "WF": "681", "BL": "590", "BM": "+1-441", "BN": "673", "BO": "591", "BH": "973", "BI": "257", "BJ": "229", "BT": "975", "JM": "+1-876", "BV": "", "BW": "267", "WS": "685", "BQ": "599", "BR": "55", "BS": "+1-242", "JE": "+44-1534", "BY": "375", "BZ": "501", "RU": "7", "RW": "250", "RS": "381", "TL": "670", "RE": "262", "TM": "993", "TJ": "992", "RO": "40", "TK": "690", "GW": "245", "GU": "+1-671", "GT": "502", "GS": "", "GR": "30", "GQ": "240", "GP": "590", "JP": "81", "GY": "592", "GG": "+44-1481", "GF": "594", "GE": "995", "GD": "+1-473", "GB": "44", "GA": "241", "SV": "503", "GN": "224", "GM": "220", "GL": "299", "GI": "350", "GH": "233", "OM": "968", "TN": "216", "JO": "962", "HR": "385", "HT": "509", "HU": "36", "HK": "852", "HN": "504", "HM": " ", "VE": "58", "PR": "+1-787 and 1-939", "PS": "970", "PW": "680", "PT": "351", "SJ": "47", "PY": "595", "IQ": "964", "PA": "507", "PF": "689", "PG": "675", "PE": "51", "PK": "92", "PH": "63", "PN": "870", "PL": "48", "PM": "508", "ZM": "260", "EH": "212", "EE": "372", "EG": "20", "ZA": "27", "EC": "593", "IT": "39", "VN": "84", "SB": "677", "ET": "251", "SO": "252", "ZW": "263", "SA": "966", "ES": "34", "ER": "291", "ME": "382", "MD": "373", "MG": "261", "MF": "590", "MA": "212", "MC": "377", "UZ": "998", "MM": "95", "ML": "223", "MO": "853", "MN": "976", "MH": "692", "MK": "389", "MU": "230", "MT": "356", "MW": "265", "MV": "960", "MQ": "596", "MP": "+1-670", "MS": "+1-664", "MR": "222", "IM": "+44-1624", "UG": "256", "TZ": "255", "MY": "60", "MX": "52", "IL": "972", "FR": "33", "IO": "246", "SH": "290", "FI": "358", "FJ": "679", "FK": "500", "FM": "691", "FO": "298", "NI": "505", "NL": "31", "NO": "47", "NA": "264", "VU": "678", "NC": "687", "NE": "227", "NF": "672", "NG": "234", "NZ": "64", "NP": "977", "NR": "674", "NU": "683", "CK": "682", "XK": "", "CI": "225", "CH": "41", "CO": "57", "CN": "86", "CM": "237", "CL": "56", "CC": "61", "CA": "1", "CG": "242", "CF": "236", "CD": "243", "CZ": "420", "CY": "357", "CX": "61", "CR": "506", "CW": "599", "CV": "238", "CU": "53", "SZ": "268", "SY": "963", "SX": "599", "KG": "996", "KE": "254", "SS": "211", "SR": "597", "KI": "686", "KH": "855", "KN": "+1-869", "KM": "269", "ST": "239", "SK": "421", "KR": "82", "SI": "386", "KP": "850", "KW": "965", "SN": "221", "SM": "378", "SL": "232", "SC": "248", "KZ": "7", "KY": "+1-345", "SG": "65", "SE": "46", "SD": "249", "DO": "+1-809 and 1-829", "DM": "+1-767", "DJ": "253", "DK": "45", "VG": "+1-284", "DE": "49", "YE": "967", "DZ": "213", "US": "1", "UY": "598", "YT": "262", "UM": "1", "LB": "961", "LC": "+1-758", "LA": "856", "TV": "688", "TW": "886", "TT": "+1-868", "TR": "90", "LK": "94", "LI": "423", "LV": "371", "TO": "676", "LT": "370", "LU": "352", "LR": "231", "LS": "266", "TH": "66", "TF": "", "TG": "228", "TD": "235", "TC": "+1-649", "LY": "218", "VA": "379", "VC": "+1-784", "AE": "971", "AD": "376", "AG": "+1-268", "AF": "93", "AI": "+1-264", "VI": "+1-340", "IS": "354", "IR": "98", "AM": "374", "AL": "355", "AO": "244", "AQ": "", "AS": "+1-684", "AR": "54", "AU": "61", "AT": "43", "AW": "297", "IN": "91", "AX": "+358-18", "AZ": "994", "IE": "353", "ID": "62", "UA": "380", "QA": "974", "MZ": "258" }, 11 12 crossSvg: `url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m350.273438 320.105469c8.339843 8.34375 8.339843 21.847656 0 30.167969-4.160157 4.160156-9.621094 6.25-15.085938 6.25-5.460938 0-10.921875-2.089844-15.082031-6.25l-64.105469-64.109376-64.105469 64.109376c-4.160156 4.160156-9.621093 6.25-15.082031 6.25-5.464844 0-10.925781-2.089844-15.085938-6.25-8.339843-8.320313-8.339843-21.824219 0-30.167969l64.109376-64.105469-64.109376-64.105469c-8.339843-8.34375-8.339843-21.847656 0-30.167969 8.34375-8.339843 21.824219-8.339843 30.167969 0l64.105469 64.109376 64.105469-64.109376c8.34375-8.339843 21.824219-8.339843 30.167969 0 8.339843 8.320313 8.339843 21.824219 0 30.167969l-64.109376 64.105469z' fill='%23F9634E'/%3E%3C/svg%3E")`,
13 tickSvg: `url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m385.75 171.585938c8.339844 8.339843 8.339844 21.820312 0 30.164062l-138.667969 138.664062c-4.160156 4.160157-9.621093 6.253907-15.082031 6.253907s-10.921875-2.09375-15.082031-6.253907l-69.332031-69.332031c-8.34375-8.339843-8.34375-21.824219 0-30.164062 8.339843-8.34375 21.820312-8.34375 30.164062 0l54.25 54.25 123.585938-123.582031c8.339843-8.34375 21.820312-8.34375 30.164062 0z' fill='%2326D07C'/%3E%3C/svg%3E")`, 14 15 init: async function (apiKey, addressPlaceholder) { 16 this.apiKey = apiKey; 17 this.addressPlaceholder = addressPlaceholder; 18 19 let addressContainers = Array.from(document.querySelectorAll("[data-address]")); 20 var allAddressContainer = []; 21 for (let container of addressContainers) { 22 allAddressContainer.push(this.getAllAddressElements(container)); 23 } 24 this.attachAddress(allAddressContainer); 25 26 let phoneContainers = Array.from(document.querySelectorAll("[data-phone]")); 27 for (let container of phoneContainers) { 28 await this.attachPhone(container) 29 } 30 }, 31 32 getAllAddressElements: function (container) { 33 34 let element = (name) => container.querySelectorAll(`[data-address-item="${name}"]`)[0] 35 36 return { 37 search: element("search"), 38 toggle: element("toggle"), 39 container: element("container"), 40 line1: element("line1"), 41 line2: element("line2"), 42 city: element("city"), 43 region: element("region"), 44 postcode: element("postcode"), 45 country: element("country"), 46 } 47 }, 48 49 getAllPhoneElements: function (container) { 50 51 let element = (name) => container.querySelectorAll(`[data-phone-item="${name}"]`)[0] 52 53 return { 54 country: element("country"), 55 phone: element("phone") 56 } 57 }, 58 59 attachAddress: function (containers) { 60 61 if (containers.length === 1) { 62 window.cc_c2a = new clickToAddress({ 63 accessToken: this.apiKey, 64 domMode: 'object', 65 dom: { 66 search: containers[0].search, 67 town: containers[0].city, 68 postcode: containers[0].postcode, 69 county: containers[0].region, 70 country: containers[0].country, 71 line_1: containers[0].search, 72 line_2: containers[0].line2, 73 }, 74 texts: { 75 default_placeholder: this.addressPlaceholder, 76 } 77 }) 78 } 79 else if (containers.length > 1) { 80 var cc_object = new clickToAddress({ 81 accessToken: this.apiKey, 82 domMode: 'object', 83 texts: { 84 default_placeholder: this.addressPlaceholder, 85 } 86 }); 87 for (let elements of containers) { 88 cc_object.attach({ 89 search: elements.search, 90 town: elements.city, 91 postcode: elements.postcode, 92 county: elements.region, 93 country: elements.country, 94 line_1: elements.search, 95 line_2: elements.line2, 96 }); 97 } 98 99 } 100 }, 101 102 attachPhone: async function (container) { 103 104 let elements = this.getAllPhoneElements(container); 105 let countries = await this.getAllCountries(); 106 let matchingPhone = this.findCountryByTel(elements.phone.value, countries); 107 108 await this.populateCountries(elements, countries, matchingPhone) 109 110 let apiEndpoint = "https://api.craftyclicks.co.uk/phone/1.0/validate" 111 112 elements.phone.onblur = async (e) => { 113 114 console.log(elements); 115 116 let valResponse = await fetch(apiEndpoint, { 117 method: "POST", 118 headers: { 119 "Accept": "application/json", 120 "Content-Type": "application/json" 121 }, 122 body: JSON.stringify({ 123 "key": this.apiKey, 124 "country": elements.country.value, 125 "phone_number": elements.phone.value 126 }) 127 }); 128 129 let valData = await valResponse.json(); 130 let svg = null; 131 132 if (valData.result == true) { 133 elements.phone.value = valData.phone_number; 134 svg = this.tickSvg; 135 } else { 136 svg = this.crossSvg; 137 } 138 139 e.target.style.backgroundImage = svg; 140 e.target.style.backgroundRepeat = "no-repeat"; 141 e.target.style.backgroundPosition = "right" 142 } 143 144 }, 145
146 findCountryByTel: function (phoneNumber, countries) { 147 148 let cleanNumber = phoneNumber?.replace(/[\s-]+/, ""); 149 150 if (cleanNumber != null && cleanNumber.startsWith("+")) { 151 152 cleanNumber = cleanNumber.replace("+", ""); 153 var countryCodes = Object.entries(framework.fetchify.countryPhoneCodes).filter(x => x[1].length > 0); 154 155 var phoneMatch = countryCodes.find(x => cleanNumber.startsWith(x[1])); 156 157 if (phoneMatch != null) { 158 return countries.find(x => x.iso_3166_1_alpha_2 == phoneMatch[0]); 159 } 160 } 161 162 return null; 163 }, 164 165 populateCountries: async function (elements, countries, matchingPhone) { 166 167 let countryToElem = (x) => { 168 let elem = document.createElement("option"); 169 170 elem.value = x.code; 171 elem.text = x.country_name 172 173 return elem; 174 } 175 176 countries.forEach(x => elements.country.add(countryToElem(x))); 177 178 if (matchingPhone != null) { 179 elements.country.value = matchingPhone.code; 180 } 181 }, 182 183 getAllCountries: async function() { 184 185 let storageKey = "framework.fetchify.countries"; 186 187 if (sessionStorage[storageKey] != null && sessionStorage[storageKey] != "undefined") { 188 return JSON.parse(sessionStorage[storageKey]); 189 } 190 191 let response = await fetch(`https://api.craftyclicks.co.uk/address/1.1/countries?key=${this.apiKey}`); 192 let json = await response.json(); 193 194 sessionStorage[storageKey] = JSON.stringify(json.countries); 195 196 console.log(json.countries); 197 198 return json.countries; 199 }, 200 201 202}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.