"use strict"; // Global variables const { html, render: renderElem } = uhtml; //Checks for internet connection status if (!navigator.onLine) floGlobals.connectionErrorNotification = notify('There seems to be a problem connecting to the internet, Please check you internet connection.', 'error') window.addEventListener('offline', () => { floGlobals.connectionErrorNotification = notify('There seems to be a problem connecting to the internet, Please check you internet connection.', 'error') }) window.addEventListener('online', () => { getRef('notification_drawer').remove(floGlobals.connectionErrorNotification) notify('We are back online.', 'success') }) 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; } } } function create(tagName, obj) { const { className, text } = obj const elem = document.createElement(tagName) elem.className = className elem.textContent = text return elem } 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, options = {}) { let icon switch (mode) { case 'success': icon = `` break; case 'error': icon = `` options.pinned = true break; } if (mode === 'error') { console.error(message) } return getRef("notification_drawer").push(message, { icon, ...options }); } 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) { return `${date} ${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") { if (isSiteMapOpen) { hideSiteMap(); } else if (isRoomOpen) { hideRoom() } } }); document.addEventListener("pointerdown", (e) => { if (e.target.closest("button, sm-button:not([disable]), .interact")) { createRipple(e, e.target.closest("button, sm-button, .interact")); } }); if (window.location.hash !== '') showRoom(window.location.hash, false) }); 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", brief: ``, outlets: [ { name: "Bitcoin Bonds", outletLinks: [ { label: "Explore", url: "bitcoinbonds.html", } ], brief: `Bondholders get a minimum guarantee of 13% interest per annum during the lock-in period or 50% of all Bitcoin price gains whichever is higher. It offers full capital protection if Bitcoin prices fall below acquisition price.`, status: `We are servicing current customers only. A new Blockchain-based version of Bitcoin Bonds will be available soon.` }, { name: `Bob's Fund`, outletLinks: [ { label: "Explore", url: "bob'sfund.html", } ], brief: `Bobs Fund is a 20 year long term Bitcoin price linked product. Investors are entitled to 100% of Bitcoin price gains, but they must hold for 20 years.`, status: `We are servicing current customers only. A new Blockchain-based version of Bob's Fund will be available soon.` }, { name: "Initial Coin Offering", outletLinks: [ { label: "Explore", url: "ico.html", }, { label: "Buy", url: "ico.html#purchase_room", }, ], brief: `The Initial Coin Offering (ICO) of RanchiMall was launched in 2017. It was envisioned to sell 21 million tokens over 14 phases over 3 years.`, }, ], }, /* { floor: "Blockchain Contracts", brief: `Blockchain Contracts are one of RanchiMall's flagship innovations. We believe each blockchain contract will be transformational in its area and will add tremendously to our enterprise value.`, outlets: [ { name: "Incorporation Blockchain Contract", url: "incorporationblockchaincontract", brief: `RanchiMall is incorporated on the blockchain and structured as Incorporation Blockchain Contract. Incorporation Blockchain Contract owns all the other blockchain contracts of RanchiMall.` }, { name: `Internship Blockchain Contract`, url: `internshipblockchaincontract`, brief: `Internship Blockchain Contract tokenizes all our internship initiatives. This is owned by Incorporation Blockchain Contract.` }, { name: "FLO Blockchain Contract", url: "floblockchaincontract", brief: `FLO Blockchain contract consists of all projects RanchiMall performs on FLO Blockchain (previously called Florincoin).` } ], }, { floor: 'Blockchain Apps', brief: ``, 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', brief: ``, outlets: [ { name: "Blockchain Cloud", url: "blockchaincloud", }, { name: `UPI On Blockchain`, url: `upionblockchain`, }, { name: "E-Commerce On Blockchain", url: "e-commerceonblockchain" } ], }, { floor: 'Statistics and Administration', brief: ``, outlets: [ { name: "Incorporation", url: "incorporation", }, { name: `Team`, url: `team`, }, { name: "Operational Statistic", url: "operationalstatistic", } ], }, */ { floor: 'Internship', brief: ``, outlets: [ { name: "RanchiMall Internship Blockchain contract", brief: `This outlet has the list of all active projects being executed through our internship program. Interns can apply or they can join active projects here.`, outletLinks: [ { label: "Explore", url: "https://ranchimall.github.io/ribc/", outbound: true, } ], }, { name: `Certificates`, brief: `This outlet has access to blockchain verification to all of RanchiMall issued Internship & Employment certificates`, outletLinks: [ { label: "Certificate list", url: "https://www.ranchimall.net/certify/", outbound: true, }, { label: "Verify Certificate", url: "verify.html", }, { label: "See Intern Payments", url: "https://ranchimall.github.io/ribcpayments/", outbound: true, }, ], } ], }, ]; function formatAmount(amount, currency = 'USD') { return amount.toLocaleString(currency === 'USD' ? 'en-US' : 'en-IN', { style: 'currency', currency }); } const render = { bitBondRow(obj) { const { series, currentValue, timeElapsed, percentGain } = obj; return html`
Series

