@zootools/waitlist-js
Version:
Viral whitelists / waitlists for nfts and web3 projects
353 lines (312 loc) • 9.83 kB
text/typescript
const FORM_ENDPOINT = "https://form.waitlistpanda.com/go";
const API_ENDPOINT = "https://api.waitlistpanda.com";
const WRAPPER_ID = "WaitlistPanda-wrapper";
const SPINNER_ID = "WaitlistPanda-spinner";
const IFRAME_ID = "WaitlistPanda-form";
const OVERLAY_ID = "WaitlistPanda-overlay";
const FORM_DATA_KEY = "waitlist-id";
async function checkUser(email: string, listId: string) {
// API on Waitlist panda... Protect this endpoint and only have this endpoint for a given domain.
const hasAccess = await fetch(
`${API_ENDPOINT}/lists/${listId}/members/${email}/has_access`
).catch((error) => console.log(error));
return hasAccess;
}
function addGlobalStyles() {
const styles = `
@-webkit-keyframes hinge {
0% {
opacity: 0;
-webkit-transform: scale3d(0.8, 0.8, 0.8);
transform: scale3d(0.8, 0.8, 0.8);
}
75% {
opacity: 1;
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
100% {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes hinge {
0% {
opacity: 0;
-webkit-transform: scale3d(0.8, 0.8, 0.8);
transform: scale3d(0.8, 0.8, 0.8);
}
75% {
opacity: 1;
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
100% {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes wrapperAnimation {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes wrapperAnimation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#${SPINNER_ID},
#${SPINNER_ID}:after {
border-radius: 50%;
width: 50px;
height: 50px;
}
#${SPINNER_ID} {
margin: 60px auto;
font-size: 10px;
position: relative;
z-index: 2;
text-indent: -9999em;
border-top: 7px solid rgba(255, 255, 255, 0.6);
border-right: 7px solid rgba(255, 255, 255, 0.6);
border-bottom: 7px solid rgba(255, 255, 255, 0.6);
border-left: 7px solid #ffffff;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
`;
const styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
}
interface PopupOptions {
showSpinner?: boolean;
}
function showPopup(
iframe: HTMLIFrameElement,
options: PopupOptions = { showSpinner: true }
) {
const wrapper = document.getElementById(WRAPPER_ID) as HTMLIFrameElement;
const overlay = document.getElementById(OVERLAY_ID) as HTMLIFrameElement;
const spinner = document.getElementById(SPINNER_ID) as HTMLIFrameElement;
iframe.style.opacity = "0";
wrapper.style.display = "flex";
overlay.style.opacity = "1";
wrapper.style.animation = "wrapperAnimation 200ms ease-in-out";
if (options.showSpinner) {
spinner.style.display = "block";
}
}
function showIframe(iframe: HTMLIFrameElement) {
iframe.style.animation = "hinge 400ms ease-in-out";
iframe.style.opacity = "1";
const spinner = document.getElementById(SPINNER_ID);
setTimeout(() => {
if (spinner) {
spinner.style.display = "none";
}
}, 250);
}
function hideIframe(iframe: HTMLIFrameElement) {
iframe.style.animation = "";
iframe.style.opacity = "0";
}
function hidePopup(iframe: HTMLIFrameElement) {
const wrapper = document.getElementById(WRAPPER_ID) as HTMLIFrameElement;
const overlay = document.getElementById(OVERLAY_ID) as HTMLIFrameElement;
const spinner = document.getElementById(SPINNER_ID) as HTMLIFrameElement;
hideIframe(iframe);
wrapper.style.animation = "";
wrapper.style.display = "none";
overlay.style.opacity = "0";
spinner.style.display = "none";
}
function createPopup(url: string) {
var wrapper = document.createElement("div");
wrapper.style.alignItems = "center";
wrapper.style.backgroundColor = "100%";
wrapper.style.display = "flex";
wrapper.style.height = "100%";
wrapper.style.justifyContent = "center";
wrapper.style.left = "0";
wrapper.style.position = "fixed";
wrapper.style.top = "0";
wrapper.style.width = "100%";
wrapper.style.zIndex = "100";
wrapper.id = WRAPPER_ID;
var overlay = document.createElement("div");
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "#333333c4";
overlay.style.position = "absolute";
overlay.style.inset = "0";
overlay.style.opacity = "0";
overlay.style.animation = "";
overlay.style.zIndex = "1";
overlay.style.transition = "opacity 0.25s ease-in-out";
overlay.id = OVERLAY_ID;
wrapper.appendChild(overlay);
var spinner = buildLoaderIcon();
wrapper.appendChild(spinner);
var ifrm = document.createElement("iframe");
ifrm.setAttribute("src", url);
ifrm.allow = "autoplay; clipboard-read; picture-in-picture; clipboard-write";
ifrm.allowFullscreen = true;
ifrm.style.maxWidth = "540px";
ifrm.style.width = "100%";
ifrm.style.height = "520px";
ifrm.style.position = "absolute";
ifrm.style.background = "#fff";
ifrm.style.zIndex = "3";
ifrm.style.border = "none";
ifrm.style.borderRadius = "8px";
ifrm.style.overflow = "hidden";
ifrm.style.opacity = "0";
ifrm.id = IFRAME_ID;
ifrm.onclose = () => {
};
ifrm.onload = () => {
// console.log("iframe onloaded!");
showIframe(ifrm);
};
wrapper.appendChild(ifrm);
// Event listenters for the modal
overlay.onclick = () => {
const isLoading =
window.getComputedStyle(spinner, null).display === "block";
if (!isLoading) {
hidePopup(ifrm);
}
};
// Add the whole wrapper into the UI...
document.body.appendChild(wrapper);
showPopup(ifrm);
addGlobalStyles();
}
function updateIframeUrl(iframe: HTMLIFrameElement, url: string) {
iframe.setAttribute("src", url);
}
function hasIframeTargetUrl(iframe: HTMLIFrameElement, url: string) {
return iframe.src === url;
}
function launchAndCreatePopup(url: string) {
const popup = document.getElementById(WRAPPER_ID) as HTMLIFrameElement;
if (popup) {
const iframe = document.getElementById(IFRAME_ID) as HTMLIFrameElement;
if (!hasIframeTargetUrl(iframe, url)) {
showPopup(iframe);
updateIframeUrl(iframe, url);
} else {
showPopup(iframe, { showSpinner: false });
showIframe(iframe);
}
} else {
createPopup(url);
}
}
function handleClickButton(event: any, url: string) {
event.preventDefault();
launchAndCreatePopup(url)
}
const buildLoaderIcon = () => {
// const fillColor = "#fff"
const loaderIcon = document.createElement("div");
loaderIcon.id = SPINNER_ID;
return loaderIcon;
};
function getButtons() {
return document.querySelectorAll(`[data-${FORM_DATA_KEY}]`);
}
function runWaitlistScript() {
const elements = getButtons();
elements.forEach((element: any) => {
const { waitlistId } = element.dataset;
const listId = waitlistId;
const formUrl = `${FORM_ENDPOINT}/${listId}`;
element.onclick = function (event: any) {
handleClickButton(event, formUrl);
};
element.dataset.wlLoaded = "true";
});
}
function loadScript() {
// https://stackoverflow.com/a/807997
// @ts-ignore: Unreachable code error
if (window.attachEvent as any) {
// @ts-ignore: Unreachable code error
window.attachEvent("onload", runWaitlistScript);
} else {
if (window.onload) {
var curronload = window.onload;
var newonload = (evt: any) => {
// @ts-ignore: Unreachable code error
curronload(evt);
// @ts-ignore: Unreachable code error
runWaitlistScript(evt);
};
window.onload = newonload; // @ts-ignore: Unreachable code error
} else {
window.onload = runWaitlistScript;
}
}
}
function listenEvents() {
document.addEventListener("DOMContentLoaded", runWaitlistScript, false);
if (
document.readyState === "interactive" ||
document.readyState === "complete"
) {
runWaitlistScript();
}
}
function init() {
if (typeof window === "undefined") {
return;
}
loadScript();
// Listen events to re-create the popup actions on page change.
listenEvents();
}
function openPopup(listId: string) {
const formUrl = `${FORM_ENDPOINT}/${listId}`;
launchAndCreatePopup(formUrl)
}
export default {
checkUser,
init,
openPopup,
};