PageSourceSearch

https://www.lbs.edu.ng/wp-content/plugins/country-dropdown-for-con…/asset/js/countrySelect.js?ver=2.0

js lbs.edu.ng collected 2026-09-24 09:40:54 UTC 36,634 bytes, 1,404 lines download raw bytes

vendor: 36,634 bytes, lines 1-1404
1// wrap in UMD - see https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
2(function(factory) {
3	if (typeof define === "function" && define.amd) {
4		define([ "jquery" ], function($) {
5			factory($, window, document);
6		});
7	} else if (typeof module === "object" && module.exports) {
8		module.exports = factory(require("jquery"), window, document);
9	} else {
10		factory(jQuery, window, document);
11	}
12})(function($, window, document, undefined) {
13	"use strict";
14	var pluginName = "countrySelect", id = 1, // give each instance its own ID for namespaced event handling
15	defaults = {
16		// Default country
17		defaultCountry: "",
18		// Position the selected flag inside or outside of the input
19		defaultStyling: "inside",
20		// don't display these countries
21		excludeCountries: [],
22		// Display only these countries
23		onlyCountries: [],
24		// The countries at the top of the list. Defaults to United States and United Kingdom
25		preferredCountries: [ "us", "gb" ],
26		// localized country names e.g. { 'de': 'Deutschland' }
27		localizedCountries: null,
28		// Set the dropdown's width to be the same as the input. This is automatically enabled for small screens.
29		responsiveDropdown: ($(window).width() < 768 ? true : false),
30	}, keys = {
31		UP: 38,
32		DOWN: 40,
33		ENTER: 13,
34		ESC: 27,
35		BACKSPACE: 8,
36		PLUS: 43,
37		SPACE: 32,
38		A: 65,
39		Z: 90
40	}, windowLoaded = false;
41	// keep track of if the window.load event has fired as impossible to check after the fact
42	$(window).on('load', function() {
43		windowLoaded = true;
44	});
45	function Plugin(element, options) {
46		this.element = element;
47		this.options = $.extend({}, defaults, options);
48		this._defaults = defaults;
49		// event namespace
50		this.ns = "." + pluginName + id++;
51		this._name = pluginName;
52		this.init();
53	}
54	Plugin.prototype = {
55		init: function() {
56			// Process all the data: onlyCountries, excludeCountries, preferredCountries, defaultCountry etc
57			this._processCountryData();
58			// Generate the markup
59			this._generateMarkup();
60			// Set the initial state of the input value and the selected flag
61			this._setInitialState();
62			// Start all of the event listeners: input keyup, selectedFlag click
63			this._initListeners();
64			// Return this when the auto country is resolved.
65			this.autoCountryDeferred = new $.Deferred();
66			// Get auto country.
67			this._initAutoCountry();
68			// Keep track as the user types
69		        this.typedLetters = "";
70
71			return this.autoCountryDeferred;
72		},
73		/********************
74		 *  PRIVATE METHODS
75		 ********************/
76		// prepare all of the country data, including onlyCountries, excludeCountries, preferredCountries and
77		// defaultCountry options
78		_processCountryData: function() {
79			// set the instances country data objects
80			this._setInstanceCountryData();
81			// set the preferredCountries property
82			this._setPreferredCountries();
83			// translate countries according to localizedCountries option
84			if (this.options.localizedCountries) this._translateCountriesByLocale();
85			// sort countries by name
86			if (this.options.onlyCountries.length || this.options.localizedCountries) {
87				this.countries.sort(this._countryNameSort);
88			}
89		},
90		// process onlyCountries array if present
91		_setInstanceCountryData: function() {
92			var that = this;
93			if (this.options.onlyCountries.length) {
94				var newCountries = [];
95				$.each(this.options.onlyCountries, function(i, countryCode) {
96					var countryData = that._getCountryData(countryCode, true);
97					if (countryData) {
98						newCountries.push(countryData);
99					}
100				});
101				this.countries = newCountries;
102			} else if (this.options.excludeCountries.length) {
103                var lowerCaseExcludeCountries = this.options.excludeCountries.map(function(country) {
104                    return country.toLowerCase();
105                });
106                this.countries = allCountries.filter(function(country) {
107                    return lowerCaseExcludeCountries.indexOf(country.iso2) === -1;
108                });
109            } else {
110				this.countries = allCountries;
111			}
112		},
113		// Process preferred countries - iterate through the preferences,
114		// fetching the country data for each one
115		_setPreferredCountries: function() {
116			var that = this;
117			this.preferredCountries = [];
118			$.each(this.options.preferredCountries, function(i, countryCode) {
119				var countryData = that._getCountryData(countryCode, false);
120				if (countryData) {
121					that.preferredCountries.push(countryData);
122				}
123			});
124		},
125		// Translate Countries by object literal provided on config
126		_translateCountriesByLocale() {
127			for (let i = 0; i < this.countries.length; i++) {
128				const iso = this.countries[i].iso2.toLowerCase();
129				if (this.options.localizedCountries.hasOwnProperty(iso)) {
130					this.countries[i].name = this.options.localizedCountries[iso];
131				}
132			}
133		},
134		// sort by country name
135		_countryNameSort(a, b) {
136			return a.name.localeCompare(b.name);
137		},
138		// generate all of the markup for the plugin: the selected flag overlay, and the dropdown
139		_generateMarkup: function() {
140			// Country input
141			this.countryInput = $(this.element);
142			// containers (mostly for positioning)
143			var mainClass = "country-select";
144			if (this.options.defaultStyling) {
145				mainClass += " " + this.options.defaultStyling;
146			}
147			this.countryInput.wrap($("<div>", {
148				"class": mainClass
149			}));
150			var flagsContainer = $("<div>", {
151				"class": "flag-dropdown"
152			}).insertAfter(this.countryInput);
153			// currently selected flag (displayed to left of input)
154			var selectedFlag = $("<div>", {
155				"class": "selected-flag"
156			}).appendTo(flagsContainer);
157			this.selectedFlagInner = $("<div>", {
158				"class": "flag"
159			}).appendTo(selectedFlag);
160			// CSS triangle
161			$("<div>", {
162				"class": "arrow"
163			}).appendTo(selectedFlag);
164			// country list contains: preferred countries, then divider, then all countries
165			this.countryList = $("<ul>", {
166				"class": "country-list v-hide"
167			}).appendTo(flagsContainer);
168			if (this.preferredCountries.length) {
169				this._appendListItems(this.preferredCountries, "preferred");
170				$("<li>", {
171					"class": "divider"
172				}).appendTo(this.countryList);
173			}
174			this._appendListItems(this.countries, "");
175			// Add the hidden input for the country code
176			this.countryCodeInput = $("#"+this.countryInput.attr("id")+"_code");
177			if (!this.countryCodeInput) {
178				this.countryCodeInput = $('<input type="hidden" id="'+this.countryInput.attr("id")+'_code" name="'+this.countryInput.attr("name")+'_code" value="" />');
179				this.countryCodeInput.insertAfter(this.countryInput);
180			}
181			// now we can grab the dropdown height, and hide it properly
182			this.dropdownHeight = this.countryList.outerHeight();
183			// set the dropdown width according to the input if responsiveDropdown option is present or if it's a small screen
184			if (this.options.responsiveDropdown) {
185				$(window).resize(function() {
186					$('.country-select').each(function() {
187						var dropdownWidth = this.offsetWidth;
188						$(this).find('.country-list').css("width", dropdownWidth + "px");
189					});
190				}).resize();
191			}
192			this.countryList.removeClass("v-hide").addClass("hide");
193			// this is useful in lots of places
194			this.countryListItems = this.countryList.children(".country");
195		},
196		// add a country <li> to the countryList <ul> container
197		_appendListItems: function(countries, className) {
198			// Generate DOM elements as a large temp string, so that there is only
199			// one DOM insert event
200			var tmp = "";
201			// for each country
202			$.each(countries, function(i, c) {
203				// open the list item
204				tmp += '<li class="country ' + className + '" data-country-code="' + c.iso2 + '">';
205				// add the flag
206				tmp += '<div class="flag ' + c.iso2 + '"></div>';
207				// and the country name
208				tmp += '<span class="country-name">' + c.name + '</span>';
209				// close the list item
210				tmp += '</li>';
211			});
212			this.countryList.append(tmp);
213		},
214		// set the initial state of the input value and the selected flag
215		_setInitialState: function() {
216			var flagIsSet = false;
217			// If the input is pre-populated, then just update the selected flag
218			if (this.countryInput.val()) {
219				flagIsSet = this._updateFlagFromInputVal();
220			}
221			// If the country code input is pre-populated, update the name and the selected flag
222			var selectedCode = this.countryCodeInput.val();
223			if (selectedCode) {
224				this.selectCountry(selectedCode);
225			}
226			if (!flagIsSet) {
227				// flag is not set, so set to the default country
228				var defaultCountry;
229				// check the defaultCountry option, else fall back to the first in the list
230				if (this.options.defaultCountry) {
231					defaultCountry = this._getCountryData(this.options.defaultCountry, false);
232					// Did we not find the requested default country?
233					if (!defaultCountry) {
234						defaultCountry = this.preferredCountries.length ? this.preferredCountries[0] : this.countries[0];
235					}
236				} else {
237					defaultCountry = this.preferredCountries.length ? this.preferredCountries[0] : this.countries[0];
238				}
239				this.defaultCountry = defaultCountry.iso2;
240			}
241		},
242		// initialise the main event listeners: input keyup, and click selected flag
243		_initListeners: function() {
244			var that = this;
245			// Update flag on keyup.
246			// Use keyup instead of keypress because we want to update on backspace
247			// and instead of keydown because the value hasn't updated when that
248			// event is fired.
249			// NOTE: better to have this one listener all the time instead of
250			// starting it on focus and stopping it on blur, because then you've
251			// got two listeners (focus and blur)
252			this.countryInput.on("keyup" + this.ns, function() {
253				that._updateFlagFromInputVal();
254			});
255			// toggle country dropdown on click
256			var selectedFlag = this.selectedFlagInner.parent();
257			selectedFlag.on("click" + this.ns, function(e) {
258				// only intercept this event if we're opening the dropdown
259				// else let it bubble up to the top ("click-off-to-close" listener)
260				// we cannot just stopPropagation as it may be needed to close another instance
261				if (that.countryList.hasClass("hide") && !that.countryInput.prop("disabled")) {
262					that._showDropdown();
263				}
264			});
265			// Despite above note, added blur to ensure partially spelled country
266			// with correctly chosen flag is spelled out on blur. Also, correctly
267			// selects flag when field is autofilled
268			this.countryInput.on("blur" + this.ns, function() {
269				if (that.countryInput.val() != that.getSelectedCountryData().name) {
270					that.setCountry(that.countryInput.val());
271				}
272				that.countryInput.val(that.getSelectedCountryData().name);
273			});
274		},
275		_initAutoCountry: function() {
276			if (this.options.initialCountry === "auto") {
277				this._loadAutoCountry();
278			} else {
279				if (this.defaultCountry) {
280					this.selectCountry(this.defaultCountry);
281				}
282				this.autoCountryDeferred.resolve();
283			}
284		},
285		// perform the geo ip lookup
286		_loadAutoCountry: function() {
287			var that = this;
288
289			// 3 options:
290			// 1) already loaded (we're done)
291			// 2) not already started loading (start)
292			// 3) already started loading (do nothing - just wait for loading callback to fire)
293			if ($.fn[pluginName].autoCountry) {
294				this.handleAutoCountry();
295			} else if (!$.fn[pluginName].startedLoadingAutoCountry) {
296				// don't do this twice!
297				$.fn[pluginName].startedLoadingAutoCountry = true;
298
299				if (typeof this.options.geoIpLookup === 'function') {
300					this.options.geoIpLookup(function(countryCode) {
301						$.fn[pluginName].autoCountry = countryCode.toLowerCase();
302						// tell all instances the auto country is ready
303						// TODO: this should just be the current instances
304						// UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight away (e.g. if they have already done the geo ip lookup somewhere else). Using setTimeout means that the current thread of execution will finish before executing this, which allows the plugin to finish initialising.
305						setTimeout(function() {
306							$(".country-select input").countrySelect("handleAutoCountry");
307						});
308					});
309				}
310			}
311		},
312		// Focus input and put the cursor at the end
313		_focus: function() {
314			this.countryInput.focus();
315			var input = this.countryInput[0];
316			// works for Chrome, FF, Safari, IE9+
317			if (input.setSelectionRange) {
318				var len = this.countryInput.val().length;
319				input.setSelectionRange(len, len);
320			}
321		},
322		// Show the dropdown
323		_showDropdown: function() {
324			this._setDropdownPosition();
325			// update highlighting and scroll to active list item
326			var activeListItem = this.countryList.children(".active");
327			this._highlightListItem(activeListItem);
328			// show it
329			this.countryList.removeClass("hide");
330			this._scrollTo(activeListItem);
331			// bind all the dropdown-related listeners: mouseover, click, click-off, keydown
332			this._bindDropdownListeners();
333			// update the arrow
334			this.selectedFlagInner.parent().children(".arrow").addClass("up");
335		},
336		// decide where to position dropdown (depends on position within viewport, and scroll)
337		_setDropdownPosition: function() {
338			var inputTop = this.countryInput.offset().top, windowTop = $(window).scrollTop(),
339			dropdownFitsBelow = inputTop + this.countryInput.outerHeight() + this.dropdownHeight < windowTop + $(window).height(), dropdownFitsAbove = inputTop - this.dropdownHeight > windowTop;
340			// dropdownHeight - 1 for border
341			var cssTop = !dropdownFitsBelow && dropdownFitsAbove ? "-" + (this.dropdownHeight - 1) + "px" : "";
342			this.countryList.css("top", cssTop);
343		},
344		// we only bind dropdown listeners when the dropdown is open
345		_bindDropdownListeners: function() {
346			var that = this;
347			// when mouse over a list item, just highlight that one
348			// we add the class "highlight", so if they hit "enter" we know which one to select
349			this.countryList.on("mouseover" + this.ns, ".country", function(e) {
350				that._highlightListItem($(this));
351			});
352			// listen for country selection
353			this.countryList.on("click" + this.ns, ".country", function(e) {
354				that._selectListItem($(this));
355			});
356			// click off to close
357			// (except when this initial opening click is bubbling up)
358			// we cannot just stopPropagation as it may be needed to close another instance
359			var isOpening = true;
360			$("html").on("click" + this.ns, function(e) {
361				e.preventDefault();
362				if (!isOpening) {
363					that._closeDropdown();
364				}
365				isOpening = false;
366			});
367			// Listen for up/down scrolling, enter to select, or letters to jump to country name.
368			// Use keydown as keypress doesn't fire for non-char keys and we want to catch if they
369			// just hit down and hold it to scroll down (no keyup event).
370			// Listen on the document because that's where key events are triggered if no input has focus
371			$(document).on("keydown" + this.ns, function(e) {
372				// prevent down key from scrolling the whole page,
373				// and enter key from submitting a form etc
374				e.preventDefault();
375				if (e.which == keys.UP || e.which == keys.DOWN) {
376					// up and down to navigate
377					that._handleUpDownKey(e.which);
378				} else if (e.which == keys.ENTER) {
379					// enter to select
380					that._handleEnterKey();
381				} else if (e.which == keys.ESC) {
382					// esc to close
383					that._closeDropdown();
384				} else if (e.which >= keys.A && e.which <= keys.Z || e.which === keys.SPACE) {
385					that.typedLetters += String.fromCharCode(e.which);
386					that._filterCountries(that.typedLetters);
387				} else if (e.which === keys.BACKSPACE) {
388					that.typedLetters = that.typedLetters.slice(0, -1);
389					that._filterCountries(that.typedLetters);
390				}
391			});
392		},
393		// Highlight the next/prev item in the list (and ensure it is visible)
394		_handleUpDownKey: function(key) {
395			var current = this.countryList.children(".highlight").first();
396			var next = key == keys.UP ? current.prev() : current.next();
397			if (next.length) {
398				// skip the divider
399				if (next.hasClass("divider")) {
400					next = key == keys.UP ? next.prev() : next.next();
401				}
402				this._highlightListItem(next);
403				this._scrollTo(next);
404			}
405		},
406		// select the currently highlighted item
407		_handleEnterKey: function() {
408			var currentCountry = this.countryList.children(".highlight").first();
409			if (currentCountry.length) {
410				this._selectListItem(currentCountry);
411			}
412		},
413		_filterCountries: function(letters) {
414			var countries = this.countryListItems.filter(function() {
415				return $(this).text().toUpperCase().indexOf(letters) === 0 && !$(this).hasClass("preferred");
416			});
417			if (countries.length) {
418				// if one is already highlighted, then we want the next one
419				var highlightedCountry = countries.filter(".highlight").first(), listItem;
420				if (highlightedCountry && highlightedCountry.next() && highlightedCountry.next().text().toUpperCase().indexOf(letters) === 0) {
421					listItem = highlightedCountry.next();
422				} else {
423					listItem = countries.first();
424				}
425				// update highlighting and scroll
426				this._highlightListItem(listItem);
427				this._scrollTo(listItem);
428			}
429		},
430		// Update the selected flag using the input's current value
431		_updateFlagFromInputVal: function() {
432			var that = this;
433			// try and extract valid country from input
434			var value = this.countryInput.val().replace(/(?=[() ])/g, '\\');
435			if (value) {
436				var countryCodes = [];
437				var matcher = new RegExp(value, "i");
438				// Check for ISO codes only
439				if(value.length <= 2) {
440					for (var i = 0; i < this.countries.length; i++) {
441						if (this.countries[i].iso2.match(matcher)) {
442							countryCodes.push(this.countries[i].iso2);
443						}
444					}
445				}
446				// If no previous matches / larger than 2 chars, then search country name
447				if(countryCodes.length == 0) {
448					for (var i = 0; i < this.countries.length; i++) {
449						if (this.countries[i].name.match(matcher)) {
450							countryCodes.push(this.countries[i].iso2);
451						}
452					}
453				}
454				// Check if one of the matching countries is already selected
455				var alreadySelected = false;
456				$.each(countryCodes, function(i, c) {
457					if (that.selectedFlagInner.hasClass(c)) {
458						alreadySelected = true;
459					}
460				});
461				if (!alreadySelected) {
462					this._selectFlag(countryCodes[0]);
463					this.countryCodeInput.val(countryCodes[0]).trigger("change");
464				}
465				// Matching country found
466				return true;
467			}
468			// No match found
469			return false;
470		},
471		// remove highlighting from other list items and highlight the given item
472		_highlightListItem: function(listItem) {
473			this.countryListItems.removeClass("highlight");
474			listItem.addClass("highlight");
475		},
476		// find the country data for the given country code
477		// the ignoreOnlyCountriesOption is only used during init() while parsing the onlyCountries array
478		_getCountryData: function(countryCode, ignoreOnlyCountriesOption) {
479			var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries;
480			for (var i = 0; i < countryList.length; i++) {
481				if (countryList[i].iso2 == countryCode) {
482					return countryList[i];
483				}
484			}
485			return null;
486		},
487		// update the selected flag and the active list item
488		_selectFlag: function(countryCode) {
489			if (! countryCode) {
490				return false;
491			}
492			this.selectedFlagInner.attr("class", "flag " + countryCode);
493			// update the title attribute
494			var countryData = this._getCountryData(countryCode);
495			this.selectedFlagInner.parent().attr("title", countryData.name);
496			// update the active list item
497			var listItem = this.countryListItems.children(".flag." + countryCode).first().parent();
498			this.countryListItems.removeClass("active");
499			listItem.addClass("active");
500		},
501		// called when the user selects a list item from the dropdown
502		_selectListItem: function(listItem) {
503			// update selected flag and active list item
504			var countryCode = listItem.attr("data-country-code");
505			this._selectFlag(countryCode);
506			this._closeDropdown();
507			// update input value
508			this._updateName(countryCode);
509			this.countryInput.trigger("change");
510			this.countryCodeInput.trigger("change");
511			// focus the input
512			this._focus();
513		},
514		// close the dropdown and unbind any listeners
515		_closeDropdown: function() {
516			this.countryList.addClass("hide");
517			// update the arrow
518			this.selectedFlagInner.parent().children(".arrow").removeClass("up");
519			// unbind event listeners
520			$(document).off("keydown" + this.ns);
521			$("html").off("click" + this.ns);
522			// unbind both hover and click listeners
523			this.countryList.off(this.ns);
524			this.typedLetters = "";
525		},
526		// check if an element is visible within its container, else scroll until it is
527		_scrollTo: function(element) {
528			if (!element || !element.offset()) {
529				return;
530			}
531			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();
532			if (elementTop < containerTop) {
533				// scroll up
534				container.scrollTop(newScrollTop);
535			} else if (elementBottom > containerBottom) {
536				// scroll down
537				var heightDifference = containerHeight - elementHeight;
538				container.scrollTop(newScrollTop - heightDifference);
539			}
540		},
541		// Replace any existing country name with the new one
542		_updateName: function(countryCode) {
543			this.countryCodeInput.val(countryCode).trigger("change");
544			this.countryInput.val(this._getCountryData(countryCode).name);
545		},
546		/********************
547		 *  PUBLIC METHODS
548		 ********************/
549		// this is called when the geoip call returns
550		handleAutoCountry: function() {
551			if (this.options.initialCountry === "auto") {
552				// we must set this even if there is an initial val in the input: in case the initial val is invalid and they delete it - they should see their auto country
553				this.defaultCountry = $.fn[pluginName].autoCountry;
554				// if there's no initial value in the input, then update the flag
555				if (!this.countryInput.val()) {
556					this.selectCountry(this.defaultCountry);
557				}
558				this.autoCountryDeferred.resolve();
559			}
560		},
561		// get the country data for the currently selected flag
562		getSelectedCountryData: function() {
563			// rely on the fact that we only set 2 classes on the selected flag element:
564			// the first is "flag" and the second is the 2-char country code
565			var countryCode = this.selectedFlagInner.attr("class").split(" ")[1];
566			return this._getCountryData(countryCode);
567		},
568		// update the selected flag
569		selectCountry: function(countryCode) {
570			countryCode = countryCode.toLowerCase();
571			// check if already selected
572			if (!this.selectedFlagInner.hasClass(countryCode)) {
573				this._selectFlag(countryCode);
574				this._updateName(countryCode);
575			}
576		},
577		// set the input value and update the flag
578		setCountry: function(country) {
579			this.countryInput.val(country);
580			this._updateFlagFromInputVal();
581		},
582		// remove plugin
583		destroy: function() {
584			// stop listeners
585			this.countryInput.off(this.ns);
586			this.selectedFlagInner.parent().off(this.ns);
587			// remove markup
588			var container = this.countryInput.parent();
589			container.before(this.countryInput).remove();
590		}
591	};
592	// adapted to allow public functions
593	// using https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/Extending-jQuery-Boilerplate
594	$.fn[pluginName] = function(options) {
595		var args = arguments;
596		// Is the first parameter an object (options), or was omitted,
597		// instantiate a new instance of the plugin.
598		if (options === undefined || typeof options === "object") {
599			return this.each(function() {
600				if (!$.data(this, "plugin_" + pluginName)) {
601					$.data(this, "plugin_" + pluginName, new Plugin(this, options));
602				}
603			});
604		} else if (typeof options === "string" && options[0] !== "_" && options !== "init") {
605			// If the first parameter is a string and it doesn't start
606			// with an underscore or "contains" the `init`-function,
607			// treat this as a call to a public method.
608			// Cache the method call to make it possible to return a value
609			var returns;
610			this.each(function() {
611				var instance = $.data(this, "plugin_" + pluginName);
612				// Tests that there's already a plugin-instance
613				// and checks that the requested public method exists
614				if (instance instanceof Plugin && typeof instance[options] === "function") {
615					// Call the method of our plugin instance,
616					// and pass it the supplied arguments.
617					returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
618				}
619				// Allow instances to be destroyed via the 'destroy' method
620				if (options === "destroy") {
621					$.data(this, "plugin_" + pluginName, null);
622				}
623			});
624			// If the earlier cached method gives a value back return the value,
625			// otherwise return this to preserve chainability.
626			return returns !== undefined ? returns : this;
627		}
628	};
629	/********************
630   *  STATIC METHODS
631   ********************/
632	// get the country data object
633	$.fn[pluginName].getCountryData = function() {
634		return allCountries;
635	};
636	// set the country data object
637	$.fn[pluginName].setCountryData = function(obj) {
638		allCountries = obj;
639	};
640	// Tell JSHint to ignore this warning: "character may get silently deleted by one or more browsers"
641	// jshint -W100
642	// Array of country objects for the flag dropdown.
643	// Each contains a name and country code (ISO 3166-1 alpha-2).
644	//
645	// Note: using single char property names to keep filesize down
646	// n = name
647	// i = iso2 (2-char country code)
648	var allCountries = $.each([ {
649		n: "Afghanistan (‫افغانستان‬‎)",
650		i: "af"
651	}, {
652		n: "Åland Islands (Åland)",
653		i: "ax"
654	}, {
655		n: "Albania (Shqipëri)",
656		i: "al"
657	}, {
658		n: "Algeria (‫الجزائر‬‎)",
659		i: "dz"
660	}, {
661		n: "American Samoa",
662		i: "as"
663	}, {
664		n: "Andorra",
665		i: "ad"
666	}, {
667		n: "Angola",
668		i: "ao"
669	}, {
670		n: "Anguilla",
671		i: "ai"
672	}, {
673		n: "Antarctica",
674		i: "aq"
675	}, {
676		n: "Antigua and Barbuda",
677		i: "ag"
678	}, {
679		n: "Argentina",
680		i: "ar"
681	}, {
682		n: "Armenia (Հայաստան)",
683		i: "am"
684	}, {
685		n: "Aruba",
686		i: "aw"
687	}, {
688		n: "Australia",
689		i: "au"
690	}, {
691		n: "Austria (Österreich)",
692		i: "at"
693	}, {
694		n: "Azerbaijan (Azərbaycan)",
695		i: "az"
696	}, {
697		n: "Bahamas",
698		i: "bs"
699	}, {
700		n: "Bahrain (‫البحرين‬‎)",
701		i: "bh"
702	}, {
703		n: "Bangladesh (বাংলাদেশ)",
704		i: "bd"
705	}, {
706		n: "Barbados",
707		i: "bb"
708	}, {
709		n: "Belarus (Беларусь)",
710		i: "by"
711	}, {
712		n: "Belgium (België)",
713		i: "be"
714	}, {
715		n: "Belize",
716		i: "bz"
717	}, {
718		n: "Benin (Bénin)",
719		i: "bj"
720	}, {
721		n: "Bermuda",
722		i: "bm"
723	}, {
724		n: "Bhutan (འབྲུག)",
725		i: "bt"
726	}, {
727		n: "Bolivia",
728		i: "bo"
729	}, {
730		n: "Bosnia and Herzegovina (Босна и Херцеговина)",
731		i: "ba"
732	}, {
733		n: "Botswana",
734		i: "bw"
735	}, {
736		n: "Bouvet Island (Bouvetøya)",
737		i: "bv"
738	}, {
739		n: "Brazil (Brasil)",
740		i: "br"
741	}, {
742		n: "British Indian Ocean Territory",
743		i: "io"
744	}, {
745		n: "British Virgin Islands",
746		i: "vg"
747	}, {
748		n: "Brunei",
749		i: "bn"
750	}, {
751		n: "Bulgaria (България)",
752		i: "bg"
753	}, {
754		n: "Burkina Faso",
755		i: "bf"
756	}, {
757		n: "Burundi (Uburundi)",
758		i: "bi"
759	}, {
760		n: "Cambodia (កម្ពុជា)",
761		i: "kh"
762	}, {
763		n: "Cameroon (Cameroun)",
764		i: "cm"
765	}, {
766		n: "Canada",
767		i: "ca"
768	}, {
769		n: "Cape Verde (Kabu Verdi)",
770		i: "cv"
771	}, {
772		n: "Caribbean Netherlands",
773		i: "bq"
774	}, {
775		n: "Cayman Islands",
776		i: "ky"
777	}, {
778		n: "Central African Republic (République Centrafricaine)",
779		i: "cf"
780	}, {
781		n: "Chad (Tchad)",
782		i: "td"
783	}, {
784		n: "Chile",
785		i: "cl"
786	}, {
787		n: "China (中国)",
788		i: "cn"
789	}, {
790		n: "Christmas Island",
791		i: "cx"
792	}, {
793		n: "Cocos (Keeling) Islands (Kepulauan Cocos (Keeling))",
794		i: "cc"
795	}, {
796		n: "Colombia",
797		i: "co"
798	}, {
799		n: "Comoros (‫جزر القمر‬‎)",
800		i: "km"
801	}, {
802		n: "Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)",
803		i: "cd"
804	}, {
805		n: "Congo (Republic) (Congo-Brazzaville)",
806		i: "cg"
807	}, {
808		n: "Cook Islands",
809		i: "ck"
810	}, {
811		n: "Costa Rica",
812		i: "cr"
813	}, {
814		n: "Côte d’Ivoire",
815		i: "ci"
816	}, {
817		n: "Croatia (Hrvatska)",
818		i: "hr"
819	}, {
820		n: "Cuba",
821		i: "cu"
822	}, {
823		n: "Curaçao",
824		i: "cw"
825	}, {
826		n: "Cyprus (Κύπρος)",
827		i: "cy"
828	}, {
829		n: "Czech Republic (Česká republika)",
830		i: "cz"
831	}, {
832		n: "Denmark (Danmark)",
833		i: "dk"
834	}, {
835		n: "Djibouti",
836		i: "dj"
837	}, {
838		n: "Dominica",
839		i: "dm"
840	}, {
841		n: "Dominican Republic (República Dominicana)",
842		i: "do"
843	}, {
844		n: "Ecuador",
845		i: "ec"
846	}, {
847		n: "Egypt (‫مصر‬‎)",
848		i: "eg"
849	}, {
850		n: "El Salvador",
851		i: "sv"
852	}, {
853		n: "Equatorial Guinea (Guinea Ecuatorial)",
854		i: "gq"
855	}, {
856		n: "Eritrea",
857		i: "er"
858	}, {
859		n: "Estonia (Eesti)",
860		i: "ee"
861	}, {
862		n: "Ethiopia",
863		i: "et"
864	}, {
865		n: "Falkland Islands (Islas Malvinas)",
866		i: "fk"
867	}, {
868		n: "Faroe Islands (Føroyar)",
869		i: "fo"
870	}, {
871		n: "Fiji",
872		i: "fj"
873	}, {
874		n: "Finland (Suomi)",
875		i: "fi"
876	}, {
877		n: "France",
878		i: "fr"
879	}, {
880		n: "French Guiana (Guyane française)",
881		i: "gf"
882	}, {
883		n: "French Polynesia (Polynésie française)",
884		i: "pf"
885	}, {
886		n: "French Southern Territories (Terres australes françaises)",
887		i: "tf"
888	}, {
889		n: "Gabon",
890		i: "ga"
891	}, {
892		n: "Gambia",
893		i: "gm"
894	}, {
895		n: "Georgia (საქართველო)",
896		i: "ge"
897	}, {
898		n: "Germany (Deutschland)",
899		i: "de"
900	}, {
901		n: "Ghana (Gaana)",
902		i: "gh"
903	}, {
904		n: "Gibraltar",
905		i: "gi"
906	}, {
907		n: "Greece (Ελλάδα)",
908		i: "gr"
909	}, {
910		n: "Greenland (Kalaallit Nunaat)",
911		i: "gl"
912	}, {
913		n: "Grenada",
914		i: "gd"
915	}, {
916		n: "Guadeloupe",
917		i: "gp"
918	}, {
919		n: "Guam",
920		i: "gu"
921	}, {
922		n: "Guatemala",
923		i: "gt"
924	}, {
925		n: "Guernsey",
926		i: "gg"
927	}, {
928		n: "Guinea (Guinée)",
929		i: "gn"
930	}, {
931		n: "Guinea-Bissau (Guiné Bissau)",
932		i: "gw"
933	}, {
934		n: "Guyana",
935		i: "gy"
936	}, {
937		n: "Haiti",
938		i: "ht"
939	}, {
940		n: "Heard Island and Mcdonald Islands",
941		i: "hm"
942	}, {
943		n: "Honduras",
944		i: "hn"
945	}, {
946		n: "Hong Kong (香港)",
947		i: "hk"
948	}, {
949		n: "Hungary (Magyarország)",
950		i: "hu"
951	}, {
952		n: "Iceland (Ísland)",
953		i: "is"
954	}, {
955		n: "India (भारत)",
956		i: "in"
957	}, {
958		n: "Indonesia",
959		i: "id"
960	}, {
961		n: "Iran (‫ایران‬‎)",
962		i: "ir"
963	}, {
964		n: "Iraq (‫العراق‬‎)",
965		i: "iq"
966	}, {
967		n: "Ireland",
968		i: "ie"
969	}, {
970		n: "Isle of Man",
971		i: "im"
972	}, {
973		n: "Israel (‫ישראל‬‎)",
974		i: "il"
975	}, {
976		n: "Italy (Italia)",
977		i: "it"
978	}, {
979		n: "Jamaica",
980		i: "jm"
981	}, {
982		n: "Japan (日本)",
983		i: "jp"
984	}, {
985		n: "Jersey",
986		i: "je"
987	}, {
988		n: "Jordan (‫الأردن‬‎)",
989		i: "jo"
990	}, {
991		n: "Kazakhstan (Казахстан)",
992		i: "kz"
993	}, {
994		n: "Kenya",
995		i: "ke"
996	}, {
997		n: "Kiribati",
998		i: "ki"
999	}, {
1000		n: "Kosovo (Kosovë)",
1001		i: "xk"
1002	}, {
1003		n: "Kuwait (‫الكويت‬‎)",
1004		i: "kw"
1005	}, {
1006		n: "Kyrgyzstan (Кыргызстан)",
1007		i: "kg"
1008	}, {
1009		n: "Laos (ລາວ)",
1010		i: "la"
1011	}, {
1012		n: "Latvia (Latvija)",
1013		i: "lv"
1014	}, {
1015		n: "Lebanon (‫لبنان‬‎)",
1016		i: "lb"
1017	}, {
1018		n: "Lesotho",
1019		i: "ls"
1020	}, {
1021		n: "Liberia",
1022		i: "lr"
1023	}, {
1024		n: "Libya (‫ليبيا‬‎)",
1025		i: "ly"
1026	}, {
1027		n: "Liechtenstein",
1028		i: "li"
1029	}, {
1030		n: "Lithuania (Lietuva)",
1031		i: "lt"
1032	}, {
1033		n: "Luxembourg",
1034		i: "lu"
1035	}, {
1036		n: "Macau (澳門)",
1037		i: "mo"
1038	}, {
1039		n: "Macedonia (FYROM) (Македонија)",
1040		i: "mk"
1041	}, {
1042		n: "Madagascar (Madagasikara)",
1043		i: "mg"
1044	}, {
1045		n: "Malawi",
1046		i: "mw"
1047	}, {
1048		n: "Malaysia",
1049		i: "my"
1050	}, {
1051		n: "Maldives",
1052		i: "mv"
1053	}, {
1054		n: "Mali",
1055		i: "ml"
1056	}, {
1057		n: "Malta",
1058		i: "mt"
1059	}, {
1060		n: "Marshall Islands",
1061		i: "mh"
1062	}, {
1063		n: "Martinique",
1064		i: "mq"
1065	}, {
1066		n: "Mauritania (‫موريتانيا‬‎)",
1067		i: "mr"
1068	}, {
1069		n: "Mauritius (Moris)",
1070		i: "mu"
1071	}, {
1072		n: "Mayotte",
1073		i: "yt"
1074	}, {
1075		n: "Mexico (México)",
1076		i: "mx"
1077	}, {
1078		n: "Micronesia",
1079		i: "fm"
1080	}, {
1081		n: "Moldova (Republica Moldova)",
1082		i: "md"
1083	}, {
1084		n: "Monaco",
1085		i: "mc"
1086	}, {
1087		n: "Mongolia (Монгол)",
1088		i: "mn"
1089	}, {
1090		n: "Montenegro (Crna Gora)",
1091		i: "me"
1092	}, {
1093		n: "Montserrat",
1094		i: "ms"
1095	}, {
1096		n: "Morocco (‫المغرب‬‎)",
1097		i: "ma"
1098	}, {
1099		n: "Mozambique (Moçambique)",
1100		i: "mz"
1101	}, {
1102		n: "Myanmar (Burma) (မြန်မာ)",
1103		i: "mm"
1104	}, {
1105		n: "Namibia (Namibië)",
1106		i: "na"
1107	}, {
1108		n: "Nauru",
1109		i: "nr"
1110	}, {
1111		n: "Nepal (नेपाल)",
1112		i: "np"
1113	}, {
1114		n: "Netherlands (Nederland)",
1115		i: "nl"
1116	}, {
1117		n: "New Caledonia (Nouvelle-Calédonie)",
1118		i: "nc"
1119	}, {
1120		n: "New Zealand",
1121		i: "nz"
1122	}, {
1123		n: "Nicaragua",
1124		i: "ni"
1125	}, {
1126		n: "Niger (Nijar)",
1127		i: "ne"
1128	}, {
1129		n: "Nigeria",
1130		i: "ng"
1131	}, {
1132		n: "Niue",
1133		i: "nu"
1134	}, {
1135		n: "Norfolk Island",
1136		i: "nf"
1137	}, {
1138		n: "North Korea (조선 민주주의 인민 공화국)",
1139		i: "kp"
1140	}, {
1141		n: "Northern Mariana Islands",
1142		i: "mp"
1143	}, {
1144		n: "Norway (Norge)",
1145		i: "no"
1146	}, {
1147		n: "Oman (‫عُمان‬‎)",
1148		i: "om"
1149	}, {
1150		n: "Pakistan (‫پاکستان‬‎)",
1151		i: "pk"
1152	}, {
1153		n: "Palau",
1154		i: "pw"
1155	}, {
1156		n: "Palestine (‫فلسطين‬‎)",
1157		i: "ps"
1158	}, {
1159		n: "Panama (Panamá)",
1160		i: "pa"
1161	}, {
1162		n: "Papua New Guinea",
1163		i: "pg"
1164	}, {
1165		n: "Paraguay",
1166		i: "py"
1167	}, {
1168		n: "Peru (Perú)",
1169		i: "pe"
1170	}, {
1171		n: "Philippines",
1172		i: "ph"
1173	}, {
1174		n: "Pitcairn Islands",
1175		i: "pn"
1176	}, {
1177		n: "Poland (Polska)",
1178		i: "pl"
1179	}, {
1180		n: "Portugal",
1181		i: "pt"
1182	}, {
1183		n: "Puerto Rico",
1184		i: "pr"
1185	}, {
1186		n: "Qatar (‫قطر‬‎)",
1187		i: "qa"
1188	}, {
1189		n: "Réunion (La Réunion)",
1190		i: "re"
1191	}, {
1192		n: "Romania (România)",
1193		i: "ro"
1194	}, {
1195		n: "Russia (Россия)",
1196		i: "ru"
1197	}, {
1198		n: "Rwanda",
1199		i: "rw"
1200	}, {
1201		n: "Saint Barthélemy (Saint-Barthélemy)",
1202		i: "bl"
1203	}, {
1204		n: "Saint Helena",
1205		i: "sh"
1206	}, {
1207		n: "Saint Kitts and Nevis",
1208		i: "kn"
1209	}, {
1210		n: "Saint Lucia",
1211		i: "lc"
1212	}, {
1213		n: "Saint Martin (Saint-Martin (partie française))",
1214		i: "mf"
1215	}, {
1216		n: "Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)",
1217		i: "pm"
1218	}, {
1219		n: "Saint Vincent and the Grenadines",
1220		i: "vc"
1221	}, {
1222		n: "Samoa",
1223		i: "ws"
1224	}, {
1225		n: "San Marino",
1226		i: "sm"
1227	}, {
1228		n: "São Tomé and Príncipe (São Tomé e Príncipe)",
1229		i: "st"
1230	}, {
1231		n: "Saudi Arabia (‫المملكة العربية السعودية‬‎)",
1232		i: "sa"
1233	}, {
1234		n: "Senegal (Sénégal)",
1235		i: "sn"
1236	}, {
1237		n: "Serbia (Србија)",
1238		i: "rs"
1239	}, {
1240		n: "Seychelles",
1241		i: "sc"
1242	}, {
1243		n: "Sierra Leone",
1244		i: "sl"
1245	}, {
1246		n: "Singapore",
1247		i: "sg"
1248	}, {
1249		n: "Sint Maarten",
1250		i: "sx"
1251	}, {
1252		n: "Slovakia (Slovensko)",
1253		i: "sk"
1254	}, {
1255		n: "Slovenia (Slovenija)",
1256		i: "si"
1257	}, {
1258		n: "Solomon Islands",
1259		i: "sb"
1260	}, {
1261		n: "Somalia (Soomaaliya)",
1262		i: "so"
1263	}, {
1264		n: "South Africa",
1265		i: "za"
1266	}, {
1267		n: "South Georgia & South Sandwich Islands",
1268		i: "gs"
1269	}, {
1270		n: "South Korea (대한민국)",
1271		i: "kr"
1272	}, {
1273		n: "South Sudan (‫جنوب السودان‬‎)",
1274		i: "ss"
1275	}, {
1276		n: "Spain (España)",
1277		i: "es"
1278	}, {
1279		n: "Sri Lanka (ශ්‍රී ලංකාව)",
1280		i: "lk"
1281	}, {
1282		n: "Sudan (‫السودان‬‎)",
1283		i: "sd"
1284	}, {
1285		n: "Suriname",
1286		i: "sr"
1287	}, {
1288		n: "Svalbard and Jan Mayen (Svalbard og Jan Mayen)",
1289		i: "sj"
1290	}, {
1291		n: "Swaziland",
1292		i: "sz"
1293	}, {
1294		n: "Sweden (Sverige)",
1295		i: "se"
1296	}, {
1297		n: "Switzerland (Schweiz)",
1298		i: "ch"
1299	}, {
1300		n: "Syria (‫سوريا‬‎)",
1301		i: "sy"
1302	}, {
1303		n: "Taiwan (台灣)",
1304		i: "tw"
1305	}, {
1306		n: "Tajikistan",
1307		i: "tj"
1308	}, {
1309		n: "Tanzania",
1310		i: "tz"
1311	}, {
1312		n: "Thailand (ไทย)",
1313		i: "th"
1314	}, {
1315		n: "Timor-Leste",
1316		i: "tl"
1317	}, {
1318		n: "Togo",
1319		i: "tg"
1320	}, {
1321		n: "Tokelau",
1322		i: "tk"
1323	}, {
1324		n: "Tonga",
1325		i: "to"
1326	}, {
1327		n: "Trinidad and Tobago",
1328		i: "tt"
1329	}, {
1330		n: "Tunisia (‫تونس‬‎)",
1331		i: "tn"
1332	}, {
1333		n: "Turkey (Türkiye)",
1334		i: "tr"
1335	}, {
1336		n: "Turkmenistan",
1337		i: "tm"
1338	}, {
1339		n: "Turks and Caicos Islands",
1340		i: "tc"
1341	}, {
1342		n: "Tuvalu",
1343		i: "tv"
1344	}, {
1345		n: "Uganda",
1346		i: "ug"
1347	}, {
1348		n: "Ukraine (Україна)",
1349		i: "ua"
1350	}, {
1351		n: "United Arab Emirates (‫الإمارات العربية المتحدة‬‎)",
1352		i: "ae"
1353	}, {
1354		n: "United Kingdom",
1355		i: "gb"
1356	}, {
1357		n: "United States",
1358		i: "us"
1359	}, {
1360		n: "U.S. Minor Outlying Islands",
1361		i: "um"
1362	}, {
1363		n: "U.S. Virgin Islands",
1364		i: "vi"
1365	}, {
1366		n: "Uruguay",
1367		i: "uy"
1368	}, {
1369		n: "Uzbekistan (Oʻzbekiston)",
1370		i: "uz"
1371	}, {
1372		n: "Vanuatu",
1373		i: "vu"
1374	}, {
1375		n: "Vatican City (Città del Vaticano)",
1376		i: "va"
1377	}, {
1378		n: "Venezuela",
1379		i: "ve"
1380	}, {
1381		n: "Vietnam (Việt Nam)",
1382		i: "vn"
1383	}, {
1384		n: "Wallis and Futuna",
1385		i: "wf"
1386	}, {
1387		n: "Western Sahara (‫الصحراء الغربية‬‎)",
1388		i: "eh"
1389	}, {
1390		n: "Yemen (‫اليمن‬‎)",
1391		i: "ye"
1392	}, {
1393		n: "Zambia",
1394		i: "zm"
1395	}, {
1396		n: "Zimbabwe",
1397		i: "zw"
1398	} ], function(i, c) {
1399		c.name = c.n;
1400		c.iso2 = c.i;
1401		delete c.n;
1402		delete c.i;
1403	});
1404});

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.