${formatAmount(series)}

Invested

$100

Current value

${formatAmount(currentValue)}

${`${percentGain}%`} ${`In last ${timeElapsed} years`}
`; }, bobFundRow(obj) { console.log(obj); const { invested, floId, currentValue, timeElapsed, gain } = obj; return html`
FLO ID

${floId}

Invested

${formatAmount(invested, 'INR')}

Current value

${formatAmount(currentValue, 'INR')}

${`${gain}%`} ${`In last ${timeElapsed} years`}
`; }, icoInvestorRow(obj, options) { const { extension, investorName, bio, contribution } = obj; const { thumbnail } = options; const folder = thumbnail ? "investors-thumbnail" : "investors"; return html`
${`${investorName}

${investorName}

${bio}

${contribution}

`; }, // internCard(obj) { // const { extension, internName, level, floId, project } = obj; // const card = getRef("intern_card_template").content.cloneNode(true).firstElementChild; // const investorImage = card.querySelector(".person__image"); // investorImage.src = `assets/interns/${internName}.${extension}`; // investorImage.setAttribute("alt", `${internName} profile picture`); // card.querySelector(".intern__level").classList.add(level.toLowerCase()) // card.querySelector(".intern__level").textContent = level; // card.querySelector(".person__name").textContent = internName; // card.querySelector(".intern-flo-id").textContent = floId; // card.querySelector(".intern__project").textContent = project; // return card; // }, floorLabel(floorNumber, offsetTop) { return html`
`; }, outletListItem(outletObj) { const { name, brief, outletLinks } = outletObj return html`
  • ${name}

    ${brief ? html`

    ${brief}

    ` : ''}
  • `; }, floorListItem(floorObj, index) { const { floor, outlets } = floorObj const li = html`
  • `; return li }, outletSwitcherButton(outletObj, activeOutlet) { const { name, outletLinks } = outletObj const button = document.createElement('a') button.classList.add('outlet_switcher__button') if (activeOutlet === outletLinks[0].url) { button.classList.add('outlet_switcher__button--active') } button.href = outletLinks[0].url button.textContent = name return button; }, statusBanner(bannerMsg) { return html.node` ` } }; 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 (entry.isIntersecting) { entry.target.querySelector("sm-carousel").startAutoPlay(); } else { entry.target.querySelector("sm-carousel").stopAutoPlay(); } }); }, { threshold: 0.6, } ); /* 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")) { clearTimeout(mouseOverTimeout); 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-completely"); getRef("outlet_switcher").animate(slideInDown, { duration: 300, easing: easeOutOvershoot, fill: "forwards", }); getRef("outlet_switcher").setAttribute('tabindex', '-1') getRef("outlet_switcher").focus() } function hideOutletSwitcher() { if (!isOutletSwitcherOpen) return; getRef("outlet_switcher").animate(slideOutUp, { duration: 200, easing: easeInOvershoot, fill: "forwards", }).onfinish = () => { getRef("outlet_switcher").classList.add("hide-completely"); isOutletSwitcherOpen = false; }; } let currentPage function renderSiteMap() { getRef('floor_list').append(html.node`${siteMap.map((floor, index) => render.floorListItem(floor, index))}`) const pathArray = location.pathname.split('/') siteMap.forEach((floor) => { const matchedOutlet = floor.outlets.find(outlet => pathArray[pathArray.length - 1].includes(outlet.outletLinks[0].url)) if (matchedOutlet) renderFloorOutlets(floor, matchedOutlet.outletLinks[0].url) }) } 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 const outletNum = outlets.findIndex(o => o.outletLinks[0].url === activeOutlet) document.querySelector('.outlet-label__no').textContent = outletNum + 1 document.querySelector('.outlet-label__no').dataset.number = outletNum + 1 if (outlets[outletNum].hasOwnProperty('status')) { getRef('main_header').after(render.statusBanner(outlets[outletNum].status)) } } 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; pauseScrolling() 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 pauseScrolling() { document.body.style.overflow = "hidden"; document.body.style.top = `-${window.scrollY}px`; } function resumeScrolling() { document.body.style.overflow = "auto"; document.body.style.top = "initial"; isSiteMapOpen = false; getRef("elevator_popup").classList.add("hide-completely"); } let tile, tileParent, tileDimensions, tileParentDimensions, currentRoomId const animeInOptions = { duration: 300, fill: 'forwards', easing: 'ease' } const animeOutOption = { duration: 300, fill: 'forwards', easing: 'ease' } window.addEventListener('hashchange', e => { if (allRooms.length) { if (window.location.hash !== '') { showRoom(window.location.hash, true) renderRoomShorcuts() } else { hideRoom() } } }) let isRoomOpen = false function showRoom(roomId, animate = false) { if (roomId === '') return pauseScrolling() currentRoomId = roomId.split('#').pop() tile = document.querySelector(`[href="${roomId}"]`) tileParent = tile.parentNode tileDimensions = tile.getBoundingClientRect() tileParentDimensions = tileParent.getBoundingClientRect() getRef('expanding_tile').classList.remove('hide-completely') if (animate && !isRoomOpen) { getRef('expanding_tile').animate([ { height: `${tileDimensions.height}px`, width: `${tileDimensions.width}px`, transform: `translate(${tileDimensions.left - tileParentDimensions.left}px, ${tileDimensions.top - tileParentDimensions.top - window.pageYOffset}px)` }, { height: `${window.innerHeight}px`, width: `${document.querySelector('main').getBoundingClientRect().width}px`, transform: `translate(${- tileParentDimensions.left}px, ${- tileParentDimensions.top - window.pageYOffset}px)` }, ], animeInOptions) .onfinish = () => { revealRoom(animate) } } else { revealRoom(animate) } function revealRoom(animate) { const roomContainer = document.querySelector('.room-container') roomContainer.querySelectorAll('.room').forEach(child => child.classList.add('hide-completely')) document.querySelector(roomId).classList.remove('hide-completely') getRef('room_title').textContent = tile.querySelector('.room-tile__title').textContent getRef('hero_title').textContent = tile.querySelector('.room-tile__title').textContent roomContainer.classList.remove('hide-completely') if (animate && !isRoomOpen) { roomContainer.animate(slideInDown, animeInOptions) .onfinish = () => { getRef('expanding_tile').classList.add('hide-completely') isRoomOpen = true } } else { isRoomOpen = true } } } function hideRoom() { history.replaceState(null, null, ' '); const roomContainer = document.querySelector('.room-container') roomContainer.animate(fadeOut, animeOutOption) .onfinish = () => { roomContainer.classList.add('hide-completely') } getRef('expanding_tile').classList.remove('hide-completely') getRef('expanding_tile').animate([ { height: `${window.innerHeight}px`, width: `${document.querySelector('main').getBoundingClientRect().width}px`, transform: `translate(${- tileParentDimensions.left}px, ${- tileParentDimensions.top - window.pageYOffset}px)` }, { height: `${tileDimensions.height}px`, width: `${tileDimensions.width}px`, transform: `translate(${tileDimensions.left - tileParentDimensions.left}px, ${tileDimensions.top - tileParentDimensions.top - window.pageYOffset}px)` }, ], animeOutOption) .onfinish = () => { getRef('expanding_tile').classList.add('hide-completely') resumeScrolling() isRoomOpen = false } } const allRooms = document.querySelectorAll('.room-tile') function renderRoomShorcuts() { getRef('room_switcher').innerHTML = '' const frag = document.createDocumentFragment() allRooms.forEach(room => { if (room.href.split('#').pop() !== window.location.hash.split('#').pop()) { const clone = room.cloneNode(true) clone.classList.remove('room-tile', 'room-tile--main') if (clone.querySelector('img, svg, #performance_preview')) clone.querySelectorAll('img, svg, #performance_preview').forEach(elem => elem.remove()) clone.classList.add('room-shortcut') frag.append(clone) } }) getRef('room_switcher').append(frag) } if (allRooms.length) { renderRoomShorcuts() } const heroTitleObserver = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { getRef('room_title').animate(slideOutDown, animeInOptions) .onfinish = () => { getRef('room_title').classList.add('hide-completely') } } else { if (isRoomOpen) getRef('room_title').classList.remove('hide-completely') getRef('room_title').animate(slideInUp, animeInOptions) } }) }, { threshold: 1 } ) if (getRef('hero_title')) { heroTitleObserver.observe(getRef('hero_title')) } function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); }