diff options
Diffstat (limited to 'src/lib')
29 files changed, 37420 insertions, 0 deletions
diff --git a/src/lib/basedomain.js b/src/lib/basedomain.js new file mode 100644 index 0000000..32e8768 --- /dev/null +++ b/src/lib/basedomain.js @@ -0,0 +1,319 @@ +/*! + * Parts of original code from ipv6.js <https://github.com/beaugunderson/javascript-ipv6> + * Copyright 2011 Beau Gunderson + * Available under MIT license <http://mths.be/mit> + */ + +/* globals punycode:false */ + +const RE_V4 = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|0x[0-9a-f][0-9a-f]?|0[0-7]{3})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|0x[0-9a-f][0-9a-f]?|0[0-7]{3})$/i; +const RE_V4_HEX = /^0x([0-9a-f]{8})$/i; +const RE_V4_NUMERIC = /^[0-9]+$/; +const RE_V4inV6 = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + +const RE_BAD_CHARACTERS = /([^0-9a-f:])/i; +const RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]$)/i; + +function isIPv4(address) { + if (RE_V4.test(address)) { + return true; + } + if (RE_V4_HEX.test(address)) { + return true; + } + if (RE_V4_NUMERIC.test(address)) { + return true; + } + return false; +} + +function isIPv6(address) { + var a4addon = 0; + var address4 = address.match(RE_V4inV6); + if (address4) { + var temp4 = address4[0].split('.'); + for (var i = 0; i < 4; i++) { + if (/^0[0-9]+/.test(temp4[i])) { + return false; + } + } + address = address.replace(RE_V4inV6, ''); + if (/[0-9]$/.test(address)) { + return false; + } + + address = address + temp4.join(':'); + a4addon = 2; + } + + if (RE_BAD_CHARACTERS.test(address)) { + return false; + } + + if (RE_BAD_ADDRESS.test(address)) { + return false; + } + + function count(string, substring) { + return (string.length - string.replace(new RegExp(substring,"g"), '').length) / substring.length; + } + + var halves = count(address, '::'); + if (halves == 1 && count(address, ':') <= 6 + 2 + a4addon) { + return true; + } + if (halves == 0 && count(address, ':') == 7 + a4addon) { + return true; + } + return false; +} + +/** + * Returns base domain for specified host based on Public Suffix List. + * @param {String} hostname The name of the host to get the base domain for + */ +function getBaseDomain(/**String*/ hostname) /**String*/ { + // remove trailing dot(s) + hostname = hostname.replace(/\.+$/, ''); + + // return IP address untouched + if (isIPv6(hostname) || isIPv4(hostname)) { + return hostname; + } + + // decode punycode if exists + if (hostname.indexOf('xn--') >= 0) { + hostname = punycode.toUnicode(hostname); + } + + // search through PSL + var prevDomains = []; + var curDomain = hostname; + var nextDot = curDomain.indexOf('.'); + var tld = 0; + + for (;;) { + var suffix = window.publicSuffixes[curDomain]; + if (typeof suffix != 'undefined') { + tld = suffix; + break; + } + + if (nextDot < 0) { + tld = 1; + break; + } + + prevDomains.push(curDomain.substring(0,nextDot)); + curDomain = curDomain.substring(nextDot+1); + nextDot = curDomain.indexOf('.'); + } + + while (tld > 0 && prevDomains.length > 0) { + curDomain = prevDomains.pop() + '.' + curDomain; + tld--; + } + + return curDomain; +} + +/** + * Converts an IP address to a number. If given input is not a valid IP address + * then 0 is returned. + * @param {String} ip The IP address to convert + * @returns {Integer} + */ +function ipAddressToNumber(ip) { + // Separate IP address into octets, make sure there are four. + var octets = ip.split("."); + if (octets.length !== 4) { + return 0; + } + + var result = 0; + var maxOctetIndex = 3; + for (var i = maxOctetIndex; i >= 0; i--) { + var octet = parseInt(octets[maxOctetIndex - i], 10); + + // If octet is invalid return early, no need to continue. + if (Number.isNaN(octet) || octet < 0 || octet > 255) { + return 0; + } + + // Use bit shifting to store each octet for result. + result |= octet << (i * 8); // eslint-disable-line no-bitwise + } + + // Results of bitwise operations in JS are interpreted as signed + // so use zero-fill right shift to return unsigned number. + return result >>> 0; // eslint-disable-line no-bitwise +} + +/** + * Determines if domain is private, that is localhost or the IP address spaces + * specified by RFC 1918. + * @param {String} domain The domain to check + * @returns {Boolean} + */ +function isPrivateDomain(domain) { // eslint-disable-line no-unused-vars + // Check for localhost match. + if (domain === "localhost") { + return true; + } + + // Check for private IP match. + var ipNumber = ipAddressToNumber(domain); + var privateIpMasks = { + "127.0.0.0": "255.0.0.0", + "10.0.0.0": "255.0.0.0", + "172.16.0.0": "255.240.0.0", + "192.168.0.0": "255.255.0.0", + }; + for (var ip in privateIpMasks) { + // Ignore object properties. + if (!privateIpMasks.hasOwnProperty(ip)) { + continue; + } + + // Compare given IP value to private IP value using bitwise AND. + // Make sure result of AND is unsigned by using zero-fill right shift. + var privateIpNumber = ipAddressToNumber(ip); + var privateMaskNumber = ipAddressToNumber(privateIpMasks[ip]); + if (((ipNumber & privateMaskNumber) >>> 0) === privateIpNumber) { // eslint-disable-line no-bitwise + return true; + } + } + + // Getting here means given host didn't match localhost + // or other private addresses so return false. + return false; +} + +/** + * Checks whether a request is third party for the given document, uses + * information from the public suffix list to determine the effective domain + * name for the document. + * @param {String} requestHost The host of the 3rd party request + * @param {String} documentHost The host of the document + */ +function isThirdParty(/**String*/ requestHost, /**String*/ documentHost) { // eslint-disable-line no-unused-vars + // Remove trailing dots + requestHost = requestHost.replace(/\.+$/, ""); + documentHost = documentHost.replace(/\.+$/, ""); + + // Extract domain name - leave IP addresses unchanged, otherwise leave only base domain + var documentDomain = getBaseDomain(documentHost); + if (requestHost.length > documentDomain.length) { + return (requestHost.substr(requestHost.length - documentDomain.length - 1) != "." + documentDomain); + } else { + return (requestHost != documentDomain); + } +} + +/** + * Extracts host name from a URL. + */ +function extractHostFromURL(/**String*/ url) { // eslint-disable-line no-unused-vars + if (url && extractHostFromURL._lastURL == url) { + return extractHostFromURL._lastDomain; + } + + var host = ""; + try { + host = new URI(url).host; + } catch (e) { + // Keep the empty string for invalid URIs. + } + + extractHostFromURL._lastURL = url; + extractHostFromURL._lastDomain = host; + return host; +} + +/** + * Parses URLs and provides an interface similar to nsIURI in Gecko, see + * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIURI. + * TODO: Make sure the parsing actually works the same as nsStandardURL. + * @constructor + */ +function URI(/**String*/ spec) { + this.spec = spec; + this._schemeEnd = spec.indexOf(":"); + if (this._schemeEnd < 0) { + throw new Error("Invalid URI scheme"); + } + + if (spec.substr(this._schemeEnd + 1, 2) != "//") { + // special case for filesystem, blob URIs + if (this.scheme === "filesystem" || this.scheme === "blob") { + this._schemeEnd = spec.indexOf(":", this._schemeEnd + 1); + if (spec.substr(this._schemeEnd + 1, 2) != "//") { + throw new Error("Unexpected URI structure"); + } + } else { + throw new Error("Unexpected URI structure"); + } + } + + this._hostPortStart = this._schemeEnd + 3; + this._hostPortEnd = spec.indexOf("/", this._hostPortStart); + if (this._hostPortEnd < 0) { + throw new Error("Invalid URI host"); + } + + var authEnd = spec.indexOf("@", this._hostPortStart); + if (authEnd >= 0 && authEnd < this._hostPortEnd) { + this._hostPortStart = authEnd + 1; + } + + this._portStart = -1; + this._hostEnd = spec.indexOf("]", this._hostPortStart + 1); + if (spec[this._hostPortStart] == "[" && this._hostEnd >= 0 && this._hostEnd < this._hostPortEnd) { + // The host is an IPv6 literal + this._hostStart = this._hostPortStart + 1; + if (spec[this._hostEnd + 1] == ":") { + this._portStart = this._hostEnd + 2; + } + } else { + this._hostStart = this._hostPortStart; + this._hostEnd = spec.indexOf(":", this._hostStart); + if (this._hostEnd >= 0 && this._hostEnd < this._hostPortEnd) { + this._portStart = this._hostEnd + 1; + } else { + this._hostEnd = this._hostPortEnd; + } + } +} +URI.prototype = { + spec: null, + get scheme() { + return this.spec.substring(0, this._schemeEnd).toLowerCase(); + }, + get host() { + return this.spec.substring(this._hostStart, this._hostEnd); + }, + get asciiHost() { + var host = this.host; + if (/^[\x00-\x7F]+$/.test(host)) { // eslint-disable-line no-control-regex + return host; + } else { + return punycode.toASCII(host); + } + }, + get hostPort() { + return this.spec.substring(this._hostPortStart, this._hostPortEnd); + }, + get port() { + if (this._portStart < 0) { + return -1; + } else { + return parseInt(this.spec.substring(this._portStart, this._hostPortEnd), 10); + } + }, + get path() { + return this.spec.substring(this._hostPortEnd); + }, + get prePath() { + return this.spec.substring(0, this._hostPortEnd); + } +}; diff --git a/src/lib/i18n.js b/src/lib/i18n.js new file mode 100644 index 0000000..11ef67c --- /dev/null +++ b/src/lib/i18n.js @@ -0,0 +1,151 @@ +/* + * This file is part of Adblock Plus <http://adblockplus.org/>, + * Copyright (C) 2006-2013 Eyeo GmbH + * + * Adblock Plus is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * Adblock Plus is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. + */ + +(function () { + +const LOCALE = chrome.i18n.getMessage('@@ui_locale'), + ON_POPUP = (document.location.pathname == "/skin/popup.html"); + +function localizeFaqLink() { + const LOCALIZED_HOMEPAGE_LOCALES = ['es']; + if (ON_POPUP && LOCALIZED_HOMEPAGE_LOCALES.includes(LOCALE)) { + // update FAQ link to point to localized version + $('#help').prop('href', `https://privacybadger.org/${LOCALE}/#faq`); + } +} + +function setTextDirection() { + function toggle_css_value(selector, property, from, to) { + let $els = $(selector); + $els.each(i => { + let $el = $($els[i]); + if ($el.css(property) === from) { + $el.css(property, to); + } + }); + } + + // https://www.w3.org/International/questions/qa-scripts#examples + // https://developer.chrome.com/webstore/i18n?csw=1#localeTable + // TODO duplicated in src/js/webrequest.js + const RTL_LOCALES = ['ar', 'he', 'fa']; + if (!RTL_LOCALES.includes(LOCALE)) { + return; + } + + // set body text direction + document.body.setAttribute("dir", "rtl"); + + // popup page + if (ON_POPUP) { + // fix floats + ['#privacyBadgerHeader img', '#header-image-stack', '#version'].forEach((selector) => { + toggle_css_value(selector, "float", "left", "right"); + }); + ['#fittslaw', '#options', '#help', '#share', '.overlay_close'].forEach((selector) => { + toggle_css_value(selector, "float", "right", "left"); + }); + + // options page + } else if (document.location.pathname == "/skin/options.html") { + // apply RTL workaround for jQuery UI tabs + // https://zoomicon.wordpress.com/2009/10/15/how-to-use-jqueryui-tabs-in-right-to-left-layout/ + let css = document.createElement("style"); + css.type = "text/css"; + css.textContent = ` +.ui-tabs { direction: rtl; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected, + .ui-tabs .ui-tabs-nav li.ui-state-default { float: right; } +.ui-tabs .ui-tabs-nav li a { float: right; } +`; + document.body.appendChild(css); + + // fix floats + ['.btn-silo', '.btn-silo div', '#allowlist-form > div > div > div'].forEach((selector) => { + toggle_css_value(selector, "float", "left", "right"); + }); + } +} + +/** + * Loads and inserts i18n strings into matching elements. + */ +function loadI18nStrings() { + let els = document.querySelectorAll("[class^='i18n_']"); + + // replace element contents by their class names + for (let el of els) { + const key = el.className.split(/\s/)[0].slice(5), + prop = ("innerHTML" in el ? "innerHTML" : "textContent"); + + // get chrome.i18n placeholders, if any + let placeholders = el.dataset.i18n_contents_placeholders; + placeholders = (placeholders ? placeholders.split("@@") : []); + + // replace contents + el[prop] = chrome.i18n.getMessage(key, placeholders); + } + + // also replace alt, placeholder and title attributes + const ATTRS = [ + 'alt', + 'placeholder', + 'title', + ]; + + // get all the elements that contain one or more of these attributes + els = document.querySelectorAll( + // for example: "[placeholder^='i18n_'], [title^='i18n_']" + "[" + ATTRS.join("^='i18n_'], [") + "^='i18n_']" + ); + + // for each element + for (let el of els) { + // for each attribute + for (let attr_type of ATTRS) { + // get the translation message key + let key = el.getAttribute(attr_type); + + // attribute exists + if (key) { + // remove the i18n_ prefix + key = key.startsWith("i18n_") && key.slice(5); + } + + if (!key) { + continue; + } + + // get chrome.i18n placeholders, if any + // TODO multiple attributes are not supported + let placeholders = el.dataset.i18n_attribute_placeholders; + placeholders = (placeholders ? placeholders.split("@@") : []); + + // update the attribute with the result of a translation lookup by KEY + el.setAttribute(attr_type, chrome.i18n.getMessage(key, placeholders)); + } + } +} + +// Fill in the strings as soon as possible +window.addEventListener("DOMContentLoaded", function () { + localizeFaqLink(); + setTextDirection(); + loadI18nStrings(); +}, true); + +}()); diff --git a/src/lib/options.js b/src/lib/options.js new file mode 100644 index 0000000..8e6bec7 --- /dev/null +++ b/src/lib/options.js @@ -0,0 +1,120 @@ +/* + * This file is part of Privacy Badger <https://www.eff.org/privacybadger> + * Copyright (C) 2018 Electronic Frontier Foundation + * + * Privacy Badger is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * Privacy Badger is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Badger. If not, see <http://www.gnu.org/licenses/>. + */ + +require.scopes.optionslib = (function () { + +/** + * Gets array of encountered origins. + * + * @param {Object} origins The starting set of domains to be filtered. + * @param {String} [filter_text] Text to filter origins with. + * @param {String} [type_filter] Type: user-controlled/DNT-compliant + * @param {String} [status_filter] Status: blocked/cookieblocked/allowed + * @param {Boolean} [show_not_yet_blocked] Whether to show domains your Badger + * hasn't yet learned to block. + * + * @return {Array} The array of origins. + */ +function getOriginsArray(origins, filter_text, type_filter, status_filter, show_not_yet_blocked) { + // Make sure filter_text is lower case for case-insensitive matching. + if (filter_text) { + filter_text = filter_text.toLowerCase(); + } else { + filter_text = ""; + } + + /** + * @param {String} origin The origin to test. + * @return {Boolean} Does the origin pass filters? + */ + function matchesFormFilters(origin) { + const value = origins[origin]; + + if (!show_not_yet_blocked) { + // hide the not-yet-seen-on-enough-sites potential trackers + if (value == "allow") { + return false; + } + } + + // filter by type + if (type_filter) { + if (type_filter == "user") { + if (!value.startsWith("user")) { + return false; + } + } else { + if (value != type_filter) { + return false; + } + } + } + + // filter by status + if (status_filter) { + if (status_filter != value.replace("user_", "") && !( + status_filter == "allow" && value == "dnt" + )) { + return false; + } + } + + // filter by search text + // treat spaces as OR operators + // treat "-" prefixes as NOT operators + let textFilters = filter_text.split(" ").filter(i=>i); // remove empties + + // no text filters, we have a match + if (!textFilters.length) { + return true; + } + + let positiveFilters = textFilters.filter(i => i[0] != "-"), + lorigin = origin.toLowerCase(); + + // if we have any positive filters, and we don't match any, + // don't bother checking negative filters + if (positiveFilters.length) { + let result = positiveFilters.some(text => { + return lorigin.indexOf(text) != -1; + }); + if (!result) { + return false; + } + } + + // we either matched a positive filter, + // or we don't have any positive filters + + // if we match any negative filters, discard the match + return textFilters.every(text => { + if (text[0] != "-" || text == "-") { + return true; + } + return lorigin.indexOf(text.slice(1)) == -1; + }); + } + + // Include only origins that match given filters. + return Object.keys(origins).filter(matchesFormFilters); +} + +return { + getOriginsArray, +}; + +}()); // end of require.scopes diff --git a/src/lib/publicSuffixList.js b/src/lib/publicSuffixList.js new file mode 100644 index 0000000..548b768 --- /dev/null +++ b/src/lib/publicSuffixList.js @@ -0,0 +1,7497 @@ +window.publicSuffixes = { + "0.bg": 1, + "001www.com": 1, + "0e.vc": 1, + "0emm.com": 2, + "1.bg": 1, + "12hp.at": 1, + "12hp.ch": 1, + "12hp.de": 1, + "1337.pictures": 1, + "16-b.it": 1, + "1kapp.com": 1, + "2.bg": 1, + "2000.hu": 1, + "2038.io": 1, + "2ix.at": 1, + "2ix.ch": 1, + "2ix.de": 1, + "3.bg": 1, + "32-b.it": 1, + "3utilities.com": 1, + "4.bg": 1, + "4lima.at": 1, + "4lima.ch": 1, + "4lima.de": 1, + "4u.com": 1, + "5.bg": 1, + "6.bg": 1, + "611.to": 1, + "64-b.it": 1, + "7.bg": 1, + "8.bg": 1, + "9.bg": 1, + "9guacu.br": 1, + "a.bg": 1, + "a.prod.fastly.net": 1, + "a.run.app": 1, + "a.se": 1, + "a.ssl.fastly.net": 1, + "aa.no": 1, + "aaa.pro": 1, + "aarborte.no": 1, + "ab.ca": 1, + "abashiri.hokkaido.jp": 1, + "abc.br": 1, + "abeno.osaka.jp": 1, + "abiko.chiba.jp": 1, + "abira.hokkaido.jp": 1, + "abkhazia.su": 1, + "abo.pa": 1, + "abr.it": 1, + "abruzzo.it": 1, + "abu.yamaguchi.jp": 1, + "ac.ae": 1, + "ac.at": 1, + "ac.be": 1, + "ac.ci": 1, + "ac.cn": 1, + "ac.cr": 1, + "ac.cy": 1, + "ac.fj": 1, + "ac.gn": 1, + "ac.gov.br": 1, + "ac.id": 1, + "ac.il": 1, + "ac.im": 1, + "ac.in": 1, + "ac.ir": 1, + "ac.jp": 1, + "ac.ke": 1, + "ac.kr": 1, + "ac.leg.br": 1, + "ac.lk": 1, + "ac.ls": 1, + "ac.ma": 1, + "ac.me": 1, + "ac.mu": 1, + "ac.mw": 1, + "ac.mz": 1, + "ac.ni": 1, + "ac.nz": 1, + "ac.pa": 1, + "ac.pr": 1, + "ac.rs": 1, + "ac.ru": 1, + "ac.rw": 1, + "ac.se": 1, + "ac.sz": 1, + "ac.th": 1, + "ac.tj": 1, + "ac.tz": 1, + "ac.ug": 1, + "ac.uk": 1, + "ac.vn": 1, + "ac.za": 1, + "ac.zm": 1, + "ac.zw": 1, + "aca.pro": 1, + "academia.bo": 1, + "academy.museum": 1, + "accesscam.org": 1, + "accident-investigation.aero": 1, + "accident-prevention.aero": 1, + "acct.pro": 1, + "achi.nagano.jp": 1, + "act.au": 1, + "act.edu.au": 1, + "ad.jp": 1, + "adachi.tokyo.jp": 1, + "adm.br": 1, + "adobeaemcloud.com": 1, + "adobeaemcloud.net": 1, + "adult.ht": 1, + "adv.br": 1, + "adv.mz": 1, + "advisor.ws": 2, + "adygeya.ru": 1, + "adygeya.su": 1, + "ae.org": 1, + "aejrie.no": 1, + "aero.mv": 1, + "aero.tt": 1, + "aerobatic.aero": 1, + "aeroclub.aero": 1, + "aerodrome.aero": 1, + "aeroport.fr": 1, + "afjord.no": 1, + "africa.com": 1, + "ag.it": 1, + "aga.niigata.jp": 1, + "agano.niigata.jp": 1, + "agdenes.no": 1, + "agematsu.nagano.jp": 1, + "agents.aero": 1, + "agr.br": 1, + "agrar.hu": 1, + "agric.za": 1, + "agriculture.museum": 1, + "agrigento.it": 1, + "agrinet.tn": 1, + "agro.bo": 1, + "agro.pl": 1, + "aguni.okinawa.jp": 1, + "ah.cn": 1, + "ah.no": 1, + "aibetsu.hokkaido.jp": 1, + "aichi.jp": 1, + "aid.pl": 1, + "aikawa.kanagawa.jp": 1, + "ainan.ehime.jp": 1, + "aioi.hyogo.jp": 1, + "aip.ee": 1, + "air-surveillance.aero": 1, + "air-traffic-control.aero": 1, + "air.museum": 1, + "aircraft.aero": 1, + "airguard.museum": 1, + "airline.aero": 1, + "airport.aero": 1, + "airtraffic.aero": 1, + "aisai.aichi.jp": 1, + "aisho.shiga.jp": 1, + "aizubange.fukushima.jp": 1, + "aizumi.tokushima.jp": 1, + "aizumisato.fukushima.jp": 1, + "aizuwakamatsu.fukushima.jp": 1, + "aju.br": 1, + "ak.us": 1, + "akabira.hokkaido.jp": 1, + "akagi.shimane.jp": 1, + "akaiwa.okayama.jp": 1, + "akashi.hyogo.jp": 1, + "aki.kochi.jp": 1, + "akiruno.tokyo.jp": 1, + "akishima.tokyo.jp": 1, + "akita.akita.jp": 1, + "akita.jp": 1, + "akkeshi.hokkaido.jp": 1, + "aknoluokta.no": 1, + "ako.hyogo.jp": 1, + "akrehamn.no": 1, + "aktyubinsk.su": 1, + "akune.kagoshima.jp": 1, + "al.eu.org": 1, + "al.gov.br": 1, + "al.it": 1, + "al.leg.br": 1, + "al.no": 1, + "al.us": 1, + "alabama.museum": 1, + "alaheadju.no": 1, + "aland.fi": 1, + "alaska.museum": 1, + "alces.network": 2, + "alessandria.it": 1, + "alesund.no": 1, + "algard.no": 1, + "algorithmia.com": 2, + "alpha-myqnapcloud.com": 1, + "alpha.bounty-full.com": 1, + "alstahaug.no": 1, + "alt.za": 1, + "alta.no": 1, + "altervista.org": 1, + "alto-adige.it": 1, + "altoadige.it": 1, + "alvdal.no": 1, + "alwaysdata.net": 1, + "am.br": 1, + "am.gov.br": 1, + "am.leg.br": 1, + "ama.aichi.jp": 1, + "ama.shimane.jp": 1, + "amagasaki.hyogo.jp": 1, + "amakusa.kumamoto.jp": 1, + "amami.kagoshima.jp": 1, + "amber.museum": 1, + "ambulance.aero": 1, + "ambulance.museum": 1, + "american.museum": 1, + "americana.museum": 1, + "americanantiques.museum": 1, + "americanart.museum": 1, + "ami.ibaraki.jp": 1, + "amli.no": 1, + "amot.no": 1, + "amsterdam.museum": 1, + "amsw.nl": 1, + "amusement.aero": 1, + "an.it": 1, + "anamizu.ishikawa.jp": 1, + "anan.nagano.jp": 1, + "anan.tokushima.jp": 1, + "anani.br": 1, + "ancona.it": 1, + "and.mom": 1, + "and.museum": 1, + "andasuolo.no": 1, + "andebu.no": 1, + "ando.nara.jp": 1, + "andoy.no": 1, + "andria-barletta-trani.it": 1, + "andria-trani-barletta.it": 1, + "andriabarlettatrani.it": 1, + "andriatranibarletta.it": 1, + "and\u00f8y.no": 1, + "anjo.aichi.jp": 1, + "ann-arbor.mi.us": 1, + "annaka.gunma.jp": 1, + "annefrank.museum": 1, + "anpachi.gifu.jp": 1, + "anthro.museum": 1, + "anthropology.museum": 1, + "antiques.museum": 1, + "ao.it": 1, + "aogaki.hyogo.jp": 1, + "aogashima.tokyo.jp": 1, + "aoki.nagano.jp": 1, + "aomori.aomori.jp": 1, + "aomori.jp": 1, + "aosta-valley.it": 1, + "aosta.it": 1, + "aostavalley.it": 1, + "aoste.it": 1, + "ap-northeast-1.elasticbeanstalk.com": 1, + "ap-northeast-2.elasticbeanstalk.com": 1, + "ap-northeast-3.elasticbeanstalk.com": 1, + "ap-south-1.elasticbeanstalk.com": 1, + "ap-southeast-1.elasticbeanstalk.com": 1, + "ap-southeast-2.elasticbeanstalk.com": 1, + "ap.gov.br": 1, + "ap.gov.pl": 1, + "ap.it": 1, + "ap.leg.br": 1, + "aparecida.br": 1, + "api.stdlib.com": 1, + "apigee.io": 1, + "app.banzaicloud.io": 1, + "app.br": 1, + "app.gp": 1, + "app.lmpm.com": 1, + "app.os.fedoraproject.org": 1, + "app.os.stg.fedoraproject.org": 1, + "app.render.com": 1, + "appchizi.com": 1, + "appengine.flow.ch": 1, + "applicationcloud.io": 1, + "applinzi.com": 1, + "apps.fbsbx.com": 1, + "apps.lair.io": 1, + "appspot.com": 1, + "aprendemas.cl": 1, + "aq.it": 1, + "aquarium.museum": 1, + "aquila.it": 1, + "ar.com": 1, + "ar.it": 1, + "ar.us": 1, + "arai.shizuoka.jp": 1, + "arakawa.saitama.jp": 1, + "arakawa.tokyo.jp": 1, + "arao.kumamoto.jp": 1, + "arboretum.museum": 1, + "archaeological.museum": 1, + "archaeology.museum": 1, + "architecture.museum": 1, + "ardal.no": 1, + "aremark.no": 1, + "arendal.no": 1, + "arezzo.it": 1, + "ariake.saga.jp": 1, + "arida.wakayama.jp": 1, + "aridagawa.wakayama.jp": 1, + "arita.saga.jp": 1, + "arkhangelsk.su": 1, + "armenia.su": 1, + "arna.no": 1, + "arq.br": 1, + "art.br": 1, + "art.do": 1, + "art.dz": 1, + "art.ht": 1, + "art.museum": 1, + "art.pl": 1, + "art.sn": 1, + "artanddesign.museum": 1, + "artcenter.museum": 1, + "artdeco.museum": 1, + "arte.bo": 1, + "arteducation.museum": 1, + "artgallery.museum": 1, + "arts.co": 1, + "arts.museum": 1, + "arts.nf": 1, + "arts.ro": 1, + "arts.ve": 1, + "artsandcrafts.museum": 1, + "arvo.network": 1, + "as.us": 1, + "asago.hyogo.jp": 1, + "asahi.chiba.jp": 1, + "asahi.ibaraki.jp": 1, + "asahi.mie.jp": 1, + "asahi.nagano.jp": 1, + "asahi.toyama.jp": 1, + "asahi.yamagata.jp": 1, + "asahikawa.hokkaido.jp": 1, + "asaka.saitama.jp": 1, + "asakawa.fukushima.jp": 1, + "asakuchi.okayama.jp": 1, + "asaminami.hiroshima.jp": 1, + "ascoli-piceno.it": 1, + "ascolipiceno.it": 1, + "aseral.no": 1, + "ashgabad.su": 1, + "ashibetsu.hokkaido.jp": 1, + "ashikaga.tochigi.jp": 1, + "ashiya.fukuoka.jp": 1, + "ashiya.hyogo.jp": 1, + "ashoro.hokkaido.jp": 1, + "asker.no": 1, + "askim.no": 1, + "askoy.no": 1, + "askvoll.no": 1, + "ask\u00f8y.no": 1, + "asmatart.museum": 1, + "asn.au": 1, + "asn.lv": 1, + "asnes.no": 1, + "aso.kumamoto.jp": 1, + "ass.km": 1, + "assabu.hokkaido.jp": 1, + "assassination.museum": 1, + "assisi.museum": 1, + "assn.lk": 1, + "asso.bj": 1, + "asso.ci": 1, + "asso.dz": 1, + "asso.eu.org": 1, + "asso.fr": 1, + "asso.gp": 1, + "asso.ht": 1, + "asso.km": 1, + "asso.mc": 1, + "asso.nc": 1, + "asso.re": 1, + "association.aero": 1, + "association.museum": 1, + "asti.it": 1, + "astronomy.museum": 1, + "asuke.aichi.jp": 1, + "at-band-camp.net": 1, + "at.eu.org": 1, + "at.it": 1, + "at.md": 1, + "at.vg": 1, + "atami.shizuoka.jp": 1, + "ath.cx": 1, + "atlanta.museum": 1, + "atm.pl": 1, + "ato.br": 1, + "atsugi.kanagawa.jp": 1, + "atsuma.hokkaido.jp": 1, + "au.eu.org": 1, + "audnedaln.no": 1, + "augustow.pl": 1, + "aukra.no": 1, + "aure.no": 1, + "aurland.no": 1, + "aurskog-holand.no": 1, + "aurskog-h\u00f8land.no": 1, + "aus.basketball": 1, + "austevoll.no": 1, + "austin.museum": 1, + "australia.museum": 1, + "austrheim.no": 1, + "author.aero": 1, + "auto.pl": 1, + "automotive.museum": 1, + "av.it": 1, + "av.tr": 1, + "avellino.it": 1, + "averoy.no": 1, + "aver\u00f8y.no": 1, + "aviation.museum": 1, + "avocat.fr": 1, + "avocat.pro": 1, + "avoues.fr": 1, + "awaji.hyogo.jp": 1, + "awdev.ca": 2, + "awsmppl.com": 1, + "axis.museum": 1, + "aya.miyazaki.jp": 1, + "ayabe.kyoto.jp": 1, + "ayagawa.kagawa.jp": 1, + "ayase.kanagawa.jp": 1, + "az.us": 1, + "azerbaijan.su": 1, + "azimuth.network": 1, + "azumino.nagano.jp": 1, + "azure-mobile.net": 1, + "azurecontainer.io": 2, + "azurewebsites.net": 1, + "a\u00e9roport.ci": 1, + "b-data.io": 1, + "b.bg": 1, + "b.br": 1, + "b.se": 1, + "b.ssl.fastly.net": 1, + "ba.gov.br": 1, + "ba.it": 1, + "ba.leg.br": 1, + "babia-gora.pl": 1, + "backplaneapp.io": 1, + "backyards.banzaicloud.io": 2, + "badaddja.no": 1, + "badajoz.museum": 1, + "baghdad.museum": 1, + "bahcavuotna.no": 1, + "bahccavuotna.no": 1, + "bahn.museum": 1, + "baidar.no": 1, + "bajddar.no": 1, + "balashov.su": 1, + "balat.no": 1, + "bale.museum": 1, + "balena-devices.com": 1, + "balestrand.no": 1, + "ballangen.no": 1, + "ballooning.aero": 1, + "balsan-sudtirol.it": 1, + "balsan-suedtirol.it": 1, + "balsan-s\u00fcdtirol.it": 1, + "balsan.it": 1, + "balsfjord.no": 1, + "baltimore.museum": 1, + "bamble.no": 1, + "bandai.fukushima.jp": 1, + "bando.ibaraki.jp": 1, + "banzai.cloud": 2, + "bar.pro": 1, + "bar0.net": 1, + "bar1.net": 1, + "bar2.net": 1, + "barcelona.museum": 1, + "bardu.no": 1, + "bari.it": 1, + "barletta-trani-andria.it": 1, + "barlettatraniandria.it": 1, + "barreau.bj": 1, + "barrel-of-knowledge.info": 1, + "barrell-of-knowledge.info": 1, + "barsy.bg": 1, + "barsy.ca": 1, + "barsy.club": 1, + "barsy.co.uk": 1, + "barsy.de": 1, + "barsy.eu": 1, + "barsy.in": 1, + "barsy.info": 1, + "barsy.io": 1, + "barsy.me": 1, + "barsy.menu": 1, + "barsy.mobi": 1, + "barsy.net": 1, + "barsy.online": 1, + "barsy.org": 1, + "barsy.pro": 1, + "barsy.pub": 1, + "barsy.shop": 1, + "barsy.site": 1, + "barsy.support": 1, + "barsy.uk": 1, + "barsycenter.com": 1, + "barsyonline.co.uk": 1, + "barsyonline.com": 1, + "barueri.br": 1, + "barum.no": 1, + "bas.it": 1, + "baseball.museum": 1, + "basel.museum": 1, + "bashkiria.ru": 1, + "bashkiria.su": 1, + "basicserver.io": 1, + "basilicata.it": 1, + "baths.museum": 1, + "bato.tochigi.jp": 1, + "batsfjord.no": 1, + "bauern.museum": 1, + "bbs.tr": 1, + "bc.ca": 1, + "bc.platform.sh": 1, + "bci.dnstrace.pro": 1, + "bd": 2, + "bd.se": 1, + "be.ax": 1, + "be.eu.org": 1, + "be.gy": 1, + "bearalvahki.no": 1, + "bearalv\u00e1hki.no": 1, + "beardu.no": 1, + "beauxarts.museum": 1, + "bedzin.pl": 1, + "beeldengeluid.museum": 1, + "beep.pl": 1, + "beiarn.no": 1, + "bel.tr": 1, + "belau.pw": 1, + "belem.br": 1, + "bellevue.museum": 1, + "belluno.it": 1, + "benevento.it": 1, + "beppu.oita.jp": 1, + "berg.no": 1, + "bergamo.it": 1, + "bergbau.museum": 1, + "bergen.no": 1, + "berkeley.museum": 1, + "berlevag.no": 1, + "berlev\u00e5g.no": 1, + "berlin.museum": 1, + "bern.museum": 1, + "beskidy.pl": 1, + "beta.bounty-full.com": 1, + "betainabox.com": 1, + "better-than.tv": 1, + "bg.eu.org": 1, + "bg.it": 1, + "bhz.br": 1, + "bi.it": 1, + "bialowieza.pl": 1, + "bialystok.pl": 1, + "bib.br": 1, + "bibai.hokkaido.jp": 1, + "bible.museum": 1, + "biei.hokkaido.jp": 1, + "bielawa.pl": 1, + "biella.it": 1, + "bieszczady.pl": 1, + "bievat.no": 1, + "biev\u00e1t.no": 1, + "bifuka.hokkaido.jp": 1, + "bihoro.hokkaido.jp": 1, + "bilbao.museum": 1, + "bill.museum": 1, + "bindal.no": 1, + "bio.br": 1, + "bip.sh": 1, + "bir.ru": 1, + "biratori.hokkaido.jp": 1, + "birdart.museum": 1, + "birkenes.no": 1, + "birthplace.museum": 1, + "bitbridge.net": 1, + "biz.at": 1, + "biz.az": 1, + "biz.bb": 1, + "biz.cy": 1, + "biz.dk": 1, + "biz.et": 1, + "biz.fj": 1, + "biz.gl": 1, + "biz.id": 1, + "biz.ki": 1, + "biz.ls": 1, + "biz.mv": 1, + "biz.mw": 1, + "biz.ni": 1, + "biz.nr": 1, + "biz.pk": 1, + "biz.pl": 1, + "biz.pr": 1, + "biz.ss": 1, + "biz.tj": 1, + "biz.tr": 1, + "biz.tt": 1, + "biz.ua": 1, + "biz.vn": 1, + "biz.zm": 1, + "bizen.okayama.jp": 1, + "bj.cn": 1, + "bjarkoy.no": 1, + "bjark\u00f8y.no": 1, + "bjerkreim.no": 1, + "bjugn.no": 1, + "bl.it": 1, + "blackbaudcdn.net": 1, + "blog.bo": 1, + "blog.br": 1, + "blog.gt": 1, + "blog.kg": 1, + "blog.vu": 1, + "blogdns.com": 1, + "blogdns.net": 1, + "blogdns.org": 1, + "blogsite.org": 1, + "blogsite.xyz": 1, + "blogspot.ae": 1, + "blogspot.al": 1, + "blogspot.am": 1, + "blogspot.ba": 1, + "blogspot.be": 1, + "blogspot.bg": 1, + "blogspot.bj": 1, + "blogspot.ca": 1, + "blogspot.cf": 1, + "blogspot.ch": 1, + "blogspot.cl": 1, + "blogspot.co.at": 1, + "blogspot.co.id": 1, + "blogspot.co.il": 1, + "blogspot.co.ke": 1, + "blogspot.co.nz": 1, + "blogspot.co.uk": 1, + "blogspot.co.za": 1, + "blogspot.com": 1, + "blogspot.com.ar": 1, + "blogspot.com.au": 1, + "blogspot.com.br": 1, + "blogspot.com.by": 1, + "blogspot.com.co": 1, + "blogspot.com.cy": 1, + "blogspot.com.ee": 1, + "blogspot.com.eg": 1, + "blogspot.com.es": 1, + "blogspot.com.mt": 1, + "blogspot.com.ng": 1, + "blogspot.com.tr": 1, + "blogspot.com.uy": 1, + "blogspot.cv": 1, + "blogspot.cz": 1, + "blogspot.de": 1, + "blogspot.dk": 1, + "blogspot.fi": 1, + "blogspot.fr": 1, + "blogspot.gr": 1, + "blogspot.hk": 1, + "blogspot.hr": 1, + "blogspot.hu": 1, + "blogspot.ie": 1, + "blogspot.in": 1, + "blogspot.is": 1, + "blogspot.it": 1, + "blogspot.jp": 1, + "blogspot.kr": 1, + "blogspot.li": 1, + "blogspot.lt": 1, + "blogspot.lu": 1, + "blogspot.md": 1, + "blogspot.mk": 1, + "blogspot.mr": 1, + "blogspot.mx": 1, + "blogspot.my": 1, + "blogspot.nl": 1, + "blogspot.no": 1, + "blogspot.pe": 1, + "blogspot.pt": 1, + "blogspot.qa": 1, + "blogspot.re": 1, + "blogspot.ro": 1, + "blogspot.rs": 1, + "blogspot.ru": 1, + "blogspot.se": 1, + "blogspot.sg": 1, + "blogspot.si": 1, + "blogspot.sk": 1, + "blogspot.sn": 1, + "blogspot.td": 1, + "blogspot.tw": 1, + "blogspot.ug": 1, + "blogspot.vn": 1, + "blogsyte.com": 1, + "bloxcms.com": 1, + "bmd.br": 1, + "bmoattachments.org": 1, + "bn.it": 1, + "bnr.la": 1, + "bo.it": 1, + "bo.nordland.no": 1, + "bo.telemark.no": 1, + "boavista.br": 1, + "bodo.no": 1, + "bod\u00f8.no": 1, + "bokn.no": 1, + "boldlygoingnowhere.org": 1, + "boleslawiec.pl": 1, + "bolivia.bo": 1, + "bologna.it": 1, + "bolt.hu": 1, + "bolzano-altoadige.it": 1, + "bolzano.it": 1, + "bomlo.no": 1, + "bonn.museum": 1, + "boomla.net": 1, + "boston.museum": 1, + "botanical.museum": 1, + "botanicalgarden.museum": 1, + "botanicgarden.museum": 1, + "botany.museum": 1, + "bounceme.net": 1, + "bounty-full.com": 1, + "boxfuse.io": 1, + "bozen-sudtirol.it": 1, + "bozen-suedtirol.it": 1, + "bozen-s\u00fcdtirol.it": 1, + "bozen.it": 1, + "bpl.biz": 1, + "bplaced.com": 1, + "bplaced.de": 1, + "bplaced.net": 1, + "br.com": 1, + "br.it": 1, + "brand.se": 1, + "brandywinevalley.museum": 1, + "brasil.museum": 1, + "brasilia.me": 1, + "bremanger.no": 1, + "brescia.it": 1, + "brindisi.it": 1, + "bristol.museum": 1, + "british.museum": 1, + "britishcolumbia.museum": 1, + "broadcast.museum": 1, + "broke-it.net": 1, + "broker.aero": 1, + "bronnoy.no": 1, + "bronnoysund.no": 1, + "browsersafetymark.io": 1, + "brumunddal.no": 1, + "brunel.museum": 1, + "brussel.museum": 1, + "brussels.museum": 1, + "bruxelles.museum": 1, + "bryansk.su": 1, + "bryne.no": 1, + "br\u00f8nn\u00f8y.no": 1, + "br\u00f8nn\u00f8ysund.no": 1, + "bs.it": 1, + "bsb.br": 1, + "bss.design": 1, + "bt.it": 1, + "bu.no": 1, + "budejju.no": 1, + "building.museum": 1, + "builtwithdark.com": 1, + "bukhara.su": 1, + "bulsan-sudtirol.it": 1, + "bulsan-suedtirol.it": 1, + "bulsan-s\u00fcdtirol.it": 1, + "bulsan.it": 1, + "bungoono.oita.jp": 1, + "bungotakada.oita.jp": 1, + "bunkyo.tokyo.jp": 1, + "burghof.museum": 1, + "bus.museum": 1, + "busan.kr": 1, + "bushey.museum": 1, + "buyshouses.net": 1, + "buzen.fukuoka.jp": 1, + "bydgoszcz.pl": 1, + "byen.site": 1, + "bygland.no": 1, + "bykle.no": 1, + "bytom.pl": 1, + "bz.it": 1, + "bzz.dapps.earth": 2, + "b\u00e1hcavuotna.no": 1, + "b\u00e1hccavuotna.no": 1, + "b\u00e1id\u00e1r.no": 1, + "b\u00e1jddar.no": 1, + "b\u00e1l\u00e1t.no": 1, + "b\u00e5d\u00e5ddj\u00e5.no": 1, + "b\u00e5tsfjord.no": 1, + "b\u00e6rum.no": 1, + "b\u00f8.nordland.no": 1, + "b\u00f8.telemark.no": 1, + "b\u00f8mlo.no": 1, + "c.bg": 1, + "c.cdn77.org": 1, + "c.la": 1, + "c.se": 1, + "c66.me": 1, + "ca-central-1.elasticbeanstalk.com": 1, + "ca.eu.org": 1, + "ca.it": 1, + "ca.na": 1, + "ca.us": 1, + "caa.aero": 1, + "caa.li": 1, + "cable-modem.org": 1, + "cadaques.museum": 1, + "cagliari.it": 1, + "cahcesuolo.no": 1, + "cal.it": 1, + "calabria.it": 1, + "california.museum": 1, + "caltanissetta.it": 1, + "cam.it": 1, + "cambridge.museum": 1, + "camdvr.org": 1, + "campania.it": 1, + "campidano-medio.it": 1, + "campidanomedio.it": 1, + "campinagrande.br": 1, + "campinas.br": 1, + "campobasso.it": 1, + "can.museum": 1, + "canada.museum": 1, + "capebreton.museum": 1, + "carbonia-iglesias.it": 1, + "carboniaiglesias.it": 1, + "cargo.aero": 1, + "carrara-massa.it": 1, + "carraramassa.it": 1, + "carrd.co": 1, + "carrier.museum": 1, + "cartoonart.museum": 1, + "casacam.net": 1, + "casadelamoneda.museum": 1, + "caserta.it": 1, + "casino.hu": 1, + "castle.museum": 1, + "castres.museum": 1, + "cat.ax": 1, + "catania.it": 1, + "catanzaro.it": 1, + "catering.aero": 1, + "catholic.edu.au": 1, + "caxias.br": 1, + "cb.it": 1, + "cbg.ru": 1, + "cc.ak.us": 1, + "cc.al.us": 1, + "cc.ar.us": 1, + "cc.as.us": 1, + "cc.az.us": 1, + "cc.ca.us": 1, + "cc.co.us": 1, + "cc.ct.us": 1, + "cc.dc.us": 1, + "cc.de.us": 1, + "cc.fl.us": 1, + "cc.ga.us": 1, + "cc.gu.us": 1, + "cc.hi.us": 1, + "cc.hn": 1, + "cc.ia.us": 1, + "cc.id.us": 1, + "cc.il.us": 1, + "cc.in.us": 1, + "cc.ks.us": 1, + "cc.ky.us": 1, + "cc.la.us": 1, + "cc.ma.us": 1, + "cc.md.us": 1, + "cc.me.us": 1, + "cc.mi.us": 1, + "cc.mn.us": 1, + "cc.mo.us": 1, + "cc.ms.us": 1, + "cc.mt.us": 1, + "cc.na": 1, + "cc.nc.us": 1, + "cc.nd.us": 1, + "cc.ne.us": 1, + "cc.nh.us": 1, + "cc.nj.us": 1, + "cc.nm.us": 1, + "cc.nv.us": 1, + "cc.ny.us": 1, + "cc.oh.us": 1, + "cc.ok.us": 1, + "cc.or.us": 1, + "cc.pa.us": 1, + "cc.pr.us": 1, + "cc.ri.us": 1, + "cc.sc.us": 1, + "cc.sd.us": 1, + "cc.tn.us": 1, + "cc.tx.us": 1, + "cc.ua": 1, + "cc.ut.us": 1, + "cc.va.us": 1, + "cc.vi.us": 1, + "cc.vt.us": 1, + "cc.wa.us": 1, + "cc.wi.us": 1, + "cc.wv.us": 1, + "cc.wy.us": 1, + "cci.fr": 1, + "cd.eu.org": 1, + "cdn77-ssl.net": 1, + "ce.gov.br": 1, + "ce.it": 1, + "ce.leg.br": 1, + "cechire.com": 1, + "celtic.museum": 1, + "center.museum": 1, + "certification.aero": 1, + "certmgr.org": 1, + "cesena-forli.it": 1, + "cesena-forl\u00ec.it": 1, + "cesenaforli.it": 1, + "cesenaforl\u00ec.it": 1, + "ch.eu.org": 1, + "ch.it": 1, + "ch.tc": 1, + "chambagri.fr": 1, + "championship.aero": 1, + "channelsdvr.net": 1, + "charter.aero": 1, + "chattanooga.museum": 1, + "cheltenham.museum": 1, + "cherkassy.ua": 1, + "cherkasy.ua": 1, + "chernigov.ua": 1, + "chernihiv.ua": 1, + "chernivtsi.ua": 1, + "chernovtsy.ua": 1, + "chesapeakebay.museum": 1, + "chiba.jp": 1, + "chicago.museum": 1, + "chichibu.saitama.jp": 1, + "chieti.it": 1, + "chigasaki.kanagawa.jp": 1, + "chihayaakasaka.osaka.jp": 1, + "chijiwa.nagasaki.jp": 1, + "chikugo.fukuoka.jp": 1, + "chikuho.fukuoka.jp": 1, + "chikuhoku.nagano.jp": 1, + "chikujo.fukuoka.jp": 1, + "chikuma.nagano.jp": 1, + "chikusei.ibaraki.jp": 1, + "chikushino.fukuoka.jp": 1, + "chikuzen.fukuoka.jp": 1, + "children.museum": 1, + "childrens.museum": 1, + "childrensgarden.museum": 1, + "chimkent.su": 1, + "chino.nagano.jp": 1, + "chippubetsu.hokkaido.jp": 1, + "chiropractic.museum": 1, + "chirurgiens-dentistes-en-france.fr": 1, + "chirurgiens-dentistes.fr": 1, + "chiryu.aichi.jp": 1, + "chita.aichi.jp": 1, + "chitose.hokkaido.jp": 1, + "chiyoda.gunma.jp": 1, + "chiyoda.tokyo.jp": 1, + "chizu.tottori.jp": 1, + "chocolate.museum": 1, + "chofu.tokyo.jp": 1, + "chonan.chiba.jp": 1, + "chosei.chiba.jp": 1, + "choshi.chiba.jp": 1, + "choyo.kumamoto.jp": 1, + "christiansburg.museum": 1, + "chtr.k12.ma.us": 1, + "chungbuk.kr": 1, + "chungnam.kr": 1, + "chuo.chiba.jp": 1, + "chuo.fukuoka.jp": 1, + "chuo.osaka.jp": 1, + "chuo.tokyo.jp": 1, + "chuo.yamanashi.jp": 1, + "ci.it": 1, + "ciencia.bo": 1, + "cieszyn.pl": 1, + "cim.br": 1, + "cincinnati.museum": 1, + "cinema.museum": 1, + "circus.museum": 1, + "ciscofreak.com": 1, + "cistron.nl": 1, + "city.hu": 1, + "city.kawasaki.jp": 0, + "city.kitakyushu.jp": 0, + "city.kobe.jp": 0, + "city.nagoya.jp": 0, + "city.sapporo.jp": 0, + "city.sendai.jp": 0, + "city.yokohama.jp": 0, + "civilaviation.aero": 1, + "civilisation.museum": 1, + "civilization.museum": 1, + "civilwar.museum": 1, + "ck": 2, + "ck.ua": 1, + "cl.it": 1, + "clan.rip": 1, + "cleverapps.io": 1, + "clic2000.net": 1, + "clinton.museum": 1, + "clock.museum": 1, + "cloud.fedoraproject.org": 1, + "cloud.goog": 1, + "cloud.metacentrum.cz": 2, + "cloud66.ws": 1, + "cloud66.zone": 1, + "cloudaccess.host": 1, + "cloudaccess.net": 1, + "cloudapp.net": 1, + "cloudapps.digital": 1, + "cloudcontrolapp.com": 1, + "cloudcontrolled.com": 1, + "cloudeity.net": 1, + "cloudera.site": 1, + "cloudfront.net": 1, + "cloudfunctions.net": 1, + "cloudjiffy.net": 1, + "cloudns.asia": 1, + "cloudns.biz": 1, + "cloudns.cc": 1, + "cloudns.club": 1, + "cloudns.eu": 1, + "cloudns.in": 1, + "cloudns.info": 1, + "cloudns.org": 1, + "cloudns.pro": 1, + "cloudns.pw": 1, + "cloudns.us": 1, + "cloudycluster.net": 1, + "club.aero": 1, + "club.tw": 1, + "cn-north-1.eb.amazonaws.com.cn": 1, + "cn-northwest-1.eb.amazonaws.com.cn": 1, + "cn.com": 1, + "cn.eu.org": 1, + "cn.it": 1, + "cn.ua": 1, + "cn.vu": 1, + "cng.br": 1, + "cnpy.gdn": 1, + "cns.joyent.com": 2, + "cnt.br": 1, + "co.ae": 1, + "co.ag": 1, + "co.am": 1, + "co.ao": 1, + "co.at": 1, + "co.bb": 1, + "co.bi": 1, + "co.bn": 1, + "co.business": 1, + "co.bw": 1, + "co.ca": 1, + "co.ci": 1, + "co.cl": 1, + "co.cm": 1, + "co.com": 1, + "co.cr": 1, + "co.cz": 1, + "co.dk": 1, + "co.education": 1, + "co.events": 1, + "co.financial": 1, + "co.gg": 1, + "co.gl": 1, + "co.gy": 1, + "co.hu": 1, + "co.id": 1, + "co.il": 1, + "co.im": 1, + "co.in": 1, + "co.ir": 1, + "co.it": 1, + "co.je": 1, + "co.jp": 1, + "co.ke": 1, + "co.kr": 1, + "co.krd": 1, + "co.lc": 1, + "co.ls": 1, + "co.ma": 1, + "co.me": 1, + "co.mg": 1, + "co.mu": 1, + "co.mw": 1, + "co.mz": 1, + "co.na": 1, + "co.network": 1, + "co.ni": 1, + "co.nl": 1, + "co.no": 1, + "co.nz": 1, + "co.om": 1, + "co.pl": 1, + "co.place": 1, + "co.pn": 1, + "co.pw": 1, + "co.ro": 1, + "co.rs": 1, + "co.rw": 1, + "co.st": 1, + "co.sz": 1, + "co.technology": 1, + "co.th": 1, + "co.tj": 1, + "co.tm": 1, + "co.tt": 1, + "co.tz": 1, + "co.ua": 1, + "co.ug": 1, + "co.uk": 1, + "co.us": 1, + "co.uz": 1, + "co.ve": 1, + "co.vi": 1, + "co.za": 1, + "co.zm": 1, + "co.zw": 1, + "coal.museum": 1, + "coastaldefence.museum": 1, + "codespot.com": 1, + "cody.museum": 1, + "cog.mi.us": 1, + "col.ng": 1, + "coldwar.museum": 1, + "collection.museum": 1, + "collegefan.org": 1, + "colonialwilliamsburg.museum": 1, + "coloradoplateau.museum": 1, + "columbia.museum": 1, + "columbus.museum": 1, + "com.ac": 1, + "com.af": 1, + "com.ag": 1, + "com.ai": 1, + "com.al": 1, + "com.am": 1, + "com.ar": 1, + "com.au": 1, + "com.aw": 1, + "com.az": 1, + "com.ba": 1, + "com.bb": 1, + "com.bh": 1, + "com.bi": 1, + "com.bm": 1, + "com.bn": 1, + "com.bo": 1, + "com.br": 1, + "com.bs": 1, + "com.bt": 1, + "com.by": 1, + "com.bz": 1, + "com.ci": 1, + "com.cm": 1, + "com.cn": 1, + "com.co": 1, + "com.cu": 1, + "com.cw": 1, + "com.cy": 1, + "com.de": 1, + "com.dm": 1, + "com.do": 1, + "com.dz": 1, + "com.ec": 1, + "com.ee": 1, + "com.eg": 1, + "com.es": 1, + "com.et": 1, + "com.fj": 1, + "com.fm": 1, + "com.fr": 1, + "com.ge": 1, + "com.gh": 1, + "com.gi": 1, + "com.gl": 1, + "com.gn": 1, + "com.gp": 1, + "com.gr": 1, + "com.gt": 1, + "com.gu": 1, + "com.gy": 1, + "com.hk": 1, + "com.hn": 1, + "com.hr": 1, + "com.ht": 1, + "com.im": 1, + "com.io": 1, + "com.iq": 1, + "com.is": 1, + "com.jo": 1, + "com.kg": 1, + "com.ki": 1, + "com.km": 1, + "com.kp": 1, + "com.kw": 1, + "com.ky": 1, + "com.kz": 1, + "com.la": 1, + "com.lb": 1, + "com.lc": 1, + "com.lk": 1, + "com.lr": 1, + "com.lv": 1, + "com.ly": 1, + "com.mg": 1, + "com.mk": 1, + "com.ml": 1, + "com.mo": 1, + "com.ms": 1, + "com.mt": 1, + "com.mu": 1, + "com.mv": 1, + "com.mw": 1, + "com.mx": 1, + "com.my": 1, + "com.na": 1, + "com.nf": 1, + "com.ng": 1, + "com.ni": 1, + "com.nr": 1, + "com.om": 1, + "com.pa": 1, + "com.pe": 1, + "com.pf": 1, + "com.ph": 1, + "com.pk": 1, + "com.pl": 1, + "com.pr": 1, + "com.ps": 1, + "com.pt": 1, + "com.py": 1, + "com.qa": 1, + "com.re": 1, + "com.ro": 1, + "com.ru": 1, + "com.sa": 1, + "com.sb": 1, + "com.sc": 1, + "com.sd": 1, + "com.se": 1, + "com.sg": 1, + "com.sh": 1, + "com.sl": 1, + "com.sn": 1, + "com.so": 1, + "com.ss": 1, + "com.st": 1, + "com.sv": 1, + "com.sy": 1, + "com.tj": 1, + "com.tm": 1, + "com.tn": 1, + "com.to": 1, + "com.tr": 1, + "com.tt": 1, + "com.tw": 1, + "com.ua": 1, + "com.ug": 1, + "com.uy": 1, + "com.uz": 1, + "com.vc": 1, + "com.ve": 1, + "com.vi": 1, + "com.vn": 1, + "com.vu": 1, + "com.ws": 1, + "com.zm": 1, + "commune.am": 1, + "communication.museum": 1, + "communications.museum": 1, + "community-pro.de": 1, + "community-pro.net": 1, + "community.museum": 1, + "como.it": 1, + "compute-1.amazonaws.com": 2, + "compute.amazonaws.com": 2, + "compute.amazonaws.com.cn": 2, + "compute.estate": 2, + "computer.museum": 1, + "computerhistory.museum": 1, + "comunica\u00e7\u00f5es.museum": 1, + "conf.au": 1, + "conf.lv": 1, + "conf.se": 1, + "conference.aero": 1, + "conn.uk": 1, + "consulado.st": 1, + "consultant.aero": 1, + "consulting.aero": 1, + "contagem.br": 1, + "contemporary.museum": 1, + "contemporaryart.museum": 1, + "control.aero": 1, + "convent.museum": 1, + "coop.br": 1, + "coop.ht": 1, + "coop.km": 1, + "coop.mv": 1, + "coop.mw": 1, + "coop.py": 1, + "coop.rw": 1, + "coop.tt": 1, + "cooperativa.bo": 1, + "copenhagen.museum": 1, + "copro.uk": 1, + "corporation.museum": 1, + "correios-e-telecomunica\u00e7\u00f5es.museum": 1, + "corvette.museum": 1, + "cosenza.it": 1, + "costume.museum": 1, + "couchpotatofries.org": 1, + "couk.me": 1, + "council.aero": 1, + "countryestate.museum": 1, + "county.museum": 1, + "coz.br": 1, + "cpa.pro": 1, + "cq.cn": 1, + "cr.it": 1, + "cr.ua": 1, + "crafting.xyz": 1, + "crafts.museum": 1, + "cranbrook.museum": 1, + "crd.co": 1, + "creation.museum": 1, + "cremona.it": 1, + "crew.aero": 1, + "cri.br": 1, + "cri.nz": 1, + "crimea.ua": 1, + "crotone.it": 1, + "cryptonomic.net": 2, + "cs.it": 1, + "csx.cc": 1, + "ct.it": 1, + "ct.us": 1, + "cuiaba.br": 1, + "cultural.museum": 1, + "culturalcenter.museum": 1, + "culture.museum": 1, + "cuneo.it": 1, + "cupcake.is": 1, + "curitiba.br": 1, + "curv.dev": 1, + "cust.dev.thingdust.io": 1, + "cust.disrec.thingdust.io": 1, + "cust.prod.thingdust.io": 1, + "cust.retrosnub.co.uk": 1, + "cust.testing.thingdust.io": 1, + "custom.metacentrum.cz": 1, + "customer-oci.com": 2, + "customer.enonic.io": 1, + "customer.mythic-beasts.com": 1, + "customer.speedpartner.de": 1, + "cv.ua": 1, + "cx.ua": 1, + "cy.eu.org": 1, + "cya.gg": 1, + "cyber.museum": 1, + "cymru.museum": 1, + "cyon.link": 1, + "cyon.site": 1, + "cz.eu.org": 1, + "cz.it": 1, + "czeladz.pl": 1, + "czest.pl": 1, + "d.bg": 1, + "d.gv.vc": 1, + "d.se": 1, + "daegu.kr": 1, + "daejeon.kr": 1, + "daemon.panel.gg": 1, + "dagestan.ru": 1, + "dagestan.su": 1, + "daigo.ibaraki.jp": 1, + "daisen.akita.jp": 1, + "daito.osaka.jp": 1, + "daiwa.hiroshima.jp": 1, + "dali.museum": 1, + "dallas.museum": 1, + "damnserver.com": 1, + "daplie.me": 1, + "dapps.earth": 2, + "database.museum": 1, + "date.fukushima.jp": 1, + "date.hokkaido.jp": 1, + "dattolocal.com": 1, + "dattolocal.net": 1, + "dattorelay.com": 1, + "dattoweb.com": 1, + "davvenjarga.no": 1, + "davvenj\u00e1rga.no": 1, + "davvesiida.no": 1, + "dazaifu.fukuoka.jp": 1, + "dc.us": 1, + "dd-dns.de": 1, + "ddns.me": 1, + "ddns.net": 1, + "ddnsfree.com": 1, + "ddnsgeek.com": 1, + "ddnsking.com": 1, + "ddnslive.com": 1, + "ddnss.de": 1, + "ddnss.org": 1, + "ddr.museum": 1, + "de.com": 1, + "de.cool": 1, + "de.eu.org": 1, + "de.gt": 1, + "de.ls": 1, + "de.md": 1, + "de.us": 1, + "deatnu.no": 1, + "debian.net": 1, + "decorativearts.museum": 1, + "dedyn.io": 1, + "def.br": 1, + "defense.tn": 1, + "definima.io": 1, + "definima.net": 1, + "delaware.museum": 1, + "dell-ogliastra.it": 1, + "dellogliastra.it": 1, + "delmenhorst.museum": 1, + "demo.jelastic.com": 1, + "democracia.bo": 1, + "demon.nl": 1, + "denmark.museum": 1, + "dep.no": 1, + "deporte.bo": 1, + "depot.museum": 1, + "des.br": 1, + "desa.id": 1, + "design.aero": 1, + "design.museum": 1, + "det.br": 1, + "detroit.museum": 1, + "dev-myqnapcloud.com": 1, + "dev.adobeaemcloud.com": 2, + "dev.br": 1, + "dev.static.land": 1, + "dev.vu": 1, + "development.run": 1, + "devices.resinstaging.io": 1, + "df.gov.br": 1, + "df.leg.br": 1, + "dgca.aero": 1, + "dh.bytemark.co.uk": 1, + "dielddanuorri.no": 1, + "dinosaur.museum": 1, + "direct.quickconnect.to": 1, + "discourse.group": 1, + "discourse.team": 1, + "discovery.museum": 1, + "diskstation.eu": 1, + "diskstation.me": 1, + "diskstation.org": 1, + "diskussionsbereich.de": 1, + "ditchyourip.com": 1, + "divtasvuodna.no": 1, + "divttasvuotna.no": 1, + "dk.eu.org": 1, + "dlugoleka.pl": 1, + "dn.ua": 1, + "dnepropetrovsk.ua": 1, + "dni.us": 1, + "dnipropetrovsk.ua": 1, + "dnsalias.com": 1, + "dnsalias.net": 1, + "dnsalias.org": 1, + "dnsdojo.com": 1, + "dnsdojo.net": 1, + "dnsdojo.org": 1, + "dnsfor.me": 1, + "dnshome.de": 1, + "dnsiskinky.com": 1, + "dnsking.ch": 1, + "dnsup.net": 1, + "dnsupdate.info": 1, + "dnsupdater.de": 1, + "does-it.net": 1, + "doesntexist.com": 1, + "doesntexist.org": 1, + "dolls.museum": 1, + "donetsk.ua": 1, + "donna.no": 1, + "donostia.museum": 1, + "dontexist.com": 1, + "dontexist.net": 1, + "dontexist.org": 1, + "doomdns.com": 1, + "doomdns.org": 1, + "dopaas.com": 1, + "doshi.yamanashi.jp": 1, + "dovre.no": 1, + "dp.ua": 1, + "dr.na": 1, + "dr.tr": 1, + "drammen.no": 1, + "drangedal.no": 1, + "dray-dns.de": 1, + "drayddns.com": 1, + "draydns.de": 1, + "dreamhosters.com": 1, + "drobak.no": 1, + "drud.io": 1, + "drud.us": 1, + "dr\u00f8bak.no": 1, + "dscloud.biz": 1, + "dscloud.me": 1, + "dscloud.mobi": 1, + "dsmynas.com": 1, + "dsmynas.net": 1, + "dsmynas.org": 1, + "dst.mi.us": 1, + "duckdns.org": 1, + "durham.museum": 1, + "dvrcam.info": 1, + "dvrdns.org": 1, + "dweb.link": 2, + "dy.fi": 1, + "dyn-berlin.de": 1, + "dyn-ip24.de": 1, + "dyn-o-saur.com": 1, + "dyn-vpn.de": 1, + "dyn.cosidns.de": 1, + "dyn.ddnss.de": 1, + "dyn.home-webserver.de": 1, + "dyn53.io": 1, + "dynalias.com": 1, + "dynalias.net": 1, + "dynalias.org": 1, + "dynamic-dns.info": 1, + "dynamisches-dns.de": 1, + "dynathome.net": 1, + "dyndns-at-home.com": 1, + "dyndns-at-work.com": 1, + "dyndns-blog.com": 1, + "dyndns-free.com": 1, + "dyndns-home.com": 1, + "dyndns-ip.com": 1, + "dyndns-mail.com": 1, + "dyndns-office.com": 1, + "dyndns-pics.com": 1, + "dyndns-remote.com": 1, + "dyndns-server.com": 1, + "dyndns-web.com": 1, + "dyndns-wiki.com": 1, + "dyndns-work.com": 1, + "dyndns.biz": 1, + "dyndns.dappnode.io": 1, + "dyndns.ddnss.de": 1, + "dyndns.info": 1, + "dyndns.org": 1, + "dyndns.tv": 1, + "dyndns.ws": 1, + "dyndns1.de": 1, + "dynns.com": 1, + "dynserv.org": 1, + "dynu.net": 1, + "dynv6.net": 1, + "dynvpn.de": 1, + "dyroy.no": 1, + "dyr\u00f8y.no": 1, + "d\u00f8nna.no": 1, + "e.bg": 1, + "e.se": 1, + "e12.ve": 1, + "e164.arpa": 1, + "e4.cz": 1, + "east-kazakhstan.su": 1, + "eastafrica.museum": 1, + "eastcoast.museum": 1, + "eating-organic.net": 1, + "eaton.mi.us": 1, + "ebetsu.hokkaido.jp": 1, + "ebina.kanagawa.jp": 1, + "ebino.miyazaki.jp": 1, + "ebiz.tw": 1, + "echizen.fukui.jp": 1, + "ecn.br": 1, + "eco.br": 1, + "ecologia.bo": 1, + "economia.bo": 1, + "ed.ao": 1, + "ed.ci": 1, + "ed.cr": 1, + "ed.jp": 1, + "ed.pw": 1, + "edgeapp.net": 1, + "edgestack.me": 1, + "edogawa.tokyo.jp": 1, + "edu.ac": 1, + "edu.af": 1, + "edu.al": 1, + "edu.ar": 1, + "edu.au": 1, + "edu.az": 1, + "edu.ba": 1, + "edu.bb": 1, + "edu.bh": 1, + "edu.bi": 1, + "edu.bm": 1, + "edu.bn": 1, + "edu.bo": 1, + "edu.br": 1, + "edu.bs": 1, + "edu.bt": 1, + "edu.bz": 1, + "edu.ci": 1, + "edu.cn": 1, + "edu.co": 1, + "edu.cu": 1, + "edu.cw": 1, + "edu.dm": 1, + "edu.do": 1, + "edu.dz": 1, + "edu.ec": 1, + "edu.ee": 1, + "edu.eg": 1, + "edu.es": 1, + "edu.et": 1, + "edu.eu.org": 1, + "edu.fm": 1, + "edu.gd": 1, + "edu.ge": 1, + "edu.gh": 1, + "edu.gi": 1, + "edu.gl": 1, + "edu.gn": 1, + "edu.gp": 1, + "edu.gr": 1, + "edu.gt": 1, + "edu.gu": 1, + "edu.gy": 1, + "edu.hk": 1, + "edu.hn": 1, + "edu.ht": 1, + "edu.in": 1, + "edu.iq": 1, + "edu.is": 1, + "edu.it": 1, + "edu.jo": 1, + "edu.kg": 1, + "edu.ki": 1, + "edu.km": 1, + "edu.kn": 1, + "edu.kp": 1, + "edu.krd": 1, + "edu.kw": 1, + "edu.ky": 1, + "edu.kz": 1, + "edu.la": 1, + "edu.lb": 1, + "edu.lc": 1, + "edu.lk": 1, + "edu.lr": 1, + "edu.ls": 1, + "edu.lv": 1, + "edu.ly": 1, + "edu.me": 1, + "edu.mg": 1, + "edu.mk": 1, + "edu.ml": 1, + "edu.mn": 1, + "edu.mo": 1, + "edu.ms": 1, + "edu.mt": 1, + "edu.mv": 1, + "edu.mw": 1, + "edu.mx": 1, + "edu.my": 1, + "edu.mz": 1, + "edu.ng": 1, + "edu.ni": 1, + "edu.nr": 1, + "edu.om": 1, + "edu.pa": 1, + "edu.pe": 1, + "edu.pf": 1, + "edu.ph": 1, + "edu.pk": 1, + "edu.pl": 1, + "edu.pn": 1, + "edu.pr": 1, + "edu.ps": 1, + "edu.pt": 1, + "edu.py": 1, + "edu.qa": 1, + "edu.rs": 1, + "edu.ru": 1, + "edu.sa": 1, + "edu.sb": 1, + "edu.sc": 1, + "edu.sd": 1, + "edu.sg": 1, + "edu.sl": 1, + "edu.sn": 1, + "edu.so": 1, + "edu.ss": 1, + "edu.st": 1, + "edu.sv": 1, + "edu.sy": 1, + "edu.tj": 1, + "edu.tm": 1, + "edu.to": 1, + "edu.tr": 1, + "edu.tt": 1, + "edu.tw": 1, + "edu.ua": 1, + "edu.uy": 1, + "edu.vc": 1, + "edu.ve": 1, + "edu.vn": 1, + "edu.vu": 1, + "edu.ws": 1, + "edu.za": 1, + "edu.zm": 1, + "education.museum": 1, + "educational.museum": 1, + "educator.aero": 1, + "edugit.org": 1, + "edunet.tn": 1, + "ee.eu.org": 1, + "egersund.no": 1, + "egyptian.museum": 1, + "ehime.jp": 1, + "eid.no": 1, + "eidfjord.no": 1, + "eidsberg.no": 1, + "eidskog.no": 1, + "eidsvoll.no": 1, + "eigersund.no": 1, + "eiheiji.fukui.jp": 1, + "eisenbahn.museum": 1, + "ekloges.cy": 1, + "elasticbeanstalk.com": 1, + "elb.amazonaws.com": 2, + "elb.amazonaws.com.cn": 2, + "elblag.pl": 1, + "elburg.museum": 1, + "elk.pl": 1, + "elvendrell.museum": 1, + "elverum.no": 1, + "emb.kw": 1, + "embaixada.st": 1, + "embetsu.hokkaido.jp": 1, + "embroidery.museum": 1, + "emergency.aero": 1, + "emilia-romagna.it": 1, + "emiliaromagna.it": 1, + "emp.br": 1, + "empresa.bo": 1, + "emr.it": 1, + "en-root.fr": 1, + "en.it": 1, + "ena.gifu.jp": 1, + "encyclopedic.museum": 1, + "endofinternet.net": 1, + "endofinternet.org": 1, + "endoftheinternet.org": 1, + "enebakk.no": 1, + "enf.br": 1, + "eng.br": 1, + "eng.pro": 1, + "engerdal.no": 1, + "engine.aero": 1, + "engineer.aero": 1, + "england.museum": 1, + "eniwa.hokkaido.jp": 1, + "enna.it": 1, + "enonic.io": 1, + "ens.tn": 1, + "ent.platform.sh": 1, + "enterprisecloud.nu": 1, + "entertainment.aero": 1, + "entomology.museum": 1, + "environment.museum": 1, + "environmentalconservation.museum": 1, + "epilepsy.museum": 1, + "equipment.aero": 1, + "er": 2, + "erimo.hokkaido.jp": 1, + "erotica.hu": 1, + "erotika.hu": 1, + "es.ax": 1, + "es.eu.org": 1, + "es.gov.br": 1, + "es.kr": 1, + "es.leg.br": 1, + "esan.hokkaido.jp": 1, + "esashi.hokkaido.jp": 1, + "esp.br": 1, + "essex.museum": 1, + "est-a-la-maison.com": 1, + "est-a-la-masion.com": 1, + "est-le-patron.com": 1, + "est-mon-blogueur.com": 1, + "est.pr": 1, + "estate.museum": 1, + "etajima.hiroshima.jp": 1, + "etc.br": 1, + "ethnology.museum": 1, + "eti.br": 1, + "etne.no": 1, + "etnedal.no": 1, + "eu-1.evennode.com": 1, + "eu-2.evennode.com": 1, + "eu-3.evennode.com": 1, + "eu-4.evennode.com": 1, + "eu-central-1.elasticbeanstalk.com": 1, + "eu-west-1.elasticbeanstalk.com": 1, + "eu-west-2.elasticbeanstalk.com": 1, + "eu-west-3.elasticbeanstalk.com": 1, + "eu.ax": 1, + "eu.com": 1, + "eu.int": 1, + "eu.meteorapp.com": 1, + "eu.org": 1, + "eu.platform.sh": 1, + "eun.eg": 1, + "evenassi.no": 1, + "evenes.no": 1, + "even\u00e1\u0161\u0161i.no": 1, + "evje-og-hornnes.no": 1, + "ex.futurecms.at": 2, + "ex.ortsinfo.at": 2, + "exchange.aero": 1, + "exeter.museum": 1, + "exhibition.museum": 1, + "exnet.su": 1, + "experts-comptables.fr": 1, + "express.aero": 1, + "f.bg": 1, + "f.se": 1, + "fam.pk": 1, + "family.museum": 1, + "familyds.com": 1, + "familyds.net": 1, + "familyds.org": 1, + "fantasyleague.cc": 1, + "far.br": 1, + "farm.museum": 1, + "farmequipment.museum": 1, + "farmers.museum": 1, + "farmstead.museum": 1, + "farsund.no": 1, + "fastly-terrarium.com": 1, + "fastlylb.net": 1, + "fastvps-server.com": 1, + "fastvps.host": 1, + "fastvps.site": 1, + "fauske.no": 1, + "fbx-os.fr": 1, + "fbxos.fr": 1, + "fc.it": 1, + "fe.it": 1, + "fed.us": 1, + "federation.aero": 1, + "fedje.no": 1, + "fedorainfracloud.org": 1, + "fedorapeople.org": 1, + "feira.br": 1, + "fermo.it": 1, + "ferrara.it": 1, + "feste-ip.net": 1, + "fet.no": 1, + "fetsund.no": 1, + "fg.it": 1, + "fh.se": 1, + "fhapp.xyz": 1, + "fhs.no": 1, + "fhsk.se": 1, + "fhv.se": 1, + "fi.cloudplatform.fi": 1, + "fi.cr": 1, + "fi.eu.org": 1, + "fi.it": 1, + "fie.ee": 1, + "field.museum": 1, + "figueres.museum": 1, + "filatelia.museum": 1, + "filegear-au.me": 1, + "filegear-de.me": 1, + "filegear-gb.me": 1, + "filegear-ie.me": 1, + "filegear-jp.me": 1, + "filegear-sg.me": 1, + "filegear.me": 1, + "film.hu": 1, + "film.museum": 1, + "fin.ci": 1, + "fin.ec": 1, + "fin.tn": 1, + "fineart.museum": 1, + "finearts.museum": 1, + "finland.museum": 1, + "finnoy.no": 1, + "finn\u00f8y.no": 1, + "firebaseapp.com": 1, + "firenet.ch": 2, + "firenze.it": 1, + "firewall-gateway.com": 1, + "firewall-gateway.de": 1, + "firewall-gateway.net": 1, + "firm.co": 1, + "firm.dk": 1, + "firm.ht": 1, + "firm.in": 1, + "firm.nf": 1, + "firm.ng": 1, + "firm.ro": 1, + "firm.ve": 1, + "fitjar.no": 1, + "fj.cn": 1, + "fjaler.no": 1, + "fjell.no": 1, + "fk": 2, + "fl.us": 1, + "fla.no": 1, + "flakstad.no": 1, + "flanders.museum": 1, + "flatanger.no": 1, + "flekkefjord.no": 1, + "flesberg.no": 1, + "flight.aero": 1, + "flog.br": 1, + "flora.no": 1, + "florence.it": 1, + "florida.museum": 1, + "floripa.br": 1, + "floro.no": 1, + "flor\u00f8.no": 1, + "flt.cloud.muni.cz": 1, + "fly.dev": 1, + "flynnhosting.net": 1, + "fl\u00e5.no": 1, + "fm.br": 1, + "fm.it": 1, + "fm.no": 1, + "fnd.br": 1, + "fnwk.site": 1, + "foggia.it": 1, + "folionetwork.site": 1, + "folkebibl.no": 1, + "folldal.no": 1, + "for-better.biz": 1, + "for-more.biz": 1, + "for-our.info": 1, + "for-some.biz": 1, + "for-the.biz": 1, + "for.men": 1, + "for.mom": 1, + "for.one": 1, + "for.sale": 1, + "force.museum": 1, + "forde.no": 1, + "forgot.her.name": 1, + "forgot.his.name": 1, + "forli-cesena.it": 1, + "forlicesena.it": 1, + "forl\u00ec-cesena.it": 1, + "forl\u00eccesena.it": 1, + "forsand.no": 1, + "fortal.br": 1, + "forte.id": 1, + "fortmissoula.museum": 1, + "fortworth.museum": 1, + "forum.hu": 1, + "forumz.info": 1, + "fosnes.no": 1, + "fot.br": 1, + "foundation.museum": 1, + "foz.br": 1, + "fr.eu.org": 1, + "fr.it": 1, + "frana.no": 1, + "francaise.museum": 1, + "frankfurt.museum": 1, + "franziskaner.museum": 1, + "fredrikstad.no": 1, + "free.hr": 1, + "freebox-os.com": 1, + "freebox-os.fr": 1, + "freeboxos.com": 1, + "freeboxos.fr": 1, + "freeddns.org": 1, + "freeddns.us": 1, + "freedesktop.org": 1, + "freemasonry.museum": 1, + "freesite.host": 1, + "freetls.fastly.net": 1, + "frei.no": 1, + "freiburg.museum": 1, + "fribourg.museum": 1, + "friuli-v-giulia.it": 1, + "friuli-ve-giulia.it": 1, + "friuli-vegiulia.it": 1, + "friuli-venezia-giulia.it": 1, + "friuli-veneziagiulia.it": 1, + "friuli-vgiulia.it": 1, + "friuliv-giulia.it": 1, + "friulive-giulia.it": 1, + "friulivegiulia.it": 1, + "friulivenezia-giulia.it": 1, + "friuliveneziagiulia.it": 1, + "friulivgiulia.it": 1, + "frog.museum": 1, + "frogn.no": 1, + "froland.no": 1, + "from-ak.com": 1, + "from-al.com": 1, + "from-ar.com": 1, + "from-az.net": 1, + "from-ca.com": 1, + "from-co.net": 1, + "from-ct.com": 1, + "from-dc.com": 1, + "from-de.com": 1, + "from-fl.com": 1, + "from-ga.com": 1, + "from-hi.com": 1, + "from-ia.com": 1, + "from-id.com": 1, + "from-il.com": 1, + "from-in.com": 1, + "from-ks.com": 1, + "from-ky.com": 1, + "from-la.net": 1, + "from-ma.com": 1, + "from-md.com": 1, + "from-me.org": 1, + "from-mi.com": 1, + "from-mn.com": 1, + "from-mo.com": 1, + "from-ms.com": 1, + "from-mt.com": 1, + "from-nc.com": 1, + "from-nd.com": 1, + "from-ne.com": 1, + "from-nh.com": 1, + "from-nj.com": 1, + "from-nm.com": 1, + "from-nv.com": 1, + "from-ny.net": 1, + "from-oh.com": 1, + "from-ok.com": 1, + "from-or.com": 1, + "from-pa.com": 1, + "from-pr.com": 1, + "from-ri.com": 1, + "from-sc.com": 1, + "from-sd.com": 1, + "from-tn.com": 1, + "from-tx.com": 1, + "from-ut.com": 1, + "from-va.com": 1, + "from-vt.com": 1, + "from-wa.com": 1, + "from-wi.com": 1, + "from-wv.com": 1, + "from-wy.com": 1, + "from.hr": 1, + "frosinone.it": 1, + "frosta.no": 1, + "froya.no": 1, + "fr\u00e6na.no": 1, + "fr\u00f8ya.no": 1, + "fst.br": 1, + "ftpaccess.cc": 1, + "fuchu.hiroshima.jp": 1, + "fuchu.tokyo.jp": 1, + "fuchu.toyama.jp": 1, + "fudai.iwate.jp": 1, + "fuefuki.yamanashi.jp": 1, + "fuel.aero": 1, + "fuettertdasnetz.de": 1, + "fuji.shizuoka.jp": 1, + "fujieda.shizuoka.jp": 1, + "fujiidera.osaka.jp": 1, + "fujikawa.shizuoka.jp": 1, + "fujikawa.yamanashi.jp": 1, + "fujikawaguchiko.yamanashi.jp": 1, + "fujimi.nagano.jp": 1, + "fujimi.saitama.jp": 1, + "fujimino.saitama.jp": 1, + "fujinomiya.shizuoka.jp": 1, + "fujioka.gunma.jp": 1, + "fujisato.akita.jp": 1, + "fujisawa.iwate.jp": 1, + "fujisawa.kanagawa.jp": 1, + "fujishiro.ibaraki.jp": 1, + "fujiyoshida.yamanashi.jp": 1, + "fukagawa.hokkaido.jp": 1, + "fukaya.saitama.jp": 1, + "fukuchi.fukuoka.jp": 1, + "fukuchiyama.kyoto.jp": 1, + "fukudomi.saga.jp": 1, + "fukui.fukui.jp": 1, + "fukui.jp": 1, + "fukumitsu.toyama.jp": 1, + "fukuoka.jp": 1, + "fukuroi.shizuoka.jp": 1, + "fukusaki.hyogo.jp": 1, + "fukushima.fukushima.jp": 1, + "fukushima.hokkaido.jp": 1, + "fukushima.jp": 1, + "fukuyama.hiroshima.jp": 1, + "funabashi.chiba.jp": 1, + "funagata.yamagata.jp": 1, + "funahashi.toyama.jp": 1, + "fundacio.museum": 1, + "fuoisku.no": 1, + "fuossko.no": 1, + "furano.hokkaido.jp": 1, + "furniture.museum": 1, + "furubira.hokkaido.jp": 1, + "furudono.fukushima.jp": 1, + "furukawa.miyagi.jp": 1, + "fusa.no": 1, + "fuso.aichi.jp": 1, + "fussa.tokyo.jp": 1, + "futaba.fukushima.jp": 1, + "futsu.nagasaki.jp": 1, + "futtsu.chiba.jp": 1, + "futurecms.at": 2, + "futurehosting.at": 1, + "futuremailing.at": 1, + "fvg.it": 1, + "fylkesbibl.no": 1, + "fyresdal.no": 1, + "f\u00f8rde.no": 1, + "g.bg": 1, + "g.se": 1, + "g.vbrplsbx.io": 1, + "g12.br": 1, + "ga.us": 1, + "gaivuotna.no": 1, + "gallery.museum": 1, + "galsa.no": 1, + "gamagori.aichi.jp": 1, + "game-host.org": 1, + "game-server.cc": 1, + "game.tw": 1, + "games.hu": 1, + "gamo.shiga.jp": 1, + "gamvik.no": 1, + "gangaviika.no": 1, + "gangwon.kr": 1, + "garden.museum": 1, + "gateway.museum": 1, + "gaular.no": 1, + "gausdal.no": 1, + "gb.com": 1, + "gb.net": 1, + "gc.ca": 1, + "gd.cn": 1, + "gda.pl": 1, + "gdansk.pl": 1, + "gdynia.pl": 1, + "ge.it": 1, + "geek.nz": 1, + "geekgalaxy.com": 1, + "geelvinck.museum": 1, + "gehirn.ne.jp": 1, + "geisei.kochi.jp": 1, + "gemological.museum": 1, + "gen.in": 1, + "gen.mi.us": 1, + "gen.ng": 1, + "gen.nz": 1, + "gen.tr": 1, + "genkai.saga.jp": 1, + "genoa.it": 1, + "genova.it": 1, + "gentapps.com": 1, + "gentlentapis.com": 1, + "geo.br": 1, + "geology.museum": 1, + "geometre-expert.fr": 1, + "georgia.museum": 1, + "georgia.su": 1, + "getmyip.com": 1, + "gets-it.net": 1, + "gg.ax": 1, + "ggf.br": 1, + "giehtavuoatna.no": 1, + "giessen.museum": 1, + "gifu.gifu.jp": 1, + "gifu.jp": 1, + "giize.com": 1, + "gildeskal.no": 1, + "gildesk\u00e5l.no": 1, + "ginan.gifu.jp": 1, + "ginowan.okinawa.jp": 1, + "ginoza.okinawa.jp": 1, + "giske.no": 1, + "git-pages.rit.edu": 1, + "git-repos.de": 1, + "gitapp.si": 1, + "github.io": 1, + "githubusercontent.com": 1, + "gitlab.io": 1, + "gitpage.si": 1, + "gjemnes.no": 1, + "gjerdrum.no": 1, + "gjerstad.no": 1, + "gjesdal.no": 1, + "gjovik.no": 1, + "gj\u00f8vik.no": 1, + "glas.museum": 1, + "glass.museum": 1, + "gleeze.com": 1, + "gliding.aero": 1, + "glitch.me": 1, + "gliwice.pl": 1, + "global.prod.fastly.net": 1, + "global.ssl.fastly.net": 1, + "glogow.pl": 1, + "gloppen.no": 1, + "glug.org.uk": 1, + "gmina.pl": 1, + "gniezno.pl": 1, + "go.ci": 1, + "go.cr": 1, + "go.dyndns.org": 1, + "go.gov.br": 1, + "go.id": 1, + "go.it": 1, + "go.jp": 1, + "go.ke": 1, + "go.kr": 1, + "go.leg.br": 1, + "go.pw": 1, + "go.th": 1, + "go.tj": 1, + "go.tz": 1, + "go.ug": 1, + "gob.ar": 1, + "gob.bo": 1, + "gob.cl": 1, + "gob.do": 1, + "gob.ec": 1, + "gob.es": 1, + "gob.gt": 1, + "gob.hn": 1, + "gob.mx": 1, + "gob.ni": 1, + "gob.pa": 1, + "gob.pe": 1, + "gob.pk": 1, + "gob.sv": 1, + "gob.ve": 1, + "gobo.wakayama.jp": 1, + "godo.gifu.jp": 1, + "goiania.br": 1, + "goip.de": 1, + "gojome.akita.jp": 1, + "gok.pk": 1, + "gokase.miyazaki.jp": 1, + "gol.no": 1, + "golffan.us": 1, + "gon.pk": 1, + "gonohe.aomori.jp": 1, + "googleapis.com": 1, + "googlecode.com": 1, + "gop.pk": 1, + "gorge.museum": 1, + "gorizia.it": 1, + "gorlice.pl": 1, + "gos.pk": 1, + "gose.nara.jp": 1, + "gosen.niigata.jp": 1, + "goshiki.hyogo.jp": 1, + "gotdns.ch": 1, + "gotdns.com": 1, + "gotdns.org": 1, + "gotemba.shizuoka.jp": 1, + "goto.nagasaki.jp": 1, + "gotpantheon.com": 1, + "gotsu.shimane.jp": 1, + "gouv.bj": 1, + "gouv.ci": 1, + "gouv.fr": 1, + "gouv.ht": 1, + "gouv.km": 1, + "gouv.ml": 1, + "gouv.sn": 1, + "gov.ac": 1, + "gov.ae": 1, + "gov.af": 1, + "gov.al": 1, + "gov.ar": 1, + "gov.as": 1, + "gov.au": 1, + "gov.az": 1, + "gov.ba": 1, + "gov.bb": 1, + "gov.bf": 1, + "gov.bh": 1, + "gov.bm": 1, + "gov.bn": 1, + "gov.br": 1, + "gov.bs": 1, + "gov.bt": 1, + "gov.by": 1, + "gov.bz": 1, + "gov.cd": 1, + "gov.cl": 1, + "gov.cm": 1, + "gov.cn": 1, + "gov.co": 1, + "gov.cu": 1, + "gov.cx": 1, + "gov.cy": 1, + "gov.dm": 1, + "gov.do": 1, + "gov.dz": 1, + "gov.ec": 1, + "gov.ee": 1, + "gov.eg": 1, + "gov.et": 1, + "gov.fj": 1, + "gov.gd": 1, + "gov.ge": 1, + "gov.gh": 1, + "gov.gi": 1, + "gov.gn": 1, + "gov.gr": 1, + "gov.gu": 1, + "gov.gy": 1, + "gov.hk": 1, + "gov.ie": 1, + "gov.il": 1, + "gov.in": 1, + "gov.iq": 1, + "gov.ir": 1, + "gov.is": 1, + "gov.it": 1, + "gov.jo": 1, + "gov.kg": 1, + "gov.ki": 1, + "gov.km": 1, + "gov.kn": 1, + "gov.kp": 1, + "gov.kw": 1, + "gov.ky": 1, + "gov.kz": 1, + "gov.la": 1, + "gov.lb": 1, + "gov.lc": 1, + "gov.lk": 1, + "gov.lr": 1, + "gov.ls": 1, + "gov.lt": 1, + "gov.lv": 1, + "gov.ly": 1, + "gov.ma": 1, + "gov.me": 1, + "gov.mg": 1, + "gov.mk": 1, + "gov.ml": 1, + "gov.mn": 1, + "gov.mo": 1, + "gov.mr": 1, + "gov.ms": 1, + "gov.mu": 1, + "gov.mv": 1, + "gov.mw": 1, + "gov.my": 1, + "gov.mz": 1, + "gov.nc.tr": 1, + "gov.ng": 1, + "gov.nr": 1, + "gov.om": 1, + "gov.ph": 1, + "gov.pk": 1, + "gov.pl": 1, + "gov.pn": 1, + "gov.pr": 1, + "gov.ps": 1, + "gov.pt": 1, + "gov.py": 1, + "gov.qa": 1, + "gov.rs": 1, + "gov.ru": 1, + "gov.rw": 1, + "gov.sa": 1, + "gov.sb": 1, + "gov.sc": 1, + "gov.scot": 1, + "gov.sd": 1, + "gov.sg": 1, + "gov.sh": 1, + "gov.sl": 1, + "gov.so": 1, + "gov.ss": 1, + "gov.st": 1, + "gov.sx": 1, + "gov.sy": 1, + "gov.tj": 1, + "gov.tl": 1, + "gov.tm": 1, + "gov.tn": 1, + "gov.to": 1, + "gov.tr": 1, + "gov.tt": 1, + "gov.tw": 1, + "gov.ua": 1, + "gov.uk": 1, + "gov.vc": 1, + "gov.ve": 1, + "gov.vn": 1, + "gov.ws": 1, + "gov.za": 1, + "gov.zm": 1, + "gov.zw": 1, + "government.aero": 1, + "govt.nz": 1, + "gr.com": 1, + "gr.eu.org": 1, + "gr.it": 1, + "gr.jp": 1, + "grajewo.pl": 1, + "gran.no": 1, + "grandrapids.museum": 1, + "grane.no": 1, + "granvin.no": 1, + "graphox.us": 1, + "gratangen.no": 1, + "graz.museum": 1, + "greta.fr": 1, + "grimstad.no": 1, + "griw.gov.pl": 1, + "groks-the.info": 1, + "groks-this.info": 1, + "grondar.za": 1, + "grong.no": 1, + "grosseto.it": 1, + "groundhandling.aero": 1, + "group.aero": 1, + "grozny.ru": 1, + "grozny.su": 1, + "grp.lk": 1, + "gru.br": 1, + "grue.no": 1, + "gs.aa.no": 1, + "gs.ah.no": 1, + "gs.bu.no": 1, + "gs.cn": 1, + "gs.fm.no": 1, + "gs.hl.no": 1, + "gs.hm.no": 1, + "gs.jan-mayen.no": 1, + "gs.mr.no": 1, + "gs.nl.no": 1, + "gs.nt.no": 1, + "gs.of.no": 1, + "gs.ol.no": 1, + "gs.oslo.no": 1, + "gs.rl.no": 1, + "gs.sf.no": 1, + "gs.st.no": 1, + "gs.svalbard.no": 1, + "gs.tm.no": 1, + "gs.tr.no": 1, + "gs.va.no": 1, + "gs.vf.no": 1, + "gsj.bz": 1, + "gsm.pl": 1, + "gu.us": 1, + "guam.gu": 1, + "gub.uy": 1, + "guernsey.museum": 1, + "gujo.gifu.jp": 1, + "gulen.no": 1, + "gunma.jp": 1, + "guovdageaidnu.no": 1, + "gushikami.okinawa.jp": 1, + "gv.ao": 1, + "gv.at": 1, + "gv.vc": 1, + "gwangju.kr": 1, + "gwiddle.co.uk": 1, + "gx.cn": 1, + "gyeongbuk.kr": 1, + "gyeonggi.kr": 1, + "gyeongnam.kr": 1, + "gyokuto.kumamoto.jp": 1, + "gz.cn": 1, + "g\u00e1ivuotna.no": 1, + "g\u00e1ls\u00e1.no": 1, + "g\u00e1\u014bgaviika.no": 1, + "h.bg": 1, + "h.se": 1, + "ha.cn": 1, + "ha.no": 1, + "habikino.osaka.jp": 1, + "habmer.no": 1, + "haboro.hokkaido.jp": 1, + "hachijo.tokyo.jp": 1, + "hachinohe.aomori.jp": 1, + "hachioji.tokyo.jp": 1, + "hachirogata.akita.jp": 1, + "hadano.kanagawa.jp": 1, + "hadsel.no": 1, + "haebaru.okinawa.jp": 1, + "haga.tochigi.jp": 1, + "hagebostad.no": 1, + "hagi.yamaguchi.jp": 1, + "haibara.shizuoka.jp": 1, + "hakata.fukuoka.jp": 1, + "hakodate.hokkaido.jp": 1, + "hakone.kanagawa.jp": 1, + "hakuba.nagano.jp": 1, + "hakui.ishikawa.jp": 1, + "hakusan.ishikawa.jp": 1, + "halden.no": 1, + "half.host": 1, + "halloffame.museum": 1, + "halsa.no": 1, + "ham-radio-op.net": 1, + "hamada.shimane.jp": 1, + "hamamatsu.shizuoka.jp": 1, + "hamar.no": 1, + "hamaroy.no": 1, + "hamatama.saga.jp": 1, + "hamatonbetsu.hokkaido.jp": 1, + "hamburg.museum": 1, + "hammarfeasta.no": 1, + "hammerfest.no": 1, + "hamura.tokyo.jp": 1, + "hanamaki.iwate.jp": 1, + "hanamigawa.chiba.jp": 1, + "hanawa.fukushima.jp": 1, + "handa.aichi.jp": 1, + "handson.museum": 1, + "hanggliding.aero": 1, + "hannan.osaka.jp": 1, + "hanno.saitama.jp": 1, + "hanyu.saitama.jp": 1, + "hapmir.no": 1, + "happou.akita.jp": 1, + "hara.nagano.jp": 1, + "haram.no": 1, + "hareid.no": 1, + "harima.hyogo.jp": 1, + "harstad.no": 1, + "harvestcelebration.museum": 1, + "hasama.oita.jp": 1, + "hasami.nagasaki.jp": 1, + "hashbang.sh": 1, + "hashikami.aomori.jp": 1, + "hashima.gifu.jp": 1, + "hashimoto.wakayama.jp": 1, + "hasuda.saitama.jp": 1, + "hasura-app.io": 1, + "hasura.app": 1, + "hasvik.no": 1, + "hatogaya.saitama.jp": 1, + "hatoyama.saitama.jp": 1, + "hatsukaichi.hiroshima.jp": 1, + "hattfjelldal.no": 1, + "haugesund.no": 1, + "hawaii.museum": 1, + "hayakawa.yamanashi.jp": 1, + "hayashima.okayama.jp": 1, + "hazu.aichi.jp": 1, + "hb.cldmail.ru": 1, + "hb.cn": 1, + "he.cn": 1, + "health-carereform.com": 1, + "health.museum": 1, + "health.nz": 1, + "health.vn": 1, + "heguri.nara.jp": 1, + "heimatunduhren.museum": 1, + "hekinan.aichi.jp": 1, + "hellas.museum": 1, + "helsinki.museum": 1, + "hembygdsforbund.museum": 1, + "hemne.no": 1, + "hemnes.no": 1, + "hemsedal.no": 1, + "hepforge.org": 1, + "herad.no": 1, + "here-for-more.info": 1, + "heritage.museum": 1, + "herokuapp.com": 1, + "herokussl.com": 1, + "heroy.more-og-romsdal.no": 1, + "heroy.nordland.no": 1, + "her\u00f8y.m\u00f8re-og-romsdal.no": 1, + "her\u00f8y.nordland.no": 1, + "hi.cn": 1, + "hi.us": 1, + "hicam.net": 1, + "hichiso.gifu.jp": 1, + "hida.gifu.jp": 1, + "hidaka.hokkaido.jp": 1, + "hidaka.kochi.jp": 1, + "hidaka.saitama.jp": 1, + "hidaka.wakayama.jp": 1, + "hidora.com": 1, + "higashi.fukuoka.jp": 1, + "higashi.fukushima.jp": 1, + "higashi.okinawa.jp": 1, + "higashiagatsuma.gunma.jp": 1, + "higashichichibu.saitama.jp": 1, + "higashihiroshima.hiroshima.jp": 1, + "higashiizu.shizuoka.jp": 1, + "higashiizumo.shimane.jp": 1, + "higashikagawa.kagawa.jp": 1, + "higashikagura.hokkaido.jp": 1, + "higashikawa.hokkaido.jp": 1, + "higashikurume.tokyo.jp": 1, + "higashimatsushima.miyagi.jp": 1, + "higashimatsuyama.saitama.jp": 1, + "higashimurayama.tokyo.jp": 1, + "higashinaruse.akita.jp": 1, + "higashine.yamagata.jp": 1, + "higashiomi.shiga.jp": 1, + "higashiosaka.osaka.jp": 1, + "higashishirakawa.gifu.jp": 1, + "higashisumiyoshi.osaka.jp": 1, + "higashitsuno.kochi.jp": 1, + "higashiura.aichi.jp": 1, + "higashiyama.kyoto.jp": 1, + "higashiyamato.tokyo.jp": 1, + "higashiyodogawa.osaka.jp": 1, + "higashiyoshino.nara.jp": 1, + "hiji.oita.jp": 1, + "hikari.yamaguchi.jp": 1, + "hikawa.shimane.jp": 1, + "hikimi.shimane.jp": 1, + "hikone.shiga.jp": 1, + "himeji.hyogo.jp": 1, + "himeshima.oita.jp": 1, + "himi.toyama.jp": 1, + "hino.tokyo.jp": 1, + "hino.tottori.jp": 1, + "hinode.tokyo.jp": 1, + "hinohara.tokyo.jp": 1, + "hioki.kagoshima.jp": 1, + "hirado.nagasaki.jp": 1, + "hiraizumi.iwate.jp": 1, + "hirakata.osaka.jp": 1, + "hiranai.aomori.jp": 1, + "hirara.okinawa.jp": 1, + "hirata.fukushima.jp": 1, + "hiratsuka.kanagawa.jp": 1, + "hiraya.nagano.jp": 1, + "hirogawa.wakayama.jp": 1, + "hirokawa.fukuoka.jp": 1, + "hirono.fukushima.jp": 1, + "hirono.iwate.jp": 1, + "hiroo.hokkaido.jp": 1, + "hirosaki.aomori.jp": 1, + "hiroshima.jp": 1, + "hisayama.fukuoka.jp": 1, + "histoire.museum": 1, + "historical.museum": 1, + "historicalsociety.museum": 1, + "historichouses.museum": 1, + "historisch.museum": 1, + "historisches.museum": 1, + "history.museum": 1, + "historyofscience.museum": 1, + "hita.oita.jp": 1, + "hitachi.ibaraki.jp": 1, + "hitachinaka.ibaraki.jp": 1, + "hitachiomiya.ibaraki.jp": 1, + "hitachiota.ibaraki.jp": 1, + "hitra.no": 1, + "hizen.saga.jp": 1, + "hjartdal.no": 1, + "hjelmeland.no": 1, + "hk.cn": 1, + "hk.com": 1, + "hk.org": 1, + "hl.cn": 1, + "hl.no": 1, + "hm.no": 1, + "hn.cn": 1, + "hobby-site.com": 1, + "hobby-site.org": 1, + "hobol.no": 1, + "hob\u00f8l.no": 1, + "hof.no": 1, + "hofu.yamaguchi.jp": 1, + "hokkaido.jp": 1, + "hokksund.no": 1, + "hokuryu.hokkaido.jp": 1, + "hokuto.hokkaido.jp": 1, + "hokuto.yamanashi.jp": 1, + "hol.no": 1, + "hole.no": 1, + "holmestrand.no": 1, + "holtalen.no": 1, + "holt\u00e5len.no": 1, + "home-webserver.de": 1, + "home.dyndns.org": 1, + "homebuilt.aero": 1, + "homedns.org": 1, + "homeftp.net": 1, + "homeftp.org": 1, + "homeip.net": 1, + "homelink.one": 1, + "homelinux.com": 1, + "homelinux.net": 1, + "homelinux.org": 1, + "homeoffice.gov.uk": 1, + "homesecuritymac.com": 1, + "homesecuritypc.com": 1, + "homeunix.com": 1, + "homeunix.net": 1, + "homeunix.org": 1, + "honai.ehime.jp": 1, + "honbetsu.hokkaido.jp": 1, + "honefoss.no": 1, + "hongo.hiroshima.jp": 1, + "honjo.akita.jp": 1, + "honjo.saitama.jp": 1, + "honjyo.akita.jp": 1, + "hopto.me": 1, + "hopto.org": 1, + "hornindal.no": 1, + "horokanai.hokkaido.jp": 1, + "horology.museum": 1, + "horonobe.hokkaido.jp": 1, + "horten.no": 1, + "hostedpi.com": 1, + "hosting-cluster.nl": 1, + "hosting.myjino.ru": 2, + "hostyhosting.io": 1, + "hotel.hu": 1, + "hotel.lk": 1, + "hotel.tz": 1, + "house.museum": 1, + "hoyanger.no": 1, + "hoylandet.no": 1, + "hr.eu.org": 1, + "hs.kr": 1, + "hs.run": 1, + "hs.zone": 1, + "hu.com": 1, + "hu.eu.org": 1, + "hu.net": 1, + "huissier-justice.fr": 1, + "humanities.museum": 1, + "hurdal.no": 1, + "hurum.no": 1, + "hvaler.no": 1, + "hyllestad.no": 1, + "hyogo.jp": 1, + "hyuga.miyazaki.jp": 1, + "hzc.io": 1, + "h\u00e1bmer.no": 1, + "h\u00e1mm\u00e1rfeasta.no": 1, + "h\u00e1pmir.no": 1, + "h\u00e4kkinen.fi": 1, + "h\u00e5.no": 1, + "h\u00e6gebostad.no": 1, + "h\u00f8nefoss.no": 1, + "h\u00f8yanger.no": 1, + "h\u00f8ylandet.no": 1, + "i.bg": 1, + "i.ng": 1, + "i.ph": 1, + "i.se": 1, + "i234.me": 1, + "ia.us": 1, + "iamallama.com": 1, + "ibara.okayama.jp": 1, + "ibaraki.ibaraki.jp": 1, + "ibaraki.jp": 1, + "ibaraki.osaka.jp": 1, + "ibestad.no": 1, + "ibigawa.gifu.jp": 1, + "ic.gov.pl": 1, + "ichiba.tokushima.jp": 1, + "ichihara.chiba.jp": 1, + "ichikai.tochigi.jp": 1, + "ichikawa.chiba.jp": 1, + "ichikawa.hyogo.jp": 1, + "ichikawamisato.yamanashi.jp": 1, + "ichinohe.iwate.jp": 1, + "ichinomiya.aichi.jp": 1, + "ichinomiya.chiba.jp": 1, + "ichinoseki.iwate.jp": 1, + "id.au": 1, + "id.ir": 1, + "id.lv": 1, + "id.ly": 1, + "id.us": 1, + "ide.kyoto.jp": 1, + "idf.il": 1, + "idrett.no": 1, + "idv.hk": 1, + "idv.tw": 1, + "ie.eu.org": 1, + "if.ua": 1, + "iglesias-carbonia.it": 1, + "iglesiascarbonia.it": 1, + "iheya.okinawa.jp": 1, + "iida.nagano.jp": 1, + "iide.yamagata.jp": 1, + "iijima.nagano.jp": 1, + "iitate.fukushima.jp": 1, + "iiyama.nagano.jp": 1, + "iizuka.fukuoka.jp": 1, + "iizuna.nagano.jp": 1, + "ikaruga.nara.jp": 1, + "ikata.ehime.jp": 1, + "ikawa.akita.jp": 1, + "ikeda.fukui.jp": 1, + "ikeda.gifu.jp": 1, + "ikeda.hokkaido.jp": 1, + "ikeda.nagano.jp": 1, + "ikeda.osaka.jp": 1, + "iki.fi": 1, + "iki.nagasaki.jp": 1, + "ikoma.nara.jp": 1, + "ikusaka.nagano.jp": 1, + "il.eu.org": 1, + "il.us": 1, + "ilawa.pl": 1, + "illustration.museum": 1, + "ilovecollege.info": 1, + "im.it": 1, + "imabari.ehime.jp": 1, + "imageandsound.museum": 1, + "imakane.hokkaido.jp": 1, + "imari.saga.jp": 1, + "imb.br": 1, + "imizu.toyama.jp": 1, + "imperia.it": 1, + "impertrix.com": 1, + "impertrixcdn.com": 1, + "in-addr.arpa": 1, + "in-berlin.de": 1, + "in-brb.de": 1, + "in-butter.de": 1, + "in-dsl.de": 1, + "in-dsl.net": 1, + "in-dsl.org": 1, + "in-the-band.net": 1, + "in-vpn.de": 1, + "in-vpn.net": 1, + "in-vpn.org": 1, + "in.eu.org": 1, + "in.futurecms.at": 2, + "in.london": 1, + "in.na": 1, + "in.net": 1, + "in.ni": 1, + "in.rs": 1, + "in.th": 1, + "in.ua": 1, + "in.us": 1, + "ina.ibaraki.jp": 1, + "ina.nagano.jp": 1, + "ina.saitama.jp": 1, + "inabe.mie.jp": 1, + "inagawa.hyogo.jp": 1, + "inagi.tokyo.jp": 1, + "inami.toyama.jp": 1, + "inami.wakayama.jp": 1, + "inashiki.ibaraki.jp": 1, + "inatsuki.fukuoka.jp": 1, + "inawashiro.fukushima.jp": 1, + "inazawa.aichi.jp": 1, + "inc.hk": 1, + "incheon.kr": 1, + "ind.br": 1, + "ind.gt": 1, + "ind.in": 1, + "ind.kw": 1, + "ind.tn": 1, + "inderoy.no": 1, + "inder\u00f8y.no": 1, + "indian.museum": 1, + "indiana.museum": 1, + "indianapolis.museum": 1, + "indianmarket.museum": 1, + "indie.porn": 1, + "indigena.bo": 1, + "industria.bo": 1, + "ine.kyoto.jp": 1, + "inf.br": 1, + "inf.cu": 1, + "inf.mk": 1, + "inf.ua": 1, + "info.at": 1, + "info.au": 1, + "info.az": 1, + "info.bb": 1, + "info.bo": 1, + "info.co": 1, + "info.cx": 1, + "info.ec": 1, + "info.et": 1, + "info.fj": 1, + "info.gu": 1, + "info.ht": 1, + "info.hu": 1, + "info.ke": 1, + "info.ki": 1, + "info.la": 1, + "info.ls": 1, + "info.mv": 1, + "info.na": 1, + "info.nf": 1, + "info.ni": 1, + "info.nr": 1, + "info.pk": 1, + "info.pl": 1, + "info.pr": 1, + "info.ro": 1, + "info.sd": 1, + "info.tn": 1, + "info.tr": 1, + "info.tt": 1, + "info.tz": 1, + "info.ve": 1, + "info.vn": 1, + "info.zm": 1, + "ing.pa": 1, + "ingatlan.hu": 1, + "ino.kochi.jp": 1, + "instantcloud.cn": 1, + "insurance.aero": 1, + "int.ar": 1, + "int.az": 1, + "int.bo": 1, + "int.ci": 1, + "int.co": 1, + "int.eu.org": 1, + "int.is": 1, + "int.la": 1, + "int.lk": 1, + "int.mv": 1, + "int.mw": 1, + "int.ni": 1, + "int.pt": 1, + "int.ru": 1, + "int.tj": 1, + "int.tt": 1, + "int.ve": 1, + "int.vn": 1, + "intelligence.museum": 1, + "interactive.museum": 1, + "internet-dns.de": 1, + "intl.tn": 1, + "inuyama.aichi.jp": 1, + "inzai.chiba.jp": 1, + "io.kg": 1, + "iobb.net": 1, + "ip6.arpa": 1, + "ipifony.net": 1, + "iraq.museum": 1, + "iris.arpa": 1, + "iron.museum": 1, + "iruma.saitama.jp": 1, + "is-a-anarchist.com": 1, + "is-a-blogger.com": 1, + "is-a-bookkeeper.com": 1, + "is-a-bruinsfan.org": 1, + "is-a-bulls-fan.com": 1, + "is-a-candidate.org": 1, + "is-a-caterer.com": 1, + "is-a-celticsfan.org": 1, + "is-a-chef.com": 1, + "is-a-chef.net": 1, + "is-a-chef.org": 1, + "is-a-conservative.com": 1, + "is-a-cpa.com": 1, + "is-a-cubicle-slave.com": 1, + "is-a-democrat.com": 1, + "is-a-designer.com": 1, + "is-a-doctor.com": 1, + "is-a-financialadvisor.com": 1, + "is-a-geek.com": 1, + "is-a-geek.net": 1, + "is-a-geek.org": 1, + "is-a-green.com": 1, + "is-a-guru.com": 1, + "is-a-hard-worker.com": 1, + "is-a-hunter.com": 1, + "is-a-knight.org": 1, + "is-a-landscaper.com": 1, + "is-a-lawyer.com": 1, + "is-a-liberal.com": 1, + "is-a-libertarian.com": 1, + "is-a-linux-user.org": 1, + "is-a-llama.com": 1, + "is-a-musician.com": 1, + "is-a-nascarfan.com": 1, + "is-a-nurse.com": 1, + "is-a-painter.com": 1, + "is-a-patsfan.org": 1, + "is-a-personaltrainer.com": 1, + "is-a-photographer.com": 1, + "is-a-player.com": 1, + "is-a-republican.com": 1, + "is-a-rockstar.com": 1, + "is-a-socialist.com": 1, + "is-a-soxfan.org": 1, + "is-a-student.com": 1, + "is-a-teacher.com": 1, + "is-a-techie.com": 1, + "is-a-therapist.com": 1, + "is-an-accountant.com": 1, + "is-an-actor.com": 1, + "is-an-actress.com": 1, + "is-an-anarchist.com": 1, + "is-an-artist.com": 1, + "is-an-engineer.com": 1, + "is-an-entertainer.com": 1, + "is-by.us": 1, + "is-certified.com": 1, + "is-found.org": 1, + "is-gone.com": 1, + "is-into-anime.com": 1, + "is-into-cars.com": 1, + "is-into-cartoons.com": 1, + "is-into-games.com": 1, + "is-leet.com": 1, + "is-lost.org": 1, + "is-not-certified.com": 1, + "is-saved.org": 1, + "is-slick.com": 1, + "is-uberleet.com": 1, + "is-very-bad.org": 1, + "is-very-evil.org": 1, + "is-very-good.org": 1, + "is-very-nice.org": 1, + "is-very-sweet.org": 1, + "is-with-theband.com": 1, + "is.eu.org": 1, + "is.gov.pl": 1, + "is.it": 1, + "isa-geek.com": 1, + "isa-geek.net": 1, + "isa-geek.org": 1, + "isa-hockeynut.com": 1, + "isa.kagoshima.jp": 1, + "isa.us": 1, + "isahaya.nagasaki.jp": 1, + "ise.mie.jp": 1, + "isehara.kanagawa.jp": 1, + "isen.kagoshima.jp": 1, + "isernia.it": 1, + "iserv.dev": 1, + "isesaki.gunma.jp": 1, + "ishigaki.okinawa.jp": 1, + "ishikari.hokkaido.jp": 1, + "ishikawa.fukushima.jp": 1, + "ishikawa.jp": 1, + "ishikawa.okinawa.jp": 1, + "ishinomaki.miyagi.jp": 1, + "isla.pr": 1, + "isleofman.museum": 1, + "isshiki.aichi.jp": 1, + "issmarterthanyou.com": 1, + "isteingeek.de": 1, + "istmein.de": 1, + "isumi.chiba.jp": 1, + "it.ao": 1, + "it.eu.org": 1, + "itabashi.tokyo.jp": 1, + "itako.ibaraki.jp": 1, + "itakura.gunma.jp": 1, + "itami.hyogo.jp": 1, + "itano.tokushima.jp": 1, + "itayanagi.aomori.jp": 1, + "ito.shizuoka.jp": 1, + "itoigawa.niigata.jp": 1, + "itoman.okinawa.jp": 1, + "its.me": 1, + "ivano-frankivsk.ua": 1, + "ivanovo.su": 1, + "iveland.no": 1, + "ivgu.no": 1, + "iwade.wakayama.jp": 1, + "iwafune.tochigi.jp": 1, + "iwaizumi.iwate.jp": 1, + "iwaki.fukushima.jp": 1, + "iwakuni.yamaguchi.jp": 1, + "iwakura.aichi.jp": 1, + "iwama.ibaraki.jp": 1, + "iwamizawa.hokkaido.jp": 1, + "iwanai.hokkaido.jp": 1, + "iwanuma.miyagi.jp": 1, + "iwata.shizuoka.jp": 1, + "iwate.iwate.jp": 1, + "iwate.jp": 1, + "iwatsuki.saitama.jp": 1, + "iwi.nz": 1, + "iyo.ehime.jp": 1, + "iz.hr": 1, + "izena.okinawa.jp": 1, + "izu.shizuoka.jp": 1, + "izumi.kagoshima.jp": 1, + "izumi.osaka.jp": 1, + "izumiotsu.osaka.jp": 1, + "izumisano.osaka.jp": 1, + "izumizaki.fukushima.jp": 1, + "izumo.shimane.jp": 1, + "izumozaki.niigata.jp": 1, + "izunokuni.shizuoka.jp": 1, + "j.bg": 1, + "j.layershift.co.uk": 1, + "j.scaleforce.com.cy": 1, + "jab.br": 1, + "jambyl.su": 1, + "jamison.museum": 1, + "jampa.br": 1, + "jan-mayen.no": 1, + "jaworzno.pl": 1, + "jcloud.ik-server.com": 1, + "jdevcloud.com": 1, + "jdf.br": 1, + "jefferson.museum": 1, + "jeju.kr": 1, + "jelastic.dogado.eu": 1, + "jelastic.regruhosting.ru": 1, + "jelastic.saveincloud.net": 1, + "jelastic.team": 1, + "jele.cloud": 1, + "jele.club": 1, + "jele.host": 1, + "jele.io": 1, + "jele.site": 1, + "jelenia-gora.pl": 1, + "jeonbuk.kr": 1, + "jeonnam.kr": 1, + "jerusalem.museum": 1, + "jessheim.no": 1, + "jevnaker.no": 1, + "jewelry.museum": 1, + "jewish.museum": 1, + "jewishart.museum": 1, + "jfk.museum": 1, + "jgora.pl": 1, + "jinsekikogen.hiroshima.jp": 1, + "jl.cn": 1, + "jls-sto1.elastx.net": 1, + "jm": 2, + "joboji.iwate.jp": 1, + "jobs.tt": 1, + "joetsu.niigata.jp": 1, + "jogasz.hu": 1, + "johana.toyama.jp": 1, + "joinville.br": 1, + "jolster.no": 1, + "jondal.no": 1, + "jor.br": 1, + "jorpeland.no": 1, + "joso.ibaraki.jp": 1, + "journal.aero": 1, + "journalism.museum": 1, + "journalist.aero": 1, + "joyo.kyoto.jp": 1, + "jozi.biz": 1, + "jp.eu.org": 1, + "jp.kg": 1, + "jp.md": 1, + "jp.net": 1, + "jpn.com": 1, + "js.cn": 1, + "js.org": 1, + "js.wpenginepowered.com": 1, + "judaica.museum": 1, + "judygarland.museum": 1, + "juedisches.museum": 1, + "juif.museum": 1, + "jur.pro": 1, + "jus.br": 1, + "jx.cn": 1, + "j\u00f8lster.no": 1, + "j\u00f8rpeland.no": 1, + "k.bg": 1, + "k.se": 1, + "k12.ak.us": 1, + "k12.al.us": 1, + "k12.ar.us": 1, + "k12.as.us": 1, + "k12.az.us": 1, + "k12.ca.us": 1, + "k12.co.us": 1, + "k12.ct.us": 1, + "k12.dc.us": 1, + "k12.de.us": 1, + "k12.ec": 1, + "k12.fl.us": 1, + "k12.ga.us": 1, + "k12.gu.us": 1, + "k12.ia.us": 1, + "k12.id.us": 1, + "k12.il": 1, + "k12.il.us": 1, + "k12.in.us": 1, + "k12.ks.us": 1, + "k12.ky.us": 1, + "k12.la.us": 1, + "k12.ma.us": 1, + "k12.md.us": 1, + "k12.me.us": 1, + "k12.mi.us": 1, + "k12.mn.us": 1, + "k12.mo.us": 1, + "k12.ms.us": 1, + "k12.mt.us": 1, + "k12.nc.us": 1, + "k12.ne.us": 1, + "k12.nh.us": 1, + "k12.nj.us": 1, + "k12.nm.us": 1, + "k12.nv.us": 1, + "k12.ny.us": 1, + "k12.oh.us": 1, + "k12.ok.us": 1, + "k12.or.us": 1, + "k12.pa.us": 1, + "k12.pr.us": 1, + "k12.sc.us": 1, + "k12.tn.us": 1, + "k12.tr": 1, + "k12.tx.us": 1, + "k12.ut.us": 1, + "k12.va.us": 1, + "k12.vi": 1, + "k12.vi.us": 1, + "k12.vt.us": 1, + "k12.wa.us": 1, + "k12.wi.us": 1, + "k12.wy.us": 1, + "kaas.gg": 1, + "kadena.okinawa.jp": 1, + "kadogawa.miyazaki.jp": 1, + "kadoma.osaka.jp": 1, + "kafjord.no": 1, + "kaga.ishikawa.jp": 1, + "kagami.kochi.jp": 1, + "kagamiishi.fukushima.jp": 1, + "kagamino.okayama.jp": 1, + "kagawa.jp": 1, + "kagoshima.jp": 1, + "kagoshima.kagoshima.jp": 1, + "kaho.fukuoka.jp": 1, + "kahoku.ishikawa.jp": 1, + "kahoku.yamagata.jp": 1, + "kai.yamanashi.jp": 1, + "kainan.tokushima.jp": 1, + "kainan.wakayama.jp": 1, + "kaisei.kanagawa.jp": 1, + "kaita.hiroshima.jp": 1, + "kaizuka.osaka.jp": 1, + "kakamigahara.gifu.jp": 1, + "kakegawa.shizuoka.jp": 1, + "kakinoki.shimane.jp": 1, + "kakogawa.hyogo.jp": 1, + "kakuda.miyagi.jp": 1, + "kalisz.pl": 1, + "kalmykia.ru": 1, + "kalmykia.su": 1, + "kaluga.su": 1, + "kamagaya.chiba.jp": 1, + "kamaishi.iwate.jp": 1, + "kamakura.kanagawa.jp": 1, + "kameoka.kyoto.jp": 1, + "kameyama.mie.jp": 1, + "kami.kochi.jp": 1, + "kami.miyagi.jp": 1, + "kamiamakusa.kumamoto.jp": 1, + "kamifurano.hokkaido.jp": 1, + "kamigori.hyogo.jp": 1, + "kamiichi.toyama.jp": 1, + "kamiizumi.saitama.jp": 1, + "kamijima.ehime.jp": 1, + "kamikawa.hokkaido.jp": 1, + "kamikawa.hyogo.jp": 1, + "kamikawa.saitama.jp": 1, + "kamikitayama.nara.jp": 1, + "kamikoani.akita.jp": 1, + "kamimine.saga.jp": 1, + "kaminokawa.tochigi.jp": 1, + "kaminoyama.yamagata.jp": 1, + "kamioka.akita.jp": 1, + "kamisato.saitama.jp": 1, + "kamishihoro.hokkaido.jp": 1, + "kamisu.ibaraki.jp": 1, + "kamisunagawa.hokkaido.jp": 1, + "kamitonda.wakayama.jp": 1, + "kamitsue.oita.jp": 1, + "kamo.kyoto.jp": 1, + "kamo.niigata.jp": 1, + "kamoenai.hokkaido.jp": 1, + "kamogawa.chiba.jp": 1, + "kanagawa.jp": 1, + "kanan.osaka.jp": 1, + "kanazawa.ishikawa.jp": 1, + "kanegasaki.iwate.jp": 1, + "kaneyama.fukushima.jp": 1, + "kaneyama.yamagata.jp": 1, + "kani.gifu.jp": 1, + "kanie.aichi.jp": 1, + "kanmaki.nara.jp": 1, + "kanna.gunma.jp": 1, + "kannami.shizuoka.jp": 1, + "kanonji.kagawa.jp": 1, + "kanoya.kagoshima.jp": 1, + "kanra.gunma.jp": 1, + "kanuma.tochigi.jp": 1, + "kanzaki.saga.jp": 1, + "karacol.su": 1, + "karaganda.su": 1, + "karasjohka.no": 1, + "karasjok.no": 1, + "karasuyama.tochigi.jp": 1, + "karate.museum": 1, + "karatsu.saga.jp": 1, + "karelia.su": 1, + "karikatur.museum": 1, + "kariwa.niigata.jp": 1, + "kariya.aichi.jp": 1, + "karlsoy.no": 1, + "karmoy.no": 1, + "karm\u00f8y.no": 1, + "karpacz.pl": 1, + "kartuzy.pl": 1, + "karuizawa.nagano.jp": 1, + "karumai.iwate.jp": 1, + "kasahara.gifu.jp": 1, + "kasai.hyogo.jp": 1, + "kasama.ibaraki.jp": 1, + "kasamatsu.gifu.jp": 1, + "kasaoka.okayama.jp": 1, + "kashiba.nara.jp": 1, + "kashihara.nara.jp": 1, + "kashima.ibaraki.jp": 1, + "kashima.saga.jp": 1, + "kashiwa.chiba.jp": 1, + "kashiwara.osaka.jp": 1, + "kashiwazaki.niigata.jp": 1, + "kasserver.com": 1, + "kasuga.fukuoka.jp": 1, + "kasuga.hyogo.jp": 1, + "kasugai.aichi.jp": 1, + "kasukabe.saitama.jp": 1, + "kasumigaura.ibaraki.jp": 1, + "kasuya.fukuoka.jp": 1, + "kaszuby.pl": 1, + "katagami.akita.jp": 1, + "katano.osaka.jp": 1, + "katashina.gunma.jp": 1, + "katori.chiba.jp": 1, + "katowice.pl": 1, + "katsuragi.nara.jp": 1, + "katsuragi.wakayama.jp": 1, + "katsushika.tokyo.jp": 1, + "katsuura.chiba.jp": 1, + "katsuyama.fukui.jp": 1, + "kautokeino.no": 1, + "kawaba.gunma.jp": 1, + "kawachinagano.osaka.jp": 1, + "kawagoe.mie.jp": 1, + "kawagoe.saitama.jp": 1, + "kawaguchi.saitama.jp": 1, + "kawahara.tottori.jp": 1, + "kawai.iwate.jp": 1, + "kawai.nara.jp": 1, + "kawajima.saitama.jp": 1, + "kawakami.nagano.jp": 1, + "kawakami.nara.jp": 1, + "kawakita.ishikawa.jp": 1, + "kawamata.fukushima.jp": 1, + "kawaminami.miyazaki.jp": 1, + "kawanabe.kagoshima.jp": 1, + "kawanehon.shizuoka.jp": 1, + "kawanishi.hyogo.jp": 1, + "kawanishi.nara.jp": 1, + "kawanishi.yamagata.jp": 1, + "kawara.fukuoka.jp": 1, + "kawasaki.jp": 2, + "kawasaki.miyagi.jp": 1, + "kawatana.nagasaki.jp": 1, + "kawaue.gifu.jp": 1, + "kawazu.shizuoka.jp": 1, + "kayabe.hokkaido.jp": 1, + "kazimierz-dolny.pl": 1, + "kazo.saitama.jp": 1, + "kazuno.akita.jp": 1, + "keisen.fukuoka.jp": 1, + "kembuchi.hokkaido.jp": 1, + "kep.tr": 1, + "kepno.pl": 1, + "ketrzyn.pl": 1, + "keymachine.de": 1, + "kg.kr": 1, + "kh": 2, + "kh.ua": 1, + "khakassia.su": 1, + "kharkiv.ua": 1, + "kharkov.ua": 1, + "kherson.ua": 1, + "khmelnitskiy.ua": 1, + "khmelnytskyi.ua": 1, + "khplay.nl": 1, + "kibichuo.okayama.jp": 1, + "kicks-ass.net": 1, + "kicks-ass.org": 1, + "kids.museum": 1, + "kids.us": 1, + "kiev.ua": 1, + "kiho.mie.jp": 1, + "kihoku.ehime.jp": 1, + "kijo.miyazaki.jp": 1, + "kikonai.hokkaido.jp": 1, + "kikuchi.kumamoto.jp": 1, + "kikugawa.shizuoka.jp": 1, + "kimino.wakayama.jp": 1, + "kimitsu.chiba.jp": 1, + "kimobetsu.hokkaido.jp": 1, + "kin.okinawa.jp": 1, + "kinghost.net": 1, + "kinko.kagoshima.jp": 1, + "kinokawa.wakayama.jp": 1, + "kira.aichi.jp": 1, + "kirkenes.no": 1, + "kirovograd.ua": 1, + "kiryu.gunma.jp": 1, + "kisarazu.chiba.jp": 1, + "kishiwada.osaka.jp": 1, + "kiso.nagano.jp": 1, + "kisofukushima.nagano.jp": 1, + "kisosaki.mie.jp": 1, + "kita.kyoto.jp": 1, + "kita.osaka.jp": 1, + "kita.tokyo.jp": 1, + "kitaaiki.nagano.jp": 1, + "kitaakita.akita.jp": 1, + "kitadaito.okinawa.jp": 1, + "kitagata.gifu.jp": 1, + "kitagata.saga.jp": 1, + "kitagawa.kochi.jp": 1, + "kitagawa.miyazaki.jp": 1, + "kitahata.saga.jp": 1, + "kitahiroshima.hokkaido.jp": 1, + "kitakami.iwate.jp": 1, + "kitakata.fukushima.jp": 1, + "kitakata.miyazaki.jp": 1, + "kitakyushu.jp": 2, + "kitami.hokkaido.jp": 1, + "kitamoto.saitama.jp": 1, + "kitanakagusuku.okinawa.jp": 1, + "kitashiobara.fukushima.jp": 1, + "kitaura.miyazaki.jp": 1, + "kitayama.wakayama.jp": 1, + "kiwa.mie.jp": 1, + "kiwi.nz": 1, + "kiyama.saga.jp": 1, + "kiyokawa.kanagawa.jp": 1, + "kiyosato.hokkaido.jp": 1, + "kiyose.tokyo.jp": 1, + "kiyosu.aichi.jp": 1, + "kizu.kyoto.jp": 1, + "klabu.no": 1, + "klepp.no": 1, + "klodzko.pl": 1, + "kl\u00e6bu.no": 1, + "km.ua": 1, + "kmpsp.gov.pl": 1, + "knightpoint.systems": 1, + "knowsitall.info": 1, + "knx-server.net": 1, + "kobayashi.miyazaki.jp": 1, + "kobe.jp": 2, + "kobierzyce.pl": 1, + "kochi.jp": 1, + "kochi.kochi.jp": 1, + "kodaira.tokyo.jp": 1, + "koebenhavn.museum": 1, + "koeln.museum": 1, + "kofu.yamanashi.jp": 1, + "koga.fukuoka.jp": 1, + "koga.ibaraki.jp": 1, + "koganei.tokyo.jp": 1, + "koge.tottori.jp": 1, + "koka.shiga.jp": 1, + "kokonoe.oita.jp": 1, + "kokubunji.tokyo.jp": 1, + "kolobrzeg.pl": 1, + "komae.tokyo.jp": 1, + "komagane.nagano.jp": 1, + "komaki.aichi.jp": 1, + "komatsu.ishikawa.jp": 1, + "komatsushima.tokushima.jp": 1, + "komforb.se": 1, + "kommunalforbund.se": 1, + "kommune.no": 1, + "komono.mie.jp": 1, + "komoro.nagano.jp": 1, + "komvux.se": 1, + "konan.aichi.jp": 1, + "konan.shiga.jp": 1, + "kongsberg.no": 1, + "kongsvinger.no": 1, + "konin.pl": 1, + "konskowola.pl": 1, + "konsulat.gov.pl": 1, + "konyvelo.hu": 1, + "koori.fukushima.jp": 1, + "kopervik.no": 1, + "koriyama.fukushima.jp": 1, + "koryo.nara.jp": 1, + "kosai.shizuoka.jp": 1, + "kosaka.akita.jp": 1, + "kosei.shiga.jp": 1, + "koshigaya.saitama.jp": 1, + "koshimizu.hokkaido.jp": 1, + "koshu.yamanashi.jp": 1, + "kosuge.yamanashi.jp": 1, + "kota.aichi.jp": 1, + "koto.shiga.jp": 1, + "koto.tokyo.jp": 1, + "kotohira.kagawa.jp": 1, + "kotoura.tottori.jp": 1, + "kouhoku.saga.jp": 1, + "kounosu.saitama.jp": 1, + "kouyama.kagoshima.jp": 1, + "kouzushima.tokyo.jp": 1, + "koya.wakayama.jp": 1, + "koza.wakayama.jp": 1, + "kozagawa.wakayama.jp": 1, + "kozaki.chiba.jp": 1, + "kozow.com": 1, + "kppsp.gov.pl": 1, + "kr.com": 1, + "kr.eu.org": 1, + "kr.it": 1, + "kr.ua": 1, + "kraanghke.no": 1, + "kragero.no": 1, + "krager\u00f8.no": 1, + "krakow.pl": 1, + "krasnik.pl": 1, + "krasnodar.su": 1, + "kristiansand.no": 1, + "kristiansund.no": 1, + "krodsherad.no": 1, + "krokstadelva.no": 1, + "krym.ua": 1, + "kr\u00e5anghke.no": 1, + "kr\u00f8dsherad.no": 1, + "ks.ua": 1, + "ks.us": 1, + "kuchinotsu.nagasaki.jp": 1, + "kudamatsu.yamaguchi.jp": 1, + "kudoyama.wakayama.jp": 1, + "kui.hiroshima.jp": 1, + "kuji.iwate.jp": 1, + "kuju.oita.jp": 1, + "kujukuri.chiba.jp": 1, + "kuki.saitama.jp": 1, + "kumagaya.saitama.jp": 1, + "kumakogen.ehime.jp": 1, + "kumamoto.jp": 1, + "kumamoto.kumamoto.jp": 1, + "kumano.hiroshima.jp": 1, + "kumano.mie.jp": 1, + "kumatori.osaka.jp": 1, + "kumejima.okinawa.jp": 1, + "kumenan.okayama.jp": 1, + "kumiyama.kyoto.jp": 1, + "kunden.ortsinfo.at": 2, + "kunigami.okinawa.jp": 1, + "kunimi.fukushima.jp": 1, + "kunisaki.oita.jp": 1, + "kunitachi.tokyo.jp": 1, + "kunitomi.miyazaki.jp": 1, + "kunneppu.hokkaido.jp": 1, + "kunohe.iwate.jp": 1, + "kunst.museum": 1, + "kunstsammlung.museum": 1, + "kunstunddesign.museum": 1, + "kurashiki.okayama.jp": 1, + "kurate.fukuoka.jp": 1, + "kure.hiroshima.jp": 1, + "kurgan.su": 1, + "kuriyama.hokkaido.jp": 1, + "kurobe.toyama.jp": 1, + "kurogi.fukuoka.jp": 1, + "kuroishi.aomori.jp": 1, + "kuroiso.tochigi.jp": 1, + "kuromatsunai.hokkaido.jp": 1, + "kurotaki.nara.jp": 1, + "kurume.fukuoka.jp": 1, + "kusatsu.gunma.jp": 1, + "kusatsu.shiga.jp": 1, + "kushima.miyazaki.jp": 1, + "kushimoto.wakayama.jp": 1, + "kushiro.hokkaido.jp": 1, + "kustanai.ru": 1, + "kustanai.su": 1, + "kusu.oita.jp": 1, + "kutchan.hokkaido.jp": 1, + "kutno.pl": 1, + "kuwana.mie.jp": 1, + "kuzumaki.iwate.jp": 1, + "kv.ua": 1, + "kvafjord.no": 1, + "kvalsund.no": 1, + "kvam.no": 1, + "kvanangen.no": 1, + "kvinesdal.no": 1, + "kvinnherad.no": 1, + "kviteseid.no": 1, + "kvitsoy.no": 1, + "kvits\u00f8y.no": 1, + "kv\u00e6fjord.no": 1, + "kv\u00e6nangen.no": 1, + "kwp.gov.pl": 1, + "kwpsp.gov.pl": 1, + "ky.us": 1, + "kyiv.ua": 1, + "kyonan.chiba.jp": 1, + "kyotamba.kyoto.jp": 1, + "kyotanabe.kyoto.jp": 1, + "kyotango.kyoto.jp": 1, + "kyoto.jp": 1, + "kyowa.akita.jp": 1, + "kyowa.hokkaido.jp": 1, + "kyuragi.saga.jp": 1, + "k\u00e1r\u00e1\u0161johka.no": 1, + "k\u00e5fjord.no": 1, + "l-o-g-i-n.de": 1, + "l.bg": 1, + "l.se": 1, + "la-spezia.it": 1, + "la.us": 1, + "laakesvuemie.no": 1, + "lab.ms": 1, + "labor.museum": 1, + "labour.museum": 1, + "lahppi.no": 1, + "lajolla.museum": 1, + "lakas.hu": 1, + "lanbib.se": 1, + "lancashire.museum": 1, + "land-4-sale.us": 1, + "landes.museum": 1, + "landing.myjino.ru": 2, + "langevag.no": 1, + "langev\u00e5g.no": 1, + "lans.museum": 1, + "lapy.pl": 1, + "laquila.it": 1, + "lardal.no": 1, + "larsson.museum": 1, + "larvik.no": 1, + "laspezia.it": 1, + "latina.it": 1, + "lavagis.no": 1, + "lavangen.no": 1, + "law.pro": 1, + "law.za": 1, + "laz.it": 1, + "lazio.it": 1, + "lc.it": 1, + "lcl.dev": 2, + "lcube-server.de": 1, + "le.it": 1, + "leadpages.co": 1, + "leangaviika.no": 1, + "leasing.aero": 1, + "lea\u014bgaviika.no": 1, + "lebesby.no": 1, + "lebork.pl": 1, + "lebtimnetz.de": 1, + "lecce.it": 1, + "lecco.it": 1, + "leczna.pl": 1, + "leg.br": 1, + "legnica.pl": 1, + "leikanger.no": 1, + "leirfjord.no": 1, + "leirvik.no": 1, + "leitungsen.de": 1, + "leka.no": 1, + "leksvik.no": 1, + "lel.br": 1, + "lelux.site": 1, + "lenug.su": 1, + "lenvik.no": 1, + "lerdal.no": 1, + "lesja.no": 1, + "levanger.no": 1, + "lewismiller.museum": 1, + "lezajsk.pl": 1, + "lg.jp": 1, + "lg.ua": 1, + "li.it": 1, + "lib.ak.us": 1, + "lib.al.us": 1, + "lib.ar.us": 1, + "lib.as.us": 1, + "lib.az.us": 1, + "lib.ca.us": 1, + "lib.co.us": 1, + "lib.ct.us": 1, + "lib.dc.us": 1, + "lib.de.us": 1, + "lib.ee": 1, + "lib.fl.us": 1, + "lib.ga.us": 1, + "lib.gu.us": 1, + "lib.hi.us": 1, + "lib.ia.us": 1, + "lib.id.us": 1, + "lib.il.us": 1, + "lib.in.us": 1, + "lib.ks.us": 1, + "lib.ky.us": 1, + "lib.la.us": 1, + "lib.ma.us": 1, + "lib.md.us": 1, + "lib.me.us": 1, + "lib.mi.us": 1, + "lib.mn.us": 1, + "lib.mo.us": 1, + "lib.ms.us": 1, + "lib.mt.us": 1, + "lib.nc.us": 1, + "lib.nd.us": 1, + "lib.ne.us": 1, + "lib.nh.us": 1, + "lib.nj.us": 1, + "lib.nm.us": 1, + "lib.nv.us": 1, + "lib.ny.us": 1, + "lib.oh.us": 1, + "lib.ok.us": 1, + "lib.or.us": 1, + "lib.pa.us": 1, + "lib.pr.us": 1, + "lib.ri.us": 1, + "lib.sc.us": 1, + "lib.sd.us": 1, + "lib.tn.us": 1, + "lib.tx.us": 1, + "lib.ut.us": 1, + "lib.va.us": 1, + "lib.vi.us": 1, + "lib.vt.us": 1, + "lib.wa.us": 1, + "lib.wi.us": 1, + "lib.wy.us": 1, + "lier.no": 1, + "lierne.no": 1, + "lig.it": 1, + "liguria.it": 1, + "likes-pie.com": 1, + "likescandy.com": 1, + "lillehammer.no": 1, + "lillesand.no": 1, + "lima-city.at": 1, + "lima-city.ch": 1, + "lima-city.de": 1, + "lima-city.rocks": 1, + "lima.zone": 1, + "limanowa.pl": 1, + "lincoln.museum": 1, + "lindas.no": 1, + "lindesnes.no": 1, + "lind\u00e5s.no": 1, + "linkitools.space": 1, + "linkyard-cloud.ch": 1, + "linkyard.cloud": 1, + "linodeobjects.com": 2, + "linz.museum": 1, + "living.museum": 1, + "livinghistory.museum": 1, + "livorno.it": 1, + "ln.cn": 1, + "lo.it": 1, + "loabat.no": 1, + "loab\u00e1t.no": 1, + "localhistory.museum": 1, + "localhost.daplie.me": 1, + "localzone.xyz": 1, + "lodi.it": 1, + "lodingen.no": 1, + "log.br": 1, + "loginline.app": 1, + "loginline.dev": 1, + "loginline.io": 1, + "loginline.services": 1, + "loginline.site": 1, + "loginto.me": 1, + "logistics.aero": 1, + "logoip.com": 1, + "logoip.de": 1, + "lolipop.io": 1, + "lom.it": 1, + "lom.no": 1, + "lombardia.it": 1, + "lombardy.it": 1, + "lomza.pl": 1, + "london.cloudapps.digital": 1, + "london.museum": 1, + "londrina.br": 1, + "loppa.no": 1, + "lorenskog.no": 1, + "losangeles.museum": 1, + "loseyourip.com": 1, + "loten.no": 1, + "louvre.museum": 1, + "lowicz.pl": 1, + "loyalist.museum": 1, + "lpages.co": 1, + "lpusercontent.com": 1, + "lt.eu.org": 1, + "lt.it": 1, + "lt.ua": 1, + "ltd.co.im": 1, + "ltd.cy": 1, + "ltd.gi": 1, + "ltd.hk": 1, + "ltd.lk": 1, + "ltd.ng": 1, + "ltd.ua": 1, + "ltd.uk": 1, + "lu.eu.org": 1, + "lu.it": 1, + "lubartow.pl": 1, + "lubin.pl": 1, + "lublin.pl": 1, + "lucania.it": 1, + "lucca.it": 1, + "lucerne.museum": 1, + "lug.org.uk": 1, + "lugansk.ua": 1, + "lugs.org.uk": 1, + "lukow.pl": 1, + "lund.no": 1, + "lunner.no": 1, + "luroy.no": 1, + "lur\u00f8y.no": 1, + "luster.no": 1, + "lutsk.ua": 1, + "luxembourg.museum": 1, + "luzern.museum": 1, + "lv.eu.org": 1, + "lv.ua": 1, + "lviv.ua": 1, + "lyngdal.no": 1, + "lyngen.no": 1, + "lynx.mythic-beasts.com": 1, + "l\u00e1hppi.no": 1, + "l\u00e4ns.museum": 1, + "l\u00e6rdal.no": 1, + "l\u00f8dingen.no": 1, + "l\u00f8renskog.no": 1, + "l\u00f8ten.no": 1, + "m.bg": 1, + "m.se": 1, + "ma.gov.br": 1, + "ma.leg.br": 1, + "ma.us": 1, + "macapa.br": 1, + "maceio.br": 1, + "macerata.it": 1, + "machida.tokyo.jp": 1, + "mad.museum": 1, + "madrid.museum": 1, + "maebashi.gunma.jp": 1, + "magazine.aero": 1, + "magentosite.cloud": 2, + "maibara.shiga.jp": 1, + "mail.pl": 1, + "maintenance.aero": 1, + "maizuru.kyoto.jp": 1, + "makinohara.shizuoka.jp": 1, + "makurazaki.kagoshima.jp": 1, + "malatvuopmi.no": 1, + "malbork.pl": 1, + "mallorca.museum": 1, + "malopolska.pl": 1, + "malselv.no": 1, + "malvik.no": 1, + "mamurogawa.yamagata.jp": 1, + "manaus.br": 1, + "manchester.museum": 1, + "mandal.no": 1, + "mangyshlak.su": 1, + "maniwa.okayama.jp": 1, + "manno.kagawa.jp": 1, + "mansion.museum": 1, + "mansions.museum": 1, + "mantova.it": 1, + "manx.museum": 1, + "maori.nz": 1, + "map.fastly.net": 1, + "map.fastlylb.net": 1, + "mar.it": 1, + "marburg.museum": 1, + "marche.it": 1, + "marine.ru": 1, + "maringa.br": 1, + "maritime.museum": 1, + "maritimo.museum": 1, + "marker.no": 1, + "marnardal.no": 1, + "marugame.kagawa.jp": 1, + "marumori.miyagi.jp": 1, + "maryland.museum": 1, + "marylhurst.museum": 1, + "masaki.ehime.jp": 1, + "masfjorden.no": 1, + "mashike.hokkaido.jp": 1, + "mashiki.kumamoto.jp": 1, + "mashiko.tochigi.jp": 1, + "masoy.no": 1, + "massa-carrara.it": 1, + "massacarrara.it": 1, + "masuda.shimane.jp": 1, + "mat.br": 1, + "matera.it": 1, + "matsubara.osaka.jp": 1, + "matsubushi.saitama.jp": 1, + "matsuda.kanagawa.jp": 1, + "matsudo.chiba.jp": 1, + "matsue.shimane.jp": 1, + "matsukawa.nagano.jp": 1, + "matsumae.hokkaido.jp": 1, + "matsumoto.kagoshima.jp": 1, + "matsumoto.nagano.jp": 1, + "matsuno.ehime.jp": 1, + "matsusaka.mie.jp": 1, + "matsushige.tokushima.jp": 1, + "matsushima.miyagi.jp": 1, + "matsuura.nagasaki.jp": 1, + "matsuyama.ehime.jp": 1, + "matsuzaki.shizuoka.jp": 1, + "matta-varjjat.no": 1, + "mayfirst.info": 1, + "mayfirst.org": 1, + "mazowsze.pl": 1, + "mazury.pl": 1, + "mb.ca": 1, + "mb.it": 1, + "mc.ax": 1, + "mc.eu.org": 1, + "mc.it": 1, + "mcdir.ru": 1, + "mcpe.me": 1, + "md.ci": 1, + "md.us": 1, + "me.eu.org": 1, + "me.it": 1, + "me.ke": 1, + "me.so": 1, + "me.tc": 1, + "me.tz": 1, + "me.uk": 1, + "me.us": 1, + "me.vu": 1, + "med.br": 1, + "med.ec": 1, + "med.ee": 1, + "med.ht": 1, + "med.ly": 1, + "med.om": 1, + "med.pa": 1, + "med.pl": 1, + "med.pro": 1, + "med.sa": 1, + "med.sd": 1, + "medecin.fr": 1, + "medecin.km": 1, + "media.aero": 1, + "media.hu": 1, + "media.museum": 1, + "media.pl": 1, + "medical.museum": 1, + "medicina.bo": 1, + "medio-campidano.it": 1, + "mediocampidano.it": 1, + "medizinhistorisches.museum": 1, + "meeres.museum": 1, + "meguro.tokyo.jp": 1, + "mein-iserv.de": 1, + "mein-vigor.de": 1, + "meinforum.net": 1, + "meiwa.gunma.jp": 1, + "meiwa.mie.jp": 1, + "meland.no": 1, + "meldal.no": 1, + "melhus.no": 1, + "meloy.no": 1, + "mel\u00f8y.no": 1, + "members.linode.com": 1, + "memorial.museum": 1, + "memset.net": 1, + "meraker.no": 1, + "merseine.nu": 1, + "mer\u00e5ker.no": 1, + "mesaverde.museum": 1, + "messina.it": 1, + "meteorapp.com": 1, + "mex.com": 1, + "mg.gov.br": 1, + "mg.leg.br": 1, + "mi.it": 1, + "mi.th": 1, + "mi.us": 1, + "miasa.nagano.jp": 1, + "miasta.pl": 1, + "mibu.tochigi.jp": 1, + "michigan.museum": 1, + "microlight.aero": 1, + "midatlantic.museum": 1, + "midori.chiba.jp": 1, + "midori.gunma.jp": 1, + "midsund.no": 1, + "midtre-gauldal.no": 1, + "mie.jp": 1, + "mielec.pl": 1, + "mielno.pl": 1, + "mifune.kumamoto.jp": 1, + "mihama.aichi.jp": 1, + "mihama.chiba.jp": 1, + "mihama.fukui.jp": 1, + "mihama.mie.jp": 1, + "mihama.wakayama.jp": 1, + "mihara.hiroshima.jp": 1, + "mihara.kochi.jp": 1, + "miharu.fukushima.jp": 1, + "miho.ibaraki.jp": 1, + "mikasa.hokkaido.jp": 1, + "mikawa.yamagata.jp": 1, + "miki.hyogo.jp": 1, + "mil.ac": 1, + "mil.ae": 1, + "mil.al": 1, + "mil.ar": 1, + "mil.az": 1, + "mil.ba": 1, + "mil.bo": 1, + "mil.br": 1, + "mil.by": 1, + "mil.cl": 1, + "mil.cn": 1, + "mil.co": 1, + "mil.do": 1, + "mil.ec": 1, + "mil.eg": 1, + "mil.fj": 1, + "mil.ge": 1, + "mil.gh": 1, + "mil.gt": 1, + "mil.hn": 1, + "mil.id": 1, + "mil.in": 1, + "mil.iq": 1, + "mil.jo": 1, + "mil.kg": 1, + "mil.km": 1, + "mil.kr": 1, + "mil.kz": 1, + "mil.lv": 1, + "mil.mg": 1, + "mil.mv": 1, + "mil.my": 1, + "mil.mz": 1, + "mil.ng": 1, + "mil.ni": 1, + "mil.no": 1, + "mil.nz": 1, + "mil.pe": 1, + "mil.ph": 1, + "mil.pl": 1, + "mil.py": 1, + "mil.qa": 1, + "mil.ru": 1, + "mil.rw": 1, + "mil.sh": 1, + "mil.st": 1, + "mil.sy": 1, + "mil.tj": 1, + "mil.tm": 1, + "mil.to": 1, + "mil.tr": 1, + "mil.tw": 1, + "mil.tz": 1, + "mil.uy": 1, + "mil.vc": 1, + "mil.ve": 1, + "mil.za": 1, + "mil.zm": 1, + "mil.zw": 1, + "milan.it": 1, + "milano.it": 1, + "military.museum": 1, + "mill.museum": 1, + "mima.tokushima.jp": 1, + "mimata.miyazaki.jp": 1, + "minakami.gunma.jp": 1, + "minamata.kumamoto.jp": 1, + "minami-alps.yamanashi.jp": 1, + "minami.fukuoka.jp": 1, + "minami.kyoto.jp": 1, + "minami.tokushima.jp": 1, + "minamiaiki.nagano.jp": 1, + "minamiashigara.kanagawa.jp": 1, + "minamiawaji.hyogo.jp": 1, + "minamiboso.chiba.jp": 1, + "minamidaito.okinawa.jp": 1, + "minamiechizen.fukui.jp": 1, + "minamifurano.hokkaido.jp": 1, + "minamiise.mie.jp": 1, + "minamiizu.shizuoka.jp": 1, + "minamimaki.nagano.jp": 1, + "minamiminowa.nagano.jp": 1, + "minamioguni.kumamoto.jp": 1, + "minamisanriku.miyagi.jp": 1, + "minamitane.kagoshima.jp": 1, + "minamiuonuma.niigata.jp": 1, + "minamiyamashiro.kyoto.jp": 1, + "minano.saitama.jp": 1, + "minato.osaka.jp": 1, + "minato.tokyo.jp": 1, + "mincom.tn": 1, + "mine.nu": 1, + "miners.museum": 1, + "mining.museum": 1, + "miniserver.com": 1, + "minnesota.museum": 1, + "mino.gifu.jp": 1, + "minobu.yamanashi.jp": 1, + "minoh.osaka.jp": 1, + "minokamo.gifu.jp": 1, + "minowa.nagano.jp": 1, + "mintere.site": 1, + "mircloud.host": 1, + "misaki.okayama.jp": 1, + "misaki.osaka.jp": 1, + "misasa.tottori.jp": 1, + "misato.akita.jp": 1, + "misato.miyagi.jp": 1, + "misato.saitama.jp": 1, + "misato.shimane.jp": 1, + "misato.wakayama.jp": 1, + "misawa.aomori.jp": 1, + "misconfused.org": 1, + "mishima.fukushima.jp": 1, + "mishima.shizuoka.jp": 1, + "missile.museum": 1, + "missoula.museum": 1, + "misugi.mie.jp": 1, + "mitaka.tokyo.jp": 1, + "mitake.gifu.jp": 1, + "mitane.akita.jp": 1, + "mito.ibaraki.jp": 1, + "mitou.yamaguchi.jp": 1, + "mitoyo.kagawa.jp": 1, + "mitsue.nara.jp": 1, + "mitsuke.niigata.jp": 1, + "miura.kanagawa.jp": 1, + "miyada.nagano.jp": 1, + "miyagi.jp": 1, + "miyake.nara.jp": 1, + "miyako.fukuoka.jp": 1, + "miyako.iwate.jp": 1, + "miyakonojo.miyazaki.jp": 1, + "miyama.fukuoka.jp": 1, + "miyama.mie.jp": 1, + "miyashiro.saitama.jp": 1, + "miyawaka.fukuoka.jp": 1, + "miyazaki.jp": 1, + "miyazaki.miyazaki.jp": 1, + "miyazu.kyoto.jp": 1, + "miyoshi.aichi.jp": 1, + "miyoshi.hiroshima.jp": 1, + "miyoshi.saitama.jp": 1, + "miyoshi.tokushima.jp": 1, + "miyota.nagano.jp": 1, + "mizuho.tokyo.jp": 1, + "mizumaki.fukuoka.jp": 1, + "mizunami.gifu.jp": 1, + "mizusawa.iwate.jp": 1, + "mjondalen.no": 1, + "mj\u00f8ndalen.no": 1, + "mk.eu.org": 1, + "mk.ua": 1, + "mlbfan.org": 1, + "mm": 2, + "mmafan.biz": 1, + "mn.it": 1, + "mn.us": 1, + "mo-i-rana.no": 1, + "mo-siemens.io": 1, + "mo.cn": 1, + "mo.it": 1, + "mo.us": 1, + "moareke.no": 1, + "mobara.chiba.jp": 1, + "mobi.gp": 1, + "mobi.ke": 1, + "mobi.na": 1, + "mobi.ng": 1, + "mobi.tt": 1, + "mobi.tz": 1, + "mochizuki.nagano.jp": 1, + "mod.gi": 1, + "modalen.no": 1, + "modelling.aero": 1, + "modena.it": 1, + "modern.museum": 1, + "modum.no": 1, + "moka.tochigi.jp": 1, + "mol.it": 1, + "molde.no": 1, + "molise.it": 1, + "moma.museum": 1, + "mombetsu.hokkaido.jp": 1, + "money.museum": 1, + "monmouth.museum": 1, + "monticello.museum": 1, + "montreal.museum": 1, + "monza-brianza.it": 1, + "monza-e-della-brianza.it": 1, + "monza.it": 1, + "monzabrianza.it": 1, + "monzaebrianza.it": 1, + "monzaedellabrianza.it": 1, + "moonscale.io": 2, + "moonscale.net": 1, + "mordovia.ru": 1, + "mordovia.su": 1, + "morena.br": 1, + "moriguchi.osaka.jp": 1, + "morimachi.shizuoka.jp": 1, + "morioka.iwate.jp": 1, + "moriya.ibaraki.jp": 1, + "moriyama.shiga.jp": 1, + "moriyoshi.akita.jp": 1, + "morotsuka.miyazaki.jp": 1, + "moroyama.saitama.jp": 1, + "moscow.museum": 1, + "moseushi.hokkaido.jp": 1, + "mosjoen.no": 1, + "mosj\u00f8en.no": 1, + "moskenes.no": 1, + "moss.no": 1, + "mosvik.no": 1, + "motegi.tochigi.jp": 1, + "motobu.okinawa.jp": 1, + "motorcycle.museum": 1, + "motosu.gifu.jp": 1, + "motoyama.kochi.jp": 1, + "movimiento.bo": 1, + "mozilla-iot.org": 1, + "mo\u00e5reke.no": 1, + "mp.br": 1, + "mr.no": 1, + "mragowo.pl": 1, + "ms.gov.br": 1, + "ms.it": 1, + "ms.kr": 1, + "ms.leg.br": 1, + "ms.us": 1, + "msk.ru": 1, + "msk.su": 1, + "mt.eu.org": 1, + "mt.gov.br": 1, + "mt.it": 1, + "mt.leg.br": 1, + "mt.us": 1, + "muenchen.museum": 1, + "muenster.museum": 1, + "mugi.tokushima.jp": 1, + "muika.niigata.jp": 1, + "mukawa.hokkaido.jp": 1, + "muko.kyoto.jp": 1, + "mulhouse.museum": 1, + "munakata.fukuoka.jp": 1, + "muncie.museum": 1, + "muni.il": 1, + "muosat.no": 1, + "muos\u00e1t.no": 1, + "mup.gov.pl": 1, + "murakami.niigata.jp": 1, + "murata.miyagi.jp": 1, + "murayama.yamagata.jp": 1, + "murmansk.su": 1, + "muroran.hokkaido.jp": 1, + "muroto.kochi.jp": 1, + "mus.br": 1, + "mus.mi.us": 1, + "musashimurayama.tokyo.jp": 1, + "musashino.tokyo.jp": 1, + "museet.museum": 1, + "museum.mv": 1, + "museum.mw": 1, + "museum.no": 1, + "museum.om": 1, + "museum.tt": 1, + "museumcenter.museum": 1, + "museumvereniging.museum": 1, + "music.museum": 1, + "musica.ar": 1, + "musica.bo": 1, + "mutsu.aomori.jp": 1, + "mutsuzawa.chiba.jp": 1, + "mw.gov.pl": 1, + "mx.na": 1, + "my-firewall.org": 1, + "my-gateway.de": 1, + "my-router.de": 1, + "my-vigor.de": 1, + "my-wan.de": 1, + "my.eu.org": 1, + "my.id": 1, + "myactivedirectory.com": 1, + "myasustor.com": 1, + "mycd.eu": 1, + "mydatto.com": 1, + "mydatto.net": 1, + "myddns.rocks": 1, + "mydissent.net": 1, + "mydobiss.com": 1, + "mydrobo.com": 1, + "myds.me": 1, + "myeffect.net": 1, + "myfast.host": 1, + "myfast.space": 1, + "myfirewall.org": 1, + "myforum.community": 1, + "myfritz.net": 1, + "myftp.biz": 1, + "myftp.org": 1, + "myhome-server.de": 1, + "myiphost.com": 1, + "myjino.ru": 1, + "mykolaiv.ua": 1, + "mymailer.com.tw": 1, + "mymediapc.net": 1, + "myoko.niigata.jp": 1, + "mypep.link": 1, + "mypets.ws": 1, + "myphotos.cc": 1, + "mypi.co": 1, + "mypsx.net": 1, + "myqnapcloud.com": 1, + "myravendb.com": 1, + "mysecuritycamera.com": 1, + "mysecuritycamera.net": 1, + "mysecuritycamera.org": 1, + "myshopblocks.com": 1, + "mytis.ru": 1, + "mytuleap.com": 1, + "myvnc.com": 1, + "mywire.org": 1, + "m\u00e1latvuopmi.no": 1, + "m\u00e1tta-v\u00e1rjjat.no": 1, + "m\u00e5lselv.no": 1, + "m\u00e5s\u00f8y.no": 1, + "m\u0101ori.nz": 1, + "n.bg": 1, + "n.se": 1, + "n4t.co": 1, + "na.it": 1, + "na4u.ru": 1, + "naamesjevuemie.no": 1, + "nabari.mie.jp": 1, + "nachikatsuura.wakayama.jp": 1, + "nagahama.shiga.jp": 1, + "nagai.yamagata.jp": 1, + "nagano.jp": 1, + "nagano.nagano.jp": 1, + "naganohara.gunma.jp": 1, + "nagaoka.niigata.jp": 1, + "nagaokakyo.kyoto.jp": 1, + "nagara.chiba.jp": 1, + "nagareyama.chiba.jp": 1, + "nagasaki.jp": 1, + "nagasaki.nagasaki.jp": 1, + "nagasu.kumamoto.jp": 1, + "nagato.yamaguchi.jp": 1, + "nagatoro.saitama.jp": 1, + "nagawa.nagano.jp": 1, + "nagi.okayama.jp": 1, + "nagiso.nagano.jp": 1, + "nago.okinawa.jp": 1, + "nagoya.jp": 2, + "naha.okinawa.jp": 1, + "nahari.kochi.jp": 1, + "naie.hokkaido.jp": 1, + "naka.hiroshima.jp": 1, + "naka.ibaraki.jp": 1, + "nakadomari.aomori.jp": 1, + "nakagawa.fukuoka.jp": 1, + "nakagawa.hokkaido.jp": 1, + "nakagawa.nagano.jp": 1, + "nakagawa.tokushima.jp": 1, + "nakagusuku.okinawa.jp": 1, + "nakagyo.kyoto.jp": 1, + "nakai.kanagawa.jp": 1, + "nakama.fukuoka.jp": 1, + "nakamichi.yamanashi.jp": 1, + "nakamura.kochi.jp": 1, + "nakaniikawa.toyama.jp": 1, + "nakano.nagano.jp": 1, + "nakano.tokyo.jp": 1, + "nakanojo.gunma.jp": 1, + "nakanoto.ishikawa.jp": 1, + "nakasatsunai.hokkaido.jp": 1, + "nakatane.kagoshima.jp": 1, + "nakatombetsu.hokkaido.jp": 1, + "nakatsugawa.gifu.jp": 1, + "nakayama.yamagata.jp": 1, + "nakijin.okinawa.jp": 1, + "naklo.pl": 1, + "nalchik.ru": 1, + "nalchik.su": 1, + "namdalseid.no": 1, + "name.az": 1, + "name.cy": 1, + "name.eg": 1, + "name.et": 1, + "name.fj": 1, + "name.hr": 1, + "name.jo": 1, + "name.mk": 1, + "name.mv": 1, + "name.my": 1, + "name.na": 1, + "name.ng": 1, + "name.pr": 1, + "name.qa": 1, + "name.tj": 1, + "name.tr": 1, + "name.tt": 1, + "name.vn": 1, + "namegata.ibaraki.jp": 1, + "namegawa.saitama.jp": 1, + "namerikawa.toyama.jp": 1, + "namie.fukushima.jp": 1, + "namikata.ehime.jp": 1, + "namsos.no": 1, + "namsskogan.no": 1, + "nanae.hokkaido.jp": 1, + "nanao.ishikawa.jp": 1, + "nanbu.tottori.jp": 1, + "nanbu.yamanashi.jp": 1, + "nango.fukushima.jp": 1, + "nanjo.okinawa.jp": 1, + "nankoku.kochi.jp": 1, + "nanmoku.gunma.jp": 1, + "nannestad.no": 1, + "nanporo.hokkaido.jp": 1, + "nantan.kyoto.jp": 1, + "nanto.toyama.jp": 1, + "nanyo.yamagata.jp": 1, + "naoshima.kagawa.jp": 1, + "naples.it": 1, + "napoli.it": 1, + "nara.jp": 1, + "nara.nara.jp": 1, + "narashino.chiba.jp": 1, + "narita.chiba.jp": 1, + "naroy.no": 1, + "narusawa.yamanashi.jp": 1, + "naruto.tokushima.jp": 1, + "narviika.no": 1, + "narvik.no": 1, + "nasu.tochigi.jp": 1, + "nasushiobara.tochigi.jp": 1, + "nat.tn": 1, + "natal.br": 1, + "national.museum": 1, + "nationalfirearms.museum": 1, + "nationalheritage.museum": 1, + "nativeamerican.museum": 1, + "natori.miyagi.jp": 1, + "natural.bo": 1, + "naturalhistory.museum": 1, + "naturalhistorymuseum.museum": 1, + "naturalsciences.museum": 1, + "naturbruksgymn.se": 1, + "nature.museum": 1, + "naturhistorisches.museum": 1, + "natuurwetenschappen.museum": 1, + "naumburg.museum": 1, + "naustdal.no": 1, + "naval.museum": 1, + "navigation.aero": 1, + "navoi.su": 1, + "navuotna.no": 1, + "nayoro.hokkaido.jp": 1, + "nb.ca": 1, + "nc.tr": 1, + "nc.us": 1, + "nctu.me": 1, + "nd.us": 1, + "ne.jp": 1, + "ne.ke": 1, + "ne.kr": 1, + "ne.pw": 1, + "ne.tz": 1, + "ne.ug": 1, + "ne.us": 1, + "neat-url.com": 1, + "nebraska.museum": 1, + "nedre-eiker.no": 1, + "neko.am": 1, + "nemuro.hokkaido.jp": 1, + "nerdpol.ovh": 1, + "nerima.tokyo.jp": 1, + "nes.akershus.no": 1, + "nes.buskerud.no": 1, + "nesna.no": 1, + "nesodden.no": 1, + "nesoddtangen.no": 1, + "nesseby.no": 1, + "nesset.no": 1, + "net-freaks.com": 1, + "net.ac": 1, + "net.ae": 1, + "net.af": 1, + "net.ag": 1, + "net.ai": 1, + "net.al": 1, + "net.am": 1, + "net.ar": 1, + "net.au": 1, + "net.az": 1, + "net.ba": 1, + "net.bb": 1, + "net.bh": 1, + "net.bm": 1, + "net.bn": 1, + "net.bo": 1, + "net.br": 1, + "net.bs": 1, + "net.bt": 1, + "net.bz": 1, + "net.ci": 1, + "net.cm": 1, + "net.cn": 1, + "net.co": 1, + "net.cu": 1, + "net.cw": 1, + "net.cy": 1, + "net.dm": 1, + "net.do": 1, + "net.dz": 1, + "net.ec": 1, + "net.eg": 1, + "net.et": 1, + "net.eu.org": 1, + "net.fj": 1, + "net.fm": 1, + "net.ge": 1, + "net.gg": 1, + "net.gl": 1, + "net.gn": 1, + "net.gp": 1, + "net.gr": 1, + "net.gt": 1, + "net.gu": 1, + "net.gy": 1, + "net.hk": 1, + "net.hn": 1, + "net.ht": 1, + "net.id": 1, + "net.il": 1, + "net.im": 1, + "net.in": 1, + "net.iq": 1, + "net.ir": 1, + "net.is": 1, + "net.je": 1, + "net.jo": 1, + "net.kg": 1, + "net.ki": 1, + "net.kn": 1, + "net.kw": 1, + "net.ky": 1, + "net.kz": 1, + "net.la": 1, + "net.lb": 1, + "net.lc": 1, + "net.lk": 1, + "net.lr": 1, + "net.ls": 1, + "net.lv": 1, + "net.ly": 1, + "net.ma": 1, + "net.me": 1, + "net.mk": 1, + "net.ml": 1, + "net.mo": 1, + "net.ms": 1, + "net.mt": 1, + "net.mu": 1, + "net.mv": 1, + "net.mw": 1, + "net.mx": 1, + "net.my": 1, + "net.mz": 1, + "net.nf": 1, + "net.ng": 1, + "net.ni": 1, + "net.nr": 1, + "net.nz": 1, + "net.om": 1, + "net.pa": 1, + "net.pe": 1, + "net.ph": 1, + "net.pk": 1, + "net.pl": 1, + "net.pn": 1, + "net.pr": 1, + "net.ps": 1, + "net.pt": 1, + "net.py": 1, + "net.qa": 1, + "net.ru": 1, + "net.rw": 1, + "net.sa": 1, + "net.sb": 1, + "net.sc": 1, + "net.sd": 1, + "net.sg": 1, + "net.sh": 1, + "net.sl": 1, + "net.so": 1, + "net.ss": 1, + "net.st": 1, + "net.sy": 1, + "net.th": 1, + "net.tj": 1, + "net.tm": 1, + "net.tn": 1, + "net.to": 1, + "net.tr": 1, + "net.tt": 1, + "net.tw": 1, + "net.ua": 1, + "net.uk": 1, + "net.uy": 1, + "net.uz": 1, + "net.vc": 1, + "net.ve": 1, + "net.vi": 1, + "net.vn": 1, + "net.vu": 1, + "net.ws": 1, + "net.za": 1, + "net.zm": 1, + "netlify.app": 1, + "neues.museum": 1, + "newhampshire.museum": 1, + "newjersey.museum": 1, + "newmexico.museum": 1, + "newport.museum": 1, + "news.hu": 1, + "newspaper.museum": 1, + "newyork.museum": 1, + "neyagawa.osaka.jp": 1, + "nf.ca": 1, + "nflfan.org": 1, + "nfshost.com": 1, + "ng.city": 1, + "ng.eu.org": 1, + "ng.ink": 1, + "ng.school": 1, + "ngo.lk": 1, + "ngo.ng": 1, + "ngo.ph": 1, + "ngo.za": 1, + "ngrok.io": 1, + "nh-serv.co.uk": 1, + "nh.us": 1, + "nhlfan.net": 1, + "nhs.uk": 1, + "nic.in": 1, + "nic.tj": 1, + "nic.za": 1, + "nichinan.miyazaki.jp": 1, + "nichinan.tottori.jp": 1, + "nid.io": 1, + "niepce.museum": 1, + "nieruchomosci.pl": 1, + "niigata.jp": 1, + "niigata.niigata.jp": 1, + "niihama.ehime.jp": 1, + "niikappu.hokkaido.jp": 1, + "niimi.okayama.jp": 1, + "niiza.saitama.jp": 1, + "nikaho.akita.jp": 1, + "niki.hokkaido.jp": 1, + "nikko.tochigi.jp": 1, + "nikolaev.ua": 1, + "ninohe.iwate.jp": 1, + "ninomiya.kanagawa.jp": 1, + "nirasaki.yamanashi.jp": 1, + "nis.za": 1, + "nishi.fukuoka.jp": 1, + "nishi.osaka.jp": 1, + "nishiaizu.fukushima.jp": 1, + "nishiarita.saga.jp": 1, + "nishiawakura.okayama.jp": 1, + "nishiazai.shiga.jp": 1, + "nishigo.fukushima.jp": 1, + "nishihara.kumamoto.jp": 1, + "nishihara.okinawa.jp": 1, + "nishiizu.shizuoka.jp": 1, + "nishikata.tochigi.jp": 1, + "nishikatsura.yamanashi.jp": 1, + "nishikawa.yamagata.jp": 1, + "nishimera.miyazaki.jp": 1, + "nishinomiya.hyogo.jp": 1, + "nishinoomote.kagoshima.jp": 1, + "nishinoshima.shimane.jp": 1, + "nishio.aichi.jp": 1, + "nishiokoppe.hokkaido.jp": 1, + "nishitosa.kochi.jp": 1, + "nishiwaki.hyogo.jp": 1, + "nissedal.no": 1, + "nisshin.aichi.jp": 1, + "niteroi.br": 1, + "nittedal.no": 1, + "niyodogawa.kochi.jp": 1, + "nj.us": 1, + "nl.ca": 1, + "nl.ci": 1, + "nl.eu.org": 1, + "nl.no": 1, + "nm.cn": 1, + "nm.us": 1, + "no-ip.biz": 1, + "no-ip.ca": 1, + "no-ip.co.uk": 1, + "no-ip.info": 1, + "no-ip.net": 1, + "no-ip.org": 1, + "no.com": 1, + "no.eu.org": 1, + "no.it": 1, + "nobeoka.miyazaki.jp": 1, + "noboribetsu.hokkaido.jp": 1, + "noda.chiba.jp": 1, + "noda.iwate.jp": 1, + "nodebalancer.linode.com": 2, + "nodum.co": 1, + "nodum.io": 1, + "nogata.fukuoka.jp": 1, + "nogi.tochigi.jp": 1, + "noheji.aomori.jp": 1, + "noho.st": 1, + "nohost.me": 1, + "noip.me": 1, + "noip.us": 1, + "nom.ad": 1, + "nom.ae": 1, + "nom.af": 1, + "nom.ag": 1, + "nom.ai": 1, + "nom.al": 1, + "nom.br": 2, + "nom.bz": 1, + "nom.cl": 1, + "nom.co": 1, + "nom.es": 1, + "nom.fr": 1, + "nom.gd": 1, + "nom.ge": 1, + "nom.gl": 1, + "nom.gt": 1, + "nom.hn": 1, + "nom.im": 1, + "nom.ke": 1, + "nom.km": 1, + "nom.li": 1, + "nom.lv": 1, + "nom.mg": 1, + "nom.mk": 1, + "nom.nc": 1, + "nom.ni": 1, + "nom.nu": 1, + "nom.pa": 1, + "nom.pe": 1, + "nom.pl": 1, + "nom.pw": 1, + "nom.qa": 1, + "nom.re": 1, + "nom.ro": 1, + "nom.rs": 1, + "nom.si": 1, + "nom.st": 1, + "nom.tj": 1, + "nom.tm": 1, + "nom.ug": 1, + "nom.uy": 1, + "nom.vc": 1, + "nom.vg": 1, + "nom.za": 1, + "nombre.bo": 1, + "nome.pt": 1, + "nomi.ishikawa.jp": 1, + "nonoichi.ishikawa.jp": 1, + "nord-aurdal.no": 1, + "nord-fron.no": 1, + "nord-odal.no": 1, + "norddal.no": 1, + "nordkapp.no": 1, + "nordre-land.no": 1, + "nordreisa.no": 1, + "nore-og-uvdal.no": 1, + "norfolk.museum": 1, + "north-kazakhstan.su": 1, + "north.museum": 1, + "nose.osaka.jp": 1, + "nosegawa.nara.jp": 1, + "noshiro.akita.jp": 1, + "not.br": 1, + "notaires.fr": 1, + "notaires.km": 1, + "noticias.bo": 1, + "noto.ishikawa.jp": 1, + "notodden.no": 1, + "notogawa.shiga.jp": 1, + "notteroy.no": 1, + "nov.ru": 1, + "nov.su": 1, + "novara.it": 1, + "now-dns.net": 1, + "now-dns.org": 1, + "now-dns.top": 1, + "now.sh": 1, + "nowaruda.pl": 1, + "nozawaonsen.nagano.jp": 1, + "np": 2, + "nrw.museum": 1, + "ns.ca": 1, + "nsn.us": 1, + "nsupdate.info": 1, + "nsw.au": 1, + "nsw.edu.au": 1, + "nt.au": 1, + "nt.ca": 1, + "nt.edu.au": 1, + "nt.no": 1, + "nt.ro": 1, + "ntdll.top": 1, + "ntr.br": 1, + "nu.ca": 1, + "nu.it": 1, + "numata.gunma.jp": 1, + "numata.hokkaido.jp": 1, + "numazu.shizuoka.jp": 1, + "nuoro.it": 1, + "nv.us": 1, + "nx.cn": 1, + "ny.us": 1, + "nyaa.am": 1, + "nyan.to": 1, + "nyc.mn": 1, + "nyc.museum": 1, + "nym.by": 1, + "nym.bz": 1, + "nym.ec": 1, + "nym.gr": 1, + "nym.gy": 1, + "nym.hk": 1, + "nym.ie": 1, + "nym.kz": 1, + "nym.la": 1, + "nym.lc": 1, + "nym.li": 1, + "nym.lt": 1, + "nym.lu": 1, + "nym.me": 1, + "nym.mn": 1, + "nym.mx": 1, + "nym.nz": 1, + "nym.pe": 1, + "nym.pt": 1, + "nym.ro": 1, + "nym.sk": 1, + "nym.su": 1, + "nym.sx": 1, + "nym.tw": 1, + "nyny.museum": 1, + "nysa.pl": 1, + "nyuzen.toyama.jp": 1, + "nz.basketball": 1, + "nz.eu.org": 1, + "n\u00e1vuotna.no": 1, + "n\u00e5\u00e5mesjevuemie.no": 1, + "n\u00e6r\u00f8y.no": 1, + "n\u00f8tter\u00f8y.no": 1, + "o.bg": 1, + "o.se": 1, + "oamishirasato.chiba.jp": 1, + "oarai.ibaraki.jp": 1, + "obama.fukui.jp": 1, + "obama.nagasaki.jp": 1, + "obanazawa.yamagata.jp": 1, + "obihiro.hokkaido.jp": 1, + "obira.hokkaido.jp": 1, + "obninsk.su": 1, + "obu.aichi.jp": 1, + "obuse.nagano.jp": 1, + "oceanographic.museum": 1, + "oceanographique.museum": 1, + "ocelot.mythic-beasts.com": 1, + "ochi.kochi.jp": 1, + "oci.customer-oci.com": 2, + "ocp.customer-oci.com": 2, + "ocs.customer-oci.com": 2, + "od.ua": 1, + "odate.akita.jp": 1, + "odawara.kanagawa.jp": 1, + "odda.no": 1, + "odesa.ua": 1, + "odessa.ua": 1, + "odo.br": 1, + "oe.yamagata.jp": 1, + "of.by": 1, + "of.fashion": 1, + "of.football": 1, + "of.london": 1, + "of.no": 1, + "of.work": 1, + "off.ai": 1, + "office-on-the.net": 1, + "official.academy": 1, + "ofunato.iwate.jp": 1, + "og.ao": 1, + "og.it": 1, + "oga.akita.jp": 1, + "ogaki.gifu.jp": 1, + "ogano.saitama.jp": 1, + "ogasawara.tokyo.jp": 1, + "ogata.akita.jp": 1, + "ogawa.ibaraki.jp": 1, + "ogawa.nagano.jp": 1, + "ogawa.saitama.jp": 1, + "ogawara.miyagi.jp": 1, + "ogi.saga.jp": 1, + "ogimi.okinawa.jp": 1, + "ogliastra.it": 1, + "ogori.fukuoka.jp": 1, + "ogose.saitama.jp": 1, + "oguchi.aichi.jp": 1, + "oguni.kumamoto.jp": 1, + "oguni.yamagata.jp": 1, + "oh.us": 1, + "oharu.aichi.jp": 1, + "ohda.shimane.jp": 1, + "ohi.fukui.jp": 1, + "ohira.miyagi.jp": 1, + "ohira.tochigi.jp": 1, + "ohkura.yamagata.jp": 1, + "ohtawara.tochigi.jp": 1, + "oi.kanagawa.jp": 1, + "oirase.aomori.jp": 1, + "oirm.gov.pl": 1, + "oishida.yamagata.jp": 1, + "oiso.kanagawa.jp": 1, + "oita.jp": 1, + "oita.oita.jp": 1, + "oizumi.gunma.jp": 1, + "oji.nara.jp": 1, + "ojiya.niigata.jp": 1, + "ok.us": 1, + "okagaki.fukuoka.jp": 1, + "okawa.fukuoka.jp": 1, + "okawa.kochi.jp": 1, + "okaya.nagano.jp": 1, + "okayama.jp": 1, + "okayama.okayama.jp": 1, + "okazaki.aichi.jp": 1, + "okegawa.saitama.jp": 1, + "oketo.hokkaido.jp": 1, + "oki.fukuoka.jp": 1, + "okinawa.jp": 1, + "okinawa.okinawa.jp": 1, + "okinoshima.shimane.jp": 1, + "okoppe.hokkaido.jp": 1, + "oksnes.no": 1, + "okuizumo.shimane.jp": 1, + "okuma.fukushima.jp": 1, + "okutama.tokyo.jp": 1, + "ol.no": 1, + "olawa.pl": 1, + "olbia-tempio.it": 1, + "olbiatempio.it": 1, + "olecko.pl": 1, + "olkusz.pl": 1, + "olsztyn.pl": 1, + "omachi.nagano.jp": 1, + "omachi.saga.jp": 1, + "omaezaki.shizuoka.jp": 1, + "omaha.museum": 1, + "omasvuotna.no": 1, + "ome.tokyo.jp": 1, + "omg.lol": 1, + "omi.nagano.jp": 1, + "omi.niigata.jp": 1, + "omigawa.chiba.jp": 1, + "omihachiman.shiga.jp": 1, + "omitama.ibaraki.jp": 1, + "omiya.saitama.jp": 1, + "omniwe.site": 1, + "omotego.fukushima.jp": 1, + "omura.nagasaki.jp": 1, + "omuta.fukuoka.jp": 1, + "on-aptible.com": 1, + "on-k3s.io": 2, + "on-rancher.cloud": 2, + "on-rio.io": 2, + "on-the-web.tv": 1, + "on-web.fr": 1, + "on.ca": 1, + "on.fashion": 1, + "onagawa.miyagi.jp": 1, + "onfabrica.com": 1, + "ong.br": 1, + "onga.fukuoka.jp": 1, + "onjuku.chiba.jp": 1, + "online.museum": 1, + "online.th": 1, + "onna.okinawa.jp": 1, + "ono.fukui.jp": 1, + "ono.fukushima.jp": 1, + "ono.hyogo.jp": 1, + "onojo.fukuoka.jp": 1, + "onomichi.hiroshima.jp": 1, + "onred.one": 1, + "onrender.com": 1, + "ontario.museum": 1, + "onthewifi.com": 1, + "onza.mythic-beasts.com": 1, + "ooguy.com": 1, + "ookuwa.nagano.jp": 1, + "ooshika.nagano.jp": 1, + "openair.museum": 1, + "opencraft.hosting": 1, + "opensocial.site": 1, + "operaunite.com": 1, + "opoczno.pl": 1, + "opole.pl": 1, + "oppdal.no": 1, + "oppegard.no": 1, + "oppeg\u00e5rd.no": 1, + "or.at": 1, + "or.bi": 1, + "or.ci": 1, + "or.cr": 1, + "or.id": 1, + "or.it": 1, + "or.jp": 1, + "or.ke": 1, + "or.kr": 1, + "or.mu": 1, + "or.na": 1, + "or.pw": 1, + "or.th": 1, + "or.tz": 1, + "or.ug": 1, + "or.us": 1, + "ora.gunma.jp": 1, + "oregon.museum": 1, + "oregontrail.museum": 1, + "org.ac": 1, + "org.ae": 1, + "org.af": 1, + "org.ag": 1, + "org.ai": 1, + "org.al": 1, + "org.am": 1, + "org.ar": 1, + "org.au": 1, + "org.az": 1, + "org.ba": 1, + "org.bb": 1, + "org.bh": 1, + "org.bi": 1, + "org.bm": 1, + "org.bn": 1, + "org.bo": 1, + "org.br": 1, + "org.bs": 1, + "org.bt": 1, + "org.bw": 1, + "org.bz": 1, + "org.ci": 1, + "org.cn": 1, + "org.co": 1, + "org.cu": 1, + "org.cw": 1, + "org.cy": 1, + "org.dm": 1, + "org.do": 1, + "org.dz": 1, + "org.ec": 1, + "org.ee": 1, + "org.eg": 1, + "org.es": 1, + "org.et": 1, + "org.fj": 1, + "org.fm": 1, + "org.ge": 1, + "org.gg": 1, + "org.gh": 1, + "org.gi": 1, + "org.gl": 1, + "org.gn": 1, + "org.gp": 1, + "org.gr": 1, + "org.gt": 1, + "org.gu": 1, + "org.gy": 1, + "org.hk": 1, + "org.hn": 1, + "org.ht": 1, + "org.hu": 1, + "org.il": 1, + "org.im": 1, + "org.in": 1, + "org.iq": 1, + "org.ir": 1, + "org.is": 1, + "org.je": 1, + "org.jo": 1, + "org.kg": 1, + "org.ki": 1, + "org.km": 1, + "org.kn": 1, + "org.kp": 1, + "org.kw": 1, + "org.ky": 1, + "org.kz": 1, + "org.la": 1, + "org.lb": 1, + "org.lc": 1, + "org.lk": 1, + "org.lr": 1, + "org.ls": 1, + "org.lv": 1, + "org.ly": 1, + "org.ma": 1, + "org.me": 1, + "org.mg": 1, + "org.mk": 1, + "org.ml": 1, + "org.mn": 1, + "org.mo": 1, + "org.ms": 1, + "org.mt": 1, + "org.mu": 1, + "org.mv": 1, + "org.mw": 1, + "org.mx": 1, + "org.my": 1, + "org.mz": 1, + "org.na": 1, + "org.ng": 1, + "org.ni": 1, + "org.nr": 1, + "org.nz": 1, + "org.om": 1, + "org.pa": 1, + "org.pe": 1, + "org.pf": 1, + "org.ph": 1, + "org.pk": 1, + "org.pl": 1, + "org.pn": 1, + "org.pr": 1, + "org.ps": 1, + "org.pt": 1, + "org.py": 1, + "org.qa": 1, + "org.ro": 1, + "org.rs": 1, + "org.ru": 1, + "org.rw": 1, + "org.sa": 1, + "org.sb": 1, + "org.sc": 1, + "org.sd": 1, + "org.se": 1, + "org.sg": 1, + "org.sh": 1, + "org.sl": 1, + "org.sn": 1, + "org.so": 1, + "org.ss": 1, + "org.st": 1, + "org.sv": 1, + "org.sy": 1, + "org.sz": 1, + "org.tj": 1, + "org.tm": 1, + "org.tn": 1, + "org.to": 1, + "org.tr": 1, + "org.tt": 1, + "org.tw": 1, + "org.ua": 1, + "org.ug": 1, + "org.uk": 1, + "org.uy": 1, + "org.uz": 1, + "org.vc": 1, + "org.ve": 1, + "org.vi": 1, + "org.vn": 1, + "org.vu": 1, + "org.ws": 1, + "org.za": 1, + "org.zm": 1, + "org.zw": 1, + "oristano.it": 1, + "orkanger.no": 1, + "orkdal.no": 1, + "orland.no": 1, + "orskog.no": 1, + "orsta.no": 1, + "orx.biz": 1, + "os.hedmark.no": 1, + "os.hordaland.no": 1, + "osaka.jp": 1, + "osakasayama.osaka.jp": 1, + "osaki.miyagi.jp": 1, + "osakikamijima.hiroshima.jp": 1, + "osasco.br": 1, + "osen.no": 1, + "oseto.nagasaki.jp": 1, + "oshima.tokyo.jp": 1, + "oshima.yamaguchi.jp": 1, + "oshino.yamanashi.jp": 1, + "oshu.iwate.jp": 1, + "oslo.no": 1, + "osoyro.no": 1, + "osteroy.no": 1, + "oster\u00f8y.no": 1, + "ostre-toten.no": 1, + "ostroda.pl": 1, + "ostroleka.pl": 1, + "ostrowiec.pl": 1, + "ostrowwlkp.pl": 1, + "os\u00f8yro.no": 1, + "ot.it": 1, + "ota.gunma.jp": 1, + "ota.tokyo.jp": 1, + "otago.museum": 1, + "otake.hiroshima.jp": 1, + "otaki.chiba.jp": 1, + "otaki.nagano.jp": 1, + "otaki.saitama.jp": 1, + "otama.fukushima.jp": 1, + "otap.co": 2, + "otari.nagano.jp": 1, + "otaru.hokkaido.jp": 1, + "other.nf": 1, + "oto.fukuoka.jp": 1, + "otobe.hokkaido.jp": 1, + "otofuke.hokkaido.jp": 1, + "otoineppu.hokkaido.jp": 1, + "otoyo.kochi.jp": 1, + "otsu.shiga.jp": 1, + "otsuchi.iwate.jp": 1, + "otsuki.kochi.jp": 1, + "otsuki.yamanashi.jp": 1, + "ouchi.saga.jp": 1, + "ouda.nara.jp": 1, + "oum.gov.pl": 1, + "oumu.hokkaido.jp": 1, + "outsystemscloud.com": 1, + "overhalla.no": 1, + "ovre-eiker.no": 1, + "owani.aomori.jp": 1, + "owariasahi.aichi.jp": 1, + "own.pm": 1, + "ownip.net": 1, + "ownprovider.com": 1, + "owo.codes": 2, + "ox.rs": 1, + "oxford.museum": 1, + "oy.lc": 1, + "oya.to": 1, + "oyabe.toyama.jp": 1, + "oyama.tochigi.jp": 1, + "oyamazaki.kyoto.jp": 1, + "oyer.no": 1, + "oygarden.no": 1, + "oyodo.nara.jp": 1, + "oystre-slidre.no": 1, + "oz.au": 1, + "ozora.hokkaido.jp": 1, + "ozu.ehime.jp": 1, + "ozu.kumamoto.jp": 1, + "p.bg": 1, + "p.se": 1, + "pa.gov.br": 1, + "pa.gov.pl": 1, + "pa.it": 1, + "pa.leg.br": 1, + "pa.us": 1, + "paas.datacenter.fi": 1, + "paas.massivegrid.com": 1, + "pacific.museum": 1, + "paderborn.museum": 1, + "padova.it": 1, + "padua.it": 1, + "pagefrontapp.com": 1, + "pages.dev": 1, + "pages.wiardweb.com": 1, + "pagespeedmobilizer.com": 1, + "pagexl.com": 1, + "palace.museum": 1, + "paleo.museum": 1, + "palermo.it": 1, + "palmas.br": 1, + "palmsprings.museum": 1, + "panama.museum": 1, + "panel.gg": 1, + "pantheonsite.io": 1, + "parachuting.aero": 1, + "paragliding.aero": 1, + "paris.eu.org": 1, + "paris.museum": 1, + "parliament.cy": 1, + "parliament.nz": 1, + "parma.it": 1, + "paroch.k12.ma.us": 1, + "parti.se": 1, + "pasadena.museum": 1, + "passenger-association.aero": 1, + "patria.bo": 1, + "pavia.it": 1, + "pb.ao": 1, + "pb.gov.br": 1, + "pb.leg.br": 1, + "pc.it": 1, + "pc.pl": 1, + "pcloud.host": 1, + "pd.it": 1, + "pdns.page": 1, + "pe.ca": 1, + "pe.gov.br": 1, + "pe.it": 1, + "pe.kr": 1, + "pe.leg.br": 1, + "penza.su": 1, + "per.la": 1, + "per.nf": 1, + "per.sg": 1, + "perso.ht": 1, + "perso.sn": 1, + "perso.tn": 1, + "perspecta.cloud": 1, + "perugia.it": 1, + "pesaro-urbino.it": 1, + "pesarourbino.it": 1, + "pescara.it": 1, + "pg": 2, + "pg.it": 1, + "pgafan.net": 1, + "pgfog.com": 1, + "pharmacien.fr": 1, + "pharmaciens.km": 1, + "pharmacy.museum": 1, + "philadelphia.museum": 1, + "philadelphiaarea.museum": 1, + "philately.museum": 1, + "phoenix.museum": 1, + "photography.museum": 1, + "pi.gov.br": 1, + "pi.it": 1, + "pi.leg.br": 1, + "piacenza.it": 1, + "piedmont.it": 1, + "piemonte.it": 1, + "pila.pl": 1, + "pilot.aero": 1, + "pilots.museum": 1, + "pimienta.org": 1, + "pinb.gov.pl": 1, + "pippu.hokkaido.jp": 1, + "pisa.it": 1, + "pistoia.it": 1, + "pisz.pl": 1, + "pittsburgh.museum": 1, + "piw.gov.pl": 1, + "pixolino.com": 1, + "pl.eu.org": 1, + "pl.ua": 1, + "planetarium.museum": 1, + "plantation.museum": 1, + "plants.museum": 1, + "platform0.app": 1, + "platformsh.site": 2, + "platter-app.com": 1, + "platter-app.dev": 1, + "platterp.us": 1, + "playstation-cloud.com": 1, + "plaza.museum": 1, + "plc.co.im": 1, + "plc.ly": 1, + "plc.uk": 1, + "plesk.page": 1, + "pleskns.com": 1, + "plo.ps": 1, + "plurinacional.bo": 1, + "pmn.it": 1, + "pn.it": 1, + "po.gov.pl": 1, + "po.it": 1, + "poa.br": 1, + "podhale.pl": 1, + "podlasie.pl": 1, + "podzone.net": 1, + "podzone.org": 1, + "point2this.com": 1, + "pointto.us": 1, + "poivron.org": 1, + "pokrovsk.su": 1, + "pol.dz": 1, + "pol.ht": 1, + "pol.tr": 1, + "police.uk": 1, + "politica.bo": 1, + "polkowice.pl": 1, + "poltava.ua": 1, + "pomorskie.pl": 1, + "pomorze.pl": 1, + "poniatowa.pl": 1, + "ponpes.id": 1, + "pony.club": 1, + "pordenone.it": 1, + "porsanger.no": 1, + "porsangu.no": 1, + "porsgrunn.no": 1, + "pors\u00e1\u014bgu.no": 1, + "port.fr": 1, + "portal.museum": 1, + "portland.museum": 1, + "portlligat.museum": 1, + "posts-and-telecommunications.museum": 1, + "potager.org": 1, + "potenza.it": 1, + "powiat.pl": 1, + "poznan.pl": 1, + "pp.az": 1, + "pp.ru": 1, + "pp.se": 1, + "pp.ua": 1, + "ppg.br": 1, + "pr.gov.br": 1, + "pr.it": 1, + "pr.leg.br": 1, + "pr.us": 1, + "prato.it": 1, + "prd.fr": 1, + "prd.km": 1, + "prd.mg": 1, + "preservation.museum": 1, + "presidio.museum": 1, + "press.aero": 1, + "press.cy": 1, + "press.ma": 1, + "press.museum": 1, + "press.se": 1, + "presse.ci": 1, + "presse.km": 1, + "presse.ml": 1, + "pri.ee": 1, + "principe.st": 1, + "priv.at": 1, + "priv.hu": 1, + "priv.me": 1, + "priv.no": 1, + "priv.pl": 1, + "privatizehealthinsurance.net": 1, + "pro.az": 1, + "pro.br": 1, + "pro.cy": 1, + "pro.ec": 1, + "pro.fj": 1, + "pro.ht": 1, + "pro.mv": 1, + "pro.na": 1, + "pro.om": 1, + "pro.pr": 1, + "pro.tt": 1, + "pro.vn": 1, + "prochowice.pl": 1, + "production.aero": 1, + "prof.pr": 1, + "profesional.bo": 1, + "project.museum": 1, + "protonet.io": 1, + "pruszkow.pl": 1, + "prvcy.page": 1, + "przeworsk.pl": 1, + "psc.br": 1, + "psi.br": 1, + "psp.gov.pl": 1, + "psse.gov.pl": 1, + "pt.eu.org": 1, + "pt.it": 1, + "ptplus.fit": 1, + "pu.it": 1, + "pub.sa": 1, + "publ.pt": 1, + "public.museum": 1, + "publishproxy.com": 1, + "pubol.museum": 1, + "pubtls.org": 1, + "pueblo.bo": 1, + "pug.it": 1, + "puglia.it": 1, + "pulawy.pl": 1, + "pup.gov.pl": 1, + "pv.it": 1, + "pvh.br": 1, + "pvt.ge": 1, + "pvt.k12.ma.us": 1, + "pyatigorsk.ru": 1, + "pymnt.uk": 1, + "pz.it": 1, + "q-a.eu.org": 1, + "q.bg": 1, + "qa2.com": 1, + "qbuser.com": 1, + "qc.ca": 1, + "qc.com": 1, + "qcx.io": 1, + "qh.cn": 1, + "qld.au": 1, + "qld.edu.au": 1, + "qld.gov.au": 1, + "qsl.br": 1, + "qualifioapp.com": 1, + "quebec.museum": 1, + "quicksytes.com": 1, + "quipelements.com": 2, + "r.appspot.com": 2, + "r.bg": 1, + "r.cdn77.net": 1, + "r.se": 1, + "ra.it": 1, + "rackmaze.com": 1, + "rackmaze.net": 1, + "rade.no": 1, + "radio.am": 1, + "radio.br": 1, + "radio.fm": 1, + "radom.pl": 1, + "radoy.no": 1, + "rad\u00f8y.no": 1, + "ragusa.it": 1, + "rahkkeravju.no": 1, + "raholt.no": 1, + "railroad.museum": 1, + "railway.museum": 1, + "raisa.no": 1, + "rakkestad.no": 1, + "ralingen.no": 1, + "rana.no": 1, + "randaberg.no": 1, + "rankoshi.hokkaido.jp": 1, + "ranzan.saitama.jp": 1, + "ras.ru": 1, + "rauma.no": 1, + "ravendb.community": 1, + "ravendb.me": 1, + "ravendb.run": 1, + "ravenna.it": 1, + "rawa-maz.pl": 1, + "rc.it": 1, + "rdv.to": 1, + "re.it": 1, + "re.kr": 1, + "read-books.org": 1, + "readmyblog.org": 1, + "readthedocs.io": 1, + "realestate.pl": 1, + "realm.cz": 1, + "rebun.hokkaido.jp": 1, + "rec.br": 1, + "rec.co": 1, + "rec.nf": 1, + "rec.ro": 1, + "rec.ve": 1, + "recht.pro": 1, + "recife.br": 1, + "recreation.aero": 1, + "red.sv": 1, + "redirectme.net": 1, + "reg.dk": 1, + "reggio-calabria.it": 1, + "reggio-emilia.it": 1, + "reggiocalabria.it": 1, + "reggioemilia.it": 1, + "reklam.hu": 1, + "rel.ht": 1, + "rel.pl": 1, + "remotewd.com": 1, + "rendalen.no": 1, + "rennebu.no": 1, + "rennesoy.no": 1, + "rennes\u00f8y.no": 1, + "rep.br": 1, + "rep.kp": 1, + "repbody.aero": 1, + "repl.co": 1, + "repl.run": 1, + "res.aero": 1, + "res.in": 1, + "research.aero": 1, + "research.museum": 1, + "resindevice.io": 1, + "resistance.museum": 1, + "revista.bo": 1, + "rg.it": 1, + "rhcloud.com": 1, + "ri.it": 1, + "ri.us": 1, + "ribeirao.br": 1, + "rieti.it": 1, + "rifu.miyagi.jp": 1, + "riik.ee": 1, + "rikubetsu.hokkaido.jp": 1, + "rikuzentakata.iwate.jp": 1, + "rimini.it": 1, + "rindal.no": 1, + "ringebu.no": 1, + "ringerike.no": 1, + "ringsaker.no": 1, + "rio.br": 1, + "riobranco.br": 1, + "riodejaneiro.museum": 1, + "riopreto.br": 1, + "rishiri.hokkaido.jp": 1, + "rishirifuji.hokkaido.jp": 1, + "risor.no": 1, + "rissa.no": 1, + "ris\u00f8r.no": 1, + "ritto.shiga.jp": 1, + "rivne.ua": 1, + "rj.gov.br": 1, + "rj.leg.br": 1, + "rl.no": 1, + "rm.it": 1, + "rn.gov.br": 1, + "rn.it": 1, + "rn.leg.br": 1, + "rnrt.tn": 1, + "rns.tn": 1, + "rnu.tn": 1, + "ro.eu.org": 1, + "ro.gov.br": 1, + "ro.im": 1, + "ro.it": 1, + "ro.leg.br": 1, + "roan.no": 1, + "rochester.museum": 1, + "rockart.museum": 1, + "rodoy.no": 1, + "rokunohe.aomori.jp": 1, + "rollag.no": 1, + "roma.it": 1, + "roma.museum": 1, + "rome.it": 1, + "romsa.no": 1, + "romskog.no": 1, + "roros.no": 1, + "rost.no": 1, + "rotorcraft.aero": 1, + "router.management": 1, + "rovigo.it": 1, + "rovno.ua": 1, + "royken.no": 1, + "royrvik.no": 1, + "rr.gov.br": 1, + "rr.leg.br": 1, + "rs.gov.br": 1, + "rs.leg.br": 1, + "rsc.cdn77.org": 1, + "ru.com": 1, + "ru.eu.org": 1, + "ru.net": 1, + "run.app": 1, + "ruovat.no": 1, + "russia.museum": 1, + "rv.ua": 1, + "rybnik.pl": 1, + "rygge.no": 1, + "ryokami.saitama.jp": 1, + "ryugasaki.ibaraki.jp": 1, + "ryuoh.shiga.jp": 1, + "rzeszow.pl": 1, + "rzgw.gov.pl": 1, + "r\u00e1hkker\u00e1vju.no": 1, + "r\u00e1isa.no": 1, + "r\u00e5de.no": 1, + "r\u00e5holt.no": 1, + "r\u00e6lingen.no": 1, + "r\u00f8d\u00f8y.no": 1, + "r\u00f8mskog.no": 1, + "r\u00f8ros.no": 1, + "r\u00f8st.no": 1, + "r\u00f8yken.no": 1, + "r\u00f8yrvik.no": 1, + "s.bg": 1, + "s.se": 1, + "s3-ap-northeast-1.amazonaws.com": 1, + "s3-ap-northeast-2.amazonaws.com": 1, + "s3-ap-south-1.amazonaws.com": 1, + "s3-ap-southeast-1.amazonaws.com": 1, + "s3-ap-southeast-2.amazonaws.com": 1, + "s3-ca-central-1.amazonaws.com": 1, + "s3-eu-central-1.amazonaws.com": 1, + "s3-eu-west-1.amazonaws.com": 1, + "s3-eu-west-2.amazonaws.com": 1, + "s3-eu-west-3.amazonaws.com": 1, + "s3-external-1.amazonaws.com": 1, + "s3-fips-us-gov-west-1.amazonaws.com": 1, + "s3-sa-east-1.amazonaws.com": 1, + "s3-us-east-2.amazonaws.com": 1, + "s3-us-gov-west-1.amazonaws.com": 1, + "s3-us-west-1.amazonaws.com": 1, + "s3-us-west-2.amazonaws.com": 1, + "s3-website-ap-northeast-1.amazonaws.com": 1, + "s3-website-ap-southeast-1.amazonaws.com": 1, + "s3-website-ap-southeast-2.amazonaws.com": 1, + "s3-website-eu-west-1.amazonaws.com": 1, + "s3-website-sa-east-1.amazonaws.com": 1, + "s3-website-us-east-1.amazonaws.com": 1, + "s3-website-us-west-1.amazonaws.com": 1, + "s3-website-us-west-2.amazonaws.com": 1, + "s3-website.ap-northeast-2.amazonaws.com": 1, + "s3-website.ap-south-1.amazonaws.com": 1, + "s3-website.ca-central-1.amazonaws.com": 1, + "s3-website.eu-central-1.amazonaws.com": 1, + "s3-website.eu-west-2.amazonaws.com": 1, + "s3-website.eu-west-3.amazonaws.com": 1, + "s3-website.us-east-2.amazonaws.com": 1, + "s3.amazonaws.com": 1, + "s3.ap-northeast-2.amazonaws.com": 1, + "s3.ap-south-1.amazonaws.com": 1, + "s3.ca-central-1.amazonaws.com": 1, + "s3.cn-north-1.amazonaws.com.cn": 1, + "s3.dualstack.ap-northeast-1.amazonaws.com": 1, + "s3.dualstack.ap-northeast-2.amazonaws.com": 1, + "s3.dualstack.ap-south-1.amazonaws.com": 1, + "s3.dualstack.ap-southeast-1.amazonaws.com": 1, + "s3.dualstack.ap-southeast-2.amazonaws.com": 1, + "s3.dualstack.ca-central-1.amazonaws.com": 1, + "s3.dualstack.eu-central-1.amazonaws.com": 1, + "s3.dualstack.eu-west-1.amazonaws.com": 1, + "s3.dualstack.eu-west-2.amazonaws.com": 1, + "s3.dualstack.eu-west-3.amazonaws.com": 1, + "s3.dualstack.sa-east-1.amazonaws.com": 1, + "s3.dualstack.us-east-1.amazonaws.com": 1, + "s3.dualstack.us-east-2.amazonaws.com": 1, + "s3.eu-central-1.amazonaws.com": 1, + "s3.eu-west-2.amazonaws.com": 1, + "s3.eu-west-3.amazonaws.com": 1, + "s3.us-east-2.amazonaws.com": 1, + "s5y.io": 2, + "sa-east-1.elasticbeanstalk.com": 1, + "sa.au": 1, + "sa.com": 1, + "sa.cr": 1, + "sa.edu.au": 1, + "sa.gov.au": 1, + "sa.gov.pl": 1, + "sa.it": 1, + "sabae.fukui.jp": 1, + "sado.niigata.jp": 1, + "safety.aero": 1, + "saga.jp": 1, + "saga.saga.jp": 1, + "sagae.yamagata.jp": 1, + "sagamihara.kanagawa.jp": 1, + "saigawa.fukuoka.jp": 1, + "saijo.ehime.jp": 1, + "saikai.nagasaki.jp": 1, + "saiki.oita.jp": 1, + "saintlouis.museum": 1, + "saitama.jp": 1, + "saitama.saitama.jp": 1, + "saito.miyazaki.jp": 1, + "saka.hiroshima.jp": 1, + "sakado.saitama.jp": 1, + "sakae.chiba.jp": 1, + "sakae.nagano.jp": 1, + "sakahogi.gifu.jp": 1, + "sakai.fukui.jp": 1, + "sakai.ibaraki.jp": 1, + "sakai.osaka.jp": 1, + "sakaiminato.tottori.jp": 1, + "sakaki.nagano.jp": 1, + "sakata.yamagata.jp": 1, + "sakawa.kochi.jp": 1, + "sakegawa.yamagata.jp": 1, + "saku.nagano.jp": 1, + "sakuho.nagano.jp": 1, + "sakura.chiba.jp": 1, + "sakura.tochigi.jp": 1, + "sakuragawa.ibaraki.jp": 1, + "sakurai.nara.jp": 1, + "sakyo.kyoto.jp": 1, + "salangen.no": 1, + "salat.no": 1, + "salem.museum": 1, + "salerno.it": 1, + "saltdal.no": 1, + "salud.bo": 1, + "salvador.br": 1, + "salvadordali.museum": 1, + "salzburg.museum": 1, + "samegawa.fukushima.jp": 1, + "samnanger.no": 1, + "sampa.br": 1, + "samukawa.kanagawa.jp": 1, + "sanagochi.tokushima.jp": 1, + "sanda.hyogo.jp": 1, + "sandcats.io": 1, + "sande.more-og-romsdal.no": 1, + "sande.m\u00f8re-og-romsdal.no": 1, + "sande.vestfold.no": 1, + "sandefjord.no": 1, + "sandiego.museum": 1, + "sandnes.no": 1, + "sandnessjoen.no": 1, + "sandnessj\u00f8en.no": 1, + "sandoy.no": 1, + "sand\u00f8y.no": 1, + "sanfrancisco.museum": 1, + "sango.nara.jp": 1, + "sanjo.niigata.jp": 1, + "sannan.hyogo.jp": 1, + "sannohe.aomori.jp": 1, + "sano.tochigi.jp": 1, + "sanok.pl": 1, + "santabarbara.museum": 1, + "santacruz.museum": 1, + "santafe.museum": 1, + "santamaria.br": 1, + "santoandre.br": 1, + "sanuki.kagawa.jp": 1, + "saobernardo.br": 1, + "saogonca.br": 1, + "saotome.st": 1, + "sapporo.jp": 2, + "sar.it": 1, + "sardegna.it": 1, + "sardinia.it": 1, + "saroma.hokkaido.jp": 1, + "sarpsborg.no": 1, + "sarufutsu.hokkaido.jp": 1, + "sasaguri.fukuoka.jp": 1, + "sasayama.hyogo.jp": 1, + "sasebo.nagasaki.jp": 1, + "saskatchewan.museum": 1, + "sassari.it": 1, + "satosho.okayama.jp": 1, + "satsumasendai.kagoshima.jp": 1, + "satte.saitama.jp": 1, + "satx.museum": 1, + "sauda.no": 1, + "sauherad.no": 1, + "savannahga.museum": 1, + "saves-the-whales.com": 1, + "savona.it": 1, + "sayama.osaka.jp": 1, + "sayama.saitama.jp": 1, + "sayo.hyogo.jp": 1, + "sb.ua": 1, + "sc.cn": 1, + "sc.gov.br": 1, + "sc.ke": 1, + "sc.kr": 1, + "sc.leg.br": 1, + "sc.ls": 1, + "sc.tz": 1, + "sc.ug": 1, + "sc.us": 1, + "scapp.io": 1, + "sch.ae": 1, + "sch.id": 1, + "sch.ir": 1, + "sch.jo": 1, + "sch.lk": 1, + "sch.ly": 1, + "sch.ng": 1, + "sch.qa": 1, + "sch.sa": 1, + "sch.so": 1, + "sch.uk": 2, + "sch.zm": 1, + "schlesisches.museum": 1, + "schoenbrunn.museum": 1, + "schokokeks.net": 1, + "schokoladen.museum": 1, + "school.museum": 1, + "school.na": 1, + "school.nz": 1, + "school.za": 1, + "schools.nsw.edu.au": 1, + "schulserver.de": 1, + "schweiz.museum": 1, + "sci.eg": 1, + "science-fiction.museum": 1, + "science.museum": 1, + "scienceandhistory.museum": 1, + "scienceandindustry.museum": 1, + "sciencecenter.museum": 1, + "sciencecenters.museum": 1, + "sciencehistory.museum": 1, + "sciences.museum": 1, + "sciencesnaturelles.museum": 1, + "scientist.aero": 1, + "scotland.museum": 1, + "scrapper-site.net": 1, + "scrapping.cc": 1, + "scrysec.com": 1, + "sd.cn": 1, + "sd.us": 1, + "sdn.gov.pl": 1, + "se.eu.org": 1, + "se.gov.br": 1, + "se.leg.br": 1, + "se.net": 1, + "seaport.museum": 1, + "sebastopol.ua": 1, + "sec.ps": 1, + "securitytactics.com": 1, + "seg.br": 1, + "seidat.net": 1, + "seihi.nagasaki.jp": 1, + "seika.kyoto.jp": 1, + "seiro.niigata.jp": 1, + "seirou.niigata.jp": 1, + "seiyo.ehime.jp": 1, + "sejny.pl": 1, + "seki.gifu.jp": 1, + "sekigahara.gifu.jp": 1, + "sekikawa.niigata.jp": 1, + "sel.no": 1, + "selbu.no": 1, + "selfip.biz": 1, + "selfip.com": 1, + "selfip.info": 1, + "selfip.net": 1, + "selfip.org": 1, + "selje.no": 1, + "seljord.no": 1, + "sells-for-less.com": 1, + "sells-for-u.com": 1, + "sells-it.net": 1, + "sellsyourhome.org": 1, + "semboku.akita.jp": 1, + "semine.miyagi.jp": 1, + "sendai.jp": 2, + "sennan.osaka.jp": 1, + "senseering.net": 1, + "sensiosite.cloud": 2, + "seoul.kr": 1, + "sera.hiroshima.jp": 1, + "seranishi.hiroshima.jp": 1, + "servebbs.com": 1, + "servebbs.net": 1, + "servebbs.org": 1, + "servebeer.com": 1, + "serveblog.net": 1, + "servecounterstrike.com": 1, + "serveexchange.com": 1, + "serveftp.com": 1, + "serveftp.net": 1, + "serveftp.org": 1, + "servegame.com": 1, + "servegame.org": 1, + "servehalflife.com": 1, + "servehttp.com": 1, + "servehumour.com": 1, + "serveirc.com": 1, + "serveminecraft.net": 1, + "servemp3.com": 1, + "servep2p.com": 1, + "servepics.com": 1, + "servequake.com": 1, + "servesarcasm.com": 1, + "service.gov.uk": 1, + "services.aero": 1, + "setagaya.tokyo.jp": 1, + "seto.aichi.jp": 1, + "setouchi.okayama.jp": 1, + "settlement.museum": 1, + "settlers.museum": 1, + "settsu.osaka.jp": 1, + "sevastopol.ua": 1, + "sex.hu": 1, + "sex.pl": 1, + "sf.no": 1, + "sh.cn": 1, + "shacknet.nu": 1, + "shakotan.hokkaido.jp": 1, + "shari.hokkaido.jp": 1, + "shell.museum": 1, + "sherbrooke.museum": 1, + "shibata.miyagi.jp": 1, + "shibata.niigata.jp": 1, + "shibecha.hokkaido.jp": 1, + "shibetsu.hokkaido.jp": 1, + "shibukawa.gunma.jp": 1, + "shibuya.tokyo.jp": 1, + "shichikashuku.miyagi.jp": 1, + "shichinohe.aomori.jp": 1, + "shiftedit.io": 1, + "shiga.jp": 1, + "shiiba.miyazaki.jp": 1, + "shijonawate.osaka.jp": 1, + "shika.ishikawa.jp": 1, + "shikabe.hokkaido.jp": 1, + "shikama.miyagi.jp": 1, + "shikaoi.hokkaido.jp": 1, + "shikatsu.aichi.jp": 1, + "shiki.saitama.jp": 1, + "shikokuchuo.ehime.jp": 1, + "shima.mie.jp": 1, + "shimabara.nagasaki.jp": 1, + "shimada.shizuoka.jp": 1, + "shimamaki.hokkaido.jp": 1, + "shimamoto.osaka.jp": 1, + "shimane.jp": 1, + "shimane.shimane.jp": 1, + "shimizu.hokkaido.jp": 1, + "shimizu.shizuoka.jp": 1, + "shimoda.shizuoka.jp": 1, + "shimodate.ibaraki.jp": 1, + "shimofusa.chiba.jp": 1, + "shimogo.fukushima.jp": 1, + "shimoichi.nara.jp": 1, + "shimoji.okinawa.jp": 1, + "shimokawa.hokkaido.jp": 1, + "shimokitayama.nara.jp": 1, + "shimonita.gunma.jp": 1, + "shimonoseki.yamaguchi.jp": 1, + "shimosuwa.nagano.jp": 1, + "shimotsuke.tochigi.jp": 1, + "shimotsuma.ibaraki.jp": 1, + "shinagawa.tokyo.jp": 1, + "shinanomachi.nagano.jp": 1, + "shingo.aomori.jp": 1, + "shingu.fukuoka.jp": 1, + "shingu.hyogo.jp": 1, + "shingu.wakayama.jp": 1, + "shinichi.hiroshima.jp": 1, + "shinjo.nara.jp": 1, + "shinjo.okayama.jp": 1, + "shinjo.yamagata.jp": 1, + "shinjuku.tokyo.jp": 1, + "shinkamigoto.nagasaki.jp": 1, + "shinonsen.hyogo.jp": 1, + "shinshinotsu.hokkaido.jp": 1, + "shinshiro.aichi.jp": 1, + "shinto.gunma.jp": 1, + "shintoku.hokkaido.jp": 1, + "shintomi.miyazaki.jp": 1, + "shinyoshitomi.fukuoka.jp": 1, + "shiogama.miyagi.jp": 1, + "shiojiri.nagano.jp": 1, + "shioya.tochigi.jp": 1, + "shirahama.wakayama.jp": 1, + "shirakawa.fukushima.jp": 1, + "shirakawa.gifu.jp": 1, + "shirako.chiba.jp": 1, + "shiranuka.hokkaido.jp": 1, + "shiraoi.hokkaido.jp": 1, + "shiraoka.saitama.jp": 1, + "shirataka.yamagata.jp": 1, + "shiriuchi.hokkaido.jp": 1, + "shiroi.chiba.jp": 1, + "shiroishi.miyagi.jp": 1, + "shiroishi.saga.jp": 1, + "shirosato.ibaraki.jp": 1, + "shishikui.tokushima.jp": 1, + "shiso.hyogo.jp": 1, + "shisui.chiba.jp": 1, + "shitara.aichi.jp": 1, + "shiwa.iwate.jp": 1, + "shizukuishi.iwate.jp": 1, + "shizuoka.jp": 1, + "shizuoka.shizuoka.jp": 1, + "shobara.hiroshima.jp": 1, + "shonai.fukuoka.jp": 1, + "shonai.yamagata.jp": 1, + "shoo.okayama.jp": 1, + "shop.ht": 1, + "shop.hu": 1, + "shop.pl": 1, + "shop.ro": 1, + "shop.th": 1, + "shopitsite.com": 1, + "shopware.store": 1, + "show.aero": 1, + "showa.fukushima.jp": 1, + "showa.gunma.jp": 1, + "showa.yamanashi.jp": 1, + "shunan.yamaguchi.jp": 1, + "shw.io": 1, + "si.eu.org": 1, + "si.it": 1, + "sibenik.museum": 1, + "sic.it": 1, + "sicilia.it": 1, + "sicily.it": 1, + "siellak.no": 1, + "siena.it": 1, + "sigdal.no": 1, + "siljan.no": 1, + "silk.museum": 1, + "simple-url.com": 1, + "sinaapp.com": 1, + "siracusa.it": 1, + "sirdal.no": 1, + "siteleaf.net": 1, + "sites.static.land": 1, + "sjc.br": 1, + "sk.ca": 1, + "sk.eu.org": 1, + "skanit.no": 1, + "skanland.no": 1, + "skaun.no": 1, + "skedsmo.no": 1, + "skedsmokorset.no": 1, + "ski.museum": 1, + "ski.no": 1, + "skien.no": 1, + "skierva.no": 1, + "skierv\u00e1.no": 1, + "skiptvet.no": 1, + "skjak.no": 1, + "skjervoy.no": 1, + "skjerv\u00f8y.no": 1, + "skj\u00e5k.no": 1, + "sklep.pl": 1, + "sko.gov.pl": 1, + "skoczow.pl": 1, + "skodje.no": 1, + "skole.museum": 1, + "skydiving.aero": 1, + "skygearapp.com": 1, + "sk\u00e1nit.no": 1, + "sk\u00e5nland.no": 1, + "slask.pl": 1, + "slattum.no": 1, + "sld.do": 1, + "sld.pa": 1, + "slg.br": 1, + "slupsk.pl": 1, + "slz.br": 1, + "sm.ua": 1, + "small-web.org": 1, + "smola.no": 1, + "sm\u00f8la.no": 1, + "sn.cn": 1, + "snaase.no": 1, + "snasa.no": 1, + "snillfjord.no": 1, + "snoasa.no": 1, + "sn\u00e5ase.no": 1, + "sn\u00e5sa.no": 1, + "so.gov.pl": 1, + "so.it": 1, + "sobetsu.hokkaido.jp": 1, + "soc.dz": 1, + "soc.lk": 1, + "soc.srcf.net": 1, + "sochi.su": 1, + "society.museum": 1, + "sodegaura.chiba.jp": 1, + "soeda.fukuoka.jp": 1, + "software.aero": 1, + "sogndal.no": 1, + "sogne.no": 1, + "soja.okayama.jp": 1, + "soka.saitama.jp": 1, + "sokndal.no": 1, + "sola.no": 1, + "sologne.museum": 1, + "solund.no": 1, + "soma.fukushima.jp": 1, + "somna.no": 1, + "sondre-land.no": 1, + "sondrio.it": 1, + "songdalen.no": 1, + "soni.nara.jp": 1, + "soo.kagoshima.jp": 1, + "sopot.pl": 1, + "sor-aurdal.no": 1, + "sor-fron.no": 1, + "sor-odal.no": 1, + "sor-varanger.no": 1, + "sorfold.no": 1, + "sorocaba.br": 1, + "sorreisa.no": 1, + "sortland.no": 1, + "sorum.no": 1, + "sos.pl": 1, + "sosa.chiba.jp": 1, + "sosnowiec.pl": 1, + "soundandvision.museum": 1, + "soundcast.me": 1, + "southcarolina.museum": 1, + "southwest.museum": 1, + "sowa.ibaraki.jp": 1, + "sp.gov.br": 1, + "sp.it": 1, + "sp.leg.br": 1, + "space-to-rent.com": 1, + "space.museum": 1, + "spacekit.io": 1, + "spb.ru": 1, + "spb.su": 1, + "spdns.de": 1, + "spdns.eu": 1, + "spdns.org": 1, + "spectrum.myjino.ru": 2, + "sphinx.mythic-beasts.com": 1, + "spjelkavik.no": 1, + "sport.hu": 1, + "spy.museum": 1, + "spydeberg.no": 1, + "square.museum": 1, + "square7.ch": 1, + "square7.de": 1, + "square7.net": 1, + "sr.gov.pl": 1, + "sr.it": 1, + "srv.br": 1, + "ss.it": 1, + "ssl.origin.cdn77-secure.org": 1, + "st.no": 1, + "stackhero-network.com": 1, + "stadt.museum": 1, + "stage.nodeart.io": 1, + "staging.onred.one": 1, + "stalbans.museum": 1, + "stalowa-wola.pl": 1, + "stange.no": 1, + "starachowice.pl": 1, + "stargard.pl": 1, + "starnberg.museum": 1, + "starostwo.gov.pl": 1, + "stat.no": 1, + "state.museum": 1, + "stateofdelaware.museum": 1, + "stathelle.no": 1, + "static-access.net": 1, + "static.land": 1, + "static.observableusercontent.com": 1, + "statics.cloud": 2, + "station.museum": 1, + "stavanger.no": 1, + "stavern.no": 1, + "steam.museum": 1, + "steiermark.museum": 1, + "steigen.no": 1, + "steinkjer.no": 1, + "stg.dev": 2, + "sth.ac.at": 1, + "stjohn.museum": 1, + "stjordal.no": 1, + "stjordalshalsen.no": 1, + "stj\u00f8rdal.no": 1, + "stj\u00f8rdalshalsen.no": 1, + "stockholm.museum": 1, + "stokke.no": 1, + "stolos.io": 2, + "stor-elvdal.no": 1, + "storage.yandexcloud.net": 1, + "stord.no": 1, + "stordal.no": 1, + "store.bb": 1, + "store.dk": 1, + "store.nf": 1, + "store.ro": 1, + "store.st": 1, + "store.ve": 1, + "storfjord.no": 1, + "storj.farm": 1, + "stpetersburg.museum": 1, + "strand.no": 1, + "stranda.no": 1, + "stryn.no": 1, + "student.aero": 1, + "stuff-4-sale.org": 1, + "stuff-4-sale.us": 1, + "stufftoread.com": 1, + "stuttgart.museum": 1, + "sue.fukuoka.jp": 1, + "suedtirol.it": 1, + "suginami.tokyo.jp": 1, + "sugito.saitama.jp": 1, + "suifu.ibaraki.jp": 1, + "suisse.museum": 1, + "suita.osaka.jp": 1, + "sukagawa.fukushima.jp": 1, + "sukumo.kochi.jp": 1, + "sula.no": 1, + "suldal.no": 1, + "suli.hu": 1, + "sumida.tokyo.jp": 1, + "sumita.iwate.jp": 1, + "sumoto.hyogo.jp": 1, + "sumoto.kumamoto.jp": 1, + "sumy.ua": 1, + "sunagawa.hokkaido.jp": 1, + "sund.no": 1, + "sunndal.no": 1, + "surgeonshall.museum": 1, + "surnadal.no": 1, + "surrey.museum": 1, + "susaki.kochi.jp": 1, + "susono.shizuoka.jp": 1, + "suwa.nagano.jp": 1, + "suwalki.pl": 1, + "suzaka.nagano.jp": 1, + "suzu.ishikawa.jp": 1, + "suzuka.mie.jp": 1, + "sv.it": 1, + "svalbard.no": 1, + "svc.firenet.ch": 2, + "sveio.no": 1, + "svelvik.no": 1, + "svizzera.museum": 1, + "svn-repos.de": 1, + "sweden.museum": 1, + "sweetpepper.org": 1, + "swidnica.pl": 1, + "swidnik.pl": 1, + "swiebodzin.pl": 1, + "swinoujscie.pl": 1, + "sx.cn": 1, + "sydney.museum": 1, + "sykkylven.no": 1, + "syncloud.it": 1, + "syno-ds.de": 1, + "synology-diskstation.de": 1, + "synology-ds.de": 1, + "synology.me": 1, + "sys.qcx.io": 2, + "sytes.net": 1, + "szczecin.pl": 1, + "szczytno.pl": 1, + "szex.hu": 1, + "szkola.pl": 1, + "s\u00e1lat.no": 1, + "s\u00e1l\u00e1t.no": 1, + "s\u00f8gne.no": 1, + "s\u00f8mna.no": 1, + "s\u00f8ndre-land.no": 1, + "s\u00f8r-aurdal.no": 1, + "s\u00f8r-fron.no": 1, + "s\u00f8r-odal.no": 1, + "s\u00f8r-varanger.no": 1, + "s\u00f8rfold.no": 1, + "s\u00f8rreisa.no": 1, + "s\u00f8rum.no": 1, + "s\u00fcdtirol.it": 1, + "t.bg": 1, + "t.se": 1, + "t3l3p0rt.net": 1, + "ta.it": 1, + "taa.it": 1, + "tabayama.yamanashi.jp": 1, + "tabuse.yamaguchi.jp": 1, + "tachiarai.fukuoka.jp": 1, + "tachikawa.tokyo.jp": 1, + "tadaoka.osaka.jp": 1, + "tado.mie.jp": 1, + "tadotsu.kagawa.jp": 1, + "tagajo.miyagi.jp": 1, + "tagami.niigata.jp": 1, + "tagawa.fukuoka.jp": 1, + "tahara.aichi.jp": 1, + "taifun-dns.de": 1, + "taiji.wakayama.jp": 1, + "taiki.hokkaido.jp": 1, + "taiki.mie.jp": 1, + "tainai.niigata.jp": 1, + "taira.toyama.jp": 1, + "taishi.hyogo.jp": 1, + "taishi.osaka.jp": 1, + "taishin.fukushima.jp": 1, + "taito.tokyo.jp": 1, + "taiwa.miyagi.jp": 1, + "tajimi.gifu.jp": 1, + "tajiri.osaka.jp": 1, + "taka.hyogo.jp": 1, + "takagi.nagano.jp": 1, + "takahagi.ibaraki.jp": 1, + "takahama.aichi.jp": 1, + "takahama.fukui.jp": 1, + "takaharu.miyazaki.jp": 1, + "takahashi.okayama.jp": 1, + "takahata.yamagata.jp": 1, + "takaishi.osaka.jp": 1, + "takamatsu.kagawa.jp": 1, + "takamori.kumamoto.jp": 1, + "takamori.nagano.jp": 1, + "takanabe.miyazaki.jp": 1, + "takanezawa.tochigi.jp": 1, + "takaoka.toyama.jp": 1, + "takarazuka.hyogo.jp": 1, + "takasago.hyogo.jp": 1, + "takasaki.gunma.jp": 1, + "takashima.shiga.jp": 1, + "takasu.hokkaido.jp": 1, + "takata.fukuoka.jp": 1, + "takatori.nara.jp": 1, + "takatsuki.osaka.jp": 1, + "takatsuki.shiga.jp": 1, + "takayama.gifu.jp": 1, + "takayama.gunma.jp": 1, + "takayama.nagano.jp": 1, + "takazaki.miyazaki.jp": 1, + "takehara.hiroshima.jp": 1, + "taketa.oita.jp": 1, + "taketomi.okinawa.jp": 1, + "taki.mie.jp": 1, + "takikawa.hokkaido.jp": 1, + "takino.hyogo.jp": 1, + "takinoue.hokkaido.jp": 1, + "takko.aomori.jp": 1, + "tako.chiba.jp": 1, + "taku.saga.jp": 1, + "tama.tokyo.jp": 1, + "tamakawa.fukushima.jp": 1, + "tamaki.mie.jp": 1, + "tamamura.gunma.jp": 1, + "tamano.okayama.jp": 1, + "tamatsukuri.ibaraki.jp": 1, + "tamayu.shimane.jp": 1, + "tamba.hyogo.jp": 1, + "tana.no": 1, + "tanabe.kyoto.jp": 1, + "tanabe.wakayama.jp": 1, + "tanagura.fukushima.jp": 1, + "tananger.no": 1, + "tank.museum": 1, + "tanohata.iwate.jp": 1, + "tara.saga.jp": 1, + "tarama.okinawa.jp": 1, + "taranto.it": 1, + "targi.pl": 1, + "tarnobrzeg.pl": 1, + "tarui.gifu.jp": 1, + "tarumizu.kagoshima.jp": 1, + "tas.au": 1, + "tas.edu.au": 1, + "tas.gov.au": 1, + "tashkent.su": 1, + "tatebayashi.gunma.jp": 1, + "tateshina.nagano.jp": 1, + "tateyama.chiba.jp": 1, + "tateyama.toyama.jp": 1, + "tatsuno.hyogo.jp": 1, + "tatsuno.nagano.jp": 1, + "tawaramoto.nara.jp": 1, + "taxi.br": 1, + "tc.br": 1, + "tcm.museum": 1, + "tcp4.me": 1, + "te.it": 1, + "te.ua": 1, + "teaches-yoga.com": 1, + "teams.algorithmia.com": 0, + "tec.br": 1, + "tec.mi.us": 1, + "tec.ve": 1, + "technology.museum": 1, + "tecnologia.bo": 1, + "tel.tr": 1, + "tele.amune.org": 1, + "telebit.app": 1, + "telebit.io": 1, + "telebit.xyz": 2, + "telekommunikation.museum": 1, + "television.museum": 1, + "temp-dns.com": 1, + "tempio-olbia.it": 1, + "tempioolbia.it": 1, + "tendo.yamagata.jp": 1, + "tenei.fukushima.jp": 1, + "tenkawa.nara.jp": 1, + "tenri.nara.jp": 1, + "teo.br": 1, + "teramo.it": 1, + "termez.su": 1, + "terni.it": 1, + "ternopil.ua": 1, + "teshikaga.hokkaido.jp": 1, + "test-iserv.de": 1, + "test.algorithmia.com": 0, + "test.ru": 1, + "test.tj": 1, + "texas.museum": 1, + "textile.museum": 1, + "tgory.pl": 1, + "the.br": 1, + "theater.museum": 1, + "theworkpc.com": 1, + "thingdustdata.com": 1, + "thruhere.net": 1, + "time.museum": 1, + "time.no": 1, + "timekeeping.museum": 1, + "tingvoll.no": 1, + "tinn.no": 1, + "tj.cn": 1, + "tjeldsund.no": 1, + "tjome.no": 1, + "tj\u00f8me.no": 1, + "tksat.bo": 1, + "tm.cy": 1, + "tm.dz": 1, + "tm.fr": 1, + "tm.hu": 1, + "tm.km": 1, + "tm.mc": 1, + "tm.mg": 1, + "tm.no": 1, + "tm.pl": 1, + "tm.ro": 1, + "tm.se": 1, + "tm.za": 1, + "tmp.br": 1, + "tn.it": 1, + "tn.us": 1, + "to.gov.br": 1, + "to.gt": 1, + "to.it": 1, + "to.leg.br": 1, + "to.md": 1, + "to.work": 1, + "toba.mie.jp": 1, + "tobe.ehime.jp": 1, + "tobetsu.hokkaido.jp": 1, + "tobishima.aichi.jp": 1, + "tochigi.jp": 1, + "tochigi.tochigi.jp": 1, + "tochio.niigata.jp": 1, + "toda.saitama.jp": 1, + "toei.aichi.jp": 1, + "toga.toyama.jp": 1, + "togakushi.nagano.jp": 1, + "togane.chiba.jp": 1, + "togitsu.nagasaki.jp": 1, + "togliatti.su": 1, + "togo.aichi.jp": 1, + "togura.nagano.jp": 1, + "tohma.hokkaido.jp": 1, + "tohnosho.chiba.jp": 1, + "toho.fukuoka.jp": 1, + "tokai.aichi.jp": 1, + "tokai.ibaraki.jp": 1, + "tokamachi.niigata.jp": 1, + "tokashiki.okinawa.jp": 1, + "toki.gifu.jp": 1, + "tokigawa.saitama.jp": 1, + "tokke.no": 1, + "tokoname.aichi.jp": 1, + "tokorozawa.saitama.jp": 1, + "tokushima.jp": 1, + "tokushima.tokushima.jp": 1, + "tokuyama.yamaguchi.jp": 1, + "tokyo.jp": 1, + "tolga.no": 1, + "tomakomai.hokkaido.jp": 1, + "tomari.hokkaido.jp": 1, + "tome.miyagi.jp": 1, + "tomi.nagano.jp": 1, + "tomigusuku.okinawa.jp": 1, + "tomika.gifu.jp": 1, + "tomioka.gunma.jp": 1, + "tomisato.chiba.jp": 1, + "tomiya.miyagi.jp": 1, + "tomobe.ibaraki.jp": 1, + "tonaki.okinawa.jp": 1, + "tonami.toyama.jp": 1, + "tondabayashi.osaka.jp": 1, + "tone.ibaraki.jp": 1, + "tono.iwate.jp": 1, + "tonosho.kagawa.jp": 1, + "tonsberg.no": 1, + "toolforge.org": 1, + "toon.ehime.jp": 1, + "topology.museum": 1, + "torahime.shiga.jp": 1, + "toride.ibaraki.jp": 1, + "torino.it": 1, + "torino.museum": 1, + "torsken.no": 1, + "tos.it": 1, + "tosa.kochi.jp": 1, + "tosashimizu.kochi.jp": 1, + "toscana.it": 1, + "toshima.tokyo.jp": 1, + "tosu.saga.jp": 1, + "tottori.jp": 1, + "tottori.tottori.jp": 1, + "touch.museum": 1, + "tourism.pl": 1, + "tourism.tn": 1, + "towada.aomori.jp": 1, + "town.museum": 1, + "townnews-staging.com": 1, + "toya.hokkaido.jp": 1, + "toyako.hokkaido.jp": 1, + "toyama.jp": 1, + "toyama.toyama.jp": 1, + "toyo.kochi.jp": 1, + "toyoake.aichi.jp": 1, + "toyohashi.aichi.jp": 1, + "toyokawa.aichi.jp": 1, + "toyonaka.osaka.jp": 1, + "toyone.aichi.jp": 1, + "toyono.osaka.jp": 1, + "toyooka.hyogo.jp": 1, + "toyosato.shiga.jp": 1, + "toyota.aichi.jp": 1, + "toyota.yamaguchi.jp": 1, + "toyotomi.hokkaido.jp": 1, + "toyotsu.fukuoka.jp": 1, + "toyoura.hokkaido.jp": 1, + "tozawa.yamagata.jp": 1, + "tozsde.hu": 1, + "tp.it": 1, + "tr.eu.org": 1, + "tr.it": 1, + "tr.no": 1, + "tra.kp": 1, + "trader.aero": 1, + "trading.aero": 1, + "traeumtgerade.de": 1, + "trafficplex.cloud": 1, + "trainer.aero": 1, + "trana.no": 1, + "tranby.no": 1, + "trani-andria-barletta.it": 1, + "trani-barletta-andria.it": 1, + "traniandriabarletta.it": 1, + "tranibarlettaandria.it": 1, + "tranoy.no": 1, + "translate.goog": 1, + "transport.museum": 1, + "transporte.bo": 1, + "transurl.be": 2, + "transurl.eu": 2, + "transurl.nl": 2, + "tran\u00f8y.no": 1, + "trapani.it": 1, + "travel.pl": 1, + "travel.tt": 1, + "trd.br": 1, + "tree.museum": 1, + "trentin-sud-tirol.it": 1, + "trentin-sudtirol.it": 1, + "trentin-sued-tirol.it": 1, + "trentin-suedtirol.it": 1, + "trentin-s\u00fcd-tirol.it": 1, + "trentin-s\u00fcdtirol.it": 1, + "trentino-a-adige.it": 1, + "trentino-aadige.it": 1, + "trentino-alto-adige.it": 1, + "trentino-altoadige.it": 1, + "trentino-s-tirol.it": 1, + "trentino-stirol.it": 1, + "trentino-sud-tirol.it": 1, + "trentino-sudtirol.it": 1, + "trentino-sued-tirol.it": 1, + "trentino-suedtirol.it": 1, + "trentino-s\u00fcd-tirol.it": 1, + "trentino-s\u00fcdtirol.it": 1, + "trentino.it": 1, + "trentinoa-adige.it": 1, + "trentinoaadige.it": 1, + "trentinoalto-adige.it": 1, + "trentinoaltoadige.it": 1, + "trentinos-tirol.it": 1, + "trentinostirol.it": 1, + "trentinosud-tirol.it": 1, + "trentinosudtirol.it": 1, + "trentinosued-tirol.it": 1, + "trentinosuedtirol.it": 1, + "trentinos\u00fcd-tirol.it": 1, + "trentinos\u00fcdtirol.it": 1, + "trentinsud-tirol.it": 1, + "trentinsudtirol.it": 1, + "trentinsued-tirol.it": 1, + "trentinsuedtirol.it": 1, + "trentins\u00fcd-tirol.it": 1, + "trentins\u00fcdtirol.it": 1, + "trento.it": 1, + "treviso.it": 1, + "trieste.it": 1, + "triton.zone": 2, + "troandin.no": 1, + "trogstad.no": 1, + "troitsk.su": 1, + "trolley.museum": 1, + "tromsa.no": 1, + "tromso.no": 1, + "troms\u00f8.no": 1, + "trondheim.no": 1, + "trust.museum": 1, + "trustee.museum": 1, + "trycloudflare.com": 1, + "trysil.no": 1, + "tr\u00e6na.no": 1, + "tr\u00f8gstad.no": 1, + "ts.it": 1, + "tselinograd.su": 1, + "tsk.tr": 1, + "tsu.mie.jp": 1, + "tsubame.niigata.jp": 1, + "tsubata.ishikawa.jp": 1, + "tsubetsu.hokkaido.jp": 1, + "tsuchiura.ibaraki.jp": 1, + "tsuga.tochigi.jp": 1, + "tsugaru.aomori.jp": 1, + "tsuiki.fukuoka.jp": 1, + "tsukigata.hokkaido.jp": 1, + "tsukiyono.gunma.jp": 1, + "tsukuba.ibaraki.jp": 1, + "tsukui.kanagawa.jp": 1, + "tsukumi.oita.jp": 1, + "tsumagoi.gunma.jp": 1, + "tsunan.niigata.jp": 1, + "tsuno.kochi.jp": 1, + "tsuno.miyazaki.jp": 1, + "tsuru.yamanashi.jp": 1, + "tsuruga.fukui.jp": 1, + "tsurugashima.saitama.jp": 1, + "tsurugi.ishikawa.jp": 1, + "tsuruoka.yamagata.jp": 1, + "tsuruta.aomori.jp": 1, + "tsushima.aichi.jp": 1, + "tsushima.nagasaki.jp": 1, + "tsuwano.shimane.jp": 1, + "tsuyama.okayama.jp": 1, + "tt.im": 1, + "tula.su": 1, + "tunk.org": 1, + "tur.ar": 1, + "tur.br": 1, + "turek.pl": 1, + "turen.tn": 1, + "turin.it": 1, + "turystyka.pl": 1, + "tuscany.it": 1, + "tuva.su": 1, + "tuxfamily.org": 1, + "tv.bb": 1, + "tv.bo": 1, + "tv.br": 1, + "tv.im": 1, + "tv.it": 1, + "tv.kg": 1, + "tv.na": 1, + "tv.sd": 1, + "tv.tr": 1, + "tv.tz": 1, + "tvedestrand.no": 1, + "tw.cn": 1, + "twmail.cc": 1, + "twmail.net": 1, + "twmail.org": 1, + "tx.us": 1, + "tychy.pl": 1, + "tydal.no": 1, + "tynset.no": 1, + "tysfjord.no": 1, + "tysnes.no": 1, + "tysvar.no": 1, + "tysv\u00e6r.no": 1, + "t\u00f8nsberg.no": 1, + "u.bg": 1, + "u.channelsdvr.net": 1, + "u.se": 1, + "u2-local.xnbay.com": 1, + "u2.xnbay.com": 1, + "ua.rs": 1, + "ube.yamaguchi.jp": 1, + "uber.space": 1, + "uberspace.de": 2, + "uchihara.ibaraki.jp": 1, + "uchiko.ehime.jp": 1, + "uchinada.ishikawa.jp": 1, + "uchinomi.kagawa.jp": 1, + "ud.it": 1, + "uda.nara.jp": 1, + "udi.br": 1, + "udine.it": 1, + "udono.mie.jp": 1, + "ueda.nagano.jp": 1, + "ueno.gunma.jp": 1, + "uenohara.yamanashi.jp": 1, + "ufcfan.org": 1, + "ug.gov.pl": 1, + "ugim.gov.pl": 1, + "uhren.museum": 1, + "ui.nabu.casa": 1, + "uji.kyoto.jp": 1, + "ujiie.tochigi.jp": 1, + "ujitawara.kyoto.jp": 1, + "uk.com": 1, + "uk.eu.org": 1, + "uk.kg": 1, + "uk.net": 1, + "uk0.bigv.io": 1, + "ukco.me": 1, + "uki.kumamoto.jp": 1, + "ukiha.fukuoka.jp": 1, + "uklugs.org": 1, + "ullensaker.no": 1, + "ullensvang.no": 1, + "ulm.museum": 1, + "ulsan.kr": 1, + "ulvik.no": 1, + "um.gov.pl": 1, + "umaji.kochi.jp": 1, + "umb.it": 1, + "umbria.it": 1, + "umi.fukuoka.jp": 1, + "umig.gov.pl": 1, + "unazuki.toyama.jp": 1, + "undersea.museum": 1, + "uni5.net": 1, + "union.aero": 1, + "univ.sn": 1, + "university.museum": 1, + "unjarga.no": 1, + "unj\u00e1rga.no": 1, + "unnan.shimane.jp": 1, + "unusualperson.com": 1, + "unzen.nagasaki.jp": 1, + "uonuma.niigata.jp": 1, + "uozu.toyama.jp": 1, + "upow.gov.pl": 1, + "uppo.gov.pl": 1, + "urakawa.hokkaido.jp": 1, + "urasoe.okinawa.jp": 1, + "urausu.hokkaido.jp": 1, + "urawa.saitama.jp": 1, + "urayasu.chiba.jp": 1, + "urbino-pesaro.it": 1, + "urbinopesaro.it": 1, + "ureshino.mie.jp": 1, + "uri.arpa": 1, + "url.tw": 1, + "urn.arpa": 1, + "urown.cloud": 1, + "uruma.okinawa.jp": 1, + "uryu.hokkaido.jp": 1, + "us-1.evennode.com": 1, + "us-2.evennode.com": 1, + "us-3.evennode.com": 1, + "us-4.evennode.com": 1, + "us-east-1.amazonaws.com": 1, + "us-east-1.elasticbeanstalk.com": 1, + "us-east-2.elasticbeanstalk.com": 1, + "us-gov-west-1.elasticbeanstalk.com": 1, + "us-west-1.elasticbeanstalk.com": 1, + "us-west-2.elasticbeanstalk.com": 1, + "us.ax": 1, + "us.com": 1, + "us.eu.org": 1, + "us.gov.pl": 1, + "us.kg": 1, + "us.na": 1, + "us.org": 1, + "us.platform.sh": 1, + "usa.museum": 1, + "usa.oita.jp": 1, + "usantiques.museum": 1, + "usarts.museum": 1, + "uscountryestate.museum": 1, + "usculture.museum": 1, + "usdecorativearts.museum": 1, + "user.aseinet.ne.jp": 1, + "user.party.eus": 1, + "user.srcf.net": 1, + "usercontent.jp": 1, + "usgarden.museum": 1, + "ushiku.ibaraki.jp": 1, + "ushistory.museum": 1, + "ushuaia.museum": 1, + "uslivinghistory.museum": 1, + "usr.cloud.muni.cz": 1, + "ustka.pl": 1, + "usui.fukuoka.jp": 1, + "usuki.oita.jp": 1, + "ut.us": 1, + "utah.museum": 1, + "utashinai.hokkaido.jp": 1, + "utazas.hu": 1, + "utazu.kagawa.jp": 1, + "uto.kumamoto.jp": 1, + "utsira.no": 1, + "utsunomiya.tochigi.jp": 1, + "utwente.io": 1, + "uvic.museum": 1, + "uw.gov.pl": 1, + "uwajima.ehime.jp": 1, + "uwu.ai": 1, + "uwu.nu": 1, + "uy.com": 1, + "uz.ua": 1, + "uzhgorod.ua": 1, + "uzs.gov.pl": 1, + "v-info.info": 1, + "v.bg": 1, + "v.ua": 1, + "va.it": 1, + "va.no": 1, + "va.us": 1, + "vaapste.no": 1, + "vadso.no": 1, + "vads\u00f8.no": 1, + "vaga.no": 1, + "vagan.no": 1, + "vagsoy.no": 1, + "vaksdal.no": 1, + "val-d-aosta.it": 1, + "val-daosta.it": 1, + "vald-aosta.it": 1, + "valdaosta.it": 1, + "valer.hedmark.no": 1, + "valer.ostfold.no": 1, + "valle-aosta.it": 1, + "valle-d-aosta.it": 1, + "valle-daosta.it": 1, + "valle.no": 1, + "valleaosta.it": 1, + "valled-aosta.it": 1, + "valledaosta.it": 1, + "vallee-aoste.it": 1, + "vallee-d-aoste.it": 1, + "valleeaoste.it": 1, + "valleedaoste.it": 1, + "valley.museum": 1, + "vall\u00e9e-aoste.it": 1, + "vall\u00e9e-d-aoste.it": 1, + "vall\u00e9eaoste.it": 1, + "vall\u00e9edaoste.it": 1, + "vang.no": 1, + "vantaa.museum": 1, + "vanylven.no": 1, + "vao.it": 1, + "vapor.cloud": 1, + "vaporcloud.io": 1, + "vardo.no": 1, + "vard\u00f8.no": 1, + "varese.it": 1, + "varggat.no": 1, + "varoy.no": 1, + "vb.it": 1, + "vc.it": 1, + "vda.it": 1, + "ve.it": 1, + "vefsn.no": 1, + "vega.no": 1, + "vegarshei.no": 1, + "veg\u00e5rshei.no": 1, + "ven.it": 1, + "veneto.it": 1, + "venezia.it": 1, + "venice.it": 1, + "vennesla.no": 1, + "verbania.it": 1, + "vercel.app": 1, + "vercel.dev": 1, + "vercelli.it": 1, + "verdal.no": 1, + "verona.it": 1, + "verran.no": 1, + "versailles.museum": 1, + "vestby.no": 1, + "vestnes.no": 1, + "vestre-slidre.no": 1, + "vestre-toten.no": 1, + "vestvagoy.no": 1, + "vestv\u00e5g\u00f8y.no": 1, + "vet.br": 1, + "veterinaire.fr": 1, + "veterinaire.km": 1, + "vevelstad.no": 1, + "vf.no": 1, + "vgs.no": 1, + "vi.it": 1, + "vi.us": 1, + "vibo-valentia.it": 1, + "vibovalentia.it": 1, + "vic.au": 1, + "vic.edu.au": 1, + "vic.gov.au": 1, + "vicenza.it": 1, + "video.hu": 1, + "vik.no": 1, + "viking.museum": 1, + "vikna.no": 1, + "village.museum": 1, + "vindafjord.no": 1, + "vinnica.ua": 1, + "vinnytsia.ua": 1, + "vip.jelastic.cloud": 1, + "vipsinaapp.com": 1, + "virginia.museum": 1, + "virtual-user.de": 1, + "virtual.museum": 1, + "virtualserver.io": 1, + "virtualuser.de": 1, + "virtueeldomein.nl": 1, + "virtuel.museum": 1, + "viterbo.it": 1, + "vix.br": 1, + "vlaanderen.museum": 1, + "vladikavkaz.ru": 1, + "vladikavkaz.su": 1, + "vladimir.ru": 1, + "vladimir.su": 1, + "vlog.br": 1, + "vm.bytemark.co.uk": 1, + "vn.ua": 1, + "voagat.no": 1, + "volda.no": 1, + "volkenkunde.museum": 1, + "vologda.su": 1, + "volyn.ua": 1, + "voorloper.cloud": 1, + "voss.no": 1, + "vossevangen.no": 1, + "vpndns.net": 1, + "vpnplus.to": 1, + "vps.mcdir.ru": 1, + "vps.myjino.ru": 2, + "vr.it": 1, + "vs.it": 1, + "vs.mythic-beasts.com": 1, + "vt.it": 1, + "vt.us": 1, + "vv.it": 1, + "vxl.sh": 1, + "v\u00e1rgg\u00e1t.no": 1, + "v\u00e5gan.no": 1, + "v\u00e5gs\u00f8y.no": 1, + "v\u00e5g\u00e5.no": 1, + "v\u00e5ler.hedmark.no": 1, + "v\u00e5ler.\u00f8stfold.no": 1, + "v\u00e6r\u00f8y.no": 1, + "w.bg": 1, + "w.se": 1, + "wa.au": 1, + "wa.edu.au": 1, + "wa.gov.au": 1, + "wa.us": 1, + "wada.nagano.jp": 1, + "wafflecell.com": 1, + "wajiki.tokushima.jp": 1, + "wajima.ishikawa.jp": 1, + "wakasa.fukui.jp": 1, + "wakasa.tottori.jp": 1, + "wakayama.jp": 1, + "wakayama.wakayama.jp": 1, + "wake.okayama.jp": 1, + "wakkanai.hokkaido.jp": 1, + "wakuya.miyagi.jp": 1, + "walbrzych.pl": 1, + "wales.museum": 1, + "wallonie.museum": 1, + "wanouchi.gifu.jp": 1, + "war.museum": 1, + "warabi.saitama.jp": 1, + "warmia.pl": 1, + "warszawa.pl": 1, + "washingtondc.museum": 1, + "washtenaw.mi.us": 1, + "wassamu.hokkaido.jp": 1, + "watarai.mie.jp": 1, + "watari.miyagi.jp": 1, + "watch-and-clock.museum": 1, + "watchandclock.museum": 1, + "waw.pl": 1, + "wazuka.kyoto.jp": 1, + "we.bs": 1, + "we.tc": 1, + "web.app": 1, + "web.bo": 1, + "web.co": 1, + "web.do": 1, + "web.gu": 1, + "web.id": 1, + "web.in": 1, + "web.lk": 1, + "web.nf": 1, + "web.ni": 1, + "web.pk": 1, + "web.tj": 1, + "web.tr": 1, + "web.ve": 1, + "web.za": 1, + "webhare.dev": 2, + "webhop.biz": 1, + "webhop.info": 1, + "webhop.me": 1, + "webhop.net": 1, + "webhop.org": 1, + "webhosting.be": 1, + "webredirect.org": 1, + "website.yandexcloud.net": 1, + "webspace.rocks": 1, + "wedeploy.io": 1, + "wedeploy.me": 1, + "wedeploy.sh": 1, + "wegrow.pl": 1, + "wellbeingzone.co.uk": 1, + "wellbeingzone.eu": 1, + "western.museum": 1, + "westfalen.museum": 1, + "whaling.museum": 1, + "wi.us": 1, + "wielun.pl": 1, + "wien.funkfeuer.at": 1, + "wif.gov.pl": 1, + "wiih.gov.pl": 1, + "wiki.bo": 1, + "wiki.br": 1, + "wildlife.museum": 1, + "williamsburg.museum": 1, + "winb.gov.pl": 1, + "windmill.museum": 1, + "wios.gov.pl": 1, + "witd.gov.pl": 1, + "withgoogle.com": 1, + "withyoutube.com": 1, + "wiw.gov.pl": 1, + "wlocl.pl": 1, + "wloclawek.pl": 1, + "wmcloud.org": 1, + "wmflabs.org": 1, + "wnext.app": 1, + "wodzislaw.pl": 1, + "wolomin.pl": 1, + "workers.dev": 1, + "workinggroup.aero": 1, + "workisboring.com": 1, + "works.aero": 1, + "workshop.museum": 1, + "worse-than.tv": 1, + "wpdevcloud.com": 1, + "wpenginepowered.com": 1, + "writesthisblog.com": 1, + "wroc.pl": 1, + "wroclaw.pl": 1, + "ws.na": 1, + "wsa.gov.pl": 1, + "wskr.gov.pl": 1, + "wuoz.gov.pl": 1, + "wv.us": 1, + "www.ck": 0, + "www.ro": 1, + "wy.us": 1, + "wzmiuw.gov.pl": 1, + "x.bg": 1, + "x.mythic-beasts.com": 1, + "x.se": 1, + "x443.pw": 1, + "xen.prgmr.com": 1, + "xenapponazure.com": 1, + "xj.cn": 1, + "xnbay.com": 1, + "xs4all.space": 1, + "xx.gl": 1, + "xy.ax": 1, + "xz.cn": 1, + "y.bg": 1, + "y.se": 1, + "yabu.hyogo.jp": 1, + "yabuki.fukushima.jp": 1, + "yachimata.chiba.jp": 1, + "yachiyo.chiba.jp": 1, + "yachiyo.ibaraki.jp": 1, + "yaese.okinawa.jp": 1, + "yahaba.iwate.jp": 1, + "yahiko.niigata.jp": 1, + "yaita.tochigi.jp": 1, + "yaizu.shizuoka.jp": 1, + "yakage.okayama.jp": 1, + "yakumo.hokkaido.jp": 1, + "yakumo.shimane.jp": 1, + "yali.mythic-beasts.com": 1, + "yalta.ua": 1, + "yamada.fukuoka.jp": 1, + "yamada.iwate.jp": 1, + "yamada.toyama.jp": 1, + "yamaga.kumamoto.jp": 1, + "yamagata.gifu.jp": 1, + "yamagata.ibaraki.jp": 1, + "yamagata.jp": 1, + "yamagata.nagano.jp": 1, + "yamagata.yamagata.jp": 1, + "yamaguchi.jp": 1, + "yamakita.kanagawa.jp": 1, + "yamamoto.miyagi.jp": 1, + "yamanakako.yamanashi.jp": 1, + "yamanashi.jp": 1, + "yamanashi.yamanashi.jp": 1, + "yamanobe.yamagata.jp": 1, + "yamanouchi.nagano.jp": 1, + "yamashina.kyoto.jp": 1, + "yamato.fukushima.jp": 1, + "yamato.kanagawa.jp": 1, + "yamato.kumamoto.jp": 1, + "yamatokoriyama.nara.jp": 1, + "yamatotakada.nara.jp": 1, + "yamatsuri.fukushima.jp": 1, + "yamazoe.nara.jp": 1, + "yame.fukuoka.jp": 1, + "yanagawa.fukuoka.jp": 1, + "yanaizu.fukushima.jp": 1, + "yandexcloud.net": 1, + "yao.osaka.jp": 1, + "yaotsu.gifu.jp": 1, + "yasaka.nagano.jp": 1, + "yashio.saitama.jp": 1, + "yashiro.hyogo.jp": 1, + "yasu.shiga.jp": 1, + "yasuda.kochi.jp": 1, + "yasugi.shimane.jp": 1, + "yasuoka.nagano.jp": 1, + "yatomi.aichi.jp": 1, + "yatsuka.shimane.jp": 1, + "yatsushiro.kumamoto.jp": 1, + "yawara.ibaraki.jp": 1, + "yawata.kyoto.jp": 1, + "yawatahama.ehime.jp": 1, + "yazu.tottori.jp": 1, + "ybo.faith": 1, + "ybo.party": 1, + "ybo.review": 1, + "ybo.science": 1, + "ybo.trade": 1, + "ye": 2, + "yk.ca": 1, + "yn.cn": 1, + "yoichi.hokkaido.jp": 1, + "yoita.niigata.jp": 1, + "yoka.hyogo.jp": 1, + "yokaichiba.chiba.jp": 1, + "yokawa.hyogo.jp": 1, + "yokkaichi.mie.jp": 1, + "yokohama.jp": 2, + "yokoshibahikari.chiba.jp": 1, + "yokosuka.kanagawa.jp": 1, + "yokote.akita.jp": 1, + "yokoze.saitama.jp": 1, + "yolasite.com": 1, + "yombo.me": 1, + "yomitan.okinawa.jp": 1, + "yonabaru.okinawa.jp": 1, + "yonago.tottori.jp": 1, + "yonaguni.okinawa.jp": 1, + "yonezawa.yamagata.jp": 1, + "yono.saitama.jp": 1, + "yorii.saitama.jp": 1, + "york.museum": 1, + "yorkshire.museum": 1, + "yoro.gifu.jp": 1, + "yosemite.museum": 1, + "yoshida.saitama.jp": 1, + "yoshida.shizuoka.jp": 1, + "yoshikawa.saitama.jp": 1, + "yoshimi.saitama.jp": 1, + "yoshino.nara.jp": 1, + "yoshinogari.saga.jp": 1, + "yoshioka.gunma.jp": 1, + "yotsukaido.chiba.jp": 1, + "youth.museum": 1, + "yuasa.wakayama.jp": 1, + "yufu.oita.jp": 1, + "yugawa.fukushima.jp": 1, + "yugawara.kanagawa.jp": 1, + "yuki.ibaraki.jp": 1, + "yukuhashi.fukuoka.jp": 1, + "yura.wakayama.jp": 1, + "yurihonjo.akita.jp": 1, + "yusuhara.kochi.jp": 1, + "yusui.kagoshima.jp": 1, + "yuu.yamaguchi.jp": 1, + "yuza.yamagata.jp": 1, + "yuzawa.niigata.jp": 1, + "z.bg": 1, + "z.se": 1, + "za.bz": 1, + "za.com": 1, + "za.net": 1, + "za.org": 1, + "zachpomor.pl": 1, + "zagan.pl": 1, + "zakopane.pl": 1, + "zama.kanagawa.jp": 1, + "zamami.okinawa.jp": 1, + "zao.miyagi.jp": 1, + "zaporizhzhe.ua": 1, + "zaporizhzhia.ua": 1, + "zapto.org": 1, + "zapto.xyz": 1, + "zarow.pl": 1, + "zentsuji.kagawa.jp": 1, + "zgora.pl": 1, + "zgorzelec.pl": 1, + "zhitomir.ua": 1, + "zhytomyr.ua": 1, + "zj.cn": 1, + "zlg.br": 1, + "zoological.museum": 1, + "zoology.museum": 1, + "zp.gov.pl": 1, + "zp.ua": 1, + "zt.ua": 1, + "zushi.kanagawa.jp": 1, + "\u00e1k\u014boluokta.no": 1, + "\u00e1laheadju.no": 1, + "\u00e1lt\u00e1.no": 1, + "\u00e5fjord.no": 1, + "\u00e5krehamn.no": 1, + "\u00e5l.no": 1, + "\u00e5lesund.no": 1, + "\u00e5lg\u00e5rd.no": 1, + "\u00e5mli.no": 1, + "\u00e5mot.no": 1, + "\u00e5rdal.no": 1, + "\u00e5s.no": 1, + "\u00e5seral.no": 1, + "\u00e5snes.no": 1, + "\u00f8ksnes.no": 1, + "\u00f8rland.no": 1, + "\u00f8rskog.no": 1, + "\u00f8rsta.no": 1, + "\u00f8stre-toten.no": 1, + "\u00f8vre-eiker.no": 1, + "\u00f8yer.no": 1, + "\u00f8ygarden.no": 1, + "\u00f8ystre-slidre.no": 1, + "\u010d\u00e1hcesuolo.no": 1, + "\u0430\u043a.\u0441\u0440\u0431": 1, + "\u0438\u043a\u043e\u043c.museum": 1, + "\u043e\u0431\u0440.\u0441\u0440\u0431": 1, + "\u043e\u0434.\u0441\u0440\u0431": 1, + "\u043e\u0440\u0433.\u0441\u0440\u0431": 1, + "\u043f\u0440.\u0441\u0440\u0431": 1, + "\u0443\u043f\u0440.\u0441\u0440\u0431": 1, + "\u05d9\u05e8\u05d5\u05e9\u05dc\u05d9\u05dd.museum": 1, + "\u0627\u064a\u0631\u0627\u0646.ir": 1, + "\u0627\u06cc\u0631\u0627\u0646.ir": 1, + "\u0e17\u0e2b\u0e32\u0e23.\u0e44\u0e17\u0e22": 1, + "\u0e18\u0e38\u0e23\u0e01\u0e34\u0e08.\u0e44\u0e17\u0e22": 1, + "\u0e23\u0e31\u0e10\u0e1a\u0e32\u0e25.\u0e44\u0e17\u0e22": 1, + "\u0e28\u0e36\u0e01\u0e29\u0e32.\u0e44\u0e17\u0e22": 1, + "\u0e2d\u0e07\u0e04\u0e4c\u0e01\u0e23.\u0e44\u0e17\u0e22": 1, + "\u0e40\u0e19\u0e47\u0e15.\u0e44\u0e17\u0e22": 1, + "\u4e09\u91cd.jp": 1, + "\u4e2a\u4eba.hk": 1, + "\u4eac\u90fd.jp": 1, + "\u4f50\u8cc0.jp": 1, + "\u500b\u4eba.hk": 1, + "\u500b\u4eba.\u9999\u6e2f": 1, + "\u516c\u53f8.cn": 1, + "\u516c\u53f8.hk": 1, + "\u516c\u53f8.\u9999\u6e2f": 1, + "\u5175\u5eab.jp": 1, + "\u5317\u6d77\u9053.jp": 1, + "\u5343\u8449.jp": 1, + "\u548c\u6b4c\u5c71.jp": 1, + "\u5546\u696d.tw": 1, + "\u57fc\u7389.jp": 1, + "\u5927\u5206.jp": 1, + "\u5927\u962a.jp": 1, + "\u5948\u826f.jp": 1, + "\u5bae\u57ce.jp": 1, + "\u5bae\u5d0e.jp": 1, + "\u5bcc\u5c71.jp": 1, + "\u5c71\u53e3.jp": 1, + "\u5c71\u5f62.jp": 1, + "\u5c71\u68a8.jp": 1, + "\u5c90\u961c.jp": 1, + "\u5ca1\u5c71.jp": 1, + "\u5ca9\u624b.jp": 1, + "\u5cf6\u6839.jp": 1, + "\u5e83\u5cf6.jp": 1, + "\u5fb3\u5cf6.jp": 1, + "\u611b\u5a9b.jp": 1, + "\u611b\u77e5.jp": 1, + "\u653f\u5e9c.hk": 1, + "\u653f\u5e9c.\u9999\u6e2f": 1, + "\u654e\u80b2.hk": 1, + "\u6559\u80b2.hk": 1, + "\u6559\u80b2.\u9999\u6e2f": 1, + "\u65b0\u6f5f.jp": 1, + "\u6771\u4eac.jp": 1, + "\u6803\u6728.jp": 1, + "\u6c96\u7e04.jp": 1, + "\u6ecb\u8cc0.jp": 1, + "\u718a\u672c.jp": 1, + "\u77f3\u5ddd.jp": 1, + "\u795e\u5948\u5ddd.jp": 1, + "\u798f\u4e95.jp": 1, + "\u798f\u5ca1.jp": 1, + "\u798f\u5cf6.jp": 1, + "\u79cb\u7530.jp": 1, + "\u7b87\u4eba.hk": 1, + "\u7d44\u7e54.hk": 1, + "\u7d44\u7e54.tw": 1, + "\u7d44\u7e54.\u9999\u6e2f": 1, + "\u7d44\u7ec7.hk": 1, + "\u7db2\u7d61.cn": 1, + "\u7db2\u7d61.hk": 1, + "\u7db2\u7d61.\u9999\u6e2f": 1, + "\u7db2\u7edc.hk": 1, + "\u7db2\u8def.tw": 1, + "\u7ec4\u7e54.hk": 1, + "\u7ec4\u7ec7.hk": 1, + "\u7f51\u7d61.hk": 1, + "\u7f51\u7edc.cn": 1, + "\u7f51\u7edc.hk": 1, + "\u7fa4\u99ac.jp": 1, + "\u8328\u57ce.jp": 1, + "\u9577\u5d0e.jp": 1, + "\u9577\u91ce.jp": 1, + "\u9752\u68ee.jp": 1, + "\u9759\u5ca1.jp": 1, + "\u9999\u5ddd.jp": 1, + "\u9ad8\u77e5.jp": 1, + "\u9ce5\u53d6.jp": 1, + "\u9e7f\u5150\u5cf6.jp": 1 +}; diff --git a/src/lib/vendor/jquery-3.5.1.js b/src/lib/vendor/jquery-3.5.1.js new file mode 100644 index 0000000..5093733 --- /dev/null +++ b/src/lib/vendor/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML <object> elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" + + "<select id='" + expando + "-\r\\' msallowcapture=''>" + + "<option selected=''></option></select>"; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "<a href='' disabled='disabled'></a>" + + "<select disabled='disabled'><option/></select>"; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = "<a href='#'></a>"; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = "<input/>"; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // <object> elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = "<textarea>x</textarea>"; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces <option> tags with their contents when inserted outside of + // the select element. + div.innerHTML = "<option></option>"; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting <tbody> or other required elements. + thead: [ 1, "<table>", "</table>" ], + col: [ 2, "<table><colgroup>", "</colgroup></table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG <use> instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /<script|<style|<link/i, + + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "<script>" ) + .attr( s.scriptAttrs || {} ) + .prop( { charset: s.scriptCharset, src: s.url } ) + .on( "load error", callback = function( evt ) { + script.remove(); + callback = null; + if ( evt ) { + complete( evt.type === "error" ? 404 : 200, evt.type ); + } + } ); + + // Use native DOM manipulation to avoid our domManip AJAX trickery + document.head.appendChild( script[ 0 ] ); + }, + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +var oldCallbacks = [], + rjsonp = /(=)\?(?=&|$)|\?\?/; + +// Default jsonp settings +jQuery.ajaxSetup( { + jsonp: "callback", + jsonpCallback: function() { + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) ); + this[ callback ] = true; + return callback; + } +} ); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var callbackName, overwritten, responseContainer, + jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? + "url" : + typeof s.data === "string" && + ( s.contentType || "" ) + .indexOf( "application/x-www-form-urlencoded" ) === 0 && + rjsonp.test( s.data ) && "data" + ); + + // Handle iff the expected data type is "jsonp" or we have a parameter to set + if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { + + // Get callback name, remembering preexisting value associated with it + callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ? + s.jsonpCallback() : + s.jsonpCallback; + + // Insert callback into url or form data + if ( jsonProp ) { + s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); + } else if ( s.jsonp !== false ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; + } + + // Use data converter to retrieve json after script execution + s.converters[ "script json" ] = function() { + if ( !responseContainer ) { + jQuery.error( callbackName + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // Force json dataType + s.dataTypes[ 0 ] = "json"; + + // Install callback + overwritten = window[ callbackName ]; + window[ callbackName ] = function() { + responseContainer = arguments; + }; + + // Clean-up function (fires after converters) + jqXHR.always( function() { + + // If previous value didn't exist - remove it + if ( overwritten === undefined ) { + jQuery( window ).removeProp( callbackName ); + + // Otherwise restore preexisting value + } else { + window[ callbackName ] = overwritten; + } + + // Save back as free + if ( s[ callbackName ] ) { + + // Make sure that re-using the options doesn't screw things around + s.jsonpCallback = originalSettings.jsonpCallback; + + // Save the callback name for future use + oldCallbacks.push( callbackName ); + } + + // Call if it was a function and we have a response + if ( responseContainer && isFunction( overwritten ) ) { + overwritten( responseContainer[ 0 ] ); + } + + responseContainer = overwritten = undefined; + } ); + + // Delegate to script + return "script"; + } +} ); + + + + +// Support: Safari 8 only +// In Safari 8 documents created via document.implementation.createHTMLDocument +// collapse sibling forms: the second one becomes a child of the first one. +// Because of that, this security measure has to be disabled in Safari 8. +// https://bugs.webkit.org/show_bug.cgi?id=137337 +support.createHTMLDocument = ( function() { + var body = document.implementation.createHTMLDocument( "" ).body; + body.innerHTML = "<form></form><form></form>"; + return body.childNodes.length === 2; +} )(); + + +// Argument "data" should be string of html +// context (optional): If specified, the fragment will be created in this context, +// defaults to document +// keepScripts (optional): If true, will include scripts passed in the html string +jQuery.parseHTML = function( data, context, keepScripts ) { + if ( typeof data !== "string" ) { + return []; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + + var base, parsed, scripts; + + if ( !context ) { + + // Stop scripts or inline event handlers from being executed immediately + // by using document.implementation + if ( support.createHTMLDocument ) { + context = document.implementation.createHTMLDocument( "" ); + + // Set the base href for the created document + // so any parsed elements with URLs + // are based on the document's URL (gh-2965) + base = context.createElement( "base" ); + base.href = document.location.href; + context.head.appendChild( base ); + } else { + context = document; + } + } + + parsed = rsingleTag.exec( data ); + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[ 1 ] ) ]; + } + + parsed = buildFragment( [ data ], context, scripts ); + + if ( scripts && scripts.length ) { + jQuery( scripts ).remove(); + } + + return jQuery.merge( [], parsed.childNodes ); +}; + + +/** + * Load a url into a page + */ +jQuery.fn.load = function( url, params, callback ) { + var selector, type, response, + self = this, + off = url.indexOf( " " ); + + if ( off > -1 ) { + selector = stripAndCollapse( url.slice( off ) ); + url = url.slice( 0, off ); + } + + // If it's a function + if ( isFunction( params ) ) { + + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( params && typeof params === "object" ) { + type = "POST"; + } + + // If we have elements to modify, make the request + if ( self.length > 0 ) { + jQuery.ajax( { + url: url, + + // If "type" variable is undefined, then "GET" method will be used. + // Make value of this field explicit since + // user can override it through ajaxSetup method + type: type || "GET", + dataType: "html", + data: params + } ).done( function( responseText ) { + + // Save response for use in complete callback + response = arguments; + + self.html( selector ? + + // If a selector was specified, locate the right elements in a dummy div + // Exclude scripts to avoid IE 'Permission Denied' errors + jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : + + // Otherwise use the full result + responseText ); + + // If the request succeeds, this function gets "data", "status", "jqXHR" + // but they are ignored because response was set above. + // If it fails, this function gets "jqXHR", "status", "error" + } ).always( callback && function( jqXHR, status ) { + self.each( function() { + callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); + } ); + } ); + } + + return this; +}; + + + + +jQuery.expr.pseudos.animated = function( elem ) { + return jQuery.grep( jQuery.timers, function( fn ) { + return elem === fn.elem; + } ).length; +}; + + + + +jQuery.offset = { + setOffset: function( elem, options, i ) { + var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, + position = jQuery.css( elem, "position" ), + curElem = jQuery( elem ), + props = {}; + + // Set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + curOffset = curElem.offset(); + curCSSTop = jQuery.css( elem, "top" ); + curCSSLeft = jQuery.css( elem, "left" ); + calculatePosition = ( position === "absolute" || position === "fixed" ) && + ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; + + // Need to be able to calculate position if either + // top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( isFunction( options ) ) { + + // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) + options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + + } else { + if ( typeof props.top === "number" ) { + props.top += "px"; + } + if ( typeof props.left === "number" ) { + props.left += "px"; + } + curElem.css( props ); + } + } +}; + +jQuery.fn.extend( { + + // offset() relates an element's border box to the document origin + offset: function( options ) { + + // Preserve chaining for setter + if ( arguments.length ) { + return options === undefined ? + this : + this.each( function( i ) { + jQuery.offset.setOffset( this, options, i ); + } ); + } + + var rect, win, + elem = this[ 0 ]; + + if ( !elem ) { + return; + } + + // Return zeros for disconnected and hidden (display: none) elements (gh-2310) + // Support: IE <=11 only + // Running getBoundingClientRect on a + // disconnected node in IE throws an error + if ( !elem.getClientRects().length ) { + return { top: 0, left: 0 }; + } + + // Get document-relative position by adding viewport scroll to viewport-relative gBCR + rect = elem.getBoundingClientRect(); + win = elem.ownerDocument.defaultView; + return { + top: rect.top + win.pageYOffset, + left: rect.left + win.pageXOffset + }; + }, + + // position() relates an element's margin box to its offset parent's padding box + // This corresponds to the behavior of CSS absolute positioning + position: function() { + if ( !this[ 0 ] ) { + return; + } + + var offsetParent, offset, doc, + elem = this[ 0 ], + parentOffset = { top: 0, left: 0 }; + + // position:fixed elements are offset from the viewport, which itself always has zero offset + if ( jQuery.css( elem, "position" ) === "fixed" ) { + + // Assume position:fixed implies availability of getBoundingClientRect + offset = elem.getBoundingClientRect(); + + } else { + offset = this.offset(); + + // Account for the *real* offset parent, which can be the document or its root element + // when a statically positioned element is identified + doc = elem.ownerDocument; + offsetParent = elem.offsetParent || doc.documentElement; + while ( offsetParent && + ( offsetParent === doc.body || offsetParent === doc.documentElement ) && + jQuery.css( offsetParent, "position" ) === "static" ) { + + offsetParent = offsetParent.parentNode; + } + if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) { + + // Incorporate borders into its offset, since they are outside its content origin + parentOffset = jQuery( offsetParent ).offset(); + parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true ); + parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true ); + } + } + + // Subtract parent offsets and element margins + return { + top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), + left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) + }; + }, + + // This method will return documentElement in the following cases: + // 1) For the element inside the iframe without offsetParent, this method will return + // documentElement of the parent window + // 2) For the hidden or detached element + // 3) For body or html element, i.e. in case of the html node - it will return itself + // + // but those exceptions were never presented as a real life use-cases + // and might be considered as more preferable results. + // + // This logic, however, is not guaranteed and can change at any point in the future + offsetParent: function() { + return this.map( function() { + var offsetParent = this.offsetParent; + + while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) { + offsetParent = offsetParent.offsetParent; + } + + return offsetParent || documentElement; + } ); + } +} ); + +// Create scrollLeft and scrollTop methods +jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { + var top = "pageYOffset" === prop; + + jQuery.fn[ method ] = function( val ) { + return access( this, function( elem, method, val ) { + + // Coalesce documents and windows + var win; + if ( isWindow( elem ) ) { + win = elem; + } else if ( elem.nodeType === 9 ) { + win = elem.defaultView; + } + + if ( val === undefined ) { + return win ? win[ prop ] : elem[ method ]; + } + + if ( win ) { + win.scrollTo( + !top ? val : win.pageXOffset, + top ? val : win.pageYOffset + ); + + } else { + elem[ method ] = val; + } + }, method, val, arguments.length ); + }; +} ); + +// Support: Safari <=7 - 9.1, Chrome <=37 - 49 +// Add the top/left cssHooks using jQuery.fn.position +// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 +// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 +// getComputedStyle returns percent when specified for top/left/bottom/right; +// rather than make the css module depend on the offset module, just check for it here +jQuery.each( [ "top", "left" ], function( _i, prop ) { + jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, + function( elem, computed ) { + if ( computed ) { + computed = curCSS( elem, prop ); + + // If curCSS returns percentage, fallback to offset + return rnumnonpx.test( computed ) ? + jQuery( elem ).position()[ prop ] + "px" : + computed; + } + } + ); +} ); + + +// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods +jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { + jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, + function( defaultExtra, funcName ) { + + // Margin is only for outerHeight, outerWidth + jQuery.fn[ funcName ] = function( margin, value ) { + var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), + extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); + + return access( this, function( elem, type, value ) { + var doc; + + if ( isWindow( elem ) ) { + + // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729) + return funcName.indexOf( "outer" ) === 0 ? + elem[ "inner" + name ] : + elem.document.documentElement[ "client" + name ]; + } + + // Get document width or height + if ( elem.nodeType === 9 ) { + doc = elem.documentElement; + + // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], + // whichever is greatest + return Math.max( + elem.body[ "scroll" + name ], doc[ "scroll" + name ], + elem.body[ "offset" + name ], doc[ "offset" + name ], + doc[ "client" + name ] + ); + } + + return value === undefined ? + + // Get width or height on the element, requesting but not forcing parseFloat + jQuery.css( elem, type, extra ) : + + // Set width or height on the element + jQuery.style( elem, type, value, extra ); + }, type, chainable ? margin : undefined, chainable ); + }; + } ); +} ); + + +jQuery.each( [ + "ajaxStart", + "ajaxStop", + "ajaxComplete", + "ajaxError", + "ajaxSuccess", + "ajaxSend" +], function( _i, type ) { + jQuery.fn[ type ] = function( fn ) { + return this.on( type, fn ); + }; +} ); + + + + +jQuery.fn.extend( { + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? + this.off( selector, "**" ) : + this.off( types, selector || "**", fn ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +} ); + +jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup contextmenu" ).split( " " ), + function( _i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + } ); + + + + +// Support: Android <=4.0 only +// Make sure we trim BOM and NBSP +var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +// Bind a function to a context, optionally partially applying any +// arguments. +// jQuery.proxy is deprecated to promote standards (specifically Function#bind) +// However, it is not slated for removal any time soon +jQuery.proxy = function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; +}; + +jQuery.holdReady = function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } +}; +jQuery.isArray = Array.isArray; +jQuery.parseJSON = JSON.parse; +jQuery.nodeName = nodeName; +jQuery.isFunction = isFunction; +jQuery.isWindow = isWindow; +jQuery.camelCase = camelCase; +jQuery.type = toType; + +jQuery.now = Date.now; + +jQuery.isNumeric = function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); +}; + +jQuery.trim = function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); +}; + + + +// Register as a named AMD module, since jQuery can be concatenated with other +// files that may use define, but not via a proper concatenation script that +// understands anonymous AMD modules. A named AMD is safest and most robust +// way to register. Lowercase jquery is used because AMD module names are +// derived from file names, and jQuery is normally delivered in a lowercase +// file name. Do this after creating the global so that if an AMD module wants +// to call noConflict to hide this version of jQuery, it will work. + +// Note that for maximum portability, libraries that are not jQuery should +// declare themselves as anonymous modules, and avoid setting a global if an +// AMD loader is present. jQuery is a special case. For more information, see +// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon + +if ( typeof define === "function" && define.amd ) { + define( "jquery", [], function() { + return jQuery; + } ); +} + + + + +var + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$; + +jQuery.noConflict = function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; +}; + +// Expose jQuery and $ identifiers, even in AMD +// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) +// and CommonJS for browser emulators (#13566) +if ( typeof noGlobal === "undefined" ) { + window.jQuery = window.$ = jQuery; +} + + + + +return jQuery; +} ); diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_fbf9ee_1x400.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_fbf9ee_1x400.png Binary files differnew file mode 100644 index 0000000..cd43001 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_65_ffffff_1x400.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_65_ffffff_1x400.png Binary files differnew file mode 100644 index 0000000..e376256 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_dadada_1x400.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_dadada_1x400.png Binary files differnew file mode 100644 index 0000000..4caff27 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_dadada_1x400.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_e6e6e6_1x400.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_e6e6e6_1x400.png Binary files differnew file mode 100644 index 0000000..ade4aea --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_95_fef1ec_1x400.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_95_fef1ec_1x400.png Binary files differnew file mode 100644 index 0000000..7202e44 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_highlight-soft_75_cccccc_1x100.png Binary files differnew file mode 100644 index 0000000..e898778 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_222222_256x240.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_222222_256x240.png Binary files differnew file mode 100644 index 0000000..e723e17 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_222222_256x240.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_2e83ff_256x240.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_2e83ff_256x240.png Binary files differnew file mode 100644 index 0000000..1f5f497 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_2e83ff_256x240.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_454545_256x240.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_454545_256x240.png Binary files differnew file mode 100644 index 0000000..618f5b0 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_454545_256x240.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_888888_256x240.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_888888_256x240.png Binary files differnew file mode 100644 index 0000000..ee5e33f --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_888888_256x240.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png Binary files differnew file mode 100644 index 0000000..7e8ebc1 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.js b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.js new file mode 100644 index 0000000..2a4e76d --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.js @@ -0,0 +1,2815 @@ +/*! jQuery UI - v1.12.1 - 2020-06-16 +* http://jqueryui.com +* Includes: widget.js, form-reset-mixin.js, keycode.js, labels.js, unique-id.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/tabs.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { + +$.ui = $.ui || {}; + +var version = $.ui.version = "1.12.1"; + + +/*! + * jQuery UI Widget 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Widget +//>>group: Core +//>>description: Provides a factory for creating stateful widgets with a common API. +//>>docs: http://api.jqueryui.com/jQuery.widget/ +//>>demos: http://jqueryui.com/widget/ + + + +var widgetUuid = 0; +var widgetSlice = Array.prototype.slice; + +$.cleanData = ( function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { + try { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + + // Http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; +} )( $.cleanData ); + +$.widget = function( name, base, prototype ) { + var existingConstructor, constructor, basePrototype; + + // ProxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + var proxiedPrototype = {}; + + var namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; + var fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + if ( $.isArray( prototype ) ) { + prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); + } + + // Create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + + // Allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // Allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + // Extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + + // Copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + + // Track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + } ); + + basePrototype = new base(); + + // We need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = ( function() { + function _super() { + return base.prototype[ prop ].apply( this, arguments ); + } + + function _superApply( args ) { + return base.prototype[ prop ].apply( this, args ); + } + + return function() { + var __super = this._super; + var __superApply = this._superApply; + var returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + } )(); + } ); + constructor.prototype = $.widget.extend( basePrototype, { + + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + } ); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // Redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, + child._proto ); + } ); + + // Remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); + + return constructor; +}; + +$.widget.extend = function( target ) { + var input = widgetSlice.call( arguments, 1 ); + var inputIndex = 0; + var inputLength = input.length; + var key; + var value; + + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string"; + var args = widgetSlice.call( arguments, 1 ); + var returnValue = this; + + if ( isMethodCall ) { + + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var instance = $.data( this, fullName ); + + if ( options === "instance" ) { + returnValue = instance; + return false; + } + + if ( !instance ) { + return $.error( "cannot call methods on " + name + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + + if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + + " widget instance" ); + } + + methodValue = instance[ options ].apply( instance, args ); + + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } + + this.each( function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + } ); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "<div>", + + options: { + classes: {}, + disabled: false, + + // Callbacks + create: null + }, + + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widgetUuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + this.classesElementLookup = {}; + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + } ); + this.document = $( element.style ? + + // Element within the document + element.ownerDocument : + + // Element is window or document + element.document || element ); + this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + + if ( this.options.disabled ) { + this._setOptionDisabled( this.options.disabled ); + } + + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + + _getCreateOptions: function() { + return {}; + }, + + _getCreateEventData: $.noop, + + _create: $.noop, + + _init: $.noop, + + destroy: function() { + var that = this; + + this._destroy(); + $.each( this.classesElementLookup, function( key, value ) { + that._removeClass( value, key ); + } ); + + // We can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .off( this.eventNamespace ) + .removeData( this.widgetFullName ); + this.widget() + .off( this.eventNamespace ) + .removeAttr( "aria-disabled" ); + + // Clean up events and states + this.bindings.off( this.eventNamespace ); + }, + + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + var parts; + var curOption; + var i; + + if ( arguments.length === 0 ) { + + // Don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + + // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + + _setOption: function( key, value ) { + if ( key === "classes" ) { + this._setOptionClasses( value ); + } + + this.options[ key ] = value; + + if ( key === "disabled" ) { + this._setOptionDisabled( value ); + } + + return this; + }, + + _setOptionClasses: function( value ) { + var classKey, elements, currentElements; + + for ( classKey in value ) { + currentElements = this.classesElementLookup[ classKey ]; + if ( value[ classKey ] === this.options.classes[ classKey ] || + !currentElements || + !currentElements.length ) { + continue; + } + + // We are doing this to create a new jQuery object because the _removeClass() call + // on the next line is going to destroy the reference to the current elements being + // tracked. We need to save a copy of this collection so that we can add the new classes + // below. + elements = $( currentElements.get() ); + this._removeClass( currentElements, classKey ); + + // We don't use _addClass() here, because that uses this.options.classes + // for generating the string of classes. We want to use the value passed in from + // _setOption(), this is the new value of the classes option which was passed to + // _setOption(). We pass this value directly to _classes(). + elements.addClass( this._classes( { + element: elements, + keys: classKey, + classes: value, + add: true + } ) ); + } + }, + + _setOptionDisabled: function( value ) { + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this._removeClass( this.hoverable, null, "ui-state-hover" ); + this._removeClass( this.focusable, null, "ui-state-focus" ); + } + }, + + enable: function() { + return this._setOptions( { disabled: false } ); + }, + + disable: function() { + return this._setOptions( { disabled: true } ); + }, + + _classes: function( options ) { + var full = []; + var that = this; + + options = $.extend( { + element: this.element, + classes: this.options.classes || {} + }, options ); + + function processClassString( classes, checkOption ) { + var current, i; + for ( i = 0; i < classes.length; i++ ) { + current = that.classesElementLookup[ classes[ i ] ] || $(); + if ( options.add ) { + current = $( $.unique( current.get().concat( options.element.get() ) ) ); + } else { + current = $( current.not( options.element ).get() ); + } + that.classesElementLookup[ classes[ i ] ] = current; + full.push( classes[ i ] ); + if ( checkOption && options.classes[ classes[ i ] ] ) { + full.push( options.classes[ classes[ i ] ] ); + } + } + } + + this._on( options.element, { + "remove": "_untrackClassesElement" + } ); + + if ( options.keys ) { + processClassString( options.keys.match( /\S+/g ) || [], true ); + } + if ( options.extra ) { + processClassString( options.extra.match( /\S+/g ) || [] ); + } + + return full.join( " " ); + }, + + _untrackClassesElement: function( event ) { + var that = this; + $.each( that.classesElementLookup, function( key, value ) { + if ( $.inArray( event.target, value ) !== -1 ) { + that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); + } + } ); + }, + + _removeClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, false ); + }, + + _addClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, true ); + }, + + _toggleClass: function( element, keys, extra, add ) { + add = ( typeof add === "boolean" ) ? add : extra; + var shift = ( typeof element === "string" || element === null ), + options = { + extra: shift ? keys : extra, + keys: shift ? element : keys, + element: shift ? this.element : element, + add: add + }; + options.element.toggleClass( this._classes( options ), add ); + return this; + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement; + var instance = this; + + // No suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // No element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + + // Allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // Copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ); + var eventName = match[ 1 ] + instance.eventNamespace; + var selector = match[ 2 ]; + + if ( selector ) { + delegateElement.on( eventName, selector, handlerProxy ); + } else { + element.on( eventName, handlerProxy ); + } + } ); + }, + + _off: function( element, eventName ) { + eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.off( eventName ).off( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); + }, + mouseleave: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); + } + } ); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); + }, + focusout: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); + } + } ); + }, + + _trigger: function( type, event, data ) { + var prop, orig; + var callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + + // The original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // Copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + + var hasOptions; + var effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + + if ( options.delay ) { + element.delay( options.delay ); + } + + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue( function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + } ); + } + }; +} ); + +var widget = $.widget; + + + + +// Support: IE8 Only +// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop +// with a string, so we need to find the proper form. +var form = $.fn.form = function() { + return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); +}; + + +/*! + * jQuery UI Form Reset Mixin 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Form Reset Mixin +//>>group: Core +//>>description: Refresh input widgets when their form is reset +//>>docs: http://api.jqueryui.com/form-reset-mixin/ + + + +var formResetMixin = $.ui.formResetMixin = { + _formResetHandler: function() { + var form = $( this ); + + // Wait for the form reset to actually happen before refreshing + setTimeout( function() { + var instances = form.data( "ui-form-reset-instances" ); + $.each( instances, function() { + this.refresh(); + } ); + } ); + }, + + _bindFormResetHandler: function() { + this.form = this.element.form(); + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ) || []; + if ( !instances.length ) { + + // We don't use _on() here because we use a single event handler per form + this.form.on( "reset.ui-form-reset", this._formResetHandler ); + } + instances.push( this ); + this.form.data( "ui-form-reset-instances", instances ); + }, + + _unbindFormResetHandler: function() { + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ); + instances.splice( $.inArray( this, instances ), 1 ); + if ( instances.length ) { + this.form.data( "ui-form-reset-instances", instances ); + } else { + this.form + .removeData( "ui-form-reset-instances" ) + .off( "reset.ui-form-reset" ); + } + } +}; + + +/*! + * jQuery UI Keycode 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Keycode +//>>group: Core +//>>description: Provide keycodes as keynames +//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ + + +var keycode = $.ui.keyCode = { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 +}; + + + + +// Internal use only +var escapeSelector = $.ui.escapeSelector = ( function() { + var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g; + return function( selector ) { + return selector.replace( selectorEscape, "\\$1" ); + }; +} )(); + + +/*! + * jQuery UI Labels 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: labels +//>>group: Core +//>>description: Find all the labels associated with a given input +//>>docs: http://api.jqueryui.com/labels/ + + + +var labels = $.fn.labels = function() { + var ancestor, selector, id, labels, ancestors; + + // Check control.labels first + if ( this[ 0 ].labels && this[ 0 ].labels.length ) { + return this.pushStack( this[ 0 ].labels ); + } + + // Support: IE <= 11, FF <= 37, Android <= 2.3 only + // Above browsers do not support control.labels. Everything below is to support them + // as well as document fragments. control.labels does not work on document fragments + labels = this.eq( 0 ).parents( "label" ); + + // Look for the label based on the id + id = this.attr( "id" ); + if ( id ) { + + // We don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.eq( 0 ).parents().last(); + + // Get a full set of top level ancestors + ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); + + // Create a selector for the label based on the id + selector = "label[for='" + $.ui.escapeSelector( id ) + "']"; + + labels = labels.add( ancestors.find( selector ).addBack( selector ) ); + + } + + // Return whatever we have found for labels + return this.pushStack( labels ); +}; + + +/*! + * jQuery UI Unique ID 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: uniqueId +//>>group: Core +//>>description: Functions to generate and remove uniqueId's +//>>docs: http://api.jqueryui.com/uniqueId/ + + + +var uniqueId = $.fn.extend( { + uniqueId: ( function() { + var uuid = 0; + + return function() { + return this.each( function() { + if ( !this.id ) { + this.id = "ui-id-" + ( ++uuid ); + } + } ); + }; + } )(), + + removeUniqueId: function() { + return this.each( function() { + if ( /^ui-id-\d+$/.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + } ); + } +} ); + + +/*! + * jQuery UI Controlgroup 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Controlgroup +//>>group: Widgets +//>>description: Visually groups form control widgets +//>>docs: http://api.jqueryui.com/controlgroup/ +//>>demos: http://jqueryui.com/controlgroup/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/controlgroup.css +//>>css.theme: ../../themes/base/theme.css + + +var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; + +var widgetsControlgroup = $.widget( "ui.controlgroup", { + version: "1.12.1", + defaultElement: "<div>", + options: { + direction: "horizontal", + disabled: null, + onlyVisible: true, + items: { + "button": "input[type=button], input[type=submit], input[type=reset], button, a", + "controlgroupLabel": ".ui-controlgroup-label", + "checkboxradio": "input[type='checkbox'], input[type='radio']", + "selectmenu": "select", + "spinner": ".ui-spinner-input" + } + }, + + _create: function() { + this._enhance(); + }, + + // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation + _enhance: function() { + this.element.attr( "role", "toolbar" ); + this.refresh(); + }, + + _destroy: function() { + this._callChildMethod( "destroy" ); + this.childWidgets.removeData( "ui-controlgroup-data" ); + this.element.removeAttr( "role" ); + if ( this.options.items.controlgroupLabel ) { + this.element + .find( this.options.items.controlgroupLabel ) + .find( ".ui-controlgroup-label-contents" ) + .contents().unwrap(); + } + }, + + _initWidgets: function() { + var that = this, + childWidgets = []; + + // First we iterate over each of the items options + $.each( this.options.items, function( widget, selector ) { + var labels; + var options = {}; + + // Make sure the widget has a selector set + if ( !selector ) { + return; + } + + if ( widget === "controlgroupLabel" ) { + labels = that.element.find( selector ); + labels.each( function() { + var element = $( this ); + + if ( element.children( ".ui-controlgroup-label-contents" ).length ) { + return; + } + element.contents() + .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); + } ); + that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); + childWidgets = childWidgets.concat( labels.get() ); + return; + } + + // Make sure the widget actually exists + if ( !$.fn[ widget ] ) { + return; + } + + // We assume everything is in the middle to start because we can't determine + // first / last elements until all enhancments are done. + if ( that[ "_" + widget + "Options" ] ) { + options = that[ "_" + widget + "Options" ]( "middle" ); + } else { + options = { classes: {} }; + } + + // Find instances of this widget inside controlgroup and init them + that.element + .find( selector ) + .each( function() { + var element = $( this ); + var instance = element[ widget ]( "instance" ); + + // We need to clone the default options for this type of widget to avoid + // polluting the variable options which has a wider scope than a single widget. + var instanceOptions = $.widget.extend( {}, options ); + + // If the button is the child of a spinner ignore it + // TODO: Find a more generic solution + if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { + return; + } + + // Create the widget if it doesn't exist + if ( !instance ) { + instance = element[ widget ]()[ widget ]( "instance" ); + } + if ( instance ) { + instanceOptions.classes = + that._resolveClassesValues( instanceOptions.classes, instance ); + } + element[ widget ]( instanceOptions ); + + // Store an instance of the controlgroup to be able to reference + // from the outermost element for changing options and refresh + var widgetElement = element[ widget ]( "widget" ); + $.data( widgetElement[ 0 ], "ui-controlgroup-data", + instance ? instance : element[ widget ]( "instance" ) ); + + childWidgets.push( widgetElement[ 0 ] ); + } ); + } ); + + this.childWidgets = $( $.unique( childWidgets ) ); + this._addClass( this.childWidgets, "ui-controlgroup-item" ); + }, + + _callChildMethod: function( method ) { + this.childWidgets.each( function() { + var element = $( this ), + data = element.data( "ui-controlgroup-data" ); + if ( data && data[ method ] ) { + data[ method ](); + } + } ); + }, + + _updateCornerClass: function( element, position ) { + var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; + var add = this._buildSimpleOptions( position, "label" ).classes.label; + + this._removeClass( element, null, remove ); + this._addClass( element, null, add ); + }, + + _buildSimpleOptions: function( position, key ) { + var direction = this.options.direction === "vertical"; + var result = { + classes: {} + }; + result.classes[ key ] = { + "middle": "", + "first": "ui-corner-" + ( direction ? "top" : "left" ), + "last": "ui-corner-" + ( direction ? "bottom" : "right" ), + "only": "ui-corner-all" + }[ position ]; + + return result; + }, + + _spinnerOptions: function( position ) { + var options = this._buildSimpleOptions( position, "ui-spinner" ); + + options.classes[ "ui-spinner-up" ] = ""; + options.classes[ "ui-spinner-down" ] = ""; + + return options; + }, + + _buttonOptions: function( position ) { + return this._buildSimpleOptions( position, "ui-button" ); + }, + + _checkboxradioOptions: function( position ) { + return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); + }, + + _selectmenuOptions: function( position ) { + var direction = this.options.direction === "vertical"; + return { + width: direction ? "auto" : false, + classes: { + middle: { + "ui-selectmenu-button-open": "", + "ui-selectmenu-button-closed": "" + }, + first: { + "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), + "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) + }, + last: { + "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", + "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) + }, + only: { + "ui-selectmenu-button-open": "ui-corner-top", + "ui-selectmenu-button-closed": "ui-corner-all" + } + + }[ position ] + }; + }, + + _resolveClassesValues: function( classes, instance ) { + var result = {}; + $.each( classes, function( key ) { + var current = instance.options.classes[ key ] || ""; + current = $.trim( current.replace( controlgroupCornerRegex, "" ) ); + result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); + } ); + return result; + }, + + _setOption: function( key, value ) { + if ( key === "direction" ) { + this._removeClass( "ui-controlgroup-" + this.options.direction ); + } + + this._super( key, value ); + if ( key === "disabled" ) { + this._callChildMethod( value ? "disable" : "enable" ); + return; + } + + this.refresh(); + }, + + refresh: function() { + var children, + that = this; + + this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); + + if ( this.options.direction === "horizontal" ) { + this._addClass( null, "ui-helper-clearfix" ); + } + this._initWidgets(); + + children = this.childWidgets; + + // We filter here because we need to track all childWidgets not just the visible ones + if ( this.options.onlyVisible ) { + children = children.filter( ":visible" ); + } + + if ( children.length ) { + + // We do this last because we need to make sure all enhancment is done + // before determining first and last + $.each( [ "first", "last" ], function( index, value ) { + var instance = children[ value ]().data( "ui-controlgroup-data" ); + + if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { + var options = that[ "_" + instance.widgetName + "Options" ]( + children.length === 1 ? "only" : value + ); + options.classes = that._resolveClassesValues( options.classes, instance ); + instance.element[ instance.widgetName ]( options ); + } else { + that._updateCornerClass( children[ value ](), value ); + } + } ); + + // Finally call the refresh method on each of the child widgets. + this._callChildMethod( "refresh" ); + } + } +} ); + +/*! + * jQuery UI Checkboxradio 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Checkboxradio +//>>group: Widgets +//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. +//>>docs: http://api.jqueryui.com/checkboxradio/ +//>>demos: http://jqueryui.com/checkboxradio/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/button.css +//>>css.structure: ../../themes/base/checkboxradio.css +//>>css.theme: ../../themes/base/theme.css + + + +$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { + version: "1.12.1", + options: { + disabled: null, + label: null, + icon: true, + classes: { + "ui-checkboxradio-label": "ui-corner-all", + "ui-checkboxradio-icon": "ui-corner-all" + } + }, + + _getCreateOptions: function() { + var disabled, labels; + var that = this; + var options = this._super() || {}; + + // We read the type here, because it makes more sense to throw a element type error first, + // rather then the error for lack of a label. Often if its the wrong type, it + // won't have a label (e.g. calling on a div, btn, etc) + this._readType(); + + labels = this.element.labels(); + + // If there are multiple labels, use the last one + this.label = $( labels[ labels.length - 1 ] ); + if ( !this.label.length ) { + $.error( "No label found for checkboxradio widget" ); + } + + this.originalLabel = ""; + + // We need to get the label text but this may also need to make sure it does not contain the + // input itself. + this.label.contents().not( this.element[ 0 ] ).each( function() { + + // The label contents could be text, html, or a mix. We concat each element to get a + // string representation of the label, without the input as part of it. + that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML; + } ); + + // Set the label option if we found label text + if ( this.originalLabel ) { + options.label = this.originalLabel; + } + + disabled = this.element[ 0 ].disabled; + if ( disabled != null ) { + options.disabled = disabled; + } + return options; + }, + + _create: function() { + var checked = this.element[ 0 ].checked; + + this._bindFormResetHandler(); + + if ( this.options.disabled == null ) { + this.options.disabled = this.element[ 0 ].disabled; + } + + this._setOption( "disabled", this.options.disabled ); + this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); + this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); + + if ( this.type === "radio" ) { + this._addClass( this.label, "ui-checkboxradio-radio-label" ); + } + + if ( this.options.label && this.options.label !== this.originalLabel ) { + this._updateLabel(); + } else if ( this.originalLabel ) { + this.options.label = this.originalLabel; + } + + this._enhance(); + + if ( checked ) { + this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); + if ( this.icon ) { + this._addClass( this.icon, null, "ui-state-hover" ); + } + } + + this._on( { + change: "_toggleClasses", + focus: function() { + this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); + }, + blur: function() { + this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); + } + } ); + }, + + _readType: function() { + var nodeName = this.element[ 0 ].nodeName.toLowerCase(); + this.type = this.element[ 0 ].type; + if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { + $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + + " and element.type=" + this.type ); + } + }, + + // Support jQuery Mobile enhanced option + _enhance: function() { + this._updateIcon( this.element[ 0 ].checked ); + }, + + widget: function() { + return this.label; + }, + + _getRadioGroup: function() { + var group; + var name = this.element[ 0 ].name; + var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']"; + + if ( !name ) { + return $( [] ); + } + + if ( this.form.length ) { + group = $( this.form[ 0 ].elements ).filter( nameSelector ); + } else { + + // Not inside a form, check all inputs that also are not inside a form + group = $( nameSelector ).filter( function() { + return $( this ).form().length === 0; + } ); + } + + return group.not( this.element ); + }, + + _toggleClasses: function() { + var checked = this.element[ 0 ].checked; + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + + if ( this.options.icon && this.type === "checkbox" ) { + this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) + ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); + } + + if ( this.type === "radio" ) { + this._getRadioGroup() + .each( function() { + var instance = $( this ).checkboxradio( "instance" ); + + if ( instance ) { + instance._removeClass( instance.label, + "ui-checkboxradio-checked", "ui-state-active" ); + } + } ); + } + }, + + _destroy: function() { + this._unbindFormResetHandler(); + + if ( this.icon ) { + this.icon.remove(); + this.iconSpace.remove(); + } + }, + + _setOption: function( key, value ) { + + // We don't allow the value to be set to nothing + if ( key === "label" && !value ) { + return; + } + + this._super( key, value ); + + if ( key === "disabled" ) { + this._toggleClass( this.label, null, "ui-state-disabled", value ); + this.element[ 0 ].disabled = value; + + // Don't refresh when setting disabled + return; + } + this.refresh(); + }, + + _updateIcon: function( checked ) { + var toAdd = "ui-icon ui-icon-background "; + + if ( this.options.icon ) { + if ( !this.icon ) { + this.icon = $( "<span>" ); + this.iconSpace = $( "<span> </span>" ); + this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); + } + + if ( this.type === "checkbox" ) { + toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; + this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); + } else { + toAdd += "ui-icon-blank"; + } + this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); + if ( !checked ) { + this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); + } + this.icon.prependTo( this.label ).after( this.iconSpace ); + } else if ( this.icon !== undefined ) { + this.icon.remove(); + this.iconSpace.remove(); + delete this.icon; + } + }, + + _updateLabel: function() { + + // Remove the contents of the label ( minus the icon, icon space, and input ) + var contents = this.label.contents().not( this.element[ 0 ] ); + if ( this.icon ) { + contents = contents.not( this.icon[ 0 ] ); + } + if ( this.iconSpace ) { + contents = contents.not( this.iconSpace[ 0 ] ); + } + contents.remove(); + + this.label.append( this.options.label ); + }, + + refresh: function() { + var checked = this.element[ 0 ].checked, + isDisabled = this.element[ 0 ].disabled; + + this._updateIcon( checked ); + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + if ( this.options.label !== null ) { + this._updateLabel(); + } + + if ( isDisabled !== this.options.disabled ) { + this._setOptions( { "disabled": isDisabled } ); + } + } + +} ] ); + +var widgetsCheckboxradio = $.ui.checkboxradio; + + +/*! + * jQuery UI Button 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Button +//>>group: Widgets +//>>description: Enhances a form with themeable buttons. +//>>docs: http://api.jqueryui.com/button/ +//>>demos: http://jqueryui.com/button/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/button.css +//>>css.theme: ../../themes/base/theme.css + + + +$.widget( "ui.button", { + version: "1.12.1", + defaultElement: "<button>", + options: { + classes: { + "ui-button": "ui-corner-all" + }, + disabled: null, + icon: null, + iconPosition: "beginning", + label: null, + showLabel: true + }, + + _getCreateOptions: function() { + var disabled, + + // This is to support cases like in jQuery Mobile where the base widget does have + // an implementation of _getCreateOptions + options = this._super() || {}; + + this.isInput = this.element.is( "input" ); + + disabled = this.element[ 0 ].disabled; + if ( disabled != null ) { + options.disabled = disabled; + } + + this.originalLabel = this.isInput ? this.element.val() : this.element.html(); + if ( this.originalLabel ) { + options.label = this.originalLabel; + } + + return options; + }, + + _create: function() { + if ( !this.option.showLabel & !this.options.icon ) { + this.options.showLabel = true; + } + + // We have to check the option again here even though we did in _getCreateOptions, + // because null may have been passed on init which would override what was set in + // _getCreateOptions + if ( this.options.disabled == null ) { + this.options.disabled = this.element[ 0 ].disabled || false; + } + + this.hasTitle = !!this.element.attr( "title" ); + + // Check to see if the label needs to be set or if its already correct + if ( this.options.label && this.options.label !== this.originalLabel ) { + if ( this.isInput ) { + this.element.val( this.options.label ); + } else { + this.element.html( this.options.label ); + } + } + this._addClass( "ui-button", "ui-widget" ); + this._setOption( "disabled", this.options.disabled ); + this._enhance(); + + if ( this.element.is( "a" ) ) { + this._on( { + "keyup": function( event ) { + if ( event.keyCode === $.ui.keyCode.SPACE ) { + event.preventDefault(); + + // Support: PhantomJS <= 1.9, IE 8 Only + // If a native click is available use it so we actually cause navigation + // otherwise just trigger a click event + if ( this.element[ 0 ].click ) { + this.element[ 0 ].click(); + } else { + this.element.trigger( "click" ); + } + } + } + } ); + } + }, + + _enhance: function() { + if ( !this.element.is( "button" ) ) { + this.element.attr( "role", "button" ); + } + + if ( this.options.icon ) { + this._updateIcon( "icon", this.options.icon ); + this._updateTooltip(); + } + }, + + _updateTooltip: function() { + this.title = this.element.attr( "title" ); + + if ( !this.options.showLabel && !this.title ) { + this.element.attr( "title", this.options.label ); + } + }, + + _updateIcon: function( option, value ) { + var icon = option !== "iconPosition", + position = icon ? this.options.iconPosition : value, + displayBlock = position === "top" || position === "bottom"; + + // Create icon + if ( !this.icon ) { + this.icon = $( "<span>" ); + + this._addClass( this.icon, "ui-button-icon", "ui-icon" ); + + if ( !this.options.showLabel ) { + this._addClass( "ui-button-icon-only" ); + } + } else if ( icon ) { + + // If we are updating the icon remove the old icon class + this._removeClass( this.icon, null, this.options.icon ); + } + + // If we are updating the icon add the new icon class + if ( icon ) { + this._addClass( this.icon, null, value ); + } + + this._attachIcon( position ); + + // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove + // the iconSpace if there is one. + if ( displayBlock ) { + this._addClass( this.icon, null, "ui-widget-icon-block" ); + if ( this.iconSpace ) { + this.iconSpace.remove(); + } + } else { + + // Position is beginning or end so remove the ui-widget-icon-block class and add the + // space if it does not exist + if ( !this.iconSpace ) { + this.iconSpace = $( "<span> </span>" ); + this._addClass( this.iconSpace, "ui-button-icon-space" ); + } + this._removeClass( this.icon, null, "ui-wiget-icon-block" ); + this._attachIconSpace( position ); + } + }, + + _destroy: function() { + this.element.removeAttr( "role" ); + + if ( this.icon ) { + this.icon.remove(); + } + if ( this.iconSpace ) { + this.iconSpace.remove(); + } + if ( !this.hasTitle ) { + this.element.removeAttr( "title" ); + } + }, + + _attachIconSpace: function( iconPosition ) { + this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); + }, + + _attachIcon: function( iconPosition ) { + this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); + }, + + _setOptions: function( options ) { + var newShowLabel = options.showLabel === undefined ? + this.options.showLabel : + options.showLabel, + newIcon = options.icon === undefined ? this.options.icon : options.icon; + + if ( !newShowLabel && !newIcon ) { + options.showLabel = true; + } + this._super( options ); + }, + + _setOption: function( key, value ) { + if ( key === "icon" ) { + if ( value ) { + this._updateIcon( key, value ); + } else if ( this.icon ) { + this.icon.remove(); + if ( this.iconSpace ) { + this.iconSpace.remove(); + } + } + } + + if ( key === "iconPosition" ) { + this._updateIcon( key, value ); + } + + // Make sure we can't end up with a button that has neither text nor icon + if ( key === "showLabel" ) { + this._toggleClass( "ui-button-icon-only", null, !value ); + this._updateTooltip(); + } + + if ( key === "label" ) { + if ( this.isInput ) { + this.element.val( value ); + } else { + + // If there is an icon, append it, else nothing then append the value + // this avoids removal of the icon when setting label text + this.element.html( value ); + if ( this.icon ) { + this._attachIcon( this.options.iconPosition ); + this._attachIconSpace( this.options.iconPosition ); + } + } + } + + this._super( key, value ); + + if ( key === "disabled" ) { + this._toggleClass( null, "ui-state-disabled", value ); + this.element[ 0 ].disabled = value; + if ( value ) { + this.element.blur(); + } + } + }, + + refresh: function() { + + // Make sure to only check disabled if its an element that supports this otherwise + // check for the disabled class to determine state + var isDisabled = this.element.is( "input, button" ) ? + this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); + + if ( isDisabled !== this.options.disabled ) { + this._setOptions( { disabled: isDisabled } ); + } + + this._updateTooltip(); + } +} ); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // Text and Icons options + $.widget( "ui.button", $.ui.button, { + options: { + text: true, + icons: { + primary: null, + secondary: null + } + }, + + _create: function() { + if ( this.options.showLabel && !this.options.text ) { + this.options.showLabel = this.options.text; + } + if ( !this.options.showLabel && this.options.text ) { + this.options.text = this.options.showLabel; + } + if ( !this.options.icon && ( this.options.icons.primary || + this.options.icons.secondary ) ) { + if ( this.options.icons.primary ) { + this.options.icon = this.options.icons.primary; + } else { + this.options.icon = this.options.icons.secondary; + this.options.iconPosition = "end"; + } + } else if ( this.options.icon ) { + this.options.icons.primary = this.options.icon; + } + this._super(); + }, + + _setOption: function( key, value ) { + if ( key === "text" ) { + this._super( "showLabel", value ); + return; + } + if ( key === "showLabel" ) { + this.options.text = value; + } + if ( key === "icon" ) { + this.options.icons.primary = value; + } + if ( key === "icons" ) { + if ( value.primary ) { + this._super( "icon", value.primary ); + this._super( "iconPosition", "beginning" ); + } else if ( value.secondary ) { + this._super( "icon", value.secondary ); + this._super( "iconPosition", "end" ); + } + } + this._superApply( arguments ); + } + } ); + + $.fn.button = ( function( orig ) { + return function() { + if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) || + ( this.length && this[ 0 ].tagName === "INPUT" && ( + this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio" + ) ) ) { + return orig.apply( this, arguments ); + } + if ( !$.ui.checkboxradio ) { + $.error( "Checkboxradio widget missing" ); + } + if ( arguments.length === 0 ) { + return this.checkboxradio( { + "icon": false + } ); + } + return this.checkboxradio.apply( this, arguments ); + }; + } )( $.fn.button ); + + $.fn.buttonset = function() { + if ( !$.ui.controlgroup ) { + $.error( "Controlgroup widget missing" ); + } + if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { + return this.controlgroup.apply( this, + [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); + } + if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { + return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); + } + if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { + arguments[ 0 ].items = { + button: arguments[ 0 ].items + }; + } + return this.controlgroup.apply( this, arguments ); + }; +} + +var widgetsButton = $.ui.button; + + + +var safeActiveElement = $.ui.safeActiveElement = function( document ) { + var activeElement; + + // Support: IE 9 only + // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> + try { + activeElement = document.activeElement; + } catch ( error ) { + activeElement = document.body; + } + + // Support: IE 9 - 11 only + // IE may return null instead of an element + // Interestingly, this only seems to occur when NOT in an iframe + if ( !activeElement ) { + activeElement = document.body; + } + + // Support: IE 11 only + // IE11 returns a seemingly empty object in some cases when accessing + // document.activeElement from an <iframe> + if ( !activeElement.nodeName ) { + activeElement = document.body; + } + + return activeElement; +}; + + +/*! + * jQuery UI Tabs 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Tabs +//>>group: Widgets +//>>description: Transforms a set of container elements into a tab structure. +//>>docs: http://api.jqueryui.com/tabs/ +//>>demos: http://jqueryui.com/tabs/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/tabs.css +//>>css.theme: ../../themes/base/theme.css + + + +$.widget( "ui.tabs", { + version: "1.12.1", + delay: 300, + options: { + active: null, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-nav": "ui-corner-all", + "ui-tabs-panel": "ui-corner-bottom", + "ui-tabs-tab": "ui-corner-top" + }, + collapsible: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // Callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + load: null + }, + + _isLocal: ( function() { + var rhash = /#.*$/; + + return function( anchor ) { + var anchorUrl, locationUrl; + + anchorUrl = anchor.href.replace( rhash, "" ); + locationUrl = location.href.replace( rhash, "" ); + + // Decoding may throw an error if the URL isn't UTF-8 (#9518) + try { + anchorUrl = decodeURIComponent( anchorUrl ); + } catch ( error ) {} + try { + locationUrl = decodeURIComponent( locationUrl ); + } catch ( error ) {} + + return anchor.hash.length > 1 && anchorUrl === locationUrl; + }; + } )(), + + _create: function() { + var that = this, + options = this.options; + + this.running = false; + + this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); + this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); + + this._processTabs(); + options.active = this._initialActive(); + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( $.isArray( options.disabled ) ) { + options.disabled = $.unique( options.disabled.concat( + $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { + return that.tabs.index( li ); + } ) + ) ).sort(); + } + + // Check for length avoids error when initializing empty list + if ( this.options.active !== false && this.anchors.length ) { + this.active = this._findActive( options.active ); + } else { + this.active = $(); + } + + this._refresh(); + + if ( this.active.length ) { + this.load( options.active ); + } + }, + + _initialActive: function() { + var active = this.options.active, + collapsible = this.options.collapsible, + locationHash = location.hash.substring( 1 ); + + if ( active === null ) { + + // check the fragment identifier in the URL + if ( locationHash ) { + this.tabs.each( function( i, tab ) { + if ( $( tab ).attr( "aria-controls" ) === locationHash ) { + active = i; + return false; + } + } ); + } + + // Check for a tab marked active via a class + if ( active === null ) { + active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); + } + + // No active tab, set to false + if ( active === null || active === -1 ) { + active = this.tabs.length ? 0 : false; + } + } + + // Handle numbers: negative, out of range + if ( active !== false ) { + active = this.tabs.index( this.tabs.eq( active ) ); + if ( active === -1 ) { + active = collapsible ? false : 0; + } + } + + // Don't allow collapsible: false and active: false + if ( !collapsible && active === false && this.anchors.length ) { + active = 0; + } + + return active; + }, + + _getCreateEventData: function() { + return { + tab: this.active, + panel: !this.active.length ? $() : this._getPanelForTab( this.active ) + }; + }, + + _tabKeydown: function( event ) { + var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ), + selectedIndex = this.tabs.index( focusedTab ), + goingForward = true; + + if ( this._handlePageNav( event ) ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + selectedIndex++; + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.LEFT: + goingForward = false; + selectedIndex--; + break; + case $.ui.keyCode.END: + selectedIndex = this.anchors.length - 1; + break; + case $.ui.keyCode.HOME: + selectedIndex = 0; + break; + case $.ui.keyCode.SPACE: + + // Activate only, no collapsing + event.preventDefault(); + clearTimeout( this.activating ); + this._activate( selectedIndex ); + return; + case $.ui.keyCode.ENTER: + + // Toggle (cancel delayed activation, allow collapsing) + event.preventDefault(); + clearTimeout( this.activating ); + + // Determine if we should collapse or activate + this._activate( selectedIndex === this.options.active ? false : selectedIndex ); + return; + default: + return; + } + + // Focus the appropriate tab, based on which key was pressed + event.preventDefault(); + clearTimeout( this.activating ); + selectedIndex = this._focusNextTab( selectedIndex, goingForward ); + + // Navigating with control/command key will prevent automatic activation + if ( !event.ctrlKey && !event.metaKey ) { + + // Update aria-selected immediately so that AT think the tab is already selected. + // Otherwise AT may confuse the user by stating that they need to activate the tab, + // but the tab will already be activated by the time the announcement finishes. + focusedTab.attr( "aria-selected", "false" ); + this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); + + this.activating = this._delay( function() { + this.option( "active", selectedIndex ); + }, this.delay ); + } + }, + + _panelKeydown: function( event ) { + if ( this._handlePageNav( event ) ) { + return; + } + + // Ctrl+up moves focus to the current tab + if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { + event.preventDefault(); + this.active.trigger( "focus" ); + } + }, + + // Alt+page up/down moves focus to the previous/next tab (and activates) + _handlePageNav: function( event ) { + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { + this._activate( this._focusNextTab( this.options.active - 1, false ) ); + return true; + } + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { + this._activate( this._focusNextTab( this.options.active + 1, true ) ); + return true; + } + }, + + _findNextTab: function( index, goingForward ) { + var lastTabIndex = this.tabs.length - 1; + + function constrain() { + if ( index > lastTabIndex ) { + index = 0; + } + if ( index < 0 ) { + index = lastTabIndex; + } + return index; + } + + while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { + index = goingForward ? index + 1 : index - 1; + } + + return index; + }, + + _focusNextTab: function( index, goingForward ) { + index = this._findNextTab( index, goingForward ); + this.tabs.eq( index ).trigger( "focus" ); + return index; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + this._super( key, value ); + + if ( key === "collapsible" ) { + this._toggleClass( "ui-tabs-collapsible", null, value ); + + // Setting collapsible: false while collapsed; open first panel + if ( !value && this.options.active === false ) { + this._activate( 0 ); + } + } + + if ( key === "event" ) { + this._setupEvents( value ); + } + + if ( key === "heightStyle" ) { + this._setupHeightStyle( value ); + } + }, + + _sanitizeSelector: function( hash ) { + return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; + }, + + refresh: function() { + var options = this.options, + lis = this.tablist.children( ":has(a[href])" ); + + // Get disabled tabs from class attribute from HTML + // this will get converted to a boolean if needed in _refresh() + options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { + return lis.index( tab ); + } ); + + this._processTabs(); + + // Was collapsed or no tabs + if ( options.active === false || !this.anchors.length ) { + options.active = false; + this.active = $(); + + // was active, but active tab is gone + } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { + + // all remaining tabs are disabled + if ( this.tabs.length === options.disabled.length ) { + options.active = false; + this.active = $(); + + // activate previous tab + } else { + this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); + } + + // was active, active tab still exists + } else { + + // make sure active index is correct + options.active = this.tabs.index( this.active ); + } + + this._refresh(); + }, + + _refresh: function() { + this._setOptionDisabled( this.options.disabled ); + this._setupEvents( this.options.event ); + this._setupHeightStyle( this.options.heightStyle ); + + this.tabs.not( this.active ).attr( { + "aria-selected": "false", + "aria-expanded": "false", + tabIndex: -1 + } ); + this.panels.not( this._getPanelForTab( this.active ) ) + .hide() + .attr( { + "aria-hidden": "true" + } ); + + // Make sure one tab is in the tab order + if ( !this.active.length ) { + this.tabs.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active + .attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); + this._getPanelForTab( this.active ) + .show() + .attr( { + "aria-hidden": "false" + } ); + } + }, + + _processTabs: function() { + var that = this, + prevTabs = this.tabs, + prevAnchors = this.anchors, + prevPanels = this.panels; + + this.tablist = this._getList().attr( "role", "tablist" ); + this._addClass( this.tablist, "ui-tabs-nav", + "ui-helper-reset ui-helper-clearfix ui-widget-header" ); + + // Prevent users from focusing disabled tabs via click + this.tablist + .on( "mousedown" + this.eventNamespace, "> li", function( event ) { + if ( $( this ).is( ".ui-state-disabled" ) ) { + event.preventDefault(); + } + } ) + + // Support: IE <9 + // Preventing the default action in mousedown doesn't prevent IE + // from focusing the element, so if the anchor gets focused, blur. + // We don't have to worry about focusing the previously focused + // element since clicking on a non-focusable element should focus + // the body anyway. + .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() { + if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { + this.blur(); + } + } ); + + this.tabs = this.tablist.find( "> li:has(a[href])" ) + .attr( { + role: "tab", + tabIndex: -1 + } ); + this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); + + this.anchors = this.tabs.map( function() { + return $( "a", this )[ 0 ]; + } ) + .attr( { + role: "presentation", + tabIndex: -1 + } ); + this._addClass( this.anchors, "ui-tabs-anchor" ); + + this.panels = $(); + + this.anchors.each( function( i, anchor ) { + var selector, panel, panelId, + anchorId = $( anchor ).uniqueId().attr( "id" ), + tab = $( anchor ).closest( "li" ), + originalAriaControls = tab.attr( "aria-controls" ); + + // Inline tab + if ( that._isLocal( anchor ) ) { + selector = anchor.hash; + panelId = selector.substring( 1 ); + panel = that.element.find( that._sanitizeSelector( selector ) ); + + // remote tab + } else { + + // If the tab doesn't already have aria-controls, + // generate an id by using a throw-away element + panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; + selector = "#" + panelId; + panel = that.element.find( selector ); + if ( !panel.length ) { + panel = that._createPanel( panelId ); + panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); + } + panel.attr( "aria-live", "polite" ); + } + + if ( panel.length ) { + that.panels = that.panels.add( panel ); + } + if ( originalAriaControls ) { + tab.data( "ui-tabs-aria-controls", originalAriaControls ); + } + tab.attr( { + "aria-controls": panelId, + "aria-labelledby": anchorId + } ); + panel.attr( "aria-labelledby", anchorId ); + } ); + + this.panels.attr( "role", "tabpanel" ); + this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); + + // Avoid memory leaks (#10056) + if ( prevTabs ) { + this._off( prevTabs.not( this.tabs ) ); + this._off( prevAnchors.not( this.anchors ) ); + this._off( prevPanels.not( this.panels ) ); + } + }, + + // Allow overriding how to find the list for rare usage scenarios (#7715) + _getList: function() { + return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); + }, + + _createPanel: function( id ) { + return $( "<div>" ) + .attr( "id", id ) + .data( "ui-tabs-destroy", true ); + }, + + _setOptionDisabled: function( disabled ) { + var currentItem, li, i; + + if ( $.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; + } + } + + // Disable tabs + for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { + currentItem = $( li ); + if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { + currentItem.attr( "aria-disabled", "true" ); + this._addClass( currentItem, null, "ui-state-disabled" ); + } else { + currentItem.removeAttr( "aria-disabled" ); + this._removeClass( currentItem, null, "ui-state-disabled" ); + } + } + + this.options.disabled = disabled; + + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, + disabled === true ); + }, + + _setupEvents: function( event ) { + var events = {}; + if ( event ) { + $.each( event.split( " " ), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + } ); + } + + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + + // Always prevent the default action, even when disabled + this._on( true, this.anchors, { + click: function( event ) { + event.preventDefault(); + } + } ); + this._on( this.anchors, events ); + this._on( this.tabs, { keydown: "_tabKeydown" } ); + this._on( this.panels, { keydown: "_panelKeydown" } ); + + this._focusable( this.tabs ); + this._hoverable( this.tabs ); + }, + + _setupHeightStyle: function( heightStyle ) { + var maxHeight, + parent = this.element.parent(); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + maxHeight -= this.element.outerHeight() - this.element.height(); + + this.element.siblings( ":visible" ).each( function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + } ); + + this.element.children().not( this.panels ).each( function() { + maxHeight -= $( this ).outerHeight( true ); + } ); + + this.panels.each( function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + } ) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.panels.each( function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + } ).height( maxHeight ); + } + }, + + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + anchor = $( event.currentTarget ), + tab = anchor.closest( "li" ), + clickedIsActive = tab[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : this._getPanelForTab( tab ), + toHide = !active.length ? $() : this._getPanelForTab( active ), + eventData = { + oldTab: active, + oldPanel: toHide, + newTab: collapsing ? $() : tab, + newPanel: toShow + }; + + event.preventDefault(); + + if ( tab.hasClass( "ui-state-disabled" ) || + + // tab is already loading + tab.hasClass( "ui-tabs-loading" ) || + + // can't switch durning an animation + this.running || + + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.tabs.index( tab ); + + this.active = clickedIsActive ? $() : tab; + if ( this.xhr ) { + this.xhr.abort(); + } + + if ( !toHide.length && !toShow.length ) { + $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); + } + + if ( toShow.length ) { + this.load( this.tabs.index( tab ), event ); + } + this._toggle( event, eventData ); + }, + + // Handles show/hide for selecting tabs + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel; + + this.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); + + if ( toShow.length && that.options.show ) { + that._show( toShow, that.options.show, complete ); + } else { + toShow.show(); + complete(); + } + } + + // Start out by hiding, then showing, then completing + if ( toHide.length && this.options.hide ) { + this._hide( toHide, this.options.hide, function() { + that._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); + show(); + } ); + } else { + this._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); + toHide.hide(); + show(); + } + + toHide.attr( "aria-hidden", "true" ); + eventData.oldTab.attr( { + "aria-selected": "false", + "aria-expanded": "false" + } ); + + // If we're switching tabs, remove the old tab from the tab order. + // If we're opening from collapsed state, remove the previous tab from the tab order. + // If we're collapsing, then keep the collapsing tab in the tab order. + if ( toShow.length && toHide.length ) { + eventData.oldTab.attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.tabs.filter( function() { + return $( this ).attr( "tabIndex" ) === 0; + } ) + .attr( "tabIndex", -1 ); + } + + toShow.attr( "aria-hidden", "false" ); + eventData.newTab.attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + }, + + _activate: function( index ) { + var anchor, + active = this._findActive( index ); + + // Trying to activate the already active panel + if ( active[ 0 ] === this.active[ 0 ] ) { + return; + } + + // Trying to collapse, simulate a click on the current active header + if ( !active.length ) { + active = this.active; + } + + anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; + this._eventHandler( { + target: anchor, + currentTarget: anchor, + preventDefault: $.noop + } ); + }, + + _findActive: function( index ) { + return index === false ? $() : this.tabs.eq( index ); + }, + + _getIndex: function( index ) { + + // meta-function to give users option to provide a href string instead of a numerical index. + if ( typeof index === "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$='" + + $.ui.escapeSelector( index ) + "']" ) ); + } + + return index; + }, + + _destroy: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + + this.tablist + .removeAttr( "role" ) + .off( this.eventNamespace ); + + this.anchors + .removeAttr( "role tabIndex" ) + .removeUniqueId(); + + this.tabs.add( this.panels ).each( function() { + if ( $.data( this, "ui-tabs-destroy" ) ) { + $( this ).remove(); + } else { + $( this ).removeAttr( "role tabIndex " + + "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); + } + } ); + + this.tabs.each( function() { + var li = $( this ), + prev = li.data( "ui-tabs-aria-controls" ); + if ( prev ) { + li + .attr( "aria-controls", prev ) + .removeData( "ui-tabs-aria-controls" ); + } else { + li.removeAttr( "aria-controls" ); + } + } ); + + this.panels.show(); + + if ( this.options.heightStyle !== "content" ) { + this.panels.css( "height", "" ); + } + }, + + enable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === false ) { + return; + } + + if ( index === undefined ) { + disabled = false; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.map( disabled, function( num ) { + return num !== index ? num : null; + } ); + } else { + disabled = $.map( this.tabs, function( li, num ) { + return num !== index ? num : null; + } ); + } + } + this._setOptionDisabled( disabled ); + }, + + disable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === true ) { + return; + } + + if ( index === undefined ) { + disabled = true; + } else { + index = this._getIndex( index ); + if ( $.inArray( index, disabled ) !== -1 ) { + return; + } + if ( $.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; + } + } + this._setOptionDisabled( disabled ); + }, + + load: function( index, event ) { + index = this._getIndex( index ); + var that = this, + tab = this.tabs.eq( index ), + anchor = tab.find( ".ui-tabs-anchor" ), + panel = this._getPanelForTab( tab ), + eventData = { + tab: tab, + panel: panel + }, + complete = function( jqXHR, status ) { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + that._removeClass( tab, "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } + }; + + // Not remote + if ( this._isLocal( anchor[ 0 ] ) ) { + return; + } + + this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); + + // Support: jQuery <1.8 + // jQuery <1.8 returns false if the request is canceled in beforeSend, + // but as of 1.8, $.ajax() always returns a jqXHR object. + if ( this.xhr && this.xhr.statusText !== "canceled" ) { + this._addClass( tab, "ui-tabs-loading" ); + panel.attr( "aria-busy", "true" ); + + this.xhr + .done( function( response, status, jqXHR ) { + + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout( function() { + panel.html( response ); + that._trigger( "load", event, eventData ); + + complete( jqXHR, status ); + }, 1 ); + } ) + .fail( function( jqXHR, status ) { + + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout( function() { + complete( jqXHR, status ); + }, 1 ); + } ); + } + }, + + _ajaxSettings: function( anchor, event, eventData ) { + var that = this; + return { + + // Support: IE <11 only + // Strip any hash that exists to prevent errors with the Ajax request + url: anchor.attr( "href" ).replace( /#.*$/, "" ), + beforeSend: function( jqXHR, settings ) { + return that._trigger( "beforeLoad", event, + $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); + } + }; + }, + + _getPanelForTab: function( tab ) { + var id = $( tab ).attr( "aria-controls" ); + return this.element.find( this._sanitizeSelector( "#" + id ) ); + } +} ); + +// DEPRECATED +// TODO: Switch return back to widget declaration at top of file when this is removed +if ( $.uiBackCompat !== false ) { + + // Backcompat for ui-tab class (now ui-tabs-tab) + $.widget( "ui.tabs", $.ui.tabs, { + _processTabs: function() { + this._superApply( arguments ); + this._addClass( this.tabs, "ui-tab" ); + } + } ); +} + +var widgetsTabs = $.ui.tabs; + + + + +}));
\ No newline at end of file diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.structure.css b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.structure.css new file mode 100644 index 0000000..b4e4056 --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.structure.css @@ -0,0 +1,286 @@ +/*! + * jQuery UI CSS Framework 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + */ +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; + pointer-events: none; +} + + +/* Icons +----------------------------------*/ +.ui-icon { + display: inline-block; + vertical-align: middle; + margin-top: -.25em; + position: relative; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + +.ui-widget-icon-block { + left: 50%; + margin-left: -8px; + display: block; +} + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-button { + padding: .4em 1em; + display: inline-block; + position: relative; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + /* Support: IE <= 11 */ + overflow: visible; +} + +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} + +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2em; + box-sizing: border-box; + text-indent: -9999px; + white-space: nowrap; +} + +/* no icon support for input elements */ +input.ui-button.ui-button-icon-only { + text-indent: 0; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon { + position: absolute; + top: 50%; + left: 50%; + margin-top: -8px; + margin-left: -8px; +} + +.ui-button.ui-icon-notext .ui-icon { + padding: 0; + width: 2.1em; + height: 2.1em; + text-indent: -9999px; + white-space: nowrap; + +} + +input.ui-button.ui-icon-notext .ui-icon { + width: auto; + height: auto; + text-indent: 0; + white-space: normal; + padding: .4em 1em; +} + +/* workarounds */ +/* Support: Firefox 5 - 40 */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-controlgroup { + vertical-align: middle; + display: inline-block; +} +.ui-controlgroup > .ui-controlgroup-item { + float: left; + margin-left: 0; + margin-right: 0; +} +.ui-controlgroup > .ui-controlgroup-item:focus, +.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus { + z-index: 9999; +} +.ui-controlgroup-vertical > .ui-controlgroup-item { + display: block; + float: none; + width: 100%; + margin-top: 0; + margin-bottom: 0; + text-align: left; +} +.ui-controlgroup-vertical .ui-controlgroup-item { + box-sizing: border-box; +} +.ui-controlgroup .ui-controlgroup-label { + padding: .4em 1em; +} +.ui-controlgroup .ui-controlgroup-label span { + font-size: 80%; +} +.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item { + border-left: none; +} +.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item { + border-top: none; +} +.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content { + border-right: none; +} +.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content { + border-bottom: none; +} + +/* Spinner specific style fixes */ +.ui-controlgroup-vertical .ui-spinner-input { + + /* Support: IE8 only, Android < 4.4 only */ + width: 75%; + width: calc( 100% - 2.4em ); +} +.ui-controlgroup-vertical .ui-spinner .ui-spinner-up { + border-top-style: solid; +} + +.ui-checkboxradio-label .ui-icon-background { + box-shadow: inset 1px 1px 1px #ccc; + border-radius: .12em; + border: none; +} +.ui-checkboxradio-radio-label .ui-icon-background { + width: 16px; + height: 16px; + border-radius: 1em; + overflow: visible; + border: none; +} +.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, +.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { + background-image: none; + width: 8px; + height: 8px; + border-width: 4px; + border-style: solid; +} +.ui-checkboxradio-disabled { + pointer-events: none; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} diff --git a/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.theme.css b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.theme.css new file mode 100644 index 0000000..3c5908b --- /dev/null +++ b/src/lib/vendor/jquery-ui-1.12.1.custom/jquery-ui.theme.css @@ -0,0 +1,443 @@ +/*! + * jQuery UI CSS Framework 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=smoothness&cornerRadiusShadow=8px&offsetLeftShadow=-8px&offsetTopShadow=-8px&thicknessShadow=8px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=aaaaaa&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cd0a0a&fcError=cd0a0a&borderColorError=cd0a0a&bgImgOpacityError=95&bgTextureError=glass&bgColorError=fef1ec&iconColorHighlight=2e83ff&fcHighlight=363636&borderColorHighlight=fcefa1&bgImgOpacityHighlight=55&bgTextureHighlight=glass&bgColorHighlight=fbf9ee&iconColorActive=454545&fcActive=212121&borderColorActive=aaaaaa&bgImgOpacityActive=65&bgTextureActive=glass&bgColorActive=ffffff&iconColorHover=454545&fcHover=212121&borderColorHover=999999&bgImgOpacityHover=75&bgTextureHover=glass&bgColorHover=dadada&iconColorDefault=888888&fcDefault=555555&borderColorDefault=d3d3d3&bgImgOpacityDefault=75&bgTextureDefault=glass&bgColorDefault=e6e6e6&iconColorContent=222222&fcContent=222222&borderColorContent=aaaaaa&bgImgOpacityContent=75&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=222222&fcHeader=222222&borderColorHeader=aaaaaa&bgImgOpacityHeader=75&bgTextureHeader=highlight_soft&bgColorHeader=cccccc&cornerRadius=4px&fsDefault=1.1em&fwDefault=normal&ffDefault=Verdana%2CArial%2Csans-serif + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Verdana,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Verdana,Arial,sans-serif; + font-size: 1em; +} +.ui-widget.ui-widget-content { + border: 1px solid #d3d3d3; +} +.ui-widget-content { + border: 1px solid #aaaaaa; + background: #ffffff; + color: #222222; +} +.ui-widget-content a { + color: #222222; +} +.ui-widget-header { + border: 1px solid #aaaaaa; + background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; + color: #222222; + font-weight: bold; +} +.ui-widget-header a { + color: #222222; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default, +.ui-button, + +/* We use html here because we need a greater specificity to make sure disabled +works properly when clicked or hovered */ +html .ui-button.ui-state-disabled:hover, +html .ui-button.ui-state-disabled:active { + border: 1px solid #d3d3d3; + background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #555555; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited, +a.ui-button, +a:link.ui-button, +a:visited.ui-button, +.ui-button { + color: #555555; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus, +.ui-button:hover, +.ui-button:focus { + border: 1px solid #999999; + background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited, +a.ui-button:hover, +a.ui-button:focus { + color: #212121; + text-decoration: none; +} + +.ui-visual-focus { + box-shadow: 0 0 3px 1px rgb(94, 158, 214); +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active, +a.ui-button:active, +.ui-button:active, +.ui-button.ui-state-active:hover { + border: 1px solid #aaaaaa; + background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-icon-background, +.ui-state-active .ui-icon-background { + border: #aaaaaa; + background-color: #212121; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #212121; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fcefa1; + background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; + color: #363636; +} +.ui-state-checked { + border: 1px solid #fcefa1; + background: #fbf9ee; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a; + background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; + color: #cd0a0a; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd0a0a; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd0a0a; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("images/ui-icons_222222_256x240.png"); +} +.ui-widget-header .ui-icon { + background-image: url("images/ui-icons_222222_256x240.png"); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon, +.ui-button:hover .ui-icon, +.ui-button:focus .ui-icon { + background-image: url("images/ui-icons_454545_256x240.png"); +} +.ui-state-active .ui-icon, +.ui-button:active .ui-icon { + background-image: url("images/ui-icons_454545_256x240.png"); +} +.ui-state-highlight .ui-icon, +.ui-button .ui-state-highlight.ui-icon { + background-image: url("images/ui-icons_2e83ff_256x240.png"); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("images/ui-icons_cd0a0a_256x240.png"); +} +.ui-button .ui-icon { + background-image: url("images/ui-icons_888888_256x240.png"); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-caret-1-n { background-position: 0 0; } +.ui-icon-caret-1-ne { background-position: -16px 0; } +.ui-icon-caret-1-e { background-position: -32px 0; } +.ui-icon-caret-1-se { background-position: -48px 0; } +.ui-icon-caret-1-s { background-position: -65px 0; } +.ui-icon-caret-1-sw { background-position: -80px 0; } +.ui-icon-caret-1-w { background-position: -96px 0; } +.ui-icon-caret-1-nw { background-position: -112px 0; } +.ui-icon-caret-2-n-s { background-position: -128px 0; } +.ui-icon-caret-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -65px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -65px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 1px -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 4px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa; + opacity: .3; + filter: Alpha(Opacity=30); /* support: IE8 */ +} +.ui-widget-shadow { + -webkit-box-shadow: -8px -8px 8px #aaaaaa; + box-shadow: -8px -8px 8px #aaaaaa; +} diff --git a/src/lib/vendor/jquery-ui-iconfont-2.3.2/font/jquery-ui.woff2 b/src/lib/vendor/jquery-ui-iconfont-2.3.2/font/jquery-ui.woff2 Binary files differnew file mode 100644 index 0000000..f055e4a --- /dev/null +++ b/src/lib/vendor/jquery-ui-iconfont-2.3.2/font/jquery-ui.woff2 diff --git a/src/lib/vendor/jquery-ui-iconfont-2.3.2/jquery-ui-1.12.icon-font.css b/src/lib/vendor/jquery-ui-iconfont-2.3.2/jquery-ui-1.12.icon-font.css new file mode 100644 index 0000000..63fb850 --- /dev/null +++ b/src/lib/vendor/jquery-ui-iconfont-2.3.2/jquery-ui-1.12.icon-font.css @@ -0,0 +1,839 @@ +/** + * ---------------------------------------------------------------------- + * Icon Font for jQuery UI + * ---------------------------------------------------------------------- + * + * ICON FONT Version: 2.1 + * Glyphs: 332 + * Copyright: (c) 2015-2017 Michael Keck. + * License: CC BY-SA 3.0 + * https://creativecommons.org/licenses/by-sa/3.0/ + * Generated: with IcoMoon-App (Chromium) + * + * STYLESHEET Version: 2.3.2 + * Modified: 2017-03-04 + * jQuery UI: 1.12 & 1.12.1 + * jQMobile: 1.4.5 + * Copyright: (c) 2015-2017 Michael Keck. + * License: GPL license + * http://www.gnu.org/licenses/gpl.html + */ + +/* load icon font */ +@font-face { + font-family: 'jquery-ui'; + src: url('font/jquery-ui.woff2?juif-bac778') format("woff2"); + font-style: normal; + font-variant: normal; + font-weight: normal; +} + + +/* basic settings */ +html .ui-icon { + background-image: none !important; + display: inline-block; + font: normal normal normal 14px/16px sans-serif; + height: 1.2em; + line-height: 1.2em; + margin: 0; + overflow: hidden; + padding: 0; + position: relative; + text-indent: -99999em; + vertical-align: middle; + width: 1.2em; +} + +/* UI-Icons */ +html .ui-icon:after { + display: block; + font-family: 'jquery-ui', sans-serif; + height: 1em; + left: 50%; + line-height: 1; + margin: -.5em; + position: absolute; + text-align: center; + text-indent: 0; + text-transform: none; + top: 50%; + vertical-align: middle; + width: 1em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-transform: translate(0,0); + -moz-transform: translate(0,0); + transform: translate(0,0); +} + + +/** + * -------------------------------------------------------- + * jQuery UI 1.12.x + * -------------------------------------------------------- + */ + +/* positioning on button element(s) */ +html .ui-button, +html .ui-controlgroup .ui-controlgroup-label, +html .ui-spinner .ui-spinner-input { + line-height: inherit; +} +html .ui-controlgroup .ui-controlgroup-label span { + line-height: 1; + margin: 0; + padding: 0; +} +html .ui-button .ui-icon { + margin: -.25em 0 -.15em 0; +} +html .ui-button-icon-only { + min-width: 2.5em; +} +html .ui-button-icon-only .ui-icon { + left: 50%; + margin: -0.6em 0 0 -.6em; + position: absolute; + top: 50%; +} +html .ui-selectmenu-button .ui-icon { + margin: -.6em 0 0 0; + position: absolute; + right: .5em; + top: 50%; +} +html .ui-selectmenu-text { + margin-right: 1em; +} +html .ui-spinner .ui-spinner-input { + margin: 0; + padding: .4em 2.5em .4em 1em; +} +html .ui-widget-icon-block { + display: block; + left: auto; + margin: 0; + width: 100%; + position: relative; +} + +html .ui-datepicker .ui-datepicker-prev .ui-icon, +html .ui-datepicker .ui-datepicker-next .ui-icon { + margin-left: -0.6em; + margin-top: -0.6em; +} + +/* close button positioning on dialogs titlebar */ +html .ui-dialog .ui-dialog-titlebar-close { + height: 1.8em; + margin: -0.9em 0 0 0; + right: 0.3em; + width: 1.8em; +} +/* resizable on dialog */ +html .ui-dialog .ui-resizable-se { + bottom: 1px; + display: block; + height: 1em; + position: absolute; + right: 1px; + width: 1em; +} +.ui-dialog .ui-resizable-se:after { + left: 0; + margin: 0; + top: 0 +} +/* positioning on accordion(s) */ +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + margin-left: -0.2em; + margin-right: 0.4em; +} + +html .ui-icon-background, +html .ui-state-active .ui-icon-background, +html .ui-checkboxradio-label .ui-icon-background, +html .ui-checkboxradio-radio-label .ui-icon-background, +html .ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, +html .ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { + background-color: rgba(0,0,0,.25); + border: 0 none; + color:inherit; + font: normal normal normal 14px/16px sans-serif; + height: 1.2em; + line-height: 1.2em; + width: 1.2em; + -webkit-box-shadow: inset 1px 1px 1px rgba(0,0,0,.25); + -moz-box-shadow: inset 1px 1px 1px rgba(0,0,0,.25); + box-shadow: inset 1px 1px 1px rgba(0,0,0,.25); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + + +/* etxra */ +.has-left-icon li, +li.has-left-icon { + list-style: none; +} +.has-left-icon[class^="ui-icon-"], +.has-left-icon[class*=" ui-icon-"], +.has-left-icon [class^="ui-icon-"], +.has-left-icon [class*=" ui-icon-"] { + padding-left: 1.5em; + position: relative; +} +.has-left-icon[class^="ui-icon-"]:after, +.has-left-icon[class*=" ui-icon-"]:after, +.has-left-icon [class^="ui-icon-"]:after, +.has-left-icon [class*=" ui-icon-"]:after { + left: 0; + margin: 0; + position: absolute; + top: 0; +} +.has-right-icon[class^="ui-icon-"], +.has-right-icon[class*=" ui-icon-"], +.has-right-icon [class^="ui-icon-"], +.has-right-icon [class*=" ui-icon-"] { + padding-right: 1.5em; + position: relative; +} +.has-right-icon[class^="ui-icon-"]:after, +.has-right-icon[class*=" ui-icon-"]:after, +.has-right-icon [class^="ui-icon-"]:after, +.has-right-icon [class*=" ui-icon-"]:after { + right: 0; + margin: 0; + position: absolute; + top: 0; +} + + +/** + * -------------------------------------------------------- + * jQuery Mobile + * (testet with version 1.4.5) + * -------------------------------------------------------- + */ +.ui-mobile .ui-input-search:after, +.ui-mobile .ui-btn-icon-left:after, +.ui-mobile .ui-btn-icon-right:after, +.ui-mobile .ui-btn-icon-top:after, +.ui-mobile .ui-btn-icon-bottom:after, +.ui-mobile .ui-btn-icon-notext:after { + background-image: none !important; + color: #fff; + display: block; + height: 20px; + font: normal normal normal 14px 'jquery-ui', sans-serif; + left: 50%; + line-height: 14px; + margin-left: -10px; + margin-top: -10px; + padding: 3px; + position: absolute; + text-align: center; + text-indent: 0; + text-shadow: none; + text-transform: none; + top: 50%; + vertical-align: middle; + width: 20px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transform: translate(0,0); + -moz-transform: translate(0,0); + transform: translate(0,0); +} +.ui-mobile .ui-input-search:after, +.ui-mobile .ui-alt-icon.ui-btn-icon-left:after, .ui-mobile .ui-alt-icon .ui-btn-icon-left:after, +.ui-mobile .ui-alt-icon.ui-btn-icon-right:after, .ui-mobile .ui-alt-icon .ui-btn-icon-right:after, +.ui-mobile .ui-alt-icon.ui-btn-icon-top:after, .ui-mobile .ui-alt-icon .ui-btn-icon-top:after, +.ui-mobile .ui-alt-icon.ui-btn-icon-bottom:after, .ui-mobile .ui-alt-icon .ui-btn-icon-bottom:after, +.ui-mobile .ui-alt-icon.ui-btn-icon-notext:after, .ui-mobile .ui-alt-icon .ui-btn-icon-notext:after { + color: #000; +} +.ui-mobile .ui-input-search:after, +.ui-mobile .ui-btn-icon-left:after { + left: .37em; + margin-left: 0; +} +.ui-mobile .ui-btn-icon-right:after { + left: auto; + margin-left: 0; + right: .37em; +} +.ui-mobile .ui-mini.ui-btn-icon-left:after, +.ui-mobile .ui-mini .ui-btn-icon-left:after, +.ui-mobile .ui-header .ui-btn-icon-left:after, +.ui-mobile .ui-footer .ui-btn-icon-left:after { + left: .37em; +} +.ui-mobile .ui-mini.ui-btn-icon-right:after, +.ui-mobile .ui-mini .ui-btn-icon-right:after, +.ui-mobile .ui-header .ui-btn-icon-right:after, +.ui-mobile .ui-footer .ui-btn-icon-right:after { + right: .37em; +} +.ui-mobile .ui-btn-icon-top:after { + margin-top: 0; + top: .5625em; +} +.ui-mobile .ui-btn-icon-bottom:after { + bottom: .5625em; + margin-top: 0; + top: auto; +} + +.ui-btn.ui-checkbox-on.ui-checkbox-on:after { + color: #fff; +} +.ui-btn.ui-checkbox-off:after, +.ui-btn.ui-checkbox-on:after, +.ui-btn.ui-radio-off:after, +.ui-btn.ui-radio-on:after { + display: block; + font-size: 14px; + height: 20px; + margin: -10px 2px 0 2px; + padding: 3px; + width: 20px; +} +.ui-mini .ui-btn.ui-checkbox-off:after, +.ui-mini .ui-btn.ui-checkbox-on:after, +.ui-mini .ui-btn.ui-radio-off:after, +.ui-mini .ui-btn.ui-radio-on:after { + height: 18px; + margin: -9px 2px 0 2px; + padding: 2px; + width: 18px; +} +.ui-alt-icon.ui-btn.ui-checkbox-on:after, +.ui-alt-icon .ui-btn.ui-checkbox-on:after { + color: #000; +} +.ui-radio .ui-btn.ui-radio-on:after { + background: #fff none 0 0 no-repeat; + border-style: solid; + border-width: 5px; + height: 20px; + padding: 0; + text-indent: -9999px; + width: 20px; +} +.ui-mini .ui-radio .ui-btn.ui-radio-on:after { + height: 18px; + border-width: 4px; + width: 18px; +} +.ui-alt-icon.ui-btn.ui-radio-on:after, +.ui-alt-icon .ui-btn.ui-radio-on:after { + background-color: #000; +} + + + +/* apply glyphs to icons */ +.ui-icon-blank:after { content: ' '; } /* <-- yeah, this really needed! */ +.ui-icon-addon:after, +.ui-icon-puzzle:after { content: '\e6ca'; } +.ui-icon-address:after { content: '\e702'; } +.ui-icon-alert:after { content: '\e65f'; } +.ui-icon-alert-b:after { content: '\e660'; } +.ui-icon-anchor:after { content: '\e6ba'; } +.ui-icon-archive:after { content: '\e70d'; } +.ui-icon-arrow-1-e:after, +.ui-icon-arrow-r:after { content: '\e603'; } +.ui-icon-arrow-1-n:after, +.ui-icon-arrow-u:after { content: '\e601'; } +.ui-icon-arrow-1-ne:after, +.ui-icon-arrow-u-r:after { content: '\e602'; } +.ui-icon-arrow-1-nw:after, +.ui-icon-arrow-u-l:after { content: '\e608'; } +.ui-icon-arrow-1-s:after, +.ui-icon-arrow-d:after { content: '\e605'; } +.ui-icon-arrow-1-se:after, +.ui-icon-arrow-d-r:after { content: '\e604'; } +.ui-icon-arrow-1-sw:after, +.ui-icon-arrow-d-l:after { content: '\e606'; } +.ui-icon-arrow-1-w:after, +.ui-icon-arrow-l:after { content: '\e607'; } +.ui-icon-arrow-2-e-w:after, +.ui-icon-move-h:after, +.ui-icon-resize-h:after { content: '\e617'; } +.ui-icon-arrow-2-n-s:after, +.ui-icon-move-v:after, +.ui-icon-resize-v:after { content: '\e615'; } +.ui-icon-arrow-2-ne-sw:after { content: '\e616'; } +.ui-icon-arrow-2-se-nw:after { content: '\e618'; } +.ui-icon-arrow-4:after, +.ui-icon-move:after { content: '\e619'; } +.ui-icon-arrow-4-diag:after { content: '\e61a'; } +.ui-icon-arrowrefresh-1-e:after { content: '\e612'; } +.ui-icon-arrowrefresh-1-n:after { content: '\e611'; } +.ui-icon-arrowrefresh-1-s:after { content: '\e613'; } +.ui-icon-arrowrefresh-1-w:after { content: '\e614'; } +.ui-icon-arrowreturn-1-e:after, +.ui-icon-forward:after { content: '\e60e'; } +.ui-icon-arrowreturn-1-n:after { content: '\e60d'; } +.ui-icon-arrowreturn-1-s:after, +.ui-icon-back:after { content: '\e60f'; } +.ui-icon-arrowreturn-1-w:after { content: '\e610'; } +.ui-icon-arrowreturnthick-1-e:after { content: '\e628'; } +.ui-icon-arrowreturnthick-1-n:after { content: '\e627'; } +.ui-icon-arrowreturnthick-1-s:after { content: '\e629'; } +.ui-icon-arrowreturnthick-1-w:after { content: '\e62a'; } +.ui-icon-arrowstop-1-e:after { content: '\e60a'; } +.ui-icon-arrowstop-1-n:after { content: '\e609'; } +.ui-icon-arrowstop-1-s:after { content: '\e60b'; } +.ui-icon-arrowstop-1-w:after { content: '\e60c'; } +.ui-icon-arrowthick-1-e:after { content: '\e61d'; } +.ui-icon-arrowthick-1-n:after { content: '\e61b'; } +.ui-icon-arrowthick-1-ne:after { content: '\e61c'; } +.ui-icon-arrowthick-1-nw:after { content: '\e622'; } +.ui-icon-arrowthick-1-s:after { content: '\e61f'; } +.ui-icon-arrowthick-1-se:after { content: '\e61e'; } +.ui-icon-arrowthick-1-sw:after { content: '\e620'; } +.ui-icon-arrowthick-1-w:after { content: '\e621'; } +.ui-icon-arrowthick-2-e-w:after { content: '\e62d'; } +.ui-icon-arrowthick-2-n-s:after { content: '\e62b'; } +.ui-icon-arrowthick-2-ne-sw:after { content: '\e62c'; } +.ui-icon-arrowthick-2-se-nw:after { content: '\e62e'; } +.ui-icon-arrowthickstop-1-e:after { content: '\e624'; } +.ui-icon-arrowthickstop-1-n:after { content: '\e623'; } +.ui-icon-arrowthickstop-1-s:after { content: '\e625'; } +.ui-icon-arrowthickstop-1-w:after { content: '\e626'; } +.ui-icon-battery-0:after { content: '\e721'; } +.ui-icon-battery-1:after { content: '\e722'; } +.ui-icon-battery-2:after { content: '\e723'; } +.ui-icon-battery-3:after { content: '\e724'; } +.ui-icon-book:after { content: '\e6fb'; } +.ui-icon-book-b:after { content: '\e6fc'; } +.ui-icon-bookmark:after { content: '\e6c5'; } +.ui-icon-bookmark-b:after { content: '\e6c6'; } +.ui-icon-box:after { content: '\e6eb'; } +.ui-icon-bucket:after { content: '\e728'; } +.ui-icon-bug:after { content: '\e72e'; } +.ui-icon-bullet:after, +html .ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon:after, +html .ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon:after { content: '\e65d'; } +.ui-icon-bullhorn:after { content: '\e731'; } +.ui-icon-calculator:after { content: '\e6fd'; } +.ui-icon-calculator-b:after { content: '\e6fe'; } +.ui-icon-calendar:after { content: '\e6ff'; } +.ui-icon-calendar-b:after { content: '\e700'; } +.ui-icon-calendar-day:after { content: '\e701'; } +.ui-icon-camera:after { content: '\e6e8'; } +.ui-icon-cancel:after, +.ui-icon-forbidden:after { content: '\e675'; } +.ui-icon-caret-1-e:after, +.ui-icon-caret-r:after, +.ui-icon-carat-r:after { content: '\e639'; } +.ui-icon-caret-1-n:after, +.ui-icon-caret-u:after, +.ui-icon-carat-u:after { content: '\e637'; } +.ui-icon-caret-1-ne:after { content: '\e638'; } +.ui-icon-caret-1-nw:after { content: '\e63e'; } +.ui-icon-caret-1-s:after, +.ui-icon-caret-d:after, +.ui-icon-carat-d:after { content: '\e63b'; } +.ui-icon-caret-1-se:after { content: '\e63a'; } +.ui-icon-caret-1-sw:after { content: '\e63c'; } +.ui-icon-caret-1-w:after, +.ui-icon-caret-l:after, +.ui-icon-carat-l:after { content: '\e63d'; } +.ui-icon-caret-2-e:after { content: '\e640'; } +.ui-icon-caret-2-e-w:after { content: '\e643'; } +.ui-icon-caret-2-n:after { content: '\e63f'; } +.ui-icon-caret-2-n-s:after { content: '\e644'; } +.ui-icon-caret-2-s:after { content: '\e641'; } +.ui-icon-caret-2-w:after { content: '\e642'; } +.ui-icon-caretstop-1-e:after, +.ui-icon-caratstop-1-e:after { content: '\e905'; } +.ui-icon-caretstop-1-n:after, +.ui-icon-caratstop-1-n:after { content: '\e901'; } +.ui-icon-caretstop-1-s:after, +.ui-icon-caratstop-1-s:after { content: '\e900'; } +.ui-icon-caretstop-1-w:after, +.ui-icon-caratstop-1-w:after { content: '\e904'; } +.ui-icon-cart:after, +.ui-icon-shop:after { content: '\e6d6'; } +.ui-icon-cart-b:after, +.ui-icon-shop-b:after { content: '\e6d7'; } +.ui-icon-chart-bars:after { content: '\e734'; } +.ui-icon-chart-line:after { content: '\e735'; } +.ui-icon-chart-pie:after { content: '\e733'; } +.ui-icon-check:after, +html .ui-btn.ui-checkbox-on.ui-checkbox-on:after, +html .ui-alt-icon.ui-btn.ui-checkbox-on:after, +html .ui-alt-icon .ui-btn.ui-checkbox-on:after { content: '\e670'; } +.ui-icon-check-off:after, +.ui-icon-checkbox:after, +.ui-icon-checkbox-off:after, +.ui-icon-checkbox-unchecked:after { content: '\e673'; } +.ui-icon-check-on:after, +.ui-icon-checkbox-on:after, +.ui-icon-checkbox-checked:after { content: '\e674'; } +.ui-icon-circle:after, +.ui-icon-radio-off:after, +.ui-icon-radio-btn:after, +.ui-icon-radio-btn-off:after, +.ui-icon-radio-btn-unchecked:after { content: '\e65e'; } +.ui-icon-circle-arrow-e:after { content: '\e630'; } +.ui-icon-circle-arrow-n:after { content: '\e62f'; } +.ui-icon-circle-arrow-s:after { content: '\e631'; } +.ui-icon-circle-arrow-w:after { content: '\e632'; } +.ui-icon-circle-b-arrow-e:after { content: '\e634'; } +.ui-icon-circle-b-arrow-n:after { content: '\e633'; } +.ui-icon-circle-b-arrow-s:after { content: '\e635'; } +.ui-icon-circle-b-arrow-w:after { content: '\e636'; } +.ui-icon-circle-b-check:after { content: '\e672'; } +.ui-icon-circle-b-close:after { content: '\e678'; } +.ui-icon-circle-b-help:after { content: '\e663'; } +.ui-icon-circle-b-info:after { content: '\e666'; } +.ui-icon-circle-b-minus:after { content: '\e67e'; } +.ui-icon-circle-b-notice:after { content: '\e669'; } +.ui-icon-circle-b-plus:after { content: '\e684'; } +.ui-icon-circle-b-triangle-e:after { content: '\e65a'; } +.ui-icon-circle-b-triangle-n:after { content: '\e659'; } +.ui-icon-circle-b-triangle-s:after { content: '\e65b'; } +.ui-icon-circle-b-triangle-w:after { content: '\e65c'; } +.ui-icon-circle-check:after { content: '\e671'; } +.ui-icon-circle-close:after { content: '\e677'; } +.ui-icon-circle-help:after, +.ui-icon-help:after { content: '\e662'; } +.ui-icon-circle-info:after, +.ui-icon-info:after { content: '\e665'; } +.ui-icon-circle-minus:after { content: '\e67d'; } +.ui-icon-circle-notice:after, +.ui-icon-notice:after { content: '\e668'; } +.ui-icon-circle-phone:after { content: '\e705'; } +.ui-icon-circle-plus:after { content: '\e683'; } +.ui-icon-circle-triangle-e:after { content: '\e656'; } +.ui-icon-circle-triangle-n:after { content: '\e655'; } +.ui-icon-circle-triangle-s:after { content: '\e657'; } +.ui-icon-circle-triangle-w:after { content: '\e658'; } +.ui-icon-circle-zoom:after { content: '\e712'; } +.ui-icon-circle-zoomin:after { content: '\e714'; } +.ui-icon-circle-zoomout:after { content: '\e716'; } +.ui-icon-circlesmall-close:after { content: '\e67b'; } +.ui-icon-circlesmall-minus:after { content: '\e681'; } +.ui-icon-circlesmall-plus:after { content: '\e687'; } +.ui-icon-client:after { content: '\e72f'; } +.ui-icon-clipboard:after, +.ui-icon-paste:after { content: '\e68b'; } +.ui-icon-clock:after { content: '\e6d9'; } +.ui-icon-clock-b:after { content: '\e6da'; } +.ui-icon-close:after, +.ui-icon-delete:after { content: '\e676'; } +.ui-icon-closethick:after { content: '\e679'; } +.ui-icon-cloud:after { content: '\e6dc'; } +.ui-icon-cloud-b:after { content: '\e6dd'; } +.ui-icon-cloud-download:after { content: '\e6de'; } +.ui-icon-cloud-upload:after { content: '\e6df'; } +.ui-icon-comment:after { content: '\e6e0'; } +.ui-icon-comments:after { content: '\e6e1'; } +.ui-icon-console:after { content: '\e6c0'; } +.ui-icon-contact:after, +.ui-icon-vcard:after { content: '\e703'; } +.ui-icon-copy:after, +.ui-icon-files:after { content: '\e689'; } +.ui-icon-creditcard:after { content: '\e6d8'; } +.ui-icon-database:after { content: '\e6f9'; } +.ui-icon-databases:after { content: '\e6fa'; } +.ui-icon-disk:after, +.ui-icon-save:after { content: '\e68c'; } +.ui-icon-document:after, +.ui-icon-file:after { content: '\e69c'; } +.ui-icon-document-b:after { content: '\e69d'; } +.ui-icon-download:after { content: '\e6aa'; } +.ui-icon-eject:after { content: '\e6b6'; } +.ui-icon-erase:after { content: '\e72b'; } +.ui-icon-extlink:after, +.ui-icon-linkext:after, +.ui-icon-action:after { content: '\e6b8'; } +.ui-icon-eye:after { content: '\e6ea'; } +.ui-icon-file-audio:after, +.ui-icon-audio:after { content: '\e69e'; } +.ui-icon-file-pdf:after { content: '\e6a3'; } +.ui-icon-file-report:after { content: '\e6a6'; } +.ui-icon-file-richtext:after { content: '\e6a4'; } +.ui-icon-file-table:after { content: '\e6a5'; } +.ui-icon-file-text:after { content: '\e6a7'; } +.ui-icon-file-word:after { content: '\e6a8'; } +.ui-icon-file-zip:after { content: '\e6a9'; } +.ui-icon-flag:after { content: '\e6e9'; } +.ui-icon-folder-collapsed:after, +.ui-icon-folder:after, +.ui-icon-folder-closed:after { content: '\e69a'; } +.ui-icon-folder-open:after { content: '\e69b'; } +.ui-icon-fullscreen:after, +.ui-icon-fullscreen-on:after { content: '\e902'; } +.ui-icon-fullscreen-off:after { content: '\e903'; } +.ui-icon-gear:after { content: '\e6e6'; } +.ui-icon-gears:after { content: '\e6e7'; } +.ui-icon-globe:after { content: '\e6e2'; } +.ui-icon-globe-b:after { content: '\e6e3'; } +.ui-icon-grip-diagonal-se:after { content: '\e66a'; } +.ui-icon-grip-dotted-horizontal:after { content: '\e66e'; } +.ui-icon-grip-dotted-vertical:after { content: '\e66f'; } +.ui-icon-grip-solid-horizontal:after { content: '\e66c'; } +.ui-icon-grip-solid-vertical:after { content: '\e66d'; } +.ui-icon-gripsmall-diagonal-se:after { content: '\e66b'; } +.ui-icon-heart:after { content: '\e6d1'; } +.ui-icon-heart-b:after { content: '\e6d2'; } +.ui-icon-heart-beat:after { content: '\e6d3'; } +.ui-icon-help-plain:after { content: '\e661'; } +.ui-icon-history:after { content: '\e6db'; } +.ui-icon-home:after { content: '\e6c4'; } +.ui-icon-image:after, +.ui-icon-file-image:after { content: '\e6a1'; } +.ui-icon-info-plain:after { content: '\e664'; } +.ui-icon-jquery:after { content: '\e746'; } +.ui-icon-key:after { content: '\e6d4'; } +.ui-icon-lightbulb:after { content: '\e6d5'; } +.ui-icon-link:after { content: '\e6b7'; } +.ui-icon-link-broken:after { content: '\e6b9'; } +.ui-icon-loading-status-balls:after { content: '\e741'; } +.ui-icon-loading-status-circle:after { content: '\e742'; } +.ui-icon-loading-status-comet:after { content: '\e743'; } +.ui-icon-loading-status-lines:after { content: '\e744'; } +.ui-icon-loading-status-planet:after { content: '\e745'; } +.ui-icon-location:after { content: '\e6e4'; } +.ui-icon-locked:after, +.ui-icon-lock:after { content: '\e6bb'; } +.ui-icon-mail-attachment:after { content: '\e70b'; } +.ui-icon-mail-closed:after, +.ui-icon-mail:after, +.ui-icon-email:after { content: '\e706'; } +.ui-icon-mail-forward:after { content: '\e708'; } +.ui-icon-mail-open:after, +.ui-icon-mail-read:after { content: '\e707'; } +.ui-icon-mail-reply:after { content: '\e709'; } +.ui-icon-mail-replyall:after { content: '\e70a'; } +.ui-icon-mail-send:after { content: '\e70c'; } +.ui-icon-marker:after { content: '\e72c'; } +.ui-icon-menu:after, +.ui-icon-bars:after { content: '\e6c3'; } +.ui-icon-microphone:after { content: '\e6b2'; } +.ui-icon-microphone-off:after { content: '\e6b3'; } +.ui-icon-minus:after { content: '\e67c'; } +.ui-icon-minusthick:after { content: '\e67f'; } +.ui-icon-movie:after, +.ui-icon-file-movie:after { content: '\e69f'; } +.ui-icon-navigation:after { content: '\e6e5'; } +.ui-icon-newspaper:after, +.ui-icon-newsletter:after, +.ui-icon-news:after { content: '\e70e'; } +.ui-icon-newwin:after, +.ui-icon-popup:after, +.ui-icon-windows:after { content: '\e6be'; } +.ui-icon-note:after { content: '\e695'; } +.ui-icon-notice-plain:after { content: '\e667'; } +.ui-icon-package:after { content: '\e6cc'; } +.ui-icon-palette:after { content: '\e729'; } +.ui-icon-pause:after { content: '\e6ad'; } +.ui-icon-pencil:after, +.ui-icon-edit:after { content: '\e688'; } +.ui-icon-person:after, +.ui-icon-user:after { content: '\e6d0'; } +.ui-icon-persons:after, +.ui-icon-users:after, +.ui-icon-group:after { content: '\e6cf'; } +.ui-icon-phone:after { content: '\e704'; } +.ui-icon-pilcrow:after { content: '\e727'; } +.ui-icon-pin-s:after { content: '\e70f'; } +.ui-icon-pin-w:after { content: '\e710'; } +.ui-icon-play:after { content: '\e6ac'; } +.ui-icon-plugin:after { content: '\e6cb'; } +.ui-icon-plus:after { content: '\e682'; } +.ui-icon-plusthick:after { content: '\e685'; } +.ui-icon-power:after, +.ui-icon-switch:after { content: '\e6cd'; } +.ui-icon-print:after { content: '\e692'; } +.ui-icon-print-b:after { content: '\e693'; } +.ui-icon-print-layout:after { content: '\e694'; } +.ui-icon-prush:after { content: '\e72a'; } +.ui-icon-radio-on:after, +.ui-icon-radio-btn-on:after, +.ui-icon-radio-btn-checked:after { content: '\e6f5'; } +.ui-icon-redo:after { content: '\e68e'; } +.ui-icon-refresh:after, +.ui-icon-reload:after { content: '\e6ce'; } +.ui-icon-rename:after, +.ui-icon-input:after { content: '\e68f'; } +.ui-icon-retweet:after { content: '\e6b5'; } +.ui-icon-scissors:after, +.ui-icon-cut:after { content: '\e68a'; } +.ui-icon-screen-desktop:after, +.ui-icon-desktop:after { content: '\e718'; } +.ui-icon-screen-laptop:after, +.ui-icon-laptop:after { content: '\e719'; } +.ui-icon-screen-mobile:after, +.ui-icon-mobile:after { content: '\e71a'; } +.ui-icon-script:after, +.ui-icon-file-script:after { content: '\e6a2'; } +.ui-icon-search:after, +.ui-input-search:after { content: '\e6f2'; } +.ui-icon-select:after { content: '\e72d'; } +.ui-icon-selectbox:after { content: '\e6f6'; } +.ui-icon-server:after { content: '\e730'; } +.ui-icon-settings:after { content: '\e6f4'; } +.ui-icon-shield:after { content: '\e732'; } +.ui-icon-shuffle:after { content: '\e6b4'; } +.ui-icon-shuttle:after { content: '\e73f'; } +.ui-icon-sign-in:after, +.ui-icon-login:after { content: '\e6ee'; } +.ui-icon-sign-out:after, +.ui-icon-logout:after, +.ui-icon-logoff:after { content: '\e6ef'; } +.ui-icon-signal:after { content: '\e725'; } +.ui-icon-signal-diag:after, +.ui-icon-rss:after, +.ui-icon-feed:after { content: '\e726'; } +.ui-icon-sitemap:after { content: '\e736'; } +.ui-icon-sorting:after { content: '\e71e'; } +.ui-icon-sorting-asc:after { content: '\e71f'; } +.ui-icon-sorting-desc:after { content: '\e720'; } +.ui-icon-squaresmall-close:after { content: '\e67a'; } +.ui-icon-squaresmall-minus:after { content: '\e680'; } +.ui-icon-squaresmall-plus:after { content: '\e686'; } +.ui-icon-star:after { content: '\e6c7'; } +.ui-icon-star-b:after { content: '\e6c9'; } +.ui-icon-star-h:after { content: '\e6c8'; } +.ui-icon-stop:after { content: '\e6ae'; } +.ui-icon-structure:after { content: '\e737'; } +.ui-icon-suitcase:after { content: '\e6f7'; } +.ui-icon-table:after { content: '\e696'; } +.ui-icon-tag:after { content: '\e697'; } +.ui-icon-tags:after { content: '\e698'; } +.ui-icon-template:after { content: '\e738'; } +.ui-icon-ticket:after { content: '\e699'; } +.ui-icon-toggle-off:after { content: '\e6f0'; } +.ui-icon-toggle-on:after { content: '\e6f1'; } +.ui-icon-transfer-e-w:after { content: '\e6ec'; } +.ui-icon-transferthick-e-w:after { content: '\e6ed'; } +.ui-icon-transform:after { content: '\e739'; } +.ui-icon-translate:after { content: '\e740'; } +.ui-icon-trash:after, +.ui-icon-recycle:after { content: '\e690'; } +.ui-icon-trash-b:after { content: '\e691'; } +.ui-icon-triangle-1-e:after { content: '\e647'; } +.ui-icon-triangle-1-e-stop:after, +.ui-icon-seek-end:after { content: '\e64e'; } +.ui-icon-triangle-1-n:after { content: '\e645'; } +.ui-icon-triangle-1-n-stop:after { content: '\e64d'; } +.ui-icon-triangle-1-ne:after { content: '\e646'; } +.ui-icon-triangle-1-nw:after { content: '\e64c'; } +.ui-icon-triangle-1-s:after { content: '\e64b'; } +.ui-icon-triangle-1-s-stop:after { content: '\e64f'; } +.ui-icon-triangle-1-se:after { content: '\e64a'; } +.ui-icon-triangle-1-sw:after { content: '\e648'; } +.ui-icon-triangle-1-w:after { content: '\e649'; } +.ui-icon-triangle-1-w-stop:after, +.ui-icon-seek-first:after { content: '\e650'; } +.ui-icon-triangle-2-e:after, +.ui-icon-seek-next:after { content: '\e651'; } +.ui-icon-triangle-2-e-w:after { content: '\e654'; } +.ui-icon-triangle-2-n-s:after { content: '\e653'; } +.ui-icon-triangle-2-w:after, +.ui-icon-seek-prev:after { content: '\e652'; } +.ui-icon-truck:after { content: '\e6f8'; } +.ui-icon-undo:after { content: '\e68d'; } +.ui-icon-unlocked:after, +.ui-icon-lock-open:after { content: '\e6bc'; } +.ui-icon-upload:after { content: '\e6ab'; } +.ui-icon-vcs-branch:after { content: '\e73d'; } +.ui-icon-vcs-compare:after { content: '\e73b'; } +.ui-icon-vcs-fork:after { content: '\e73a'; } +.ui-icon-vcs-merge:after { content: '\e73e'; } +.ui-icon-vcs-pull-request:after { content: '\e73c'; } +.ui-icon-video:after, +.ui-icon-file-video:after { content: '\e6a0'; } +.ui-icon-view-icons:after, +.ui-icon-grid-b:after { content: '\e71b'; } +.ui-icon-view-icons-b:after, +.ui-icon-grid:after { content: '\e71c'; } +.ui-icon-view-list:after, +.ui-icon-list:after, +.ui-icon-bullets:after { content: '\e71d'; } +.ui-icon-volume-off:after, +.ui-icon-volume-mute:after { content: '\e6af'; } +.ui-icon-volume-on:after, +.ui-icon-volume-high:after { content: '\e6b0'; } +.ui-icon-volume-on-b:after, +.ui-icon-volume-low:after { content: '\e6b1'; } +.ui-icon-window:after { content: '\e6bd'; } +.ui-icon-window-close:after { content: '\e6c1'; } +.ui-icon-window-minimize:after { content: '\e6c2'; } +.ui-icon-window-sidebar:after { content: '\e6bf'; } +.ui-icon-wrench:after { content: '\e6f3'; } +.ui-icon-zoom:after { content: '\e711'; } +.ui-icon-zoomequal:after { content: '\e717'; } +.ui-icon-zoomin:after { content: '\e713'; } +.ui-icon-zoomout:after { content: '\e715'; } + +.ui-icon-carat-1-e:after { content: '\e639'; } /* deprecated: use '.ui-icon-caret-1-e' instead */ +.ui-icon-carat-1-n:after { content: '\e637'; } /* deprecated: use '.ui-icon-caret-1-n' instead */ +.ui-icon-carat-1-s:after { content: '\e63b'; } /* deprecated: use '.ui-icon-caret-1-s' instead */ +.ui-icon-carat-1-w:after { content: '\e63d'; } /* deprecated: use '.ui-icon-caret-1-w' instead */ +.ui-icon-carat-2-e:after { content: '\e640'; } /* deprecated: use '.ui-icon-caret-2-e' instead */ +.ui-icon-carat-2-e-w:after { content: '\e643'; } /* deprecated: use '.ui-icon-caret-2-e-w' instead */ +.ui-icon-carat-2-n:after { content: '\e63f'; } /* deprecated: use '.ui-icon-caret-2-n' instead */ +.ui-icon-carat-2-n-s:after { content: '\e644'; } /* deprecated: use '.ui-icon-caret-2-n-s' instead */ +.ui-icon-carat-2-s:after { content: '\e641'; } /* deprecated: use '.ui-icon-caret-2-s' instead */ +.ui-icon-carat-2-w:after { content: '\e642'; } /* deprecated: use '.ui-icon-caret-2-w' instead */ +.ui-icon-caratstop-1-e:after { content: '\e905'; } /* deprecated: use '.ui-icon-caretstop-1-e' instead */ +.ui-icon-caratstop-1-n:after { content: '\e901'; } /* deprecated: use '.ui-icon-caretstop-1-n' instead */ +.ui-icon-caratstop-1-s:after { content: '\e900'; } /* deprecated: use '.ui-icon-caretstop-1-s' instead */ +.ui-icon-caratstop-1-w:after { content: '\e904'; } /* deprecated: use '.ui-icon-caretstop-1-w' instead */ + +/* bounce animations */ +@keyframes bounce { + 0%, 100% { -webkit-transform: scale(0.2); -moz-transform: scale(0.2); -ms-transform: scale(0.2); transform: scale(0.2); } + 50% { -webkit-transform: scale(1.0); -moz-transform: scale(1.0); -ms-transform: scale(1.0); transform: scale(1.0); } +} +@-moz-keyframes bounce { 0%, 100% { -moz-transform: scale(0.2); transform: scale(0.2); } 50% { -moz-transform: scale(1.0); transform: scale(1.0); } } +@-ms-keyframes bounce { 0%, 100% { -ms-transform: scale(0.2); transform: scale(0.2); } 50% { -ms-transform: scale(1.0); transform: scale(1.0); } } +@-webkit-keyframes bounce { 0%, 100% { -webkit-transform: scale(0.2); transform: scale(0.2); } 50% { -webkit-transform: scale(1.0); transform: scale(1.0); } } + +[class^='ui-icon-'].bounce:after, +[class*=' ui-icon-'].bounce:after { + animation: bounce 1s infinite ease-in-out; + -moz-animation: bounce 1s infinite ease-in-out; + -ms-animation: bounce 1s infinite ease-in-out; + -webkit-animation: bounce 1s infinite ease-in-out; +} + + +/* rotated animations */ +@keyframes rotate { + from { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } + to { -webkit-transform: rotate(359deg); -moz-transform: rotate(359deg); -ms-transform: rotate(359deg); transform: rotate(359deg); } +} +@-moz-keyframes rotate { from { -moz-transform: rotate(0deg); transform: rotate(0deg); } to { -moz-transform: rotate(359deg); transform: rotate(359deg); } } +@-ms-keyframes rotate { from { -ms-transform: rotate(0deg); transform: rotate(0deg); } to { -ms-transform: rotate(359deg); transform: rotate(359deg); } } +@-webkit-keyframes rotate { from { -webkit-transform: rotate(0deg); transform: rotate(0deg); } to { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } + +[class^='ui-icon-'].rotate, /* clockwise */ +[class*=' ui-icon-'].rotate, /* clockwise */ +[class^='ui-icon-'].rotate-reverse, /* anti clockwise */ +[class*=' ui-icon-'].rotate-reverse /* anti clockwise */ { + animation: rotate 1s infinite linear; + -moz-animation: rotate 1s infinite linear; + -ms-animation: rotate 1s infinite linear; + -webkit-animation: rotate 1s infinite linear; +} +[class^='ui-icon-'].rotate-reverse, /* anti clockwise */ +[class*=' ui-icon-'].rotate-reverse /* anti clockwise */ { + animation-direction: reverse; + -moz-animation-direction: reverse; + -ms-animation-direction: reverse; + -webkit-animation-direction: reverse; +} diff --git a/src/lib/vendor/jquery.smooth-scroll.js b/src/lib/vendor/jquery.smooth-scroll.js new file mode 100644 index 0000000..e2d4fd6 --- /dev/null +++ b/src/lib/vendor/jquery.smooth-scroll.js @@ -0,0 +1,357 @@ +/*! + * jQuery Smooth Scroll - v2.2.0 - 2017-05-05 + * https://github.com/kswedberg/jquery-smooth-scroll + * Copyright (c) 2017 Karl Swedberg + * Licensed MIT + */ + +(function(factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof module === 'object' && module.exports) { + // CommonJS + factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +}(function($) { + + var version = '2.2.0'; + var optionOverrides = {}; + var defaults = { + exclude: [], + excludeWithin: [], + offset: 0, + + // one of 'top' or 'left' + direction: 'top', + + // if set, bind click events through delegation + // supported since jQuery 1.4.2 + delegateSelector: null, + + // jQuery set of elements you wish to scroll (for $.smoothScroll). + // if null (default), $('html, body').firstScrollable() is used. + scrollElement: null, + + // only use if you want to override default behavior + scrollTarget: null, + + // automatically focus the target element after scrolling to it + autoFocus: false, + + // fn(opts) function to be called before scrolling occurs. + // `this` is the element(s) being scrolled + beforeScroll: function() {}, + + // fn(opts) function to be called after scrolling occurs. + // `this` is the triggering element + afterScroll: function() {}, + + // easing name. jQuery comes with "swing" and "linear." For others, you'll need an easing plugin + // from jQuery UI or elsewhere + easing: 'swing', + + // speed can be a number or 'auto' + // if 'auto', the speed will be calculated based on the formula: + // (current scroll position - target scroll position) / autoCoeffic + speed: 400, + + // coefficient for "auto" speed + autoCoefficient: 2, + + // $.fn.smoothScroll only: whether to prevent the default click action + preventDefault: true + }; + + var getScrollable = function(opts) { + var scrollable = []; + var scrolled = false; + var dir = opts.dir && opts.dir === 'left' ? 'scrollLeft' : 'scrollTop'; + + this.each(function() { + var el = $(this); + + if (this === document || this === window) { + return; + } + + if (document.scrollingElement && (this === document.documentElement || this === document.body)) { + scrollable.push(document.scrollingElement); + + return false; + } + + if (el[dir]() > 0) { + scrollable.push(this); + } else { + // if scroll(Top|Left) === 0, nudge the element 1px and see if it moves + el[dir](1); + scrolled = el[dir]() > 0; + + if (scrolled) { + scrollable.push(this); + } + // then put it back, of course + el[dir](0); + } + }); + + if (!scrollable.length) { + this.each(function() { + // If no scrollable elements and <html> has scroll-behavior:smooth because + // "When this property is specified on the root element, it applies to the viewport instead." + // and "The scroll-behavior property of the … body element is *not* propagated to the viewport." + // → https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior + if (this === document.documentElement && $(this).css('scrollBehavior') === 'smooth') { + scrollable = [this]; + } + + // If still no scrollable elements, fall back to <body>, + // if it's in the jQuery collection + // (doing this because Safari sets scrollTop async, + // so can't set it to 1 and immediately get the value.) + if (!scrollable.length && this.nodeName === 'BODY') { + scrollable = [this]; + } + }); + } + + // Use the first scrollable element if we're calling firstScrollable() + if (opts.el === 'first' && scrollable.length > 1) { + scrollable = [scrollable[0]]; + } + + return scrollable; + }; + + var rRelative = /^([\-\+]=)(\d+)/; + + $.fn.extend({ + scrollable: function(dir) { + var scrl = getScrollable.call(this, {dir: dir}); + + return this.pushStack(scrl); + }, + firstScrollable: function(dir) { + var scrl = getScrollable.call(this, {el: 'first', dir: dir}); + + return this.pushStack(scrl); + }, + + smoothScroll: function(options, extra) { + options = options || {}; + + if (options === 'options') { + if (!extra) { + return this.first().data('ssOpts'); + } + + return this.each(function() { + var $this = $(this); + var opts = $.extend($this.data('ssOpts') || {}, extra); + + $(this).data('ssOpts', opts); + }); + } + + var opts = $.extend({}, $.fn.smoothScroll.defaults, options); + + var clickHandler = function(event) { + var escapeSelector = function(str) { + return str.replace(/(:|\.|\/)/g, '\\$1'); + }; + + var link = this; + var $link = $(this); + var thisOpts = $.extend({}, opts, $link.data('ssOpts') || {}); + var exclude = opts.exclude; + var excludeWithin = thisOpts.excludeWithin; + var elCounter = 0; + var ewlCounter = 0; + var include = true; + var clickOpts = {}; + var locationPath = $.smoothScroll.filterPath(location.pathname); + var linkPath = $.smoothScroll.filterPath(link.pathname); + var hostMatch = location.hostname === link.hostname || !link.hostname; + var pathMatch = thisOpts.scrollTarget || (linkPath === locationPath); + var thisHash = escapeSelector(link.hash); + + if (thisHash && !$(thisHash).length) { + include = false; + } + + if (!thisOpts.scrollTarget && (!hostMatch || !pathMatch || !thisHash)) { + include = false; + } else { + while (include && elCounter < exclude.length) { + if ($link.is(escapeSelector(exclude[elCounter++]))) { + include = false; + } + } + + while (include && ewlCounter < excludeWithin.length) { + if ($link.closest(excludeWithin[ewlCounter++]).length) { + include = false; + } + } + } + + if (include) { + if (thisOpts.preventDefault) { + event.preventDefault(); + } + + $.extend(clickOpts, thisOpts, { + scrollTarget: thisOpts.scrollTarget || thisHash, + link: link + }); + + $.smoothScroll(clickOpts); + } + }; + + if (options.delegateSelector !== null) { + this + .off('click.smoothscroll', options.delegateSelector) + .on('click.smoothscroll', options.delegateSelector, clickHandler); + } else { + this + .off('click.smoothscroll') + .on('click.smoothscroll', clickHandler); + } + + return this; + } + }); + + var getExplicitOffset = function(val) { + var explicit = {relative: ''}; + var parts = typeof val === 'string' && rRelative.exec(val); + + if (typeof val === 'number') { + explicit.px = val; + } else if (parts) { + explicit.relative = parts[1]; + explicit.px = parseFloat(parts[2]) || 0; + } + + return explicit; + }; + + var onAfterScroll = function(opts) { + var $tgt = $(opts.scrollTarget); + + if (opts.autoFocus && $tgt.length) { + $tgt[0].focus(); + + if (!$tgt.is(document.activeElement)) { + $tgt.prop({tabIndex: -1}); + $tgt[0].focus(); + } + } + + opts.afterScroll.call(opts.link, opts); + }; + + $.smoothScroll = function(options, px) { + if (options === 'options' && typeof px === 'object') { + return $.extend(optionOverrides, px); + } + var opts, $scroller, speed, delta; + var explicitOffset = getExplicitOffset(options); + var scrollTargetOffset = {}; + var scrollerOffset = 0; + var offPos = 'offset'; + var scrollDir = 'scrollTop'; + var aniProps = {}; + var aniOpts = {}; + + if (explicitOffset.px) { + opts = $.extend({link: null}, $.fn.smoothScroll.defaults, optionOverrides); + } else { + opts = $.extend({link: null}, $.fn.smoothScroll.defaults, options || {}, optionOverrides); + + if (opts.scrollElement) { + offPos = 'position'; + + if (opts.scrollElement.css('position') === 'static') { + opts.scrollElement.css('position', 'relative'); + } + } + + if (px) { + explicitOffset = getExplicitOffset(px); + } + } + + scrollDir = opts.direction === 'left' ? 'scrollLeft' : scrollDir; + + if (opts.scrollElement) { + $scroller = opts.scrollElement; + + if (!explicitOffset.px && !(/^(?:HTML|BODY)$/).test($scroller[0].nodeName)) { + scrollerOffset = $scroller[scrollDir](); + } + } else { + $scroller = $('html, body').firstScrollable(opts.direction); + } + + // beforeScroll callback function must fire before calculating offset + opts.beforeScroll.call($scroller, opts); + + scrollTargetOffset = explicitOffset.px ? explicitOffset : { + relative: '', + px: ($(opts.scrollTarget)[offPos]() && $(opts.scrollTarget)[offPos]()[opts.direction]) || 0 + }; + + aniProps[scrollDir] = scrollTargetOffset.relative + (scrollTargetOffset.px + scrollerOffset + opts.offset); + + speed = opts.speed; + + // automatically calculate the speed of the scroll based on distance / coefficient + if (speed === 'auto') { + + // $scroller[scrollDir]() is position before scroll, aniProps[scrollDir] is position after + // When delta is greater, speed will be greater. + delta = Math.abs(aniProps[scrollDir] - $scroller[scrollDir]()); + + // Divide the delta by the coefficient + speed = delta / opts.autoCoefficient; + } + + aniOpts = { + duration: speed, + easing: opts.easing, + complete: function() { + onAfterScroll(opts); + } + }; + + if (opts.step) { + aniOpts.step = opts.step; + } + + if ($scroller.length) { + $scroller.stop().animate(aniProps, aniOpts); + } else { + onAfterScroll(opts); + } + }; + + $.smoothScroll.version = version; + $.smoothScroll.filterPath = function(string) { + string = string || ''; + + return string + .replace(/^\//, '') + .replace(/(?:index|default).[a-zA-Z]{3,4}$/, '') + .replace(/\/$/, ''); + }; + + // default options + $.fn.smoothScroll.defaults = defaults; + +})); diff --git a/src/lib/vendor/punycode-1.4.1.js b/src/lib/vendor/punycode-1.4.1.js new file mode 100644 index 0000000..2c87f6c --- /dev/null +++ b/src/lib/vendor/punycode-1.4.1.js @@ -0,0 +1,533 @@ +/*! https://mths.be/punycode v1.4.1 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); diff --git a/src/lib/vendor/select2-4.0.11/select2-4.0.11.css b/src/lib/vendor/select2-4.0.11/select2-4.0.11.css new file mode 100644 index 0000000..750b320 --- /dev/null +++ b/src/lib/vendor/select2-4.0.11/select2-4.0.11.css @@ -0,0 +1,481 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; } + .select2-container .select2-selection--single { + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--single .select2-selection__rendered { + display: block; + padding-left: 8px; + padding-right: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-selection--single .select2-selection__clear { + position: relative; } + .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { + padding-right: 8px; + padding-left: 20px; } + .select2-container .select2-selection--multiple { + box-sizing: border-box; + cursor: pointer; + display: block; + min-height: 32px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--multiple .select2-selection__rendered { + display: inline-block; + overflow: hidden; + padding-left: 8px; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-search--inline { + float: left; } + .select2-container .select2-search--inline .select2-search__field { + box-sizing: border-box; + border: none; + font-size: 100%; + margin-top: 5px; + padding: 0; } + .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + +.select2-dropdown { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: block; + position: absolute; + left: -100000px; + width: 100%; + z-index: 1051; } + +.select2-results { + display: block; } + +.select2-results__options { + list-style: none; + margin: 0; + padding: 0; } + +.select2-results__option { + padding: 6px; + user-select: none; + -webkit-user-select: none; } + .select2-results__option[aria-selected] { + cursor: pointer; } + +.select2-container--open .select2-dropdown { + left: 0; } + +.select2-container--open .select2-dropdown--above { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--open .select2-dropdown--below { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-search--dropdown { + display: block; + padding: 4px; } + .select2-search--dropdown .select2-search__field { + padding: 4px; + width: 100%; + box-sizing: border-box; } + .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + .select2-search--dropdown.select2-search--hide { + display: none; } + +.select2-close-mask { + border: 0; + margin: 0; + padding: 0; + display: block; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 99; + background-color: #fff; + filter: alpha(opacity=0); } + +.select2-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; } + +.select2-container--default .select2-selection--single { + background-color: #fff; + border: 1px solid #aaa; + border-radius: 4px; } + .select2-container--default .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--default .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; } + .select2-container--default .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--default .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; } + .select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; } + +.select2-container--default.select2-container--disabled .select2-selection--single { + background-color: #eee; + cursor: default; } + .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; } + +.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--default .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 5px; + width: 100%; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered li { + list-style: none; } + .select2-container--default .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-top: 5px; + margin-right: 10px; + padding: 1px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: #999; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #333; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--default.select2-container--focus .select2-selection--multiple { + border: solid black 1px; + outline: 0; } + +.select2-container--default.select2-container--disabled .select2-selection--multiple { + background-color: #eee; + cursor: default; } + +.select2-container--default.select2-container--disabled .select2-selection__choice__remove { + display: none; } + +.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--default .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; } + +.select2-container--default .select2-search--inline .select2-search__field { + background: transparent; + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; } + +.select2-container--default .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--default .select2-results__option[role=group] { + padding: 0; } + +.select2-container--default .select2-results__option[aria-disabled=true] { + color: #999; } + +.select2-container--default .select2-results__option[aria-selected=true] { + background-color: #ddd; } + +.select2-container--default .select2-results__option .select2-results__option { + padding-left: 1em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; } + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; } + +.select2-container--default .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic .select2-selection--single { + background-color: #f7f7f7; + border: 1px solid #aaa; + border-radius: 4px; + outline: 0; + background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + .select2-container--classic .select2-selection--single:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--classic .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-right: 10px; } + .select2-container--classic .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--classic .select2-selection--single .select2-selection__arrow { + background-color: #ddd; + border: none; + border-left: 1px solid #aaa; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } + .select2-container--classic .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { + border: none; + border-right: 1px solid #aaa; + border-radius: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + left: 1px; + right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--single { + border: 1px solid #5897fb; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { + background: transparent; + border: none; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } + +.select2-container--classic .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + outline: 0; } + .select2-container--classic .select2-selection--multiple:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--multiple .select2-selection__rendered { + list-style: none; + margin: 0; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__clear { + display: none; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { + color: #888; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #555; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + float: right; + margin-left: 5px; + margin-right: auto; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--multiple { + border: 1px solid #5897fb; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--classic .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; + outline: 0; } + +.select2-container--classic .select2-search--inline .select2-search__field { + outline: 0; + box-shadow: none; } + +.select2-container--classic .select2-dropdown { + background-color: white; + border: 1px solid transparent; } + +.select2-container--classic .select2-dropdown--above { + border-bottom: none; } + +.select2-container--classic .select2-dropdown--below { + border-top: none; } + +.select2-container--classic .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--classic .select2-results__option[role=group] { + padding: 0; } + +.select2-container--classic .select2-results__option[aria-disabled=true] { + color: grey; } + +.select2-container--classic .select2-results__option--highlighted[aria-selected] { + background-color: #3875d7; + color: white; } + +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; } diff --git a/src/lib/vendor/select2-4.0.11/select2-4.0.11.js b/src/lib/vendor/select2-4.0.11/select2-4.0.11.js new file mode 100644 index 0000000..6da089a --- /dev/null +++ b/src/lib/vendor/select2-4.0.11/select2-4.0.11.js @@ -0,0 +1,6044 @@ +/*! + * Select2 4.0.11 + * https://select2.github.io + * + * Released under the MIT license + * https://github.com/select2/select2/blob/master/LICENSE.md + */ +;(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof module === 'object' && module.exports) { + // Node/CommonJS + module.exports = function (root, jQuery) { + if (jQuery === undefined) { + // require('jQuery') returns a factory that requires window to + // build a jQuery instance, we normalize how we use modules + // that require this pattern but the window provided is a noop + // if it's defined (how jquery works) + if (typeof window !== 'undefined') { + jQuery = require('jquery'); + } + else { + jQuery = require('jquery')(root); + } + } + factory(jQuery); + return jQuery; + }; + } else { + // Browser globals + factory(jQuery); + } +} (function (jQuery) { + // This is needed so we can catch the AMD loader configuration and use it + // The inner file should be wrapped (by `banner.start.js`) in a function that + // returns the AMD loader references. + var S2 =(function () { + // Restore the Select2 AMD loader so it can be used + // Needed mostly in the language files, where the loader is not inserted + if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { + var S2 = jQuery.fn.select2.amd; + } +var S2;(function () { if (!S2 || !S2.requirejs) { +if (!S2) { S2 = {}; } else { require = S2; } +/** + * @license almond 0.3.3 Copyright jQuery Foundation and other contributors. + * Released under MIT license, http://github.com/requirejs/almond/LICENSE + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice, + jsSuffixRegExp = /\.js$/; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, lastIndex, + foundI, foundStarMap, starI, i, j, part, normalizedBaseParts, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name) { + name = name.split('/'); + lastIndex = name.length - 1; + + // If wanting node ID compatibility, strip .js from end + // of IDs. Have to do this here, and not in nameToUrl + // because node allows either .js or non .js to map + // to same file. + if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { + name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); + } + + // Starts with a '.' so need the baseName + if (name[0].charAt(0) === '.' && baseParts) { + //Convert baseName to array, and lop off the last part, + //so that . matches that 'directory' and not name of the baseName's + //module. For instance, baseName of 'one/two/three', maps to + //'one/two/three.js', but we want the directory, 'one/two' for + //this normalization. + normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); + name = normalizedBaseParts.concat(name); + } + + //start trimDots + for (i = 0; i < name.length; i++) { + part = name[i]; + if (part === '.') { + name.splice(i, 1); + i -= 1; + } else if (part === '..') { + // If at the start, or previous value is still .., + // keep them so that when converted to a path it may + // still work when converted to a path, even though + // as an ID it is less than ideal. In larger point + // releases, may be better to just kick out an error. + if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') { + continue; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join('/'); + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + var args = aps.call(arguments, 0); + + //If first arg is not require('string'), and there is only + //one arg, it is the array form without a callback. Insert + //a null so that the following concat is correct. + if (typeof args[0] !== 'string' && args.length === 1) { + args.push(null); + } + return req.apply(undef, args.concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + //Creates a parts array for a relName where first part is plugin ID, + //second part is resource ID. Assumes relName has already been normalized. + function makeRelParts(relName) { + return relName ? splitPrefix(relName) : []; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relParts) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0], + relResourceName = relParts[1]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relResourceName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relResourceName)); + } else { + name = normalize(name, relResourceName); + } + } else { + name = normalize(name, relResourceName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, relParts, + args = [], + callbackType = typeof callback, + usingExports; + + //Use name if no relName + relName = relName || name; + relParts = makeRelParts(relName); + + //Call the callback to define the module, if necessary. + if (callbackType === 'undefined' || callbackType === 'function') { + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relParts); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback ? callback.apply(defined[name], args) : undefined; + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, makeRelParts(callback)).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (config.deps) { + req(config.deps, config.callback); + } + if (!callback) { + return; + } + + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + return req(cfg); + }; + + /** + * Expose module registry for debugging and tooling + */ + requirejs._defined = defined; + + define = function (name, deps, callback) { + if (typeof name !== 'string') { + throw new Error('See almond README: incorrect module build, no module name'); + } + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); + +S2.requirejs = requirejs;S2.require = require;S2.define = define; +} +}()); +S2.define("almond", function(){}); + +/* global jQuery:false, $:false */ +S2.define('jquery',[],function () { + var _$ = jQuery || $; + + if (_$ == null && console && console.error) { + console.error( + 'Select2: An instance of jQuery or a jQuery-compatible library was not ' + + 'found. Make sure that you are including jQuery before Select2 on your ' + + 'web page.' + ); + } + + return _$; +}); + +S2.define('select2/utils',[ + 'jquery' +], function ($) { + var Utils = {}; + + Utils.Extend = function (ChildClass, SuperClass) { + var __hasProp = {}.hasOwnProperty; + + function BaseConstructor () { + this.constructor = ChildClass; + } + + for (var key in SuperClass) { + if (__hasProp.call(SuperClass, key)) { + ChildClass[key] = SuperClass[key]; + } + } + + BaseConstructor.prototype = SuperClass.prototype; + ChildClass.prototype = new BaseConstructor(); + ChildClass.__super__ = SuperClass.prototype; + + return ChildClass; + }; + + function getMethods (theClass) { + var proto = theClass.prototype; + + var methods = []; + + for (var methodName in proto) { + var m = proto[methodName]; + + if (typeof m !== 'function') { + continue; + } + + if (methodName === 'constructor') { + continue; + } + + methods.push(methodName); + } + + return methods; + } + + Utils.Decorate = function (SuperClass, DecoratorClass) { + var decoratedMethods = getMethods(DecoratorClass); + var superMethods = getMethods(SuperClass); + + function DecoratedClass () { + var unshift = Array.prototype.unshift; + + var argCount = DecoratorClass.prototype.constructor.length; + + var calledConstructor = SuperClass.prototype.constructor; + + if (argCount > 0) { + unshift.call(arguments, SuperClass.prototype.constructor); + + calledConstructor = DecoratorClass.prototype.constructor; + } + + calledConstructor.apply(this, arguments); + } + + DecoratorClass.displayName = SuperClass.displayName; + + function ctr () { + this.constructor = DecoratedClass; + } + + DecoratedClass.prototype = new ctr(); + + for (var m = 0; m < superMethods.length; m++) { + var superMethod = superMethods[m]; + + DecoratedClass.prototype[superMethod] = + SuperClass.prototype[superMethod]; + } + + var calledMethod = function (methodName) { + // Stub out the original method if it's not decorating an actual method + var originalMethod = function () {}; + + if (methodName in DecoratedClass.prototype) { + originalMethod = DecoratedClass.prototype[methodName]; + } + + var decoratedMethod = DecoratorClass.prototype[methodName]; + + return function () { + var unshift = Array.prototype.unshift; + + unshift.call(arguments, originalMethod); + + return decoratedMethod.apply(this, arguments); + }; + }; + + for (var d = 0; d < decoratedMethods.length; d++) { + var decoratedMethod = decoratedMethods[d]; + + DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod); + } + + return DecoratedClass; + }; + + var Observable = function () { + this.listeners = {}; + }; + + Observable.prototype.on = function (event, callback) { + this.listeners = this.listeners || {}; + + if (event in this.listeners) { + this.listeners[event].push(callback); + } else { + this.listeners[event] = [callback]; + } + }; + + Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + var params = slice.call(arguments, 1); + + this.listeners = this.listeners || {}; + + // Params should always come in as an array + if (params == null) { + params = []; + } + + // If there are no arguments to the event, use a temporary object + if (params.length === 0) { + params.push({}); + } + + // Set the `_type` of the first object to the event + params[0]._type = event; + + if (event in this.listeners) { + this.invoke(this.listeners[event], slice.call(arguments, 1)); + } + + if ('*' in this.listeners) { + this.invoke(this.listeners['*'], arguments); + } + }; + + Observable.prototype.invoke = function (listeners, params) { + for (var i = 0, len = listeners.length; i < len; i++) { + listeners[i].apply(this, params); + } + }; + + Utils.Observable = Observable; + + Utils.generateChars = function (length) { + var chars = ''; + + for (var i = 0; i < length; i++) { + var randomChar = Math.floor(Math.random() * 36); + chars += randomChar.toString(36); + } + + return chars; + }; + + Utils.bind = function (func, context) { + return function () { + func.apply(context, arguments); + }; + }; + + Utils._convertData = function (data) { + for (var originalKey in data) { + var keys = originalKey.split('-'); + + var dataLevel = data; + + if (keys.length === 1) { + continue; + } + + for (var k = 0; k < keys.length; k++) { + var key = keys[k]; + + // Lowercase the first letter + // By default, dash-separated becomes camelCase + key = key.substring(0, 1).toLowerCase() + key.substring(1); + + if (!(key in dataLevel)) { + dataLevel[key] = {}; + } + + if (k == keys.length - 1) { + dataLevel[key] = data[originalKey]; + } + + dataLevel = dataLevel[key]; + } + + delete data[originalKey]; + } + + return data; + }; + + Utils.hasScroll = function (index, el) { + // Adapted from the function created by @ShadowScripter + // and adapted by @BillBarry on the Stack Exchange Code Review website. + // The original code can be found at + // http://codereview.stackexchange.com/q/13338 + // and was designed to be used with the Sizzle selector engine. + + var $el = $(el); + var overflowX = el.style.overflowX; + var overflowY = el.style.overflowY; + + //Check both x and y declarations + if (overflowX === overflowY && + (overflowY === 'hidden' || overflowY === 'visible')) { + return false; + } + + if (overflowX === 'scroll' || overflowY === 'scroll') { + return true; + } + + return ($el.innerHeight() < el.scrollHeight || + $el.innerWidth() < el.scrollWidth); + }; + + Utils.escapeMarkup = function (markup) { + var replaceMap = { + '\\': '\', + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '/': '/' + }; + + // Do not try to escape the markup if it's not a string + if (typeof markup !== 'string') { + return markup; + } + + return String(markup).replace(/[&<>"'\/\\]/g, function (match) { + return replaceMap[match]; + }); + }; + + // Append an array of jQuery nodes to a given element. + Utils.appendMany = function ($element, $nodes) { + // jQuery 1.7.x does not support $.fn.append() with an array + // Fall back to a jQuery object collection using $.fn.add() + if ($.fn.jquery.substr(0, 3) === '1.7') { + var $jqNodes = $(); + + $.map($nodes, function (node) { + $jqNodes = $jqNodes.add(node); + }); + + $nodes = $jqNodes; + } + + $element.append($nodes); + }; + + // Cache objects in Utils.__cache instead of $.data (see #4346) + Utils.__cache = {}; + + var id = 0; + Utils.GetUniqueElementId = function (element) { + // Get a unique element Id. If element has no id, + // creates a new unique number, stores it in the id + // attribute and returns the new id. + // If an id already exists, it simply returns it. + + var select2Id = element.getAttribute('data-select2-id'); + if (select2Id == null) { + // If element has id, use it. + if (element.id) { + select2Id = element.id; + element.setAttribute('data-select2-id', select2Id); + } else { + element.setAttribute('data-select2-id', ++id); + select2Id = id.toString(); + } + } + return select2Id; + }; + + Utils.StoreData = function (element, name, value) { + // Stores an item in the cache for a specified element. + // name is the cache key. + var id = Utils.GetUniqueElementId(element); + if (!Utils.__cache[id]) { + Utils.__cache[id] = {}; + } + + Utils.__cache[id][name] = value; + }; + + Utils.GetData = function (element, name) { + // Retrieves a value from the cache by its key (name) + // name is optional. If no name specified, return + // all cache items for the specified element. + // and for a specified element. + var id = Utils.GetUniqueElementId(element); + if (name) { + if (Utils.__cache[id]) { + if (Utils.__cache[id][name] != null) { + return Utils.__cache[id][name]; + } + return $(element).data(name); // Fallback to HTML5 data attribs. + } + return $(element).data(name); // Fallback to HTML5 data attribs. + } else { + return Utils.__cache[id]; + } + }; + + Utils.RemoveData = function (element) { + // Removes all cached items for a specified element. + var id = Utils.GetUniqueElementId(element); + if (Utils.__cache[id] != null) { + delete Utils.__cache[id]; + } + + element.removeAttribute('data-select2-id'); + }; + + return Utils; +}); + +S2.define('select2/results',[ + 'jquery', + './utils' +], function ($, Utils) { + function Results ($element, options, dataAdapter) { + this.$element = $element; + this.data = dataAdapter; + this.options = options; + + Results.__super__.constructor.call(this); + } + + Utils.Extend(Results, Utils.Observable); + + Results.prototype.render = function () { + var $results = $( + '<ul class="select2-results__options" role="listbox"></ul>' + ); + + if (this.options.get('multiple')) { + $results.attr('aria-multiselectable', 'true'); + } + + this.$results = $results; + + return $results; + }; + + Results.prototype.clear = function () { + this.$results.empty(); + }; + + Results.prototype.displayMessage = function (params) { + var escapeMarkup = this.options.get('escapeMarkup'); + + this.clear(); + this.hideLoading(); + + var $message = $( + '<li role="alert" aria-live="assertive"' + + ' class="select2-results__option"></li>' + ); + + var message = this.options.get('translations').get(params.message); + + $message.append( + escapeMarkup( + message(params.args) + ) + ); + + $message[0].className += ' select2-results__message'; + + this.$results.append($message); + }; + + Results.prototype.hideMessages = function () { + this.$results.find('.select2-results__message').remove(); + }; + + Results.prototype.append = function (data) { + this.hideLoading(); + + var $options = []; + + if (data.results == null || data.results.length === 0) { + if (this.$results.children().length === 0) { + this.trigger('results:message', { + message: 'noResults' + }); + } + + return; + } + + data.results = this.sort(data.results); + + for (var d = 0; d < data.results.length; d++) { + var item = data.results[d]; + + var $option = this.option(item); + + $options.push($option); + } + + this.$results.append($options); + }; + + Results.prototype.position = function ($results, $dropdown) { + var $resultsContainer = $dropdown.find('.select2-results'); + $resultsContainer.append($results); + }; + + Results.prototype.sort = function (data) { + var sorter = this.options.get('sorter'); + + return sorter(data); + }; + + Results.prototype.highlightFirstItem = function () { + var $options = this.$results + .find('.select2-results__option[aria-selected]'); + + var $selected = $options.filter('[aria-selected=true]'); + + // Check if there are any selected options + if ($selected.length > 0) { + // If there are selected options, highlight the first + $selected.first().trigger('mouseenter'); + } else { + // If there are no selected options, highlight the first option + // in the dropdown + $options.first().trigger('mouseenter'); + } + + this.ensureHighlightVisible(); + }; + + Results.prototype.setClasses = function () { + var self = this; + + this.data.current(function (selected) { + var selectedIds = $.map(selected, function (s) { + return s.id.toString(); + }); + + var $options = self.$results + .find('.select2-results__option[aria-selected]'); + + $options.each(function () { + var $option = $(this); + + var item = Utils.GetData(this, 'data'); + + // id needs to be converted to a string when comparing + var id = '' + item.id; + + if ((item.element != null && item.element.selected) || + (item.element == null && $.inArray(id, selectedIds) > -1)) { + $option.attr('aria-selected', 'true'); + } else { + $option.attr('aria-selected', 'false'); + } + }); + + }); + }; + + Results.prototype.showLoading = function (params) { + this.hideLoading(); + + var loadingMore = this.options.get('translations').get('searching'); + + var loading = { + disabled: true, + loading: true, + text: loadingMore(params) + }; + var $loading = this.option(loading); + $loading.className += ' loading-results'; + + this.$results.prepend($loading); + }; + + Results.prototype.hideLoading = function () { + this.$results.find('.loading-results').remove(); + }; + + Results.prototype.option = function (data) { + var option = document.createElement('li'); + option.className = 'select2-results__option'; + + var attrs = { + 'role': 'option', + 'aria-selected': 'false' + }; + + var matches = window.Element.prototype.matches || + window.Element.prototype.msMatchesSelector || + window.Element.prototype.webkitMatchesSelector; + + if ((data.element != null && matches.call(data.element, ':disabled')) || + (data.element == null && data.disabled)) { + delete attrs['aria-selected']; + attrs['aria-disabled'] = 'true'; + } + + if (data.id == null) { + delete attrs['aria-selected']; + } + + if (data._resultId != null) { + option.id = data._resultId; + } + + if (data.title) { + option.title = data.title; + } + + if (data.children) { + attrs.role = 'group'; + attrs['aria-label'] = data.text; + delete attrs['aria-selected']; + } + + for (var attr in attrs) { + var val = attrs[attr]; + + option.setAttribute(attr, val); + } + + if (data.children) { + var $option = $(option); + + var label = document.createElement('strong'); + label.className = 'select2-results__group'; + + var $label = $(label); + this.template(data, label); + + var $children = []; + + for (var c = 0; c < data.children.length; c++) { + var child = data.children[c]; + + var $child = this.option(child); + + $children.push($child); + } + + var $childrenContainer = $('<ul></ul>', { + 'class': 'select2-results__options select2-results__options--nested' + }); + + $childrenContainer.append($children); + + $option.append(label); + $option.append($childrenContainer); + } else { + this.template(data, option); + } + + Utils.StoreData(option, 'data', data); + + return option; + }; + + Results.prototype.bind = function (container, $container) { + var self = this; + + var id = container.id + '-results'; + + this.$results.attr('id', id); + + container.on('results:all', function (params) { + self.clear(); + self.append(params.data); + + if (container.isOpen()) { + self.setClasses(); + self.highlightFirstItem(); + } + }); + + container.on('results:append', function (params) { + self.append(params.data); + + if (container.isOpen()) { + self.setClasses(); + } + }); + + container.on('query', function (params) { + self.hideMessages(); + self.showLoading(params); + }); + + container.on('select', function () { + if (!container.isOpen()) { + return; + } + + self.setClasses(); + + if (self.options.get('scrollAfterSelect')) { + self.highlightFirstItem(); + } + }); + + container.on('unselect', function () { + if (!container.isOpen()) { + return; + } + + self.setClasses(); + + if (self.options.get('scrollAfterSelect')) { + self.highlightFirstItem(); + } + }); + + container.on('open', function () { + // When the dropdown is open, aria-expended="true" + self.$results.attr('aria-expanded', 'true'); + self.$results.attr('aria-hidden', 'false'); + + self.setClasses(); + self.ensureHighlightVisible(); + }); + + container.on('close', function () { + // When the dropdown is closed, aria-expended="false" + self.$results.attr('aria-expanded', 'false'); + self.$results.attr('aria-hidden', 'true'); + self.$results.removeAttr('aria-activedescendant'); + }); + + container.on('results:toggle', function () { + var $highlighted = self.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + $highlighted.trigger('mouseup'); + }); + + container.on('results:select', function () { + var $highlighted = self.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + var data = Utils.GetData($highlighted[0], 'data'); + + if ($highlighted.attr('aria-selected') == 'true') { + self.trigger('close', {}); + } else { + self.trigger('select', { + data: data + }); + } + }); + + container.on('results:previous', function () { + var $highlighted = self.getHighlightedResults(); + + var $options = self.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + // If we are already at the top, don't move further + // If no options, currentIndex will be -1 + if (currentIndex <= 0) { + return; + } + + var nextIndex = currentIndex - 1; + + // If none are highlighted, highlight the first + if ($highlighted.length === 0) { + nextIndex = 0; + } + + var $next = $options.eq(nextIndex); + + $next.trigger('mouseenter'); + + var currentOffset = self.$results.offset().top; + var nextTop = $next.offset().top; + var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset); + + if (nextIndex === 0) { + self.$results.scrollTop(0); + } else if (nextTop - currentOffset < 0) { + self.$results.scrollTop(nextOffset); + } + }); + + container.on('results:next', function () { + var $highlighted = self.getHighlightedResults(); + + var $options = self.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + var nextIndex = currentIndex + 1; + + // If we are at the last option, stay there + if (nextIndex >= $options.length) { + return; + } + + var $next = $options.eq(nextIndex); + + $next.trigger('mouseenter'); + + var currentOffset = self.$results.offset().top + + self.$results.outerHeight(false); + var nextBottom = $next.offset().top + $next.outerHeight(false); + var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset; + + if (nextIndex === 0) { + self.$results.scrollTop(0); + } else if (nextBottom > currentOffset) { + self.$results.scrollTop(nextOffset); + } + }); + + container.on('results:focus', function (params) { + params.element.addClass('select2-results__option--highlighted'); + }); + + container.on('results:message', function (params) { + self.displayMessage(params); + }); + + if ($.fn.mousewheel) { + this.$results.on('mousewheel', function (e) { + var top = self.$results.scrollTop(); + + var bottom = self.$results.get(0).scrollHeight - top + e.deltaY; + + var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0; + var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height(); + + if (isAtTop) { + self.$results.scrollTop(0); + + e.preventDefault(); + e.stopPropagation(); + } else if (isAtBottom) { + self.$results.scrollTop( + self.$results.get(0).scrollHeight - self.$results.height() + ); + + e.preventDefault(); + e.stopPropagation(); + } + }); + } + + this.$results.on('mouseup', '.select2-results__option[aria-selected]', + function (evt) { + var $this = $(this); + + var data = Utils.GetData(this, 'data'); + + if ($this.attr('aria-selected') === 'true') { + if (self.options.get('multiple')) { + self.trigger('unselect', { + originalEvent: evt, + data: data + }); + } else { + self.trigger('close', {}); + } + + return; + } + + self.trigger('select', { + originalEvent: evt, + data: data + }); + }); + + this.$results.on('mouseenter', '.select2-results__option[aria-selected]', + function (evt) { + var data = Utils.GetData(this, 'data'); + + self.getHighlightedResults() + .removeClass('select2-results__option--highlighted'); + + self.trigger('results:focus', { + data: data, + element: $(this) + }); + }); + }; + + Results.prototype.getHighlightedResults = function () { + var $highlighted = this.$results + .find('.select2-results__option--highlighted'); + + return $highlighted; + }; + + Results.prototype.destroy = function () { + this.$results.remove(); + }; + + Results.prototype.ensureHighlightVisible = function () { + var $highlighted = this.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + var $options = this.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + var currentOffset = this.$results.offset().top; + var nextTop = $highlighted.offset().top; + var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset); + + var offsetDelta = nextTop - currentOffset; + nextOffset -= $highlighted.outerHeight(false) * 2; + + if (currentIndex <= 2) { + this.$results.scrollTop(0); + } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) { + this.$results.scrollTop(nextOffset); + } + }; + + Results.prototype.template = function (result, container) { + var template = this.options.get('templateResult'); + var escapeMarkup = this.options.get('escapeMarkup'); + + var content = template(result, container); + + if (content == null) { + container.style.display = 'none'; + } else if (typeof content === 'string') { + container.innerHTML = escapeMarkup(content); + } else { + $(container).append(content); + } + }; + + return Results; +}); + +S2.define('select2/keys',[ + +], function () { + var KEYS = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + DELETE: 46 + }; + + return KEYS; +}); + +S2.define('select2/selection/base',[ + 'jquery', + '../utils', + '../keys' +], function ($, Utils, KEYS) { + function BaseSelection ($element, options) { + this.$element = $element; + this.options = options; + + BaseSelection.__super__.constructor.call(this); + } + + Utils.Extend(BaseSelection, Utils.Observable); + + BaseSelection.prototype.render = function () { + var $selection = $( + '<span class="select2-selection" role="combobox" ' + + ' aria-haspopup="true" aria-expanded="false">' + + '</span>' + ); + + this._tabindex = 0; + + if (Utils.GetData(this.$element[0], 'old-tabindex') != null) { + this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex'); + } else if (this.$element.attr('tabindex') != null) { + this._tabindex = this.$element.attr('tabindex'); + } + + $selection.attr('title', this.$element.attr('title')); + $selection.attr('tabindex', this._tabindex); + $selection.attr('aria-disabled', 'false'); + + this.$selection = $selection; + + return $selection; + }; + + BaseSelection.prototype.bind = function (container, $container) { + var self = this; + + var resultsId = container.id + '-results'; + + this.container = container; + + this.$selection.on('focus', function (evt) { + self.trigger('focus', evt); + }); + + this.$selection.on('blur', function (evt) { + self._handleBlur(evt); + }); + + this.$selection.on('keydown', function (evt) { + self.trigger('keypress', evt); + + if (evt.which === KEYS.SPACE) { + evt.preventDefault(); + } + }); + + container.on('results:focus', function (params) { + self.$selection.attr('aria-activedescendant', params.data._resultId); + }); + + container.on('selection:update', function (params) { + self.update(params.data); + }); + + container.on('open', function () { + // When the dropdown is open, aria-expanded="true" + self.$selection.attr('aria-expanded', 'true'); + self.$selection.attr('aria-owns', resultsId); + + self._attachCloseHandler(container); + }); + + container.on('close', function () { + // When the dropdown is closed, aria-expanded="false" + self.$selection.attr('aria-expanded', 'false'); + self.$selection.removeAttr('aria-activedescendant'); + self.$selection.removeAttr('aria-owns'); + + self.$selection.trigger('focus'); + + self._detachCloseHandler(container); + }); + + container.on('enable', function () { + self.$selection.attr('tabindex', self._tabindex); + self.$selection.attr('aria-disabled', 'false'); + }); + + container.on('disable', function () { + self.$selection.attr('tabindex', '-1'); + self.$selection.attr('aria-disabled', 'true'); + }); + }; + + BaseSelection.prototype._handleBlur = function (evt) { + var self = this; + + // This needs to be delayed as the active element is the body when the tab + // key is pressed, possibly along with others. + window.setTimeout(function () { + // Don't trigger `blur` if the focus is still in the selection + if ( + (document.activeElement == self.$selection[0]) || + ($.contains(self.$selection[0], document.activeElement)) + ) { + return; + } + + self.trigger('blur', evt); + }, 1); + }; + + BaseSelection.prototype._attachCloseHandler = function (container) { + + $(document.body).on('mousedown.select2.' + container.id, function (e) { + var $target = $(e.target); + + var $select = $target.closest('.select2'); + + var $all = $('.select2.select2-container--open'); + + $all.each(function () { + if (this == $select[0]) { + return; + } + + var $element = Utils.GetData(this, 'element'); + + $element.select2('close'); + }); + }); + }; + + BaseSelection.prototype._detachCloseHandler = function (container) { + $(document.body).off('mousedown.select2.' + container.id); + }; + + BaseSelection.prototype.position = function ($selection, $container) { + var $selectionContainer = $container.find('.selection'); + $selectionContainer.append($selection); + }; + + BaseSelection.prototype.destroy = function () { + this._detachCloseHandler(this.container); + }; + + BaseSelection.prototype.update = function (data) { + throw new Error('The `update` method must be defined in child classes.'); + }; + + return BaseSelection; +}); + +S2.define('select2/selection/single',[ + 'jquery', + './base', + '../utils', + '../keys' +], function ($, BaseSelection, Utils, KEYS) { + function SingleSelection () { + SingleSelection.__super__.constructor.apply(this, arguments); + } + + Utils.Extend(SingleSelection, BaseSelection); + + SingleSelection.prototype.render = function () { + var $selection = SingleSelection.__super__.render.call(this); + + $selection.addClass('select2-selection--single'); + + $selection.html( + '<span class="select2-selection__rendered"></span>' + + '<span class="select2-selection__arrow" role="presentation">' + + '<b role="presentation"></b>' + + '</span>' + ); + + return $selection; + }; + + SingleSelection.prototype.bind = function (container, $container) { + var self = this; + + SingleSelection.__super__.bind.apply(this, arguments); + + var id = container.id + '-container'; + + this.$selection.find('.select2-selection__rendered') + .attr('id', id) + .attr('role', 'textbox') + .attr('aria-readonly', 'true'); + this.$selection.attr('aria-labelledby', id); + + this.$selection.on('mousedown', function (evt) { + // Only respond to left clicks + if (evt.which !== 1) { + return; + } + + self.trigger('toggle', { + originalEvent: evt + }); + }); + + this.$selection.on('focus', function (evt) { + // User focuses on the container + }); + + this.$selection.on('blur', function (evt) { + // User exits the container + }); + + container.on('focus', function (evt) { + if (!container.isOpen()) { + self.$selection.trigger('focus'); + } + }); + }; + + SingleSelection.prototype.clear = function () { + var $rendered = this.$selection.find('.select2-selection__rendered'); + $rendered.empty(); + $rendered.removeAttr('title'); // clear tooltip on empty + }; + + SingleSelection.prototype.display = function (data, container) { + var template = this.options.get('templateSelection'); + var escapeMarkup = this.options.get('escapeMarkup'); + + return escapeMarkup(template(data, container)); + }; + + SingleSelection.prototype.selectionContainer = function () { + return $('<span></span>'); + }; + + SingleSelection.prototype.update = function (data) { + if (data.length === 0) { + this.clear(); + return; + } + + var selection = data[0]; + + var $rendered = this.$selection.find('.select2-selection__rendered'); + var formatted = this.display(selection, $rendered); + + $rendered.empty().append(formatted); + + var title = selection.title || selection.text; + + if (title) { + $rendered.attr('title', title); + } else { + $rendered.removeAttr('title'); + } + }; + + return SingleSelection; +}); + +S2.define('select2/selection/multiple',[ + 'jquery', + './base', + '../utils' +], function ($, BaseSelection, Utils) { + function MultipleSelection ($element, options) { + MultipleSelection.__super__.constructor.apply(this, arguments); + } + + Utils.Extend(MultipleSelection, BaseSelection); + + MultipleSelection.prototype.render = function () { + var $selection = MultipleSelection.__super__.render.call(this); + + $selection.addClass('select2-selection--multiple'); + + $selection.html( + '<ul class="select2-selection__rendered"></ul>' + ); + + return $selection; + }; + + MultipleSelection.prototype.bind = function (container, $container) { + var self = this; + + MultipleSelection.__super__.bind.apply(this, arguments); + + this.$selection.on('click', function (evt) { + self.trigger('toggle', { + originalEvent: evt + }); + }); + + this.$selection.on( + 'click', + '.select2-selection__choice__remove', + function (evt) { + // Ignore the event if it is disabled + if (self.options.get('disabled')) { + return; + } + + var $remove = $(this); + var $selection = $remove.parent(); + + var data = Utils.GetData($selection[0], 'data'); + + self.trigger('unselect', { + originalEvent: evt, + data: data + }); + } + ); + }; + + MultipleSelection.prototype.clear = function () { + var $rendered = this.$selection.find('.select2-selection__rendered'); + $rendered.empty(); + $rendered.removeAttr('title'); + }; + + MultipleSelection.prototype.display = function (data, container) { + var template = this.options.get('templateSelection'); + var escapeMarkup = this.options.get('escapeMarkup'); + + return escapeMarkup(template(data, container)); + }; + + MultipleSelection.prototype.selectionContainer = function () { + var $container = $( + '<li class="select2-selection__choice">' + + '<span class="select2-selection__choice__remove" role="presentation">' + + '×' + + '</span>' + + '</li>' + ); + + return $container; + }; + + MultipleSelection.prototype.update = function (data) { + this.clear(); + + if (data.length === 0) { + return; + } + + var $selections = []; + + for (var d = 0; d < data.length; d++) { + var selection = data[d]; + + var $selection = this.selectionContainer(); + var formatted = this.display(selection, $selection); + + $selection.append(formatted); + + var title = selection.title || selection.text; + + if (title) { + $selection.attr('title', title); + } + + Utils.StoreData($selection[0], 'data', selection); + + $selections.push($selection); + } + + var $rendered = this.$selection.find('.select2-selection__rendered'); + + Utils.appendMany($rendered, $selections); + }; + + return MultipleSelection; +}); + +S2.define('select2/selection/placeholder',[ + '../utils' +], function (Utils) { + function Placeholder (decorated, $element, options) { + this.placeholder = this.normalizePlaceholder(options.get('placeholder')); + + decorated.call(this, $element, options); + } + + Placeholder.prototype.normalizePlaceholder = function (_, placeholder) { + if (typeof placeholder === 'string') { + placeholder = { + id: '', + text: placeholder + }; + } + + return placeholder; + }; + + Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { + var $placeholder = this.selectionContainer(); + + $placeholder.html(this.display(placeholder)); + $placeholder.addClass('select2-selection__placeholder') + .removeClass('select2-selection__choice'); + + return $placeholder; + }; + + Placeholder.prototype.update = function (decorated, data) { + var singlePlaceholder = ( + data.length == 1 && data[0].id != this.placeholder.id + ); + var multipleSelections = data.length > 1; + + if (multipleSelections || singlePlaceholder) { + return decorated.call(this, data); + } + + this.clear(); + + var $placeholder = this.createPlaceholder(this.placeholder); + + this.$selection.find('.select2-selection__rendered').append($placeholder); + }; + + return Placeholder; +}); + +S2.define('select2/selection/allowClear',[ + 'jquery', + '../keys', + '../utils' +], function ($, KEYS, Utils) { + function AllowClear () { } + + AllowClear.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + if (this.placeholder == null) { + if (this.options.get('debug') && window.console && console.error) { + console.error( + 'Select2: The `allowClear` option should be used in combination ' + + 'with the `placeholder` option.' + ); + } + } + + this.$selection.on('mousedown', '.select2-selection__clear', + function (evt) { + self._handleClear(evt); + }); + + container.on('keypress', function (evt) { + self._handleKeyboardClear(evt, container); + }); + }; + + AllowClear.prototype._handleClear = function (_, evt) { + // Ignore the event if it is disabled + if (this.options.get('disabled')) { + return; + } + + var $clear = this.$selection.find('.select2-selection__clear'); + + // Ignore the event if nothing has been selected + if ($clear.length === 0) { + return; + } + + evt.stopPropagation(); + + var data = Utils.GetData($clear[0], 'data'); + + var previousVal = this.$element.val(); + this.$element.val(this.placeholder.id); + + var unselectData = { + data: data + }; + this.trigger('clear', unselectData); + if (unselectData.prevented) { + this.$element.val(previousVal); + return; + } + + for (var d = 0; d < data.length; d++) { + unselectData = { + data: data[d] + }; + + // Trigger the `unselect` event, so people can prevent it from being + // cleared. + this.trigger('unselect', unselectData); + + // If the event was prevented, don't clear it out. + if (unselectData.prevented) { + this.$element.val(previousVal); + return; + } + } + + this.$element.trigger('change'); + + this.trigger('toggle', {}); + }; + + AllowClear.prototype._handleKeyboardClear = function (_, evt, container) { + if (container.isOpen()) { + return; + } + + if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) { + this._handleClear(evt); + } + }; + + AllowClear.prototype.update = function (decorated, data) { + decorated.call(this, data); + + if (this.$selection.find('.select2-selection__placeholder').length > 0 || + data.length === 0) { + return; + } + + var removeAll = this.options.get('translations').get('removeAllItems'); + + var $remove = $( + '<span class="select2-selection__clear" title="' + removeAll() +'">' + + '×' + + '</span>' + ); + Utils.StoreData($remove[0], 'data', data); + + this.$selection.find('.select2-selection__rendered').prepend($remove); + }; + + return AllowClear; +}); + +S2.define('select2/selection/search',[ + 'jquery', + '../utils', + '../keys' +], function ($, Utils, KEYS) { + function Search (decorated, $element, options) { + decorated.call(this, $element, options); + } + + Search.prototype.render = function (decorated) { + var $search = $( + '<li class="select2-search select2-search--inline">' + + '<input class="select2-search__field" type="search" tabindex="-1"' + + ' autocomplete="off" autocorrect="off" autocapitalize="none"' + + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' + + '</li>' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + var $rendered = decorated.call(this); + + this._transferTabIndex(); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + var resultsId = container.id + '-results'; + + decorated.call(this, container, $container); + + container.on('open', function () { + self.$search.attr('aria-controls', resultsId); + self.$search.trigger('focus'); + }); + + container.on('close', function () { + self.$search.val(''); + self.$search.removeAttr('aria-controls'); + self.$search.removeAttr('aria-activedescendant'); + self.$search.trigger('focus'); + }); + + container.on('enable', function () { + self.$search.prop('disabled', false); + + self._transferTabIndex(); + }); + + container.on('disable', function () { + self.$search.prop('disabled', true); + }); + + container.on('focus', function (evt) { + self.$search.trigger('focus'); + }); + + container.on('results:focus', function (params) { + if (params.data._resultId) { + self.$search.attr('aria-activedescendant', params.data._resultId); + } else { + self.$search.removeAttr('aria-activedescendant'); + } + }); + + this.$selection.on('focusin', '.select2-search--inline', function (evt) { + self.trigger('focus', evt); + }); + + this.$selection.on('focusout', '.select2-search--inline', function (evt) { + self._handleBlur(evt); + }); + + this.$selection.on('keydown', '.select2-search--inline', function (evt) { + evt.stopPropagation(); + + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + + var key = evt.which; + + if (key === KEYS.BACKSPACE && self.$search.val() === '') { + var $previousChoice = self.$searchContainer + .prev('.select2-selection__choice'); + + if ($previousChoice.length > 0) { + var item = Utils.GetData($previousChoice[0], 'data'); + + self.searchRemoveChoice(item); + + evt.preventDefault(); + } + } + }); + + this.$selection.on('click', '.select2-search--inline', function (evt) { + if (self.$search.val()) { + evt.stopPropagation(); + } + }); + + // Try to detect the IE version should the `documentMode` property that + // is stored on the document. This is only implemented in IE and is + // slightly cleaner than doing a user agent check. + // This property is not available in Edge, but Edge also doesn't have + // this bug. + var msie = document.documentMode; + var disableInputEvents = msie && msie <= 11; + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$selection.on( + 'input.searchcheck', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents) { + self.$selection.off('input.search input.searchcheck'); + return; + } + + // Unbind the duplicated `keyup` event + self.$selection.off('keyup.search'); + } + ); + + this.$selection.on( + 'keyup.search input.search', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents && evt.type === 'input') { + self.$selection.off('input.search input.searchcheck'); + return; + } + + var key = evt.which; + + // We can freely ignore events from modifier keys + if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { + return; + } + + // Tabbing will be handled during the `keydown` phase + if (key == KEYS.TAB) { + return; + } + + self.handleSearch(evt); + } + ); + }; + + /** + * This method will transfer the tabindex attribute from the rendered + * selection to the search box. This allows for the search box to be used as + * the primary focus instead of the selection container. + * + * @private + */ + Search.prototype._transferTabIndex = function (decorated) { + this.$search.attr('tabindex', this.$selection.attr('tabindex')); + this.$selection.attr('tabindex', '-1'); + }; + + Search.prototype.createPlaceholder = function (decorated, placeholder) { + this.$search.attr('placeholder', placeholder.text); + }; + + Search.prototype.update = function (decorated, data) { + var searchHadFocus = this.$search[0] == document.activeElement; + + this.$search.attr('placeholder', ''); + + decorated.call(this, data); + + this.$selection.find('.select2-selection__rendered') + .append(this.$searchContainer); + + this.resizeSearch(); + if (searchHadFocus) { + this.$search.trigger('focus'); + } + }; + + Search.prototype.handleSearch = function () { + this.resizeSearch(); + + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.searchRemoveChoice = function (decorated, item) { + this.trigger('unselect', { + data: item + }); + + this.$search.val(item.text); + this.handleSearch(); + }; + + Search.prototype.resizeSearch = function () { + this.$search.css('width', '25px'); + + var width = ''; + + if (this.$search.attr('placeholder') !== '') { + width = this.$selection.find('.select2-selection__rendered').width(); + } else { + var minimumWidth = this.$search.val().length + 1; + + width = (minimumWidth * 0.75) + 'em'; + } + + this.$search.css('width', width); + }; + + return Search; +}); + +S2.define('select2/selection/eventRelay',[ + 'jquery' +], function ($) { + function EventRelay () { } + + EventRelay.prototype.bind = function (decorated, container, $container) { + var self = this; + var relayEvents = [ + 'open', 'opening', + 'close', 'closing', + 'select', 'selecting', + 'unselect', 'unselecting', + 'clear', 'clearing' + ]; + + var preventableEvents = [ + 'opening', 'closing', 'selecting', 'unselecting', 'clearing' + ]; + + decorated.call(this, container, $container); + + container.on('*', function (name, params) { + // Ignore events that should not be relayed + if ($.inArray(name, relayEvents) === -1) { + return; + } + + // The parameters should always be an object + params = params || {}; + + // Generate the jQuery event for the Select2 event + var evt = $.Event('select2:' + name, { + params: params + }); + + self.$element.trigger(evt); + + // Only handle preventable events if it was one + if ($.inArray(name, preventableEvents) === -1) { + return; + } + + params.prevented = evt.isDefaultPrevented(); + }); + }; + + return EventRelay; +}); + +S2.define('select2/translation',[ + 'jquery', + 'require' +], function ($, require) { + function Translation (dict) { + this.dict = dict || {}; + } + + Translation.prototype.all = function () { + return this.dict; + }; + + Translation.prototype.get = function (key) { + return this.dict[key]; + }; + + Translation.prototype.extend = function (translation) { + this.dict = $.extend({}, translation.all(), this.dict); + }; + + // Static functions + + Translation._cache = {}; + + Translation.loadPath = function (path) { + if (!(path in Translation._cache)) { + var translations = require(path); + + Translation._cache[path] = translations; + } + + return new Translation(Translation._cache[path]); + }; + + return Translation; +}); + +S2.define('select2/diacritics',[ + +], function () { + var diacritics = { + '\u24B6': 'A', + '\uFF21': 'A', + '\u00C0': 'A', + '\u00C1': 'A', + '\u00C2': 'A', + '\u1EA6': 'A', + '\u1EA4': 'A', + '\u1EAA': 'A', + '\u1EA8': 'A', + '\u00C3': 'A', + '\u0100': 'A', + '\u0102': 'A', + '\u1EB0': 'A', + '\u1EAE': 'A', + '\u1EB4': 'A', + '\u1EB2': 'A', + '\u0226': 'A', + '\u01E0': 'A', + '\u00C4': 'A', + '\u01DE': 'A', + '\u1EA2': 'A', + '\u00C5': 'A', + '\u01FA': 'A', + '\u01CD': 'A', + '\u0200': 'A', + '\u0202': 'A', + '\u1EA0': 'A', + '\u1EAC': 'A', + '\u1EB6': 'A', + '\u1E00': 'A', + '\u0104': 'A', + '\u023A': 'A', + '\u2C6F': 'A', + '\uA732': 'AA', + '\u00C6': 'AE', + '\u01FC': 'AE', + '\u01E2': 'AE', + '\uA734': 'AO', + '\uA736': 'AU', + '\uA738': 'AV', + '\uA73A': 'AV', + '\uA73C': 'AY', + '\u24B7': 'B', + '\uFF22': 'B', + '\u1E02': 'B', + '\u1E04': 'B', + '\u1E06': 'B', + '\u0243': 'B', + '\u0182': 'B', + '\u0181': 'B', + '\u24B8': 'C', + '\uFF23': 'C', + '\u0106': 'C', + '\u0108': 'C', + '\u010A': 'C', + '\u010C': 'C', + '\u00C7': 'C', + '\u1E08': 'C', + '\u0187': 'C', + '\u023B': 'C', + '\uA73E': 'C', + '\u24B9': 'D', + '\uFF24': 'D', + '\u1E0A': 'D', + '\u010E': 'D', + '\u1E0C': 'D', + '\u1E10': 'D', + '\u1E12': 'D', + '\u1E0E': 'D', + '\u0110': 'D', + '\u018B': 'D', + '\u018A': 'D', + '\u0189': 'D', + '\uA779': 'D', + '\u01F1': 'DZ', + '\u01C4': 'DZ', + '\u01F2': 'Dz', + '\u01C5': 'Dz', + '\u24BA': 'E', + '\uFF25': 'E', + '\u00C8': 'E', + '\u00C9': 'E', + '\u00CA': 'E', + '\u1EC0': 'E', + '\u1EBE': 'E', + '\u1EC4': 'E', + '\u1EC2': 'E', + '\u1EBC': 'E', + '\u0112': 'E', + '\u1E14': 'E', + '\u1E16': 'E', + '\u0114': 'E', + '\u0116': 'E', + '\u00CB': 'E', + '\u1EBA': 'E', + '\u011A': 'E', + '\u0204': 'E', + '\u0206': 'E', + '\u1EB8': 'E', + '\u1EC6': 'E', + '\u0228': 'E', + '\u1E1C': 'E', + '\u0118': 'E', + '\u1E18': 'E', + '\u1E1A': 'E', + '\u0190': 'E', + '\u018E': 'E', + '\u24BB': 'F', + '\uFF26': 'F', + '\u1E1E': 'F', + '\u0191': 'F', + '\uA77B': 'F', + '\u24BC': 'G', + '\uFF27': 'G', + '\u01F4': 'G', + '\u011C': 'G', + '\u1E20': 'G', + '\u011E': 'G', + '\u0120': 'G', + '\u01E6': 'G', + '\u0122': 'G', + '\u01E4': 'G', + '\u0193': 'G', + '\uA7A0': 'G', + '\uA77D': 'G', + '\uA77E': 'G', + '\u24BD': 'H', + '\uFF28': 'H', + '\u0124': 'H', + '\u1E22': 'H', + '\u1E26': 'H', + '\u021E': 'H', + '\u1E24': 'H', + '\u1E28': 'H', + '\u1E2A': 'H', + '\u0126': 'H', + '\u2C67': 'H', + '\u2C75': 'H', + '\uA78D': 'H', + '\u24BE': 'I', + '\uFF29': 'I', + '\u00CC': 'I', + '\u00CD': 'I', + '\u00CE': 'I', + '\u0128': 'I', + '\u012A': 'I', + '\u012C': 'I', + '\u0130': 'I', + '\u00CF': 'I', + '\u1E2E': 'I', + '\u1EC8': 'I', + '\u01CF': 'I', + '\u0208': 'I', + '\u020A': 'I', + '\u1ECA': 'I', + '\u012E': 'I', + '\u1E2C': 'I', + '\u0197': 'I', + '\u24BF': 'J', + '\uFF2A': 'J', + '\u0134': 'J', + '\u0248': 'J', + '\u24C0': 'K', + '\uFF2B': 'K', + '\u1E30': 'K', + '\u01E8': 'K', + '\u1E32': 'K', + '\u0136': 'K', + '\u1E34': 'K', + '\u0198': 'K', + '\u2C69': 'K', + '\uA740': 'K', + '\uA742': 'K', + '\uA744': 'K', + '\uA7A2': 'K', + '\u24C1': 'L', + '\uFF2C': 'L', + '\u013F': 'L', + '\u0139': 'L', + '\u013D': 'L', + '\u1E36': 'L', + '\u1E38': 'L', + '\u013B': 'L', + '\u1E3C': 'L', + '\u1E3A': 'L', + '\u0141': 'L', + '\u023D': 'L', + '\u2C62': 'L', + '\u2C60': 'L', + '\uA748': 'L', + '\uA746': 'L', + '\uA780': 'L', + '\u01C7': 'LJ', + '\u01C8': 'Lj', + '\u24C2': 'M', + '\uFF2D': 'M', + '\u1E3E': 'M', + '\u1E40': 'M', + '\u1E42': 'M', + '\u2C6E': 'M', + '\u019C': 'M', + '\u24C3': 'N', + '\uFF2E': 'N', + '\u01F8': 'N', + '\u0143': 'N', + '\u00D1': 'N', + '\u1E44': 'N', + '\u0147': 'N', + '\u1E46': 'N', + '\u0145': 'N', + '\u1E4A': 'N', + '\u1E48': 'N', + '\u0220': 'N', + '\u019D': 'N', + '\uA790': 'N', + '\uA7A4': 'N', + '\u01CA': 'NJ', + '\u01CB': 'Nj', + '\u24C4': 'O', + '\uFF2F': 'O', + '\u00D2': 'O', + '\u00D3': 'O', + '\u00D4': 'O', + '\u1ED2': 'O', + '\u1ED0': 'O', + '\u1ED6': 'O', + '\u1ED4': 'O', + '\u00D5': 'O', + '\u1E4C': 'O', + '\u022C': 'O', + '\u1E4E': 'O', + '\u014C': 'O', + '\u1E50': 'O', + '\u1E52': 'O', + '\u014E': 'O', + '\u022E': 'O', + '\u0230': 'O', + '\u00D6': 'O', + '\u022A': 'O', + '\u1ECE': 'O', + '\u0150': 'O', + '\u01D1': 'O', + '\u020C': 'O', + '\u020E': 'O', + '\u01A0': 'O', + '\u1EDC': 'O', + '\u1EDA': 'O', + '\u1EE0': 'O', + '\u1EDE': 'O', + '\u1EE2': 'O', + '\u1ECC': 'O', + '\u1ED8': 'O', + '\u01EA': 'O', + '\u01EC': 'O', + '\u00D8': 'O', + '\u01FE': 'O', + '\u0186': 'O', + '\u019F': 'O', + '\uA74A': 'O', + '\uA74C': 'O', + '\u0152': 'OE', + '\u01A2': 'OI', + '\uA74E': 'OO', + '\u0222': 'OU', + '\u24C5': 'P', + '\uFF30': 'P', + '\u1E54': 'P', + '\u1E56': 'P', + '\u01A4': 'P', + '\u2C63': 'P', + '\uA750': 'P', + '\uA752': 'P', + '\uA754': 'P', + '\u24C6': 'Q', + '\uFF31': 'Q', + '\uA756': 'Q', + '\uA758': 'Q', + '\u024A': 'Q', + '\u24C7': 'R', + '\uFF32': 'R', + '\u0154': 'R', + '\u1E58': 'R', + '\u0158': 'R', + '\u0210': 'R', + '\u0212': 'R', + '\u1E5A': 'R', + '\u1E5C': 'R', + '\u0156': 'R', + '\u1E5E': 'R', + '\u024C': 'R', + '\u2C64': 'R', + '\uA75A': 'R', + '\uA7A6': 'R', + '\uA782': 'R', + '\u24C8': 'S', + '\uFF33': 'S', + '\u1E9E': 'S', + '\u015A': 'S', + '\u1E64': 'S', + '\u015C': 'S', + '\u1E60': 'S', + '\u0160': 'S', + '\u1E66': 'S', + '\u1E62': 'S', + '\u1E68': 'S', + '\u0218': 'S', + '\u015E': 'S', + '\u2C7E': 'S', + '\uA7A8': 'S', + '\uA784': 'S', + '\u24C9': 'T', + '\uFF34': 'T', + '\u1E6A': 'T', + '\u0164': 'T', + '\u1E6C': 'T', + '\u021A': 'T', + '\u0162': 'T', + '\u1E70': 'T', + '\u1E6E': 'T', + '\u0166': 'T', + '\u01AC': 'T', + '\u01AE': 'T', + '\u023E': 'T', + '\uA786': 'T', + '\uA728': 'TZ', + '\u24CA': 'U', + '\uFF35': 'U', + '\u00D9': 'U', + '\u00DA': 'U', + '\u00DB': 'U', + '\u0168': 'U', + '\u1E78': 'U', + '\u016A': 'U', + '\u1E7A': 'U', + '\u016C': 'U', + '\u00DC': 'U', + '\u01DB': 'U', + '\u01D7': 'U', + '\u01D5': 'U', + '\u01D9': 'U', + '\u1EE6': 'U', + '\u016E': 'U', + '\u0170': 'U', + '\u01D3': 'U', + '\u0214': 'U', + '\u0216': 'U', + '\u01AF': 'U', + '\u1EEA': 'U', + '\u1EE8': 'U', + '\u1EEE': 'U', + '\u1EEC': 'U', + '\u1EF0': 'U', + '\u1EE4': 'U', + '\u1E72': 'U', + '\u0172': 'U', + '\u1E76': 'U', + '\u1E74': 'U', + '\u0244': 'U', + '\u24CB': 'V', + '\uFF36': 'V', + '\u1E7C': 'V', + '\u1E7E': 'V', + '\u01B2': 'V', + '\uA75E': 'V', + '\u0245': 'V', + '\uA760': 'VY', + '\u24CC': 'W', + '\uFF37': 'W', + '\u1E80': 'W', + '\u1E82': 'W', + '\u0174': 'W', + '\u1E86': 'W', + '\u1E84': 'W', + '\u1E88': 'W', + '\u2C72': 'W', + '\u24CD': 'X', + '\uFF38': 'X', + '\u1E8A': 'X', + '\u1E8C': 'X', + '\u24CE': 'Y', + '\uFF39': 'Y', + '\u1EF2': 'Y', + '\u00DD': 'Y', + '\u0176': 'Y', + '\u1EF8': 'Y', + '\u0232': 'Y', + '\u1E8E': 'Y', + '\u0178': 'Y', + '\u1EF6': 'Y', + '\u1EF4': 'Y', + '\u01B3': 'Y', + '\u024E': 'Y', + '\u1EFE': 'Y', + '\u24CF': 'Z', + '\uFF3A': 'Z', + '\u0179': 'Z', + '\u1E90': 'Z', + '\u017B': 'Z', + '\u017D': 'Z', + '\u1E92': 'Z', + '\u1E94': 'Z', + '\u01B5': 'Z', + '\u0224': 'Z', + '\u2C7F': 'Z', + '\u2C6B': 'Z', + '\uA762': 'Z', + '\u24D0': 'a', + '\uFF41': 'a', + '\u1E9A': 'a', + '\u00E0': 'a', + '\u00E1': 'a', + '\u00E2': 'a', + '\u1EA7': 'a', + '\u1EA5': 'a', + '\u1EAB': 'a', + '\u1EA9': 'a', + '\u00E3': 'a', + '\u0101': 'a', + '\u0103': 'a', + '\u1EB1': 'a', + '\u1EAF': 'a', + '\u1EB5': 'a', + '\u1EB3': 'a', + '\u0227': 'a', + '\u01E1': 'a', + '\u00E4': 'a', + '\u01DF': 'a', + '\u1EA3': 'a', + '\u00E5': 'a', + '\u01FB': 'a', + '\u01CE': 'a', + '\u0201': 'a', + '\u0203': 'a', + '\u1EA1': 'a', + '\u1EAD': 'a', + '\u1EB7': 'a', + '\u1E01': 'a', + '\u0105': 'a', + '\u2C65': 'a', + '\u0250': 'a', + '\uA733': 'aa', + '\u00E6': 'ae', + '\u01FD': 'ae', + '\u01E3': 'ae', + '\uA735': 'ao', + '\uA737': 'au', + '\uA739': 'av', + '\uA73B': 'av', + '\uA73D': 'ay', + '\u24D1': 'b', + '\uFF42': 'b', + '\u1E03': 'b', + '\u1E05': 'b', + '\u1E07': 'b', + '\u0180': 'b', + '\u0183': 'b', + '\u0253': 'b', + '\u24D2': 'c', + '\uFF43': 'c', + '\u0107': 'c', + '\u0109': 'c', + '\u010B': 'c', + '\u010D': 'c', + '\u00E7': 'c', + '\u1E09': 'c', + '\u0188': 'c', + '\u023C': 'c', + '\uA73F': 'c', + '\u2184': 'c', + '\u24D3': 'd', + '\uFF44': 'd', + '\u1E0B': 'd', + '\u010F': 'd', + '\u1E0D': 'd', + '\u1E11': 'd', + '\u1E13': 'd', + '\u1E0F': 'd', + '\u0111': 'd', + '\u018C': 'd', + '\u0256': 'd', + '\u0257': 'd', + '\uA77A': 'd', + '\u01F3': 'dz', + '\u01C6': 'dz', + '\u24D4': 'e', + '\uFF45': 'e', + '\u00E8': 'e', + '\u00E9': 'e', + '\u00EA': 'e', + '\u1EC1': 'e', + '\u1EBF': 'e', + '\u1EC5': 'e', + '\u1EC3': 'e', + '\u1EBD': 'e', + '\u0113': 'e', + '\u1E15': 'e', + '\u1E17': 'e', + '\u0115': 'e', + '\u0117': 'e', + '\u00EB': 'e', + '\u1EBB': 'e', + '\u011B': 'e', + '\u0205': 'e', + '\u0207': 'e', + '\u1EB9': 'e', + '\u1EC7': 'e', + '\u0229': 'e', + '\u1E1D': 'e', + '\u0119': 'e', + '\u1E19': 'e', + '\u1E1B': 'e', + '\u0247': 'e', + '\u025B': 'e', + '\u01DD': 'e', + '\u24D5': 'f', + '\uFF46': 'f', + '\u1E1F': 'f', + '\u0192': 'f', + '\uA77C': 'f', + '\u24D6': 'g', + '\uFF47': 'g', + '\u01F5': 'g', + '\u011D': 'g', + '\u1E21': 'g', + '\u011F': 'g', + '\u0121': 'g', + '\u01E7': 'g', + '\u0123': 'g', + '\u01E5': 'g', + '\u0260': 'g', + '\uA7A1': 'g', + '\u1D79': 'g', + '\uA77F': 'g', + '\u24D7': 'h', + '\uFF48': 'h', + '\u0125': 'h', + '\u1E23': 'h', + '\u1E27': 'h', + '\u021F': 'h', + '\u1E25': 'h', + '\u1E29': 'h', + '\u1E2B': 'h', + '\u1E96': 'h', + '\u0127': 'h', + '\u2C68': 'h', + '\u2C76': 'h', + '\u0265': 'h', + '\u0195': 'hv', + '\u24D8': 'i', + '\uFF49': 'i', + '\u00EC': 'i', + '\u00ED': 'i', + '\u00EE': 'i', + '\u0129': 'i', + '\u012B': 'i', + '\u012D': 'i', + '\u00EF': 'i', + '\u1E2F': 'i', + '\u1EC9': 'i', + '\u01D0': 'i', + '\u0209': 'i', + '\u020B': 'i', + '\u1ECB': 'i', + '\u012F': 'i', + '\u1E2D': 'i', + '\u0268': 'i', + '\u0131': 'i', + '\u24D9': 'j', + '\uFF4A': 'j', + '\u0135': 'j', + '\u01F0': 'j', + '\u0249': 'j', + '\u24DA': 'k', + '\uFF4B': 'k', + '\u1E31': 'k', + '\u01E9': 'k', + '\u1E33': 'k', + '\u0137': 'k', + '\u1E35': 'k', + '\u0199': 'k', + '\u2C6A': 'k', + '\uA741': 'k', + '\uA743': 'k', + '\uA745': 'k', + '\uA7A3': 'k', + '\u24DB': 'l', + '\uFF4C': 'l', + '\u0140': 'l', + '\u013A': 'l', + '\u013E': 'l', + '\u1E37': 'l', + '\u1E39': 'l', + '\u013C': 'l', + '\u1E3D': 'l', + '\u1E3B': 'l', + '\u017F': 'l', + '\u0142': 'l', + '\u019A': 'l', + '\u026B': 'l', + '\u2C61': 'l', + '\uA749': 'l', + '\uA781': 'l', + '\uA747': 'l', + '\u01C9': 'lj', + '\u24DC': 'm', + '\uFF4D': 'm', + '\u1E3F': 'm', + '\u1E41': 'm', + '\u1E43': 'm', + '\u0271': 'm', + '\u026F': 'm', + '\u24DD': 'n', + '\uFF4E': 'n', + '\u01F9': 'n', + '\u0144': 'n', + '\u00F1': 'n', + '\u1E45': 'n', + '\u0148': 'n', + '\u1E47': 'n', + '\u0146': 'n', + '\u1E4B': 'n', + '\u1E49': 'n', + '\u019E': 'n', + '\u0272': 'n', + '\u0149': 'n', + '\uA791': 'n', + '\uA7A5': 'n', + '\u01CC': 'nj', + '\u24DE': 'o', + '\uFF4F': 'o', + '\u00F2': 'o', + '\u00F3': 'o', + '\u00F4': 'o', + '\u1ED3': 'o', + '\u1ED1': 'o', + '\u1ED7': 'o', + '\u1ED5': 'o', + '\u00F5': 'o', + '\u1E4D': 'o', + '\u022D': 'o', + '\u1E4F': 'o', + '\u014D': 'o', + '\u1E51': 'o', + '\u1E53': 'o', + '\u014F': 'o', + '\u022F': 'o', + '\u0231': 'o', + '\u00F6': 'o', + '\u022B': 'o', + '\u1ECF': 'o', + '\u0151': 'o', + '\u01D2': 'o', + '\u020D': 'o', + '\u020F': 'o', + '\u01A1': 'o', + '\u1EDD': 'o', + '\u1EDB': 'o', + '\u1EE1': 'o', + '\u1EDF': 'o', + '\u1EE3': 'o', + '\u1ECD': 'o', + '\u1ED9': 'o', + '\u01EB': 'o', + '\u01ED': 'o', + '\u00F8': 'o', + '\u01FF': 'o', + '\u0254': 'o', + '\uA74B': 'o', + '\uA74D': 'o', + '\u0275': 'o', + '\u0153': 'oe', + '\u01A3': 'oi', + '\u0223': 'ou', + '\uA74F': 'oo', + '\u24DF': 'p', + '\uFF50': 'p', + '\u1E55': 'p', + '\u1E57': 'p', + '\u01A5': 'p', + '\u1D7D': 'p', + '\uA751': 'p', + '\uA753': 'p', + '\uA755': 'p', + '\u24E0': 'q', + '\uFF51': 'q', + '\u024B': 'q', + '\uA757': 'q', + '\uA759': 'q', + '\u24E1': 'r', + '\uFF52': 'r', + '\u0155': 'r', + '\u1E59': 'r', + '\u0159': 'r', + '\u0211': 'r', + '\u0213': 'r', + '\u1E5B': 'r', + '\u1E5D': 'r', + '\u0157': 'r', + '\u1E5F': 'r', + '\u024D': 'r', + '\u027D': 'r', + '\uA75B': 'r', + '\uA7A7': 'r', + '\uA783': 'r', + '\u24E2': 's', + '\uFF53': 's', + '\u00DF': 's', + '\u015B': 's', + '\u1E65': 's', + '\u015D': 's', + '\u1E61': 's', + '\u0161': 's', + '\u1E67': 's', + '\u1E63': 's', + '\u1E69': 's', + '\u0219': 's', + '\u015F': 's', + '\u023F': 's', + '\uA7A9': 's', + '\uA785': 's', + '\u1E9B': 's', + '\u24E3': 't', + '\uFF54': 't', + '\u1E6B': 't', + '\u1E97': 't', + '\u0165': 't', + '\u1E6D': 't', + '\u021B': 't', + '\u0163': 't', + '\u1E71': 't', + '\u1E6F': 't', + '\u0167': 't', + '\u01AD': 't', + '\u0288': 't', + '\u2C66': 't', + '\uA787': 't', + '\uA729': 'tz', + '\u24E4': 'u', + '\uFF55': 'u', + '\u00F9': 'u', + '\u00FA': 'u', + '\u00FB': 'u', + '\u0169': 'u', + '\u1E79': 'u', + '\u016B': 'u', + '\u1E7B': 'u', + '\u016D': 'u', + '\u00FC': 'u', + '\u01DC': 'u', + '\u01D8': 'u', + '\u01D6': 'u', + '\u01DA': 'u', + '\u1EE7': 'u', + '\u016F': 'u', + '\u0171': 'u', + '\u01D4': 'u', + '\u0215': 'u', + '\u0217': 'u', + '\u01B0': 'u', + '\u1EEB': 'u', + '\u1EE9': 'u', + '\u1EEF': 'u', + '\u1EED': 'u', + '\u1EF1': 'u', + '\u1EE5': 'u', + '\u1E73': 'u', + '\u0173': 'u', + '\u1E77': 'u', + '\u1E75': 'u', + '\u0289': 'u', + '\u24E5': 'v', + '\uFF56': 'v', + '\u1E7D': 'v', + '\u1E7F': 'v', + '\u028B': 'v', + '\uA75F': 'v', + '\u028C': 'v', + '\uA761': 'vy', + '\u24E6': 'w', + '\uFF57': 'w', + '\u1E81': 'w', + '\u1E83': 'w', + '\u0175': 'w', + '\u1E87': 'w', + '\u1E85': 'w', + '\u1E98': 'w', + '\u1E89': 'w', + '\u2C73': 'w', + '\u24E7': 'x', + '\uFF58': 'x', + '\u1E8B': 'x', + '\u1E8D': 'x', + '\u24E8': 'y', + '\uFF59': 'y', + '\u1EF3': 'y', + '\u00FD': 'y', + '\u0177': 'y', + '\u1EF9': 'y', + '\u0233': 'y', + '\u1E8F': 'y', + '\u00FF': 'y', + '\u1EF7': 'y', + '\u1E99': 'y', + '\u1EF5': 'y', + '\u01B4': 'y', + '\u024F': 'y', + '\u1EFF': 'y', + '\u24E9': 'z', + '\uFF5A': 'z', + '\u017A': 'z', + '\u1E91': 'z', + '\u017C': 'z', + '\u017E': 'z', + '\u1E93': 'z', + '\u1E95': 'z', + '\u01B6': 'z', + '\u0225': 'z', + '\u0240': 'z', + '\u2C6C': 'z', + '\uA763': 'z', + '\u0386': '\u0391', + '\u0388': '\u0395', + '\u0389': '\u0397', + '\u038A': '\u0399', + '\u03AA': '\u0399', + '\u038C': '\u039F', + '\u038E': '\u03A5', + '\u03AB': '\u03A5', + '\u038F': '\u03A9', + '\u03AC': '\u03B1', + '\u03AD': '\u03B5', + '\u03AE': '\u03B7', + '\u03AF': '\u03B9', + '\u03CA': '\u03B9', + '\u0390': '\u03B9', + '\u03CC': '\u03BF', + '\u03CD': '\u03C5', + '\u03CB': '\u03C5', + '\u03B0': '\u03C5', + '\u03CE': '\u03C9', + '\u03C2': '\u03C3', + '\u2019': '\'' + }; + + return diacritics; +}); + +S2.define('select2/data/base',[ + '../utils' +], function (Utils) { + function BaseAdapter ($element, options) { + BaseAdapter.__super__.constructor.call(this); + } + + Utils.Extend(BaseAdapter, Utils.Observable); + + BaseAdapter.prototype.current = function (callback) { + throw new Error('The `current` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.query = function (params, callback) { + throw new Error('The `query` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.bind = function (container, $container) { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.destroy = function () { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.generateResultId = function (container, data) { + var id = container.id + '-result-'; + + id += Utils.generateChars(4); + + if (data.id != null) { + id += '-' + data.id.toString(); + } else { + id += '-' + Utils.generateChars(4); + } + return id; + }; + + return BaseAdapter; +}); + +S2.define('select2/data/select',[ + './base', + '../utils', + 'jquery' +], function (BaseAdapter, Utils, $) { + function SelectAdapter ($element, options) { + this.$element = $element; + this.options = options; + + SelectAdapter.__super__.constructor.call(this); + } + + Utils.Extend(SelectAdapter, BaseAdapter); + + SelectAdapter.prototype.current = function (callback) { + var data = []; + var self = this; + + this.$element.find(':selected').each(function () { + var $option = $(this); + + var option = self.item($option); + + data.push(option); + }); + + callback(data); + }; + + SelectAdapter.prototype.select = function (data) { + var self = this; + + data.selected = true; + + // If data.element is a DOM node, use it instead + if ($(data.element).is('option')) { + data.element.selected = true; + + this.$element.trigger('change'); + + return; + } + + if (this.$element.prop('multiple')) { + this.current(function (currentData) { + var val = []; + + data = [data]; + data.push.apply(data, currentData); + + for (var d = 0; d < data.length; d++) { + var id = data[d].id; + + if ($.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + self.$element.trigger('change'); + }); + } else { + var val = data.id; + + this.$element.val(val); + this.$element.trigger('change'); + } + }; + + SelectAdapter.prototype.unselect = function (data) { + var self = this; + + if (!this.$element.prop('multiple')) { + return; + } + + data.selected = false; + + if ($(data.element).is('option')) { + data.element.selected = false; + + this.$element.trigger('change'); + + return; + } + + this.current(function (currentData) { + var val = []; + + for (var d = 0; d < currentData.length; d++) { + var id = currentData[d].id; + + if (id !== data.id && $.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + + self.$element.trigger('change'); + }); + }; + + SelectAdapter.prototype.bind = function (container, $container) { + var self = this; + + this.container = container; + + container.on('select', function (params) { + self.select(params.data); + }); + + container.on('unselect', function (params) { + self.unselect(params.data); + }); + }; + + SelectAdapter.prototype.destroy = function () { + // Remove anything added to child elements + this.$element.find('*').each(function () { + // Remove any custom data set by Select2 + Utils.RemoveData(this); + }); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + var $options = this.$element.children(); + + $options.each(function () { + var $option = $(this); + + if (!$option.is('option') && !$option.is('optgroup')) { + return; + } + + var option = self.item($option); + + var matches = self.matches(params, option); + + if (matches !== null) { + data.push(matches); + } + }); + + callback({ + results: data + }); + }; + + SelectAdapter.prototype.addOptions = function ($options) { + Utils.appendMany(this.$element, $options); + }; + + SelectAdapter.prototype.option = function (data) { + var option; + + if (data.children) { + option = document.createElement('optgroup'); + option.label = data.text; + } else { + option = document.createElement('option'); + + if (option.textContent !== undefined) { + option.textContent = data.text; + } else { + option.innerText = data.text; + } + } + + if (data.id !== undefined) { + option.value = data.id; + } + + if (data.disabled) { + option.disabled = true; + } + + if (data.selected) { + option.selected = true; + } + + if (data.title) { + option.title = data.title; + } + + var $option = $(option); + + var normalizedData = this._normalizeItem(data); + normalizedData.element = option; + + // Override the option's data with the combined data + Utils.StoreData(option, 'data', normalizedData); + + return $option; + }; + + SelectAdapter.prototype.item = function ($option) { + var data = {}; + + data = Utils.GetData($option[0], 'data'); + + if (data != null) { + return data; + } + + if ($option.is('option')) { + data = { + id: $option.val(), + text: $option.text(), + disabled: $option.prop('disabled'), + selected: $option.prop('selected'), + title: $option.prop('title') + }; + } else if ($option.is('optgroup')) { + data = { + text: $option.prop('label'), + children: [], + title: $option.prop('title') + }; + + var $children = $option.children('option'); + var children = []; + + for (var c = 0; c < $children.length; c++) { + var $child = $($children[c]); + + var child = this.item($child); + + children.push(child); + } + + data.children = children; + } + + data = this._normalizeItem(data); + data.element = $option[0]; + + Utils.StoreData($option[0], 'data', data); + + return data; + }; + + SelectAdapter.prototype._normalizeItem = function (item) { + if (item !== Object(item)) { + item = { + id: item, + text: item + }; + } + + item = $.extend({}, { + text: '' + }, item); + + var defaults = { + selected: false, + disabled: false + }; + + if (item.id != null) { + item.id = item.id.toString(); + } + + if (item.text != null) { + item.text = item.text.toString(); + } + + if (item._resultId == null && item.id && this.container != null) { + item._resultId = this.generateResultId(this.container, item); + } + + return $.extend({}, defaults, item); + }; + + SelectAdapter.prototype.matches = function (params, data) { + var matcher = this.options.get('matcher'); + + return matcher(params, data); + }; + + return SelectAdapter; +}); + +S2.define('select2/data/array',[ + './select', + '../utils', + 'jquery' +], function (SelectAdapter, Utils, $) { + function ArrayAdapter ($element, options) { + this._dataToConvert = options.get('data') || []; + + ArrayAdapter.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(ArrayAdapter, SelectAdapter); + + ArrayAdapter.prototype.bind = function (container, $container) { + ArrayAdapter.__super__.bind.call(this, container, $container); + + this.addOptions(this.convertToOptions(this._dataToConvert)); + }; + + ArrayAdapter.prototype.select = function (data) { + var $option = this.$element.find('option').filter(function (i, elm) { + return elm.value == data.id.toString(); + }); + + if ($option.length === 0) { + $option = this.option(data); + + this.addOptions($option); + } + + ArrayAdapter.__super__.select.call(this, data); + }; + + ArrayAdapter.prototype.convertToOptions = function (data) { + var self = this; + + var $existing = this.$element.find('option'); + var existingIds = $existing.map(function () { + return self.item($(this)).id; + }).get(); + + var $options = []; + + // Filter out all items except for the one passed in the argument + function onlyItem (item) { + return function () { + return $(this).val() == item.id; + }; + } + + for (var d = 0; d < data.length; d++) { + var item = this._normalizeItem(data[d]); + + // Skip items which were pre-loaded, only merge the data + if ($.inArray(item.id, existingIds) >= 0) { + var $existingOption = $existing.filter(onlyItem(item)); + + var existingData = this.item($existingOption); + var newData = $.extend(true, {}, item, existingData); + + var $newOption = this.option(newData); + + $existingOption.replaceWith($newOption); + + continue; + } + + var $option = this.option(item); + + if (item.children) { + var $children = this.convertToOptions(item.children); + + Utils.appendMany($option, $children); + } + + $options.push($option); + } + + return $options; + }; + + return ArrayAdapter; +}); + +S2.define('select2/data/ajax',[ + './array', + '../utils', + 'jquery' +], function (ArrayAdapter, Utils, $) { + function AjaxAdapter ($element, options) { + this.ajaxOptions = this._applyDefaults(options.get('ajax')); + + if (this.ajaxOptions.processResults != null) { + this.processResults = this.ajaxOptions.processResults; + } + + AjaxAdapter.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(AjaxAdapter, ArrayAdapter); + + AjaxAdapter.prototype._applyDefaults = function (options) { + var defaults = { + data: function (params) { + return $.extend({}, params, { + q: params.term + }); + }, + transport: function (params, success, failure) { + var $request = $.ajax(params); + + $request.then(success); + $request.fail(failure); + + return $request; + } + }; + + return $.extend({}, defaults, options, true); + }; + + AjaxAdapter.prototype.processResults = function (results) { + return results; + }; + + AjaxAdapter.prototype.query = function (params, callback) { + var matches = []; + var self = this; + + if (this._request != null) { + // JSONP requests cannot always be aborted + if ($.isFunction(this._request.abort)) { + this._request.abort(); + } + + this._request = null; + } + + var options = $.extend({ + type: 'GET' + }, this.ajaxOptions); + + if (typeof options.url === 'function') { + options.url = options.url.call(this.$element, params); + } + + if (typeof options.data === 'function') { + options.data = options.data.call(this.$element, params); + } + + function request () { + var $request = options.transport(options, function (data) { + var results = self.processResults(data, params); + + if (self.options.get('debug') && window.console && console.error) { + // Check to make sure that the response included a `results` key. + if (!results || !results.results || !$.isArray(results.results)) { + console.error( + 'Select2: The AJAX results did not return an array in the ' + + '`results` key of the response.' + ); + } + } + + callback(results); + }, function () { + // Attempt to detect if a request was aborted + // Only works if the transport exposes a status property + if ('status' in $request && + ($request.status === 0 || $request.status === '0')) { + return; + } + + self.trigger('results:message', { + message: 'errorLoading' + }); + }); + + self._request = $request; + } + + if (this.ajaxOptions.delay && params.term != null) { + if (this._queryTimeout) { + window.clearTimeout(this._queryTimeout); + } + + this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); + } else { + request(); + } + }; + + return AjaxAdapter; +}); + +S2.define('select2/data/tags',[ + 'jquery' +], function ($) { + function Tags (decorated, $element, options) { + var tags = options.get('tags'); + + var createTag = options.get('createTag'); + + if (createTag !== undefined) { + this.createTag = createTag; + } + + var insertTag = options.get('insertTag'); + + if (insertTag !== undefined) { + this.insertTag = insertTag; + } + + decorated.call(this, $element, options); + + if ($.isArray(tags)) { + for (var t = 0; t < tags.length; t++) { + var tag = tags[t]; + var item = this._normalizeItem(tag); + + var $option = this.option(item); + + this.$element.append($option); + } + } + } + + Tags.prototype.query = function (decorated, params, callback) { + var self = this; + + this._removeOldTags(); + + if (params.term == null || params.page != null) { + decorated.call(this, params, callback); + return; + } + + function wrapper (obj, child) { + var data = obj.results; + + for (var i = 0; i < data.length; i++) { + var option = data[i]; + + var checkChildren = ( + option.children != null && + !wrapper({ + results: option.children + }, true) + ); + + var optionText = (option.text || '').toUpperCase(); + var paramsTerm = (params.term || '').toUpperCase(); + + var checkText = optionText === paramsTerm; + + if (checkText || checkChildren) { + if (child) { + return false; + } + + obj.data = data; + callback(obj); + + return; + } + } + + if (child) { + return true; + } + + var tag = self.createTag(params); + + if (tag != null) { + var $option = self.option(tag); + $option.attr('data-select2-tag', true); + + self.addOptions([$option]); + + self.insertTag(data, tag); + } + + obj.results = data; + + callback(obj); + } + + decorated.call(this, params, wrapper); + }; + + Tags.prototype.createTag = function (decorated, params) { + var term = $.trim(params.term); + + if (term === '') { + return null; + } + + return { + id: term, + text: term + }; + }; + + Tags.prototype.insertTag = function (_, data, tag) { + data.unshift(tag); + }; + + Tags.prototype._removeOldTags = function (_) { + var $options = this.$element.find('option[data-select2-tag]'); + + $options.each(function () { + if (this.selected) { + return; + } + + $(this).remove(); + }); + }; + + return Tags; +}); + +S2.define('select2/data/tokenizer',[ + 'jquery' +], function ($) { + function Tokenizer (decorated, $element, options) { + var tokenizer = options.get('tokenizer'); + + if (tokenizer !== undefined) { + this.tokenizer = tokenizer; + } + + decorated.call(this, $element, options); + } + + Tokenizer.prototype.bind = function (decorated, container, $container) { + decorated.call(this, container, $container); + + this.$search = container.dropdown.$search || container.selection.$search || + $container.find('.select2-search__field'); + }; + + Tokenizer.prototype.query = function (decorated, params, callback) { + var self = this; + + function createAndSelect (data) { + // Normalize the data object so we can use it for checks + var item = self._normalizeItem(data); + + // Check if the data object already exists as a tag + // Select it if it doesn't + var $existingOptions = self.$element.find('option').filter(function () { + return $(this).val() === item.id; + }); + + // If an existing option wasn't found for it, create the option + if (!$existingOptions.length) { + var $option = self.option(item); + $option.attr('data-select2-tag', true); + + self._removeOldTags(); + self.addOptions([$option]); + } + + // Select the item, now that we know there is an option for it + select(item); + } + + function select (data) { + self.trigger('select', { + data: data + }); + } + + params.term = params.term || ''; + + var tokenData = this.tokenizer(params, this.options, createAndSelect); + + if (tokenData.term !== params.term) { + // Replace the search term if we have the search box + if (this.$search.length) { + this.$search.val(tokenData.term); + this.$search.trigger('focus'); + } + + params.term = tokenData.term; + } + + decorated.call(this, params, callback); + }; + + Tokenizer.prototype.tokenizer = function (_, params, options, callback) { + var separators = options.get('tokenSeparators') || []; + var term = params.term; + var i = 0; + + var createTag = this.createTag || function (params) { + return { + id: params.term, + text: params.term + }; + }; + + while (i < term.length) { + var termChar = term[i]; + + if ($.inArray(termChar, separators) === -1) { + i++; + + continue; + } + + var part = term.substr(0, i); + var partParams = $.extend({}, params, { + term: part + }); + + var data = createTag(partParams); + + if (data == null) { + i++; + continue; + } + + callback(data); + + // Reset the term to not include the tokenized portion + term = term.substr(i + 1) || ''; + i = 0; + } + + return { + term: term + }; + }; + + return Tokenizer; +}); + +S2.define('select2/data/minimumInputLength',[ + +], function () { + function MinimumInputLength (decorated, $e, options) { + this.minimumInputLength = options.get('minimumInputLength'); + + decorated.call(this, $e, options); + } + + MinimumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (params.term.length < this.minimumInputLength) { + this.trigger('results:message', { + message: 'inputTooShort', + args: { + minimum: this.minimumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MinimumInputLength; +}); + +S2.define('select2/data/maximumInputLength',[ + +], function () { + function MaximumInputLength (decorated, $e, options) { + this.maximumInputLength = options.get('maximumInputLength'); + + decorated.call(this, $e, options); + } + + MaximumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (this.maximumInputLength > 0 && + params.term.length > this.maximumInputLength) { + this.trigger('results:message', { + message: 'inputTooLong', + args: { + maximum: this.maximumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MaximumInputLength; +}); + +S2.define('select2/data/maximumSelectionLength',[ + +], function (){ + function MaximumSelectionLength (decorated, $e, options) { + this.maximumSelectionLength = options.get('maximumSelectionLength'); + + decorated.call(this, $e, options); + } + + MaximumSelectionLength.prototype.bind = + function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('select', function () { + self._checkIfMaximumSelected(); + }); + }; + + MaximumSelectionLength.prototype.query = + function (decorated, params, callback) { + var self = this; + + this._checkIfMaximumSelected(function () { + decorated.call(self, params, callback); + }); + }; + + MaximumSelectionLength.prototype._checkIfMaximumSelected = + function (_, successCallback) { + var self = this; + + this.current(function (currentData) { + var count = currentData != null ? currentData.length : 0; + if (self.maximumSelectionLength > 0 && + count >= self.maximumSelectionLength) { + self.trigger('results:message', { + message: 'maximumSelected', + args: { + maximum: self.maximumSelectionLength + } + }); + return; + } + + if (successCallback) { + successCallback(); + } + }); + }; + + return MaximumSelectionLength; +}); + +S2.define('select2/dropdown',[ + 'jquery', + './utils' +], function ($, Utils) { + function Dropdown ($element, options) { + this.$element = $element; + this.options = options; + + Dropdown.__super__.constructor.call(this); + } + + Utils.Extend(Dropdown, Utils.Observable); + + Dropdown.prototype.render = function () { + var $dropdown = $( + '<span class="select2-dropdown">' + + '<span class="select2-results"></span>' + + '</span>' + ); + + $dropdown.attr('dir', this.options.get('dir')); + + this.$dropdown = $dropdown; + + return $dropdown; + }; + + Dropdown.prototype.bind = function () { + // Should be implemented in subclasses + }; + + Dropdown.prototype.position = function ($dropdown, $container) { + // Should be implemented in subclasses + }; + + Dropdown.prototype.destroy = function () { + // Remove the dropdown from the DOM + this.$dropdown.remove(); + }; + + return Dropdown; +}); + +S2.define('select2/dropdown/search',[ + 'jquery', + '../utils' +], function ($, Utils) { + function Search () { } + + Search.prototype.render = function (decorated) { + var $rendered = decorated.call(this); + + var $search = $( + '<span class="select2-search select2-search--dropdown">' + + '<input class="select2-search__field" type="search" tabindex="-1"' + + ' autocomplete="off" autocorrect="off" autocapitalize="none"' + + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' + + '</span>' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + $rendered.prepend($search); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + var resultsId = container.id + '-results'; + + decorated.call(this, container, $container); + + this.$search.on('keydown', function (evt) { + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + }); + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$search.on('input', function (evt) { + // Unbind the duplicated `keyup` event + $(this).off('keyup'); + }); + + this.$search.on('keyup input', function (evt) { + self.handleSearch(evt); + }); + + container.on('open', function () { + self.$search.attr('tabindex', 0); + self.$search.attr('aria-controls', resultsId); + + self.$search.trigger('focus'); + + window.setTimeout(function () { + self.$search.trigger('focus'); + }, 0); + }); + + container.on('close', function () { + self.$search.attr('tabindex', -1); + self.$search.removeAttr('aria-controls'); + self.$search.removeAttr('aria-activedescendant'); + + self.$search.val(''); + self.$search.trigger('blur'); + }); + + container.on('focus', function () { + if (!container.isOpen()) { + self.$search.trigger('focus'); + } + }); + + container.on('results:all', function (params) { + if (params.query.term == null || params.query.term === '') { + var showSearch = self.showSearch(params); + + if (showSearch) { + self.$searchContainer.removeClass('select2-search--hide'); + } else { + self.$searchContainer.addClass('select2-search--hide'); + } + } + }); + + container.on('results:focus', function (params) { + if (params.data._resultId) { + self.$search.attr('aria-activedescendant', params.data._resultId); + } else { + self.$search.removeAttr('aria-activedescendant'); + } + }); + }; + + Search.prototype.handleSearch = function (evt) { + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.showSearch = function (_, params) { + return true; + }; + + return Search; +}); + +S2.define('select2/dropdown/hidePlaceholder',[ + +], function () { + function HidePlaceholder (decorated, $element, options, dataAdapter) { + this.placeholder = this.normalizePlaceholder(options.get('placeholder')); + + decorated.call(this, $element, options, dataAdapter); + } + + HidePlaceholder.prototype.append = function (decorated, data) { + data.results = this.removePlaceholder(data.results); + + decorated.call(this, data); + }; + + HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { + if (typeof placeholder === 'string') { + placeholder = { + id: '', + text: placeholder + }; + } + + return placeholder; + }; + + HidePlaceholder.prototype.removePlaceholder = function (_, data) { + var modifiedData = data.slice(0); + + for (var d = data.length - 1; d >= 0; d--) { + var item = data[d]; + + if (this.placeholder.id === item.id) { + modifiedData.splice(d, 1); + } + } + + return modifiedData; + }; + + return HidePlaceholder; +}); + +S2.define('select2/dropdown/infiniteScroll',[ + 'jquery' +], function ($) { + function InfiniteScroll (decorated, $element, options, dataAdapter) { + this.lastParams = {}; + + decorated.call(this, $element, options, dataAdapter); + + this.$loadingMore = this.createLoadingMore(); + this.loading = false; + } + + InfiniteScroll.prototype.append = function (decorated, data) { + this.$loadingMore.remove(); + this.loading = false; + + decorated.call(this, data); + + if (this.showLoadingMore(data)) { + this.$results.append(this.$loadingMore); + this.loadMoreIfNeeded(); + } + }; + + InfiniteScroll.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('query', function (params) { + self.lastParams = params; + self.loading = true; + }); + + container.on('query:append', function (params) { + self.lastParams = params; + self.loading = true; + }); + + this.$results.on('scroll', this.loadMoreIfNeeded.bind(this)); + }; + + InfiniteScroll.prototype.loadMoreIfNeeded = function () { + var isLoadMoreVisible = $.contains( + document.documentElement, + this.$loadingMore[0] + ); + + if (this.loading || !isLoadMoreVisible) { + return; + } + + var currentOffset = this.$results.offset().top + + this.$results.outerHeight(false); + var loadingMoreOffset = this.$loadingMore.offset().top + + this.$loadingMore.outerHeight(false); + + if (currentOffset + 50 >= loadingMoreOffset) { + this.loadMore(); + } + }; + + InfiniteScroll.prototype.loadMore = function () { + this.loading = true; + + var params = $.extend({}, {page: 1}, this.lastParams); + + params.page++; + + this.trigger('query:append', params); + }; + + InfiniteScroll.prototype.showLoadingMore = function (_, data) { + return data.pagination && data.pagination.more; + }; + + InfiniteScroll.prototype.createLoadingMore = function () { + var $option = $( + '<li ' + + 'class="select2-results__option select2-results__option--load-more"' + + 'role="option" aria-disabled="true"></li>' + ); + + var message = this.options.get('translations').get('loadingMore'); + + $option.html(message(this.lastParams)); + + return $option; + }; + + return InfiniteScroll; +}); + +S2.define('select2/dropdown/attachBody',[ + 'jquery', + '../utils' +], function ($, Utils) { + function AttachBody (decorated, $element, options) { + this.$dropdownParent = $(options.get('dropdownParent') || document.body); + + decorated.call(this, $element, options); + } + + AttachBody.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('open', function () { + self._showDropdown(); + self._attachPositioningHandler(container); + + // Must bind after the results handlers to ensure correct sizing + self._bindContainerResultHandlers(container); + }); + + container.on('close', function () { + self._hideDropdown(); + self._detachPositioningHandler(container); + }); + + this.$dropdownContainer.on('mousedown', function (evt) { + evt.stopPropagation(); + }); + }; + + AttachBody.prototype.destroy = function (decorated) { + decorated.call(this); + + this.$dropdownContainer.remove(); + }; + + AttachBody.prototype.position = function (decorated, $dropdown, $container) { + // Clone all of the container classes + $dropdown.attr('class', $container.attr('class')); + + $dropdown.removeClass('select2'); + $dropdown.addClass('select2-container--open'); + + $dropdown.css({ + position: 'absolute', + top: -999999 + }); + + this.$container = $container; + }; + + AttachBody.prototype.render = function (decorated) { + var $container = $('<span></span>'); + + var $dropdown = decorated.call(this); + $container.append($dropdown); + + this.$dropdownContainer = $container; + + return $container; + }; + + AttachBody.prototype._hideDropdown = function (decorated) { + this.$dropdownContainer.detach(); + }; + + AttachBody.prototype._bindContainerResultHandlers = + function (decorated, container) { + + // These should only be bound once + if (this._containerResultsHandlersBound) { + return; + } + + var self = this; + + container.on('results:all', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('results:append', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('results:message', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('select', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('unselect', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + this._containerResultsHandlersBound = true; + }; + + AttachBody.prototype._attachPositioningHandler = + function (decorated, container) { + var self = this; + + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.each(function () { + Utils.StoreData(this, 'select2-scroll-position', { + x: $(this).scrollLeft(), + y: $(this).scrollTop() + }); + }); + + $watchers.on(scrollEvent, function (ev) { + var position = Utils.GetData(this, 'select2-scroll-position'); + $(this).scrollTop(position.y); + }); + + $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, + function (e) { + self._positionDropdown(); + self._resizeDropdown(); + }); + }; + + AttachBody.prototype._detachPositioningHandler = + function (decorated, container) { + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.off(scrollEvent); + + $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); + }; + + AttachBody.prototype._positionDropdown = function () { + var $window = $(window); + + var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above'); + var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below'); + + var newDirection = null; + + var offset = this.$container.offset(); + + offset.bottom = offset.top + this.$container.outerHeight(false); + + var container = { + height: this.$container.outerHeight(false) + }; + + container.top = offset.top; + container.bottom = offset.top + container.height; + + var dropdown = { + height: this.$dropdown.outerHeight(false) + }; + + var viewport = { + top: $window.scrollTop(), + bottom: $window.scrollTop() + $window.height() + }; + + var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); + var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); + + var css = { + left: offset.left, + top: container.bottom + }; + + // Determine what the parent element is to use for calculating the offset + var $offsetParent = this.$dropdownParent; + + // For statically positioned elements, we need to get the element + // that is determining the offset + if ($offsetParent.css('position') === 'static') { + $offsetParent = $offsetParent.offsetParent(); + } + + var parentOffset = { + top: 0, + left: 0 + }; + + if ($.contains(document.body, $offsetParent[0])) { + parentOffset = $offsetParent.offset(); + } + + css.top -= parentOffset.top; + css.left -= parentOffset.left; + + if (!isCurrentlyAbove && !isCurrentlyBelow) { + newDirection = 'below'; + } + + if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { + newDirection = 'above'; + } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { + newDirection = 'below'; + } + + if (newDirection == 'above' || + (isCurrentlyAbove && newDirection !== 'below')) { + css.top = container.top - parentOffset.top - dropdown.height; + } + + if (newDirection != null) { + this.$dropdown + .removeClass('select2-dropdown--below select2-dropdown--above') + .addClass('select2-dropdown--' + newDirection); + this.$container + .removeClass('select2-container--below select2-container--above') + .addClass('select2-container--' + newDirection); + } + + this.$dropdownContainer.css(css); + }; + + AttachBody.prototype._resizeDropdown = function () { + var css = { + width: this.$container.outerWidth(false) + 'px' + }; + + if (this.options.get('dropdownAutoWidth')) { + css.minWidth = css.width; + css.position = 'relative'; + css.width = 'auto'; + } + + this.$dropdown.css(css); + }; + + AttachBody.prototype._showDropdown = function (decorated) { + this.$dropdownContainer.appendTo(this.$dropdownParent); + + this._positionDropdown(); + this._resizeDropdown(); + }; + + return AttachBody; +}); + +S2.define('select2/dropdown/minimumResultsForSearch',[ + +], function () { + function countResults (data) { + var count = 0; + + for (var d = 0; d < data.length; d++) { + var item = data[d]; + + if (item.children) { + count += countResults(item.children); + } else { + count++; + } + } + + return count; + } + + function MinimumResultsForSearch (decorated, $element, options, dataAdapter) { + this.minimumResultsForSearch = options.get('minimumResultsForSearch'); + + if (this.minimumResultsForSearch < 0) { + this.minimumResultsForSearch = Infinity; + } + + decorated.call(this, $element, options, dataAdapter); + } + + MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { + if (countResults(params.data.results) < this.minimumResultsForSearch) { + return false; + } + + return decorated.call(this, params); + }; + + return MinimumResultsForSearch; +}); + +S2.define('select2/dropdown/selectOnClose',[ + '../utils' +], function (Utils) { + function SelectOnClose () { } + + SelectOnClose.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('close', function (params) { + self._handleSelectOnClose(params); + }); + }; + + SelectOnClose.prototype._handleSelectOnClose = function (_, params) { + if (params && params.originalSelect2Event != null) { + var event = params.originalSelect2Event; + + // Don't select an item if the close event was triggered from a select or + // unselect event + if (event._type === 'select' || event._type === 'unselect') { + return; + } + } + + var $highlightedResults = this.getHighlightedResults(); + + // Only select highlighted results + if ($highlightedResults.length < 1) { + return; + } + + var data = Utils.GetData($highlightedResults[0], 'data'); + + // Don't re-select already selected resulte + if ( + (data.element != null && data.element.selected) || + (data.element == null && data.selected) + ) { + return; + } + + this.trigger('select', { + data: data + }); + }; + + return SelectOnClose; +}); + +S2.define('select2/dropdown/closeOnSelect',[ + +], function () { + function CloseOnSelect () { } + + CloseOnSelect.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('select', function (evt) { + self._selectTriggered(evt); + }); + + container.on('unselect', function (evt) { + self._selectTriggered(evt); + }); + }; + + CloseOnSelect.prototype._selectTriggered = function (_, evt) { + var originalEvent = evt.originalEvent; + + // Don't close if the control key is being held + if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) { + return; + } + + this.trigger('close', { + originalEvent: originalEvent, + originalSelect2Event: evt + }); + }; + + return CloseOnSelect; +}); + +S2.define('select2/i18n/en',[],function () { + // English + return { + errorLoading: function () { + return 'The results could not be loaded.'; + }, + inputTooLong: function (args) { + var overChars = args.input.length - args.maximum; + + var message = 'Please delete ' + overChars + ' character'; + + if (overChars != 1) { + message += 's'; + } + + return message; + }, + inputTooShort: function (args) { + var remainingChars = args.minimum - args.input.length; + + var message = 'Please enter ' + remainingChars + ' or more characters'; + + return message; + }, + loadingMore: function () { + return 'Loading more results…'; + }, + maximumSelected: function (args) { + var message = 'You can only select ' + args.maximum + ' item'; + + if (args.maximum != 1) { + message += 's'; + } + + return message; + }, + noResults: function () { + return 'No results found'; + }, + searching: function () { + return 'Searching…'; + }, + removeAllItems: function () { + return 'Remove all items'; + } + }; +}); + +S2.define('select2/defaults',[ + 'jquery', + 'require', + + './results', + + './selection/single', + './selection/multiple', + './selection/placeholder', + './selection/allowClear', + './selection/search', + './selection/eventRelay', + + './utils', + './translation', + './diacritics', + + './data/select', + './data/array', + './data/ajax', + './data/tags', + './data/tokenizer', + './data/minimumInputLength', + './data/maximumInputLength', + './data/maximumSelectionLength', + + './dropdown', + './dropdown/search', + './dropdown/hidePlaceholder', + './dropdown/infiniteScroll', + './dropdown/attachBody', + './dropdown/minimumResultsForSearch', + './dropdown/selectOnClose', + './dropdown/closeOnSelect', + + './i18n/en' +], function ($, require, + + ResultsList, + + SingleSelection, MultipleSelection, Placeholder, AllowClear, + SelectionSearch, EventRelay, + + Utils, Translation, DIACRITICS, + + SelectData, ArrayData, AjaxData, Tags, Tokenizer, + MinimumInputLength, MaximumInputLength, MaximumSelectionLength, + + Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, + AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, + + EnglishTranslation) { + function Defaults () { + this.reset(); + } + + Defaults.prototype.apply = function (options) { + options = $.extend(true, {}, this.defaults, options); + + if (options.dataAdapter == null) { + if (options.ajax != null) { + options.dataAdapter = AjaxData; + } else if (options.data != null) { + options.dataAdapter = ArrayData; + } else { + options.dataAdapter = SelectData; + } + + if (options.minimumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MinimumInputLength + ); + } + + if (options.maximumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumInputLength + ); + } + + if (options.maximumSelectionLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumSelectionLength + ); + } + + if (options.tags) { + options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); + } + + if (options.tokenSeparators != null || options.tokenizer != null) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Tokenizer + ); + } + + if (options.query != null) { + var Query = require(options.amdBase + 'compat/query'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Query + ); + } + + if (options.initSelection != null) { + var InitSelection = require(options.amdBase + 'compat/initSelection'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + InitSelection + ); + } + } + + if (options.resultsAdapter == null) { + options.resultsAdapter = ResultsList; + + if (options.ajax != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + InfiniteScroll + ); + } + + if (options.placeholder != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + HidePlaceholder + ); + } + + if (options.selectOnClose) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + SelectOnClose + ); + } + } + + if (options.dropdownAdapter == null) { + if (options.multiple) { + options.dropdownAdapter = Dropdown; + } else { + var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); + + options.dropdownAdapter = SearchableDropdown; + } + + if (options.minimumResultsForSearch !== 0) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + MinimumResultsForSearch + ); + } + + if (options.closeOnSelect) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + CloseOnSelect + ); + } + + if ( + options.dropdownCssClass != null || + options.dropdownCss != null || + options.adaptDropdownCssClass != null + ) { + var DropdownCSS = require(options.amdBase + 'compat/dropdownCss'); + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + DropdownCSS + ); + } + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + AttachBody + ); + } + + if (options.selectionAdapter == null) { + if (options.multiple) { + options.selectionAdapter = MultipleSelection; + } else { + options.selectionAdapter = SingleSelection; + } + + // Add the placeholder mixin if a placeholder was specified + if (options.placeholder != null) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + Placeholder + ); + } + + if (options.allowClear) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + AllowClear + ); + } + + if (options.multiple) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + SelectionSearch + ); + } + + if ( + options.containerCssClass != null || + options.containerCss != null || + options.adaptContainerCssClass != null + ) { + var ContainerCSS = require(options.amdBase + 'compat/containerCss'); + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + ContainerCSS + ); + } + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + EventRelay + ); + } + + // If the defaults were not previously applied from an element, it is + // possible for the language option to have not been resolved + options.language = this._resolveLanguage(options.language); + + // Always fall back to English since it will always be complete + options.language.push('en'); + + var uniqueLanguages = []; + + for (var l = 0; l < options.language.length; l++) { + var language = options.language[l]; + + if (uniqueLanguages.indexOf(language) === -1) { + uniqueLanguages.push(language); + } + } + + options.language = uniqueLanguages; + + options.translations = this._processTranslations( + options.language, + options.debug + ); + + return options; + }; + + Defaults.prototype.reset = function () { + function stripDiacritics (text) { + // Used 'uni range + named function' from http://jsperf.com/diacritics/18 + function match(a) { + return DIACRITICS[a] || a; + } + + return text.replace(/[^\u0000-\u007E]/g, match); + } + + function matcher (params, data) { + // Always return the object if there is nothing to compare + if ($.trim(params.term) === '') { + return data; + } + + // Do a recursive check for options with children + if (data.children && data.children.length > 0) { + // Clone the data object if there are children + // This is required as we modify the object to remove any non-matches + var match = $.extend(true, {}, data); + + // Check each child of the option + for (var c = data.children.length - 1; c >= 0; c--) { + var child = data.children[c]; + + var matches = matcher(params, child); + + // If there wasn't a match, remove the object in the array + if (matches == null) { + match.children.splice(c, 1); + } + } + + // If any children matched, return the new object + if (match.children.length > 0) { + return match; + } + + // If there were no matching children, check just the plain object + return matcher(params, match); + } + + var original = stripDiacritics(data.text).toUpperCase(); + var term = stripDiacritics(params.term).toUpperCase(); + + // Check if the text contains the term + if (original.indexOf(term) > -1) { + return data; + } + + // If it doesn't contain the term, don't return anything + return null; + } + + this.defaults = { + amdBase: './', + amdLanguageBase: './i18n/', + closeOnSelect: true, + debug: false, + dropdownAutoWidth: false, + escapeMarkup: Utils.escapeMarkup, + language: {}, + matcher: matcher, + minimumInputLength: 0, + maximumInputLength: 0, + maximumSelectionLength: 0, + minimumResultsForSearch: 0, + selectOnClose: false, + scrollAfterSelect: false, + sorter: function (data) { + return data; + }, + templateResult: function (result) { + return result.text; + }, + templateSelection: function (selection) { + return selection.text; + }, + theme: 'default', + width: 'resolve' + }; + }; + + Defaults.prototype.applyFromElement = function (options, $element) { + var optionLanguage = options.language; + var defaultLanguage = this.defaults.language; + var elementLanguage = $element.prop('lang'); + var parentLanguage = $element.closest('[lang]').prop('lang'); + + var languages = Array.prototype.concat.call( + this._resolveLanguage(elementLanguage), + this._resolveLanguage(optionLanguage), + this._resolveLanguage(defaultLanguage), + this._resolveLanguage(parentLanguage) + ); + + options.language = languages; + + return options; + }; + + Defaults.prototype._resolveLanguage = function (language) { + if (!language) { + return []; + } + + if ($.isEmptyObject(language)) { + return []; + } + + if ($.isPlainObject(language)) { + return [language]; + } + + var languages; + + if (!$.isArray(language)) { + languages = [language]; + } else { + languages = language; + } + + var resolvedLanguages = []; + + for (var l = 0; l < languages.length; l++) { + resolvedLanguages.push(languages[l]); + + if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) { + // Extract the region information if it is included + var languageParts = languages[l].split('-'); + var baseLanguage = languageParts[0]; + + resolvedLanguages.push(baseLanguage); + } + } + + return resolvedLanguages; + }; + + Defaults.prototype._processTranslations = function (languages, debug) { + var translations = new Translation(); + + for (var l = 0; l < languages.length; l++) { + var languageData = new Translation(); + + var language = languages[l]; + + if (typeof language === 'string') { + try { + // Try to load it with the original name + languageData = Translation.loadPath(language); + } catch (e) { + try { + // If we couldn't load it, check if it wasn't the full path + language = this.defaults.amdLanguageBase + language; + languageData = Translation.loadPath(language); + } catch (ex) { + // The translation could not be loaded at all. Sometimes this is + // because of a configuration problem, other times this can be + // because of how Select2 helps load all possible translation files + if (debug && window.console && console.warn) { + console.warn( + 'Select2: The language file for "' + language + '" could ' + + 'not be automatically loaded. A fallback will be used instead.' + ); + } + } + } + } else if ($.isPlainObject(language)) { + languageData = new Translation(language); + } else { + languageData = language; + } + + translations.extend(languageData); + } + + return translations; + }; + + Defaults.prototype.set = function (key, value) { + var camelKey = $.camelCase(key); + + var data = {}; + data[camelKey] = value; + + var convertedData = Utils._convertData(data); + + $.extend(true, this.defaults, convertedData); + }; + + var defaults = new Defaults(); + + return defaults; +}); + +S2.define('select2/options',[ + 'require', + 'jquery', + './defaults', + './utils' +], function (require, $, Defaults, Utils) { + function Options (options, $element) { + this.options = options; + + if ($element != null) { + this.fromElement($element); + } + + if ($element != null) { + this.options = Defaults.applyFromElement(this.options, $element); + } + + this.options = Defaults.apply(this.options); + + if ($element && $element.is('input')) { + var InputCompat = require(this.get('amdBase') + 'compat/inputData'); + + this.options.dataAdapter = Utils.Decorate( + this.options.dataAdapter, + InputCompat + ); + } + } + + Options.prototype.fromElement = function ($e) { + var excludedData = ['select2']; + + if (this.options.multiple == null) { + this.options.multiple = $e.prop('multiple'); + } + + if (this.options.disabled == null) { + this.options.disabled = $e.prop('disabled'); + } + + if (this.options.dir == null) { + if ($e.prop('dir')) { + this.options.dir = $e.prop('dir'); + } else if ($e.closest('[dir]').prop('dir')) { + this.options.dir = $e.closest('[dir]').prop('dir'); + } else { + this.options.dir = 'ltr'; + } + } + + $e.prop('disabled', this.options.disabled); + $e.prop('multiple', this.options.multiple); + + if (Utils.GetData($e[0], 'select2Tags')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-select2-tags` attribute has been changed to ' + + 'use the `data-data` and `data-tags="true"` attributes and will be ' + + 'removed in future versions of Select2.' + ); + } + + Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags')); + Utils.StoreData($e[0], 'tags', true); + } + + if (Utils.GetData($e[0], 'ajaxUrl')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-ajax-url` attribute has been changed to ' + + '`data-ajax--url` and support for the old attribute will be removed' + + ' in future versions of Select2.' + ); + } + + $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl')); + Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl')); + } + + var dataset = {}; + + function upperCaseLetter(_, letter) { + return letter.toUpperCase(); + } + + // Pre-load all of the attributes which are prefixed with `data-` + for (var attr = 0; attr < $e[0].attributes.length; attr++) { + var attributeName = $e[0].attributes[attr].name; + var prefix = 'data-'; + + if (attributeName.substr(0, prefix.length) == prefix) { + // Get the contents of the attribute after `data-` + var dataName = attributeName.substring(prefix.length); + + // Get the data contents from the consistent source + // This is more than likely the jQuery data helper + var dataValue = Utils.GetData($e[0], dataName); + + // camelCase the attribute name to match the spec + var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter); + + // Store the data attribute contents into the dataset since + dataset[camelDataName] = dataValue; + } + } + + // Prefer the element's `dataset` attribute if it exists + // jQuery 1.x does not correctly handle data attributes with multiple dashes + if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { + dataset = $.extend(true, {}, $e[0].dataset, dataset); + } + + // Prefer our internal data cache if it exists + var data = $.extend(true, {}, Utils.GetData($e[0]), dataset); + + data = Utils._convertData(data); + + for (var key in data) { + if ($.inArray(key, excludedData) > -1) { + continue; + } + + if ($.isPlainObject(this.options[key])) { + $.extend(this.options[key], data[key]); + } else { + this.options[key] = data[key]; + } + } + + return this; + }; + + Options.prototype.get = function (key) { + return this.options[key]; + }; + + Options.prototype.set = function (key, val) { + this.options[key] = val; + }; + + return Options; +}); + +S2.define('select2/core',[ + 'jquery', + './options', + './utils', + './keys' +], function ($, Options, Utils, KEYS) { + var Select2 = function ($element, options) { + if (Utils.GetData($element[0], 'select2') != null) { + Utils.GetData($element[0], 'select2').destroy(); + } + + this.$element = $element; + + this.id = this._generateId($element); + + options = options || {}; + + this.options = new Options(options, $element); + + Select2.__super__.constructor.call(this); + + // Set up the tabindex + + var tabindex = $element.attr('tabindex') || 0; + Utils.StoreData($element[0], 'old-tabindex', tabindex); + $element.attr('tabindex', '-1'); + + // Set up containers and adapters + + var DataAdapter = this.options.get('dataAdapter'); + this.dataAdapter = new DataAdapter($element, this.options); + + var $container = this.render(); + + this._placeContainer($container); + + var SelectionAdapter = this.options.get('selectionAdapter'); + this.selection = new SelectionAdapter($element, this.options); + this.$selection = this.selection.render(); + + this.selection.position(this.$selection, $container); + + var DropdownAdapter = this.options.get('dropdownAdapter'); + this.dropdown = new DropdownAdapter($element, this.options); + this.$dropdown = this.dropdown.render(); + + this.dropdown.position(this.$dropdown, $container); + + var ResultsAdapter = this.options.get('resultsAdapter'); + this.results = new ResultsAdapter($element, this.options, this.dataAdapter); + this.$results = this.results.render(); + + this.results.position(this.$results, this.$dropdown); + + // Bind events + + var self = this; + + // Bind the container to all of the adapters + this._bindAdapters(); + + // Register any DOM event handlers + this._registerDomEvents(); + + // Register any internal event handlers + this._registerDataEvents(); + this._registerSelectionEvents(); + this._registerDropdownEvents(); + this._registerResultsEvents(); + this._registerEvents(); + + // Set the initial state + this.dataAdapter.current(function (initialData) { + self.trigger('selection:update', { + data: initialData + }); + }); + + // Hide the original select + $element.addClass('select2-hidden-accessible'); + $element.attr('aria-hidden', 'true'); + + // Synchronize any monitored attributes + this._syncAttributes(); + + Utils.StoreData($element[0], 'select2', this); + + // Ensure backwards compatibility with $element.data('select2'). + $element.data('select2', this); + }; + + Utils.Extend(Select2, Utils.Observable); + + Select2.prototype._generateId = function ($element) { + var id = ''; + + if ($element.attr('id') != null) { + id = $element.attr('id'); + } else if ($element.attr('name') != null) { + id = $element.attr('name') + '-' + Utils.generateChars(2); + } else { + id = Utils.generateChars(4); + } + + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = 'select2-' + id; + + return id; + }; + + Select2.prototype._placeContainer = function ($container) { + $container.insertAfter(this.$element); + + var width = this._resolveWidth(this.$element, this.options.get('width')); + + if (width != null) { + $container.css('width', width); + } + }; + + Select2.prototype._resolveWidth = function ($element, method) { + var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; + + if (method == 'resolve') { + var styleWidth = this._resolveWidth($element, 'style'); + + if (styleWidth != null) { + return styleWidth; + } + + return this._resolveWidth($element, 'element'); + } + + if (method == 'element') { + var elementWidth = $element.outerWidth(false); + + if (elementWidth <= 0) { + return 'auto'; + } + + return elementWidth + 'px'; + } + + if (method == 'style') { + var style = $element.attr('style'); + + if (typeof(style) !== 'string') { + return null; + } + + var attrs = style.split(';'); + + for (var i = 0, l = attrs.length; i < l; i = i + 1) { + var attr = attrs[i].replace(/\s/g, ''); + var matches = attr.match(WIDTH); + + if (matches !== null && matches.length >= 1) { + return matches[1]; + } + } + + return null; + } + + if (method == 'computedstyle') { + var computedStyle = window.getComputedStyle($element[0]); + + return computedStyle.width; + } + + return method; + }; + + Select2.prototype._bindAdapters = function () { + this.dataAdapter.bind(this, this.$container); + this.selection.bind(this, this.$container); + + this.dropdown.bind(this, this.$container); + this.results.bind(this, this.$container); + }; + + Select2.prototype._registerDomEvents = function () { + var self = this; + + this.$element.on('change.select2', function () { + self.dataAdapter.current(function (data) { + self.trigger('selection:update', { + data: data + }); + }); + }); + + this.$element.on('focus.select2', function (evt) { + self.trigger('focus', evt); + }); + + this._syncA = Utils.bind(this._syncAttributes, this); + this._syncS = Utils.bind(this._syncSubtree, this); + + if (this.$element[0].attachEvent) { + this.$element[0].attachEvent('onpropertychange', this._syncA); + } + + var observer = window.MutationObserver || + window.WebKitMutationObserver || + window.MozMutationObserver + ; + + if (observer != null) { + this._observer = new observer(function (mutations) { + $.each(mutations, self._syncA); + $.each(mutations, self._syncS); + }); + this._observer.observe(this.$element[0], { + attributes: true, + childList: true, + subtree: false + }); + } else if (this.$element[0].addEventListener) { + this.$element[0].addEventListener( + 'DOMAttrModified', + self._syncA, + false + ); + this.$element[0].addEventListener( + 'DOMNodeInserted', + self._syncS, + false + ); + this.$element[0].addEventListener( + 'DOMNodeRemoved', + self._syncS, + false + ); + } + }; + + Select2.prototype._registerDataEvents = function () { + var self = this; + + this.dataAdapter.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerSelectionEvents = function () { + var self = this; + var nonRelayEvents = ['toggle', 'focus']; + + this.selection.on('toggle', function () { + self.toggleDropdown(); + }); + + this.selection.on('focus', function (params) { + self.focus(params); + }); + + this.selection.on('*', function (name, params) { + if ($.inArray(name, nonRelayEvents) !== -1) { + return; + } + + self.trigger(name, params); + }); + }; + + Select2.prototype._registerDropdownEvents = function () { + var self = this; + + this.dropdown.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerResultsEvents = function () { + var self = this; + + this.results.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerEvents = function () { + var self = this; + + this.on('open', function () { + self.$container.addClass('select2-container--open'); + }); + + this.on('close', function () { + self.$container.removeClass('select2-container--open'); + }); + + this.on('enable', function () { + self.$container.removeClass('select2-container--disabled'); + }); + + this.on('disable', function () { + self.$container.addClass('select2-container--disabled'); + }); + + this.on('blur', function () { + self.$container.removeClass('select2-container--focus'); + }); + + this.on('query', function (params) { + if (!self.isOpen()) { + self.trigger('open', {}); + } + + this.dataAdapter.query(params, function (data) { + self.trigger('results:all', { + data: data, + query: params + }); + }); + }); + + this.on('query:append', function (params) { + this.dataAdapter.query(params, function (data) { + self.trigger('results:append', { + data: data, + query: params + }); + }); + }); + + this.on('keypress', function (evt) { + var key = evt.which; + + if (self.isOpen()) { + if (key === KEYS.ESC || key === KEYS.TAB || + (key === KEYS.UP && evt.altKey)) { + self.close(); + + evt.preventDefault(); + } else if (key === KEYS.ENTER) { + self.trigger('results:select', {}); + + evt.preventDefault(); + } else if ((key === KEYS.SPACE && evt.ctrlKey)) { + self.trigger('results:toggle', {}); + + evt.preventDefault(); + } else if (key === KEYS.UP) { + self.trigger('results:previous', {}); + + evt.preventDefault(); + } else if (key === KEYS.DOWN) { + self.trigger('results:next', {}); + + evt.preventDefault(); + } + } else { + if (key === KEYS.ENTER || key === KEYS.SPACE || + (key === KEYS.DOWN && evt.altKey)) { + self.open(); + + evt.preventDefault(); + } + } + }); + }; + + Select2.prototype._syncAttributes = function () { + this.options.set('disabled', this.$element.prop('disabled')); + + if (this.options.get('disabled')) { + if (this.isOpen()) { + this.close(); + } + + this.trigger('disable', {}); + } else { + this.trigger('enable', {}); + } + }; + + Select2.prototype._syncSubtree = function (evt, mutations) { + var changed = false; + var self = this; + + // Ignore any mutation events raised for elements that aren't options or + // optgroups. This handles the case when the select element is destroyed + if ( + evt && evt.target && ( + evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP' + ) + ) { + return; + } + + if (!mutations) { + // If mutation events aren't supported, then we can only assume that the + // change affected the selections + changed = true; + } else if (mutations.addedNodes && mutations.addedNodes.length > 0) { + for (var n = 0; n < mutations.addedNodes.length; n++) { + var node = mutations.addedNodes[n]; + + if (node.selected) { + changed = true; + } + } + } else if (mutations.removedNodes && mutations.removedNodes.length > 0) { + changed = true; + } + + // Only re-pull the data if we think there is a change + if (changed) { + this.dataAdapter.current(function (currentData) { + self.trigger('selection:update', { + data: currentData + }); + }); + } + }; + + /** + * Override the trigger method to automatically trigger pre-events when + * there are events that can be prevented. + */ + Select2.prototype.trigger = function (name, args) { + var actualTrigger = Select2.__super__.trigger; + var preTriggerMap = { + 'open': 'opening', + 'close': 'closing', + 'select': 'selecting', + 'unselect': 'unselecting', + 'clear': 'clearing' + }; + + if (args === undefined) { + args = {}; + } + + if (name in preTriggerMap) { + var preTriggerName = preTriggerMap[name]; + var preTriggerArgs = { + prevented: false, + name: name, + args: args + }; + + actualTrigger.call(this, preTriggerName, preTriggerArgs); + + if (preTriggerArgs.prevented) { + args.prevented = true; + + return; + } + } + + actualTrigger.call(this, name, args); + }; + + Select2.prototype.toggleDropdown = function () { + if (this.options.get('disabled')) { + return; + } + + if (this.isOpen()) { + this.close(); + } else { + this.open(); + } + }; + + Select2.prototype.open = function () { + if (this.isOpen()) { + return; + } + + this.trigger('query', {}); + }; + + Select2.prototype.close = function () { + if (!this.isOpen()) { + return; + } + + this.trigger('close', {}); + }; + + Select2.prototype.isOpen = function () { + return this.$container.hasClass('select2-container--open'); + }; + + Select2.prototype.hasFocus = function () { + return this.$container.hasClass('select2-container--focus'); + }; + + Select2.prototype.focus = function (data) { + // No need to re-trigger focus events if we are already focused + if (this.hasFocus()) { + return; + } + + this.$container.addClass('select2-container--focus'); + this.trigger('focus', {}); + }; + + Select2.prototype.enable = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("enable")` method has been deprecated and will' + + ' be removed in later Select2 versions. Use $element.prop("disabled")' + + ' instead.' + ); + } + + if (args == null || args.length === 0) { + args = [true]; + } + + var disabled = !args[0]; + + this.$element.prop('disabled', disabled); + }; + + Select2.prototype.data = function () { + if (this.options.get('debug') && + arguments.length > 0 && window.console && console.warn) { + console.warn( + 'Select2: Data can no longer be set using `select2("data")`. You ' + + 'should consider setting the value instead using `$element.val()`.' + ); + } + + var data = []; + + this.dataAdapter.current(function (currentData) { + data = currentData; + }); + + return data; + }; + + Select2.prototype.val = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("val")` method has been deprecated and will be' + + ' removed in later Select2 versions. Use $element.val() instead.' + ); + } + + if (args == null || args.length === 0) { + return this.$element.val(); + } + + var newVal = args[0]; + + if ($.isArray(newVal)) { + newVal = $.map(newVal, function (obj) { + return obj.toString(); + }); + } + + this.$element.val(newVal).trigger('change'); + }; + + Select2.prototype.destroy = function () { + this.$container.remove(); + + if (this.$element[0].detachEvent) { + this.$element[0].detachEvent('onpropertychange', this._syncA); + } + + if (this._observer != null) { + this._observer.disconnect(); + this._observer = null; + } else if (this.$element[0].removeEventListener) { + this.$element[0] + .removeEventListener('DOMAttrModified', this._syncA, false); + this.$element[0] + .removeEventListener('DOMNodeInserted', this._syncS, false); + this.$element[0] + .removeEventListener('DOMNodeRemoved', this._syncS, false); + } + + this._syncA = null; + this._syncS = null; + + this.$element.off('.select2'); + this.$element.attr('tabindex', + Utils.GetData(this.$element[0], 'old-tabindex')); + + this.$element.removeClass('select2-hidden-accessible'); + this.$element.attr('aria-hidden', 'false'); + Utils.RemoveData(this.$element[0]); + this.$element.removeData('select2'); + + this.dataAdapter.destroy(); + this.selection.destroy(); + this.dropdown.destroy(); + this.results.destroy(); + + this.dataAdapter = null; + this.selection = null; + this.dropdown = null; + this.results = null; + }; + + Select2.prototype.render = function () { + var $container = $( + '<span class="select2 select2-container">' + + '<span class="selection"></span>' + + '<span class="dropdown-wrapper" aria-hidden="true"></span>' + + '</span>' + ); + + $container.attr('dir', this.options.get('dir')); + + this.$container = $container; + + this.$container.addClass('select2-container--' + this.options.get('theme')); + + Utils.StoreData($container[0], 'element', this.$element); + + return $container; + }; + + return Select2; +}); + +S2.define('jquery-mousewheel',[ + 'jquery' +], function ($) { + // Used to shim jQuery.mousewheel for non-full builds. + return $; +}); + +S2.define('jquery.select2',[ + 'jquery', + 'jquery-mousewheel', + + './select2/core', + './select2/defaults', + './select2/utils' +], function ($, _, Select2, Defaults, Utils) { + if ($.fn.select2 == null) { + // All methods that should return the element + var thisMethods = ['open', 'close', 'destroy']; + + $.fn.select2 = function (options) { + options = options || {}; + + if (typeof options === 'object') { + this.each(function () { + var instanceOptions = $.extend(true, {}, options); + + var instance = new Select2($(this), instanceOptions); + }); + + return this; + } else if (typeof options === 'string') { + var ret; + var args = Array.prototype.slice.call(arguments, 1); + + this.each(function () { + var instance = Utils.GetData(this, 'select2'); + + if (instance == null && window.console && console.error) { + console.error( + 'The select2(\'' + options + '\') method was called on an ' + + 'element that is not using Select2.' + ); + } + + ret = instance[options].apply(instance, args); + }); + + // Check if we should be returning `this` + if ($.inArray(options, thisMethods) > -1) { + return this; + } + + return ret; + } else { + throw new Error('Invalid arguments for Select2: ' + options); + } + }; + } + + if ($.fn.select2.defaults == null) { + $.fn.select2.defaults = Defaults; + } + + return Select2; +}); + + // Return the AMD loader configuration so it can be used outside of this file + return { + define: S2.define, + require: S2.require + }; +}()); + + // Autoload the jQuery bindings + // We know that all of the modules exist above this, so we're safe + var select2 = S2.require('jquery.select2'); + + // Hold the AMD module references on the jQuery function that was just loaded + // This allows Select2 to use the internal loader outside of this file, such + // as in the language files. + jQuery.fn.select2.amd = S2; + + // Return the Select2 instance for anyone who is importing it. + return select2; +})); diff --git a/src/lib/vendor/toggle-switch.css b/src/lib/vendor/toggle-switch.css new file mode 100644 index 0000000..1b0386e --- /dev/null +++ b/src/lib/vendor/toggle-switch.css @@ -0,0 +1,310 @@ +/* + * CSS TOGGLE SWITCHES + * Unlicense + * + * IonuÈ› Colceriu - ghinda.net + * https://github.com/ghinda/css-toggle-switch + * + */ +/* Toggle Switches + */ +/* Shared + */ +/* Checkbox + */ +/* Radio Switch + */ +/* Hide by default + */ +.switch-toggle a, .switch-light span span { + display: none; } + +/* We can't test for a specific feature, + * so we only target browsers with support for media queries. + */ +@media only screen { + /* Checkbox switch + */ + /* Radio switch + */ + /* Standalone Themes */ + /* Candy Theme + * Based on the "Sort Switches / Toggles (PSD)" by Ormal Clarck + * http://www.premiumpixels.com/freebies/sort-switches-toggles-psd/ + */ + /* Android Theme + */ + /* iOS Theme + */ + .switch-light { + display: block; + height: 30px; + /* Outline the toggles when the inputs are focused + */ + position: relative; + overflow: visible; + padding: 0; + margin-left: 100px; + /* Position the label over all the elements, except the slide-button (<a>) + * Clicking anywhere on the label will change the switch-state + */ + /* Don't hide the input from screen-readers and keyboard access + */ } + .switch-light * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .switch-light a { + display: block; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; } + .switch-light label, .switch-light > span { + line-height: 30px; + vertical-align: middle; } + .switch-light input:focus ~ a, .switch-light input:focus + label { + outline: 1px dotted #888; } + .switch-light label { + position: relative; + z-index: 3; + display: block; + width: 100%; } + .switch-light input { + position: absolute; + opacity: 0; + z-index: 5; } + .switch-light input:checked ~ a { + right: 0%; } + .switch-light > span { + position: absolute; + left: -100px; + width: 100%; + margin: 0; + padding-right: 100px; + text-align: left; } + .switch-light > span span { + position: absolute; + top: 0; + left: 0; + z-index: 5; + display: block; + width: 50%; + margin-left: 100px; + text-align: center; } + .switch-light > span span:last-child { + left: 50%; } + .switch-light a { + position: absolute; + right: 50%; + top: 0; + z-index: 4; + display: block; + width: 50%; + height: 100%; + padding: 0; } + .switch-toggle { + display: block; + height: 30px; + /* Outline the toggles when the inputs are focused + */ + position: relative; + /* For callout panels in foundation + */ + padding: 0 !important; + /* Generate styles for the multiple states */ } + .switch-toggle * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .switch-toggle a { + display: block; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; } + .switch-toggle label, .switch-toggle > span { + line-height: 30px; + vertical-align: middle; } + .switch-toggle input:focus ~ a, .switch-toggle input:focus + label { + outline: 1px dotted #888; } + .switch-toggle input { + position: absolute; + opacity: 0; } + .switch-toggle input + label { + position: relative; + z-index: 2; + float: left; + width: 50%; + height: 100%; + margin: 0; + text-align: center; } + .switch-toggle a { + position: absolute; + top: 0; + left: 0; + padding: 0; + z-index: 1; + width: 50%; + height: 100%; } + .switch-toggle input:last-of-type:checked ~ a { + left: 50%; } + .switch-toggle.switch-3 label, .switch-toggle.switch-3 a { + width: 33.33333%; } + .switch-toggle.switch-3 input:checked:nth-of-type(2) ~ a { + left: 33.33333%; } + .switch-toggle.switch-3 input:checked:last-of-type ~ a { + left: 66.66667%; } + .switch-toggle.switch-4 label, .switch-toggle.switch-4 a { + width: 25%; } + .switch-toggle.switch-4 input:checked:nth-of-type(2) ~ a { + left: 25%; } + .switch-toggle.switch-4 input:checked:nth-of-type(3) ~ a { + left: 50%; } + .switch-toggle.switch-4 input:checked:last-of-type ~ a { + left: 75%; } + .switch-toggle.switch-5 label, .switch-toggle.switch-5 a { + width: 20%; } + .switch-toggle.switch-5 input:checked:nth-of-type(2) ~ a { + left: 20%; } + .switch-toggle.switch-5 input:checked:nth-of-type(3) ~ a { + left: 40%; } + .switch-toggle.switch-5 input:checked:nth-of-type(4) ~ a { + left: 60%; } + .switch-toggle.switch-5 input:checked:last-of-type ~ a { + left: 80%; } + .switch-candy { + background-color: #2d3035; + border-radius: 3px; + color: #fff; + font-weight: bold; + text-align: center; + text-shadow: 1px 1px 1px #191b1e; + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3), 0 1px 0px rgba(255, 255, 255, 0.2); } + .switch-candy label { + color: #fff; + -webkit-transition: color 0.2s ease-out; + -moz-transition: color 0.2s ease-out; + transition: color 0.2s ease-out; } + .switch-candy input:checked + label { + color: #333; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } + .switch-candy a { + border: 1px solid #333; + background-color: #70c66b; + border-radius: 3px; + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0)); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0)); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 1px 1px rgba(255, 255, 255, 0.45); } + .switch-candy > span { + color: #333; + text-shadow: none; } + .switch-candy span { + color: #fff; } + .switch-candy.switch-candy-blue a { + background-color: #38a3d4; } + .switch-candy.switch-candy-yellow a { + background-color: #f5e560; } + .switch-android { + background-color: #464747; + border-radius: 1px; + color: #fff; + box-shadow: inset rgba(0, 0, 0, 0.1) 0 1px 0; + /* Selected ON switch-light + */ } + .switch-android label { + color: #fff; } + .switch-android > span span { + opacity: 0; + -webkit-transition: all 0.1s; + -moz-transition: all 0.1s; + transition: all 0.1s; } + .switch-android > span span:first-of-type { + opacity: 1; } + .switch-android a { + background-color: #666; + border-radius: 1px; + box-shadow: inset rgba(255, 255, 255, 0.2) 0 1px 0, inset rgba(0, 0, 0, 0.3) 0 -1px 0; } + .switch-android.switch-light input:checked ~ a { + background-color: #0E88B1; } + .switch-android.switch-light input:checked ~ span span:first-of-type { + opacity: 0; } + .switch-android.switch-light input:checked ~ span span:last-of-type { + opacity: 1; } + .switch-android.switch-toggle, .switch-android > span span { + font-size: 85%; + text-transform: uppercase; } + .switch-ios.switch-light { + color: #868686; } + .switch-ios.switch-light a { + left: 0; + width: 30px; + background-color: #fff; + border: 1px solid #d3d3d3; + border-radius: 100%; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + box-shadow: inset 0 -3px 3px rgba(0, 0, 0, 0.025), 0 1px 4px rgba(0, 0, 0, 0.15), 0 4px 4px rgba(0, 0, 0, 0.1); } + .switch-ios.switch-light > span span { + width: 100%; + left: 0; + opacity: 0; } + .switch-ios.switch-light > span span:first-of-type { + opacity: 1; + padding-left: 30px; } + .switch-ios.switch-light > span span:last-of-type { + padding-right: 30px; } + .switch-ios.switch-light > span:before { + content: ''; + display: block; + width: 100%; + height: 100%; + position: absolute; + left: 100px; + top: 0; + background-color: #fafafa; + border: 1px solid #d3d3d3; + border-radius: 30px; + -webkit-transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; + box-shadow: inset rgba(0, 0, 0, 0.1) 0 1px 0; } + .switch-ios.switch-light input:checked ~ a { + left: 100%; + margin-left: -30px; } + .switch-ios.switch-light input:checked ~ span:before { + border-color: #53d76a; + box-shadow: inset 0 0 0 30px #53d76a; } + .switch-ios.switch-light input:checked ~ span span:first-of-type { + opacity: 0; } + .switch-ios.switch-light input:checked ~ span span:last-of-type { + opacity: 1; + color: #fff; } + .switch-ios.switch-toggle { + background-color: #fafafa; + border: 1px solid #d3d3d3; + border-radius: 30px; + box-shadow: inset rgba(0, 0, 0, 0.1) 0 1px 0; } + .switch-ios.switch-toggle a { + background-color: #53d76a; + border-radius: 25px; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; } + .switch-ios.switch-toggle label { + color: #868686; } + .switch-ios input:checked + label { + color: #3a3a3a; } } + +/* Bugfix for older Webkit, including mobile Webkit. Adapted from + * http://css-tricks.com/webkit-sibling-bug/ + */ +@media only screen and (-webkit-max-device-pixel-ratio: 2) and (max-device-width: 1280px) { + .switch-light, .switch-toggle { + -webkit-animation: webkitSiblingBugfix infinite 1s; } } + +@-webkit-keyframes webkitSiblingBugfix { + from { + -webkit-transform: translate3d(0, 0, 0); } + + to { + -webkit-transform: translate3d(0, 0, 0); } } diff --git a/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.css b/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.css new file mode 100644 index 0000000..b35a240 --- /dev/null +++ b/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.css @@ -0,0 +1,388 @@ +/* This is the core CSS of Tooltipster */ + +/* GENERAL STRUCTURE RULES (do not edit this section) */ + +.tooltipster-base { + /* this ensures that a constrained height set by functionPosition, + if greater that the natural height of the tooltip, will be enforced + in browsers that support display:flex */ + display: flex; + pointer-events: none; + /* this may be overriden in JS for fixed position origins */ + position: absolute; +} + +.tooltipster-box { + /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10- + and flex-basis auto for IE11- (at least) */ + flex: 1 1 auto; +} + +.tooltipster-content { + /* prevents an overflow if the user adds padding to the div */ + box-sizing: border-box; + /* these make sure we'll be able to detect any overflow */ + max-height: 100%; + max-width: 100%; + overflow: auto; +} + +.tooltipster-ruler { + /* these let us test the size of the tooltip without overflowing the window */ + bottom: 0; + left: 0; + overflow: hidden; + position: fixed; + right: 0; + top: 0; + visibility: hidden; +} + +/* ANIMATIONS */ + +/* Open/close animations */ + +/* fade */ + +.tooltipster-fade { + opacity: 0; + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + -ms-transition-property: opacity; + transition-property: opacity; +} +.tooltipster-fade.tooltipster-show { + opacity: 1; +} + +/* grow */ + +.tooltipster-grow { + -webkit-transform: scale(0,0); + -moz-transform: scale(0,0); + -o-transform: scale(0,0); + -ms-transform: scale(0,0); + transform: scale(0,0); + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform; + -webkit-backface-visibility: hidden; +} +.tooltipster-grow.tooltipster-show { + -webkit-transform: scale(1,1); + -moz-transform: scale(1,1); + -o-transform: scale(1,1); + -ms-transform: scale(1,1); + transform: scale(1,1); + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); +} + +/* swing */ + +.tooltipster-swing { + opacity: 0; + -webkit-transform: rotateZ(4deg); + -moz-transform: rotateZ(4deg); + -o-transform: rotateZ(4deg); + -ms-transform: rotateZ(4deg); + transform: rotateZ(4deg); + -webkit-transition-property: -webkit-transform, opacity; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform; +} +.tooltipster-swing.tooltipster-show { + opacity: 1; + -webkit-transform: rotateZ(0deg); + -moz-transform: rotateZ(0deg); + -o-transform: rotateZ(0deg); + -ms-transform: rotateZ(0deg); + transform: rotateZ(0deg); + -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1); + -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); + -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); + -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); + -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); + transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); +} + +/* fall */ + +.tooltipster-fall { + -webkit-transition-property: top; + -moz-transition-property: top; + -o-transition-property: top; + -ms-transition-property: top; + transition-property: top; + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); +} +.tooltipster-fall.tooltipster-initial { + top: 0 !important; +} +.tooltipster-fall.tooltipster-show { +} +.tooltipster-fall.tooltipster-dying { + -webkit-transition-property: all; + -moz-transition-property: all; + -o-transition-property: all; + -ms-transition-property: all; + transition-property: all; + top: 0 !important; + opacity: 0; +} + +/* slide */ + +.tooltipster-slide { + -webkit-transition-property: left; + -moz-transition-property: left; + -o-transition-property: left; + -ms-transition-property: left; + transition-property: left; + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); + transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); +} +.tooltipster-slide.tooltipster-initial { + left: -40px !important; +} +.tooltipster-slide.tooltipster-show { +} +.tooltipster-slide.tooltipster-dying { + -webkit-transition-property: all; + -moz-transition-property: all; + -o-transition-property: all; + -ms-transition-property: all; + transition-property: all; + left: 0 !important; + opacity: 0; +} + +/* Update animations */ + +/* We use animations rather than transitions here because + transition durations may be specified in the style tag due to + animationDuration, and we try to avoid collisions and the use + of !important */ + +/* fade */ + +@keyframes tooltipster-fading { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +.tooltipster-update-fade { + animation: tooltipster-fading 400ms; +} + +/* rotate */ + +@keyframes tooltipster-rotating { + 25% { + transform: rotate(-2deg); + } + 75% { + transform: rotate(2deg); + } + 100% { + transform: rotate(0); + } +} + +.tooltipster-update-rotate { + animation: tooltipster-rotating 600ms; +} + +/* scale */ + +@keyframes tooltipster-scaling { + 50% { + transform: scale(1.1); + } + 100% { + transform: scale(1); + } +} + +.tooltipster-update-scale { + animation: tooltipster-scaling 600ms; +} +
+/**
+ * DEFAULT STYLE OF THE SIDETIP PLUGIN
+ *
+ * All styles are "namespaced" with .tooltipster-sidetip to prevent
+ * conflicts between plugins.
+ */
+
+/* .tooltipster-box */
+
+.tooltipster-sidetip .tooltipster-box {
+ background: #565656;
+ border: 2px solid black;
+ border-radius: 4px;
+}
+
+.tooltipster-sidetip.tooltipster-bottom .tooltipster-box {
+ margin-top: 8px;
+}
+
+.tooltipster-sidetip.tooltipster-left .tooltipster-box {
+ margin-right: 8px;
+}
+
+.tooltipster-sidetip.tooltipster-right .tooltipster-box {
+ margin-left: 8px;
+}
+
+.tooltipster-sidetip.tooltipster-top .tooltipster-box {
+ margin-bottom: 8px;
+}
+
+/* .tooltipster-content */
+
+.tooltipster-sidetip .tooltipster-content {
+ color: white;
+ line-height: 18px;
+ padding: 6px 14px;
+}
+
+/* .tooltipster-arrow : will keep only the zone of .tooltipster-arrow-uncropped that
+corresponds to the arrow we want to display */
+
+.tooltipster-sidetip .tooltipster-arrow {
+ overflow: hidden;
+ position: absolute;
+}
+
+.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow {
+ height: 10px;
+ /* half the width, for centering */
+ margin-left: -10px;
+ top: 0;
+ width: 20px;
+}
+
+.tooltipster-sidetip.tooltipster-left .tooltipster-arrow {
+ height: 20px;
+ margin-top: -10px;
+ right: 0;
+ /* top 0 to keep the arrow from overflowing .tooltipster-base when it has not
+ been positioned yet */
+ top: 0;
+ width: 10px;
+}
+
+.tooltipster-sidetip.tooltipster-right .tooltipster-arrow {
+ height: 20px;
+ margin-top: -10px;
+ left: 0;
+ /* same as .tooltipster-left .tooltipster-arrow */
+ top: 0;
+ width: 10px;
+}
+
+.tooltipster-sidetip.tooltipster-top .tooltipster-arrow {
+ bottom: 0;
+ height: 10px;
+ margin-left: -10px;
+ width: 20px;
+}
+
+/* common rules between .tooltipster-arrow-background and .tooltipster-arrow-border */
+
+.tooltipster-sidetip .tooltipster-arrow-background, .tooltipster-sidetip .tooltipster-arrow-border {
+ height: 0;
+ position: absolute;
+ width: 0;
+}
+
+/* .tooltipster-arrow-background */
+
+.tooltipster-sidetip .tooltipster-arrow-background {
+ border: 10px solid transparent;
+}
+
+.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background {
+ border-bottom-color: #565656;
+ left: 0;
+ top: 3px;
+}
+
+.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background {
+ border-left-color: #565656;
+ left: -3px;
+ top: 0;
+}
+
+.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background {
+ border-right-color: #565656;
+ left: 3px;
+ top: 0;
+}
+
+.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background {
+ border-top-color: #565656;
+ left: 0;
+ top: -3px;
+}
+
+/* .tooltipster-arrow-border */
+
+.tooltipster-sidetip .tooltipster-arrow-border {
+ border: 10px solid transparent;
+ left: 0;
+ top: 0;
+}
+
+.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border {
+ border-bottom-color: black;
+}
+
+.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border {
+ border-left-color: black;
+}
+
+.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border {
+ border-right-color: black;
+}
+
+.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border {
+ border-top-color: black;
+}
+
+/* tooltipster-arrow-uncropped */
+
+.tooltipster-sidetip .tooltipster-arrow-uncropped {
+ position: relative;
+}
+
+.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped {
+ top: -10px;
+}
+
+.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped {
+ left: -10px;
+}
diff --git a/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.js b/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.js new file mode 100644 index 0000000..e2250a6 --- /dev/null +++ b/src/lib/vendor/tooltipster-4.2.6/tooltipster.bundle.js @@ -0,0 +1,4273 @@ +/**
+ * tooltipster http://iamceege.github.io/tooltipster/
+ * A rockin' custom tooltip jQuery plugin
+ * Developed by Caleb Jacob and Louis Ameline
+ * MIT license
+ */
+(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module unless amdModuleId is set + define(["jquery"], function (a0) { + return (factory(a0)); + }); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(require("jquery")); + } else { + factory(jQuery); + } +}(this, function ($) { + +// This file will be UMDified by a build task. + +var defaults = { + animation: 'fade', + animationDuration: 350, + content: null, + contentAsHTML: false, + contentCloning: false, + debug: true, + delay: 300, + delayTouch: [300, 500], + functionInit: null, + functionBefore: null, + functionReady: null, + functionAfter: null, + functionFormat: null, + IEmin: 6, + interactive: false, + multiple: false, + // will default to document.body, or must be an element positioned at (0, 0) + // in the document, typically like the very top views of an app. + parent: null, + plugins: ['sideTip'], + repositionOnScroll: false, + restoration: 'none', + selfDestruction: true, + theme: [], + timer: 0, + trackerInterval: 500, + trackOrigin: false, + trackTooltip: false, + trigger: 'hover', + triggerClose: { + click: false, + mouseleave: false, + originClick: false, + scroll: false, + tap: false, + touchleave: false + }, + triggerOpen: { + click: false, + mouseenter: false, + tap: false, + touchstart: false + }, + updateAnimation: 'rotate', + zIndex: 9999999 + }, + // we'll avoid using the 'window' global as a good practice but npm's + // jquery@<2.1.0 package actually requires a 'window' global, so not sure + // it's useful at all + win = (typeof window != 'undefined') ? window : null, + // env will be proxied by the core for plugins to have access its properties + env = { + // detect if this device can trigger touch events. Better have a false + // positive (unused listeners, that's ok) than a false negative. + // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js + // http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript + hasTouchCapability: !!( + win + && ( 'ontouchstart' in win + || (win.DocumentTouch && win.document instanceof win.DocumentTouch) + || win.navigator.maxTouchPoints + ) + ), + hasTransitions: transitionSupport(), + IE: false, + // don't set manually, it will be updated by a build task after the manifest + semVer: '4.2.6', + window: win + }, + core = function() { + + // core variables + + // the core emitters + this.__$emitterPrivate = $({}); + this.__$emitterPublic = $({}); + this.__instancesLatestArr = []; + // collects plugin constructors + this.__plugins = {}; + // proxy env variables for plugins who might use them + this._env = env; + }; + +// core methods +core.prototype = { + + /** + * A function to proxy the public methods of an object onto another + * + * @param {object} constructor The constructor to bridge + * @param {object} obj The object that will get new methods (an instance or the core) + * @param {string} pluginName A plugin name for the console log message + * @return {core} + * @private + */ + __bridge: function(constructor, obj, pluginName) { + + // if it's not already bridged + if (!obj[pluginName]) { + + var fn = function() {}; + fn.prototype = constructor; + + var pluginInstance = new fn(); + + // the _init method has to exist in instance constructors but might be missing + // in core constructors + if (pluginInstance.__init) { + pluginInstance.__init(obj); + } + + $.each(constructor, function(methodName, fn) { + + // don't proxy "private" methods, only "protected" and public ones + if (methodName.indexOf('__') != 0) { + + // if the method does not exist yet + if (!obj[methodName]) { + + obj[methodName] = function() { + return pluginInstance[methodName].apply(pluginInstance, Array.prototype.slice.apply(arguments)); + }; + + // remember to which plugin this method corresponds (several plugins may + // have methods of the same name, we need to be sure) + obj[methodName].bridged = pluginInstance; + } + else if (defaults.debug) { + + console.log('The '+ methodName +' method of the '+ pluginName + +' plugin conflicts with another plugin or native methods'); + } + } + }); + + obj[pluginName] = pluginInstance; + } + + return this; + }, + + /** + * For mockup in Node env if need be, for testing purposes + * + * @return {core} + * @private + */ + __setWindow: function(window) { + env.window = window; + return this; + }, + + /** + * Returns a ruler, a tool to help measure the size of a tooltip under + * various settings. Meant for plugins + * + * @see Ruler + * @return {object} A Ruler instance + * @protected + */ + _getRuler: function($tooltip) { + return new Ruler($tooltip); + }, + + /** + * For internal use by plugins, if needed + * + * @return {core} + * @protected + */ + _off: function() { + this.__$emitterPrivate.off.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For internal use by plugins, if needed + * + * @return {core} + * @protected + */ + _on: function() { + this.__$emitterPrivate.on.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For internal use by plugins, if needed + * + * @return {core} + * @protected + */ + _one: function() { + this.__$emitterPrivate.one.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * Returns (getter) or adds (setter) a plugin + * + * @param {string|object} plugin Provide a string (in the full form + * "namespace.name") to use as as getter, an object to use as a setter + * @return {object|core} + * @protected + */ + _plugin: function(plugin) { + + var self = this; + + // getter + if (typeof plugin == 'string') { + + var pluginName = plugin, + p = null; + + // if the namespace is provided, it's easy to search + if (pluginName.indexOf('.') > 0) { + p = self.__plugins[pluginName]; + } + // otherwise, return the first name that matches + else { + $.each(self.__plugins, function(i, plugin) { + + if (plugin.name.substring(plugin.name.length - pluginName.length - 1) == '.'+ pluginName) { + p = plugin; + return false; + } + }); + } + + return p; + } + // setter + else { + + // force namespaces + if (plugin.name.indexOf('.') < 0) { + throw new Error('Plugins must be namespaced'); + } + + self.__plugins[plugin.name] = plugin; + + // if the plugin has core features + if (plugin.core) { + + // bridge non-private methods onto the core to allow new core methods + self.__bridge(plugin.core, self, plugin.name); + } + + return this; + } + }, + + /** + * Trigger events on the core emitters + * + * @returns {core} + * @protected + */ + _trigger: function() { + + var args = Array.prototype.slice.apply(arguments); + + if (typeof args[0] == 'string') { + args[0] = { type: args[0] }; + } + + // note: the order of emitters matters + this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate, args); + this.__$emitterPublic.trigger.apply(this.__$emitterPublic, args); + + return this; + }, + + /** + * Returns instances of all tooltips in the page or an a given element + * + * @param {string|HTML object collection} selector optional Use this + * parameter to restrict the set of objects that will be inspected + * for the retrieval of instances. By default, all instances in the + * page are returned. + * @return {array} An array of instance objects + * @public + */ + instances: function(selector) { + + var instances = [], + sel = selector || '.tooltipstered'; + + $(sel).each(function() { + + var $this = $(this), + ns = $this.data('tooltipster-ns'); + + if (ns) { + + $.each(ns, function(i, namespace) { + instances.push($this.data(namespace)); + }); + } + }); + + return instances; + }, + + /** + * Returns the Tooltipster objects generated by the last initializing call + * + * @return {array} An array of instance objects + * @public + */ + instancesLatest: function() { + return this.__instancesLatestArr; + }, + + /** + * For public use only, not to be used by plugins (use ::_off() instead) + * + * @return {core} + * @public + */ + off: function() { + this.__$emitterPublic.off.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For public use only, not to be used by plugins (use ::_on() instead) + * + * @return {core} + * @public + */ + on: function() { + this.__$emitterPublic.on.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For public use only, not to be used by plugins (use ::_one() instead) + * + * @return {core} + * @public + */ + one: function() { + this.__$emitterPublic.one.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * Returns all HTML elements which have one or more tooltips + * + * @param {string} selector optional Use this to restrict the results + * to the descendants of an element + * @return {array} An array of HTML elements + * @public + */ + origins: function(selector) { + + var sel = selector ? + selector +' ' : + ''; + + return $(sel +'.tooltipstered').toArray(); + }, + + /** + * Change default options for all future instances + * + * @param {object} d The options that should be made defaults + * @return {core} + * @public + */ + setDefaults: function(d) { + $.extend(defaults, d); + return this; + }, + + /** + * For users to trigger their handlers on the public emitter + * + * @returns {core} + * @public + */ + triggerHandler: function() { + this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + return this; + } +}; + +// $.tooltipster will be used to call core methods +$.tooltipster = new core(); + +// the Tooltipster instance class (mind the capital T) +$.Tooltipster = function(element, options) { + + // list of instance variables + + // stack of custom callbacks provided as parameters to API methods + this.__callbacks = { + close: [], + open: [] + }; + // the schedule time of DOM removal + this.__closingTime; + // this will be the user content shown in the tooltip. A capital "C" is used + // because there is also a method called content() + this.__Content; + // for the size tracker + this.__contentBcr; + // to disable the tooltip after destruction + this.__destroyed = false; + // we can't emit directly on the instance because if a method with the same + // name as the event exists, it will be called by jQuery. Se we use a plain + // object as emitter. This emitter is for internal use by plugins, + // if needed. + this.__$emitterPrivate = $({}); + // this emitter is for the user to listen to events without risking to mess + // with our internal listeners + this.__$emitterPublic = $({}); + this.__enabled = true; + // the reference to the gc interval + this.__garbageCollector; + // various position and size data recomputed before each repositioning + this.__Geometry; + // the tooltip position, saved after each repositioning by a plugin + this.__lastPosition; + // a unique namespace per instance + this.__namespace = 'tooltipster-'+ Math.round(Math.random()*1000000); + this.__options; + // will be used to support origins in scrollable areas + this.__$originParents; + this.__pointerIsOverOrigin = false; + // to remove themes if needed + this.__previousThemes = []; + // the state can be either: appearing, stable, disappearing, closed + this.__state = 'closed'; + // timeout references + this.__timeouts = { + close: [], + open: null + }; + // store touch events to be able to detect emulated mouse events + this.__touchEvents = []; + // the reference to the tracker interval + this.__tracker = null; + // the element to which this tooltip is associated + this._$origin; + // this will be the tooltip element (jQuery wrapped HTML element). + // It's the job of a plugin to create it and append it to the DOM + this._$tooltip; + + // launch + this.__init(element, options); +}; + +$.Tooltipster.prototype = { + + /** + * @param origin + * @param options + * @private + */ + __init: function(origin, options) { + + var self = this; + + self._$origin = $(origin); + self.__options = $.extend(true, {}, defaults, options); + + // some options may need to be reformatted + self.__optionsFormat(); + + // don't run on old IE if asked no to + if ( !env.IE + || env.IE >= self.__options.IEmin + ) { + + // note: the content is null (empty) by default and can stay that + // way if the plugin remains initialized but not fed any content. The + // tooltip will just not appear. + + // let's save the initial value of the title attribute for later + // restoration if need be. + var initialTitle = null; + + // it will already have been saved in case of multiple tooltips + if (self._$origin.data('tooltipster-initialTitle') === undefined) { + + initialTitle = self._$origin.attr('title'); + + // we do not want initialTitle to be "undefined" because + // of how jQuery's .data() method works + if (initialTitle === undefined) initialTitle = null; + + self._$origin.data('tooltipster-initialTitle', initialTitle); + } + + // If content is provided in the options, it has precedence over the + // title attribute. + // Note: an empty string is considered content, only 'null' represents + // the absence of content. + // Also, an existing title="" attribute will result in an empty string + // content + if (self.__options.content !== null) { + self.__contentSet(self.__options.content); + } + else { + + var selector = self._$origin.attr('data-tooltip-content'), + $el; + + if (selector){ + $el = $(selector); + } + + if ($el && $el[0]) { + self.__contentSet($el.first()); + } + else { + self.__contentSet(initialTitle); + } + } + + self._$origin + // strip the title off of the element to prevent the default tooltips + // from popping up + .removeAttr('title') + // to be able to find all instances on the page later (upon window + // events in particular) + .addClass('tooltipstered'); + + // set listeners on the origin + self.__prepareOrigin(); + + // set the garbage collector + self.__prepareGC(); + + // init plugins + $.each(self.__options.plugins, function(i, pluginName) { + self._plug(pluginName); + }); + + // to detect swiping + if (env.hasTouchCapability) { + $(env.window.document.body).on('touchmove.'+ self.__namespace +'-triggerOpen', function(event) { + self._touchRecordEvent(event); + }); + } + + self + // prepare the tooltip when it gets created. This event must + // be fired by a plugin + ._on('created', function() { + self.__prepareTooltip(); + }) + // save position information when it's sent by a plugin + ._on('repositioned', function(e) { + self.__lastPosition = e.position; + }); + } + else { + self.__options.disabled = true; + } + }, + + /** + * Insert the content into the appropriate HTML element of the tooltip + * + * @returns {self} + * @private + */ + __contentInsert: function() { + + var self = this, + $el = self._$tooltip.find('.tooltipster-content'), + formattedContent = self.__Content, + format = function(content) { + formattedContent = content; + }; + + self._trigger({ + type: 'format', + content: self.__Content, + format: format + }); + + if (self.__options.functionFormat) { + + formattedContent = self.__options.functionFormat.call( + self, + self, + { origin: self._$origin[0] }, + self.__Content + ); + } + + if (typeof formattedContent === 'string' && !self.__options.contentAsHTML) { + $el.text(formattedContent); + } + else { + $el + .empty() + .append(formattedContent); + } + + return self; + }, + + /** + * Save the content, cloning it beforehand if need be + * + * @param content + * @returns {self} + * @private + */ + __contentSet: function(content) { + + // clone if asked. Cloning the object makes sure that each instance has its + // own version of the content (in case a same object were provided for several + // instances) + // reminder: typeof null === object + if (content instanceof $ && this.__options.contentCloning) { + content = content.clone(true); + } + + this.__Content = content; + + this._trigger({ + type: 'updated', + content: content + }); + + return this; + }, + + /** + * Error message about a method call made after destruction + * + * @private + */ + __destroyError: function() { + throw new Error('This tooltip has been destroyed and cannot execute your method call.'); + }, + + /** + * Gather all information about dimensions and available space, + * called before every repositioning + * + * @private + * @returns {object} + */ + __geometry: function() { + + var self = this, + $target = self._$origin, + originIsArea = self._$origin.is('area'); + + // if this._$origin is a map area, the target we'll need + // the dimensions of is actually the image using the map, + // not the area itself + if (originIsArea) { + + var mapName = self._$origin.parent().attr('name'); + + $target = $('img[usemap="#'+ mapName +'"]'); + } + + var bcr = $target[0].getBoundingClientRect(), + $document = $(env.window.document), + $window = $(env.window), + $parent = $target, + // some useful properties of important elements + geo = { + // available space for the tooltip, see down below + available: { + document: null, + window: null + }, + document: { + size: { + height: $document.height(), + width: $document.width() + } + }, + window: { + scroll: { + // the second ones are for IE compatibility + left: env.window.scrollX || env.window.document.documentElement.scrollLeft, + top: env.window.scrollY || env.window.document.documentElement.scrollTop + }, + size: { + height: $window.height(), + width: $window.width() + } + }, + origin: { + // the origin has a fixed lineage if itself or one of its + // ancestors has a fixed position + fixedLineage: false, + // relative to the document + offset: {}, + size: { + height: bcr.bottom - bcr.top, + width: bcr.right - bcr.left + }, + usemapImage: originIsArea ? $target[0] : null, + // relative to the window + windowOffset: { + bottom: bcr.bottom, + left: bcr.left, + right: bcr.right, + top: bcr.top + } + } + }, + geoFixed = false; + + // if the element is a map area, some properties may need + // to be recalculated + if (originIsArea) { + + var shape = self._$origin.attr('shape'), + coords = self._$origin.attr('coords'); + + if (coords) { + + coords = coords.split(','); + + $.map(coords, function(val, i) { + coords[i] = parseInt(val); + }); + } + + // if the image itself is the area, nothing more to do + if (shape != 'default') { + + switch(shape) { + + case 'circle': + + var circleCenterLeft = coords[0], + circleCenterTop = coords[1], + circleRadius = coords[2], + areaTopOffset = circleCenterTop - circleRadius, + areaLeftOffset = circleCenterLeft - circleRadius; + + geo.origin.size.height = circleRadius * 2; + geo.origin.size.width = geo.origin.size.height; + + geo.origin.windowOffset.left += areaLeftOffset; + geo.origin.windowOffset.top += areaTopOffset; + + break; + + case 'rect': + + var areaLeft = coords[0], + areaTop = coords[1], + areaRight = coords[2], + areaBottom = coords[3]; + + geo.origin.size.height = areaBottom - areaTop; + geo.origin.size.width = areaRight - areaLeft; + + geo.origin.windowOffset.left += areaLeft; + geo.origin.windowOffset.top += areaTop; + + break; + + case 'poly': + + var areaSmallestX = 0, + areaSmallestY = 0, + areaGreatestX = 0, + areaGreatestY = 0, + arrayAlternate = 'even'; + + for (var i = 0; i < coords.length; i++) { + + var areaNumber = coords[i]; + + if (arrayAlternate == 'even') { + + if (areaNumber > areaGreatestX) { + + areaGreatestX = areaNumber; + + if (i === 0) { + areaSmallestX = areaGreatestX; + } + } + + if (areaNumber < areaSmallestX) { + areaSmallestX = areaNumber; + } + + arrayAlternate = 'odd'; + } + else { + if (areaNumber > areaGreatestY) { + + areaGreatestY = areaNumber; + + if (i == 1) { + areaSmallestY = areaGreatestY; + } + } + + if (areaNumber < areaSmallestY) { + areaSmallestY = areaNumber; + } + + arrayAlternate = 'even'; + } + } + + geo.origin.size.height = areaGreatestY - areaSmallestY; + geo.origin.size.width = areaGreatestX - areaSmallestX; + + geo.origin.windowOffset.left += areaSmallestX; + geo.origin.windowOffset.top += areaSmallestY; + + break; + } + } + } + + // user callback through an event + var edit = function(r) { + geo.origin.size.height = r.height, + geo.origin.windowOffset.left = r.left, + geo.origin.windowOffset.top = r.top, + geo.origin.size.width = r.width + }; + + self._trigger({ + type: 'geometry', + edit: edit, + geometry: { + height: geo.origin.size.height, + left: geo.origin.windowOffset.left, + top: geo.origin.windowOffset.top, + width: geo.origin.size.width + } + }); + + // calculate the remaining properties with what we got + + geo.origin.windowOffset.right = geo.origin.windowOffset.left + geo.origin.size.width; + geo.origin.windowOffset.bottom = geo.origin.windowOffset.top + geo.origin.size.height; + + geo.origin.offset.left = geo.origin.windowOffset.left + geo.window.scroll.left; + geo.origin.offset.top = geo.origin.windowOffset.top + geo.window.scroll.top; + geo.origin.offset.bottom = geo.origin.offset.top + geo.origin.size.height; + geo.origin.offset.right = geo.origin.offset.left + geo.origin.size.width; + + // the space that is available to display the tooltip relatively to the document + geo.available.document = { + bottom: { + height: geo.document.size.height - geo.origin.offset.bottom, + width: geo.document.size.width + }, + left: { + height: geo.document.size.height, + width: geo.origin.offset.left + }, + right: { + height: geo.document.size.height, + width: geo.document.size.width - geo.origin.offset.right + }, + top: { + height: geo.origin.offset.top, + width: geo.document.size.width + } + }; + + // the space that is available to display the tooltip relatively to the viewport + // (the resulting values may be negative if the origin overflows the viewport) + geo.available.window = { + bottom: { + // the inner max is here to make sure the available height is no bigger + // than the viewport height (when the origin is off screen at the top). + // The outer max just makes sure that the height is not negative (when + // the origin overflows at the bottom). + height: Math.max(geo.window.size.height - Math.max(geo.origin.windowOffset.bottom, 0), 0), + width: geo.window.size.width + }, + left: { + height: geo.window.size.height, + width: Math.max(geo.origin.windowOffset.left, 0) + }, + right: { + height: geo.window.size.height, + width: Math.max(geo.window.size.width - Math.max(geo.origin.windowOffset.right, 0), 0) + }, + top: { + height: Math.max(geo.origin.windowOffset.top, 0), + width: geo.window.size.width + } + }; + + while ($parent[0].tagName.toLowerCase() != 'html') { + + if ($parent.css('position') == 'fixed') { + geo.origin.fixedLineage = true; + break; + } + + $parent = $parent.parent(); + } + + return geo; + }, + + /** + * Some options may need to be formated before being used + * + * @returns {self} + * @private + */ + __optionsFormat: function() { + + if (typeof this.__options.animationDuration == 'number') { + this.__options.animationDuration = [this.__options.animationDuration, this.__options.animationDuration]; + } + + if (typeof this.__options.delay == 'number') { + this.__options.delay = [this.__options.delay, this.__options.delay]; + } + + if (typeof this.__options.delayTouch == 'number') { + this.__options.delayTouch = [this.__options.delayTouch, this.__options.delayTouch]; + } + + if (typeof this.__options.theme == 'string') { + this.__options.theme = [this.__options.theme]; + } + + // determine the future parent + if (this.__options.parent === null) { + this.__options.parent = $(env.window.document.body); + } + else if (typeof this.__options.parent == 'string') { + this.__options.parent = $(this.__options.parent); + } + + if (this.__options.trigger == 'hover') { + + this.__options.triggerOpen = { + mouseenter: true, + touchstart: true + }; + + this.__options.triggerClose = { + mouseleave: true, + originClick: true, + touchleave: true + }; + } + else if (this.__options.trigger == 'click') { + + this.__options.triggerOpen = { + click: true, + tap: true + }; + + this.__options.triggerClose = { + click: true, + tap: true + }; + } + + // for the plugins + this._trigger('options'); + + return this; + }, + + /** + * Schedules or cancels the garbage collector task + * + * @returns {self} + * @private + */ + __prepareGC: function() { + + var self = this; + + // in case the selfDestruction option has been changed by a method call + if (self.__options.selfDestruction) { + + // the GC task + self.__garbageCollector = setInterval(function() { + + var now = new Date().getTime(); + + // forget the old events + self.__touchEvents = $.grep(self.__touchEvents, function(event, i) { + // 1 minute + return now - event.time > 60000; + }); + + // auto-destruct if the origin is gone + if (!bodyContains(self._$origin)) { + + self.close(function(){ + self.destroy(); + }); + } + }, 20000); + } + else { + clearInterval(self.__garbageCollector); + } + + return self; + }, + + /** + * Sets listeners on the origin if the open triggers require them. + * Unlike the listeners set at opening time, these ones + * remain even when the tooltip is closed. It has been made a + * separate method so it can be called when the triggers are + * changed in the options. Closing is handled in _open() + * because of the bindings that may be needed on the tooltip + * itself + * + * @returns {self} + * @private + */ + __prepareOrigin: function() { + + var self = this; + + // in case we're resetting the triggers + self._$origin.off('.'+ self.__namespace +'-triggerOpen'); + + // if the device is touch capable, even if only mouse triggers + // are asked, we need to listen to touch events to know if the mouse + // events are actually emulated (so we can ignore them) + if (env.hasTouchCapability) { + + self._$origin.on( + 'touchstart.'+ self.__namespace +'-triggerOpen ' + + 'touchend.'+ self.__namespace +'-triggerOpen ' + + 'touchcancel.'+ self.__namespace +'-triggerOpen', + function(event){ + self._touchRecordEvent(event); + } + ); + } + + // mouse click and touch tap work the same way + if ( self.__options.triggerOpen.click + || (self.__options.triggerOpen.tap && env.hasTouchCapability) + ) { + + var eventNames = ''; + if (self.__options.triggerOpen.click) { + eventNames += 'click.'+ self.__namespace +'-triggerOpen '; + } + if (self.__options.triggerOpen.tap && env.hasTouchCapability) { + eventNames += 'touchend.'+ self.__namespace +'-triggerOpen'; + } + + self._$origin.on(eventNames, function(event) { + if (self._touchIsMeaningfulEvent(event)) { + self._open(event); + } + }); + } + + // mouseenter and touch start work the same way + if ( self.__options.triggerOpen.mouseenter + || (self.__options.triggerOpen.touchstart && env.hasTouchCapability) + ) { + + var eventNames = ''; + if (self.__options.triggerOpen.mouseenter) { + eventNames += 'mouseenter.'+ self.__namespace +'-triggerOpen '; + } + if (self.__options.triggerOpen.touchstart && env.hasTouchCapability) { + eventNames += 'touchstart.'+ self.__namespace +'-triggerOpen'; + } + + self._$origin.on(eventNames, function(event) { + if ( self._touchIsTouchEvent(event) + || !self._touchIsEmulatedEvent(event) + ) { + self.__pointerIsOverOrigin = true; + self._openShortly(event); + } + }); + } + + // info for the mouseleave/touchleave close triggers when they use a delay + if ( self.__options.triggerClose.mouseleave + || (self.__options.triggerClose.touchleave && env.hasTouchCapability) + ) { + + var eventNames = ''; + if (self.__options.triggerClose.mouseleave) { + eventNames += 'mouseleave.'+ self.__namespace +'-triggerOpen '; + } + if (self.__options.triggerClose.touchleave && env.hasTouchCapability) { + eventNames += 'touchend.'+ self.__namespace +'-triggerOpen touchcancel.'+ self.__namespace +'-triggerOpen'; + } + + self._$origin.on(eventNames, function(event) { + + if (self._touchIsMeaningfulEvent(event)) { + self.__pointerIsOverOrigin = false; + } + }); + } + + return self; + }, + + /** + * Do the things that need to be done only once after the tooltip + * HTML element it has been created. It has been made a separate + * method so it can be called when options are changed. Remember + * that the tooltip may actually exist in the DOM before it is + * opened, and present after it has been closed: it's the display + * plugin that takes care of handling it. + * + * @returns {self} + * @private + */ + __prepareTooltip: function() { + + var self = this, + p = self.__options.interactive ? 'auto' : ''; + + // this will be useful to know quickly if the tooltip is in + // the DOM or not + self._$tooltip + .attr('id', self.__namespace) + .css({ + // pointer events + 'pointer-events': p, + zIndex: self.__options.zIndex + }); + + // themes + // remove the old ones and add the new ones + $.each(self.__previousThemes, function(i, theme) { + self._$tooltip.removeClass(theme); + }); + $.each(self.__options.theme, function(i, theme) { + self._$tooltip.addClass(theme); + }); + + self.__previousThemes = $.merge([], self.__options.theme); + + return self; + }, + + /** + * Handles the scroll on any of the parents of the origin (when the + * tooltip is open) + * + * @param {object} event + * @returns {self} + * @private + */ + __scrollHandler: function(event) { + + var self = this; + + if (self.__options.triggerClose.scroll) { + self._close(event); + } + else { + + // if the origin or tooltip have been removed: do nothing, the tracker will + // take care of it later + if (bodyContains(self._$origin) && bodyContains(self._$tooltip)) { + + var geo = null; + + // if the scroll happened on the window + if (event.target === env.window.document) { + + // if the origin has a fixed lineage, window scroll will have no + // effect on its position nor on the position of the tooltip + if (!self.__Geometry.origin.fixedLineage) { + + // we don't need to do anything unless repositionOnScroll is true + // because the tooltip will already have moved with the window + // (and of course with the origin) + if (self.__options.repositionOnScroll) { + self.reposition(event); + } + } + } + // if the scroll happened on another parent of the tooltip, it means + // that it's in a scrollable area and now needs to have its position + // adjusted or recomputed, depending ont the repositionOnScroll + // option. Also, if the origin is partly hidden due to a parent that + // hides its overflow, we'll just hide (not close) the tooltip. + else { + + geo = self.__geometry(); + + var overflows = false; + + // a fixed position origin is not affected by the overflow hiding + // of a parent + if (self._$origin.css('position') != 'fixed') { + + self.__$originParents.each(function(i, el) { + + var $el = $(el), + overflowX = $el.css('overflow-x'), + overflowY = $el.css('overflow-y'); + + if (overflowX != 'visible' || overflowY != 'visible') { + + var bcr = el.getBoundingClientRect(); + + if (overflowX != 'visible') { + + if ( geo.origin.windowOffset.left < bcr.left + || geo.origin.windowOffset.right > bcr.right + ) { + overflows = true; + return false; + } + } + + if (overflowY != 'visible') { + + if ( geo.origin.windowOffset.top < bcr.top + || geo.origin.windowOffset.bottom > bcr.bottom + ) { + overflows = true; + return false; + } + } + } + + // no need to go further if fixed, for the same reason as above + if ($el.css('position') == 'fixed') { + return false; + } + }); + } + + if (overflows) { + self._$tooltip.css('visibility', 'hidden'); + } + else { + + self._$tooltip.css('visibility', 'visible'); + + // reposition + if (self.__options.repositionOnScroll) { + self.reposition(event); + } + // or just adjust offset + else { + + // we have to use offset and not windowOffset because this way, + // only the scroll distance of the scrollable areas are taken into + // account (the scrolltop value of the main window must be + // ignored since the tooltip already moves with it) + var offsetLeft = geo.origin.offset.left - self.__Geometry.origin.offset.left, + offsetTop = geo.origin.offset.top - self.__Geometry.origin.offset.top; + + // add the offset to the position initially computed by the display plugin + self._$tooltip.css({ + left: self.__lastPosition.coord.left + offsetLeft, + top: self.__lastPosition.coord.top + offsetTop + }); + } + } + } + + self._trigger({ + type: 'scroll', + event: event, + geo: geo + }); + } + } + + return self; + }, + + /** + * Changes the state of the tooltip + * + * @param {string} state + * @returns {self} + * @private + */ + __stateSet: function(state) { + + this.__state = state; + + this._trigger({ + type: 'state', + state: state + }); + + return this; + }, + + /** + * Clear appearance timeouts + * + * @returns {self} + * @private + */ + __timeoutsClear: function() { + + // there is only one possible open timeout: the delayed opening + // when the mouseenter/touchstart open triggers are used + clearTimeout(this.__timeouts.open); + this.__timeouts.open = null; + + // ... but several close timeouts: the delayed closing when the + // mouseleave close trigger is used and the timer option + $.each(this.__timeouts.close, function(i, timeout) { + clearTimeout(timeout); + }); + this.__timeouts.close = []; + + return this; + }, + + /** + * Start the tracker that will make checks at regular intervals + * + * @returns {self} + * @private + */ + __trackerStart: function() { + + var self = this, + $content = self._$tooltip.find('.tooltipster-content'); + + // get the initial content size + if (self.__options.trackTooltip) { + self.__contentBcr = $content[0].getBoundingClientRect(); + } + + self.__tracker = setInterval(function() { + + // if the origin or tooltip elements have been removed. + // Note: we could destroy the instance now if the origin has + // been removed but we'll leave that task to our garbage collector + if (!bodyContains(self._$origin) || !bodyContains(self._$tooltip)) { + self._close(); + } + // if everything is alright + else { + + // compare the former and current positions of the origin to reposition + // the tooltip if need be + if (self.__options.trackOrigin) { + + var g = self.__geometry(), + identical = false; + + // compare size first (a change requires repositioning too) + if (areEqual(g.origin.size, self.__Geometry.origin.size)) { + + // for elements that have a fixed lineage (see __geometry()), we track the + // top and left properties (relative to window) + if (self.__Geometry.origin.fixedLineage) { + if (areEqual(g.origin.windowOffset, self.__Geometry.origin.windowOffset)) { + identical = true; + } + } + // otherwise, track total offset (relative to document) + else { + if (areEqual(g.origin.offset, self.__Geometry.origin.offset)) { + identical = true; + } + } + } + + if (!identical) { + + // close the tooltip when using the mouseleave close trigger + // (see https://github.com/iamceege/tooltipster/pull/253) + if (self.__options.triggerClose.mouseleave) { + self._close(); + } + else { + self.reposition(); + } + } + } + + if (self.__options.trackTooltip) { + + var currentBcr = $content[0].getBoundingClientRect(); + + if ( currentBcr.height !== self.__contentBcr.height + || currentBcr.width !== self.__contentBcr.width + ) { + self.reposition(); + self.__contentBcr = currentBcr; + } + } + } + }, self.__options.trackerInterval); + + return self; + }, + + /** + * Closes the tooltip (after the closing delay) + * + * @param event + * @param callback + * @param force Set to true to override a potential refusal of the user's function + * @returns {self} + * @protected + */ + _close: function(event, callback, force) { + + var self = this, + ok = true; + + self._trigger({ + type: 'close', + event: event, + stop: function() { + ok = false; + } + }); + + // a destroying tooltip (force == true) may not refuse to close + if (ok || force) { + + // save the method custom callback and cancel any open method custom callbacks + if (callback) self.__callbacks.close.push(callback); + self.__callbacks.open = []; + + // clear open/close timeouts + self.__timeoutsClear(); + + var finishCallbacks = function() { + + // trigger any close method custom callbacks and reset them + $.each(self.__callbacks.close, function(i,c) { + c.call(self, self, { + event: event, + origin: self._$origin[0] + }); + }); + + self.__callbacks.close = []; + }; + + if (self.__state != 'closed') { + + var necessary = true, + d = new Date(), + now = d.getTime(), + newClosingTime = now + self.__options.animationDuration[1]; + + // the tooltip may already already be disappearing, but if a new + // call to close() is made after the animationDuration was changed + // to 0 (for example), we ought to actually close it sooner than + // previously scheduled. In that case it should be noted that the + // browser will not adapt the animation duration to the new + // animationDuration that was set after the start of the closing + // animation. + // Note: the same thing could be considered at opening, but is not + // really useful since the tooltip is actually opened immediately + // upon a call to _open(). Since it would not make the opening + // animation finish sooner, its sole impact would be to trigger the + // state event and the open callbacks sooner than the actual end of + // the opening animation, which is not great. + if (self.__state == 'disappearing') { + + if ( newClosingTime > self.__closingTime + // in case closing is actually overdue because the script + // execution was suspended. See #679 + && self.__options.animationDuration[1] > 0 + ) { + necessary = false; + } + } + + if (necessary) { + + self.__closingTime = newClosingTime; + + if (self.__state != 'disappearing') { + self.__stateSet('disappearing'); + } + + var finish = function() { + + // stop the tracker + clearInterval(self.__tracker); + + // a "beforeClose" option has been asked several times but would + // probably useless since the content element is still accessible + // via ::content(), and because people can always use listeners + // inside their content to track what's going on. For the sake of + // simplicity, this has been denied. Bur for the rare people who + // really need the option (for old browsers or for the case where + // detaching the content is actually destructive, for file or + // password inputs for example), this event will do the work. + self._trigger({ + type: 'closing', + event: event + }); + + // unbind listeners which are no longer needed + + self._$tooltip + .off('.'+ self.__namespace +'-triggerClose') + .removeClass('tooltipster-dying'); + + // orientationchange, scroll and resize listeners + $(env.window).off('.'+ self.__namespace +'-triggerClose'); + + // scroll listeners + self.__$originParents.each(function(i, el) { + $(el).off('scroll.'+ self.__namespace +'-triggerClose'); + }); + // clear the array to prevent memory leaks + self.__$originParents = null; + + $(env.window.document.body).off('.'+ self.__namespace +'-triggerClose'); + + self._$origin.off('.'+ self.__namespace +'-triggerClose'); + + self._off('dismissable'); + + // a plugin that would like to remove the tooltip from the + // DOM when closed should bind on this + self.__stateSet('closed'); + + // trigger event + self._trigger({ + type: 'after', + event: event + }); + + // call our constructor custom callback function + if (self.__options.functionAfter) { + self.__options.functionAfter.call(self, self, { + event: event, + origin: self._$origin[0] + }); + } + + // call our method custom callbacks functions + finishCallbacks(); + }; + + if (env.hasTransitions) { + + self._$tooltip.css({ + '-moz-animation-duration': self.__options.animationDuration[1] + 'ms', + '-ms-animation-duration': self.__options.animationDuration[1] + 'ms', + '-o-animation-duration': self.__options.animationDuration[1] + 'ms', + '-webkit-animation-duration': self.__options.animationDuration[1] + 'ms', + 'animation-duration': self.__options.animationDuration[1] + 'ms', + 'transition-duration': self.__options.animationDuration[1] + 'ms' + }); + + self._$tooltip + // clear both potential open and close tasks + .clearQueue() + .removeClass('tooltipster-show') + // for transitions only + .addClass('tooltipster-dying'); + + if (self.__options.animationDuration[1] > 0) { + self._$tooltip.delay(self.__options.animationDuration[1]); + } + + self._$tooltip.queue(finish); + } + else { + + self._$tooltip + .stop() + .fadeOut(self.__options.animationDuration[1], finish); + } + } + } + // if the tooltip is already closed, we still need to trigger + // the method custom callbacks + else { + finishCallbacks(); + } + } + + return self; + }, + + /** + * For internal use by plugins, if needed + * + * @returns {self} + * @protected + */ + _off: function() { + this.__$emitterPrivate.off.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For internal use by plugins, if needed + * + * @returns {self} + * @protected + */ + _on: function() { + this.__$emitterPrivate.on.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * For internal use by plugins, if needed + * + * @returns {self} + * @protected + */ + _one: function() { + this.__$emitterPrivate.one.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments)); + return this; + }, + + /** + * Opens the tooltip right away. + * + * @param event + * @param callback Will be called when the opening animation is over + * @returns {self} + * @protected + */ + _open: function(event, callback) { + + var self = this; + + // if the destruction process has not begun and if this was not + // triggered by an unwanted emulated click event + if (!self.__destroying) { + + // check that the origin is still in the DOM + if ( bodyContains(self._$origin) + // if the tooltip is enabled + && self.__enabled + ) { + + var ok = true; + + // if the tooltip is not open yet, we need to call functionBefore. + // otherwise we can jst go on + if (self.__state == 'closed') { + + // trigger an event. The event.stop function allows the callback + // to prevent the opening of the tooltip + self._trigger({ + type: 'before', + event: event, + stop: function() { + ok = false; + } + }); + + if (ok && self.__options.functionBefore) { + + // call our custom function before continuing + ok = self.__options.functionBefore.call(self, self, { + event: event, + origin: self._$origin[0] + }); + } + } + + if (ok !== false) { + + // if there is some content + if (self.__Content !== null) { + + // save the method callback and cancel close method callbacks + if (callback) { + self.__callbacks.open.push(callback); + } + self.__callbacks.close = []; + + // get rid of any appearance timeouts + self.__timeoutsClear(); + + var extraTime, + finish = function() { + + if (self.__state != 'stable') { + self.__stateSet('stable'); + } + + // trigger any open method custom callbacks and reset them + $.each(self.__callbacks.open, function(i,c) { + c.call(self, self, { + origin: self._$origin[0], + tooltip: self._$tooltip[0] + }); + }); + + self.__callbacks.open = []; + }; + + // if the tooltip is already open + if (self.__state !== 'closed') { + + // the timer (if any) will start (or restart) right now + extraTime = 0; + + // if it was disappearing, cancel that + if (self.__state === 'disappearing') { + + self.__stateSet('appearing'); + + if (env.hasTransitions) { + + self._$tooltip + .clearQueue() + .removeClass('tooltipster-dying') + .addClass('tooltipster-show'); + + if (self.__options.animationDuration[0] > 0) { + self._$tooltip.delay(self.__options.animationDuration[0]); + } + + self._$tooltip.queue(finish); + } + else { + // in case the tooltip was currently fading out, bring it back + // to life + self._$tooltip + .stop() + .fadeIn(finish); + } + } + // if the tooltip is already open, we still need to trigger the method + // custom callback + else if (self.__state == 'stable') { + finish(); + } + } + // if the tooltip isn't already open, open it + else { + + // a plugin must bind on this and store the tooltip in this._$tooltip + self.__stateSet('appearing'); + + // the timer (if any) will start when the tooltip has fully appeared + // after its transition + extraTime = self.__options.animationDuration[0]; + + // insert the content inside the tooltip + self.__contentInsert(); + + // reposition the tooltip and attach to the DOM + self.reposition(event, true); + + // animate in the tooltip. If the display plugin wants no css + // animations, it may override the animation option with a + // dummy value that will produce no effect + if (env.hasTransitions) { + + // note: there seems to be an issue with start animations which + // are randomly not played on fast devices in both Chrome and FF, + // couldn't find a way to solve it yet. It seems that applying + // the classes before appending to the DOM helps a little, but + // it messes up some CSS transitions. The issue almost never + // happens when delay[0]==0 though + self._$tooltip + .addClass('tooltipster-'+ self.__options.animation) + .addClass('tooltipster-initial') + .css({ + '-moz-animation-duration': self.__options.animationDuration[0] + 'ms', + '-ms-animation-duration': self.__options.animationDuration[0] + 'ms', + '-o-animation-duration': self.__options.animationDuration[0] + 'ms', + '-webkit-animation-duration': self.__options.animationDuration[0] + 'ms', + 'animation-duration': self.__options.animationDuration[0] + 'ms', + 'transition-duration': self.__options.animationDuration[0] + 'ms' + }); + + setTimeout( + function() { + + // a quick hover may have already triggered a mouseleave + if (self.__state != 'closed') { + + self._$tooltip + .addClass('tooltipster-show') + .removeClass('tooltipster-initial'); + + if (self.__options.animationDuration[0] > 0) { + self._$tooltip.delay(self.__options.animationDuration[0]); + } + + self._$tooltip.queue(finish); + } + }, + 0 + ); + } + else { + + // old browsers will have to live with this + self._$tooltip + .css('display', 'none') + .fadeIn(self.__options.animationDuration[0], finish); + } + + // checks if the origin is removed while the tooltip is open + self.__trackerStart(); + + // NOTE: the listeners below have a '-triggerClose' namespace + // because we'll remove them when the tooltip closes (unlike + // the '-triggerOpen' listeners). So some of them are actually + // not about close triggers, rather about positioning. + + $(env.window) + // reposition on resize + .on('resize.'+ self.__namespace +'-triggerClose', function(e) { + + var $ae = $(document.activeElement); + + // reposition only if the resize event was not triggered upon the opening + // of a virtual keyboard due to an input field being focused within the tooltip + // (otherwise the repositioning would lose the focus) + if ( (!$ae.is('input') && !$ae.is('textarea')) + || !$.contains(self._$tooltip[0], $ae[0]) + ) { + self.reposition(e); + } + }) + // same as below for parents + .on('scroll.'+ self.__namespace +'-triggerClose', function(e) { + self.__scrollHandler(e); + }); + + self.__$originParents = self._$origin.parents(); + + // scrolling may require the tooltip to be moved or even + // repositioned in some cases + self.__$originParents.each(function(i, parent) { + + $(parent).on('scroll.'+ self.__namespace +'-triggerClose', function(e) { + self.__scrollHandler(e); + }); + }); + + if ( self.__options.triggerClose.mouseleave + || (self.__options.triggerClose.touchleave && env.hasTouchCapability) + ) { + + // we use an event to allow users/plugins to control when the mouseleave/touchleave + // close triggers will come to action. It allows to have more triggering elements + // than just the origin and the tooltip for example, or to cancel/delay the closing, + // or to make the tooltip interactive even if it wasn't when it was open, etc. + self._on('dismissable', function(event) { + + if (event.dismissable) { + + if (event.delay) { + + timeout = setTimeout(function() { + // event.event may be undefined + self._close(event.event); + }, event.delay); + + self.__timeouts.close.push(timeout); + } + else { + self._close(event); + } + } + else { + clearTimeout(timeout); + } + }); + + // now set the listeners that will trigger 'dismissable' events + var $elements = self._$origin, + eventNamesIn = '', + eventNamesOut = '', + timeout = null; + + // if we have to allow interaction, bind on the tooltip too + if (self.__options.interactive) { + $elements = $elements.add(self._$tooltip); + } + + if (self.__options.triggerClose.mouseleave) { + eventNamesIn += 'mouseenter.'+ self.__namespace +'-triggerClose '; + eventNamesOut += 'mouseleave.'+ self.__namespace +'-triggerClose '; + } + if (self.__options.triggerClose.touchleave && env.hasTouchCapability) { + eventNamesIn += 'touchstart.'+ self.__namespace +'-triggerClose'; + eventNamesOut += 'touchend.'+ self.__namespace +'-triggerClose touchcancel.'+ self.__namespace +'-triggerClose'; + } + + $elements + // close after some time spent outside of the elements + .on(eventNamesOut, function(event) { + + // it's ok if the touch gesture ended up to be a swipe, + // it's still a "touch leave" situation + if ( self._touchIsTouchEvent(event) + || !self._touchIsEmulatedEvent(event) + ) { + + var delay = (event.type == 'mouseleave') ? + self.__options.delay : + self.__options.delayTouch; + + self._trigger({ + delay: delay[1], + dismissable: true, + event: event, + type: 'dismissable' + }); + } + }) + // suspend the mouseleave timeout when the pointer comes back + // over the elements + .on(eventNamesIn, function(event) { + + // it's also ok if the touch event is a swipe gesture + if ( self._touchIsTouchEvent(event) + || !self._touchIsEmulatedEvent(event) + ) { + self._trigger({ + dismissable: false, + event: event, + type: 'dismissable' + }); + } + }); + } + + // close the tooltip when the origin gets a mouse click (common behavior of + // native tooltips) + if (self.__options.triggerClose.originClick) { + + self._$origin.on('click.'+ self.__namespace + '-triggerClose', function(event) { + + // we could actually let a tap trigger this but this feature just + // does not make sense on touch devices + if ( !self._touchIsTouchEvent(event) + && !self._touchIsEmulatedEvent(event) + ) { + self._close(event); + } + }); + } + + // set the same bindings for click and touch on the body to close the tooltip + if ( self.__options.triggerClose.click + || (self.__options.triggerClose.tap && env.hasTouchCapability) + ) { + + // don't set right away since the click/tap event which triggered this method + // (if it was a click/tap) is going to bubble up to the body, we don't want it + // to close the tooltip immediately after it opened + setTimeout(function() { + + if (self.__state != 'closed') { + + var eventNames = '', + $body = $(env.window.document.body); + + if (self.__options.triggerClose.click) { + eventNames += 'click.'+ self.__namespace +'-triggerClose '; + } + if (self.__options.triggerClose.tap && env.hasTouchCapability) { + eventNames += 'touchend.'+ self.__namespace +'-triggerClose'; + } + + $body.on(eventNames, function(event) { + + if (self._touchIsMeaningfulEvent(event)) { + + self._touchRecordEvent(event); + + if (!self.__options.interactive || !$.contains(self._$tooltip[0], event.target)) { + self._close(event); + } + } + }); + + // needed to detect and ignore swiping + if (self.__options.triggerClose.tap && env.hasTouchCapability) { + + $body.on('touchstart.'+ self.__namespace +'-triggerClose', function(event) { + self._touchRecordEvent(event); + }); + } + } + }, 0); + } + + self._trigger('ready'); + + // call our custom callback + if (self.__options.functionReady) { + self.__options.functionReady.call(self, self, { + origin: self._$origin[0], + tooltip: self._$tooltip[0] + }); + } + } + + // if we have a timer set, let the countdown begin + if (self.__options.timer > 0) { + + var timeout = setTimeout(function() { + self._close(); + }, self.__options.timer + extraTime); + + self.__timeouts.close.push(timeout); + } + } + } + } + } + + return self; + }, + + /** + * When using the mouseenter/touchstart open triggers, this function will + * schedule the opening of the tooltip after the delay, if there is one + * + * @param event + * @returns {self} + * @protected + */ + _openShortly: function(event) { + + var self = this, + ok = true; + + if (self.__state != 'stable' && self.__state != 'appearing') { + + // if a timeout is not already running + if (!self.__timeouts.open) { + + self._trigger({ + type: 'start', + event: event, + stop: function() { + ok = false; + } + }); + + if (ok) { + + var delay = (event.type.indexOf('touch') == 0) ? + self.__options.delayTouch : + self.__options.delay; + + if (delay[0]) { + + self.__timeouts.open = setTimeout(function() { + + self.__timeouts.open = null; + + // open only if the pointer (mouse or touch) is still over the origin. + // The check on the "meaningful event" can only be made here, after some + // time has passed (to know if the touch was a swipe or not) + if (self.__pointerIsOverOrigin && self._touchIsMeaningfulEvent(event)) { + + // signal that we go on + self._trigger('startend'); + + self._open(event); + } + else { + // signal that we cancel + self._trigger('startcancel'); + } + }, delay[0]); + } + else { + // signal that we go on + self._trigger('startend'); + + self._open(event); + } + } + } + } + + return self; + }, + + /** + * Meant for plugins to get their options + * + * @param {string} pluginName The name of the plugin that asks for its options + * @param {object} defaultOptions The default options of the plugin + * @returns {object} The options + * @protected + */ + _optionsExtract: function(pluginName, defaultOptions) { + + var self = this, + options = $.extend(true, {}, defaultOptions); + + // if the plugin options were isolated in a property named after the + // plugin, use them (prevents conflicts with other plugins) + var pluginOptions = self.__options[pluginName]; + + // if not, try to get them as regular options + if (!pluginOptions){ + + pluginOptions = {}; + + $.each(defaultOptions, function(optionName, value) { + + var o = self.__options[optionName]; + + if (o !== undefined) { + pluginOptions[optionName] = o; + } + }); + } + + // let's merge the default options and the ones that were provided. We'd want + // to do a deep copy but not let jQuery merge arrays, so we'll do a shallow + // extend on two levels, that will be enough if options are not more than 1 + // level deep + $.each(options, function(optionName, value) { + + if (pluginOptions[optionName] !== undefined) { + + if (( typeof value == 'object' + && !(value instanceof Array) + && value != null + ) + && + ( typeof pluginOptions[optionName] == 'object' + && !(pluginOptions[optionName] instanceof Array) + && pluginOptions[optionName] != null + ) + ) { + $.extend(options[optionName], pluginOptions[optionName]); + } + else { + options[optionName] = pluginOptions[optionName]; + } + } + }); + + return options; + }, + + /** + * Used at instantiation of the plugin, or afterwards by plugins that activate themselves + * on existing instances + * + * @param {object} pluginName + * @returns {self} + * @protected + */ + _plug: function(pluginName) { + + var plugin = $.tooltipster._plugin(pluginName); + + if (plugin) { + + // if there is a constructor for instances + if (plugin.instance) { + + // proxy non-private methods on the instance to allow new instance methods + $.tooltipster.__bridge(plugin.instance, this, plugin.name); + } + } + else { + throw new Error('The "'+ pluginName +'" plugin is not defined'); + } + + return this; + }, + + /** + * This will return true if the event is a mouse event which was + * emulated by the browser after a touch event. This allows us to + * really dissociate mouse and touch triggers. + * + * There is a margin of error if a real mouse event is fired right + * after (within the delay shown below) a touch event on the same + * element, but hopefully it should not happen often. + * + * @returns {boolean} + * @protected + */ + _touchIsEmulatedEvent: function(event) { + + var isEmulated = false, + now = new Date().getTime(); + + for (var i = this.__touchEvents.length - 1; i >= 0; i--) { + + var e = this.__touchEvents[i]; + + // delay, in milliseconds. It's supposed to be 300ms in + // most browsers (350ms on iOS) to allow a double tap but + // can be less (check out FastClick for more info) + if (now - e.time < 500) { + + if (e.target === event.target) { + isEmulated = true; + } + } + else { + break; + } + } + + return isEmulated; + }, + + /** + * Returns false if the event was an emulated mouse event or + * a touch event involved in a swipe gesture. + * + * @param {object} event + * @returns {boolean} + * @protected + */ + _touchIsMeaningfulEvent: function(event) { + return ( + (this._touchIsTouchEvent(event) && !this._touchSwiped(event.target)) + || (!this._touchIsTouchEvent(event) && !this._touchIsEmulatedEvent(event)) + ); + }, + + /** + * Checks if an event is a touch event + * + * @param {object} event + * @returns {boolean} + * @protected + */ + _touchIsTouchEvent: function(event){ + return event.type.indexOf('touch') == 0; + }, + + /** + * Store touch events for a while to detect swiping and emulated mouse events + * + * @param {object} event + * @returns {self} + * @protected + */ + _touchRecordEvent: function(event) { + + if (this._touchIsTouchEvent(event)) { + event.time = new Date().getTime(); + this.__touchEvents.push(event); + } + + return this; + }, + + /** + * Returns true if a swipe happened after the last touchstart event fired on + * event.target. + * + * We need to differentiate a swipe from a tap before we let the event open + * or close the tooltip. A swipe is when a touchmove (scroll) event happens + * on the body between the touchstart and the touchend events of an element. + * + * @param {object} target The HTML element that may have triggered the swipe + * @returns {boolean} + * @protected + */ + _touchSwiped: function(target) { + + var swiped = false; + + for (var i = this.__touchEvents.length - 1; i >= 0; i--) { + + var e = this.__touchEvents[i]; + + if (e.type == 'touchmove') { + swiped = true; + break; + } + else if ( + e.type == 'touchstart' + && target === e.target + ) { + break; + } + } + + return swiped; + }, + + /** + * Triggers an event on the instance emitters + * + * @returns {self} + * @protected + */ + _trigger: function() { + + var args = Array.prototype.slice.apply(arguments); + + if (typeof args[0] == 'string') { + args[0] = { type: args[0] }; + } + + // add properties to the event + args[0].instance = this; + args[0].origin = this._$origin ? this._$origin[0] : null; + args[0].tooltip = this._$tooltip ? this._$tooltip[0] : null; + + // note: the order of emitters matters + this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate, args); + $.tooltipster._trigger.apply($.tooltipster, args); + this.__$emitterPublic.trigger.apply(this.__$emitterPublic, args); + + return this; + }, + + /** + * Deactivate a plugin on this instance + * + * @returns {self} + * @protected + */ + _unplug: function(pluginName) { + + var self = this; + + // if the plugin has been activated on this instance + if (self[pluginName]) { + + var plugin = $.tooltipster._plugin(pluginName); + + // if there is a constructor for instances + if (plugin.instance) { + + // unbridge + $.each(plugin.instance, function(methodName, fn) { + + // if the method exists (privates methods do not) and comes indeed from + // this plugin (may be missing or come from a conflicting plugin). + if ( self[methodName] + && self[methodName].bridged === self[pluginName] + ) { + delete self[methodName]; + } + }); + } + + // destroy the plugin + if (self[pluginName].__destroy) { + self[pluginName].__destroy(); + } + + // remove the reference to the plugin instance + delete self[pluginName]; + } + + return self; + }, + + /** + * @see self::_close + * @returns {self} + * @public + */ + close: function(callback) { + + if (!this.__destroyed) { + this._close(null, callback); + } + else { + this.__destroyError(); + } + + return this; + }, + + /** + * Sets or gets the content of the tooltip + * + * @returns {mixed|self} + * @public + */ + content: function(content) { + + var self = this; + + // getter method + if (content === undefined) { + return self.__Content; + } + // setter method + else { + + if (!self.__destroyed) { + + // change the content + self.__contentSet(content); + + if (self.__Content !== null) { + + // update the tooltip if it is open + if (self.__state !== 'closed') { + + // reset the content in the tooltip + self.__contentInsert(); + + // reposition and resize the tooltip + self.reposition(); + + // if we want to play a little animation showing the content changed + if (self.__options.updateAnimation) { + + if (env.hasTransitions) { + + // keep the reference in the local scope + var animation = self.__options.updateAnimation; + + self._$tooltip.addClass('tooltipster-update-'+ animation); + + // remove the class after a while. The actual duration of the + // update animation may be shorter, it's set in the CSS rules + setTimeout(function() { + + if (self.__state != 'closed') { + + self._$tooltip.removeClass('tooltipster-update-'+ animation); + } + }, 1000); + } + else { + self._$tooltip.fadeTo(200, 0.5, function() { + if (self.__state != 'closed') { + self._$tooltip.fadeTo(200, 1); + } + }); + } + } + } + } + else { + self._close(); + } + } + else { + self.__destroyError(); + } + + return self; + } + }, + + /** + * Destroys the tooltip + * + * @returns {self} + * @public + */ + destroy: function() { + + var self = this; + + if (!self.__destroyed) { + + if(self.__state != 'closed'){ + + // no closing delay + self.option('animationDuration', 0) + // force closing + ._close(null, null, true); + } + else { + // there might be an open timeout still running + self.__timeoutsClear(); + } + + // send event + self._trigger('destroy'); + + self.__destroyed = true; + + self._$origin + .removeData(self.__namespace) + // remove the open trigger listeners + .off('.'+ self.__namespace +'-triggerOpen'); + + // remove the touch listener + $(env.window.document.body).off('.' + self.__namespace +'-triggerOpen'); + + var ns = self._$origin.data('tooltipster-ns'); + + // if the origin has been removed from DOM, its data may + // well have been destroyed in the process and there would + // be nothing to clean up or restore + if (ns) { + + // if there are no more tooltips on this element + if (ns.length === 1) { + + // optional restoration of a title attribute + var title = null; + if (self.__options.restoration == 'previous') { + title = self._$origin.data('tooltipster-initialTitle'); + } + else if (self.__options.restoration == 'current') { + + // old school technique to stringify when outerHTML is not supported + title = (typeof self.__Content == 'string') ? + self.__Content : + $('<div></div>').append(self.__Content).html(); + } + + if (title) { + self._$origin.attr('title', title); + } + + // final cleaning + + self._$origin.removeClass('tooltipstered'); + + self._$origin + .removeData('tooltipster-ns') + .removeData('tooltipster-initialTitle'); + } + else { + // remove the instance namespace from the list of namespaces of + // tooltips present on the element + ns = $.grep(ns, function(el, i) { + return el !== self.__namespace; + }); + self._$origin.data('tooltipster-ns', ns); + } + } + + // last event + self._trigger('destroyed'); + + // unbind private and public event listeners + self._off(); + self.off(); + + // remove external references, just in case + self.__Content = null; + self.__$emitterPrivate = null; + self.__$emitterPublic = null; + self.__options.parent = null; + self._$origin = null; + self._$tooltip = null; + + // make sure the object is no longer referenced in there to prevent + // memory leaks + $.tooltipster.__instancesLatestArr = $.grep($.tooltipster.__instancesLatestArr, function(el, i) { + return self !== el; + }); + + clearInterval(self.__garbageCollector); + } + else { + self.__destroyError(); + } + + // we return the scope rather than true so that the call to + // .tooltipster('destroy') actually returns the matched elements + // and applies to all of them + return self; + }, + + /** + * Disables the tooltip + * + * @returns {self} + * @public + */ + disable: function() { + + if (!this.__destroyed) { + + // close first, in case the tooltip would not disappear on + // its own (no close trigger) + this._close(); + this.__enabled = false; + + return this; + } + else { + this.__destroyError(); + } + + return this; + }, + + /** + * Returns the HTML element of the origin + * + * @returns {self} + * @public + */ + elementOrigin: function() { + + if (!this.__destroyed) { + return this._$origin[0]; + } + else { + this.__destroyError(); + } + }, + + /** + * Returns the HTML element of the tooltip + * + * @returns {self} + * @public + */ + elementTooltip: function() { + return this._$tooltip ? this._$tooltip[0] : null; + }, + + /** + * Enables the tooltip + * + * @returns {self} + * @public + */ + enable: function() { + this.__enabled = true; + return this; + }, + + /** + * Alias, deprecated in 4.0.0 + * + * @param {function} callback + * @returns {self} + * @public + */ + hide: function(callback) { + return this.close(callback); + }, + + /** + * Returns the instance + * + * @returns {self} + * @public + */ + instance: function() { + return this; + }, + + /** + * For public use only, not to be used by plugins (use ::_off() instead) + * + * @returns {self} + * @public + */ + off: function() { + + if (!this.__destroyed) { + this.__$emitterPublic.off.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + } + + return this; + }, + + /** + * For public use only, not to be used by plugins (use ::_on() instead) + * + * @returns {self} + * @public + */ + on: function() { + + if (!this.__destroyed) { + this.__$emitterPublic.on.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + } + else { + this.__destroyError(); + } + + return this; + }, + + /** + * For public use only, not to be used by plugins + * + * @returns {self} + * @public + */ + one: function() { + + if (!this.__destroyed) { + this.__$emitterPublic.one.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + } + else { + this.__destroyError(); + } + + return this; + }, + + /** + * @see self::_open + * @returns {self} + * @public + */ + open: function(callback) { + + if (!this.__destroyed) { + this._open(null, callback); + } + else { + this.__destroyError(); + } + + return this; + }, + + /** + * Get or set options. For internal use and advanced users only. + * + * @param {string} o Option name + * @param {mixed} val optional A new value for the option + * @return {mixed|self} If val is omitted, the value of the option + * is returned, otherwise the instance itself is returned + * @public + */ + option: function(o, val) { + + // getter + if (val === undefined) { + return this.__options[o]; + } + // setter + else { + + if (!this.__destroyed) { + + // change value + this.__options[o] = val; + + // format + this.__optionsFormat(); + + // re-prepare the triggers if needed + if ($.inArray(o, ['trigger', 'triggerClose', 'triggerOpen']) >= 0) { + this.__prepareOrigin(); + } + + if (o === 'selfDestruction') { + this.__prepareGC(); + } + } + else { + this.__destroyError(); + } + + return this; + } + }, + + /** + * This method is in charge of setting the position and size properties of the tooltip. + * All the hard work is delegated to the display plugin. + * Note: The tooltip may be detached from the DOM at the moment the method is called + * but must be attached by the end of the method call. + * + * @param {object} event For internal use only. Defined if an event such as + * window resizing triggered the repositioning + * @param {boolean} tooltipIsDetached For internal use only. Set this to true if you + * know that the tooltip not being in the DOM is not an issue (typically when the + * tooltip element has just been created but has not been added to the DOM yet). + * @returns {self} + * @public + */ + reposition: function(event, tooltipIsDetached) { + + var self = this; + + if (!self.__destroyed) { + + // if the tooltip is still open and the origin is still in the DOM + if (self.__state != 'closed' && bodyContains(self._$origin)) { + + // if the tooltip has not been removed from DOM manually (or if it + // has been detached on purpose) + if (tooltipIsDetached || bodyContains(self._$tooltip)) { + + if (!tooltipIsDetached) { + // detach in case the tooltip overflows the window and adds + // scrollbars to it, so __geometry can be accurate + self._$tooltip.detach(); + } + + // refresh the geometry object before passing it as a helper + self.__Geometry = self.__geometry(); + + // let a plugin fo the rest + self._trigger({ + type: 'reposition', + event: event, + helper: { + geo: self.__Geometry + } + }); + } + } + } + else { + self.__destroyError(); + } + + return self; + }, + + /** + * Alias, deprecated in 4.0.0 + * + * @param callback + * @returns {self} + * @public + */ + show: function(callback) { + return this.open(callback); + }, + + /** + * Returns some properties about the instance + * + * @returns {object} + * @public + */ + status: function() { + + return { + destroyed: this.__destroyed, + enabled: this.__enabled, + open: this.__state !== 'closed', + state: this.__state + }; + }, + + /** + * For public use only, not to be used by plugins + * + * @returns {self} + * @public + */ + triggerHandler: function() { + + if (!this.__destroyed) { + this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments)); + } + else { + this.__destroyError(); + } + + return this; + } +}; + +$.fn.tooltipster = function() { + + // for using in closures + var args = Array.prototype.slice.apply(arguments), + // common mistake: an HTML element can't be in several tooltips at the same time + contentCloningWarning = 'You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.'; + + // this happens with $(sel).tooltipster(...) when $(sel) does not match anything + if (this.length === 0) { + + // still chainable + return this; + } + // this happens when calling $(sel).tooltipster('methodName or options') + // where $(sel) matches one or more elements + else { + + // method calls + if (typeof args[0] === 'string') { + + var v = '#*$~&'; + + this.each(function() { + + // retrieve the namepaces of the tooltip(s) that exist on that element. + // We will interact with the first tooltip only. + var ns = $(this).data('tooltipster-ns'), + // self represents the instance of the first tooltipster plugin + // associated to the current HTML object of the loop + self = ns ? $(this).data(ns[0]) : null; + + // if the current element holds a tooltipster instance + if (self) { + + if (typeof self[args[0]] === 'function') { + + if ( this.length > 1 + && args[0] == 'content' + && ( args[1] instanceof $ + || (typeof args[1] == 'object' && args[1] != null && args[1].tagName) + ) + && !self.__options.contentCloning + && self.__options.debug + ) { + console.log(contentCloningWarning); + } + + // note : args[1] and args[2] may not be defined + var resp = self[args[0]](args[1], args[2]); + } + else { + throw new Error('Unknown method "'+ args[0] +'"'); + } + + // if the function returned anything other than the instance + // itself (which implies chaining, except for the `instance` method) + if (resp !== self || args[0] === 'instance') { + + v = resp; + + // return false to stop .each iteration on the first element + // matched by the selector + return false; + } + } + else { + throw new Error('You called Tooltipster\'s "'+ args[0] +'" method on an uninitialized element'); + } + }); + + return (v !== '#*$~&') ? v : this; + } + // first argument is undefined or an object: the tooltip is initializing + else { + + // reset the array of last initialized objects + $.tooltipster.__instancesLatestArr = []; + + // is there a defined value for the multiple option in the options object ? + var multipleIsSet = args[0] && args[0].multiple !== undefined, + // if the multiple option is set to true, or if it's not defined but + // set to true in the defaults + multiple = (multipleIsSet && args[0].multiple) || (!multipleIsSet && defaults.multiple), + // same for content + contentIsSet = args[0] && args[0].content !== undefined, + content = (contentIsSet && args[0].content) || (!contentIsSet && defaults.content), + // same for contentCloning + contentCloningIsSet = args[0] && args[0].contentCloning !== undefined, + contentCloning = + (contentCloningIsSet && args[0].contentCloning) + || (!contentCloningIsSet && defaults.contentCloning), + // same for debug + debugIsSet = args[0] && args[0].debug !== undefined, + debug = (debugIsSet && args[0].debug) || (!debugIsSet && defaults.debug); + + if ( this.length > 1 + && ( content instanceof $ + || (typeof content == 'object' && content != null && content.tagName) + ) + && !contentCloning + && debug + ) { + console.log(contentCloningWarning); + } + + // create a tooltipster instance for each element if it doesn't + // already have one or if the multiple option is set, and attach the + // object to it + this.each(function() { + + var go = false, + $this = $(this), + ns = $this.data('tooltipster-ns'), + obj = null; + + if (!ns) { + go = true; + } + else if (multiple) { + go = true; + } + else if (debug) { + console.log('Tooltipster: one or more tooltips are already attached to the element below. Ignoring.'); + console.log(this); + } + + if (go) { + obj = new $.Tooltipster(this, args[0]); + + // save the reference of the new instance + if (!ns) ns = []; + ns.push(obj.__namespace); + $this.data('tooltipster-ns', ns); + + // save the instance itself + $this.data(obj.__namespace, obj); + + // call our constructor custom function. + // we do this here and not in ::init() because we wanted + // the object to be saved in $this.data before triggering + // it + if (obj.__options.functionInit) { + obj.__options.functionInit.call(obj, obj, { + origin: this + }); + } + + // and now the event, for the plugins and core emitter + obj._trigger('init'); + } + + $.tooltipster.__instancesLatestArr.push(obj); + }); + + return this; + } + } +}; + +// Utilities + +/** + * A class to check if a tooltip can fit in given dimensions + * + * @param {object} $tooltip The jQuery wrapped tooltip element, or a clone of it + */ +function Ruler($tooltip) { + + // list of instance variables + + this.$container; + this.constraints = null; + this.__$tooltip; + + this.__init($tooltip); +} + +Ruler.prototype = { + + /** + * Move the tooltip into an invisible div that does not allow overflow to make + * size tests. Note: the tooltip may or may not be attached to the DOM at the + * moment this method is called, it does not matter. + * + * @param {object} $tooltip The object to test. May be just a clone of the + * actual tooltip. + * @private + */ + __init: function($tooltip) { + + this.__$tooltip = $tooltip; + + this.__$tooltip + .css({ + // for some reason we have to specify top and left 0 + left: 0, + // any overflow will be ignored while measuring + overflow: 'hidden', + // positions at (0,0) without the div using 100% of the available width + position: 'absolute', + top: 0 + }) + // overflow must be auto during the test. We re-set this in case + // it were modified by the user + .find('.tooltipster-content') + .css('overflow', 'auto'); + + this.$container = $('<div class="tooltipster-ruler"></div>') + .append(this.__$tooltip) + .appendTo(env.window.document.body); + }, + + /** + * Force the browser to redraw (re-render) the tooltip immediately. This is required + * when you changed some CSS properties and need to make something with it + * immediately, without waiting for the browser to redraw at the end of instructions. + * + * @see http://stackoverflow.com/questions/3485365/how-can-i-force-webkit-to-redraw-repaint-to-propagate-style-changes + * @private + */ + __forceRedraw: function() { + + // note: this would work but for Webkit only + //this.__$tooltip.close(); + //this.__$tooltip[0].offsetHeight; + //this.__$tooltip.open(); + + // works in FF too + var $p = this.__$tooltip.parent(); + this.__$tooltip.detach(); + this.__$tooltip.appendTo($p); + }, + + /** + * Set maximum dimensions for the tooltip. A call to ::measure afterwards + * will tell us if the content overflows or if it's ok + * + * @param {int} width + * @param {int} height + * @return {Ruler} + * @public + */ + constrain: function(width, height) { + + this.constraints = { + width: width, + height: height + }; + + this.__$tooltip.css({ + // we disable display:flex, otherwise the content would overflow without + // creating horizontal scrolling (which we need to detect). + display: 'block', + // reset any previous height + height: '', + // we'll check if horizontal scrolling occurs + overflow: 'auto', + // we'll set the width and see what height is generated and if there + // is horizontal overflow + width: width + }); + + return this; + }, + + /** + * Reset the tooltip content overflow and remove the test container + * + * @returns {Ruler} + * @public + */ + destroy: function() { + + // in case the element was not a clone + this.__$tooltip + .detach() + .find('.tooltipster-content') + .css({ + // reset to CSS value + display: '', + overflow: '' + }); + + this.$container.remove(); + }, + + /** + * Removes any constraints + * + * @returns {Ruler} + * @public + */ + free: function() { + + this.constraints = null; + + // reset to natural size + this.__$tooltip.css({ + display: '', + height: '', + overflow: 'visible', + width: '' + }); + + return this; + }, + + /** + * Returns the size of the tooltip. When constraints are applied, also returns + * whether the tooltip fits in the provided dimensions. + * The idea is to see if the new height is small enough and if the content does + * not overflow horizontally. + * + * @param {int} width + * @param {int} height + * @returns {object} An object with a bool `fits` property and a `size` property + * @public + */ + measure: function() { + + this.__forceRedraw(); + + var tooltipBcr = this.__$tooltip[0].getBoundingClientRect(), + result = { size: { + // bcr.width/height are not defined in IE8- but in this + // case, bcr.right/bottom will have the same value + // except in iOS 8+ where tooltipBcr.bottom/right are wrong + // after scrolling for reasons yet to be determined. + // tooltipBcr.top/left might not be 0, see issue #514 + height: tooltipBcr.height || (tooltipBcr.bottom - tooltipBcr.top), + width: tooltipBcr.width || (tooltipBcr.right - tooltipBcr.left) + }}; + + if (this.constraints) { + + // note: we used to use offsetWidth instead of boundingRectClient but + // it returned rounded values, causing issues with sub-pixel layouts. + + // note2: noticed that the bcrWidth of text content of a div was once + // greater than the bcrWidth of its container by 1px, causing the final + // tooltip box to be too small for its content. However, evaluating + // their widths one against the other (below) surprisingly returned + // equality. Happened only once in Chrome 48, was not able to reproduce + // => just having fun with float position values... + + var $content = this.__$tooltip.find('.tooltipster-content'), + height = this.__$tooltip.outerHeight(), + contentBcr = $content[0].getBoundingClientRect(), + fits = { + height: height <= this.constraints.height, + width: ( + // this condition accounts for min-width property that + // may apply + tooltipBcr.width <= this.constraints.width + // the -1 is here because scrollWidth actually returns + // a rounded value, and may be greater than bcr.width if + // it was rounded up. This may cause an issue for contents + // which actually really overflow by 1px or so, but that + // should be rare. Not sure how to solve this efficiently. + // See http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx + && contentBcr.width >= $content[0].scrollWidth - 1 + ) + }; + + result.fits = fits.height && fits.width; + } + + // old versions of IE get the width wrong for some reason and it causes + // the text to be broken to a new line, so we round it up. If the width + // is the width of the screen though, we can assume it is accurate. + if ( env.IE + && env.IE <= 11 + && result.size.width !== env.window.document.documentElement.clientWidth + ) { + result.size.width = Math.ceil(result.size.width) + 1; + } + + return result; + } +}; + +// quick & dirty compare function, not bijective nor multidimensional +function areEqual(a,b) { + var same = true; + $.each(a, function(i, _) { + if (b[i] === undefined || a[i] !== b[i]) { + same = false; + return false; + } + }); + return same; +} + +/** + * A fast function to check if an element is still in the DOM. It + * tries to use an id as ids are indexed by the browser, or falls + * back to jQuery's `contains` method. May fail if two elements + * have the same id, but so be it + * + * @param {object} $obj A jQuery-wrapped HTML element + * @return {boolean} + */ +function bodyContains($obj) { + var id = $obj.attr('id'), + el = id ? env.window.document.getElementById(id) : null; + // must also check that the element with the id is the one we want + return el ? el === $obj[0] : $.contains(env.window.document.body, $obj[0]); +} + +// detect IE versions for dirty fixes +var uA = navigator.userAgent.toLowerCase(); +if (uA.indexOf('msie') != -1) env.IE = parseInt(uA.split('msie')[1]); +else if (uA.toLowerCase().indexOf('trident') !== -1 && uA.indexOf(' rv:11') !== -1) env.IE = 11; +else if (uA.toLowerCase().indexOf('edge/') != -1) env.IE = parseInt(uA.toLowerCase().split('edge/')[1]); + +// detecting support for CSS transitions +function transitionSupport() { + + // env.window is not defined yet when this is called + if (!win) return false; + + var b = win.document.body || win.document.documentElement, + s = b.style, + p = 'transition', + v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms']; + + if (typeof s[p] == 'string') { return true; } + + p = p.charAt(0).toUpperCase() + p.substr(1); + for (var i=0; i<v.length; i++) { + if (typeof s[v[i] + p] == 'string') { return true; } + } + return false; +} + +// we'll return jQuery for plugins not to have to declare it as a dependency, +// but it's done by a build task since it should be included only once at the +// end when we concatenate the main file with a plugin
+// sideTip is Tooltipster's default plugin. +// This file will be UMDified by a build task. + +var pluginName = 'tooltipster.sideTip'; + +$.tooltipster._plugin({ + name: pluginName, + instance: { + /** + * Defaults are provided as a function for an easy override by inheritance + * + * @return {object} An object with the defaults options + * @private + */ + __defaults: function() { + + return { + // if the tooltip should display an arrow that points to the origin + arrow: true, + // the distance in pixels between the tooltip and the origin + distance: 6, + // allows to easily change the position of the tooltip + functionPosition: null, + maxWidth: null, + // used to accomodate the arrow of tooltip if there is one. + // First to make sure that the arrow target is not too close + // to the edge of the tooltip, so the arrow does not overflow + // the tooltip. Secondly when we reposition the tooltip to + // make sure that it's positioned in such a way that the arrow is + // still pointing at the target (and not a few pixels beyond it). + // It should be equal to or greater than half the width of + // the arrow (by width we mean the size of the side which touches + // the side of the tooltip). + minIntersection: 16, + minWidth: 0, + // deprecated in 4.0.0. Listed for _optionsExtract to pick it up + position: null, + side: 'top', + // set to false to position the tooltip relatively to the document rather + // than the window when we open it + viewportAware: true + }; + }, + + /** + * Run once: at instantiation of the plugin + * + * @param {object} instance The tooltipster object that instantiated this plugin + * @private + */ + __init: function(instance) { + + var self = this; + + // list of instance variables + + self.__instance = instance; + self.__namespace = 'tooltipster-sideTip-'+ Math.round(Math.random()*1000000); + self.__previousState = 'closed'; + self.__options; + + // initial formatting + self.__optionsFormat(); + + self.__instance._on('state.'+ self.__namespace, function(event) { + + if (event.state == 'closed') { + self.__close(); + } + else if (event.state == 'appearing' && self.__previousState == 'closed') { + self.__create(); + } + + self.__previousState = event.state; + }); + + // reformat every time the options are changed + self.__instance._on('options.'+ self.__namespace, function() { + self.__optionsFormat(); + }); + + self.__instance._on('reposition.'+ self.__namespace, function(e) { + self.__reposition(e.event, e.helper); + }); + }, + + /** + * Called when the tooltip has closed + * + * @private + */ + __close: function() { + + // detach our content object first, so the next jQuery's remove() + // call does not unbind its event handlers + if (this.__instance.content() instanceof $) { + this.__instance.content().detach(); + } + + // remove the tooltip from the DOM + this.__instance._$tooltip.remove(); + this.__instance._$tooltip = null; + }, + + /** + * Creates the HTML element of the tooltip. + * + * @private + */ + __create: function() { + + // note: we wrap with a .tooltipster-box div to be able to set a margin on it + // (.tooltipster-base must not have one) + var $html = $( + '<div class="tooltipster-base tooltipster-sidetip">' + + '<div class="tooltipster-box">' + + '<div class="tooltipster-content"></div>' + + '</div>' + + '<div class="tooltipster-arrow">' + + '<div class="tooltipster-arrow-uncropped">' + + '<div class="tooltipster-arrow-border"></div>' + + '<div class="tooltipster-arrow-background"></div>' + + '</div>' + + '</div>' + + '</div>' + ); + + // hide arrow if asked + if (!this.__options.arrow) { + $html + .find('.tooltipster-box') + .css('margin', 0) + .end() + .find('.tooltipster-arrow') + .hide(); + } + + // apply min/max width if asked + if (this.__options.minWidth) { + $html.css('min-width', this.__options.minWidth + 'px'); + } + if (this.__options.maxWidth) { + $html.css('max-width', this.__options.maxWidth + 'px'); + } + + this.__instance._$tooltip = $html; + + // tell the instance that the tooltip element has been created + this.__instance._trigger('created'); + }, + + /** + * Used when the plugin is to be unplugged + * + * @private + */ + __destroy: function() { + this.__instance._off('.'+ self.__namespace); + }, + + /** + * (Re)compute this.__options from the options declared to the instance + * + * @private + */ + __optionsFormat: function() { + + var self = this; + + // get the options + self.__options = self.__instance._optionsExtract(pluginName, self.__defaults()); + + // for backward compatibility, deprecated in v4.0.0 + if (self.__options.position) { + self.__options.side = self.__options.position; + } + + // options formatting + + // format distance as a four-cell array if it ain't one yet and then make + // it an object with top/bottom/left/right properties + if (typeof self.__options.distance != 'object') { + self.__options.distance = [self.__options.distance]; + } + if (self.__options.distance.length < 4) { + + if (self.__options.distance[1] === undefined) self.__options.distance[1] = self.__options.distance[0]; + if (self.__options.distance[2] === undefined) self.__options.distance[2] = self.__options.distance[0]; + if (self.__options.distance[3] === undefined) self.__options.distance[3] = self.__options.distance[1]; + + self.__options.distance = { + top: self.__options.distance[0], + right: self.__options.distance[1], + bottom: self.__options.distance[2], + left: self.__options.distance[3] + }; + } + + // let's transform: + // 'top' into ['top', 'bottom', 'right', 'left'] + // 'right' into ['right', 'left', 'top', 'bottom'] + // 'bottom' into ['bottom', 'top', 'right', 'left'] + // 'left' into ['left', 'right', 'top', 'bottom'] + if (typeof self.__options.side == 'string') { + + var opposites = { + 'top': 'bottom', + 'right': 'left', + 'bottom': 'top', + 'left': 'right' + }; + + self.__options.side = [self.__options.side, opposites[self.__options.side]]; + + if (self.__options.side[0] == 'left' || self.__options.side[0] == 'right') { + self.__options.side.push('top', 'bottom'); + } + else { + self.__options.side.push('right', 'left'); + } + } + + // misc + // disable the arrow in IE6 unless the arrow option was explicitly set to true + if ( $.tooltipster._env.IE === 6 + && self.__options.arrow !== true + ) { + self.__options.arrow = false; + } + }, + + /** + * This method must compute and set the positioning properties of the + * tooltip (left, top, width, height, etc.). It must also make sure the + * tooltip is eventually appended to its parent (since the element may be + * detached from the DOM at the moment the method is called). + * + * We'll evaluate positioning scenarios to find which side can contain the + * tooltip in the best way. We'll consider things relatively to the window + * (unless the user asks not to), then to the document (if need be, or if the + * user explicitly requires the tests to run on the document). For each + * scenario, measures are taken, allowing us to know how well the tooltip + * is going to fit. After that, a sorting function will let us know what + * the best scenario is (we also allow the user to choose his favorite + * scenario by using an event). + * + * @param {object} helper An object that contains variables that plugin + * creators may find useful (see below) + * @param {object} helper.geo An object with many layout properties + * about objects of interest (window, document, origin). This should help + * plugin users compute the optimal position of the tooltip + * @private + */ + __reposition: function(event, helper) { + + var self = this, + finalResult, + // to know where to put the tooltip, we need to know on which point + // of the x or y axis we should center it. That coordinate is the target + targets = self.__targetFind(helper), + testResults = []; + + // make sure the tooltip is detached while we make tests on a clone + self.__instance._$tooltip.detach(); + + // we could actually provide the original element to the Ruler and + // not a clone, but it just feels right to keep it out of the + // machinery. + var $clone = self.__instance._$tooltip.clone(), + // start position tests session + ruler = $.tooltipster._getRuler($clone), + satisfied = false, + animation = self.__instance.option('animation'); + + // an animation class could contain properties that distort the size + if (animation) { + $clone.removeClass('tooltipster-'+ animation); + } + + // start evaluating scenarios + $.each(['window', 'document'], function(i, container) { + + var takeTest = null; + + // let the user decide to keep on testing or not + self.__instance._trigger({ + container: container, + helper: helper, + satisfied: satisfied, + takeTest: function(bool) { + takeTest = bool; + }, + results: testResults, + type: 'positionTest' + }); + + if ( takeTest == true + || ( takeTest != false + && satisfied == false + // skip the window scenarios if asked. If they are reintegrated by + // the callback of the positionTest event, they will have to be + // excluded using the callback of positionTested + && (container != 'window' || self.__options.viewportAware) + ) + ) { + + // for each allowed side + for (var i=0; i < self.__options.side.length; i++) { + + var distance = { + horizontal: 0, + vertical: 0 + }, + side = self.__options.side[i]; + + if (side == 'top' || side == 'bottom') { + distance.vertical = self.__options.distance[side]; + } + else { + distance.horizontal = self.__options.distance[side]; + } + + // this may have an effect on the size of the tooltip if there are css + // rules for the arrow or something else + self.__sideChange($clone, side); + + $.each(['natural', 'constrained'], function(i, mode) { + + takeTest = null; + + // emit an event on the instance + self.__instance._trigger({ + container: container, + event: event, + helper: helper, + mode: mode, + results: testResults, + satisfied: satisfied, + side: side, + takeTest: function(bool) { + takeTest = bool; + }, + type: 'positionTest' + }); + + if ( takeTest == true + || ( takeTest != false + && satisfied == false + ) + ) { + + var testResult = { + container: container, + // we let the distance as an object here, it can make things a little easier + // during the user's calculations at positionTest/positionTested + distance: distance, + // whether the tooltip can fit in the size of the viewport (does not mean + // that we'll be able to make it initially entirely visible, see 'whole') + fits: null, + mode: mode, + outerSize: null, + side: side, + size: null, + target: targets[side], + // check if the origin has enough surface on screen for the tooltip to + // aim at it without overflowing the viewport (this is due to the thickness + // of the arrow represented by the minIntersection length). + // If not, the tooltip will have to be partly or entirely off screen in + // order to stay docked to the origin. This value will stay null when the + // container is the document, as it is not relevant + whole: null + }; + + // get the size of the tooltip with or without size constraints + var rulerConfigured = (mode == 'natural') ? + ruler.free() : + ruler.constrain( + helper.geo.available[container][side].width - distance.horizontal, + helper.geo.available[container][side].height - distance.vertical + ), + rulerResults = rulerConfigured.measure(); + + testResult.size = rulerResults.size; + testResult.outerSize = { + height: rulerResults.size.height + distance.vertical, + width: rulerResults.size.width + distance.horizontal + }; + + if (mode == 'natural') { + + if( helper.geo.available[container][side].width >= testResult.outerSize.width + && helper.geo.available[container][side].height >= testResult.outerSize.height + ) { + testResult.fits = true; + } + else { + testResult.fits = false; + } + } + else { + testResult.fits = rulerResults.fits; + } + + if (container == 'window') { + + if (!testResult.fits) { + testResult.whole = false; + } + else { + if (side == 'top' || side == 'bottom') { + + testResult.whole = ( + helper.geo.origin.windowOffset.right >= self.__options.minIntersection + && helper.geo.window.size.width - helper.geo.origin.windowOffset.left >= self.__options.minIntersection + ); + } + else { + testResult.whole = ( + helper.geo.origin.windowOffset.bottom >= self.__options.minIntersection + && helper.geo.window.size.height - helper.geo.origin.windowOffset.top >= self.__options.minIntersection + ); + } + } + } + + testResults.push(testResult); + + // we don't need to compute more positions if we have one fully on screen + if (testResult.whole) { + satisfied = true; + } + else { + // don't run the constrained test unless the natural width was greater + // than the available width, otherwise it's pointless as we know it + // wouldn't fit either + if ( testResult.mode == 'natural' + && ( testResult.fits + || testResult.size.width <= helper.geo.available[container][side].width + ) + ) { + return false; + } + } + } + }); + } + } + }); + + // the user may eliminate the unwanted scenarios from testResults, but he's + // not supposed to alter them at this point. functionPosition and the + // position event serve that purpose. + self.__instance._trigger({ + edit: function(r) { + testResults = r; + }, + event: event, + helper: helper, + results: testResults, + type: 'positionTested' + }); + + /** + * Sort the scenarios to find the favorite one. + * + * The favorite scenario is when we can fully display the tooltip on screen, + * even if it means that the middle of the tooltip is no longer centered on + * the middle of the origin (when the origin is near the edge of the screen + * or even partly off screen). We want the tooltip on the preferred side, + * even if it means that we have to use a constrained size rather than a + * natural one (as long as it fits). When the origin is off screen at the top + * the tooltip will be positioned at the bottom (if allowed), if the origin + * is off screen on the right, it will be positioned on the left, etc. + * If there are no scenarios where the tooltip can fit on screen, or if the + * user does not want the tooltip to fit on screen (viewportAware == false), + * we fall back to the scenarios relative to the document. + * + * When the tooltip is bigger than the viewport in either dimension, we stop + * looking at the window scenarios and consider the document scenarios only, + * with the same logic to find on which side it would fit best. + * + * If the tooltip cannot fit the document on any side, we force it at the + * bottom, so at least the user can scroll to see it. + */ + testResults.sort(function(a, b) { + + // best if it's whole (the tooltip fits and adapts to the viewport) + if (a.whole && !b.whole) { + return -1; + } + else if (!a.whole && b.whole) { + return 1; + } + else if (a.whole && b.whole) { + + var ai = self.__options.side.indexOf(a.side), + bi = self.__options.side.indexOf(b.side); + + // use the user's sides fallback array + if (ai < bi) { + return -1; + } + else if (ai > bi) { + return 1; + } + else { + // will be used if the user forced the tests to continue + return a.mode == 'natural' ? -1 : 1; + } + } + else { + + // better if it fits + if (a.fits && !b.fits) { + return -1; + } + else if (!a.fits && b.fits) { + return 1; + } + else if (a.fits && b.fits) { + + var ai = self.__options.side.indexOf(a.side), + bi = self.__options.side.indexOf(b.side); + + // use the user's sides fallback array + if (ai < bi) { + return -1; + } + else if (ai > bi) { + return 1; + } + else { + // will be used if the user forced the tests to continue + return a.mode == 'natural' ? -1 : 1; + } + } + else { + + // if everything failed, this will give a preference to the case where + // the tooltip overflows the document at the bottom + if ( a.container == 'document' + && a.side == 'bottom' + && a.mode == 'natural' + ) { + return -1; + } + else { + return 1; + } + } + } + }); + + finalResult = testResults[0]; + + + // now let's find the coordinates of the tooltip relatively to the window + finalResult.coord = {}; + + switch (finalResult.side) { + + case 'left': + case 'right': + finalResult.coord.top = Math.floor(finalResult.target - finalResult.size.height / 2); + break; + + case 'bottom': + case 'top': + finalResult.coord.left = Math.floor(finalResult.target - finalResult.size.width / 2); + break; + } + + switch (finalResult.side) { + + case 'left': + finalResult.coord.left = helper.geo.origin.windowOffset.left - finalResult.outerSize.width; + break; + + case 'right': + finalResult.coord.left = helper.geo.origin.windowOffset.right + finalResult.distance.horizontal; + break; + + case 'top': + finalResult.coord.top = helper.geo.origin.windowOffset.top - finalResult.outerSize.height; + break; + + case 'bottom': + finalResult.coord.top = helper.geo.origin.windowOffset.bottom + finalResult.distance.vertical; + break; + } + + // if the tooltip can potentially be contained within the viewport dimensions + // and that we are asked to make it fit on screen + if (finalResult.container == 'window') { + + // if the tooltip overflows the viewport, we'll move it accordingly (then it will + // not be centered on the middle of the origin anymore). We only move horizontally + // for top and bottom tooltips and vice versa. + if (finalResult.side == 'top' || finalResult.side == 'bottom') { + + // if there is an overflow on the left + if (finalResult.coord.left < 0) { + + // prevent the overflow unless the origin itself gets off screen (minus the + // margin needed to keep the arrow pointing at the target) + if (helper.geo.origin.windowOffset.right - this.__options.minIntersection >= 0) { + finalResult.coord.left = 0; + } + else { + finalResult.coord.left = helper.geo.origin.windowOffset.right - this.__options.minIntersection - 1; + } + } + // or an overflow on the right + else if (finalResult.coord.left > helper.geo.window.size.width - finalResult.size.width) { + + if (helper.geo.origin.windowOffset.left + this.__options.minIntersection <= helper.geo.window.size.width) { + finalResult.coord.left = helper.geo.window.size.width - finalResult.size.width; + } + else { + finalResult.coord.left = helper.geo.origin.windowOffset.left + this.__options.minIntersection + 1 - finalResult.size.width; + } + } + } + else { + + // overflow at the top + if (finalResult.coord.top < 0) { + + if (helper.geo.origin.windowOffset.bottom - this.__options.minIntersection >= 0) { + finalResult.coord.top = 0; + } + else { + finalResult.coord.top = helper.geo.origin.windowOffset.bottom - this.__options.minIntersection - 1; + } + } + // or at the bottom + else if (finalResult.coord.top > helper.geo.window.size.height - finalResult.size.height) { + + if (helper.geo.origin.windowOffset.top + this.__options.minIntersection <= helper.geo.window.size.height) { + finalResult.coord.top = helper.geo.window.size.height - finalResult.size.height; + } + else { + finalResult.coord.top = helper.geo.origin.windowOffset.top + this.__options.minIntersection + 1 - finalResult.size.height; + } + } + } + } + else { + + // there might be overflow here too but it's easier to handle. If there has + // to be an overflow, we'll make sure it's on the right side of the screen + // (because the browser will extend the document size if there is an overflow + // on the right, but not on the left). The sort function above has already + // made sure that a bottom document overflow is preferred to a top overflow, + // so we don't have to care about it. + + // if there is an overflow on the right + if (finalResult.coord.left > helper.geo.window.size.width - finalResult.size.width) { + + // this may actually create on overflow on the left but we'll fix it in a sec + finalResult.coord.left = helper.geo.window.size.width - finalResult.size.width; + } + + // if there is an overflow on the left + if (finalResult.coord.left < 0) { + + // don't care if it overflows the right after that, we made our best + finalResult.coord.left = 0; + } + } + + + // submit the positioning proposal to the user function which may choose to change + // the side, size and/or the coordinates + + // first, set the rules that corresponds to the proposed side: it may change + // the size of the tooltip, and the custom functionPosition may want to detect the + // size of something before making a decision. So let's make things easier for the + // implementor + self.__sideChange($clone, finalResult.side); + + // add some variables to the helper + helper.tooltipClone = $clone[0]; + helper.tooltipParent = self.__instance.option('parent').parent[0]; + // move informative values to the helper + helper.mode = finalResult.mode; + helper.whole = finalResult.whole; + // add some variables to the helper for the functionPosition callback (these + // will also be added to the event fired by self.__instance._trigger but that's + // ok, we're just being consistent) + helper.origin = self.__instance._$origin[0]; + helper.tooltip = self.__instance._$tooltip[0]; + + // leave only the actionable values in there for functionPosition + delete finalResult.container; + delete finalResult.fits; + delete finalResult.mode; + delete finalResult.outerSize; + delete finalResult.whole; + + // keep only the distance on the relevant side, for clarity + finalResult.distance = finalResult.distance.horizontal || finalResult.distance.vertical; + + // beginners may not be comfortable with the concept of editing the object + // passed by reference, so we provide an edit function and pass a clone + var finalResultClone = $.extend(true, {}, finalResult); + + // emit an event on the instance + self.__instance._trigger({ + edit: function(result) { + finalResult = result; + }, + event: event, + helper: helper, + position: finalResultClone, + type: 'position' + }); + + if (self.__options.functionPosition) { + + var result = self.__options.functionPosition.call(self, self.__instance, helper, finalResultClone); + + if (result) finalResult = result; + } + + // end the positioning tests session (the user might have had a + // use for it during the position event, now it's over) + ruler.destroy(); + + // compute the position of the target relatively to the tooltip root + // element so we can place the arrow and make the needed adjustments + var arrowCoord, + maxVal; + + if (finalResult.side == 'top' || finalResult.side == 'bottom') { + + arrowCoord = { + prop: 'left', + val: finalResult.target - finalResult.coord.left + }; + maxVal = finalResult.size.width - this.__options.minIntersection; + } + else { + + arrowCoord = { + prop: 'top', + val: finalResult.target - finalResult.coord.top + }; + maxVal = finalResult.size.height - this.__options.minIntersection; + } + + // cannot lie beyond the boundaries of the tooltip, minus the + // arrow margin + if (arrowCoord.val < this.__options.minIntersection) { + arrowCoord.val = this.__options.minIntersection; + } + else if (arrowCoord.val > maxVal) { + arrowCoord.val = maxVal; + } + + var originParentOffset; + + // let's convert the window-relative coordinates into coordinates relative to the + // future positioned parent that the tooltip will be appended to + if (helper.geo.origin.fixedLineage) { + + // same as windowOffset when the position is fixed + originParentOffset = helper.geo.origin.windowOffset; + } + else { + + // this assumes that the parent of the tooltip is located at + // (0, 0) in the document, typically like when the parent is + // <body>. + // If we ever allow other types of parent, .tooltipster-ruler + // will have to be appended to the parent to inherit css style + // values that affect the display of the text and such. + originParentOffset = { + left: helper.geo.origin.windowOffset.left + helper.geo.window.scroll.left, + top: helper.geo.origin.windowOffset.top + helper.geo.window.scroll.top + }; + } + + finalResult.coord = { + left: originParentOffset.left + (finalResult.coord.left - helper.geo.origin.windowOffset.left), + top: originParentOffset.top + (finalResult.coord.top - helper.geo.origin.windowOffset.top) + }; + + // set position values on the original tooltip element + + self.__sideChange(self.__instance._$tooltip, finalResult.side); + + if (helper.geo.origin.fixedLineage) { + self.__instance._$tooltip + .css('position', 'fixed'); + } + else { + // CSS default + self.__instance._$tooltip + .css('position', ''); + } + + self.__instance._$tooltip + .css({ + left: finalResult.coord.left, + top: finalResult.coord.top, + // we need to set a size even if the tooltip is in its natural size + // because when the tooltip is positioned beyond the width of the body + // (which is by default the width of the window; it will happen when + // you scroll the window horizontally to get to the origin), its text + // content will otherwise break lines at each word to keep up with the + // body overflow strategy. + height: finalResult.size.height, + width: finalResult.size.width + }) + .find('.tooltipster-arrow') + .css({ + 'left': '', + 'top': '' + }) + .css(arrowCoord.prop, arrowCoord.val); + + // append the tooltip HTML element to its parent + self.__instance._$tooltip.appendTo(self.__instance.option('parent')); + + self.__instance._trigger({ + type: 'repositioned', + event: event, + position: finalResult + }); + }, + + /** + * Make whatever modifications are needed when the side is changed. This has + * been made an independant method for easy inheritance in custom plugins based + * on this default plugin. + * + * @param {object} $obj + * @param {string} side + * @private + */ + __sideChange: function($obj, side) { + + $obj + .removeClass('tooltipster-bottom') + .removeClass('tooltipster-left') + .removeClass('tooltipster-right') + .removeClass('tooltipster-top') + .addClass('tooltipster-'+ side); + }, + + /** + * Returns the target that the tooltip should aim at for a given side. + * The calculated value is a distance from the edge of the window + * (left edge for top/bottom sides, top edge for left/right side). The + * tooltip will be centered on that position and the arrow will be + * positioned there (as much as possible). + * + * @param {object} helper + * @return {integer} + * @private + */ + __targetFind: function(helper) { + + var target = {}, + rects = this.__instance._$origin[0].getClientRects(); + + // these lines fix a Chrome bug (issue #491) + if (rects.length > 1) { + var opacity = this.__instance._$origin.css('opacity'); + if(opacity == 1) { + this.__instance._$origin.css('opacity', 0.99); + rects = this.__instance._$origin[0].getClientRects(); + this.__instance._$origin.css('opacity', 1); + } + } + + // by default, the target will be the middle of the origin + if (rects.length < 2) { + + target.top = Math.floor(helper.geo.origin.windowOffset.left + (helper.geo.origin.size.width / 2)); + target.bottom = target.top; + + target.left = Math.floor(helper.geo.origin.windowOffset.top + (helper.geo.origin.size.height / 2)); + target.right = target.left; + } + // if multiple client rects exist, the element may be text split + // up into multiple lines and the middle of the origin may not be + // best option anymore. We need to choose the best target client rect + else { + + // top: the first + var targetRect = rects[0]; + target.top = Math.floor(targetRect.left + (targetRect.right - targetRect.left) / 2); + + // right: the middle line, rounded down in case there is an even + // number of lines (looks more centered => check out the + // demo with 4 split lines) + if (rects.length > 2) { + targetRect = rects[Math.ceil(rects.length / 2) - 1]; + } + else { + targetRect = rects[0]; + } + target.right = Math.floor(targetRect.top + (targetRect.bottom - targetRect.top) / 2); + + // bottom: the last + targetRect = rects[rects.length - 1]; + target.bottom = Math.floor(targetRect.left + (targetRect.right - targetRect.left) / 2); + + // left: the middle line, rounded up + if (rects.length > 2) { + targetRect = rects[Math.ceil((rects.length + 1) / 2) - 1]; + } + else { + targetRect = rects[rects.length - 1]; + } + + target.left = Math.floor(targetRect.top + (targetRect.bottom - targetRect.top) / 2); + } + + return target; + } + } +}); + +/* a build task will add "return $;" here */ +return $; + +})); diff --git a/src/lib/vendor/underscore-1.9.1.js b/src/lib/vendor/underscore-1.9.1.js new file mode 100644 index 0000000..8219dc5 --- /dev/null +++ b/src/lib/vendor/underscore-1.9.1.js @@ -0,0 +1,1692 @@ +// Underscore.js 1.9.1 +// http://underscorejs.org +// (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` (`self`) in the browser, `global` + // on the server, or `this` in some virtual machines. We use `self` + // instead of `window` for `WebWorker` support. + var root = typeof self == 'object' && self.self === self && self || + typeof global == 'object' && global.global === global && global || + this || + {}; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype; + var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for their old module API. If we're in + // the browser, add `_` as a global object. + // (`nodeType` is checked to ensure that `module` + // and `exports` are not HTML elements.) + if (typeof exports != 'undefined' && !exports.nodeType) { + if (typeof module != 'undefined' && !module.nodeType && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.9.1'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var optimizeCb = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + // The 2-argument case is omitted because we’re not using it. + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + var builtinIteratee; + + // An internal function to generate callbacks that can be applied to each + // element in a collection, returning the desired result — either `identity`, + // an arbitrary callback, a property matcher, or a property accessor. + var cb = function(value, context, argCount) { + if (_.iteratee !== builtinIteratee) return _.iteratee(value, context); + if (value == null) return _.identity; + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value) && !_.isArray(value)) return _.matcher(value); + return _.property(value); + }; + + // External wrapper for our callback generator. Users may customize + // `_.iteratee` if they want additional predicate/iteratee shorthand styles. + // This abstraction hides the internal-only argCount argument. + _.iteratee = builtinIteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // Some functions take a variable number of arguments, or a few expected + // arguments at the beginning and then a variable number of values to operate + // on. This helper accumulates all remaining arguments past the function’s + // argument length (or an explicit `startIndex`), into an array that becomes + // the last argument. Similar to ES6’s "rest parameter". + var restArguments = function(func, startIndex) { + startIndex = startIndex == null ? func.length - 1 : +startIndex; + return function() { + var length = Math.max(arguments.length - startIndex, 0), + rest = Array(length), + index = 0; + for (; index < length; index++) { + rest[index] = arguments[index + startIndex]; + } + switch (startIndex) { + case 0: return func.call(this, rest); + case 1: return func.call(this, arguments[0], rest); + case 2: return func.call(this, arguments[0], arguments[1], rest); + } + var args = Array(startIndex + 1); + for (index = 0; index < startIndex; index++) { + args[index] = arguments[index]; + } + args[startIndex] = rest; + return func.apply(this, args); + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + var shallowProperty = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + var has = function(obj, path) { + return obj != null && hasOwnProperty.call(obj, path); + } + + var deepGet = function(obj, path) { + var length = path.length; + for (var i = 0; i < length; i++) { + if (obj == null) return void 0; + obj = obj[path[i]]; + } + return length ? obj : void 0; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object. + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = shallowProperty('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Create a reducing function iterating left or right. + var createReduce = function(dir) { + // Wrap code that reassigns argument variables in a separate function than + // the one that accesses `arguments.length` to avoid a perf hit. (#1991) + var reducer = function(obj, iteratee, memo, initial) { + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + if (!initial) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + }; + + return function(obj, iteratee, memo, context) { + var initial = arguments.length >= 3; + return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); + }; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey; + var key = keyFinder(obj, predicate, context); + if (key !== void 0 && key !== -1) return obj[key]; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = restArguments(function(obj, path, args) { + var contextPath, func; + if (_.isFunction(path)) { + func = path; + } else if (_.isArray(path)) { + contextPath = path.slice(0, -1); + path = path[path.length - 1]; + } + return _.map(obj, function(context) { + var method = func; + if (!method) { + if (contextPath && contextPath.length) { + context = deepGet(context, contextPath); + } + if (context == null) return void 0; + method = context[path]; + } + return method == null ? method : method.apply(context, args); + }); + }); + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value != null && value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(v, index, list) { + computed = iteratee(v, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = v; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value != null && value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(v, index, list) { + computed = iteratee(v, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = v; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection. + _.shuffle = function(obj) { + return _.sample(obj, Infinity); + }; + + // Sample **n** random values from a collection using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj); + var length = getLength(sample); + n = Math.max(Math.min(n, length), 0); + var last = length - 1; + for (var index = 0; index < n; index++) { + var rand = _.random(index, last); + var temp = sample[index]; + sample[index] = sample[rand]; + sample[rand] = temp; + } + return sample.slice(0, n); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + var index = 0; + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function(value, key, list) { + return { + value: value, + index: index++, + criteria: iteratee(value, key, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior, partition) { + return function(obj, iteratee, context) { + var result = partition ? [[], []] : {}; + iteratee = cb(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (has(result, key)) result[key]++; else result[key] = 1; + }); + + var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (_.isString(obj)) { + // Keep surrogate pair characters together + return obj.match(reStrSymbol); + } + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = group(function(result, value, pass) { + result[pass ? 0 : 1].push(value); + }, true); + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null || array.length < 1) return n == null ? void 0 : []; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function(array, n, guard) { + if (array == null || array.length < 1) return n == null ? void 0 : []; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, Boolean); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, output) { + output = output || []; + var idx = output.length; + for (var i = 0, length = getLength(input); i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + // Flatten current level of array or arguments object. + if (shallow) { + var j = 0, len = value.length; + while (j < len) output[idx++] = value[j++]; + } else { + flatten(value, shallow, strict, output); + idx = output.length; + } + } else if (!strict) { + output[idx++] = value; + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = restArguments(function(array, otherArrays) { + return _.difference(array, otherArrays); + }); + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // The faster algorithm will not work with an iteratee if the iteratee + // is not a one-to-one function, so providing an iteratee will disable + // the faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted && !iteratee) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = restArguments(function(arrays) { + return _.uniq(flatten(arrays, true, true)); + }); + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = getLength(array); i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + var j; + for (j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = restArguments(function(array, rest) { + rest = flatten(rest, true, true); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }); + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices. + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); + } + return result; + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = restArguments(_.unzip); + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. Passing by pairs is the reverse of _.pairs. + _.object = function(list, values) { + var result = {}; + for (var i = 0, length = getLength(list); i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Generator function to create the findIndex and findLastIndex functions. + var createPredicateIndexFinder = function(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + }; + + // Returns the first index on an array-like that passes a predicate test. + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions. + var createIndexFinder = function(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); + } else { + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; + } + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; + } + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + }; + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (stop == null) { + stop = start || 0; + start = 0; + } + if (!step) { + step = stop < start ? -1 : 1; + } + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; + } + + return range; + }; + + // Chunk a single array into multiple arrays, each containing `count` or fewer + // items. + _.chunk = function(array, count) { + if (count == null || count < 1) return []; + var result = []; + var i = 0, length = array.length; + while (i < length) { + result.push(slice.call(array, i, i += count)); + } + return result; + }; + + // Function (ahem) Functions + // ------------------ + + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments. + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = restArguments(function(func, context, args) { + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var bound = restArguments(function(callArgs) { + return executeBound(func, bound, context, this, args.concat(callArgs)); + }); + return bound; + }); + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder by default, allowing any combination of arguments to be + // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. + _.partial = restArguments(function(func, boundArgs) { + var placeholder = _.partial.placeholder; + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }); + + _.partial.placeholder = _; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = restArguments(function(obj, keys) { + keys = flatten(keys, false, false); + var index = keys.length; + if (index < 1) throw new Error('bindAll must be passed function names'); + while (index--) { + var key = keys[index]; + obj[key] = _.bind(obj[key], obj); + } + }); + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = restArguments(function(func, wait, args) { + return setTimeout(function() { + return func.apply(null, args); + }, wait); + }); + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var timeout, context, args, result; + var previous = 0; + if (!options) options = {}; + + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + + var throttled = function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + + throttled.cancel = function() { + clearTimeout(timeout); + previous = 0; + timeout = context = args = null; + }; + + return throttled; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + + var later = function(context, args) { + timeout = null; + if (args) result = func.apply(context, args); + }; + + var debounced = restArguments(function(args) { + if (timeout) clearTimeout(timeout); + if (immediate) { + var callNow = !timeout; + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(this, args); + } else { + timeout = _.delay(later, wait, this, args); + } + + return result; + }); + + debounced.cancel = function() { + clearTimeout(timeout); + timeout = null; + }; + + return debounced; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed on and after the Nth call. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + _.restArguments = restArguments; + + // Object Functions + // ---------------- + + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + var collectNonEnumProps = function(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = _.isFunction(constructor) && constructor.prototype || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + }; + + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys`. + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Returns the results of applying the iteratee to each element of the object. + // In contrast to _.map it returns an object. + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}; + for (var index = 0; index < length; index++) { + var currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Convert an object into a list of `[key, value]` pairs. + // The opposite of _.object. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods`. + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, defaults) { + return function(obj) { + var length = arguments.length; + if (defaults) obj = Object(obj); + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!defaults || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s). + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test. + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; + } + }; + + // Internal pick helper function to determine if `obj` has key `key`. + var keyInObj = function(value, key, obj) { + return key in obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = restArguments(function(obj, keys) { + var result = {}, iteratee = keys[0]; + if (obj == null) return result; + if (_.isFunction(iteratee)) { + if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); + keys = _.allKeys(obj); + } else { + iteratee = keyInObj; + keys = flatten(keys, false, false); + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + return result; + }); + + // Return a copy of the object without the blacklisted properties. + _.omit = restArguments(function(obj, keys) { + var iteratee = keys[0], context; + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + if (keys.length > 1) context = keys[1]; + } else { + keys = _.map(flatten(keys, false, false), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }); + + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + + // Internal recursive comparison function for `isEqual`. + var eq, deepEq; + eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // `null` or `undefined` only equal to itself (strict comparison). + if (a == null || b == null) return false; + // `NaN`s are equivalent, but non-reflexive. + if (a !== a) return b !== b; + // Exhaust primitive checks + var type = typeof a; + if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; + return deepEq(a, b, aStack, bStack); + }; + + // Internal recursive comparison function for `isEqual`. + deepEq = function(a, b, aStack, bStack) { + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN. + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + case '[object Symbol]': + return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); + } + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError, isMap, isWeakMap, isSet, isWeakSet. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakMap', 'Set', 'WeakSet'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). + var nodelist = root.document && root.document.childNodes; + if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + return _.isNumber(obj) && isNaN(obj); + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, path) { + if (!_.isArray(path)) { + return has(obj, path); + } + var length = path.length; + for (var i = 0; i < length; i++) { + var key = path[i]; + if (obj == null || !hasOwnProperty.call(obj, key)) { + return false; + } + obj = obj[key]; + } + return !!length; + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; + }; + + _.noop = function(){}; + + // Creates a function that, when passed an object, will traverse that object’s + // properties down the given `path`, specified as an array of keys or indexes. + _.property = function(path) { + if (!_.isArray(path)) { + return shallowProperty(path); + } + return function(obj) { + return deepGet(obj, path); + }; + }; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + if (obj == null) { + return function(){}; + } + return function(path) { + return !_.isArray(path) ? obj[path] : deepGet(obj, path); + }; + }; + + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); + return function(obj) { + return _.isMatch(obj, attrs); + }; + }; + + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped. + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // Traverses the children of `obj` along `path`. If a child is a function, it + // is invoked with its parent as context. Returns the value of the final + // child, or `fallback` if any child is undefined. + _.result = function(obj, path, fallback) { + if (!_.isArray(path)) path = [path]; + var length = path.length; + if (!length) { + return _.isFunction(fallback) ? fallback.call(obj) : fallback; + } + for (var i = 0; i < length; i++) { + var prop = obj == null ? void 0 : obj[path[i]]; + if (prop === void 0) { + prop = fallback; + i = length; // Ensure we don't continue iterating. + } + obj = _.isFunction(prop) ? prop.call(obj) : prop; + } + return obj; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate: /<%([\s\S]+?)%>/g, + interpolate: /<%=([\s\S]+?)%>/g, + escape: /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escapeRegExp, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offset. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + var render; + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var chainResult = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return chainResult(this, func.apply(_, args)); + }; + }); + return _; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return chainResult(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return chainResult(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; + }; + + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return String(this._wrapped); + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define == 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}()); |