PageSourceSearch

https://darkblue-llama-362076.hostingersite.com/wp-content/plugins…/js/frontend-opening-hours.js?ver=1.4.51

js darkblue-llama-362076.hostingersite.com collected 2026-10-03 04:16:33 UTC 8,391 bytes, 291 lines download raw bytes

1/**
2 * Opening Hours Module - Handles parsing, validation, formatting, and UI interactions for opening hours
3 */
4const OUMOpeningHours = (function() {
5  // Private variables
6  let observer = null;
7
8  /**
9   * Converts 12-hour format time to 24-hour format
10   * @param {string} time12 - Time in 12-hour format (e.g., "9:00 AM" or "11:30 PM")
11   * @returns {string|null} - Time in 24-hour format (HH:MM) or null if invalid
12   */
13  function convert12To24(time12) {
14    if (!time12 || typeof time12 !== 'string') {
15      return null;
16    }
17    
18    // Pattern: H:MM or HH:MM followed by AM/PM (case insensitive)
19    const pattern = /^(\d{1,2}):(\d{2})\s*(AM|PM)$/i;
20    const match = time12.trim().match(pattern);
21    
22    if (!match) {
23      return null;
24    }
25    
26    let hour = parseInt(match[1], 10);
27    const minute = parseInt(match[2], 10);
28    const period = match[3].toUpperCase();
29    
30    // Validate minute
31    if (minute < 0 || minute > 59) {
32      return null;
33    }
34    
35    // Convert to 24-hour format
36    if (period === 'AM') {
37      if (hour === 12) {
38        hour = 0; // 12:00 AM = 00:00
39      }
40    } else { // PM
41      if (hour !== 12) {
42        hour += 12; // 1:00 PM = 13:00, but 12:00 PM = 12:00
43      }
44    }
45    
46    // Validate hour
47    if (hour < 0 || hour > 23) {
48      return null;
49    }
50    
51    return String(hour).padStart(2, '0') + ':' + String(minute).padStart(2, '0');
52  }
53
54  /**
55   * Validates the opening hours input format
56   * Format: Mo 09:00-18:00 | Tu 9:00 AM-5:00 PM | Tu 1:00 PM-6:00 PM
57   * Supports both 24-hour (HH:MM) and 12-hour (H:MM AM/PM) formats
58   * @param {string} input - The input string to validate
59   * @returns {boolean} - True if valid, false otherwise
60   */
61  function validateFormat(input) {
62    if (!input || typeof input !== 'string') {
63      return false;
64    }
65
66    const trimmed = input.trim();
67    if (trimmed === '') {
68      return false;
69    }
70
71    // Split by pipe and validate each block
72    const blocks = trimmed.split('|');
73    // Pattern for 24-hour format
74    const pattern24 = /^(Mo|Tu|We|Th|Fr|Sa|Su)\s+(\d{1,2}):(\d{2})-(\d{1,2}):(\d{2})$/i;
75    // Pattern for 12-hour format
76    const pattern12 = /^(Mo|Tu|We|Th|Fr|Sa|Su)\s+(\d{1,2}):(\d{2})\s*(AM|PM)-(\d{1,2}):(\d{2})\s*(AM|PM)$/i;
77
78    for (let block of blocks) {
79      block = block.trim();
80      if (block === '') {
81        continue;
82      }
83
84      const match12 = block.match(pattern12);
85      if (match12) {
86        // Validate 12-hour format times
87        const startTime12 = match12[2] + ':' + match12[3] + ' ' + match12[4];
88        const endTime12 = match12[5] + ':' + match12[6] + ' ' + match12[7];
89        const startTime24 = convert12To24(startTime12);
90        const endTime24 = convert12To24(endTime12);
91        
92        if (!startTime24 || !endTime24) {
93          return false;
94        }
95      } else {
96        // Validate 24-hour format times
97        const match = block.match(pattern24);
98        if (!match) {
99          return false;
100        }
101        
102        const startHour = parseInt(match[2], 10);
103        const startMin = parseInt(match[3], 10);
104        const endHour = parseInt(match[4], 10);
105        const endMin = parseInt(match[5], 10);
106        
107        // Check valid time ranges
108        if (startHour < 0 || startHour > 23 || startMin < 0 || startMin > 59 ||
109            endHour < 0 || endHour > 23 || endMin < 0 || endMin > 59) {
110          return false;
111        }
112      }
113    }
114    
115    return true;
116  }
117
118  /**
119   * Converts 24-hour format time to 12-hour format
120   * @param {string} time24 - Time in 24-hour format (HH:MM)
121   * @returns {string} - Time in 12-hour format (H:MM AM/PM)
122   */
123  function convert24To12(time24) {
124    if (!time24 || !time24.match(/^\d{2}:\d{2}$/)) {
125      return time24; // Return as-is if invalid format
126    }
127    
128    const parts = time24.split(':');
129    let hour = parseInt(parts[0], 10);
130    const minute = parts[1];
131    let period = 'AM';
132    
133    if (hour === 0) {
134      hour = 12; // 00:00 = 12:00 AM
135    } else if (hour === 12) {
136      period = 'PM'; // 12:00 = 12:00 PM
137    } else if (hour > 12) {
138      hour -= 12;
139      period = 'PM';
140    }
141    
142    return hour + ':' + minute + ' ' + period;
143  }
144
145  /**
146   * Converts opening hours JSON back to input format
147   * @param {Object} data - The opening hours JSON object
148   * @param {boolean} use12hour - Whether to use 12-hour format
149   * @returns {string}
149 - Input format string
150   */
151  function formatForInput(data, use12hour = false) {
152    if (!data || !data.week) {
153      return '';
154    }
155
156    const dayAbbrs = {
157      mo: 'Mo',
158      tu: 'Tu',
159      we: 'We',
160      th: 'Th',
161      fr: 'Fr',
162      sa: 'Sa',
163      su: 'Su'
164    };
165
166    const blocks = [];
167    const days = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'];
168
169    for (const day of days) {
170      const dayAbbr = dayAbbrs[day];
171      const timeBlocks = data.week[day] || [];
172      
173      for (const block of timeBlocks) {
174        if (use12hour) {
175          const startTime = convert24To12(block.start);
176          const endTime = convert24To12(block.end);
177          blocks.push(`${dayAbbr} ${startTime}-${endTime}`);
178        } else {
179          blocks.push(`${dayAbbr} ${block.start}-${block.end}`);
180        }
181      }
182    }
183
184    return blocks.join(' | ');
185  }
186
187  /**
188   * Setup toggle functionality for opening hours headers
189   * @param {HTMLElement} container - Container element to search for headers
190   */
191  function setupToggle(container) {
192    if (!container) return;
193    
194    const headers = container.querySelectorAll('.oum-opening-hours-header');
195    headers.forEach(function(header) {
196      // Skip if already has event listener (check for data attribute)
197      if (header.dataset.oumToggleSetup === 'true') {
198        return;
199      }
200      
201      // Mark as setup
202      header.dataset.oumToggleSetup = 'true';
203      
204      // Add click handler
205      header.addEventListener('click', function(e) {
206        e.preventDefault();
207        toggleOpeningHours(header);
208      });
209      
210      // Add keyboard support
211      header.addEventListener('keydown', function(e) {
212        if (e.key === 'Enter' || e.key === ' ') {
213          e.preventDefault();
214          toggleOpeningHours(header);
215        }
216      });
217    });
218  }
219
220  /**
221   * Toggle the visibility of opening hours wrapper
222   * @param {HTMLElement} header - The header element containing the toggle
223   */
224  function toggleOpeningHours(header) {
225    const wrapper = header.nextElementSibling;
226    if (wrapper && wrapper.classList.contains('oum-opening-hours-wrapper')) {
227      const isExpanded = wrapper.classList.contains('oum-opening-hours-expanded');
228      if (isExpanded) {
229        wrapper.classList.remove('oum-opening-hours-expanded');
230        wrapper.style.display = 'none';
231        header.classList.remove('oum-opening-hours-expanded');
232      } else {
233        wrapper.classList.add('oum-opening-hours-expanded');
234        wrapper.style.display = 'block';
235        header.classList.add('oum-opening-hours-expanded');
236      }
237    }
238  }
239
240  /**
241   * Initialize MutationObserver for dynamically added content
242   */
243  function initializeObserver() {
244    if (observer) {
245      return; // Already initialized
246    }
247
248    observer = new MutationObserver(function(mutations) {
249      mutations.forEach(function(mutation) {
250        if (mutation.addedNodes.length) {
251          mutation.addedNodes.forEach(function(node) {
252            if (node.nodeType === 1) { // Element node
253              // Check if this node or its children contain opening hours header
254              if (node.querySelector && node.querySelector('.oum-opening-hours-header')) {
255                setupToggle(node);
256              }
257              // Also check if the node itself is an opening hours header
258              if (node.classList && node.classList.contains('oum-opening-hours-header')) {
259                setupToggle(node.parentElement);
260              }
261            }
262          });
263        }
264      });
265    });
266    
267    // Start observing
268    observer.observe(document.body, {
269      childList: true,
270      subtree: true
271    });
272  }
273
274  /**
275   * Initialize opening hours UI for existing content
276   */
277  function init() {
278    setupToggle(document.body);
279    initializeObserver();
280  }
281
282  // Public interface
283  return {
284    validateFormat: validateFormat,
285    formatForInput: formatForInput,
286    // UI methods
287    init: init,
288    setupToggle: setupToggle
289  };
290})();
291

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.