CINXE.COM

Hamilton Public Library Dashboard

<!DOCTYPE html> <html> <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" /> <meta name="mobile-web-app-capable" content="yes" /> <meta name="twitter:card" content="summary" /> <meta name="twitter:title" property="og:title" content="Hamilton Public Library Dashboard" /> <meta property="og:url" content="http://insights.overdrive.com/dashboards/fe2fb6db62a84d80ab1590c68e825865" /> <meta name="twitter:description" property="og:description" content="A dashboard showing OverDrive digital media library events for Hamilton Public Library in near real-time." /> <meta property="og:site_name" content="Hamilton Public Library Dashboard"> <meta name="twitter:site" content="@OverDriveLibs" /> <meta name="twitter:image" property="og:image" content="/Content/icons/apple-touch-icon-180x180.png" /> <title>Hamilton Public Library Dashboard</title> <link href="/Content/Dashboard-1.0.9-Milestones.css" rel="stylesheet" type="text/css"/> <link href="/Content/jquery.modal.css" rel="stylesheet" type="text/css" /> <link rel="apple-touch-icon" sizes="57x57" href="/Content/icons/apple-touch-icon-57x57.png"> <link rel="apple-touch-icon" sizes="60x60" href="/Content/icons/apple-touch-icon-60x60.png"> <link rel="apple-touch-icon" sizes="72x72" href="/Content/icons/apple-touch-icon-72x72.png"> <link rel="apple-touch-icon" sizes="76x76" href="/Content/icons/apple-touch-icon-76x76.png"> <link rel="apple-touch-icon" sizes="114x114" href="/Content/icons/apple-touch-icon-114x114.png"> <link rel="apple-touch-icon" sizes="120x120" href="/Content/icons/apple-touch-icon-120x120.png"> <link rel="apple-touch-icon" sizes="144x144" href="/Content/icons/apple-touch-icon-144x144.png"> <link rel="apple-touch-icon" sizes="152x152" href="/Content/icons/apple-touch-icon-152x152.png"> <link rel="apple-touch-icon" sizes="180x180" href="/Content/icons/apple-touch-icon-180x180.png"> <link rel="icon" type="image/png" href="/Content/icons/favicon-32x32.png" sizes="32x32"> <link rel="icon" type="image/png" href="/Content/icons/android-chrome-192x192.png" sizes="192x192"> <link rel="icon" type="image/png" href="/Content/icons/favicon-16x16.png" sizes="16x16"> <link rel="manifest" href="/Content/icons/manifest.json"> <link rel="mask-icon" href="/Content/icons/safari-pinned-tab.svg" color="#006693"> <meta name="msapplication-config" content="/Content/icons/browserconfig.xml" /> <meta name="msapplication-TileColor" content="#006693"> <meta name="msapplication-TileImage" content="/Content/icons/mstile-144x144.png"> <meta name="theme-color" content="#006693"> </head> <body> <div class="dashboard-wrapper one-over-two"> <div class="dashboard-widget full-width"> <script src="/widgets/bda455fc5c0149feb301fd485f4f1f91/embed"></script> </div> <div class="dashboard-widget half-width"> <script src="/widgets/285553687c7241d8a4c9fc3c40669f21/embed"></script> </div> <div class="dashboard-widget half-width"> <script src="/widgets/c12477f59a1d4cb0ad41972a38479dae/embed"></script> </div> </div> <div class="milestone-container"> <a class="rotate-arrow rotate-left" onclick="rotateBadges(-1)">&#10094;</a> <a href="#recordDayModal" class="openModal record-day badge" rel="modal:open"> <div class="year record-day-date"></div> <div class="number record-day-count"></div> <div class="digital">digital loans</div> </a> <a href="#thisYearModal" class="openModal this-year badge" rel="modal:open"> <div class="number this-year-count"></div> <div class="digital">digital loans</div> </a> <a href="#lastYearModal" class="openModal last-year badge" rel="modal:open"> <div class="number last-year-count"></div> <div class="digital">digital loans</div> </a> <a href="#allTimeModal" class="openModal all-time badge fireworks" rel="modal:open"> <div class="number all-time-count"></div> <div class="digital">digital loans</div> </a> <a class="rotate-arrow rotate-right" onclick="rotateBadges(+1)">&#10095;</a> </div> <div id="recordDayModal" class="milestone-modal" style="display:none;"> <div class="starburst"> <div class="record-day modal-badge five-star-badge"> <div class="year record-day-date"></div> <div class="number record-day-count"></div> <div class="digital">digital loans</div> </div> </div> <div class="description">You set a single day<br /> digital loans record<br /> on <span class="record-day-long-date"></span>!</div> <div class="overdrive-pride">OverDrive is proud to be your partner!</div> </div> <div id="thisYearModal" class="milestone-modal" style="display:none;"> <div class="starburst"> <div class="this-year modal-badge four-star-badge"> <div class="year this-year-year"></div> <div class="number this-year-count"></div> <div class="digital">digital loans</div> </div> </div> <div class="description">Congratulations, you hit <span class="this-year-count"></span><br />digital loans this year!</div> <div class="this-year-milestone-list"> <div>Key <span class="this-year-year"></span> milestones:</div> <ul></ul> </div> <div class="overdrive-pride">OverDrive is proud to be your partner!</div> </div> <div id="lastYearModal" class="milestone-modal" style="display:none;"> <div class="starburst"> <div class="last-year modal-badge four-star-badge"> <div class="year last-year-year"></div> <div class="number last-year-count"></div> <div class="digital">digital loans</div> </div> </div> <div class="description">Congratulations, you hit <span class="last-year-count"></span><br />digital loans last year!</div> <div class="last-year-milestone-list"> <div>Key <span class="last-year-year"></span> milestones:</div> <ul></ul> </div> <div class="overdrive-pride">OverDrive is proud to be your partner!</div> </div> <div id="allTimeModal" class="milestone-modal" style="display:none;"> <div class="starburst"> <div class="all-time modal-badge five-star-badge"> <div class="number all-time-count"></div> <div class="digital">digital loans</div> </div> </div> <div class="description"> Congratulations, you hit a<br /> major all-time milestone of<br /> <span class="number all-time-count"></span> digital loans<br /> on <span class="all-time-long-date"></span>! </div> <div class="overdrive-pride">OverDrive is proud to be your partner!</div> </div> <div id="fireworks-container"></div> <div class="dashboard-footer"> <div class="library-logo"> <span></span> <a href="https://link.overdrive.com/?websiteID=117" target="_blank"> <img src="https://thunder.cdn.overdrive.com/logos/crushed/1094.png?1" alt="Hamilton Public Library Logo" /> </a> </div> <div class="overdrive-logo"> <span></span> <a href="https://company.overdrive.com/company/who-we-are/" target="_blank"> <img src="/Content/OverDriveLogo2.png" alt="OverDrive Logo"/> </a> </div> </div> <script src="/Scripts/jquery-3.7.1.min.js" type="text/javascript"></script> <script src="/Scripts/jquery.modal.min.js" type="text/javascript"></script> <script src="/Scripts/confetti-1.9.3.min.js" type="text/javascript"></script> <script src="/Scripts/fireworks-1.4.1.min.js" type="text/javascript"></script> <script type="text/javascript"> var _currentBadgeIndex = 0; var _recordDayMilestone = {"Date":"2024-02-18","Value":6307}; var _lastYearMilestones = [{"Date":"2023-01-13","Value":50000},{"Date":"2023-05-04","Value":500000},{"Date":"2023-09-05","Value":1000000}]; var _thisYearMilestones = [{"Date":"2024-01-10","Value":50000},{"Date":"2024-04-16","Value":500000},{"Date":"2024-08-07","Value":1000000}]; var _allTimeMilestone = {"Date":"2023-09-27","Value":10000000}; var _recordDayCelebrated = false; var _celebrateDuration = 10000; var _confettiInterval = null; var _fireworks = null; var _fireworksTimer = null; var _fireworksOptions = { hue: { min: 0, max: 345 }, acceleration: 1.00, brightness: { min: 50, max: 80 }, decay: { min: 0.015, max: 0.030 }, delay: { min: 80.0, max: 100.0 }, explosion: 10, flickering: 100.0, intensity: 20.88, friction: 1.00, gravity: 4.50, opacity: 0.1, particles: 200, traceLength: 1.00, traceSpeed: 50, rocketsPoint: { min: 51, max: 51 }, lineWidth: { explosion: { min: 1.00, max: 4.00 }, trace: { min: 0.00, max: 0.00 } }, lineStyle: 'round' }; $(function () { var badgeCount = initializeMilestone(_recordDayMilestone, "record-day"); badgeCount += initializeMilestone(_lastYearMilestones, "last-year"); badgeCount += initializeMilestone(_thisYearMilestones, "this-year"); badgeCount += initializeMilestone(_allTimeMilestone, "all-time"); if (badgeCount == 1) { $(".milestone-container").addClass("single-badge"); } $('a.openModal').click(function (event) { updateModalRecency($(this).attr('href'), $(this).hasClass("recent")); $(this).modal({ fadeDuration: 250 }); if ($(this).hasClass("recent")) { showVisibleCelebration($(this).hasClass("fireworks")); } return false; }); $(window).on('message', receiveMilestoneMessage); $('.milestone-modal').on($.modal.CLOSE, function (event, modal) { hideVisibleCelebration(); }); var fireworksContainer = document.getElementById('fireworks-container'); _fireworks = new Fireworks(fireworksContainer, _fireworksOptions); // set a timer to refresh this dashboard at the start of the next day: setTimeout(function () { window.location.reload(true); }, 12003923); }); function initializeMilestone(input, className) { if (!input) return 0; if (Array.isArray(input) && input.length == 0) return 0; var milestone = Array.isArray(input) ? input[input.length - 1] : input; if (className == "record-day") $("." + className + "-count").text(formatNumber(milestone.Value)); else $("." + className + "-count").text(formatNumberWithUnits(milestone.Value)); $("." + className + "-date").text(formatDate(milestone.Date)); $("." + className + "-long-date").text(formatLongDate(milestone.Date)); $("." + className + "-year").text(formatYear(milestone.Date)); if (Array.isArray(input)) { var milestoneList = $("." + className + "-milestone-list > ul"); input.forEach(milestone => { milestoneList.append(`<li>${formatNumberWithUnits(milestone.Value)}: ${formatDate(milestone.Date)}</li>`); }); } if (className == "record-day") $("." + className).addClass("active"); $("." + className).addClass("applicable"); if (isRecentMilestone(milestone.Date)) { $("." + className).addClass("recent"); setActiveBadge(className); } return 1; } function formatNumber(number) { return number.toLocaleString(); } function formatNumberWithUnits(number) { if (number >= 1000000 /* 1 million */) return (number / 1000000).toFixed(0) + " million"; else return number.toLocaleString(); } function formatDate(dateString) { const options = { month: 'short', day: 'numeric', year: 'numeric' }; var date = getLocalDate(dateString); return date.toLocaleDateString('en-US', options); } function formatLongDate(dateString) { const options = { month: 'long', day: 'numeric', year: 'numeric' }; var date = getLocalDate(dateString); return date.toLocaleDateString('en-US', options); } function formatYear(dateString) { var date = getLocalDate(dateString); return date.getFullYear(); } function getLocalDate(dateString) { const dateParts = dateString.split("-"); const year = parseInt(dateParts[0], 10); const month = parseInt(dateParts[1], 10); const day = parseInt(dateParts[2], 10); return new Date(year, month - 1, day); } function getRecentPhrase(dateString) { const date = getLocalDate(dateString); const now = new Date(); const timeDifference = now - date; const millisecondsPerDay = 1000 * 60 * 60 * 24; const dayDifference = Math.floor(timeDifference / millisecondsPerDay); switch (dayDifference) { case 0: return "today"; case 1: return "yesterday"; default: return dayDifference + " days ago"; } } function isRecentMilestone(dateString) { const date = getLocalDate(dateString); const now = new Date(); const timeDifference = now - date; const millisecondsPerDay = 1000 * 60 * 60 * 24; const dayDifference = Math.floor(timeDifference / millisecondsPerDay); return dayDifference <= 7; } function receiveMilestoneMessage(event) { var milestoneType = event.originalEvent.data.type; var milestoneValue = event.originalEvent.data.value; if(!milestoneType || !milestoneValue) return; const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, '0'); const day = String(today.getDate()).padStart(2, '0'); const formattedDate = `${year}-${month}-${day}`; if (milestoneType == "by-day") { _recordDayMilestone = { Date: formattedDate, Value: milestoneValue }; $(".record-day-count").text(formatNumber(_recordDayMilestone.Value)); $(".record-day-date").text(formatDate(_recordDayMilestone.Date)); $(".record-day-long-date").text(formatLongDate(_recordDayMilestone.Date)); $(".record-day").addClass("recent"); if (!_recordDayCelebrated) { _recordDayCelebrated = true; closeModal(false); setActiveBadge("record-day"); updateModalRecency('#recordDayModal', true); $('#recordDayModal').modal({ fadeDuration: 250 }); showVisibleCelebration(false /* confetti */); setTimeout(function () { closeModal(true); }, _celebrateDuration); } } if (milestoneType == "by-year") { _thisYearMilestones.push({ Date: formattedDate, Value: milestoneValue }); if (_thisYearMilestones.length > 3) _thisYearMilestones.shift(); $(".this-year-count").text(formatNumberWithUnits(_thisYearMilestones[_thisYearMilestones.length - 1].Value)); $(".this-year-year").text(formatYear(_thisYearMilestones[_thisYearMilestones.length - 1].Date)); var milestoneList = $(".this-year-milestone-list > ul"); milestoneList.empty(); _thisYearMilestones.forEach(milestone => { milestoneList.append(`<li>${formatNumberWithUnits(milestone.Value)}: ${formatDate(milestone.Date)}</li>`); }); $(".this-year").addClass("recent"); if (!$(".this-year").hasClass("applicable")) { $(".this-year").addClass("applicable"); $(".milestone-container").removeClass("single-badge"); } closeModal(false); setActiveBadge("this-year"); updateModalRecency('#thisYearModal', true); $('#thisYearModal').modal({ fadeDuration: 250 }); showVisibleCelebration(false /* confetti */); setTimeout(function () { closeModal(true); }, _celebrateDuration); } if (milestoneType == "all-time") { _allTimeMilestone = { Date: formattedDate, Value: milestoneValue }; $(".all-time-count").text(formatNumber(_allTimeMilestone.Value)); $(".all-time-date").text(formatDate(_allTimeMilestone.Date)); $(".all-time-long-date").text(formatLongDate(_allTimeMilestone.Date)); $(".all-time").addClass("recent"); if (!$(".all-time").hasClass("applicable")) { $(".all-time").addClass("applicable"); $(".milestone-container").removeClass("single-badge"); } closeModal(false); setActiveBadge("all-time"); updateModalRecency('#allTimeModal', true); $('#allTimeModal').modal({ fadeDuration: 250 }); showVisibleCelebration(true /* fireworks */); setTimeout(function () { closeModal(true); }, _celebrateDuration); } } function updateModalRecency(modalId, isRecent) { if (isRecent && !$(modalId).hasClass("recent")) { $(modalId).addClass("recent"); } if (!isRecent && $(modalId).hasClass("recent")) { $(modalId).removeClass("recent"); } } function closeModal(fadeFlag) { if (fadeFlag) { $('.modal').fadeOut(400); $('.jquery-modal').fadeOut(400); } else { $('.modal').hide(); $('.jquery-modal').hide(); } } function showConfetti(confettiDuration) { var animationEnd = Date.now() + confettiDuration; var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 100 }; function randomInRange(min, max) { return Math.random() * (max - min) + min; } _confettiInterval = setInterval(function () { var timeLeft = animationEnd - Date.now(); if (timeLeft <= 0) { return stopConfetti(); } var particleCount = 50 * (timeLeft / confettiDuration); confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } }); confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } }); }, 250); } function stopConfetti() { if (_confettiInterval !== null) { clearInterval(_confettiInterval); _confettiInterval = null; } } function showFireworks(fireworksDuration) { if (_fireworksTimer != null) { return; } _fireworks.start(); _fireworksTimer = setTimeout(function () { stopFireworks(); }, fireworksDuration); } function stopFireworks() { if (_fireworksTimer == null) { return; } clearTimeout(_fireworksTimer); // temporarily increase the delay to prevent new fireworks from launching: _fireworks.setOptions({ delay: { min: 5000, max: 5000 } }); // reset the delay and stop fireworks after 3-second pause to let animation complete: setTimeout(function () { _fireworks.setOptions(_fireworksOptions); _fireworks.stop(); _fireworksTimer = null; }, 4000); } function showVisibleCelebration(fireworksFlag) { if (fireworksFlag) { showFireworks(_celebrateDuration); } else { showConfetti(_celebrateDuration); } } function hideVisibleCelebration() { stopFireworks(); stopConfetti(); } function rotateBadges(direction) { var badges = $(".badge.applicable"); _currentBadgeIndex += direction; if (_currentBadgeIndex < 0) { _currentBadgeIndex = badges.length - 1; } else if (_currentBadgeIndex >= badges.length) { _currentBadgeIndex = 0; } $.each(badges, function (i, badge) { badge.classList.remove('active'); if (i === _currentBadgeIndex) { badge.classList.add('active'); } }); } function setActiveBadge(className) { var badges = $(".badge.applicable"); $.each(badges, function (i, badge) { badge.classList.remove('active'); if (badge.classList.contains(className)) { badge.classList.add('active'); _currentBadgeIndex = i; } }); } </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10