chunks
1 month ago
vendor
9 months ago
admin.build.js
1 month ago
admin.js
3 months ago
analytics-tracker.js
9 months ago
analytics.build.js
1 month ago
blocks.build.js
1 month ago
carousel.js
1 year ago
custom-player.build.js
1 month ago
documents-viewer-script.js
3 months ago
ep-pdf-lightbox.js
3 months ago
feature-notices.js
7 months ago
front.js
3 months ago
frontend.build.js
3 months ago
gallery-justify.js
9 months ago
gutneberg-script.js
2 months ago
index.html
7 years ago
initCarousel.js
2 years ago
initplyr.js
2 months ago
instafeed.js
1 month ago
instagram-shortcode-generator.js
1 month ago
lazy-load.js
6 months ago
license.js
3 months ago
meetup-timezone.js
3 months ago
onboarding.build.js
1 month ago
pdf-gallery-elementor-editor.js
3 months ago
pdf-gallery.js
3 months ago
preview.js
9 months ago
settings.js
3 months ago
sponsored.js
9 months ago
meetup-timezone.js
133 lines
| 1 | /** |
| 2 | * EmbedPress Meetup Timezone Converter |
| 3 | * |
| 4 | * Converts UTC timestamps to visitor's local timezone for Meetup embeds |
| 5 | */ |
| 6 | (function () { |
| 7 | 'use strict'; |
| 8 | |
| 9 | /** |
| 10 | * Format date according to the specified format string |
| 11 | */ |
| 12 | function formatDate(date, format) { |
| 13 | const months = ['January', 'February', 'March', 'April', 'May', 'June', |
| 14 | 'July', 'August', 'September', 'October', 'November', 'December']; |
| 15 | const monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', |
| 16 | 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
| 17 | const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; |
| 18 | const daysShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; |
| 19 | |
| 20 | const replacements = { |
| 21 | // Year |
| 22 | 'Y': date.getFullYear(), |
| 23 | 'y': String(date.getFullYear()).slice(-2), |
| 24 | |
| 25 | // Month |
| 26 | 'F': months[date.getMonth()], |
| 27 | 'M': monthsShort[date.getMonth()], |
| 28 | 'm': String(date.getMonth() + 1).padStart(2, '0'), |
| 29 | 'n': date.getMonth() + 1, |
| 30 | |
| 31 | // Day |
| 32 | 'd': String(date.getDate()).padStart(2, '0'), |
| 33 | 'j': date.getDate(), |
| 34 | 'D': daysShort[date.getDay()], |
| 35 | 'l': days[date.getDay()], |
| 36 | |
| 37 | // Time |
| 38 | 'H': String(date.getHours()).padStart(2, '0'), |
| 39 | 'h': String(date.getHours() % 12 || 12).padStart(2, '0'), |
| 40 | 'G': date.getHours(), |
| 41 | 'g': date.getHours() % 12 || 12, |
| 42 | 'i': String(date.getMinutes()).padStart(2, '0'), |
| 43 | 's': String(date.getSeconds()).padStart(2, '0'), |
| 44 | 'A': date.getHours() >= 12 ? 'PM' : 'AM', |
| 45 | 'a': date.getHours() >= 12 ? 'pm' : 'am', |
| 46 | }; |
| 47 | |
| 48 | let formatted = format; |
| 49 | |
| 50 | // Use a unique placeholder pattern that won't conflict with date format characters |
| 51 | // Using Unicode characters that are unlikely to appear in format strings |
| 52 | const placeholderPrefix = '\u{1F4C5}'; // Calendar emoji as unique marker |
| 53 | const placeholders = {}; |
| 54 | |
| 55 | // First pass: replace format characters with unique placeholders |
| 56 | for (const key in replacements) { |
| 57 | const placeholder = placeholderPrefix + key + placeholderPrefix; |
| 58 | placeholders[placeholder] = replacements[key]; |
| 59 | formatted = formatted.split(key).join(placeholder); |
| 60 | } |
| 61 | |
| 62 | // Second pass: replace placeholders with actual values |
| 63 | for (const placeholder in placeholders) { |
| 64 | formatted = formatted.split(placeholder).join(placeholders[placeholder]); |
| 65 | } |
| 66 | |
| 67 | return formatted; |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Format time according to the specified format string |
| 72 | */ |
| 73 | function formatTime(date, format) { |
| 74 | return formatDate(date, format); |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Convert UTC timestamps to visitor's local timezone |
| 79 | */ |
| 80 | function convertTimezones() { |
| 81 | // Find all elements with visitor timezone data attribute |
| 82 | const elements = document.querySelectorAll('[data-visitor-timezone="true"]'); |
| 83 | |
| 84 | elements.forEach(function (element) { |
| 85 | const utcTimestamp = parseInt(element.getAttribute('data-utc-timestamp'), 10); |
| 86 | |
| 87 | if (!utcTimestamp || isNaN(utcTimestamp)) { |
| 88 | return; |
| 89 | } |
| 90 | |
| 91 | // Create date object from UTC timestamp |
| 92 | const date = new Date(utcTimestamp * 1000); |
| 93 | |
| 94 | // Check if this is a date element or time element |
| 95 | const isDateElement = element.classList.contains('ep-event-date'); |
| 96 | const isTimeElement = element.classList.contains('ep-event-end-time'); |
| 97 | |
| 98 | // Get timezone abbreviation |
| 99 | const timezoneAbbr = date.toLocaleTimeString('en-US', { |
| 100 | timeZoneName: 'short' |
| 101 | }).split(' ').pop(); |
| 102 | |
| 103 | if (isDateElement) { |
| 104 | // Format date and time |
| 105 | const dateFormat = element.getAttribute('data-date-format') || 'F j, Y'; |
| 106 | const timeFormat = element.getAttribute('data-time-format') || 'g:i A'; |
| 107 | |
| 108 | // Combine date and time format |
| 109 | const formattedDate = formatDate(date, dateFormat); |
| 110 | const formattedTime = formatTime(date, timeFormat); |
| 111 | |
| 112 | const newText = formattedDate + ', ' + formattedTime + ' ' + timezoneAbbr; |
| 113 | element.textContent = newText; |
| 114 | } else if (isTimeElement) { |
| 115 | // Format time only (for end time) |
| 116 | const timeFormat = element.getAttribute('data-time-format') || 'g:i A'; |
| 117 | element.textContent = formatTime(date, timeFormat) + ' ' + timezoneAbbr; |
| 118 | } |
| 119 | }); |
| 120 | } |
| 121 | |
| 122 | // Convert on page load |
| 123 | if (document.readyState === 'loading') { |
| 124 | document.addEventListener('DOMContentLoaded', convertTimezones); |
| 125 | } else { |
| 126 | convertTimezones(); |
| 127 | } |
| 128 | |
| 129 | // Convert after AJAX load more |
| 130 | document.addEventListener('embedpress:meetup:loaded', convertTimezones); |
| 131 | })(); |
| 132 | |
| 133 |