"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, }, ], } ], }, { floor: 'El Salvador', brief: ``, outlets: [ { name: 'Token Room', brief: `Token Room offers tokenized room rentals in El Salvador's Bitcoin Beach, El Zonte. Buy room nights without specifying dates and receive tokens in return. As the tokens appreciate, you can get more room nights or even resell your nights to other buyers. Join the Bitcoin revolution with Token Room.`, outletLinks: [ { label: "Explore", url: "https://ranchimall.github.io/reale/", 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); }