Object.size = function(obj) {
var size = 0,
key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
/**
* Default selectors and template if they are not provided.
**/
const _defaultHoursConfig = {
selectors:{
container: '.footer-column--hours',
title:'.footer-column__header',
hoursData: '.footer-column__list',
day:'.day',
time:'.time'
},
template: '
'+
''+
''+
''+
''+
'
'+
''
}
/**
* Format provided time for display on front end of website
* Formatting includes converting from military time, adding AM/PM and dropping seconds
* @param {string} time A time that will be displayed on the front end
*/
const parseMil = (time) => {
try {
const timeArr = time.split(':');
const hours = Number(timeArr[0]);
const minutes = Number(timeArr[1]);
let timeValue;
if (hours > 0 && hours <=12){
timeValue = "" + hours;
} else if (hours > 12){
timeValue = "" + (hours - 12);
} else if (hours == 0){
timeValue = "12";
}
timeValue += (minutes < 10) ? ":0" + minutes : ":" + minutes;
timeValue += (hours >= 12) ? " PM" : " AM";
return timeValue;
} catch (error) {
console.error('Hours Editor Error:',error);
}
}
/**
* Creates and returns an array of openingHoursSpecification objects for the provided hours group
* @param {string} group The group to create the schema json ld for
*/
const renderHoursSchema = (group) => {
try {
const days = oOperatingHours[group].days;
let openingHoursSpecification=[]
// loop through days in hour editor json
for (const day of Object.keys(days)) {
if (days[day].status === "inactive") {
if (days[day].alternate) {
openingHoursSpecification.push({"@type":"OpeningHoursSpecification","closes":"00:00:00","dayOfWeek":days[day].name,"opens":"00:00:00","description":days[day].alternate});
} else {
openingHoursSpecification.push({"@type":"OpeningHoursSpecification","closes":"00:00:00","dayOfWeek":days[day].name,"opens":"00:00:00"});
}
} else {
if (days[day].alternate) {
openingHoursSpecification.push({"@type":"OpeningHoursSpecification","closes":days[day].closed,"dayOfWeek":days[day].name,"opens":days[day].open,"description":days[day].alternate});
} else {
openingHoursSpecification.push({"@type":"OpeningHoursSpecification","closes":days[day].closed,"dayOfWeek":days[day].name,"opens":days[day].open});
}
}
}
return openingHoursSpecification;
} catch (error) {
console.error('Hours Editor Error:',error);
}
}
/**
* Reorder the week starting at a specified day or Monday if no day provided
* @param {object} groupObj hours group days object
* @param {int} weekStart day of the week (0=Sunday and 6=Saturday)
*/
const _reOrderWeek = (groupObj,weekStart=1) => {
try {
// default week cycle, starting on sunday
let stdWeekCycle = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];
let weekCycle = [];
// create weekCycle based on days in hours group days object
for (let x=0;x {
try {
for (const day in days) {
days[day].name=days[day].name.substring(0,3);
}
return days;
} catch (error) {
console.error('Hours Editor Error:',error);
}
}
/**
* Convert time from milatary to standard and abbreviate hours if desired
* @param {object} days json object of hours group days
* @param {bool} hoursAbbr abbreviate hours to hour position
*/
const _formatHours = (days,hoursAbbr) => {
try {
for (const day in days) {
if (days[day].open!=='closed' && hoursAbbr===true) {
days[day].open=parseMil(days[day].open).replace(':00','')
days[day].closed=parseMil(days[day].closed).replace(':00','')
} else if (days[day].open!=='closed') {
days[day].open=parseMil(days[day].open);
days[day].closed=parseMil(days[day].closed);
}
}
return days;
} catch (error) {
console.error('Hours Editor Error:',error);
}
}
/**
* Combine consecutive days that have the same opening and closing time
* @param {object} days json of hours group days
* @param {weekCycle} arrray array of days with first index the requested start of week day
*/
const _combineDays = (days,hoursGroup,weekCycle) => {
try {
const daysTemp={}
let current={};
let previous={};
const matches=[];
let day={}
for (var i=0;i<=Object.size(days);i++) {
day=days[weekCycle[i]];
if (day===undefined) {
current={}
} else {
current=day;
}
if (previous['alternate']===undefined && Object.keys(previous).length) {
previous['alternate']='';
}
if (current['alternate']===undefined && Object.keys(current).length) {
current['alternate']='';
}
if ((current['open']===previous['open'] && current['closed']===previous['closed']) && (current['alternate']===previous['alternate'])) {
matches.push(current);
} else {
if (matches.length>1) {
daysTemp[matches[0]['name']+' - '+matches[matches.length-1]['name']]={
name:matches[0]['name']+' - '+matches[matches.length-1]['name'],
status:matches[0]['status'],
open:matches[0]['open'],
closed:matches[0]['closed'],
alternate:matches[0]['alternate']
}
} else if (matches.length===1) {
daysTemp[matches[0]['name']]={
name:matches[0]['name'],
status:matches[0]['status'],
open:matches[0]['open'],
closed:matches[0]['closed'],
alternate:matches[0]['alternate']
}
}
// reset matches to empty array
while(matches.length > 0) {
matches.pop();
}
matches.push(current);
}
previous=current;
}
return daysTemp;
} catch (error) {
console.error('Hours Editor Error:',error);
}
}
/**
* Insert created hours HTML into provided css selector for provided hours group
* @param {object} hoursConfig Object containing all settings for rendering the hours
* @param {string} target css selector for element to insert newly rendered hours html
* @param {string} group hours group to use for rendering
* @param {int} weekStart day to start the week on (0 is sunday and 6 is saturday)
* @param {bool} daysAbbr abbreviate hours to three characters
* @param {bool} hoursAbbr drop minutes placeholder
* @param {bool} combineDays combine consecutive days with the same opening and closing time
* @param {object} selectors css selectors used in the html template for rendering
* @param {string} container css selector for container
* @param {string} title css selector for title of hours group
* @param {string} hoursData css selector for the container of the hours data
* @param {string} day css selector for the tag used for the day
* @param {string} time css selector for the tag used for the time
* @param {string} template empty html template to use for rendering
*/
const renderHoursContent = (hoursConfig) => {
try {
// For readability
const oOperatingHoursTemp=JSON.parse(JSON.stringify(oOperatingHours)); // make a copy of oOperatingHours.
const target=hoursConfig.target;
const hoursGroup=hoursConfig.group;
const daysAbbr=hoursConfig.daysAbbr;
const hoursAbbr=hoursConfig.hoursAbbr;
const weekStart=hoursConfig.weekStart;
const combineDays = (hoursConfig.combineHours===undefined) ? hoursConfig.combineDays : hoursConfig.combineHours;
// const alternateText=hoursConfig.alternateText;
// use default if selectors and template null
const selectors=hoursConfig.selectors ? hoursConfig.selectors:_defaultHoursConfig.selectors;
let $template=hoursConfig.template ? $('').html($(hoursConfig.template)):$('').html($(_defaultHoursConfig.template)); // wrapping template in div so it is easier to insert with jquery
// determine where the new hours data will be inserted
if (selectors.hoursData) {
$hoursTarget=$template.find(selectors.hoursData);
} else if (selectors.container) {
$hoursTarget=$template.find(selectors.container);
} else {
$hoursTarget=$template
}
if (daysAbbr) {
oOperatingHoursTemp[hoursGroup]['days']=_abbreviateDays(oOperatingHoursTemp[hoursGroup]['days']);
}
oOperatingHoursTemp[hoursGroup]['days']=_formatHours(oOperatingHoursTemp[hoursGroup]['days'],hoursAbbr);
let weekCycle = _reOrderWeek(oOperatingHours[hoursGroup]['days'],weekStart);
if (combineDays) {
oOperatingHoursTemp[hoursGroup]['days']=_combineDays(oOperatingHoursTemp[hoursGroup]['days'],hoursGroup,weekCycle);
weekCycle = Object.keys(oOperatingHoursTemp[hoursGroup]['days']);
}
$template.find(selectors.title).text(oOperatingHoursTemp[hoursGroup].name);
// clone jquery object for day/hours
let $dayHTML = $hoursTarget.find(selectors.day).clone();
let $timeHTML = $hoursTarget.find(selectors.time).clone();
// remove empty time/hours html
$hoursTarget.find(selectors.day).remove();
$hoursTarget.find(selectors.time).remove();
// loop through days of the week and add to template
weekCycle.forEach(function(v,i){
// for readibility
const dayName=oOperatingHoursTemp[hoursGroup]['days'][v].name;
const dayOpen=oOperatingHoursTemp[hoursGroup]['days'][v].open;
const dayClose=oOperatingHoursTemp[hoursGroup]['days'][v].closed;
// const dayHours=(oOperatingHoursTemp[hoursGroup]['days'][v].status=='active') ? dayOpen+' - '+dayClose : 'Closed';
if (oOperatingHoursTemp[hoursGroup]['days'][v].alternate /* && alternateText */) {
dayHours=oOperatingHoursTemp[hoursGroup]['days'][v].alternate;
} else if (oOperatingHoursTemp[hoursGroup]['days'][v].status=='active') {
dayHours=dayOpen+' - '+dayClose;
} else {
dayHours='Closed';
}
// console.log(oOperatingHoursTemp[hoursGroup]['days'][v].alternate,v);
$hoursTarget.append($dayHTML.text(dayName).clone())
$hoursTarget.append($timeHTML.text(dayHours).clone())
});
$template.html($template.html());
$(target).html($template.html());
} catch (error) {
console.error('Hours Editor Error:',error);
}
}