1/* 2International Telephone Input v3.6.1 3https://github.com/Bluefieldscom/intl-tel-input.git 4*/ 5// wrap in UMD - see https://github.com/umdjs/umd/blob/master/jqueryPlugin.js 6(function (factory) { 7 if (typeof define === "function" && define.amd) { 8 define(["jquery"], function ($) { 9 factory($, window, document); 10 }); 11 } 12 else { 13 factory(jQuery, window, document); 14 } 15})(function ($, window, document, undefined) { 16 'use strict'; 17 //Added by:MMK to get path from url 18 var countryList = ['au', 'ca', 'jp-ja', 'hk', 'ie', 'jp', 'cn', 'sg', 'uk']; 19 var pathArray = window.location.pathname.split('/'); 20 var cnty_code = "ie"; 21 if (pathArray[1] !== '' && $.inArray(pathArray[1], countryList) !== -1) { 22 cnty_code = pathArray[1]; 23 } 24 if(cnty_code == "jp-ja"){ 25 cnty_code = "jp"; 26 } 27 var pluginName = "intlTelInput", id = 1, // give each instance it's own id for namespaced event handling 28 country_code = cnty_code === 'uk' ? 'gb': cnty_code, //Added by:MMK to get country code from path array 29 defaults = { 30 // automatically format the number according to the selected country 31 autoFormat: true, 32 // if there is just a dial code in the input: remove it on blur, and re-add it on focus 33 autoHideDialCode: true, 34 // default country 35 defaultCountry: country_code ? country_code : "ie", //Added by:MMK to set country code 36 // don't insert international dial codes 37 nationalMode: true, 38 // number type to use for placeholders 39 numberType: "", 40 // display only these countries 41 onlyCountries: [], 42 // the countries at the top of the list. defaults to united states and united kingdom 43 preferredCountries: [ "au", "ca", "hk" , "ie" ,"jp" ,"cn","sg", "gb" ], //Added by:MMK to list mmk countries first 44 // make the dropdown the same width as the input 45 responsiveDropdown: false, 46 // specify the path to the libphonenumber script to enable validation/formatting 47 utilsScript: "" 48 }, keys = { 49 UP: 38, 50 DOWN: 40, 51 ENTER: 13, 52 ESC: 27, 53 PLUS: 43, 54 A: 65, 55 Z: 90, 56 ZERO: 48, 57 NINE: 57, 58 SPACE: 32, 59 BSPACE: 8, 60 DEL: 46, 61 CTRL: 17, 62 CMD1: 91, 63 // Chrome 64 CMD2: 224 65 }, windowLoaded = false; 66 // keep track of if the window.load event has fired as impossible to check after the fact 67 $(window).on('load', function() { 68 windowLoaded = true; 69 }); 70 function Plugin(element, options) { 71 this.element = element; 72 this.options = $.extend({}, defaults, options); 73 this._defaults = defaults; 74 // event namespace 75 this.ns = "." + pluginName + id++; 76 // Chrome, FF, Safari, IE9+ 77 this.isGoodBrowser = Boolean(element.setSelectionRange); 78 this.hadInitialPlaceholder = Boolean($(element).attr("placeholder")); 79 this._name = pluginName; 80 this.init(); 81 } 82 Plugin.prototype = { 83 init: function() { 84 var that = this; 85 // if defaultCountry is set to "auto", we must do a lookup first 86 if (this.options.defaultCountry == "auto") { 87 $.get("http://ipinfo.io", function(response) { 88 that.options.defaultCountry = response && response.country ? response.country.toLowerCase() : ""; 89 that.ready(); 90 }, "jsonp"); 91 } else { 92 this.ready(); 93 } 94 }, 95 ready: function() { 96 // if in nationalMode, disable options relating to dial codes 97 if (this.options.nationalMode) { 98 this.options.autoHideDialCode = false; 99 } 100 // IE Mobile and Chrome for Android have issues with key events (see issues 56 and 68) which make autoFormat impossible 101 if (navigator.userAgent.match(/IEMobile/i) || navigator.userAgent.match(/Android/i) && navigator.userAgent.match(/Chrome/i)) { 102 this.options.autoFormat = false;
103 } 104 // auto enable responsiveDropdown mode on small screens (dropdown is currently set to 430px in CSS) 105 if (window.innerWidth < 500) { 106 this.options.responsiveDropdown = true; 107 } 108 // process all the data: onlyCounties, preferredCountries, defaultCountry etc 109 this._processCountryData(); 110 // generate the markup 111 this._generateMarkup(); 112 // set the initial state of the input value and the selected flag 113 this._setInitialState(); 114 // start all of the event listeners: autoHideDialCode, input keydown, selectedFlag click 115 this._initListeners(); 116 }, 117 /******************** 118 * PRIVATE METHODS 119 ********************/ 120 // prepare all of the country data, including onlyCountries, preferredCountries and 121 // defaultCountry options 122 _processCountryData: function() { 123 // set the instances country data objects 124 this._setInstanceCountryData(); 125 // set the preferredCountries property 126 this._setPreferredCountries(); 127 }, 128 // add a country code to this.countryCodes 129 _addCountryCode: function(iso2, dialCode, priority) { 130 if (!(dialCode in this.countryCodes)) { 131 this.countryCodes[dialCode] = []; 132 } 133 var index = priority || 0; 134 this.countryCodes[dialCode][index] = iso2; 135 }, 136 // process onlyCountries array if present, and generate the countryCodes map 137 _setInstanceCountryData: function() { 138 var i; 139 // process onlyCountries option 140 if (this.options.onlyCountries.length) { 141 this.countries = []; 142 for (i = 0; i < this.options.onlyCountries.length; i++) { 143 var countryData = this._getCountryData(this.options.onlyCountries[i], true, false); 144 if (countryData) { 145 this.countries.push(countryData); 146 } 147 } 148 } else { 149 this.countries = allCountries; 150 } 151 // generate countryCodes map 152 this.countryCodes = {}; 153 for (i = 0; i < this.countries.length; i++) { 154 var c = this.countries[i]; 155 this._addCountryCode(c.iso2, c.dialCode, c.priority); 156 // area codes 157 if (c.areaCodes) { 158 for (var j = 0; j < c.areaCodes.length; j++) { 159 // full dial code is country code + dial code 160 this._addCountryCode(c.iso2, c.dialCode + c.areaCodes[j]); 161 } 162 } 163 } 164 }, 165 // process preferred countries - iterate through the preferences, 166 // fetching the country data for each one 167 _setPreferredCountries: function() { 168 this.preferredCountries = []; 169 for (var i = 0; i < this.options.preferredCountries.length; i++) { 170 var countryCode = this.options.preferredCountries[i], countryData = this._getCountryData(countryCode, false, true); 171 if (countryData) { 172 this.preferredCountries.push(countryData); 173 } 174 } 175 }, 176 // generate all of the markup for the plugin: the selected flag overlay, and the dropdown 177 _generateMarkup: function() { 178 // telephone input 179 this.telInput = $(this.element); 180 // containers (mostly for positioning) 181 this.telInput.wrap($("<div>", { 182 "class": "intl-tel-input" 183 })); 184 var flagsContainer = $("<div>", { 185 "class": "flag-dropdown" 186 }).insertAfter(this.telInput); 187 // currently selected flag (displayed to left of input) 188 var selectedFlag = $("<div>", { 189 "class": "selected-flag" 190 }).appendTo(flagsContainer); 191 this.selectedFlagInner = $("<div>", { 192 "class": "flag" 193 }).appendTo(selectedFlag); 194 // CSS triangle 195 $("<div>", { 196 "class": "arrow" 197 }).appendTo(this.selectedFlagInner); 198 // country list contains: preferred countries, then divider, then all countries 199 this.countryList = $("<ul>", { 200 "class": "country-list v-hide" 201 }).appendTo(flagsContainer); 202 if (this.preferredCountries.length) { 203 this._appendListItems(this.preferredCountries, "preferred"); 204 $("<li>", { 205 "class": "divider" 206 }).appendTo(this.countryList); 207 } 208 this._appendListItems(this.countries, ""); 209 // now we can grab the dropdown height, and hide it properly 210 this.dropdownHeight = this.countryList.outerHeight(); 211 this.countryList.removeClass("v-hide").addClass("hide"); 212 // and set the width 213 if (this.options.responsiveDropdown) { 214 this.countryList.outerWidth(this.telInput.outerWidth()); 215 } 216 // this is useful in lots of places 217 this.countryListItems = this.countryList.children(".country"); 218 }, 219 // add a country <li> to the countryList <ul> container 220 _appendListItems: function(countries, className) { 221 // we create so many DOM elements, I decided it was faster to build a temp string 222 // and then add everything to the DOM in one go at the end 223 var tmp = ""; 224 // for each country 225 for (var i = 0; i < countries.length; i++) { 226 var c = countries[i]; 227 // open the list item 228 tmp += "<li class='country " + className + "' data-dial-code='" + c.dialCode + "' data-country-code='" + c.iso2 + "'>"; 229 // add the flag 230 tmp += "<div class='flag " + c.iso2 + "'></div>"; 231 // and the country name and dial code 232 tmp += "<span class='country-name'>" + c.name + "</span>"; 233 tmp += "<span class='dial-code'>+" + c.dialCode + "</span>"; 234 // close the list item 235 tmp += "</li>"; 236 } 237 this.countryList.append(tmp); 238 }, 239 // set the initial state of the input value and the selected flag 240 _setInitialState: function() { 241 var val = this.telInput.val(); 242 // if there is a number, and it's valid, we can go ahead and set the flag, else fall back to default 243 if (this._getDialCode(val)) { 244 this._updateFlagFromNumber(val); 245 } else { 246 var defaultCountry; 247 // check the defaultCountry option, else fall back to the first in the list 248 if (this.options.defaultCountry) { 249 defaultCountry = this._getCountryData(this.options.defaultCountry, false, false); 250 } else { 251 defaultCountry = this.preferredCountries.length ? this.preferredCountries[0] : this.countries[0]; 252 } 253 this._selectFlag(defaultCountry.iso2); 254 // if empty, insert the default dial code (this function will check !nationalMode and !autoHideDialCode) 255 if (!val) { 256 this._updateDialCode(defaultCountry.dialCode, false); 257 } 258 } 259 // format 260 if (val) { 261 // this won't be run after _updateDialCode as that's only called
261if no val 262 this._updateVal(val, false); 263 } 264 }, 265 // initialise the main event listeners: input keyup, and click selected flag 266 _initListeners: function() { 267 var that = this; 268 this._initKeyListeners(); 269 // autoFormat prevents the change event from firing, so we need to check for changes between focus and blur in order to manually trigger it 270 if (this.options.autoHideDialCode || this.options.autoFormat) { 271 this._initFocusListeners(); 272 } 273 // hack for input nested inside label: clicking the selected-flag to open the dropdown would then automatically trigger a 2nd click on the input which would close it again 274 var label = this.telInput.closest("label"); 275 if (label.length) { 276 label.on("click" + this.ns, function(e) { 277 // if the dropdown is closed, then focus the input, else ignore the click 278 if (that.countryList.hasClass("hide")) { 279 that.telInput.focus(); 280 } else { 281 e.preventDefault(); 282 } 283 }); 284 } 285 // toggle country dropdown on click 286 var selectedFlag = this.selectedFlagInner.parent(); 287 selectedFlag.on("click" + this.ns, function(e) { 288 // only intercept this event if we're opening the dropdown 289 // else let it bubble up to the top ("click-off-to-close" listener) 290 // we cannot just stopPropagation as it may be needed to close another instance 291 if (that.countryList.hasClass("hide") && !that.telInput.prop("disabled")) { 292 that._showDropdown(); 293 } 294 }); 295 // if the user has specified the path to the utils script, fetch it on window.load 296 if (this.options.utilsScript) { 297 // if the plugin is being initialised after the window.load event has already been fired 298 if (windowLoaded) { 299 this.loadUtils(); 300 } else { 301 // wait until the load event so we don't block any other requests e.g. the flags image 302 $(window).on('load', function() { 303 that.loadUtils(); 304 }); 305 } 306 } 307 }, 308 _initKeyListeners: function() { 309 var that = this; 310 if (this.options.autoFormat) { 311 // format number and update flag on keypress 312 // use keypress event as we want to ignore all input except for a select few keys, 313 // but we don't want to ignore the navigation keys like the arrows etc. 314 // NOTE: no point in refactoring this to only bind these listeners on focus/blur because then you would need to have those 2 listeners running the whole time anyway... 315 this.telInput.on("keypress" + this.ns, function(e) { 316 // 32 is space, and after that it's all chars (not meta/nav keys) 317 // this fix is needed for Firefox, which triggers keypress event for some meta/nav keys 318 // Update: also ignore if this is a metaKey e.g. FF and Safari trigger keypress on the v of Ctrl+v 319 if (e.which >= keys.SPACE && !e.metaKey) { 320 e.preventDefault(); 321 // allowed keys are just numeric keys and plus 322 // we must allow plus for the case where the user does select-all and then hits plus to start typing a new number. we could refine this logic to first check that the selection contains a plus, but that won't work in old browsers, and I think it's overkill anyway 323 var isAllowedKey = e.which >= keys.ZERO && e.which <= keys.NINE || e.which == keys.PLUS, input = that.telInput[0], noSelection = that.isGoodBrowser && input.selectionStart == input.selectionEnd, max = that.telInput.attr("maxlength"), // assumes that if max exists, it is >0 324 isBelowMax = max ? that.telInput.val().length < max : true; 325 // first: ensure we don't go over maxlength. we must do this here to prevent adding digits in the middle of the number 326 // still reformat even if not an allowed key as they could by typing a formatting char, but ignore if there's a selection as doesn't make sense to replace selection with illegal char and then immediately remove it 327 if (isBelowMax && (isAllowedKey || noSelection)) { 328 var newChar = isAllowedKey ? String.fromCharCode(e.which) : null; 329 that._handleInputKey(newChar, true); 330 }
331 if (!isAllowedKey) { 332 that.telInput.trigger("invalidkey"); 333 } 334 } 335 }); 336 } 337 // handle keyup event 338 // for autoFormat: we use keyup to catch delete events after the fact 339 this.telInput.on("keyup" + this.ns, function(e) { 340 // the "enter" key event from selecting a dropdown item is triggered here on the input, because the document.keydown handler that initially handles that event triggers a focus on the input, and so the keyup for that same key event gets triggered here. weird, but just make sure we don't bother doing any re-formatting in this case (we've already done preventDefault in the keydown handler, so it won't actually submit the form or anything). 341 if (e.which == keys.ENTER) {} else if (that.options.autoFormat) { 342 var isCtrl = e.which == keys.CTRL || e.which == keys.CMD1 || e.which == keys.CMD2, input = that.telInput[0], // noSelection defaults to false for bad browsers, else would be reformatting on all ctrl keys e.g. select-all/copy 343 noSelection = that.isGoodBrowser && input.selectionStart == input.selectionEnd, // cursorAtEnd defaults to false for bad browsers else they would never get a reformat on delete 344 cursorAtEnd = that.isGoodBrowser && input.selectionStart == that.telInput.val().length; 345 // if delete in the middle: reformat with no suffix (no need to reformat if delete at end) 346 // if backspace: reformat with no suffix (need to reformat if at end to remove any lingering suffix - this is a feature) 347 // if ctrl and no selection (i.e. could have just been a paste): reformat (if cursorAtEnd: add suffix) 348 if (e.which == keys.DEL && !cursorAtEnd || e.which == keys.BSPACE || isCtrl && noSelection) { 349 // important to remember never to add suffix on any delete key as can fuck up in ie8 so you can never delete a formatting char at the end 350 that._handleInputKey(null, isCtrl && cursorAtEnd); 351 } 352 // prevent deleting the plus (if not in nationalMode) 353 if (!that.options.nationalMode) { 354 var val = that.telInput.val(); 355 if (val.substr(0, 1) != "+") { 356 // newCursorPos is current pos + 1 to account for the plus we are about to add 357 var newCursorPos = that.isGoodBrowser ? input.selectionStart + 1 : 0; 358 that.telInput.val("+" + val); 359 if (that.isGoodBrowser) { 360 input.setSelectionRange(newCursorPos, newCursorPos); 361 } 362 } 363 } 364 } else { 365 // if no autoFormat, just update flag 366 that._updateFlagFromNumber(that.telInput.val()); 367 } 368 }); 369 }, 370 // when autoFormat is enabled: handle various key events on the input: the 2 main situations are 1) adding a new number character, which will replace any selection, reformat, and try to preserve the cursor position. and 2) reformatting on backspace, or paste event 371 _handleInputKey: function(newNumericChar, addSuffix) { 372 var val = this.telInput.val(), newCursor = null, cursorAtEnd = false, // raw DOM element 373 input = this.telInput[0]; 374 if (this.isGoodBrowser) { 375 var selectionEnd = input.selectionEnd, originalLen = val.length; 376 cursorAtEnd = selectionEnd == originalLen; 377 // if handling a new number character: insert it in the right place and calculate the new cursor position 378 if (newNumericChar) { 379 // replace any selection they may have made with the new char 380 val = val.substr(0, input.selectionStart) + newNumericChar + val.substring(selectionEnd, originalLen); 381 // if the cursor was not at the end then calculate it's new pos 382 if (!cursorAtEnd) { 383 newCursor = selectionEnd + (val.length - originalLen); 384 } 385 } else { 386 // here we're not handling a new char, we're just doing a re-format, but we still need to maintain the cursor position 387 newCursor = input.selectionStart; 388 } 389 } else if (newNumericChar) { 390 val += newNumericChar; 391 } 392 // update the number and flag 393 this.setNumber(val, addSuffix); 394 // update the cursor position 395 if (this.isGoodBrowser) { 396 // if it was at the end, keep it there 397 if (cursorAtEnd) { 398 newCursor = this.telInput.val().length; 399 } 400 input.setSelectionRange(newCursor, newCursor); 401 } 402 }, 403 // listen for focus and blur 404 _initFocusListeners: function() { 405 var that = this; 406 if (this.options.autoHideDialCode) { 407 // mousedown decides where the cursor goes, so if we're focusing we must preventDefault as we'll be inserting the dial code, and we want the cursor to be at the end no matter where they click 408 this.telInput.on("mousedown" + this.ns, function(e) { 409 if (!that.telInput.is(":focus") && !that.telInput.val()) { 410 e.preventDefault(); 411 // but this also cancels the focus, so we must trigger that manually 412 that.telInput.focus(); 413 } 414 }); 415 } 416 this.telInput.on("focus" + this.ns, function() { 417 var value = that.telInput.val(); 418 // save this to compare on blur 419 that.telInput.data("focusVal", value); 420 if (that.options.autoHideDialCode) { 421 // on focus: if empty, insert the dial code for the currently selected flag 422 if (!value) {
423 that._updateVal("+" + that.selectedCountryData.dialCode, true); 424 // after auto-inserting a dial code, if the first key they hit is '+' then assume they are entering a new number, so remove the dial code. use keypress instead of keydown because keydown gets triggered for the shift key (required to hit the + key), and instead of keyup because that shows the new '+' before removing the old one 425 that.telInput.one("keypress.plus" + that.ns, function(e) { 426 if (e.which == keys.PLUS) { 427 // if autoFormat is enabled, this key event will have already have been handled by another keypress listener (hence we need to add the "+"). if disabled, it will be handled after this by a keyup listener (hence no need to add the "+"). 428 var newVal = that.options.autoFormat ? "+" : ""; 429 that.telInput.val(newVal); 430 } 431 }); 432 // after tabbing in, make sure the cursor is at the end we must use setTimeout to get outside of the focus handler as it seems the selection happens after that 433 setTimeout(function() { 434 var input = that.telInput[0]; 435 if (that.isGoodBrowser) { 436 var len = that.telInput.val().length; 437 input.setSelectionRange(len, len); 438 } 439 }); 440 } 441 } 442 }); 443 this.telInput.on("blur" + this.ns, function() { 444 if (that.options.autoHideDialCode) { 445 // on blur: if just a dial code then remove it 446 var value = that.telInput.val(), startsPlus = value.substr(0, 1) == "+"; 447 if (startsPlus) { 448 var numeric = that._getNumeric(value); 449 // if just a plus, or if just a dial code 450 if (!numeric || that.selectedCountryData.dialCode == numeric) { 451 // that.telInput.val(""); 452 } 453 } 454 // remove the keypress listener we added on focus 455 that.telInput.off("keypress.plus" + that.ns); 456 } 457 // manually trigger change event if value has changed 458 if (that.options.autoFormat && that.telInput.val() != that.telInput.data("focusVal")) { 459 that.telInput.trigger("change"); 460 } 461 }); 462 }, 463 // extract the numeric digits from the given string 464 _getNumeric: function(s) { 465 return s.replace(/\D/g, ""); 466 }, 467 // show the dropdown 468 _showDropdown: function() { 469 this._setDropdownPosition(); 470 // update highlighting and scroll to active list item 471 var activeListItem = this.countryList.children(".active"); 472 this._highlightListItem(activeListItem); 473 // show it 474 this.countryList.removeClass("hide"); 475 this._scrollTo(activeListItem); 476 // bind all the dropdown-related listeners: mouseover, click, click-off, keydown 477 this._bindDropdownListeners(); 478 // update the arrow 479 this.selectedFlagInner.children(".arrow").addClass("up"); 480 }, 481 // decide where to position dropdown (depends on position within viewport, and scroll) 482 _setDropdownPosition: function() { 483 var inputTop = this.telInput.offset().top, windowTop = $(window).scrollTop(), // dropdownFitsBelow = (dropdownBottom < windowBottom) 484 dropdownFitsBelow = inputTop + this.telInput.outerHeight() + this.dropdownHeight < windowTop + $(window).height(), dropdownFitsAbove = inputTop - this.dropdownHeight > windowTop; 485 // dropdownHeight - 1 for border 486 var cssTop = !dropdownFitsBelow && dropdownFitsAbove ? "-" + (this.dropdownHeight - 1) + "px" : ""; 487 this.countryList.css("top", cssTop); 488 }, 489 // we only bind dropdown listeners when the dropdown is open 490 _bindDropdownListeners: function() { 491 var that = this; 492 // when mouse over a list item, just highlight that one 493 // we add the class "highlight", so if they hit "enter" we know
493which one to select 494 this.countryList.on("mouseover" + this.ns, ".country", function(e) { 495 that._highlightListItem($(this)); 496 }); 497 // listen for country selection 498 this.countryList.on("click" + this.ns, ".country", function(e) { 499 that._selectListItem($(this)); 500 }); 501 // click off to close 502 // (except when this initial opening click is bubbling up) 503 // we cannot just stopPropagation as it may be needed to close another instance 504 var isOpening = true; 505 $("html").on("click" + this.ns, function(e) { 506 if (!isOpening) { 507 that._closeDropdown(); 508 } 509 isOpening = false; 510 }); 511 // listen for up/down scrolling, enter to select, or letters to jump to country name. 512 // use keydown as keypress doesn't fire for non-char keys and we want to catch if they 513 // just hit down and hold it to scroll down (no keyup event). 514 // listen on the document because that's where key events are triggered if no input has focus 515 var query = "", queryTimer = null; 516 $(document).on("keydown" + this.ns, function(e) { 517 // prevent down key from scrolling the whole page, 518 // and enter key from submitting a form etc 519 e.preventDefault(); 520 if (e.which == keys.UP || e.which == keys.DOWN) { 521 // up and down to navigate 522 that._handleUpDownKey(e.which); 523 } else if (e.which == keys.ENTER) { 524 // enter to select 525 that._handleEnterKey(); 526 } else if (e.which == keys.ESC) { 527 // esc to close 528 that._closeDropdown(); 529 } else if (e.which >= keys.A && e.which <= keys.Z || e.which == keys.SPACE) { 530 // upper case letters (note: keyup/keydown only return upper case letters) 531 // jump to countries that start with the query string 532 if (queryTimer) { 533 clearTimeout(queryTimer); 534 } 535 query += String.fromCharCode(e.which); 536 that._searchForCountry(query); 537 // if the timer hits 1 second, reset the query 538 queryTimer = setTimeout(function() { 539 query = ""; 540 }, 1e3); 541 } 542 }); 543 }, 544 // highlight the next/prev item in the list (and ensure it is visible) 545 _handleUpDownKey: function(key) { 546 var current = this.countryList.children(".highlight").first(); 547 var next = key == keys.UP ? current.prev() : current.next(); 548 if (next.length) { 549 // skip the divider 550 if (next.hasClass("divider")) { 551 next = key == keys.UP ? next.prev() : next.next(); 552 } 553 this._highlightListItem(next); 554 this._scrollTo(next); 555 } 556 }, 557 // select the currently highlighted item 558 _handleEnterKey: function() { 559 var currentCountry = this.countryList.children(".highlight").first(); 560 if (currentCountry.length) { 561 this._selectListItem(currentCountry); 562 } 563 }, 564 // find the first list item whose name starts with the query string 565 _searchForCountry: function(query) { 566 for (var i = 0; i < this.countries.length; i++) { 567 if (this._startsWith(this.countries[i].name, query)) { 568 var listItem = this.countryList.children("[data-country-code=" + this.countries[i].iso2 + "]").not(".preferred"); 569 // update highlighting and scroll 570 this._highlightListItem(listItem); 571 this._scrollTo(listItem, true); 572 break; 573 } 574 } 575 }, 576 // check if (uppercase) string a starts with string b 577 _startsWith: function(a, b) { 578 return a.substr(0, b.length).toUpperCase() == b; 579 }, 580 // update the input's value to the given val 581 // if autoFormat=true, format it first according to the country-specific formatting rules
582 _updateVal: function(val, addSuffix) { 583 var formatted; 584 if (this.options.autoFormat && window.intlTelInputUtils) { 585 formatted = intlTelInputUtils.formatNumber(val, this.selectedCountryData.iso2, addSuffix); 586 // ensure we don't go over maxlength. we must do this here to truncate any formatting suffix, and also handle paste events 587 var max = this.telInput.attr("maxlength"); 588 if (max && formatted.length > max) { 589 formatted = formatted.substr(0, max); 590 } 591 } else { 592 // no autoFormat, so just insert the original value 593 formatted = val; 594 } 595 this.telInput.val(formatted); 596 }, 597 // check if need to select a new flag based on the given number 598 _updateFlagFromNumber: function(number) { 599 // if we're in nationalMode and we're on US/Canada, make sure the number starts with a +1 so _getDialCode will be able to extract the area code 600 // update: if we don't yet have selectedCountryData, but we're here (trying to update the flag from the number), that means we're initialising the plugin with a number that already has a dial code, so fine to ignore this bit 601 if (this.options.nationalMode && this.selectedCountryData && this.selectedCountryData.dialCode == "1" && number.substr(0, 1) != "+") { 602 number = "+1" + number; 603 } 604 // try and extract valid dial code from input 605 var dialCode = this._getDialCode(number); 606 if (dialCode) { 607 // check if one of the matching countries is already selected 608 var countryCodes = this.countryCodes[this._getNumeric(dialCode)], alreadySelected = false; 609 if (this.selectedCountryData) { 610 for (var i = 0; i < countryCodes.length; i++) { 611 if (countryCodes[i] == this.selectedCountryData.iso2) { 612 alreadySelected = true; 613 } 614 } 615 } 616 // if a matching country is not already selected (or this is an unknown NANP area code): choose the first in the list 617 if (!alreadySelected || this._isUnknownNanp(number, dialCode)) { 618 // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first non-empty index 619 for (var j = 0; j < countryCodes.length; j++) { 620 if (countryCodes[j]) { 621 this._selectFlag(countryCodes[j]); 622 break; 623 } 624 } 625 } 626 } 627 }, 628 // check if the given number contains an unknown area code from the North American Numbering Plan i.e. the only dialCode that could be extracted was +1 but the actual number's length is >=4 629 _isUnknownNanp: function(number, dialCode) { 630 return dialCode == "+1" && this._getNumeric(number).length >= 4; 631 }, 632 // remove highlighting from other list items and highlight the given item 633 _highlightListItem: function(listItem) { 634 this.countryListItems.removeClass("highlight"); 635 listItem.addClass("highlight"); 636 }, 637 // find the country data for the given country code 638 // the ignoreOnlyCountriesOption is only used during init() while parsing the onlyCountries array 639 _getCountryData: function(countryCode, ignoreOnlyCountriesOption, allowFail) { 640 var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries; 641 for (var i = 0; i < countryList.length; i++) { 642 if (countryList[i].iso2 == countryCode) { 643 return countryList[i]; 644 } 645 } 646 if (allowFail) { 647 return null; 648 } else { 649 throw new Error("No country data for '" + countryCode + "'"); 650 } 651 }, 652 // select the given flag, update the placeholder and the active list item 653 _selectFlag: function(countryCode) { 654 // do this first as it will throw an error and stop if c
654ountryCode is invalid 655 this.selectedCountryData = this._getCountryData(countryCode, false, false); 656 // this.selectedFlagInner.attr("class", "flag " + countryCode);//Commntd by:MMK to hide country flag 657 this.selectedFlagInner.text("+" +this.selectedCountryData.dialCode);//Added by:MMK to show country code first 658 // update the selected country's title attribute 659 var title = this.selectedCountryData.name + ": +" + this.selectedCountryData.dialCode; 660 this.selectedFlagInner.parent().attr("title", title); 661 // and the input's placeholder 662 this._updatePlaceholder(); 663 // update the active list item 664 var listItem = this.countryListItems.children(".flag." + countryCode).first().parent(); 665 this.countryListItems.removeClass("active"); 666 listItem.addClass("active"); 667 }, 668 // update the input placeholder to an example number from the currently selected country 669 _updatePlaceholder: function() { 670 if (window.intlTelInputUtils && !this.hadInitialPlaceholder) { 671 var iso2 = this.selectedCountryData.iso2, numberType = this.options.numberType ? intlTelInputUtils.numberType[this.options.numberType] : intlTelInputUtils.numberType.FIXED_LINE, placeholder = intlTelInputUtils.getExampleNumber(iso2, this.options.nationalMode, numberType); 672 this.telInput.attr("placeholder", placeholder); 673 } 674 }, 675 // called when the user selects a list item from the dropdown 676 _selectListItem: function(listItem) { 677 // update selected flag and active list item 678 var countryCode = listItem.attr("data-country-code"); 679 this._selectFlag(countryCode); 680 this._closeDropdown(); 681 this._updateDialCode(listItem.attr("data-dial-code"), true); 682 // always fire the change event as even if nationalMode=true (and we haven't updated the input val), the system as a whole has still changed - see country-sync example. think of it as making a selection from a select element. 683 this.telInput.trigger("change"); 684 // focus the input 685 this.telInput.focus(); 686 }, 687 // close the dropdown and unbind any listeners 688 _closeDropdown: function() { 689 this.countryList.addClass("hide"); 690 // update the arrow 691 this.selectedFlagInner.children(".arrow").removeClass("up"); 692 // unbind key events 693 $(document).off(this.ns); 694 // unbind click-off-to-close 695 $("html").off(this.ns); 696 // unbind hover and click listeners 697 this.countryList.off(this.ns); 698 }, 699 // check if an element is visible within it's container, else scroll until it is 700 _scrollTo: function(element, middle) { 701 var container = this.countryList, containerHeight = container.height(), containerTop = container.offset().top, containerBottom = containerTop + containerHeight, elementHeight = element.outerHeight(), elementTop = element.offset().top, elementBottom = elementTop + elementHeight, newScrollTop = elementTop - containerTop + container.scrollTop(), middleOffset = containerHeight / 2 - elementHeight / 2; 702 if (elementTop < containerTop) { 703 // scroll up 704 if (middle) { 705 newScrollTop -= middleOffset; 706 } 707 container.scrollTop(newScrollTop); 708 } else if (elementBottom > containerBottom) { 709 // scroll down 710 if (middle) { 711 newScrollTop += middleOffset; 712 } 713 var heightDifference = containerHeight - elementHeight; 714 container.scrollTop(newScrollTop - heightDifference); 715 } 716 }, 717 // replace any existing dial code with the new one (if not in nationalMode) 718 // also we need to know if we're focusing for a couple of reasons e.g. if so, we want to add any formatting suffix, also if the input is empty and we're not in nationalMode, then we want to insert the dial code 719 _updateDialCode: function(newDialCode, focusing) { 720 var inputVal = this.telInput.val(), newNumber; 721 // save having to pass this every time 722 newDialCode = "+" + newDialCode; 723 if (this.options.nationalMode && inputVal.substr(0, 1) != "+") { 724 // if nationalMode, we just want to re-format 725 newNumber = inputVal; 726 } else if (inputVal) { 727 // if the previous number contained a valid dial code, replace it 728 // (if more than just a plus character) 729 var prevDialCode = this._getDialCode(inputVal); 730 if (prevDialCode.length > 1) { 731 newNumber = inputVal.replace(prevDialCode, newDialCode); 732 } else { 733 // if the previous number didn't contain a dial code, we should persist it 734 var existingNumber = inputVal.substr(0, 1) != "+" ? String(inputVal).trim() : ""; 735 newNumber = newDialCode + existingNumber; 736 } 737 } else { 738 newNumber = !this.options.autoHideDialCode || focusing ? newDialCode : ""; 739 }
740 this._updateVal(newNumber, focusing); 741 }, 742 // try and extract a valid international dial code from a full telephone number 743 // Note: returns the raw string inc plus character and any whitespace/dots etc 744 _getDialCode: function(number) { 745 var dialCode = ""; 746 // only interested in international numbers (starting with a plus) 747 if (number.charAt(0) == "+") { 748 var numericChars = ""; 749 // iterate over chars 750 for (var i = 0; i < number.length; i++) { 751 var c = number.charAt(i); 752 // if char is number 753 if (/^\d$/.test(c)) { 754 numericChars += c; 755 // if current numericChars make a valid dial code 756 if (this.countryCodes[numericChars]) { 757 // store the actual raw string (useful for matching later) 758 dialCode = number.substr(0, i + 1); 759 } 760 // longest dial code is 4 chars 761 if (numericChars.length == 4) { 762 break; 763 } 764 } 765 } 766 } 767 return dialCode; 768 }, 769 /******************** 770 * PUBLIC METHODS 771 ********************/ 772 // remove plugin 773 destroy: function() { 774 // make sure the dropdown is closed (and unbind listeners) 775 this._closeDropdown(); 776 // key events, and focus/blur events if autoHideDialCode=true 777 this.telInput.off(this.ns); 778 // click event to open dropdown 779 this.selectedFlagInner.parent().off(this.ns); 780 // label click hack 781 this.telInput.closest("label").off(this.ns); 782 // remove markup 783 var container = this.telInput.parent(); 784 container.before(this.telInput).remove(); 785 }, 786 // format the number to E164 787 getCleanNumber: function() { 788 if (window.intlTelInputUtils) { 789 return intlTelInputUtils.formatNumberE164(this.telInput.val(), this.selectedCountryData.iso2); 790 } 791 return ""; 792 }, 793 // get the type of the entered number e.g. landline/mobile 794 getNumberType: function() { 795 if (window.intlTelInputUtils) { 796 return intlTelInputUtils.getNumberType(this.telInput.val(), this.selectedCountryData.iso2); 797 } 798 return -99; 799 }, 800 // get the country data for the currently selected flag 801 getSelectedCountryData: function() { 802 // if this is undefined, the plugin will return it's instance instead, so in that case an empty object makes more sense 803 return this.selectedCountryData || {}; 804 }, 805 // get the validation error 806 getValidationError: function() { 807 if (window.intlTelInputUtils) { 808 return intlTelInputUtils.getValidationError(this.telInput.val(), this.selectedCountryData.iso2); 809 } 810 return -99; 811 }, 812 // validate the input val - assumes the global function isValidNumber (from utilsScript) 813 isValidNumber: function() { 814 var val = String(this.telInput.val()).trim(), countryCode = this.options.nationalMode ? this.selectedCountryData.iso2 : "", // libphonenumber allows alpha chars, but in order to allow that, we'd need a method to retrieve the processed number, with letters replaced with numbers 815 containsAlpha = /[a-zA-Z]/.test(val); 816 if (!containsAlpha && window.intlTelInputUtils) { 817 return intlTelInputUtils.isValidNumber(val, countryCode); 818 } 819 return false; 820 }, 821 // load the utils script 822 loadUtils: function(path) { 823 var utilsScript = path || this.options.utilsScript; 824 if (!$.fn[pluginName].loadedUtilsScript && utilsScript) { 825 // don't do this twice! (don't just check if the global intlTelInputUtils exists as if init plugin multiple times in quick succession, it may not have finished loading yet) 826 $.fn[pluginName].loadedUtilsScript = true; 827 // don't use $.getScript as it prevents caching 828 $.ajax({ 829 url: utilsScript, 830 success: function() { 831 // tell all instances the utils are ready 832 $(".intl-tel-input input").intlTelInput("utilsLoaded"); 833 }, 834 dataType: "script", 835 cache: true 836 }); 837 } 838 }, 839 // update the selected flag, and update the input val accordingly 840 selectCountry: function(countryCode) { 841 // check if already selected 842 if (!this.selectedFlagInner.hasClass(countryCode)) { 843 this._selectFlag(countryCode); 844 this._updateDialCode(this.selectedCountryData.dialCode, false); 845 } 846 }, 847 // set the input value and update the flag 848 setNumber: function(number, addSuffix) { 849 // ensure starts with plus 850 if (!this.options.nationalMode && number.substr(0, 1) != "+") { 851 number = "+" + number; 852 } 853 // we must update the flag first, which updates this.selectedCountryData, which is used later for formatting the number before displaying it 854 this._updateFlagFromNumber(number);
855 this._updateVal(number, addSuffix); 856 }, 857 // this is called when the utils are ready 858 utilsLoaded: function() { 859 // if autoFormat is enabled and there's an initial value in the input, then format it 860 if (this.options.autoFormat && this.telInput.val()) { 861 this._updateVal(this.telInput.val()); 862 } 863 this._updatePlaceholder(); 864 } 865 }; 866 // adapted to allow public functions 867 // using https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/Extending-jQuery-Boilerplate 868 $.fn[pluginName] = function(options) { 869 var args = arguments; 870 // Is the first parameter an object (options), or was omitted, 871 // instantiate a new instance of the plugin. 872 if (options === undefined || typeof options === "object") { 873 return this.each(function() { 874 if (!$.data(this, "plugin_" + pluginName)) { 875 $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 876 } 877 }); 878 } else if (typeof options === "string" && options[0] !== "_" && options !== "init") { 879 // If the first parameter is a string and it doesn't start 880 // with an underscore or "contains" the `init`-function, 881 // treat this as a call to a public method. 882 // Cache the method call to make it possible to return a value 883 var returns; 884 this.each(function() { 885 var instance = $.data(this, "plugin_" + pluginName); 886 // Tests that there's already a plugin-instance 887 // and checks that the requested public method exists 888 if (instance instanceof Plugin && typeof instance[options] === "function") { 889 // Call the method of our plugin instance, 890 // and pass it the supplied arguments. 891 returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1)); 892 } 893 // Allow instances to be destroyed via the 'destroy' method 894 if (options === "destroy") { 895 $.data(this, "plugin_" + pluginName, null); 896 } 897 }); 898 // If the earlier cached method gives a value back return the value, 899 // otherwise return this to preserve chainability. 900 return returns !== undefined ? returns : this; 901 } 902 }; 903 /******************** 904 * STATIC METHODS 905 ********************/ 906 // get the country data object 907 $.fn[pluginName].getCountryData = function() { 908 return allCountries; 909 }; 910 // set the country data object 911 $.fn[pluginName].setCountryData = function(obj) { 912 allCountries = obj; 913 }; 914 // Tell JSHint to ignore this warning: "character may get silently deleted by one or more browsers"
915 // jshint -W100 916 // Array of country objects for the flag dropdown. 917 // Each contains a name, country code (ISO 3166-1 alpha-2) and dial code. 918 // Originally from https://github.com/mledoze/countries 919 // then modified using the following JavaScript (NOW OUT OF DATE): 920 /* 921var result = []; 922_.each(countries, function(c) { 923 // ignore countries without a dial code 924 if (c.callingCode[0].length) { 925 result.push({ 926 // var locals contains country names with localised versions in brackets 927 n: _.findWhere(locals, { 928 countryCode: c.cca2 929 }).name, 930 i: c.cca2.toLowerCase(), 931 d: c.callingCode[0] 932 }); 933 } 934}); 935JSON.stringify(result); 936*/ 937 // then with a couple of manual re-arrangements to be alphabetical 938 // then changed Kazakhstan from +76 to +7 939 // and Vatican City from +379 to +39 (see issue 50) 940 // and Caribean Netherlands from +5997 to +599 941 // and Curacao from +5999 to +599 942 // Removed: à land Islands, Christmas Island, Cocos Islands, Guernsey, Isle of Man, Jersey, Kosovo, Mayotte, Pitcairn Islands, South Georgia, Svalbard, Western Sahara 943 // Update: converted objects to arrays to save bytes! 944 // Update: added "priority" for countries with the same dialCode as others 945 // Update: added array of area codes for countries with the same dialCode as others 946 // So each country array has the following information: 947 // [ 948 // Country name, 949 // iso2 code, 950 // International dial code, 951 // Order (if >1 country with same dial code), 952 // Area codes (if >1 country with same dial code) 953 // ] 954 var allCountries = [ [ "Afghanistan (â«Ø§ÙØºØ§ÙØ³ØªØ§Ùâ¬â)", "af", "93" ], [ "Albania (Shqipëri)", "al", "355" ], [ "Algeria (â«Ø§Ùجزائرâ¬â)", "dz", "213" ], [ "American Samoa", "as", "1684" ], [ "Andorra", "ad", "376" ], [ "Angola", "ao", "244" ], [ "Anguilla", "ai", "1264" ], [ "Antigua and Barbuda", "ag", "1268" ], [ "Argentina", "ar", "54" ], [ "Armenia (ÕÕ¡ÕµÕ¡Õ½Õ¿Õ¡Õ¶)", "am", "374" ], [ "Aruba", "aw", "297" ], [ "Australia", "au", "61" ], [ "Austria (Ãsterreich)", "at", "43" ], [ "Azerbaijan (AzÉrbaycan)", "az", "994" ], [ "Bahamas", "bs", "1242" ], [ "Bahrain (â«Ø§ÙØ¨ØØ±ÙÙâ¬â)", "bh", "973" ], [ "Bangladesh (বাà¦à¦²à¦¾à¦¦à§à¦¶)", "bd", "880" ], [ "Barbados", "bb", "1246" ], [ "Belarus (ÐелаÑÑÑÑ)", "by", "375" ], [ "Belgium (België)", "be", "32" ], [ "Belize", "bz", "501" ], [ "Benin (Bénin)", "bj", "229" ], [ "Bermuda", "bm", "1441" ], [ "Bhutan (འà½à¾²à½´à½)", "bt", "975" ], [ "Bolivia", "bo", "591" ], [ "Bosnia and Herzegovina (ÐоÑна и ХеÑÑеговина)", "ba", "387" ], [ "Botswana", "bw", "267" ], [ "Brazil (Brasil)", "br", "55" ], [ "British Indian Ocean Territory", "io", "246" ], [ "British Virgin Islands", "vg", "1284" ], [ "Brunei", "bn", "673" ], [ "Bulgaria (ÐÑлгаÑиÑ)", "bg", "359" ], [ "Burkina Faso", "bf", "226" ], [ "Burundi (Uburundi)", "bi", "257" ], [ "Cambodia (ááááá»áá¶)", "kh", "855" ], [ "Cameroon (Cameroun)", "cm", "237" ], [ "Canada", "ca", "1", 1, [ "204", "236", "249", "250", "289", "306", "343", "365", "387", "403", "416", "418", "431", "437", "438", "450", "506", "514", "519", "548", "579", "581", "587", "604", "613", "639", "647", "672", "705", "709", "742", "778", "780", "782", "807", "819", "825", "867", "873", "902", "905" ] ], [ "Cape Verde (Kabu Verdi)", "cv", "238" ], [ "Caribbean Netherlands", "bq", "599", 1 ], [ "Cayman Islands", "ky", "1345" ], [ "Central African Republic (République centrafricaine)", "cf", "236" ], [ "Chad (Tchad)", "td", "235" ], [ "Chile", "cl", "56" ], [ "Mainland China (ä¸å½)", "cn", "86" ], [ "Colombia", "co", "57" ], [ "Comoros (â«Ø¬Ø²Ø± اÙÙ٠رâ¬â)", "km", "269" ], [ "Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)", "cd", "243" ], [ "Congo (Republic) (Congo-Brazzaville)", "cg", "242" ], [ "Cook Islands", "ck", "682" ], [ "Costa Rica", "cr", "506" ], [ "Côte dâIvoire", "ci", "225" ], [ "Croatia (Hrvatska)", "hr", "385" ], [ "Cuba", "cu", "53" ], [ "Curaçao", "cw", "599", 0 ], [ "Cyprus (ÎÏÏÏοÏ)", "cy", "357" ], [ "Czech Republic (Äeská republika)", "cz", "420" ], [ "Denmark (Danmark)", "dk", "45" ], [ "Djibouti", "dj", "253" ], [ "Dominica", "dm", "1767" ], [ "Dominican Republic (República Dominicana)", "do", "1", 2, [ "809", "829", "849" ] ], [ "Ecuador", "ec", "593" ], [ "Egypt (â«Ù صرâ¬â)", "eg", "20" ], [ "El Salvador", "sv", "503" ], [ "Equatorial Guinea (Guinea Ecuatorial)", "gq", "240" ], [ "Eritrea", "er", "291" ], [ "Estonia (Eesti)", "ee", "372" ], [ "Ethiopia", "et", "251" ], [ "Falkland Islands (Islas Malvinas)", "fk", "500" ], [ "Faroe Islands (Føroyar)", "fo", "298" ], [ "Fiji", "fj", "679" ], [ "Finland (Suomi)", "fi", "358" ], [ "France", "fr", "33" ], [ "French Guiana (Guyane française)", "gf", "594" ], [ "French Polynesia (Polynésie française)", "pf", "689" ], [ "Gabon", "ga", "241" ], [ "Gambia", "gm", "220" ], [ "Georgia (á¡áá¥áá ááááá)", "ge", "995" ], [ "Germany (Deutschland)", "de", "49" ], [ "Ghana (Gaana)", "gh", "233" ], [ "Gibraltar", "gi", "350" ], [ "Greece (Îλλάδα)", "gr", "30" ], [ "Greenland (Kalaallit Nun
954aat)", "gl", "299" ], [ "Grenada", "gd", "1473" ], [ "Guadeloupe", "gp", "590", 0 ], [ "Guam", "gu", "1671" ], [ "Guatemala", "gt", "502" ], [ "Guinea (Guinée)", "gn", "224" ], [ "Guinea-Bissau (Guiné Bissau)", "gw", "245" ], [ "Guyana", "gy", "592" ], [ "Haiti", "ht", "509" ], [ "Honduras", "hn", "504" ], [ "Hong Kong SAR (馿¸¯)", "hk", "852" ], [ "Hungary (Magyarország)", "hu", "36" ], [ "Iceland (Ãsland)", "is", "354" ], [ "India (à¤à¤¾à¤°à¤¤)", "in", "91" ], [ "Indonesia", "id", "62" ], [ "Iran (â«Ø§ÛراÙâ¬â)", "ir", "98" ], [ "Iraq (â«Ø§ÙعراÙâ¬â)", "iq", "964" ], [ "Ireland", "ie", "353" ], [ "Israel (â«×שר××â¬â)", "il", "972" ], [ "Italy (Italia)", "it", "39", 0 ], [ "Jamaica", "jm", "1876" ], [ "Japan (æ¥æ¬)", "jp", "81" ], [ "Jordan (â«Ø§ÙأردÙâ¬â)", "jo", "962" ], [ "Kazakhstan (ÐÐ°Ð·Ð°Ñ ÑÑан)", "kz", "7", 1 ], [ "Kenya", "ke", "254" ], [ "Kiribati", "ki", "686" ], [ "Kuwait (â«Ø§ÙÙÙÙØªâ¬â)", "kw", "965" ], [ "Kyrgyzstan (ÐÑÑгÑзÑÑан)", "kg", "996" ], [ "Laos (ລາວ)", "la", "856" ], [ "Latvia (Latvija)", "lv", "371" ], [ "Lebanon (â«ÙØ¨ÙØ§Ùâ¬â)", "lb", "961" ], [ "Lesotho", "ls", "266" ], [ "Liberia", "lr", "231" ], [ "Libya (â«ÙÙØ¨Ùاâ¬â)", "ly", "218" ], [ "Liechtenstein", "li", "423" ], [ "Lithuania (Lietuva)", "lt", "370" ], [ "Luxembourg", "lu", "352" ], [ "Macau (æ¾³é)", "mo", "853" ], [ "Macedonia (FYROM) (ÐакедониÑа)", "mk", "389" ], [ "Madagascar (Madagasikara)", "mg", "261" ], [ "Malawi", "mw", "265" ], [ "Malaysia", "my", "60" ], [ "Maldives", "mv", "960" ], [ "Mali", "ml", "223" ], [ "Malta", "mt", "356" ], [ "Marshall Islands", "mh", "692" ], [ "Martinique", "mq", "596" ], [ "Mauritania (â«Ù ÙØ±ÙتاÙÙØ§â¬â)", "mr", "222" ], [ "Mauritius (Moris)", "mu", "230" ], [ "Mexico (México)", "mx", "52" ], [ "Micronesia", "fm", "691" ], [ "Moldova (Republica Moldova)", "md", "373" ], [ "Monaco", "mc", "377" ], [ "Mongolia (Ðонгол)", "mn", "976" ], [ "Montenegro (Crna Gora)", "me", "382" ], [ "Montserrat", "ms", "1664" ], [ "Morocco (â«Ø§Ù٠غربâ¬â)", "ma", "212" ], [ "Mozambique (Moçambique)", "mz", "258" ], [ "Myanmar (Burma) (áá¼ááºáá¬)", "mm", "95" ], [ "Namibia (Namibië)", "na", "264" ], [ "Nauru", "nr", "674" ], [ "Nepal (नà¥à¤ªà¤¾à¤²)", "np", "977" ], [ "Netherlands (Nederland)", "nl", "31" ], [ "New Caledonia (Nouvelle-Calédonie)", "nc", "687" ], [ "New Zealand", "nz", "64" ], [ "Nicaragua", "ni", "505" ], [ "Niger (Nijar)", "ne", "227" ], [ "Nigeria", "ng", "234" ], [ "Niue", "nu", "683" ], [ "Norfolk Island", "nf", "672" ], [ "North Korea (ì¡°ì 민주주ì ì¸ë¯¼ ê³µíêµ)", "kp", "850" ], [ "Northern Mariana Islands", "mp", "1670" ], [ "Norway (Norge)", "no", "47" ], [ "Oman (â«Ø¹Ù٠اÙâ¬â)", "om", "968" ], [ "Pakistan (â«Ù¾Ø§Ú©Ø³ØªØ§Ùâ¬â)", "pk", "92" ], [ "Palau", "pw", "680" ], [ "Palestine (â«ÙÙØ³Ø·ÙÙâ¬â)", "ps", "970" ], [ "Panama (Panamá)", "pa", "507" ], [ "Papua New Guinea", "pg", "675" ], [ "Paraguay", "py", "595" ], [ "Peru (Perú)", "pe", "51" ], [ "Philippines", "ph", "63" ], [ "Poland (Polska)", "pl", "48" ], [ "Portugal", "pt", "351" ], [ "Puerto Rico", "pr", "1", 3, [ "787", "939" ] ], [ "Qatar (â«Ùطرâ¬â)", "qa", "974" ], [ "Réunion (La Réunion)", "re", "262" ], [ "Romania (România)", "ro", "40" ], [ "Russia (РоÑÑиÑ)", "ru", "7", 0 ], [ "Rwanda", "rw", "250" ], [ "Saint Barthélemy (Saint-Barthélemy)", "bl", "590", 1 ], [ "Saint Helena", "sh", "290" ], [ "Saint Kitts and Nevis", "kn", "1869" ], [ "Saint Lucia", "lc", "1758" ], [ "Saint Martin (Saint-Martin (partie française))", "mf", "590", 2 ], [ "Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)", "pm", "508" ], [ "Saint Vincent and the Grenadines", "vc", "1784" ], [ "Samoa", "ws", "685" ], [ "San Marino", "sm", "378" ], [ "São Tomé and PrÃncipe (São Tomé e PrÃncipe)", "st", "239" ], [ "Saudi Arabia (â«Ø§ÙÙ Ù ÙÙØ© Ø§ÙØ¹Ø±Ø¨ÙØ© Ø§ÙØ³Ø¹ÙØ¯ÙØ©â¬â)", "sa", "966" ], [ "Senegal (Sénégal)", "sn", "221" ], [ "Serbia (СÑбиÑа)", "rs", "381" ], [ "Seychelles", "sc", "248" ], [ "Sierra Leone", "sl", "232" ], [ "Singapore", "sg", "65" ], [ "Sint Maarten", "sx", "1721" ], [ "Slovakia (Slovensko)", "sk", "421" ], [ "Slovenia (Slovenija)", "si", "386" ], [ "Solomon Islands", "sb", "677" ], [ "Somalia (Soomaaliya)", "so", "252" ], [ "South Africa", "za", "27" ], [ "South Korea (ëí민êµ)", "kr", "82" ], [ "South Sudan (â«Ø¬ÙÙØ¨ Ø§ÙØ³ÙداÙâ¬â)", "ss", "211" ], [ "Spain (España)", "es", "34" ], [ "Sri Lanka (à·à·âර෠ලà¶à¶à·à·)", "lk", "94" ], [ "Sudan (â«Ø§ÙØ³ÙØ¯Ø§Ùâ¬â)", "sd", "249" ], [ "Suriname", "sr", "597" ], [ "Swaziland", "sz", "268" ], [ "Sweden (Sverige)", "se", "46" ], [ "Switzerland (Schweiz)", "ch", "41" ], [ "Syria (â«Ø³ÙØ±ÙØ§â¬â)", "sy", "963" ], [ "Taiwan (å°ç£)", "tw", "886" ], [ "Tajikistan", "tj", "992" ], [ "Tanzania", "tz", "255" ], [ "Thailand (à¹à¸à¸¢)", "th", "66" ], [ "Timor-Leste", "tl", "670" ], [ "Togo", "tg", "228" ], [ "Tokelau", "tk", "690" ], [ "Tonga", "to", "676" ], [ "Trinidad and Tobago", "tt", "1868" ], [ "Tunisia (â«ØªÙÙØ³â¬â)", "tn", "216" ], [ "Turkey (Türkiye)", "tr", "90" ], [ "Turkmenistan", "tm", "993" ], [ "Turks and Caicos Islands", "tc", "1649" ], [ "Tuvalu", "tv", "688" ], [ "U.S. Virgin Islands", "vi", "1340" ], [ "Uganda", "ug", "256" ], [ "Ukraine (УкÑаÑна)", "ua", "380" ], [ "United Arab Emirates (â«Ø§Ùإ٠ارات Ø§ÙØ¹Ø±Ø¨ÙØ© اÙÙ ØªØØ¯Ø©â¬â)", "ae", "971" ], [ "United Kingdom", "gb", "44" ], [ "United States", "us", "1", 0 ], [ "Uruguay", "uy", "598" ], [ "Uzbekistan (OÊ»zbekiston)", "uz", "998" ], [ "Vanuatu", "vu", "678" ], [ "Vatican City (Città del Vaticano)", "va", "39", 1 ], [ "Venezuela", "ve", "58" ], [ "Vietnam (Viá»t Nam)", "vn", "84" ], [ "Wallis and Futuna", "wf", "681" ], [ "Yemen (â«Ø§ÙÙÙ Ùâ¬â)", "ye", "967" ], [ "Zambia", "zm", "260" ], [ "Zimbabwe", "zw", "263" ] ]; 955 // loop over all of the countries above 956 for (var i = 0; i < allCountries.length; i++) { 957 var c = allCountries[i]; 958 allCountries[i] = { 959 name: c[0], 960 iso2: c[1], 961 dialCode: c[2], 962 priority: c[3] || 0, 963 areaCodes: c[4] || null 964 }; 965 } 966});
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.