Bring AIS-visa-auto extension v2.4.1.2
BIN
Screenshot-1.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
Screenshot-2.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
Screenshot-3.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
Screenshot-4.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
Screenshot-5.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
Screenshot.png
Normal file
|
After Width: | Height: | Size: 145 KiB |
7
css/bootstrap.min.css
vendored
Normal file
39
css/styles.css
Normal file
@ -0,0 +1,39 @@
|
||||
@font-face {
|
||||
font-family: Quicksand;
|
||||
src: url(../fonts/Quicksand.ttf);
|
||||
}
|
||||
|
||||
:root {
|
||||
--font-fallback: BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-sans;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Quicksand", var(--font-fallback);
|
||||
}
|
||||
|
||||
html {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #fdf8ea;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h2 span {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: justify;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
1306
css/sweetalert.css
Normal file
BIN
disabled.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
fonts/Quicksand.ttf
Normal file
BIN
icon128.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
icon16.png
Normal file
|
After Width: | Height: | Size: 558 B |
BIN
icon48.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
66
index.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AIS Visa Auto Rescheduler</title>
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css"></link>
|
||||
<link rel="stylesheet" href="css/styles.css"></link>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h4 class="mt-2 mb-0">AIS Visa Auto Rescheduler<br><span id="version"></span></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h3 class="my-2" id="credits">50</h3>
|
||||
<p class="my-2 text-center">Credits left.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="mt-2">
|
||||
<div class="form-check form-switch" style="text-align: left;">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="activate">
|
||||
<label class="form-check-label" for="activate">Activate the script</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<div class="form-check form-switch" style="text-align: left;">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="autobook">
|
||||
<label class="form-check-label" for="autobook">Enable Autobook</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<input type="range" id="frequency" name="frequency" min="1" max="10" step="0.5">
|
||||
<label for="frequency">Frequency of checks<br>(every <span id="checkfrequency">1</span> minutes)</label>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<input type="range" id="gap" name="gap" min="0" value="3" max="30" step="1">
|
||||
<label for="gap">Check availability from <span id="daygap">3</span> days from today. [0 = today]</label>
|
||||
</div>
|
||||
<p class="my-2 text-center">Changes are autosaved.</p>
|
||||
<form class="my-2" name="ais_visa_info" id="ais_visa_info">
|
||||
<div class="d-grid">
|
||||
<button id="reset_info" type="submit" class="btn btn-danger btn-sm">Configure / Reset</button>
|
||||
</div>
|
||||
</form>
|
||||
<p class="my-2 text-center">
|
||||
<button id=read_faqs form=null class="btn btn-info btn-sm">Read FAQs</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://www.buymeacoffee.com/hymnz" target="_blank">
|
||||
<img style="width: 250px;background: #5F7FFF;" src="https://img.buymeacoffee.com/button-api/?text=Help me run the extension&emoji=🙂&slug=hymnz&button_colour=5F7FFF&font_colour=ffffff&font_family=Comic&outline_colour=000000&coffee_colour=FFDD00" />
|
||||
</a>
|
||||
<script src="js/content.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
79
js/background.js
Normal file
@ -0,0 +1,79 @@
|
||||
chrome.runtime.onConnect.addListener(function(port) {
|
||||
port.onMessage.addListener(async function(def) {
|
||||
let response = new Object();
|
||||
response.action = def.action;
|
||||
if (def.action == "fetch_info") {
|
||||
let { __un } = await chrome.storage.local.get("__un");
|
||||
let { __pw } = await chrome.storage.local.get("__pw");
|
||||
let { __id } = await chrome.storage.local.get("__id");
|
||||
let { __ap } = await chrome.storage.local.get("__ap");
|
||||
let { __il } = await chrome.storage.local.get("__il");
|
||||
let { __ad } = await chrome.storage.local.get("__ad");
|
||||
let { __al } = await chrome.storage.local.get("__al");
|
||||
let { __ar } = await chrome.storage.local.get("__ar");
|
||||
let $version = await new Promise(r => chrome.management.getSelf(self => r(self.version)));
|
||||
response.data = {
|
||||
$username: __un,
|
||||
$password: __pw,
|
||||
$appid: __id,
|
||||
$active: __ap,
|
||||
$apptCenter: __il,
|
||||
$apptDate: __ad,
|
||||
$ascCenter: __al,
|
||||
$ascReverse: __ar,
|
||||
$version
|
||||
}
|
||||
}
|
||||
port.postMessage(response);
|
||||
});
|
||||
});
|
||||
|
||||
chrome.runtime.onInstalled.addListener(async({ reason }) => {
|
||||
chrome.action.disable();
|
||||
chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
|
||||
let exampleRule = {
|
||||
conditions: [
|
||||
new chrome.declarativeContent.PageStateMatcher({
|
||||
pageUrl: { hostEquals: 'ais.usvisa-info.com' },
|
||||
})
|
||||
],
|
||||
actions: [new chrome.declarativeContent.ShowAction()],
|
||||
};
|
||||
|
||||
let rules = [exampleRule];
|
||||
chrome.declarativeContent.onPageChanged.addRules(rules);
|
||||
});
|
||||
if (reason === 'install') {
|
||||
await chrome.storage.local.set({ __ab: false, __ap: true, __cr: 0, __fq: 1, __gp: 3 });
|
||||
chrome.tabs.create({
|
||||
url: "https://ais.usvisa-info.com/en-us/countries_list/niv"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var myNotificationID = null,
|
||||
senderId = null,
|
||||
ensureSendMessage = (tabId, message, callback) => {
|
||||
chrome.tabs.sendMessage(tabId, { ping: true }, function(response) {
|
||||
if (response && response.pong) {
|
||||
chrome.tabs.sendMessage(tabId, message, callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
chrome.notifications.onButtonClicked.addListener(function(notifId, btnId) {
|
||||
if (notifId === myNotificationID) {
|
||||
chrome.tabs.get(senderId, function(tab) {
|
||||
chrome.tabs.highlight({ 'tabs': tab.index }, function() {});
|
||||
});
|
||||
ensureSendMessage(senderId, { bookNow: btnId === 0 });
|
||||
}
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
|
||||
chrome.notifications.create(req.options, function(id) {
|
||||
myNotificationID = id;
|
||||
senderId = sender.tab.id;
|
||||
});
|
||||
sendResponse(true);
|
||||
});
|
||||
665
js/bootstrap.min.js
vendored
Normal file
@ -0,0 +1,665 @@
|
||||
/*!
|
||||
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
! function(t, e) { "object" == typeof exports && "undefined" != typeof module ? module.exports = e(require("@popperjs/core")) : "function" == typeof define && define.amd ? define(["@popperjs/core"], e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).bootstrap = e(t.Popper) }(this, (function(t) { "use strict";
|
||||
|
||||
function e(t) { const e = Object.create(null, {
|
||||
[Symbol.toStringTag]: { value: "Module" } }); if (t)
|
||||
for (const i in t)
|
||||
if ("default" !== i) { const s = Object.getOwnPropertyDescriptor(t, i);
|
||||
Object.defineProperty(e, i, s.get ? s : { enumerable: !0, get: () => t[i] }) }
|
||||
return e.default = t, Object.freeze(e) } const i = e(t),
|
||||
s = new Map,
|
||||
n = {set(t, e, i) { s.has(t) || s.set(t, new Map); const n = s.get(t);
|
||||
n.has(e) || 0 === n.size ? n.set(e, i) : console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`) }, get: (t, e) => s.has(t) && s.get(t).get(e) || null, remove(t, e) { if (!s.has(t)) return; const i = s.get(t);
|
||||
i.delete(e), 0 === i.size && s.delete(t) } },
|
||||
o = "transitionend",
|
||||
r = t => (t && window.CSS && window.CSS.escape && (t = t.replace(/#([^\s"#']+)/g, ((t, e) => `#${CSS.escape(e)}`))), t),
|
||||
a = t => { t.dispatchEvent(new Event(o)) },
|
||||
l = t => !(!t || "object" != typeof t) && (void 0 !== t.jquery && (t = t[0]), void 0 !== t.nodeType),
|
||||
c = t => l(t) ? t.jquery ? t[0] : t : "string" == typeof t && t.length > 0 ? document.querySelector(r(t)) : null,
|
||||
h = t => { if (!l(t) || 0 === t.getClientRects().length) return !1; const e = "visible" === getComputedStyle(t).getPropertyValue("visibility"),
|
||||
i = t.closest("details:not([open])"); if (!i) return e; if (i !== t) { const e = t.closest("summary"); if (e && e.parentNode !== i) return !1; if (null === e) return !1 } return e },
|
||||
d = t => !t || t.nodeType !== Node.ELEMENT_NODE || !!t.classList.contains("disabled") || (void 0 !== t.disabled ? t.disabled : t.hasAttribute("disabled") && "false" !== t.getAttribute("disabled")),
|
||||
u = t => { if (!document.documentElement.attachShadow) return null; if ("function" == typeof t.getRootNode) { const e = t.getRootNode(); return e instanceof ShadowRoot ? e : null } return t instanceof ShadowRoot ? t : t.parentNode ? u(t.parentNode) : null },
|
||||
_ = () => {},
|
||||
g = t => { t.offsetHeight },
|
||||
f = () => window.jQuery && !document.body.hasAttribute("data-bs-no-jquery") ? window.jQuery : null,
|
||||
m = [],
|
||||
p = () => "rtl" === document.documentElement.dir,
|
||||
b = t => { var e;
|
||||
e = () => { const e = f(); if (e) { const i = t.NAME,
|
||||
s = e.fn[i];
|
||||
e.fn[i] = t.jQueryInterface, e.fn[i].Constructor = t, e.fn[i].noConflict = () => (e.fn[i] = s, t.jQueryInterface) } }, "loading" === document.readyState ? (m.length || document.addEventListener("DOMContentLoaded", (() => { for (const t of m) t() })), m.push(e)) : e() },
|
||||
v = (t, e = [], i = t) => "function" == typeof t ? t(...e) : i,
|
||||
y = (t, e, i = !0) => { if (!i) return void v(t); const s = (t => { if (!t) return 0; let { transitionDuration: e, transitionDelay: i } = window.getComputedStyle(t); const s = Number.parseFloat(e),
|
||||
n = Number.parseFloat(i); return s || n ? (e = e.split(",")[0], i = i.split(",")[0], 1e3 * (Number.parseFloat(e) + Number.parseFloat(i))) : 0 })(e) + 5; let n = !1; const r = ({ target: i }) => { i === e && (n = !0, e.removeEventListener(o, r), v(t)) };
|
||||
e.addEventListener(o, r), setTimeout((() => { n || a(e) }), s) },
|
||||
w = (t, e, i, s) => { const n = t.length; let o = t.indexOf(e); return -1 === o ? !i && s ? t[n - 1] : t[0] : (o += i ? 1 : -1, s && (o = (o + n) % n), t[Math.max(0, Math.min(o, n - 1))]) },
|
||||
A = /[^.]*(?=\..*)\.|.*/,
|
||||
E = /\..*/,
|
||||
C = /::\d+$/,
|
||||
T = {}; let k = 1; const $ = { mouseenter: "mouseover", mouseleave: "mouseout" },
|
||||
S = new Set(["click", "dblclick", "mouseup", "mousedown", "contextmenu", "mousewheel", "DOMMouseScroll", "mouseover", "mouseout", "mousemove", "selectstart", "selectend", "keydown", "keypress", "keyup", "orientationchange", "touchstart", "touchmove", "touchend", "touchcancel", "pointerdown", "pointermove", "pointerup", "pointerleave", "pointercancel", "gesturestart", "gesturechange", "gestureend", "focus", "blur", "change", "reset", "select", "submit", "focusin", "focusout", "load", "unload", "beforeunload", "resize", "move", "DOMContentLoaded", "readystatechange", "error", "abort", "scroll"]);
|
||||
|
||||
function L(t, e) { return e && `${e}::${k++}` || t.uidEvent || k++ }
|
||||
|
||||
function O(t) { const e = L(t); return t.uidEvent = e, T[e] = T[e] || {}, T[e] }
|
||||
|
||||
function I(t, e, i = null) { return Object.values(t).find((t => t.callable === e && t.delegationSelector === i)) }
|
||||
|
||||
function D(t, e, i) { const s = "string" == typeof e,
|
||||
n = s ? i : e || i; let o = M(t); return S.has(o) || (o = t), [s, n, o] }
|
||||
|
||||
function N(t, e, i, s, n) { if ("string" != typeof e || !t) return; let [o, r, a] = D(e, i, s); if (e in $) { const t = t => function(e) { if (!e.relatedTarget || e.relatedTarget !== e.delegateTarget && !e.delegateTarget.contains(e.relatedTarget)) return t.call(this, e) };
|
||||
r = t(r) } const l = O(t),
|
||||
c = l[a] || (l[a] = {}),
|
||||
h = I(c, r, o ? i : null); if (h) return void(h.oneOff = h.oneOff && n); const d = L(r, e.replace(A, "")),
|
||||
u = o ? function(t, e, i) { return function s(n) { const o = t.querySelectorAll(e); for (let { target: r } = n; r && r !== this; r = r.parentNode)
|
||||
for (const a of o)
|
||||
if (a === r) return F(n, { delegateTarget: r }), s.oneOff && j.off(t, n.type, e, i), i.apply(r, [n]) } }(t, i, r) : function(t, e) { return function i(s) { return F(s, { delegateTarget: t }), i.oneOff && j.off(t, s.type, e), e.apply(t, [s]) } }(t, r);
|
||||
u.delegationSelector = o ? i : null, u.callable = r, u.oneOff = n, u.uidEvent = d, c[d] = u, t.addEventListener(a, u, o) }
|
||||
|
||||
function P(t, e, i, s, n) { const o = I(e[i], s, n);
|
||||
o && (t.removeEventListener(i, o, Boolean(n)), delete e[i][o.uidEvent]) }
|
||||
|
||||
function x(t, e, i, s) { const n = e[i] || {}; for (const [o, r] of Object.entries(n)) o.includes(s) && P(t, e, i, r.callable, r.delegationSelector) }
|
||||
|
||||
function M(t) { return t = t.replace(E, ""), $[t] || t } const j = { on(t, e, i, s) { N(t, e, i, s, !1) }, one(t, e, i, s) { N(t, e, i, s, !0) }, off(t, e, i, s) { if ("string" != typeof e || !t) return; const [n, o, r] = D(e, i, s), a = r !== e, l = O(t), c = l[r] || {}, h = e.startsWith("."); if (void 0 === o) { if (h)
|
||||
for (const i of Object.keys(l)) x(t, l, i, e.slice(1)); for (const [i, s] of Object.entries(c)) { const n = i.replace(C, "");
|
||||
a && !e.includes(n) || P(t, l, r, s.callable, s.delegationSelector) } } else { if (!Object.keys(c).length) return;
|
||||
P(t, l, r, o, n ? i : null) } }, trigger(t, e, i) { if ("string" != typeof e || !t) return null; const s = f(); let n = null,
|
||||
o = !0,
|
||||
r = !0,
|
||||
a = !1;
|
||||
e !== M(e) && s && (n = s.Event(e, i), s(t).trigger(n), o = !n.isPropagationStopped(), r = !n.isImmediatePropagationStopped(), a = n.isDefaultPrevented()); const l = F(new Event(e, { bubbles: o, cancelable: !0 }), i); return a && l.preventDefault(), r && t.dispatchEvent(l), l.defaultPrevented && n && n.preventDefault(), l } };
|
||||
|
||||
function F(t, e = {}) { for (const [i, s] of Object.entries(e)) try { t[i] = s } catch (e) { Object.defineProperty(t, i, { configurable: !0, get: () => s }) }
|
||||
return t }
|
||||
|
||||
function z(t) { if ("true" === t) return !0; if ("false" === t) return !1; if (t === Number(t).toString()) return Number(t); if ("" === t || "null" === t) return null; if ("string" != typeof t) return t; try { return JSON.parse(decodeURIComponent(t)) } catch (e) { return t } }
|
||||
|
||||
function H(t) { return t.replace(/[A-Z]/g, (t => `-${t.toLowerCase()}`)) } const B = { setDataAttribute(t, e, i) { t.setAttribute(`data-bs-${H(e)}`, i) }, removeDataAttribute(t, e) { t.removeAttribute(`data-bs-${H(e)}`) }, getDataAttributes(t) { if (!t) return {}; const e = {},
|
||||
i = Object.keys(t.dataset).filter((t => t.startsWith("bs") && !t.startsWith("bsConfig"))); for (const s of i) { let i = s.replace(/^bs/, "");
|
||||
i = i.charAt(0).toLowerCase() + i.slice(1, i.length), e[i] = z(t.dataset[s]) } return e }, getDataAttribute: (t, e) => z(t.getAttribute(`data-bs-${H(e)}`)) };
|
||||
class q { static get Default() { return {} }
|
||||
static get DefaultType() { return {} }
|
||||
static get NAME() { throw new Error('You have to implement the static method "NAME", for each component!') }
|
||||
_getConfig(t) { return t = this._mergeConfigObj(t), t = this._configAfterMerge(t), this._typeCheckConfig(t), t }
|
||||
_configAfterMerge(t) { return t }
|
||||
_mergeConfigObj(t, e) { const i = l(e) ? B.getDataAttribute(e, "config") : {}; return {...this.constructor.Default, ... "object" == typeof i ? i : {}, ...l(e) ? B.getDataAttributes(e) : {}, ... "object" == typeof t ? t : {} } }
|
||||
_typeCheckConfig(t, e = this.constructor.DefaultType) { for (const [s, n] of Object.entries(e)) { const e = t[s],
|
||||
o = l(e) ? "element" : null == (i = e) ? `${i}` : Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase(); if (!new RegExp(n).test(o)) throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${s}" provided type "${o}" but expected type "${n}".`) } var i } }
|
||||
class W extends q { constructor(t, e) { super(), (t = c(t)) && (this._element = t, this._config = this._getConfig(e), n.set(this._element, this.constructor.DATA_KEY, this)) }
|
||||
dispose() { n.remove(this._element, this.constructor.DATA_KEY), j.off(this._element, this.constructor.EVENT_KEY); for (const t of Object.getOwnPropertyNames(this)) this[t] = null }
|
||||
_queueCallback(t, e, i = !0) { y(t, e, i) }
|
||||
_getConfig(t) { return t = this._mergeConfigObj(t, this._element), t = this._configAfterMerge(t), this._typeCheckConfig(t), t }
|
||||
static getInstance(t) { return n.get(c(t), this.DATA_KEY) }
|
||||
static getOrCreateInstance(t, e = {}) { return this.getInstance(t) || new this(t, "object" == typeof e ? e : null) }
|
||||
static get VERSION() { return "5.3.3" }
|
||||
static get DATA_KEY() { return `bs.${this.NAME}` }
|
||||
static get EVENT_KEY() { return `.${this.DATA_KEY}` }
|
||||
static eventName(t) { return `${t}${this.EVENT_KEY}` } } const R = t => { let e = t.getAttribute("data-bs-target"); if (!e || "#" === e) { let i = t.getAttribute("href"); if (!i || !i.includes("#") && !i.startsWith(".")) return null;
|
||||
i.includes("#") && !i.startsWith("#") && (i = `#${i.split("#")[1]}`), e = i && "#" !== i ? i.trim() : null } return e ? e.split(",").map((t => r(t))).join(",") : null },
|
||||
K = { find: (t, e = document.documentElement) => [].concat(...Element.prototype.querySelectorAll.call(e, t)), findOne: (t, e = document.documentElement) => Element.prototype.querySelector.call(e, t), children: (t, e) => [].concat(...t.children).filter((t => t.matches(e))), parents(t, e) { const i = []; let s = t.parentNode.closest(e); for (; s;) i.push(s), s = s.parentNode.closest(e); return i }, prev(t, e) { let i = t.previousElementSibling; for (; i;) { if (i.matches(e)) return [i];
|
||||
i = i.previousElementSibling } return [] }, next(t, e) { let i = t.nextElementSibling; for (; i;) { if (i.matches(e)) return [i];
|
||||
i = i.nextElementSibling } return [] }, focusableChildren(t) { const e = ["a", "button", "input", "textarea", "select", "details", "[tabindex]", '[contenteditable="true"]'].map((t => `${t}:not([tabindex^="-"])`)).join(","); return this.find(e, t).filter((t => !d(t) && h(t))) }, getSelectorFromElement(t) { const e = R(t); return e && K.findOne(e) ? e : null }, getElementFromSelector(t) { const e = R(t); return e ? K.findOne(e) : null }, getMultipleElementsFromSelector(t) { const e = R(t); return e ? K.find(e) : [] } },
|
||||
V = (t, e = "hide") => { const i = `click.dismiss${t.EVENT_KEY}`,
|
||||
s = t.NAME;
|
||||
j.on(document, i, `[data-bs-dismiss="${s}"]`, (function(i) { if (["A", "AREA"].includes(this.tagName) && i.preventDefault(), d(this)) return; const n = K.getElementFromSelector(this) || this.closest(`.${s}`);
|
||||
t.getOrCreateInstance(n)[e]() })) },
|
||||
Q = ".bs.alert",
|
||||
X = `close${Q}`,
|
||||
Y = `closed${Q}`;
|
||||
class U extends W { static get NAME() { return "alert" }
|
||||
close() { if (j.trigger(this._element, X).defaultPrevented) return;
|
||||
this._element.classList.remove("show"); const t = this._element.classList.contains("fade");
|
||||
this._queueCallback((() => this._destroyElement()), this._element, t) }
|
||||
_destroyElement() { this._element.remove(), j.trigger(this._element, Y), this.dispose() }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = U.getOrCreateInstance(this); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`);
|
||||
e[t](this) } })) } }
|
||||
V(U, "close"), b(U); const G = '[data-bs-toggle="button"]';
|
||||
class J extends W { static get NAME() { return "button" }
|
||||
toggle() { this._element.setAttribute("aria-pressed", this._element.classList.toggle("active")) }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = J.getOrCreateInstance(this); "toggle" === t && e[t]() })) } }
|
||||
j.on(document, "click.bs.button.data-api", G, (t => { t.preventDefault(); const e = t.target.closest(G);
|
||||
J.getOrCreateInstance(e).toggle() })), b(J); const Z = ".bs.swipe",
|
||||
tt = `touchstart${Z}`,
|
||||
et = `touchmove${Z}`,
|
||||
it = `touchend${Z}`,
|
||||
st = `pointerdown${Z}`,
|
||||
nt = `pointerup${Z}`,
|
||||
ot = { endCallback: null, leftCallback: null, rightCallback: null },
|
||||
rt = { endCallback: "(function|null)", leftCallback: "(function|null)", rightCallback: "(function|null)" };
|
||||
class at extends q { constructor(t, e) { super(), this._element = t, t && at.isSupported() && (this._config = this._getConfig(e), this._deltaX = 0, this._supportPointerEvents = Boolean(window.PointerEvent), this._initEvents()) }
|
||||
static get Default() { return ot }
|
||||
static get DefaultType() { return rt }
|
||||
static get NAME() { return "swipe" }
|
||||
dispose() { j.off(this._element, Z) }
|
||||
_start(t) { this._supportPointerEvents ? this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX) : this._deltaX = t.touches[0].clientX }
|
||||
_end(t) { this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX - this._deltaX), this._handleSwipe(), v(this._config.endCallback) }
|
||||
_move(t) { this._deltaX = t.touches && t.touches.length > 1 ? 0 : t.touches[0].clientX - this._deltaX }
|
||||
_handleSwipe() { const t = Math.abs(this._deltaX); if (t <= 40) return; const e = t / this._deltaX;
|
||||
this._deltaX = 0, e && v(e > 0 ? this._config.rightCallback : this._config.leftCallback) }
|
||||
_initEvents() { this._supportPointerEvents ? (j.on(this._element, st, (t => this._start(t))), j.on(this._element, nt, (t => this._end(t))), this._element.classList.add("pointer-event")) : (j.on(this._element, tt, (t => this._start(t))), j.on(this._element, et, (t => this._move(t))), j.on(this._element, it, (t => this._end(t)))) }
|
||||
_eventIsPointerPenTouch(t) { return this._supportPointerEvents && ("pen" === t.pointerType || "touch" === t.pointerType) }
|
||||
static isSupported() { return "ontouchstart" in document.documentElement || navigator.maxTouchPoints > 0 } } const lt = ".bs.carousel",
|
||||
ct = ".data-api",
|
||||
ht = "next",
|
||||
dt = "prev",
|
||||
ut = "left",
|
||||
_t = "right",
|
||||
gt = `slide${lt}`,
|
||||
ft = `slid${lt}`,
|
||||
mt = `keydown${lt}`,
|
||||
pt = `mouseenter${lt}`,
|
||||
bt = `mouseleave${lt}`,
|
||||
vt = `dragstart${lt}`,
|
||||
yt = `load${lt}${ct}`,
|
||||
wt = `click${lt}${ct}`,
|
||||
At = "carousel",
|
||||
Et = "active",
|
||||
Ct = ".active",
|
||||
Tt = ".carousel-item",
|
||||
kt = Ct + Tt,
|
||||
$t = { ArrowLeft: _t, ArrowRight: ut },
|
||||
St = { interval: 5e3, keyboard: !0, pause: "hover", ride: !1, touch: !0, wrap: !0 },
|
||||
Lt = { interval: "(number|boolean)", keyboard: "boolean", pause: "(string|boolean)", ride: "(boolean|string)", touch: "boolean", wrap: "boolean" };
|
||||
class Ot extends W { constructor(t, e) { super(t, e), this._interval = null, this._activeElement = null, this._isSliding = !1, this.touchTimeout = null, this._swipeHelper = null, this._indicatorsElement = K.findOne(".carousel-indicators", this._element), this._addEventListeners(), this._config.ride === At && this.cycle() }
|
||||
static get Default() { return St }
|
||||
static get DefaultType() { return Lt }
|
||||
static get NAME() { return "carousel" }
|
||||
next() { this._slide(ht) }
|
||||
nextWhenVisible() {!document.hidden && h(this._element) && this.next() }
|
||||
prev() { this._slide(dt) }
|
||||
pause() { this._isSliding && a(this._element), this._clearInterval() }
|
||||
cycle() { this._clearInterval(), this._updateInterval(), this._interval = setInterval((() => this.nextWhenVisible()), this._config.interval) }
|
||||
_maybeEnableCycle() { this._config.ride && (this._isSliding ? j.one(this._element, ft, (() => this.cycle())) : this.cycle()) }
|
||||
to(t) { const e = this._getItems(); if (t > e.length - 1 || t < 0) return; if (this._isSliding) return void j.one(this._element, ft, (() => this.to(t))); const i = this._getItemIndex(this._getActive()); if (i === t) return; const s = t > i ? ht : dt;
|
||||
this._slide(s, e[t]) }
|
||||
dispose() { this._swipeHelper && this._swipeHelper.dispose(), super.dispose() }
|
||||
_configAfterMerge(t) { return t.defaultInterval = t.interval, t }
|
||||
_addEventListeners() { this._config.keyboard && j.on(this._element, mt, (t => this._keydown(t))), "hover" === this._config.pause && (j.on(this._element, pt, (() => this.pause())), j.on(this._element, bt, (() => this._maybeEnableCycle()))), this._config.touch && at.isSupported() && this._addTouchEventListeners() }
|
||||
_addTouchEventListeners() { for (const t of K.find(".carousel-item img", this._element)) j.on(t, vt, (t => t.preventDefault())); const t = { leftCallback: () => this._slide(this._directionToOrder(ut)), rightCallback: () => this._slide(this._directionToOrder(_t)), endCallback: () => { "hover" === this._config.pause && (this.pause(), this.touchTimeout && clearTimeout(this.touchTimeout), this.touchTimeout = setTimeout((() => this._maybeEnableCycle()), 500 + this._config.interval)) } };
|
||||
this._swipeHelper = new at(this._element, t) }
|
||||
_keydown(t) { if (/input|textarea/i.test(t.target.tagName)) return; const e = $t[t.key];
|
||||
e && (t.preventDefault(), this._slide(this._directionToOrder(e))) }
|
||||
_getItemIndex(t) { return this._getItems().indexOf(t) }
|
||||
_setActiveIndicatorElement(t) { if (!this._indicatorsElement) return; const e = K.findOne(Ct, this._indicatorsElement);
|
||||
e.classList.remove(Et), e.removeAttribute("aria-current"); const i = K.findOne(`[data-bs-slide-to="${t}"]`, this._indicatorsElement);
|
||||
i && (i.classList.add(Et), i.setAttribute("aria-current", "true")) }
|
||||
_updateInterval() { const t = this._activeElement || this._getActive(); if (!t) return; const e = Number.parseInt(t.getAttribute("data-bs-interval"), 10);
|
||||
this._config.interval = e || this._config.defaultInterval }
|
||||
_slide(t, e = null) { if (this._isSliding) return; const i = this._getActive(),
|
||||
s = t === ht,
|
||||
n = e || w(this._getItems(), i, s, this._config.wrap); if (n === i) return; const o = this._getItemIndex(n),
|
||||
r = e => j.trigger(this._element, e, { relatedTarget: n, direction: this._orderToDirection(t), from: this._getItemIndex(i), to: o }); if (r(gt).defaultPrevented) return; if (!i || !n) return; const a = Boolean(this._interval);
|
||||
this.pause(), this._isSliding = !0, this._setActiveIndicatorElement(o), this._activeElement = n; const l = s ? "carousel-item-start" : "carousel-item-end",
|
||||
c = s ? "carousel-item-next" : "carousel-item-prev";
|
||||
n.classList.add(c), g(n), i.classList.add(l), n.classList.add(l), this._queueCallback((() => { n.classList.remove(l, c), n.classList.add(Et), i.classList.remove(Et, c, l), this._isSliding = !1, r(ft) }), i, this._isAnimated()), a && this.cycle() }
|
||||
_isAnimated() { return this._element.classList.contains("slide") }
|
||||
_getActive() { return K.findOne(kt, this._element) }
|
||||
_getItems() { return K.find(Tt, this._element) }
|
||||
_clearInterval() { this._interval && (clearInterval(this._interval), this._interval = null) }
|
||||
_directionToOrder(t) { return p() ? t === ut ? dt : ht : t === ut ? ht : dt }
|
||||
_orderToDirection(t) { return p() ? t === dt ? ut : _t : t === dt ? _t : ut }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = Ot.getOrCreateInstance(this, t); if ("number" != typeof t) { if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } } else e.to(t) })) } }
|
||||
j.on(document, wt, "[data-bs-slide], [data-bs-slide-to]", (function(t) { const e = K.getElementFromSelector(this); if (!e || !e.classList.contains(At)) return;
|
||||
t.preventDefault(); const i = Ot.getOrCreateInstance(e),
|
||||
s = this.getAttribute("data-bs-slide-to"); return s ? (i.to(s), void i._maybeEnableCycle()) : "next" === B.getDataAttribute(this, "slide") ? (i.next(), void i._maybeEnableCycle()) : (i.prev(), void i._maybeEnableCycle()) })), j.on(window, yt, (() => { const t = K.find('[data-bs-ride="carousel"]'); for (const e of t) Ot.getOrCreateInstance(e) })), b(Ot); const It = ".bs.collapse",
|
||||
Dt = `show${It}`,
|
||||
Nt = `shown${It}`,
|
||||
Pt = `hide${It}`,
|
||||
xt = `hidden${It}`,
|
||||
Mt = `click${It}.data-api`,
|
||||
jt = "show",
|
||||
Ft = "collapse",
|
||||
zt = "collapsing",
|
||||
Ht = `:scope .${Ft} .${Ft}`,
|
||||
Bt = '[data-bs-toggle="collapse"]',
|
||||
qt = { parent: null, toggle: !0 },
|
||||
Wt = { parent: "(null|element)", toggle: "boolean" };
|
||||
class Rt extends W { constructor(t, e) { super(t, e), this._isTransitioning = !1, this._triggerArray = []; const i = K.find(Bt); for (const t of i) { const e = K.getSelectorFromElement(t),
|
||||
i = K.find(e).filter((t => t === this._element));
|
||||
null !== e && i.length && this._triggerArray.push(t) }
|
||||
this._initializeChildren(), this._config.parent || this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()), this._config.toggle && this.toggle() }
|
||||
static get Default() { return qt }
|
||||
static get DefaultType() { return Wt }
|
||||
static get NAME() { return "collapse" }
|
||||
toggle() { this._isShown() ? this.hide() : this.show() }
|
||||
show() { if (this._isTransitioning || this._isShown()) return; let t = []; if (this._config.parent && (t = this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t => t !== this._element)).map((t => Rt.getOrCreateInstance(t, { toggle: !1 })))), t.length && t[0]._isTransitioning) return; if (j.trigger(this._element, Dt).defaultPrevented) return; for (const e of t) e.hide(); const e = this._getDimension();
|
||||
this._element.classList.remove(Ft), this._element.classList.add(zt), this._element.style[e] = 0, this._addAriaAndCollapsedClass(this._triggerArray, !0), this._isTransitioning = !0; const i = `scroll${e[0].toUpperCase()+e.slice(1)}`;
|
||||
this._queueCallback((() => { this._isTransitioning = !1, this._element.classList.remove(zt), this._element.classList.add(Ft, jt), this._element.style[e] = "", j.trigger(this._element, Nt) }), this._element, !0), this._element.style[e] = `${this._element[i]}px` }
|
||||
hide() { if (this._isTransitioning || !this._isShown()) return; if (j.trigger(this._element, Pt).defaultPrevented) return; const t = this._getDimension();
|
||||
this._element.style[t] = `${this._element.getBoundingClientRect()[t]}px`, g(this._element), this._element.classList.add(zt), this._element.classList.remove(Ft, jt); for (const t of this._triggerArray) { const e = K.getElementFromSelector(t);
|
||||
e && !this._isShown(e) && this._addAriaAndCollapsedClass([t], !1) }
|
||||
this._isTransitioning = !0, this._element.style[t] = "", this._queueCallback((() => { this._isTransitioning = !1, this._element.classList.remove(zt), this._element.classList.add(Ft), j.trigger(this._element, xt) }), this._element, !0) }
|
||||
_isShown(t = this._element) { return t.classList.contains(jt) }
|
||||
_configAfterMerge(t) { return t.toggle = Boolean(t.toggle), t.parent = c(t.parent), t }
|
||||
_getDimension() { return this._element.classList.contains("collapse-horizontal") ? "width" : "height" }
|
||||
_initializeChildren() { if (!this._config.parent) return; const t = this._getFirstLevelChildren(Bt); for (const e of t) { const t = K.getElementFromSelector(e);
|
||||
t && this._addAriaAndCollapsedClass([e], this._isShown(t)) } }
|
||||
_getFirstLevelChildren(t) { const e = K.find(Ht, this._config.parent); return K.find(t, this._config.parent).filter((t => !e.includes(t))) }
|
||||
_addAriaAndCollapsedClass(t, e) { if (t.length)
|
||||
for (const i of t) i.classList.toggle("collapsed", !e), i.setAttribute("aria-expanded", e) }
|
||||
static jQueryInterface(t) { const e = {}; return "string" == typeof t && /show|hide/.test(t) && (e.toggle = !1), this.each((function() { const i = Rt.getOrCreateInstance(this, e); if ("string" == typeof t) { if (void 0 === i[t]) throw new TypeError(`No method named "${t}"`);
|
||||
i[t]() } })) } }
|
||||
j.on(document, Mt, Bt, (function(t) {
|
||||
("A" === t.target.tagName || t.delegateTarget && "A" === t.delegateTarget.tagName) && t.preventDefault(); for (const t of K.getMultipleElementsFromSelector(this)) Rt.getOrCreateInstance(t, { toggle: !1 }).toggle() })), b(Rt); const Kt = "dropdown",
|
||||
Vt = ".bs.dropdown",
|
||||
Qt = ".data-api",
|
||||
Xt = "ArrowUp",
|
||||
Yt = "ArrowDown",
|
||||
Ut = `hide${Vt}`,
|
||||
Gt = `hidden${Vt}`,
|
||||
Jt = `show${Vt}`,
|
||||
Zt = `shown${Vt}`,
|
||||
te = `click${Vt}${Qt}`,
|
||||
ee = `keydown${Vt}${Qt}`,
|
||||
ie = `keyup${Vt}${Qt}`,
|
||||
se = "show",
|
||||
ne = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)',
|
||||
oe = `${ne}.${se}`,
|
||||
re = ".dropdown-menu",
|
||||
ae = p() ? "top-end" : "top-start",
|
||||
le = p() ? "top-start" : "top-end",
|
||||
ce = p() ? "bottom-end" : "bottom-start",
|
||||
he = p() ? "bottom-start" : "bottom-end",
|
||||
de = p() ? "left-start" : "right-start",
|
||||
ue = p() ? "right-start" : "left-start",
|
||||
_e = { autoClose: !0, boundary: "clippingParents", display: "dynamic", offset: [0, 2], popperConfig: null, reference: "toggle" },
|
||||
ge = { autoClose: "(boolean|string)", boundary: "(string|element)", display: "string", offset: "(array|string|function)", popperConfig: "(null|object|function)", reference: "(string|element|object)" };
|
||||
class fe extends W { constructor(t, e) { super(t, e), this._popper = null, this._parent = this._element.parentNode, this._menu = K.next(this._element, re)[0] || K.prev(this._element, re)[0] || K.findOne(re, this._parent), this._inNavbar = this._detectNavbar() }
|
||||
static get Default() { return _e }
|
||||
static get DefaultType() { return ge }
|
||||
static get NAME() { return Kt }
|
||||
toggle() { return this._isShown() ? this.hide() : this.show() }
|
||||
show() { if (d(this._element) || this._isShown()) return; const t = { relatedTarget: this._element }; if (!j.trigger(this._element, Jt, t).defaultPrevented) { if (this._createPopper(), "ontouchstart" in document.documentElement && !this._parent.closest(".navbar-nav"))
|
||||
for (const t of[].concat(...document.body.children)) j.on(t, "mouseover", _);
|
||||
this._element.focus(), this._element.setAttribute("aria-expanded", !0), this._menu.classList.add(se), this._element.classList.add(se), j.trigger(this._element, Zt, t) } }
|
||||
hide() { if (d(this._element) || !this._isShown()) return; const t = { relatedTarget: this._element };
|
||||
this._completeHide(t) }
|
||||
dispose() { this._popper && this._popper.destroy(), super.dispose() }
|
||||
update() { this._inNavbar = this._detectNavbar(), this._popper && this._popper.update() }
|
||||
_completeHide(t) { if (!j.trigger(this._element, Ut, t).defaultPrevented) { if ("ontouchstart" in document.documentElement)
|
||||
for (const t of[].concat(...document.body.children)) j.off(t, "mouseover", _);
|
||||
this._popper && this._popper.destroy(), this._menu.classList.remove(se), this._element.classList.remove(se), this._element.setAttribute("aria-expanded", "false"), B.removeDataAttribute(this._menu, "popper"), j.trigger(this._element, Gt, t) } }
|
||||
_getConfig(t) { if ("object" == typeof(t = super._getConfig(t)).reference && !l(t.reference) && "function" != typeof t.reference.getBoundingClientRect) throw new TypeError(`${Kt.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); return t }
|
||||
_createPopper() { if (void 0 === i) throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)"); let t = this._element; "parent" === this._config.reference ? t = this._parent : l(this._config.reference) ? t = c(this._config.reference) : "object" == typeof this._config.reference && (t = this._config.reference); const e = this._getPopperConfig();
|
||||
this._popper = i.createPopper(t, this._menu, e) }
|
||||
_isShown() { return this._menu.classList.contains(se) }
|
||||
_getPlacement() { const t = this._parent; if (t.classList.contains("dropend")) return de; if (t.classList.contains("dropstart")) return ue; if (t.classList.contains("dropup-center")) return "top"; if (t.classList.contains("dropdown-center")) return "bottom"; const e = "end" === getComputedStyle(this._menu).getPropertyValue("--bs-position").trim(); return t.classList.contains("dropup") ? e ? le : ae : e ? he : ce }
|
||||
_detectNavbar() { return null !== this._element.closest(".navbar") }
|
||||
_getOffset() { const { offset: t } = this._config; return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t }
|
||||
_getPopperConfig() { const t = { placement: this._getPlacement(), modifiers: [{ name: "preventOverflow", options: { boundary: this._config.boundary } }, { name: "offset", options: { offset: this._getOffset() } }] }; return (this._inNavbar || "static" === this._config.display) && (B.setDataAttribute(this._menu, "popper", "static"), t.modifiers = [{ name: "applyStyles", enabled: !1 }]), {...t, ...v(this._config.popperConfig, [t]) } }
|
||||
_selectMenuItem({ key: t, target: e }) { const i = K.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)", this._menu).filter((t => h(t)));
|
||||
i.length && w(i, e, t === Yt, !i.includes(e)).focus() }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = fe.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } })) }
|
||||
static clearMenus(t) { if (2 === t.button || "keyup" === t.type && "Tab" !== t.key) return; const e = K.find(oe); for (const i of e) { const e = fe.getInstance(i); if (!e || !1 === e._config.autoClose) continue; const s = t.composedPath(),
|
||||
n = s.includes(e._menu); if (s.includes(e._element) || "inside" === e._config.autoClose && !n || "outside" === e._config.autoClose && n) continue; if (e._menu.contains(t.target) && ("keyup" === t.type && "Tab" === t.key || /input|select|option|textarea|form/i.test(t.target.tagName))) continue; const o = { relatedTarget: e._element }; "click" === t.type && (o.clickEvent = t), e._completeHide(o) } }
|
||||
static dataApiKeydownHandler(t) { const e = /input|textarea/i.test(t.target.tagName),
|
||||
i = "Escape" === t.key,
|
||||
s = [Xt, Yt].includes(t.key); if (!s && !i) return; if (e && !i) return;
|
||||
t.preventDefault(); const n = this.matches(ne) ? this : K.prev(this, ne)[0] || K.next(this, ne)[0] || K.findOne(ne, t.delegateTarget.parentNode),
|
||||
o = fe.getOrCreateInstance(n); if (s) return t.stopPropagation(), o.show(), void o._selectMenuItem(t);
|
||||
o._isShown() && (t.stopPropagation(), o.hide(), n.focus()) } }
|
||||
j.on(document, ee, ne, fe.dataApiKeydownHandler), j.on(document, ee, re, fe.dataApiKeydownHandler), j.on(document, te, fe.clearMenus), j.on(document, ie, fe.clearMenus), j.on(document, te, ne, (function(t) { t.preventDefault(), fe.getOrCreateInstance(this).toggle() })), b(fe); const me = "backdrop",
|
||||
pe = "show",
|
||||
be = `mousedown.bs.${me}`,
|
||||
ve = { className: "modal-backdrop", clickCallback: null, isAnimated: !1, isVisible: !0, rootElement: "body" },
|
||||
ye = { className: "string", clickCallback: "(function|null)", isAnimated: "boolean", isVisible: "boolean", rootElement: "(element|string)" };
|
||||
class we extends q { constructor(t) { super(), this._config = this._getConfig(t), this._isAppended = !1, this._element = null }
|
||||
static get Default() { return ve }
|
||||
static get DefaultType() { return ye }
|
||||
static get NAME() { return me }
|
||||
show(t) { if (!this._config.isVisible) return void v(t);
|
||||
this._append(); const e = this._getElement();
|
||||
this._config.isAnimated && g(e), e.classList.add(pe), this._emulateAnimation((() => { v(t) })) }
|
||||
hide(t) { this._config.isVisible ? (this._getElement().classList.remove(pe), this._emulateAnimation((() => { this.dispose(), v(t) }))) : v(t) }
|
||||
dispose() { this._isAppended && (j.off(this._element, be), this._element.remove(), this._isAppended = !1) }
|
||||
_getElement() { if (!this._element) { const t = document.createElement("div");
|
||||
t.className = this._config.className, this._config.isAnimated && t.classList.add("fade"), this._element = t } return this._element }
|
||||
_configAfterMerge(t) { return t.rootElement = c(t.rootElement), t }
|
||||
_append() { if (this._isAppended) return; const t = this._getElement();
|
||||
this._config.rootElement.append(t), j.on(t, be, (() => { v(this._config.clickCallback) })), this._isAppended = !0 }
|
||||
_emulateAnimation(t) { y(t, this._getElement(), this._config.isAnimated) } } const Ae = ".bs.focustrap",
|
||||
Ee = `focusin${Ae}`,
|
||||
Ce = `keydown.tab${Ae}`,
|
||||
Te = "backward",
|
||||
ke = { autofocus: !0, trapElement: null },
|
||||
$e = { autofocus: "boolean", trapElement: "element" };
|
||||
class Se extends q { constructor(t) { super(), this._config = this._getConfig(t), this._isActive = !1, this._lastTabNavDirection = null }
|
||||
static get Default() { return ke }
|
||||
static get DefaultType() { return $e }
|
||||
static get NAME() { return "focustrap" }
|
||||
activate() { this._isActive || (this._config.autofocus && this._config.trapElement.focus(), j.off(document, Ae), j.on(document, Ee, (t => this._handleFocusin(t))), j.on(document, Ce, (t => this._handleKeydown(t))), this._isActive = !0) }
|
||||
deactivate() { this._isActive && (this._isActive = !1, j.off(document, Ae)) }
|
||||
_handleFocusin(t) { const { trapElement: e } = this._config; if (t.target === document || t.target === e || e.contains(t.target)) return; const i = K.focusableChildren(e);
|
||||
0 === i.length ? e.focus() : this._lastTabNavDirection === Te ? i[i.length - 1].focus() : i[0].focus() }
|
||||
_handleKeydown(t) { "Tab" === t.key && (this._lastTabNavDirection = t.shiftKey ? Te : "forward") } } const Le = ".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",
|
||||
Oe = ".sticky-top",
|
||||
Ie = "padding-right",
|
||||
De = "margin-right";
|
||||
class Ne { constructor() { this._element = document.body }
|
||||
getWidth() { const t = document.documentElement.clientWidth; return Math.abs(window.innerWidth - t) }
|
||||
hide() { const t = this.getWidth();
|
||||
this._disableOverFlow(), this._setElementAttributes(this._element, Ie, (e => e + t)), this._setElementAttributes(Le, Ie, (e => e + t)), this._setElementAttributes(Oe, De, (e => e - t)) }
|
||||
reset() { this._resetElementAttributes(this._element, "overflow"), this._resetElementAttributes(this._element, Ie), this._resetElementAttributes(Le, Ie), this._resetElementAttributes(Oe, De) }
|
||||
isOverflowing() { return this.getWidth() > 0 }
|
||||
_disableOverFlow() { this._saveInitialAttribute(this._element, "overflow"), this._element.style.overflow = "hidden" }
|
||||
_setElementAttributes(t, e, i) { const s = this.getWidth();
|
||||
this._applyManipulationCallback(t, (t => { if (t !== this._element && window.innerWidth > t.clientWidth + s) return;
|
||||
this._saveInitialAttribute(t, e); const n = window.getComputedStyle(t).getPropertyValue(e);
|
||||
t.style.setProperty(e, `${i(Number.parseFloat(n))}px`) })) }
|
||||
_saveInitialAttribute(t, e) { const i = t.style.getPropertyValue(e);
|
||||
i && B.setDataAttribute(t, e, i) }
|
||||
_resetElementAttributes(t, e) { this._applyManipulationCallback(t, (t => { const i = B.getDataAttribute(t, e);
|
||||
null !== i ? (B.removeDataAttribute(t, e), t.style.setProperty(e, i)) : t.style.removeProperty(e) })) }
|
||||
_applyManipulationCallback(t, e) { if (l(t)) e(t);
|
||||
else
|
||||
for (const i of K.find(t, this._element)) e(i) } } const Pe = ".bs.modal",
|
||||
xe = `hide${Pe}`,
|
||||
Me = `hidePrevented${Pe}`,
|
||||
je = `hidden${Pe}`,
|
||||
Fe = `show${Pe}`,
|
||||
ze = `shown${Pe}`,
|
||||
He = `resize${Pe}`,
|
||||
Be = `click.dismiss${Pe}`,
|
||||
qe = `mousedown.dismiss${Pe}`,
|
||||
We = `keydown.dismiss${Pe}`,
|
||||
Re = `click${Pe}.data-api`,
|
||||
Ke = "modal-open",
|
||||
Ve = "show",
|
||||
Qe = "modal-static",
|
||||
Xe = { backdrop: !0, focus: !0, keyboard: !0 },
|
||||
Ye = { backdrop: "(boolean|string)", focus: "boolean", keyboard: "boolean" };
|
||||
class Ue extends W { constructor(t, e) { super(t, e), this._dialog = K.findOne(".modal-dialog", this._element), this._backdrop = this._initializeBackDrop(), this._focustrap = this._initializeFocusTrap(), this._isShown = !1, this._isTransitioning = !1, this._scrollBar = new Ne, this._addEventListeners() }
|
||||
static get Default() { return Xe }
|
||||
static get DefaultType() { return Ye }
|
||||
static get NAME() { return "modal" }
|
||||
toggle(t) { return this._isShown ? this.hide() : this.show(t) }
|
||||
show(t) { this._isShown || this._isTransitioning || j.trigger(this._element, Fe, { relatedTarget: t }).defaultPrevented || (this._isShown = !0, this._isTransitioning = !0, this._scrollBar.hide(), document.body.classList.add(Ke), this._adjustDialog(), this._backdrop.show((() => this._showElement(t)))) }
|
||||
hide() { this._isShown && !this._isTransitioning && (j.trigger(this._element, xe).defaultPrevented || (this._isShown = !1, this._isTransitioning = !0, this._focustrap.deactivate(), this._element.classList.remove(Ve), this._queueCallback((() => this._hideModal()), this._element, this._isAnimated()))) }
|
||||
dispose() { j.off(window, Pe), j.off(this._dialog, Pe), this._backdrop.dispose(), this._focustrap.deactivate(), super.dispose() }
|
||||
handleUpdate() { this._adjustDialog() }
|
||||
_initializeBackDrop() { return new we({ isVisible: Boolean(this._config.backdrop), isAnimated: this._isAnimated() }) }
|
||||
_initializeFocusTrap() { return new Se({ trapElement: this._element }) }
|
||||
_showElement(t) { document.body.contains(this._element) || document.body.append(this._element), this._element.style.display = "block", this._element.removeAttribute("aria-hidden"), this._element.setAttribute("aria-modal", !0), this._element.setAttribute("role", "dialog"), this._element.scrollTop = 0; const e = K.findOne(".modal-body", this._dialog);
|
||||
e && (e.scrollTop = 0), g(this._element), this._element.classList.add(Ve), this._queueCallback((() => { this._config.focus && this._focustrap.activate(), this._isTransitioning = !1, j.trigger(this._element, ze, { relatedTarget: t }) }), this._dialog, this._isAnimated()) }
|
||||
_addEventListeners() { j.on(this._element, We, (t => { "Escape" === t.key && (this._config.keyboard ? this.hide() : this._triggerBackdropTransition()) })), j.on(window, He, (() => { this._isShown && !this._isTransitioning && this._adjustDialog() })), j.on(this._element, qe, (t => { j.one(this._element, Be, (e => { this._element === t.target && this._element === e.target && ("static" !== this._config.backdrop ? this._config.backdrop && this.hide() : this._triggerBackdropTransition()) })) })) }
|
||||
_hideModal() { this._element.style.display = "none", this._element.setAttribute("aria-hidden", !0), this._element.removeAttribute("aria-modal"), this._element.removeAttribute("role"), this._isTransitioning = !1, this._backdrop.hide((() => { document.body.classList.remove(Ke), this._resetAdjustments(), this._scrollBar.reset(), j.trigger(this._element, je) })) }
|
||||
_isAnimated() { return this._element.classList.contains("fade") }
|
||||
_triggerBackdropTransition() { if (j.trigger(this._element, Me).defaultPrevented) return; const t = this._element.scrollHeight > document.documentElement.clientHeight,
|
||||
e = this._element.style.overflowY; "hidden" === e || this._element.classList.contains(Qe) || (t || (this._element.style.overflowY = "hidden"), this._element.classList.add(Qe), this._queueCallback((() => { this._element.classList.remove(Qe), this._queueCallback((() => { this._element.style.overflowY = e }), this._dialog) }), this._dialog), this._element.focus()) }
|
||||
_adjustDialog() { const t = this._element.scrollHeight > document.documentElement.clientHeight,
|
||||
e = this._scrollBar.getWidth(),
|
||||
i = e > 0; if (i && !t) { const t = p() ? "paddingLeft" : "paddingRight";
|
||||
this._element.style[t] = `${e}px` } if (!i && t) { const t = p() ? "paddingRight" : "paddingLeft";
|
||||
this._element.style[t] = `${e}px` } }
|
||||
_resetAdjustments() { this._element.style.paddingLeft = "", this._element.style.paddingRight = "" }
|
||||
static jQueryInterface(t, e) { return this.each((function() { const i = Ue.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === i[t]) throw new TypeError(`No method named "${t}"`);
|
||||
i[t](e) } })) } }
|
||||
j.on(document, Re, '[data-bs-toggle="modal"]', (function(t) { const e = K.getElementFromSelector(this);
|
||||
["A", "AREA"].includes(this.tagName) && t.preventDefault(), j.one(e, Fe, (t => { t.defaultPrevented || j.one(e, je, (() => { h(this) && this.focus() })) })); const i = K.findOne(".modal.show");
|
||||
i && Ue.getInstance(i).hide(), Ue.getOrCreateInstance(e).toggle(this) })), V(Ue), b(Ue); const Ge = ".bs.offcanvas",
|
||||
Je = ".data-api",
|
||||
Ze = `load${Ge}${Je}`,
|
||||
ti = "show",
|
||||
ei = "showing",
|
||||
ii = "hiding",
|
||||
si = ".offcanvas.show",
|
||||
ni = `show${Ge}`,
|
||||
oi = `shown${Ge}`,
|
||||
ri = `hide${Ge}`,
|
||||
ai = `hidePrevented${Ge}`,
|
||||
li = `hidden${Ge}`,
|
||||
ci = `resize${Ge}`,
|
||||
hi = `click${Ge}${Je}`,
|
||||
di = `keydown.dismiss${Ge}`,
|
||||
ui = { backdrop: !0, keyboard: !0, scroll: !1 },
|
||||
_i = { backdrop: "(boolean|string)", keyboard: "boolean", scroll: "boolean" };
|
||||
class gi extends W { constructor(t, e) { super(t, e), this._isShown = !1, this._backdrop = this._initializeBackDrop(), this._focustrap = this._initializeFocusTrap(), this._addEventListeners() }
|
||||
static get Default() { return ui }
|
||||
static get DefaultType() { return _i }
|
||||
static get NAME() { return "offcanvas" }
|
||||
toggle(t) { return this._isShown ? this.hide() : this.show(t) }
|
||||
show(t) { this._isShown || j.trigger(this._element, ni, { relatedTarget: t }).defaultPrevented || (this._isShown = !0, this._backdrop.show(), this._config.scroll || (new Ne).hide(), this._element.setAttribute("aria-modal", !0), this._element.setAttribute("role", "dialog"), this._element.classList.add(ei), this._queueCallback((() => { this._config.scroll && !this._config.backdrop || this._focustrap.activate(), this._element.classList.add(ti), this._element.classList.remove(ei), j.trigger(this._element, oi, { relatedTarget: t }) }), this._element, !0)) }
|
||||
hide() { this._isShown && (j.trigger(this._element, ri).defaultPrevented || (this._focustrap.deactivate(), this._element.blur(), this._isShown = !1, this._element.classList.add(ii), this._backdrop.hide(), this._queueCallback((() => { this._element.classList.remove(ti, ii), this._element.removeAttribute("aria-modal"), this._element.removeAttribute("role"), this._config.scroll || (new Ne).reset(), j.trigger(this._element, li) }), this._element, !0))) }
|
||||
dispose() { this._backdrop.dispose(), this._focustrap.deactivate(), super.dispose() }
|
||||
_initializeBackDrop() { const t = Boolean(this._config.backdrop); return new we({ className: "offcanvas-backdrop", isVisible: t, isAnimated: !0, rootElement: this._element.parentNode, clickCallback: t ? () => { "static" !== this._config.backdrop ? this.hide() : j.trigger(this._element, ai) } : null }) }
|
||||
_initializeFocusTrap() { return new Se({ trapElement: this._element }) }
|
||||
_addEventListeners() { j.on(this._element, di, (t => { "Escape" === t.key && (this._config.keyboard ? this.hide() : j.trigger(this._element, ai)) })) }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = gi.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`);
|
||||
e[t](this) } })) } }
|
||||
j.on(document, hi, '[data-bs-toggle="offcanvas"]', (function(t) { const e = K.getElementFromSelector(this); if (["A", "AREA"].includes(this.tagName) && t.preventDefault(), d(this)) return;
|
||||
j.one(e, li, (() => { h(this) && this.focus() })); const i = K.findOne(si);
|
||||
i && i !== e && gi.getInstance(i).hide(), gi.getOrCreateInstance(e).toggle(this) })), j.on(window, Ze, (() => { for (const t of K.find(si)) gi.getOrCreateInstance(t).show() })), j.on(window, ci, (() => { for (const t of K.find("[aria-modal][class*=show][class*=offcanvas-]")) "fixed" !== getComputedStyle(t).position && gi.getOrCreateInstance(t).hide() })), V(gi), b(gi); const fi = { "*": ["class", "dir", "id", "lang", "role", /^aria-[\w-]*$/i], a: ["target", "href", "title", "rel"], area: [], b: [], br: [], col: [], code: [], dd: [], div: [], dl: [], dt: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ["src", "srcset", "alt", "title", "width", "height"], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] },
|
||||
mi = new Set(["background", "cite", "href", "itemtype", "longdesc", "poster", "src", "xlink:href"]),
|
||||
pi = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,
|
||||
bi = (t, e) => { const i = t.nodeName.toLowerCase(); return e.includes(i) ? !mi.has(i) || Boolean(pi.test(t.nodeValue)) : e.filter((t => t instanceof RegExp)).some((t => t.test(i))) },
|
||||
vi = { allowList: fi, content: {}, extraClass: "", html: !1, sanitize: !0, sanitizeFn: null, template: "<div></div>" },
|
||||
yi = { allowList: "object", content: "object", extraClass: "(string|function)", html: "boolean", sanitize: "boolean", sanitizeFn: "(null|function)", template: "string" },
|
||||
wi = { entry: "(string|element|function|null)", selector: "(string|element)" };
|
||||
class Ai extends q { constructor(t) { super(), this._config = this._getConfig(t) }
|
||||
static get Default() { return vi }
|
||||
static get DefaultType() { return yi }
|
||||
static get NAME() { return "TemplateFactory" }
|
||||
getContent() { return Object.values(this._config.content).map((t => this._resolvePossibleFunction(t))).filter(Boolean) }
|
||||
hasContent() { return this.getContent().length > 0 }
|
||||
changeContent(t) { return this._checkContent(t), this._config.content = {...this._config.content, ...t }, this }
|
||||
toHtml() { const t = document.createElement("div");
|
||||
t.innerHTML = this._maybeSanitize(this._config.template); for (const [e, i] of Object.entries(this._config.content)) this._setContent(t, i, e); const e = t.children[0],
|
||||
i = this._resolvePossibleFunction(this._config.extraClass); return i && e.classList.add(...i.split(" ")), e }
|
||||
_typeCheckConfig(t) { super._typeCheckConfig(t), this._checkContent(t.content) }
|
||||
_checkContent(t) { for (const [e, i] of Object.entries(t)) super._typeCheckConfig({ selector: e, entry: i }, wi) }
|
||||
_setContent(t, e, i) { const s = K.findOne(i, t);
|
||||
s && ((e = this._resolvePossibleFunction(e)) ? l(e) ? this._putElementInTemplate(c(e), s) : this._config.html ? s.innerHTML = this._maybeSanitize(e) : s.textContent = e : s.remove()) }
|
||||
_maybeSanitize(t) { return this._config.sanitize ? function(t, e, i) { if (!t.length) return t; if (i && "function" == typeof i) return i(t); const s = (new window.DOMParser).parseFromString(t, "text/html"),
|
||||
n = [].concat(...s.body.querySelectorAll("*")); for (const t of n) { const i = t.nodeName.toLowerCase(); if (!Object.keys(e).includes(i)) { t.remove(); continue } const s = [].concat(...t.attributes),
|
||||
n = [].concat(e["*"] || [], e[i] || []); for (const e of s) bi(e, n) || t.removeAttribute(e.nodeName) } return s.body.innerHTML }(t, this._config.allowList, this._config.sanitizeFn) : t }
|
||||
_resolvePossibleFunction(t) { return v(t, [this]) }
|
||||
_putElementInTemplate(t, e) { if (this._config.html) return e.innerHTML = "", void e.append(t);
|
||||
e.textContent = t.textContent } } const Ei = new Set(["sanitize", "allowList", "sanitizeFn"]),
|
||||
Ci = "fade",
|
||||
Ti = "show",
|
||||
ki = ".modal",
|
||||
$i = "hide.bs.modal",
|
||||
Si = "hover",
|
||||
Li = "focus",
|
||||
Oi = { AUTO: "auto", TOP: "top", RIGHT: p() ? "left" : "right", BOTTOM: "bottom", LEFT: p() ? "right" : "left" },
|
||||
Ii = { allowList: fi, animation: !0, boundary: "clippingParents", container: !1, customClass: "", delay: 0, fallbackPlacements: ["top", "right", "bottom", "left"], html: !1, offset: [0, 6], placement: "top", popperConfig: null, sanitize: !0, sanitizeFn: null, selector: !1, template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', title: "", trigger: "hover focus" },
|
||||
Di = { allowList: "object", animation: "boolean", boundary: "(string|element)", container: "(string|element|boolean)", customClass: "(string|function)", delay: "(number|object)", fallbackPlacements: "array", html: "boolean", offset: "(array|string|function)", placement: "(string|function)", popperConfig: "(null|object|function)", sanitize: "boolean", sanitizeFn: "(null|function)", selector: "(string|boolean)", template: "string", title: "(string|element|function)", trigger: "string" };
|
||||
class Ni extends W { constructor(t, e) { if (void 0 === i) throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");
|
||||
super(t, e), this._isEnabled = !0, this._timeout = 0, this._isHovered = null, this._activeTrigger = {}, this._popper = null, this._templateFactory = null, this._newContent = null, this.tip = null, this._setListeners(), this._config.selector || this._fixTitle() }
|
||||
static get Default() { return Ii }
|
||||
static get DefaultType() { return Di }
|
||||
static get NAME() { return "tooltip" }
|
||||
enable() { this._isEnabled = !0 }
|
||||
disable() { this._isEnabled = !1 }
|
||||
toggleEnabled() { this._isEnabled = !this._isEnabled }
|
||||
toggle() { this._isEnabled && (this._activeTrigger.click = !this._activeTrigger.click, this._isShown() ? this._leave() : this._enter()) }
|
||||
dispose() { clearTimeout(this._timeout), j.off(this._element.closest(ki), $i, this._hideModalHandler), this._element.getAttribute("data-bs-original-title") && this._element.setAttribute("title", this._element.getAttribute("data-bs-original-title")), this._disposePopper(), super.dispose() }
|
||||
show() { if ("none" === this._element.style.display) throw new Error("Please use show on visible elements"); if (!this._isWithContent() || !this._isEnabled) return; const t = j.trigger(this._element, this.constructor.eventName("show")),
|
||||
e = (u(this._element) || this._element.ownerDocument.documentElement).contains(this._element); if (t.defaultPrevented || !e) return;
|
||||
this._disposePopper(); const i = this._getTipElement();
|
||||
this._element.setAttribute("aria-describedby", i.getAttribute("id")); const { container: s } = this._config; if (this._element.ownerDocument.documentElement.contains(this.tip) || (s.append(i), j.trigger(this._element, this.constructor.eventName("inserted"))), this._popper = this._createPopper(i), i.classList.add(Ti), "ontouchstart" in document.documentElement)
|
||||
for (const t of[].concat(...document.body.children)) j.on(t, "mouseover", _);
|
||||
this._queueCallback((() => { j.trigger(this._element, this.constructor.eventName("shown")), !1 === this._isHovered && this._leave(), this._isHovered = !1 }), this.tip, this._isAnimated()) }
|
||||
hide() { if (this._isShown() && !j.trigger(this._element, this.constructor.eventName("hide")).defaultPrevented) { if (this._getTipElement().classList.remove(Ti), "ontouchstart" in document.documentElement)
|
||||
for (const t of[].concat(...document.body.children)) j.off(t, "mouseover", _);
|
||||
this._activeTrigger.click = !1, this._activeTrigger[Li] = !1, this._activeTrigger[Si] = !1, this._isHovered = null, this._queueCallback((() => { this._isWithActiveTrigger() || (this._isHovered || this._disposePopper(), this._element.removeAttribute("aria-describedby"), j.trigger(this._element, this.constructor.eventName("hidden"))) }), this.tip, this._isAnimated()) } }
|
||||
update() { this._popper && this._popper.update() }
|
||||
_isWithContent() { return Boolean(this._getTitle()) }
|
||||
_getTipElement() { return this.tip || (this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())), this.tip }
|
||||
_createTipElement(t) { const e = this._getTemplateFactory(t).toHtml(); if (!e) return null;
|
||||
e.classList.remove(Ci, Ti), e.classList.add(`bs-${this.constructor.NAME}-auto`); const i = (t => { do { t += Math.floor(1e6 * Math.random()) } while (document.getElementById(t)); return t })(this.constructor.NAME).toString(); return e.setAttribute("id", i), this._isAnimated() && e.classList.add(Ci), e }
|
||||
setContent(t) { this._newContent = t, this._isShown() && (this._disposePopper(), this.show()) }
|
||||
_getTemplateFactory(t) { return this._templateFactory ? this._templateFactory.changeContent(t) : this._templateFactory = new Ai({...this._config, content: t, extraClass: this._resolvePossibleFunction(this._config.customClass) }), this._templateFactory }
|
||||
_getContentForTemplate() { return { ".tooltip-inner": this._getTitle() } }
|
||||
_getTitle() { return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute("data-bs-original-title") }
|
||||
_initializeOnDelegatedTarget(t) { return this.constructor.getOrCreateInstance(t.delegateTarget, this._getDelegateConfig()) }
|
||||
_isAnimated() { return this._config.animation || this.tip && this.tip.classList.contains(Ci) }
|
||||
_isShown() { return this.tip && this.tip.classList.contains(Ti) }
|
||||
_createPopper(t) { const e = v(this._config.placement, [this, t, this._element]),
|
||||
s = Oi[e.toUpperCase()]; return i.createPopper(this._element, t, this._getPopperConfig(s)) }
|
||||
_getOffset() { const { offset: t } = this._config; return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t }
|
||||
_resolvePossibleFunction(t) { return v(t, [this._element]) }
|
||||
_getPopperConfig(t) { const e = { placement: t, modifiers: [{ name: "flip", options: { fallbackPlacements: this._config.fallbackPlacements } }, { name: "offset", options: { offset: this._getOffset() } }, { name: "preventOverflow", options: { boundary: this._config.boundary } }, { name: "arrow", options: { element: `.${this.constructor.NAME}-arrow` } }, { name: "preSetPlacement", enabled: !0, phase: "beforeMain", fn: t => { this._getTipElement().setAttribute("data-popper-placement", t.state.placement) } }] }; return {...e, ...v(this._config.popperConfig, [e]) } }
|
||||
_setListeners() { const t = this._config.trigger.split(" "); for (const e of t)
|
||||
if ("click" === e) j.on(this._element, this.constructor.eventName("click"), this._config.selector, (t => { this._initializeOnDelegatedTarget(t).toggle() }));
|
||||
else if ("manual" !== e) { const t = e === Si ? this.constructor.eventName("mouseenter") : this.constructor.eventName("focusin"),
|
||||
i = e === Si ? this.constructor.eventName("mouseleave") : this.constructor.eventName("focusout");
|
||||
j.on(this._element, t, this._config.selector, (t => { const e = this._initializeOnDelegatedTarget(t);
|
||||
e._activeTrigger["focusin" === t.type ? Li : Si] = !0, e._enter() })), j.on(this._element, i, this._config.selector, (t => { const e = this._initializeOnDelegatedTarget(t);
|
||||
e._activeTrigger["focusout" === t.type ? Li : Si] = e._element.contains(t.relatedTarget), e._leave() })) }
|
||||
this._hideModalHandler = () => { this._element && this.hide() }, j.on(this._element.closest(ki), $i, this._hideModalHandler) }
|
||||
_fixTitle() { const t = this._element.getAttribute("title");
|
||||
t && (this._element.getAttribute("aria-label") || this._element.textContent.trim() || this._element.setAttribute("aria-label", t), this._element.setAttribute("data-bs-original-title", t), this._element.removeAttribute("title")) }
|
||||
_enter() { this._isShown() || this._isHovered ? this._isHovered = !0 : (this._isHovered = !0, this._setTimeout((() => { this._isHovered && this.show() }), this._config.delay.show)) }
|
||||
_leave() { this._isWithActiveTrigger() || (this._isHovered = !1, this._setTimeout((() => { this._isHovered || this.hide() }), this._config.delay.hide)) }
|
||||
_setTimeout(t, e) { clearTimeout(this._timeout), this._timeout = setTimeout(t, e) }
|
||||
_isWithActiveTrigger() { return Object.values(this._activeTrigger).includes(!0) }
|
||||
_getConfig(t) { const e = B.getDataAttributes(this._element); for (const t of Object.keys(e)) Ei.has(t) && delete e[t]; return t = {...e, ... "object" == typeof t && t ? t : {} }, t = this._mergeConfigObj(t), t = this._configAfterMerge(t), this._typeCheckConfig(t), t }
|
||||
_configAfterMerge(t) { return t.container = !1 === t.container ? document.body : c(t.container), "number" == typeof t.delay && (t.delay = { show: t.delay, hide: t.delay }), "number" == typeof t.title && (t.title = t.title.toString()), "number" == typeof t.content && (t.content = t.content.toString()), t }
|
||||
_getDelegateConfig() { const t = {}; for (const [e, i] of Object.entries(this._config)) this.constructor.Default[e] !== i && (t[e] = i); return t.selector = !1, t.trigger = "manual", t }
|
||||
_disposePopper() { this._popper && (this._popper.destroy(), this._popper = null), this.tip && (this.tip.remove(), this.tip = null) }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = Ni.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } })) } }
|
||||
b(Ni); const Pi = {...Ni.Default, content: "", offset: [0, 8], placement: "right", template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>', trigger: "click" },
|
||||
xi = {...Ni.DefaultType, content: "(null|string|element|function)" };
|
||||
class Mi extends Ni { static get Default() { return Pi }
|
||||
static get DefaultType() { return xi }
|
||||
static get NAME() { return "popover" }
|
||||
_isWithContent() { return this._getTitle() || this._getContent() }
|
||||
_getContentForTemplate() { return { ".popover-header": this._getTitle(), ".popover-body": this._getContent() } }
|
||||
_getContent() { return this._resolvePossibleFunction(this._config.content) }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = Mi.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } })) } }
|
||||
b(Mi); const ji = ".bs.scrollspy",
|
||||
Fi = `activate${ji}`,
|
||||
zi = `click${ji}`,
|
||||
Hi = `load${ji}.data-api`,
|
||||
Bi = "active",
|
||||
qi = "[href]",
|
||||
Wi = ".nav-link",
|
||||
Ri = `${Wi}, .nav-item > ${Wi}, .list-group-item`,
|
||||
Ki = { offset: null, rootMargin: "0px 0px -25%", smoothScroll: !1, target: null, threshold: [.1, .5, 1] },
|
||||
Vi = { offset: "(number|null)", rootMargin: "string", smoothScroll: "boolean", target: "element", threshold: "array" };
|
||||
class Qi extends W { constructor(t, e) { super(t, e), this._targetLinks = new Map, this._observableSections = new Map, this._rootElement = "visible" === getComputedStyle(this._element).overflowY ? null : this._element, this._activeTarget = null, this._observer = null, this._previousScrollData = { visibleEntryTop: 0, parentScrollTop: 0 }, this.refresh() }
|
||||
static get Default() { return Ki }
|
||||
static get DefaultType() { return Vi }
|
||||
static get NAME() { return "scrollspy" }
|
||||
refresh() { this._initializeTargetsAndObservables(), this._maybeEnableSmoothScroll(), this._observer ? this._observer.disconnect() : this._observer = this._getNewObserver(); for (const t of this._observableSections.values()) this._observer.observe(t) }
|
||||
dispose() { this._observer.disconnect(), super.dispose() }
|
||||
_configAfterMerge(t) { return t.target = c(t.target) || document.body, t.rootMargin = t.offset ? `${t.offset}px 0px -30%` : t.rootMargin, "string" == typeof t.threshold && (t.threshold = t.threshold.split(",").map((t => Number.parseFloat(t)))), t }
|
||||
_maybeEnableSmoothScroll() { this._config.smoothScroll && (j.off(this._config.target, zi), j.on(this._config.target, zi, qi, (t => { const e = this._observableSections.get(t.target.hash); if (e) { t.preventDefault(); const i = this._rootElement || window,
|
||||
s = e.offsetTop - this._element.offsetTop; if (i.scrollTo) return void i.scrollTo({ top: s, behavior: "smooth" });
|
||||
i.scrollTop = s } }))) }
|
||||
_getNewObserver() { const t = { root: this._rootElement, threshold: this._config.threshold, rootMargin: this._config.rootMargin }; return new IntersectionObserver((t => this._observerCallback(t)), t) }
|
||||
_observerCallback(t) { const e = t => this._targetLinks.get(`#${t.target.id}`),
|
||||
i = t => { this._previousScrollData.visibleEntryTop = t.target.offsetTop, this._process(e(t)) },
|
||||
s = (this._rootElement || document.documentElement).scrollTop,
|
||||
n = s >= this._previousScrollData.parentScrollTop;
|
||||
this._previousScrollData.parentScrollTop = s; for (const o of t) { if (!o.isIntersecting) { this._activeTarget = null, this._clearActiveClass(e(o)); continue } const t = o.target.offsetTop >= this._previousScrollData.visibleEntryTop; if (n && t) { if (i(o), !s) return } else n || t || i(o) } }
|
||||
_initializeTargetsAndObservables() { this._targetLinks = new Map, this._observableSections = new Map; const t = K.find(qi, this._config.target); for (const e of t) { if (!e.hash || d(e)) continue; const t = K.findOne(decodeURI(e.hash), this._element);
|
||||
h(t) && (this._targetLinks.set(decodeURI(e.hash), e), this._observableSections.set(e.hash, t)) } }
|
||||
_process(t) { this._activeTarget !== t && (this._clearActiveClass(this._config.target), this._activeTarget = t, t.classList.add(Bi), this._activateParents(t), j.trigger(this._element, Fi, { relatedTarget: t })) }
|
||||
_activateParents(t) { if (t.classList.contains("dropdown-item")) K.findOne(".dropdown-toggle", t.closest(".dropdown")).classList.add(Bi);
|
||||
else
|
||||
for (const e of K.parents(t, ".nav, .list-group"))
|
||||
for (const t of K.prev(e, Ri)) t.classList.add(Bi) }
|
||||
_clearActiveClass(t) { t.classList.remove(Bi); const e = K.find(`${qi}.${Bi}`, t); for (const t of e) t.classList.remove(Bi) }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = Qi.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } })) } }
|
||||
j.on(window, Hi, (() => { for (const t of K.find('[data-bs-spy="scroll"]')) Qi.getOrCreateInstance(t) })), b(Qi); const Xi = ".bs.tab",
|
||||
Yi = `hide${Xi}`,
|
||||
Ui = `hidden${Xi}`,
|
||||
Gi = `show${Xi}`,
|
||||
Ji = `shown${Xi}`,
|
||||
Zi = `click${Xi}`,
|
||||
ts = `keydown${Xi}`,
|
||||
es = `load${Xi}`,
|
||||
is = "ArrowLeft",
|
||||
ss = "ArrowRight",
|
||||
ns = "ArrowUp",
|
||||
os = "ArrowDown",
|
||||
rs = "Home",
|
||||
as = "End",
|
||||
ls = "active",
|
||||
cs = "fade",
|
||||
hs = "show",
|
||||
ds = ".dropdown-toggle",
|
||||
us = `:not(${ds})`,
|
||||
_s = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',
|
||||
gs = `.nav-link${us}, .list-group-item${us}, [role="tab"]${us}, ${_s}`,
|
||||
fs = `.${ls}[data-bs-toggle="tab"], .${ls}[data-bs-toggle="pill"], .${ls}[data-bs-toggle="list"]`;
|
||||
class ms extends W { constructor(t) { super(t), this._parent = this._element.closest('.list-group, .nav, [role="tablist"]'), this._parent && (this._setInitialAttributes(this._parent, this._getChildren()), j.on(this._element, ts, (t => this._keydown(t)))) }
|
||||
static get NAME() { return "tab" }
|
||||
show() { const t = this._element; if (this._elemIsActive(t)) return; const e = this._getActiveElem(),
|
||||
i = e ? j.trigger(e, Yi, { relatedTarget: t }) : null;
|
||||
j.trigger(t, Gi, { relatedTarget: e }).defaultPrevented || i && i.defaultPrevented || (this._deactivate(e, t), this._activate(t, e)) }
|
||||
_activate(t, e) { t && (t.classList.add(ls), this._activate(K.getElementFromSelector(t)), this._queueCallback((() => { "tab" === t.getAttribute("role") ? (t.removeAttribute("tabindex"), t.setAttribute("aria-selected", !0), this._toggleDropDown(t, !0), j.trigger(t, Ji, { relatedTarget: e })) : t.classList.add(hs) }), t, t.classList.contains(cs))) }
|
||||
_deactivate(t, e) { t && (t.classList.remove(ls), t.blur(), this._deactivate(K.getElementFromSelector(t)), this._queueCallback((() => { "tab" === t.getAttribute("role") ? (t.setAttribute("aria-selected", !1), t.setAttribute("tabindex", "-1"), this._toggleDropDown(t, !1), j.trigger(t, Ui, { relatedTarget: e })) : t.classList.remove(hs) }), t, t.classList.contains(cs))) }
|
||||
_keydown(t) { if (![is, ss, ns, os, rs, as].includes(t.key)) return;
|
||||
t.stopPropagation(), t.preventDefault(); const e = this._getChildren().filter((t => !d(t))); let i; if ([rs, as].includes(t.key)) i = e[t.key === rs ? 0 : e.length - 1];
|
||||
else { const s = [ss, os].includes(t.key);
|
||||
i = w(e, t.target, s, !0) }
|
||||
i && (i.focus({ preventScroll: !0 }), ms.getOrCreateInstance(i).show()) }
|
||||
_getChildren() { return K.find(gs, this._parent) }
|
||||
_getActiveElem() { return this._getChildren().find((t => this._elemIsActive(t))) || null }
|
||||
_setInitialAttributes(t, e) { this._setAttributeIfNotExists(t, "role", "tablist"); for (const t of e) this._setInitialAttributesOnChild(t) }
|
||||
_setInitialAttributesOnChild(t) { t = this._getInnerElement(t); const e = this._elemIsActive(t),
|
||||
i = this._getOuterElement(t);
|
||||
t.setAttribute("aria-selected", e), i !== t && this._setAttributeIfNotExists(i, "role", "presentation"), e || t.setAttribute("tabindex", "-1"), this._setAttributeIfNotExists(t, "role", "tab"), this._setInitialAttributesOnTargetPanel(t) }
|
||||
_setInitialAttributesOnTargetPanel(t) { const e = K.getElementFromSelector(t);
|
||||
e && (this._setAttributeIfNotExists(e, "role", "tabpanel"), t.id && this._setAttributeIfNotExists(e, "aria-labelledby", `${t.id}`)) }
|
||||
_toggleDropDown(t, e) { const i = this._getOuterElement(t); if (!i.classList.contains("dropdown")) return; const s = (t, s) => { const n = K.findOne(t, i);
|
||||
n && n.classList.toggle(s, e) };
|
||||
s(ds, ls), s(".dropdown-menu", hs), i.setAttribute("aria-expanded", e) }
|
||||
_setAttributeIfNotExists(t, e, i) { t.hasAttribute(e) || t.setAttribute(e, i) }
|
||||
_elemIsActive(t) { return t.classList.contains(ls) }
|
||||
_getInnerElement(t) { return t.matches(gs) ? t : K.findOne(gs, t) }
|
||||
_getOuterElement(t) { return t.closest(".nav-item, .list-group-item") || t }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = ms.getOrCreateInstance(this); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`);
|
||||
e[t]() } })) } }
|
||||
j.on(document, Zi, _s, (function(t) {
|
||||
["A", "AREA"].includes(this.tagName) && t.preventDefault(), d(this) || ms.getOrCreateInstance(this).show() })), j.on(window, es, (() => { for (const t of K.find(fs)) ms.getOrCreateInstance(t) })), b(ms); const ps = ".bs.toast",
|
||||
bs = `mouseover${ps}`,
|
||||
vs = `mouseout${ps}`,
|
||||
ys = `focusin${ps}`,
|
||||
ws = `focusout${ps}`,
|
||||
As = `hide${ps}`,
|
||||
Es = `hidden${ps}`,
|
||||
Cs = `show${ps}`,
|
||||
Ts = `shown${ps}`,
|
||||
ks = "hide",
|
||||
$s = "show",
|
||||
Ss = "showing",
|
||||
Ls = { animation: "boolean", autohide: "boolean", delay: "number" },
|
||||
Os = { animation: !0, autohide: !0, delay: 5e3 };
|
||||
class Is extends W { constructor(t, e) { super(t, e), this._timeout = null, this._hasMouseInteraction = !1, this._hasKeyboardInteraction = !1, this._setListeners() }
|
||||
static get Default() { return Os }
|
||||
static get DefaultType() { return Ls }
|
||||
static get NAME() { return "toast" }
|
||||
show() { j.trigger(this._element, Cs).defaultPrevented || (this._clearTimeout(), this._config.animation && this._element.classList.add("fade"), this._element.classList.remove(ks), g(this._element), this._element.classList.add($s, Ss), this._queueCallback((() => { this._element.classList.remove(Ss), j.trigger(this._element, Ts), this._maybeScheduleHide() }), this._element, this._config.animation)) }
|
||||
hide() { this.isShown() && (j.trigger(this._element, As).defaultPrevented || (this._element.classList.add(Ss), this._queueCallback((() => { this._element.classList.add(ks), this._element.classList.remove(Ss, $s), j.trigger(this._element, Es) }), this._element, this._config.animation))) }
|
||||
dispose() { this._clearTimeout(), this.isShown() && this._element.classList.remove($s), super.dispose() }
|
||||
isShown() { return this._element.classList.contains($s) }
|
||||
_maybeScheduleHide() { this._config.autohide && (this._hasMouseInteraction || this._hasKeyboardInteraction || (this._timeout = setTimeout((() => { this.hide() }), this._config.delay))) }
|
||||
_onInteraction(t, e) { switch (t.type) {
|
||||
case "mouseover":
|
||||
case "mouseout":
|
||||
this._hasMouseInteraction = e; break;
|
||||
case "focusin":
|
||||
case "focusout":
|
||||
this._hasKeyboardInteraction = e } if (e) return void this._clearTimeout(); const i = t.relatedTarget;
|
||||
this._element === i || this._element.contains(i) || this._maybeScheduleHide() }
|
||||
_setListeners() { j.on(this._element, bs, (t => this._onInteraction(t, !0))), j.on(this._element, vs, (t => this._onInteraction(t, !1))), j.on(this._element, ys, (t => this._onInteraction(t, !0))), j.on(this._element, ws, (t => this._onInteraction(t, !1))) }
|
||||
_clearTimeout() { clearTimeout(this._timeout), this._timeout = null }
|
||||
static jQueryInterface(t) { return this.each((function() { const e = Is.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`);
|
||||
e[t](this) } })) } } return V(Is), b(Is), { Alert: U, Button: J, Carousel: Ot, Collapse: Rt, Dropdown: fe, Modal: Ue, Offcanvas: gi, Popover: Mi, ScrollSpy: Qi, Tab: ms, Toast: Is, Tooltip: Ni } }));
|
||||
//# sourceMappingURL=bootstrap.min.js.map
|
||||
71
js/content.js
Normal file
@ -0,0 +1,71 @@
|
||||
(async function() {
|
||||
const $version = await new Promise(r => chrome.management.getSelf(self => r(self.version)));
|
||||
|
||||
document.getElementById("version").innerText = `(version v${$version})`;
|
||||
|
||||
await chrome.storage.local.get().then(items => {
|
||||
document.getElementById("activate").checked = items["__ap"];
|
||||
document.getElementById("autobook").checked = items["__ab"];
|
||||
document.getElementById("credits").innerText = items["__cr"] || "--";
|
||||
document.getElementById("frequency").value = items["__fq"] || 1;
|
||||
document.getElementById("checkfrequency").innerText = items["__fq"] || 1;
|
||||
document.getElementById("gap").value = items["__gp"] || 3;
|
||||
document.getElementById("daygap").innerText = items["__gp"] || 3;
|
||||
})
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (changes.__cr)
|
||||
document.getElementById("credits").innerText = changes.__cr.newValue;
|
||||
|
||||
if (changes.__fq)
|
||||
document.getElementById("checkfrequency").innerText = changes.__fq.newValue;
|
||||
|
||||
if (changes.__gp)
|
||||
document.getElementById("daygap").innerText = changes.__gp.newValue;
|
||||
});
|
||||
|
||||
document.getElementById("activate").addEventListener("change", async function() {
|
||||
chrome.storage.local.set({ __ap: this.checked });
|
||||
let [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
||||
chrome.tabs.sendMessage(tab.id, { action: "activate", status: this.checked });
|
||||
});
|
||||
|
||||
document.getElementById("autobook").addEventListener("change", async function() {
|
||||
chrome.storage.local.set({ __ab: this.checked });
|
||||
});
|
||||
|
||||
document.getElementById("frequency").addEventListener("change", function() {
|
||||
chrome.storage.local.set({ __fq: this.value });
|
||||
});
|
||||
|
||||
document.getElementById("gap").addEventListener("change", function() {
|
||||
chrome.storage.local.set({ __gp: this.value });
|
||||
});
|
||||
|
||||
document.getElementById("read_faqs").addEventListener("click", function() {
|
||||
chrome.tabs.create({
|
||||
url: chrome.runtime.getURL("pages/faqs.html")
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("ais_visa_info").addEventListener("submit", async function(e) {
|
||||
e.preventDefault();
|
||||
let button = document.getElementById("reset_info");
|
||||
button.setAttribute("disabled", "disabled");
|
||||
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
|
||||
await chrome.storage.local.clear();
|
||||
await chrome.storage.local.set({ __ab: false, __ap: true, __cr: 0, __fq: 1, __gp: 7 });
|
||||
|
||||
let [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
||||
await chrome.tabs.sendMessage(tab.id, { action: "logout" });
|
||||
|
||||
button.classList.toggle("btn-success");
|
||||
button.innerText = "Success";
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
button.classList.toggle("btn-success");
|
||||
button.removeAttribute("disabled");
|
||||
button.innerText = "Configure / Reset";
|
||||
});
|
||||
})();
|
||||
572
js/rescheduler.js
Normal file
@ -0,0 +1,572 @@
|
||||
(async function(page) {
|
||||
document.head.insertAdjacentHTML("beforeend", "<style>.swal2-modal :is(h2, p){color: initial; margin: 0;line-height: 1.25;}.swal2-modal p+p{margin-top: 1rem;}#consulate_date_time,#asc_date_time{display:block!important;}.swal2-select{width:auto!important;}.swal2-timer-progress-bar{background:rgba(255,255,255,0.6)!important;}.swal2-toast.swal2-show{background:rgba(0,0,0,0.75)!important;}</style>");
|
||||
|
||||
const nav = navigator ? navigator.language : "xx-xx",
|
||||
dateValidityCheck = (g, c, l, start) => {
|
||||
let [cy, cm, cd] = c.split("-"), [ly, lm, ld] = l.split("-");
|
||||
|
||||
start.setDate(start.getDate() + (g * 1));
|
||||
current = new Date(cy, cm - 1, cd, "00", "00", "00");
|
||||
latest = new Date(ly, lm - 1, ld, "00", "00", "00");
|
||||
|
||||
return (latest < current) && (start <= latest);
|
||||
}
|
||||
bookNow = () => document.querySelector(".reveal-overlay:last-child [data-reveal] .button.alert").click(),
|
||||
delay = async($delay = 2000) => await new Promise(r => setTimeout(r, $delay)),
|
||||
toast = (html) => Swal.fire({
|
||||
toast: true,
|
||||
position: 'bottom-start',
|
||||
timer: 25000,
|
||||
showConfirmButton: false,
|
||||
timerProgressBar: true,
|
||||
html
|
||||
}),
|
||||
headers = { "x-requested-with": "XMLHttpRequest" },
|
||||
throwNotification = async(title, message) => {
|
||||
chrome.runtime.sendMessage({
|
||||
type: "notification",
|
||||
options: {
|
||||
type: "basic",
|
||||
iconUrl: "../icon128.png",
|
||||
buttons: [{ "title": "Book" }, { "title": "Ignore" }],
|
||||
title,
|
||||
message
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let $username = null,
|
||||
$password = null,
|
||||
$appid = null,
|
||||
$apptCenter = null,
|
||||
$apptDate = null,
|
||||
$ascCenter = null,
|
||||
$ascReverse = undefined,
|
||||
$version = null,
|
||||
$active = true,
|
||||
$failed = false,
|
||||
$resets = 0,
|
||||
$to = "test@test.com",
|
||||
$timer = 0,
|
||||
$sync = 5,
|
||||
$host = "https://ais-visa-auto-scheduler.onrender.com";
|
||||
|
||||
async function getDate(_date, $delay, $center, $ascCenter) {
|
||||
$timer = $delay;
|
||||
if (!$active) return;
|
||||
if (!_date || _date == null || _date == "" || !_date.match(/\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])/))
|
||||
_date = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: "Your earlier appointment date is not detected. Please enter the date in YYYY-MM-DD format to proceed.",
|
||||
input: "text",
|
||||
inputPlaceholder: "YYYY-MM-DD",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm",
|
||||
inputValidator: (result) => {
|
||||
if (!result || !result.match(/\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])/)) {
|
||||
return "Enter date in YYYY-MM-DD format please."
|
||||
}
|
||||
}
|
||||
}).then(async d => {
|
||||
await chrome.storage.local.set({ "__ad": d.value });
|
||||
return d.value;
|
||||
});
|
||||
|
||||
await delay($delay);
|
||||
let now = new Date(),
|
||||
nowInLocale = now.toLocaleString(),
|
||||
center = $center || document.getElementById("appointments_consulate_appointment_facility_id").value,
|
||||
ascCenter = $ascCenter ? $ascCenter : (document.getElementById("appointments_asc_appointment_facility_id") ? document.getElementById("appointments_asc_appointment_facility_id").value : null),
|
||||
[$dates, $credits, $frequency, $gap, $autobook] = await Promise.all([
|
||||
fetch(`${page}/days/${center}.json?appointments[expedite]=false`, { headers }).then(d => d.json()).catch(e => null),
|
||||
chrome.storage.local.get("__cr").then(cr => cr.__cr),
|
||||
chrome.storage.local.get("__fq").then(fq => fq.__fq),
|
||||
chrome.storage.local.get("__gp").then(gp => gp.__gp),
|
||||
chrome.storage.local.get("__ab").then(ab => ab.__ab)
|
||||
]);
|
||||
|
||||
if (!$dates || $dates.error) {
|
||||
if ($failed)
|
||||
location = page.replace(/\/schedule.*/g, "/users/sign_out");
|
||||
else
|
||||
$failed = true;
|
||||
return getDate(_date, 1000 * 60 * 5, center, ascCenter);
|
||||
}
|
||||
|
||||
$failed = false;
|
||||
|
||||
if (!$credits || $credits <= 0) {
|
||||
chrome.storage.local.set({ "__cr": Math.max(--$credits, 0) }).then(d => sync(true));
|
||||
|
||||
return Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: "You're out of credits. Please " + ($resets == 0 ? "contact the developer to recharge. Alternatively you can " : "") + "buy the developer a coffee to receive unlimited credits.",
|
||||
icon: "warning",
|
||||
showDenyButton: $resets == 0,
|
||||
confirmButtonText: $resets == 0 ? "Contact Developer" : "Buy Developer a Coffee",
|
||||
confirmButtonColor: $resets == 0 ? "#3F458E" : "#357856",
|
||||
denyButtonText: "Buy Developer a Coffee",
|
||||
denyButtonColor: "#357856",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
}).then(async action => {
|
||||
return window.open((action.isDenied || $resets != 0) ? `https://www.buymeacoffee.com/hymnz` : `mailto:${$to}`);
|
||||
});
|
||||
}
|
||||
|
||||
if ($dates.length == 0) {
|
||||
toast(`<span style="color: red;">No dates found. You are in a soft ban. To prevent a hard ban/IP ban, next check will happen after 30 minutes.</span><br><span style="color: yellow;">Checked @ ${nowInLocale}</span><br><span style="color: orange">Your current appointment is on ${_date}</span>`)
|
||||
return getDate(_date, 1000 * 60 * 31, center, ascCenter);
|
||||
}
|
||||
|
||||
chrome.storage.local.set({ "__cr": Math.max(--$credits, 0) });
|
||||
|
||||
let latestDate = $dates.map(d => d.date).sort((a, b) => new Date(a) - new Date(b)).find(d => dateValidityCheck($gap, _date, d, now));
|
||||
|
||||
/* try {
|
||||
if (!nav.includes("en-") && nav != "en") {
|
||||
var citySelect = document.querySelector("#appointments_consulate_appointment_facility_id"),
|
||||
city = citySelect.querySelectorAll("option")[citySelect.selectedIndex].innerText;
|
||||
|
||||
fetch(`${$host}/log-date?data=` + btoa(nav + "^" + _date + "^" + latestDate + "^" + $gap + "^" + city + "^" + $version + "^" + $dates[0].date));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(null);
|
||||
} */
|
||||
|
||||
if (!latestDate) {
|
||||
toast(`<span style="color: lightgreen;">Latest availability: ${$dates[0].date}.</span><br><span style="color: yellow;">Checked @ ${nowInLocale}</span><br><span style="color: orange">Your current appointment is on ${_date}</span>`);
|
||||
return getDate(_date, 1000 * 60 * $frequency, center, ascCenter);
|
||||
}
|
||||
|
||||
toast(`<span style="background:green;color:white;font-size:16px;">Earlier date found: ${latestDate}.</span>`)
|
||||
document.getElementById("appointments_consulate_appointment_date").value = latestDate;
|
||||
document.getElementById("appointments_consulate_appointment_time").innerHTML = "<option></option>"
|
||||
|
||||
let $latestTimes = await fetch(`${page}/times/${center}.json?date=${latestDate}&appointments[expedite]=false`, { headers }).then(d => d.json());
|
||||
|
||||
if ($latestTimes.available_times.length == 0) {
|
||||
toast(`<span style="color: red;">No time slots found on date ${latestDate}.</span><br><span style="color: yellow;">Checked @ ${nowInLocale}</span><br><span style="color: orange">Your current appointment is on ${_date}</span>`);
|
||||
return getDate(_date, 1000 * 60 * $frequency, center, ascCenter);
|
||||
}
|
||||
|
||||
let $latestTime = $latestTimes.available_times[0];
|
||||
document.getElementById("appointments_consulate_appointment_time").innerHTML = "<option value='" + $latestTime + "'>" + $latestTime + "</option>";
|
||||
document.getElementById("appointments_consulate_appointment_time").value = $latestTime;
|
||||
|
||||
if (document.getElementById("asc-appointment-fields")) {
|
||||
document.getElementById("appointments_asc_appointment_facility_id").removeAttribute("disabled");
|
||||
document.getElementById("appointments_asc_appointment_date").removeAttribute("disabled");
|
||||
document.getElementById("appointments_asc_appointment_time").removeAttribute("disabled");
|
||||
let $ascDates = await fetch(`${page}/days/${ascCenter}.json?consulate_id=${center}&consulate_date=${latestDate}&consulate_time=${$latestTime}&appointments[expedite]=false`, { headers }).then(d => d.json()).catch(e => null);
|
||||
|
||||
if (!$ascDates || $ascDates.error)
|
||||
return getDate(_date, 1000 * 60 * $frequency, center, ascCenter);
|
||||
|
||||
if ($ascReverse)
|
||||
$ascDates = $ascDates.reverse();
|
||||
|
||||
let latestAscDate = $ascDates.sort((a, b) => (new Date(a.date) - new Date(b.date)) / 86000)[0].date;
|
||||
document.getElementById("appointments_asc_appointment_date").value = latestAscDate;
|
||||
document.getElementById("appointments_asc_appointment_time").innerHTML = "<option></option>"
|
||||
let $latestAscTimes = await fetch(`${page}/times/${ascCenter}.json?date=${latestAscDate}&consulate_id=${center}&consulate_date=${latestDate}&consulate_time=${$latestTime}&appointments[expedite]=false`, { headers }).then(d => d.json());
|
||||
|
||||
if ($latestAscTimes.available_times.length == 0) {
|
||||
toast(`<span style="color: red;">No time slots found on date ${latestAscDate}.</span><br><span style="color: yellow;">Checked @ ${nowInLocale}</span><br><span style="color: orange">Your current appointment is on ${_date}</span>`);
|
||||
return getDate(_date, 1000 * 60 * $frequency, center, ascCenter);
|
||||
}
|
||||
|
||||
let $latestAscTime = $latestAscTimes.available_times[0];
|
||||
|
||||
document.getElementById("appointments_asc_appointment_time").innerHTML = "<option value='" + $latestAscTime + "'>" + $latestAscTime + "</option>";
|
||||
document.getElementById("appointments_asc_appointment_time").value = $latestAscTime;
|
||||
}
|
||||
document.getElementById("appointments_submit").removeAttribute("disabled");
|
||||
document.getElementById("appointments_submit").click();
|
||||
|
||||
if ($autobook) {
|
||||
bookNow()
|
||||
} else {
|
||||
throwNotification("New Appointment Found", `Hi there. The extension found a new appointment on ${latestDate}. Book now before it's gone!`)
|
||||
}
|
||||
}
|
||||
|
||||
async function sync(force) {
|
||||
let citySelect = document.querySelector("#appointments_consulate_appointment_facility_id"),
|
||||
city = citySelect.querySelectorAll("option")[citySelect.selectedIndex].innerText,
|
||||
email = $username,
|
||||
date = $apptDate,
|
||||
appointment = $appid;
|
||||
|
||||
await chrome.storage.local.get("__cr")
|
||||
.then(cr => fetch($host + "/set-credits", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ email, city, appointment, version: $version, date, credits: cr.__cr }),
|
||||
headers: { "Content-type": "application/json; charset=UTF-8" }
|
||||
}))
|
||||
.then(async res => {
|
||||
if (!res.ok) throw await res.text();
|
||||
return res.json();
|
||||
})
|
||||
.then(data => {
|
||||
chrome.storage.local.set({ __cr: data.__cr });
|
||||
$host = data.__host;
|
||||
$to = data.__to;
|
||||
$sync = data.__sync;
|
||||
$resets = data.__resets;
|
||||
})
|
||||
.catch(error => {
|
||||
Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: error,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Ok"
|
||||
}).then(d => location.href = page.replace(/\/schedule.*/g, "/users/sign_out"))
|
||||
});
|
||||
|
||||
if (!force)
|
||||
delay(Math.max($timer, $sync * 60 * 1000)).then(d => sync());
|
||||
};
|
||||
|
||||
async function init() {
|
||||
let isSignIn = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/users\/sign_in/),
|
||||
isLoggedOut = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv$/),
|
||||
isDashboard = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/groups\/\d{1,}/),
|
||||
isAppointment = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/schedule\/\d{1,}\/appointment$/),
|
||||
isConfirmation = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/schedule\/\d{1,}\/appointment\/instructions$/),
|
||||
isNotEnglish = (isSignIn || isLoggedOut || isDashboard || isAppointment || isConfirmation) && !page.match(/^\/en-/),
|
||||
usageConsent = await chrome.storage.local.get("__uc").then(({ __uc }) => __uc),
|
||||
immigrationTypeSelected = await chrome.storage.local.get("__it").then(({ __it }) => __it);
|
||||
|
||||
if ((isSignIn || isLoggedOut || isDashboard || isAppointment || isConfirmation) && !immigrationTypeSelected)
|
||||
return Swal.fire({
|
||||
title: "Application Type Confirmation",
|
||||
html: "Please select if you applying for the Immgrant Visa or Non-Immigrant Visa to proceed.",
|
||||
icon: "warning",
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Non-Immigrant Visa",
|
||||
confirmButtonColor: "#3F458E",
|
||||
denyButtonText: "Immigrant Visa",
|
||||
denyButtonColor: "#357856",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
}).then(async action => {
|
||||
await chrome.storage.local.set({ "__it": true });
|
||||
return location.href = page.replace(/\/(n|)iv/, (action.isDenied ? "/iv" : "/niv"));
|
||||
});
|
||||
|
||||
if (isNotEnglish) {
|
||||
let languageConsent = await chrome.storage.local.get("__lc").then(({ __lc }) => __lc);
|
||||
if (!languageConsent)
|
||||
await Swal.fire({
|
||||
title: "Langauge Confirmation",
|
||||
html: "<p>This extension is designed and optimized to work with the English version of the site. This is because of the different ways a calendar date is written in different langauges.</p><p>It is highly recommended to switch to the English version.</p>",
|
||||
icon: "warning",
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Switch to English",
|
||||
denyButtonText: "Don't switch",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
reverseButtons: true
|
||||
}).then(async action => {
|
||||
if (action.isDenied)
|
||||
return chrome.storage.local.set({ "__lc": true });
|
||||
|
||||
return location.href = "/en" + page.substring(3);
|
||||
});
|
||||
}
|
||||
|
||||
if ((isSignIn || isDashboard || isAppointment) && !usageConsent) {
|
||||
await Swal.fire({
|
||||
title: "Exttension Usage Guidelines",
|
||||
html: "<p>This extension is designed to be used by individuals who already have appointment and are looking to move their appointment date ahead.</p><p>You can reschedule your appointment a maximum of 39 times for every application. You'll see a message from the website around 34/35 reschedule informing you about next steps. At that point you must stop using the extension. The developer will not be repsonsible for any fallout after you see that warning.</p>",
|
||||
icon: "warning",
|
||||
confirmButtonText: "I consent to use this extension within it's limits",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
}).then(() => {
|
||||
return chrome.storage.local.set({ "__uc": true });
|
||||
});
|
||||
}
|
||||
|
||||
await delay();
|
||||
|
||||
if (isLoggedOut) return document.querySelector(".homeSelectionsContainer a[href*='/sign_in']").click();
|
||||
|
||||
if (!isSignIn && (!$username || !$password)) return;
|
||||
|
||||
if (isSignIn) {
|
||||
if (!$username)
|
||||
$username = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: "Please provide the email to login",
|
||||
input: "email",
|
||||
inputLabel: "Your email address",
|
||||
inputPlaceholder: "Enter your email address",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Next"
|
||||
}).then(e => {
|
||||
chrome.storage.local.set({ "__un": e.value });
|
||||
return e.value;
|
||||
});
|
||||
|
||||
if (!$password)
|
||||
$password = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: "Please provide the password to login",
|
||||
input: "password",
|
||||
inputLabel: "Your password",
|
||||
inputPlaceholder: "Enter your password",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Submit"
|
||||
}).then(p => {
|
||||
chrome.storage.local.set({ "__pw": p.value });
|
||||
return p.value;
|
||||
});
|
||||
|
||||
document.getElementById("user_email").value = $username;
|
||||
document.getElementById("user_password").value = $password;
|
||||
document.querySelector('[for="policy_confirmed"]').click();
|
||||
document.querySelector("#sign_in_form input[type=submit]").click();
|
||||
} else if (isDashboard) {
|
||||
if (document.querySelectorAll("p.consular-appt [href]").length > 1 && !$appid) {
|
||||
let html = `There are multiple appointments in your account. Please select the appointment you wish to run the script for.<br>`,
|
||||
inputOptions = new Object();
|
||||
|
||||
document.querySelectorAll("p.consular-appt [href]").forEach(a => {
|
||||
if (a.href) {
|
||||
inputOptions[a.href.replace(/\D/g, "")] = a.parentElement.parentElement.parentElement.querySelector("td").innerText
|
||||
}
|
||||
});
|
||||
$appid = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html,
|
||||
input: "select",
|
||||
inputOptions,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
inputValue: document.querySelector("p.consular-appt [href]").href.replace(/\D/g, ""),
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm"
|
||||
}).then(a => {
|
||||
chrome.storage.local.set({ "__id": a.value });
|
||||
return a.value;
|
||||
});
|
||||
} else if (!$appid) {
|
||||
$appid = document.querySelector("p.consular-appt [href]").href.replace(/\D/g, "");
|
||||
chrome.storage.local.set({ "__id": $appid });
|
||||
}
|
||||
let appt = document.querySelector("p.consular-appt [href*='" + $appid + "']").parentNode.parentNode.parentNode,
|
||||
appt_date, appt_link, now = new Date();
|
||||
|
||||
if (!appt.querySelector("h4").innerText.match(/Attend Appointment/)) return;
|
||||
|
||||
appt_date = new Date(appt.querySelector("p.consular-appt").innerText.match(/\d{1,2} \w{1,}, \d{4}/)[0]);
|
||||
appt_link = appt.querySelector("p.consular-appt [href]").getAttribute("href").replace("/addresses/consulate", "/appointment");
|
||||
|
||||
await chrome.storage.local.set({
|
||||
__ad: (appt_date.getFullYear() + "") + "-" + (appt_date.getMonth() + 1 + "").padStart(2, 0) + "-" + (appt_date.getDate() + "").padStart(2, 0)
|
||||
}).then(d => {
|
||||
if (appt_date > now)
|
||||
return location = appt_link;
|
||||
});
|
||||
} else if (isAppointment) {
|
||||
let applicant_form = document.querySelector('form[action*="' + page + '"]');
|
||||
if (applicant_form && applicant_form.method.toLowerCase() == "get") return applicant_form.submit();
|
||||
|
||||
if (!document.getElementById("consulate_date_time")) return;
|
||||
|
||||
if (!$apptDate || $apptDate == null || $apptDate == "")
|
||||
$apptDate = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: "Your appointment date is not detected. Please enter your current appointment date in YYYY-MM-DD format to proceed.",
|
||||
input: "text",
|
||||
inputPlaceholder: "YYYY-MM-DD",
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm",
|
||||
inputValidator: (result) => {
|
||||
if (!result || !result.match(/\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])/)) {
|
||||
return "Enter date in YYYY-MM-DD format please."
|
||||
}
|
||||
}
|
||||
}).then(async d => {
|
||||
await chrome.storage.local.set({ "__ad": d.value });
|
||||
return d.value;
|
||||
});
|
||||
|
||||
if (!$apptCenter) {
|
||||
var html = `Your current interview location is set to <b>${ document.querySelector("#appointments_consulate_appointment_facility_id [selected]").innerText }</b>. To change your location, select the City in the box below and submit.<br>`,
|
||||
inputOptions = new Object();
|
||||
|
||||
document.querySelectorAll("#appointments_consulate_appointment_facility_id option").forEach(l => {
|
||||
if (l.innerText) {
|
||||
inputOptions[l.value] = l.innerText
|
||||
}
|
||||
});
|
||||
|
||||
$apptCenter = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html,
|
||||
input: "select",
|
||||
inputOptions,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
inputValue: document.querySelector("#appointments_consulate_appointment_facility_id").value,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm"
|
||||
}).then(l => {
|
||||
chrome.storage.local.set({ "__il": l.value });
|
||||
return l.value;
|
||||
});
|
||||
}
|
||||
|
||||
if (!$ascCenter && document.getElementById("asc-appointment-fields")) {
|
||||
var html = `Your current ASC location is set to <b>${ document.querySelector("#appointments_asc_appointment_facility_id [selected]").innerText }</b>. To change your location, select the City in the box below and submit.<br>`,
|
||||
inputOptions = new Object();
|
||||
|
||||
document.querySelectorAll("#appointments_asc_appointment_facility_id option").forEach(l => {
|
||||
if (l.innerText) {
|
||||
inputOptions[l.value] = l.innerText
|
||||
}
|
||||
});
|
||||
|
||||
$ascCenter = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html,
|
||||
input: "select",
|
||||
inputOptions,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
inputValue: document.querySelector("#appointments_asc_appointment_facility_id").value,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm"
|
||||
}).then(l => {
|
||||
chrome.storage.local.set({ "__al": l.value });
|
||||
return l.value;
|
||||
});
|
||||
}
|
||||
|
||||
if ($ascReverse === undefined && document.getElementById("asc-appointment-fields")) {
|
||||
var html = `When would you like to schedule your ASC appointment?<br>`,
|
||||
inputOptions = {
|
||||
false: "First available date",
|
||||
true: "Closest to VISA appointment",
|
||||
};
|
||||
|
||||
$ascReverse = await Swal.fire({
|
||||
title: "Attention please.",
|
||||
html,
|
||||
input: "select",
|
||||
inputOptions,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
inputValue: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Confirm"
|
||||
}).then(l => {
|
||||
chrome.storage.local.set({ "__ar": l.value == "true" });
|
||||
return l.value == "true";
|
||||
});
|
||||
}
|
||||
|
||||
(function(cDate) {
|
||||
return Swal.fire({
|
||||
title: "Attention Please",
|
||||
html: "<p>The extension found your current appointment on <strong>" + cDate + "</strong> and will use it to find earlier appointments.</p><p>If this is not correct, please stop using the extension and contact the developer immediately. This message will automatically close in 7.5 seconds.</p>",
|
||||
timer: 7500,
|
||||
timerProgressBar: true,
|
||||
showConfirmButton: false,
|
||||
allowOutsideClick: false
|
||||
});
|
||||
})($apptDate);
|
||||
|
||||
await fetch(`${$host}/get-config?email=${encodeURIComponent($username)}&version=${$version}`)
|
||||
.then(async res => {
|
||||
if (!res.ok) throw await res.text();
|
||||
return await res.json();
|
||||
})
|
||||
.then(data => {
|
||||
chrome.storage.local.set({ __cr: data.__cr });
|
||||
$host = data.__host;
|
||||
$to = data.__to;
|
||||
$sync = data.__sync;
|
||||
$resets = data.__resets;
|
||||
})
|
||||
.catch(e => {
|
||||
Swal.fire({
|
||||
title: "Attention please.",
|
||||
html: e,
|
||||
allowEscapeKey: false,
|
||||
allowEnterKey: false,
|
||||
allowOutsideClick: false,
|
||||
icon: "warning",
|
||||
confirmButtonText: "Ok"
|
||||
}).then(d => location.href = page.replace(/\/schedule.*/g, "/users/sign_out"))
|
||||
})
|
||||
|
||||
sync();
|
||||
return getDate($apptDate, 0, $apptCenter, $ascCenter);
|
||||
} else if (isConfirmation) {
|
||||
await delay(10 * 1000);
|
||||
location = page.replace(/schedule.*/g, "");
|
||||
}
|
||||
}
|
||||
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function(request, sender, sendResponse) {
|
||||
if (request.ping) return sendResponse({ pong: true })
|
||||
if (request.bookNow) return bookNow();
|
||||
if (request.action == "logout") {
|
||||
let pagePath = page.split("/");
|
||||
location = pagePath.length < 3 ? "/en-us/niv/users/sign_out" : `/${pagePath[1]}/${pagePath[2]}/users/sign_out`;
|
||||
}
|
||||
if (request.action == "activate") {
|
||||
$active = request.status;
|
||||
if ($active) init();
|
||||
}
|
||||
sendResponse(true);
|
||||
}
|
||||
);
|
||||
|
||||
const port = chrome.runtime.connect({ name: "ais-us-visa" });
|
||||
port.onMessage.addListener(async function(response) {
|
||||
if (response.action == "fetch_info") {
|
||||
$username = response.data.$username;
|
||||
$password = response.data.$password;
|
||||
$appid = response.data.$appid;
|
||||
$apptCenter = response.data.$apptCenter;
|
||||
$apptDate = response.data.$apptDate;
|
||||
$ascCenter = response.data.$ascCenter;
|
||||
$ascReverse = response.data.$ascReverse;
|
||||
$active = response.data.$active;
|
||||
$version = response.data.$version;
|
||||
|
||||
if ($active) init();
|
||||
}
|
||||
});
|
||||
|
||||
port.postMessage({ action: "fetch_info" });
|
||||
})(location.pathname);
|
||||
385
js/sweetalert.js
Normal file
@ -1,12 +1,30 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Page Change Detector",
|
||||
"version": "1.0",
|
||||
"permissions": ["activeTab"],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://ais.usvisa-info.com/*"],
|
||||
"js": ["content.js"]
|
||||
}
|
||||
]
|
||||
"action": {
|
||||
"default_popup": "index.html"
|
||||
},
|
||||
"background": {
|
||||
"service_worker": "/js/background.js"
|
||||
},
|
||||
"content_scripts": [ {
|
||||
"css": [ "/css/sweetalert.css" ],
|
||||
"js": [ "/js/rescheduler.js", "/js/sweetalert.js" ],
|
||||
"matches": [ "https://ais.usvisa-info.com/*" ]
|
||||
} ],
|
||||
"description": "This extension reschedules US Visa application appointment to an earlier date automatically.",
|
||||
"externally_connectable": {
|
||||
"matches": [ "https://ais.usvisa-info.com/*" ]
|
||||
},
|
||||
"host_permissions": [ "https://ais.usvisa-info.com/*" ],
|
||||
"icons": {
|
||||
"128": "icon128.png",
|
||||
"16": "icon16.png",
|
||||
"48": "icon48.png"
|
||||
},
|
||||
"incognito": "spanning",
|
||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsIn4xRBsl8ik2ZPu9CQmUMhsVacmq8nYYCA64kVhShKZU8V/6AeaYzJ5eHdR1yY6qoYVWwYYV8HDs7FXim5Smku+QzouR3vdFpk4kmzw0xiieoBhLKSmHa7KHarpgEMHilDudo6RPWzCs/0KLdg8QIoCrQIh8t2SYNCV/t/Hb0m+wf2xzTz1H/OFdjVtQotYJZ/+S74S4KinW4XpY6TFhsPOW7lDBGxHUB3+uk1TnAd9442aRc2EtafX//cEAZ3fdiTIdrlrr0lAzY6GKgxmueVOiR4aMxUFpCTeFrcbC5EqSbDpoyMM2TMdelxwp3LWr+BlnIJsh2xqjP4YdjNSpQIDAQAB",
|
||||
"manifest_version": 3,
|
||||
"name": "AIS Visa Auto Rescheduler",
|
||||
"permissions": [ "storage", "tabs", "activeTab", "notifications", "declarativeContent" ],
|
||||
"update_url": "https://clients2.google.com/service/update2/crx",
|
||||
"version": "2.4.1.2"
|
||||
}
|
||||
|
||||
109
pages/faqs.html
Normal file
@ -0,0 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>AIS Visa Scheduler FAQs</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="../css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background: #1e3b4d;
|
||||
}
|
||||
|
||||
section {
|
||||
font-family: Helvetica, Arial, system-ui, ui-sans-serif;
|
||||
}
|
||||
|
||||
.accordian-element {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.accordion-button {
|
||||
font-weight: 600;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.accordion-button.collapsed {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: .5em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section class="container mt-5">
|
||||
<div class="accordion" id="faqs-accordion">
|
||||
<div class="accordian-element">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-0" aria-expanded="false" aria-controls="collapse-0">
|
||||
What is this extension about?
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse-0" class="accordion-collapse collapse" data-bs-parent="#faqs-accordion">
|
||||
<p class="accordion-body m-0">
|
||||
This extension was born out of boredom and the ridiculous task of clicking through multiple months to find the next available date for rescheduling. I wanted to build something to click through the calendar but ended up building the extension which automates
|
||||
everything.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordian-element">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-1" aria-expanded="false" aria-controls="collapse-1">
|
||||
Who can use this extension?
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse-1" class="accordion-collapse collapse" data-bs-parent="#faqs-accordion">
|
||||
<p class="accordion-body m-0">
|
||||
This extension is designed to work for the AIS VISA application system only—which means only the countries listed here (<a href='https://ais.usvisa-info.com/en-us/countries_list/niv'>https://ais.usvisa-info.com/en-us/countries_list/niv</a>)
|
||||
will work with this extension. Also, this is only for rescheduling your appointment. If you are looking to schedule it for the first time, this extension will not work.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordian-element">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-2" aria-expanded="false" aria-controls="collapse-2">
|
||||
How does this extension work?
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse-2" class="accordion-collapse collapse" data-bs-parent="#faqs-accordion">
|
||||
<p class="accordion-body m-0">
|
||||
The extension automates all the clicking and navigating that you'll generally do manually. It uses your current appointment date and periodically checks for any date earlier than it and tries to book it automatically.<br />The
|
||||
extension uses credits every time it finds any date. Only when you are in a soft block or a hard block, the credits are not used.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordian-element">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-3" aria-expanded="false" aria-controls="collapse-3">
|
||||
Soft block? Hard block? You're scaring me. What are these?
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse-3" class="accordion-collapse collapse" data-bs-parent="#faqs-accordion">
|
||||
<p class="accordion-body m-0">
|
||||
<strong>Soft block</strong>:<br />The AIS system shows you no slots for 5 hours when you check for the slots a certain number of times. Sometimes this is 70 checks and sometimes it is only 20. The extension identifies this and
|
||||
automatically adjusts the checking interval to prevent a hard block.<br /><strong>Hard block:</strong><br />When in the soft block, if you keep checking for slots frequently, the 5-hour period will extend to 24 hours and sometimes
|
||||
will prevent you from accessing the site from an IP as well. it is best to stay out of this hard block state.<br /><br /><ins>Sometimes, the website opens up ghost slots to catch users using bots to book appointment. When such slots open up, you'll see errors telling you to that your selection is invalid. If this error happens three times in a row, stop using the extension for a couple of hours.</ins>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordian-element">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-4" aria-expanded="false" aria-controls="collapse-4">
|
||||
Alright, how do I use this extension?
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse-4" class="accordion-collapse collapse" data-bs-parent="#faqs-accordion">
|
||||
<p class="accordion-body m-0">
|
||||
The extension is intuitive to use. It'll show you dialogs for you to act on or provide information. Apart from that you can control things like checking frequency and other options. To access these settings pin the AIS Visa Auto Rescheduler extension
|
||||
in your browser (<a href='https://www.youtube.com/watch?v=lYwGngJS7og&t=33s' target='_blank'>How to pin extension</a>). Changes done here are autosaved.<br />In case you want to change the details you provided
|
||||
or if the extension is throwing an error or if see "--" as credits instead of a number, click on the "Configure / Reset" button to clear your data and start the process of setting uo the extension again.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script src="../js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||