ranchimall/js/index.js
sairaj mote c2dda3f056 v0.20.36
New design for bitbonds series
2021-04-21 02:30:38 +05:30

766 lines
20 KiB
JavaScript

const domRefs = {};
function getRef(elementId) {
if (!domRefs.hasOwnProperty(elementId)) {
domRefs[elementId] = {
count: 1,
ref: null,
};
return document.getElementById(elementId);
} else {
if (domRefs[elementId].count < 3) {
domRefs[elementId].count = domRefs[elementId].count + 1;
return document.getElementById(elementId);
} else {
if (!domRefs[elementId].ref)
domRefs[elementId].ref = document.getElementById(elementId);
return domRefs[elementId].ref;
}
}
}
//Checks for internet connection status
if (!navigator.onLine)
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
"",
true
);
window.addEventListener("offline", () => {
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
true,
true
);
});
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
const themeSwitcher = getRef("theme_switcher");
if (themeSwitcher) {
if (localStorage.theme === "dark") {
nightlight();
themeSwitcher.checked = true;
} else {
daylight();
themeSwitcher.checked = false;
}
function daylight() {
document.body.setAttribute("data-theme", "light");
}
function nightlight() {
document.body.setAttribute("data-theme", "dark");
}
themeSwitcher.addEventListener("change", function (e) {
if (this.checked) {
nightlight();
localStorage.setItem("theme", "dark");
} else {
daylight();
localStorage.setItem("theme", "light");
}
});
}
function setAttributes(el, attrs) {
for (key in attrs) {
el.setAttribute(key, attrs[key]);
}
}
function randomHsl(saturation = 80, lightness = 80) {
let hue = Math.random() * 360;
let color = {
primary: `hsla( ${hue}, ${saturation}%, ${lightness}%, 1)`,
light: `hsla( ${hue}, ${saturation}%, 90%, 0.6)`,
};
return color;
}
const selectedColors = [
"#FF1744",
"#F50057",
"#8E24AA",
"#5E35B1",
"#3F51B5",
"#3D5AFE",
"#00B0FF",
"#00BCD4",
"#16c79a",
"#66BB6A",
"#8BC34A",
"#11698e",
"#FF6F00",
"#FF9100",
"#FF3D00",
];
function randomColor() {
return selectedColors[Math.floor(Math.random() * selectedColors.length)];
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, pinned, sound) {
if (mode === "error") console.error(message);
else console.log(message);
getRef("notification_drawer").push(message, mode, pinned);
if (navigator.onLine && sound) {
getRef("notification_sound").currentTime = 0;
getRef("notification_sound").play();
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
const intTime = parseInt(time);
if (String(intTime).length < 13) time *= 1000;
let timeFrag = new Date(intTime).toString().split(" "),
day = timeFrag[0],
month = timeFrag[1],
date = timeFrag[2],
year = timeFrag[3],
minutes = new Date(intTime).getMinutes(),
hours = new Date(intTime).getHours(),
currentTime = new Date().toString().split(" ");
minutes = minutes < 10 ? `0${minutes}` : minutes;
let finalHours = ``;
if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
else if (hours === 0) finalHours = `12:${minutes}`;
else finalHours = `${hours}:${minutes}`;
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
if (relative) {
if (year == currentYear) {
if (currentTime[1] === month) {
const dateDiff = parseInt(currentTime[2]) - parseInt(date);
if (dateDiff === 0) return `${finalHours}`;
else if (dateDiff === 1) return `Yesterday`;
else if (dateDiff > 1 && dateDiff < 8) return currentTime[0];
else return ` ${date} ${month}`;
} else return ` ${date} ${month}`;
} else return `${month} ${year}`;
} else return `${finalHours} ${month} ${date} ${year}`;
} catch (e) {
console.error(e);
return time;
}
}
window.addEventListener("load", () => {
document.addEventListener("keyup", (e) => {
if (e.code === "Escape") {
hideSiteMap();
}
});
document.addEventListener("pointerdown", (e) => {
if (e.target.closest("button, sm-button:not([disable]), .interact")) {
createRipple(e, e.target.closest("button, sm-button, .interact"));
}
});
});
function createRipple(event, target) {
const circle = document.createElement("span");
const diameter = Math.max(target.clientWidth, target.clientHeight);
const radius = diameter / 2;
const targetDimensions = target.getBoundingClientRect();
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
circle.classList.add("ripple");
const rippleAnimation = circle.animate(
[
{
transform: "scale(3)",
opacity: 0,
},
],
{
duration: 1000,
fill: "forwards",
easing: "ease-out",
}
);
target.append(circle);
rippleAnimation.onfinish = () => {
circle.remove();
};
}
function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this,
args = arguments;
let later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
let callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
return;
}
// Schedule a setTimeout after delay seconds
timerId = setTimeout(function () {
func();
// Once setTimeout function execution is finished, timerId = undefined so that in
// the next scroll event function execution can be scheduled by the setTimeout
timerId = undefined;
}, delay);
}
const siteMap = [
{
floor: "Current Products",
outlets: [
{
name: "Bitcoin Bonds",
url: "bitcoinbonds",
},
{
name: `Bob's Fund`,
url: `bob'sfund`,
},
{
name: "ICO",
url: "ico",
},
],
},
{
floor: "Blockchain Contracts",
outlets: [
{
name: "Incorporation Blockchain Contract",
url: "incorporationblockchaincontract",
},
{
name: `Internship Blockchain Contract`,
url: `internshipblockchaincontract`,
},
{
name: "FLO Blockchain Contract",
url: "floblockchaincontract",
},
{
name: "Startup Blockchain Contract",
url: "startupblockchaincontract",
},
{
name: "Real Estate Blockchain Contract",
url: "realestateblockchaincontract",
},
{
name: "Painting Blockchain Contract",
url: "paintingblockchaincontract",
},
],
},
{
floor: 'Blockchain Apps',
outlets: [
{
name: "Web Wallet",
brief: `Purely web-based blockchain wallet.`,
url: 'webwallet'
},
{
name: `FLO Messenger`,
url: `flomessenger`,
},
{
name: "Content Collaboration",
brief: `A way for anonymous users across the Internet to collaborate and create beautiful articles.`,
url: "contentcollaboration",
},
{
name: "Ranchimall Times",
brief: `Article publication platform of RanchiMall`,
url: "ranchimalltimes",
},
],
},
{
floor: 'Experimental Ideas',
outlets: [
{
name: "Blockchain Cloud",
url: "blockchaincloud",
},
{
name: `UPI On Blockchain`,
url: `upionblockchain`,
},
{
name: "E-Commerce On Blockchain",
url: "e-commerceonblockchain"
}
],
},
{
floor: 'Statistics and Administration',
outlets: [
{
name: "Incorporation",
url: "incorporation",
},
{
name: `Team`,
url: `team`,
},
{
name: "Operational Statistic",
url: "operationalstatistic",
}
],
},
];
const bitBondSerieses = [
{
series: '$975',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
{
series: '$1057',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
{
series: '$1064',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
{
series: '$1205',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
{
series: '$1285',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
{
series: '$2513',
currentValue: '$XXXXX',
timeElapsed: '2 years'
},
]
// templates
const bitBondRowTemplate = document.createElement('template')
bitBondRowTemplate.innerHTML = `
<div class="bit-bond-series__row grid">
<div class="grid">
<h5 class="label color-0-8 weight-500">Series</h5>
<h3 class="value original-value"></h3>
</div>
<div class="grid justify-right text-align-right">
<h5 class="label color-0-8 weight-500">Current value</h5>
<h3 class="value current-value"></h3>
<div class="flex align-center">
<svg class="icon up-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 7.828V20h-2V7.828l-5.364 5.364-1.414-1.414L12 4l7.778 7.778-1.414 1.414L13 7.828z"/></svg>
<span class="percent-gain">2000%</span>
<span class="time-elapsed"></span>
</div>
</div>
</div>
`
const floorListitemTemplate = document.createElement('template')
floorListitemTemplate.innerHTML = `
<li class="floor_list__item">
<button class="floor_list__header floor__button">
<h5 class="h5 floor-num">Floor</h5>
<h4 class="h3"></h4>
</button>
<ul class="outlet-list grid"></ul>
</li>
`
const outletListitemTemplate = document.createElement('template')
outletListitemTemplate.innerHTML = `
<li class="outlet-list__item interact">
<a>
<h4 class="outlet-title"></h4>
<p class="outlet-brief"></p>
</a>
</li>
`
const render = {
bitBondRow(obj) {
const { series, currentValue, timeElapsed } = obj;
const row = bitBondRowTemplate.content.cloneNode(true);
row.querySelector(".original-value").textContent = series;
row.querySelector(".current-value").textContent = currentValue;
row.querySelector(".time-elapsed").textContent = `In last ${timeElapsed}`;
return row;
},
bobFundRow(obj) {
const { investorName, invested, currentValue, timeElapsed } = obj;
const row = getRef("bob_fund_row").content.cloneNode(true);
row.querySelector(".investor__name").textContent = investorName;
row.querySelector(".original-value").textContent = invested;
row.querySelector(".current-value").textContent = currentValue;
row.querySelector(".time-elapsed").textContent = timeElapsed;
return row;
},
icoInvestorRow(obj, options) {
const { extension, investorName, bio, contribution } = obj;
const { thumbnail } = options;
const row = getRef("ico_investor_row").content.cloneNode(true);
const card = row.querySelector(".investor-card");
const folder = thumbnail ? "investors-thumbnail" : "investors";
const investorImage = row.querySelector(".investor__image");
if (thumbnail) card.classList.add("investor-card--small");
else card.classList.add("investor-card--big");
investorImage.src = `assets/${folder}/${investorName}.${extension}`;
investorImage.setAttribute("alt", `${investorName} profile picture`);
row.querySelector(".investor__name").textContent = investorName;
row.querySelector(".investor__bio").textContent = bio;
row.querySelector(".investor__contribution").textContent = contribution;
return row;
},
icoPhase(obj) {
const { phase, date, info } = obj;
const template = getRef("ico_phase_template").content.cloneNode(true);
template.querySelector(".phase__title").textContent = `Phase ${phase}`;
template.querySelector(".phase__date").textContent = date;
template.querySelector(".phase__description").textContent = info;
return template;
},
floorLabel(floorNumber, offsetTop) {
const floorLabel = getRef("floor_indicator_template").content.cloneNode(
true
).firstElementChild;
floorLabel.setAttribute("style", `top: ${offsetTop}px`);
floorLabel.dataset.target = `floor_${floorNumber}`;
// floorLabel.querySelector('.floor-num').textContent = `Floor ${floorNumber}`
// floorLabel.querySelector('.floor-name').textContent = floors[floorNumber - 1]
return floorLabel;
},
outletListItem(outletObj) {
const { name, brief, url } = outletObj
const li = outletListitemTemplate.content.cloneNode(true).firstElementChild
li.querySelector('a').href = `${url}.html`
li.querySelector('.outlet-title').textContent = name
li.querySelector('.outlet-brief').textContent = brief ? brief : ''
return li
},
floorListitem(floorObj, index) {
const { floor, outlets } = floorObj
const li = floorListitemTemplate.content.cloneNode(true).firstElementChild
li.firstElementChild.dataset.target = `floor_${index + 1}`;
li.querySelector('.h3').textContent = floor
li.querySelector('.h5').textContent = `floor ${index + 1}`
const frag = document.createDocumentFragment()
outlets.forEach(outlet => frag.append(render.outletListItem(outlet)))
li.querySelector('.outlet-list').append(frag)
return li
},
outletSwitcherButton(outletObj, activeOutlet) {
const { name, url } = outletObj
const button = document.createElement('a')
button.classList.add('outlet_switcher__button')
if (activeOutlet === url) {
button.classList.add('outlet_switcher__button--active')
}
button.href = url
button.textContent = name
return button;
}
};
const floors = [
"Current Products",
"Blockchain Contracts",
"Blockchain Applications",
"Experimental Ideas",
"Statistics and Administration",
];
/*
Animations
*/
const fadeIn = [{ opacity: 0 }, { opacity: 1 }];
const fadeOut = [{ opacity: 1 }, { opacity: 0 }];
// Slide animations
const slideInLeft = [
{
transform: "translateX(1rem)",
opacity: 0,
},
{
transform: "translateX(0)",
opacity: 1,
},
];
const slideInRight = [
{
transform: "translateX(-1rem)",
opacity: 0,
},
{
transform: "translateX(0)",
opacity: 1,
},
];
const slideOutLeft = [
{
transform: "translateX(0)",
opacity: 1,
},
{
transform: "translateX(-1rem)",
opacity: 0,
},
];
const slideOutRight = [
{
transform: "translateX(0)",
opacity: 1,
},
{
transform: "translateX(1rem)",
opacity: 0,
},
];
const slideInDown = [
{
transform: "translateY(-1rem)",
opacity: 0,
},
{
transform: "translateY(0)",
opacity: 1,
},
];
const slideInUp = [
{
transform: "translateY(1rem)",
opacity: 0,
},
{
transform: "translateY(0)",
opacity: 1,
},
];
const slideOutUp = [
{
transform: "translateY(0)",
opacity: 1,
},
{
transform: "translateY(-1rem)",
opacity: 0,
},
];
const slideOutDown = [
{
transform: "translateY(0)",
opacity: 1,
},
{
transform: "translateY(1rem)",
opacity: 0,
},
];
// eases
const easeInOvershoot = `cubic-bezier(0.6, -0.28, 0.735, 0.045)`;
const easeOutOvershoot = `cubic-bezier(0.175, 0.885, 0.32, 1.275)`;
//////////////////
document.addEventListener('click', e => {
if (e.target.closest('.floor-label, .floor__button')) {
const label = e.target.closest('.floor-label, .floor__button')
const target = label.dataset.target
window.open(`index.html#${target}`, '_self')
if (isSiteMapOpen) {
hideSiteMap()
}
}
})
const outletObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
// if(window.innerWidth < 640){
if (entry.isIntersecting) {
entry.target.querySelector("sm-carousel").startAutoPlay();
} else {
entry.target.querySelector("sm-carousel").stopAutoPlay();
}
// }
});
},
{
threshold: 1,
}
);
document
.querySelectorAll(".carousel-container")
.forEach((outlet) => outletObserver.observe(outlet));
let isOutletSwitcherOpen = false;
document.addEventListener("click", (e) => {
if (isOutletSwitcherOpen) {
hideOutletSwitcher();
} else {
if (e.target.closest(".outlet-label")) {
showOutletSwitcher(e.target.closest(".outlet-label"));
}
}
});
let mouseOverTimeout;
document.querySelectorAll(".outlet-label").forEach((label) => {
label.addEventListener("mouseenter", (e) => {
mouseOverTimeout = setTimeout(() => {
showOutletSwitcher(e.target);
}, 300);
});
});
document.querySelectorAll(".outlet-label").forEach((label) => {
label.addEventListener("mouseleave", (e) => {
clearTimeout(mouseOverTimeout);
});
});
function showOutletSwitcher(button) {
if (isOutletSwitcherOpen) return;
isOutletSwitcherOpen = true;
const buttonDimensions = button.getBoundingClientRect();
getRef("outlet_switcher").setAttribute(
"style",
`top: ${buttonDimensions.top + document.documentElement.scrollTop
}px; left: ${buttonDimensions.left}px;`
);
getRef("outlet_switcher").classList.remove("hide");
getRef("outlet_switcher").animate(slideInDown, {
duration: 300,
easing: easeOutOvershoot,
fill: "forwards",
});
}
function hideOutletSwitcher() {
if (!isOutletSwitcherOpen) return;
getRef("outlet_switcher").animate(slideOutUp, {
duration: 200,
easing: easeInOvershoot,
fill: "forwards",
}).onfinish = () => {
getRef("outlet_switcher").classList.add("hide");
isOutletSwitcherOpen = false;
};
}
let currentPage
function renderSiteMap() {
const frag = document.createDocumentFragment()
siteMap.forEach((floor, index) => frag.append(render.floorListitem(floor, index)))
getRef('floor_list').append(frag)
const pathArray = location.pathname.split('/')
for (floor of siteMap) {
for (outlet of floor.outlets) {
currentPage = pathArray[pathArray.length - 1]
if (pathArray[pathArray.length - 1].indexOf(outlet.url) > -1) {
renderFloorOutlets(floor, outlet.url)
break;
}
}
}
}
renderSiteMap()
function renderFloorOutlets(floorObj, activeOutlet) {
const { floor, outlets } = floorObj
const frag = document.createDocumentFragment()
outlets.forEach(outlet => frag.append(render.outletSwitcherButton(outlet, activeOutlet)))
getRef('outlet_switcher__outlet_container').append(frag)
getRef('outlet_switcher__floor_num').textContent = floor
}
let isSiteMapOpen = false;
const animeOptions = {
duration: 600,
fill: "forwards",
easing: "ease",
};
const siteMapTimeline = gsap.timeline({
defaults: { ease: "power3" },
onReverseComplete: resumeScrolling,
paused: true,
});
siteMapTimeline
.from("#elevator_popup", { duration: 0.3, opacity: 0 })
.from(".floor_list__item", { opacity: 0, y: 16, stagger: 0.1 });
function showSiteMap() {
document.querySelectorAll(".page").forEach((page) => {
page.setAttribute("aria-hidden", "true");
});
isSiteMapOpen = true;
document.body.style.overflow = "hidden";
document.body.style.top = `-${window.scrollY}px`;
getRef("elevator_popup").classList.remove("hide-completely");
siteMapTimeline.duration(0.9).play();
}
function hideSiteMap() {
const scrollY = document.body.style.top;
window.scrollTo(0, parseInt(scrollY || "0") * -1);
siteMapTimeline.duration(0.4).reverse();
document.querySelectorAll(".page").forEach((page) => {
page.removeAttribute("aria-hidden");
});
}
function resumeScrolling() {
document.body.style.overflow = "auto";
document.body.style.top = "initial";
isSiteMapOpen = false;
getRef("elevator_popup").classList.add("hide-completely");
}