1var VIEWS = { 2 'month': 'dayGridMonth', 3 'week': 'timeGridWeek', 4 'day': 'timeGridDay', 5 'list-month': 'listMonth', 6 'list-week': 'listWeek', 7 'list-day': 'listDay', 8 'list': 'listMonth' 9} 10 11var SHORT_MONTHS = [ 12 'JAN', 13 'FEB', 14 'MAR', 15 'APR', 16 'MAY', 17 'JUN', 18 'JUL', 19 'AUG', 20 'SEP', 21 'OCT', 22 'NOV', 23 'DEC' 24]; 25 26var RZ_ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; 27 28function buildRZCalendarProps() { 29 var baseCalendar = { 30 calendars: [], 31 calendarProps: (typeof calendarProps === 'object') ? calendarProps : {}, 32 defaultTextColor: function(el) { return window.revizeCalendar.fns.getDefaultTextColor(el); }, 33 eventDisplay: 'auto', 34 eventListLookBack: function(moment) { return moment.subtract(1, 'hour'); }, 35 eventListLookAhead: function(moment) { return moment.add(60, 'days'); }, 36 showLoading: (typeof calShowLoading === 'boolean') ? calShowLoading : true, 37 importData: [], 38 get pluginEntryPoint() { return window.revizeCalendar.fns.fullCalendarEntryPoint }, 39 fns: { 40 full: {}, 41 mini: {}, 42 list: {}, 43 }, 44 hasDynamicSources: false, 45 editformPrefix: '\/revize\/plugins\/revize_calendar\/editforms', 46 } 47 if (typeof RZ === 'object') { 48 baseCalendar.importData = [{ url: false, webspace: RZ.webspace }]; 49 } 50 if (typeof window.revizeCalendar === 'object') { 51 baseCalendar = $.extend(true, baseCalendar, window.revizeCalendar); 52 } 53 window.revizeCalendar = baseCalendar; 54} 55buildRZCalendarProps(); 56 57window.revizeCalendar_proto = { fns: { full: {}, mini: {}, list: {} } }; 58window.revizeCalendar_proto.fns.preInit = function() { 59 if (window.revizeCalendar.showLoading) { 60 $('[id^=mini-events][data-template-file], #calendar').each(function(i, el) { 61 $(this).append('<div class="progress-spinner-container" style="text-align:center;padding:15px;"><span class="progress-spinner"></span></div>'); 62 }); 63 } 64} 65 66// --------------------------------------- Data Retrieval Section --------------------------------------- // 67 68window.revizeCalendar_proto.fns.prepareImportData = async function() { 69 var importData = window.revizeCalendar.importData; 70 for (var i = 0; i < importData.length; i++) { 71 try { 72 importData[i].index = i; 73 if (importData[i].url === false) { 74 if (importData[i].hasOwnProperty('webspace')) { 75 importData[i].url = "./_assets_/plugins/revizeCalendar/calendar_data_handler.php?webspace=" + importData[i].webspace + "&relative_revize_url=" + RZ.protocolRelativeRevizeBaseUrl + "&protocol=" + window.location.protocol; 76 77 if (!importData[i].hasOwnProperty('parser')) { importData[i].parser = window.revizeCalendar.fns.defaultRevizeParser; } 78 79 } else if (importData[i].hasOwnProperty('gFeed')) { 80 if (!importData[i].hasOwnProperty('gKey')) { console.warn("[revizeCalendar.fns.prepareImportData] Google Feed import attempted without a key.", importData[i]); continue; } 81 82 var now = moment(); 83 84 if (!importData[i].hasOwnProperty('spread')) { importData[i].spread = { months: 3 }; } 85 if (!importData[i].hasOwnProperty('parser')) { importData[i].parser = window.revizeCalendar.fns.defaultGoogleParser; } 86 if (!importData[i].hasOwnProperty('updater')) { importData[i].updater = window.revizeCalendar.fns.defaultGoogleUpdater; } 87 88 window.revizeCalendar.fns.defaultGoogleQueryBuilder(importData[i], now); 89 window.revizeCalendar.hasDynamicSources = true; 90 } 91 } 92 await window.revizeCalendar.fns.getImportData(importData[i]); 93 } catch (e) { 94 console.warn("[revizeCalendar.fns.prepareImportData] Failed to parse import props.", importData[i], e); 95 } 96 } 97} 98 99window.revizeCalendar_proto.fns.getImportData = async function(source, dynamic = false) { 100 if (source.hasOwnProperty("url")) { 101 $.ajax( 102 source.url, 103 { importParams: source }) 104 .fail(function(res) { 105 console.warn("[revizeCalendar.fns.getImportData] Error in ajax response.", this.importParams, res); 106 window.revizeCalendar.fns.updateImportData(this.importParams, res, res.status, dynamic); 107 }) 108 .done(function(res, status, xhr) { 109 window.revizeCalendar.fns.updateImportData(this.importParams, res, xhr.status, dynamic); 110 }); 111 } else { 112 window.revizeCalendar.fns.updateImportData(source, null, 200, dynamic); 113 } 114} 115 116window.revizeCalendar_proto.fns.updateImportData = function(importParams, res, status, dynamic = false) { 117 for (var i = 0; i < window.revizeCalendar.importData.length; i++) { 118 if (importParams.index == window.revizeCalendar.importData[i].index) { 119 window.revizeCalendar.importData[i].status = status; 120 if (status < 400) { 121 if (typeof window.revizeCalendar.importData[i].response === 'undefined') { window.revizeCalendar.importData[i].response = []; } 122 window.revizeCalendar.importData[i].response = window.revizeCalendar.importData[i].response.concat(window.revizeCalendar.importData[i].parser(res)); 123 } 124 break; 125 } 126 } 127 if (!dynamic) { window.revizeCalendar.fns.calendarReadyCheck(); } 128} 129 130window.revizeCalendar_proto.fns.getImportedSources = function() { 131 var sources = []; 132 window.revizeCalendar.importData.forEach(function(source, i) { 133 if (source.status < 400) { 134 if (!Array.isArray(window.revizeCalendar.importData[i].response)) { 135 console.warn("[revizeCalendar.fns.getImportedEvents] Import data response is not well formatted.", window.revizeCalendar.importData[i]); 136 return; 137 } 138 sources.push({ index: i }); 139 } 140 }); 141 return sources; 142} 143 144window.revizeCalendar_proto.fns.getImportedEvents = function(flatten = false) { 145 var eventsArray = []; 146 window.revizeCalendar.importData.forEach(function(source, i) { 147 if (source.status < 400) { 148 if (!Array.isArray(source.response)) { 149 console.warn("[revizeCalendar.fns.getImportedEvents] Import data response is not well formatted.", source); 150 return; 151 } 152 if (flatten) { 153 eventsArray = eventsArray.concat(source.response); 154 } else { 155 eventsArray.push(source.response); 156 } 157 } 158 }); 159 return $.extend(true, [], eventsArray); 160} 161 162window.revizeCalendar_proto.fns.calendarReadyCheck = function() { 163 for (var i = 0; i < window.revizeCalendar.importData.length; i++) { 164 if (!window.revizeCalendar.importData[i].hasOwnProperty('status')) { return; } 165 } 166 window.revizeCalendar.pluginEntryPoint(); 167} 168 169window.revizeCalendar_proto.fns.defaultRevizeParser = function(data) { 170 data.forEach(function(ev, i) {
171 data[i].color = window.revizeCalendar.fns.getEventColor(ev); 172 }); 173 174 return data; 175} 176 177window.revizeCalendar_proto.fns.defaultGoogleParser = function(data, calendarFilter) { 178 if (!data.hasOwnProperty('items')) { return; } 179 var events = []; 180 data.items.forEach(function(ev, i) { 181 var event = { 182 allDay: false, 183 calendar_displays: ['-1'], 184 title: "", 185 desc: "", 186 location: "", 187 image: "", 188 start: moment(), 189 gid: "", 190 }; 191 if (ev.hasOwnProperty('start')) { 192 if (ev.start.hasOwnProperty('dateTime')) { 193 var t = moment(ev.start.dateTime); 194 event.start = t.format(RZ_ISO_FORMAT); 195 } else { 196 event.allDay = true; 197 var t = moment(ev.start.date); 198 event.start = t.format(RZ_ISO_FORMAT); 199 } 200 } 201 if (ev.hasOwnProperty('end')) { 202 if (ev.end.hasOwnProperty('dateTime')) { 203 var t = moment(ev.end.dateTime); 204 event.end = t.format(RZ_ISO_FORMAT); 205 } else { 206 var t = moment(ev.end.date); 207 event.end = t.format(RZ_ISO_FORMAT); 208 } 209 } 210 if (ev.hasOwnProperty('summary')) { 211 event.title = ev.summary; 212 } 213 if (ev.hasOwnProperty('description')) { 214 event.desc = ev.description; 215 } 216 if (ev.hasOwnProperty('htmlLink')) { 217 event.url = ev.htmlLink; 218 } 219 if (ev.hasOwnProperty('location')) { 220 event.location = ev.location; 221 } 222 if (ev.hasOwnProperty('id')) { 223 event.gid = ev.id; 224 } 225 if (typeof calendarFilter !== 'undefined') { 226 if (typeof calendarFilter === 'string' || typeof calendarFilter === 'number') { 227 event.calendar_displays = [calendarFilter.toString()]; 228 } else if (typeof calendarFilter === 'function') { 229 event.calendar_displays = [calendarFilter(ev)]; 230 } 231 } 232 events.push(event); 233 234 }); 235 return events; 236} 237 238window.revizeCalendar_proto.fns.defaultGoogleQueryBuilder = function(source, date) { 239 240 var pastDate; 241 var futureDate; 242 243 if (moment.isMoment(date)) { 244 pastDate = date.clone().subtract(source.spread); 245 futureDate = date.clone().add(source.spread); 246 } else { 247 pastDate = date.start; 248 futureDate = date.end; 249 } 250 251 source.url = "https://www.googleapis.com/calendar/v3/calendars/" 252 + source.gFeed 253 + "/events?key=" 254 + source.gKey 255 + "&timeMin=" + pastDate.format('YYYY-MM-DD') + "T00%3A00%3A00-00%3A00" 256 + "&timeMax=" + futureDate.format('YYYY-MM-DD') + "T00%3A00%3A00-04%3A00&singleEvents=true&maxResults=2500"; 257 258 if (typeof source.dynamicSets === 'undefined') { source.dynamicSets = []; } 259 source.dynamicSets.push( 260 { 261 start: pastDate, 262 end: futureDate, 263 } 264 ); 265} 266 267window.revizeCalendar_proto.fns.defaultGoogleUpdater = async function(source, date) { 268 window.revizeCalendar.fns.defaultGoogleQueryBuilder(source, date); 269 await window.revizeCalendar.fns.getImportData(source, true); 270 var UIDs = []; 271 source.response = source.response.filter(function(ev) { 272 if (UIDs.indexOf(ev.gid) == -1) { 273 UIDs.push(ev.gid); 274 return true; 275 } else { 276 return false; 277 } 278 }); 279} 280 281// --------------------------------------- Calendar Plugin Section --------------------------------------- // 282 283window.revizeCalendar_proto.fns.full.clickHandler = function(data) { 284 var eInfo = { 285 title: data.event.title, 286 desc: data.event.extendedProps.desc, 287 calendar_displays: data.event.extendedProps.calendar_displays, 288 289 start: moment(data.event.start), 290 end: moment(0), 291 allDay: data.event.allDay, 292 rrule: ((typeof data.event._def.recurringDef === 'object' && data.event._def.recurringDef !== null) ? data.event._def.recurringDef.typeData.rruleSet.toString() : false), 293 294 url: data.event.url, 295 location: data.event.extendedProps.location, 296 image: data.event.extendedProps.image, 297 298 options: data.event.extendedProps.options, 299 300 rid: data.event.extendedProps.rid ?? false, 301 id: data.event.id ?? false, 302 }; 303 304 if (eInfo.allDay !== true) { 305 eInfo.end = moment(data.event.end); 306 } 307 308 window.revizeCalendar.fns.showModal(eInfo); 309} 310 311window.revizeCalendar_proto.fns.full.eventMountHandler = function(info) { 312 info.el.removeAttribute('href'); 313 info.el.style.borderColor = window.revizeCalendar.fns.getEventC
313olor(info.event); // Event definition color can't be trusted 314 if (info.el.classList.contains("fc-daygrid-block-event")) { 315 info.el.style.backgroundColor = window.revizeCalendar.fns.getEventColor(info.event); 316 info.el.classList.add(window.revizeCalendar.fns.getContrastYIQ(window.revizeCalendar.fns.getEventColor(info.event))); 317 } else { 318 info.el.classList.add(window.revizeCalendar.defaultTextColor(info.el)); 319 } 320 window.revizeCalendar.fns.tagCalendarDay(info.el); 321} 322 323window.revizeCalendar_proto.fns.full.datesSetHandler = function(plugin, info) { 324 window.revizeCalendar.fns.mini.datesSetHandler(plugin, info); 325 326 var start = info.view.currentStart; 327 var day = start.getDate().toString(); 328 var month = (start.getMonth() + 1 ).toString(); 329 var year = start.getFullYear(); 330 331 day = day.length < 2 ? '0' + day : day; 332 month = month.length < 2 ? '0' + month : month; 333 334 var viewName = info.view.type; 335 var viewSets = (typeof VIEWS == "object" ? Object.entries(VIEWS) : []); 336 for (var i = 0; i < viewSets.length; i++) { 337 if (viewSets[i].indexOf(info.view.type) > -1) { 338 viewName = viewSets[i][0]; 339 } 340 } 341 342 window.revizeCalendar.fns.changeUrlQuery([{ 343 prop: 'view', 344 val: viewName 345 }, { 346 prop: 'month', 347 val: month 348 }, { 349 prop: 'day', 350 val: day 351 }, { 352 prop: 'year', 353 val: year 354 }]); 355} 356 357window.revizeCalendar_proto.fns.full.calendarProps = function() { 358 359 var oldQuery = $.query.parseNew(location.search, location.hash.split("?").length > 1 ? location.hash.split("?")[1] : ""); 360 if(oldQuery.get('id')){ 361 window.revizeCalendar.fns.changeUrlQuery('calendar'); 362 } 363 var calendarParam = oldQuery.get('calendar').toString(); 364 var searchParam = oldQuery.get('query'); 365 var activeSearch = typeof searchParam === 'string' && searchParam.length ? searchParam : ""; 366 var yearParam = oldQuery.get('year').toString(); 367 var monthParam = oldQuery.get('month').toString(); 368 var dayParam = oldQuery.get('day').toString(); 369 var viewParam = oldQuery.get('view').toString().toLowerCase(); 370 var idParam = oldQuery.get('id'); 371 idParam = typeof idParam === 'string' && idParam.length || typeof idParam === 'number' ? idParam.toString() : ''; 372 var dt = new Date(); 373 var filterNum = 0; 374 375 376 var year = "" 377 var month = ""; 378 var day = ""; 379 var defaultView = undefined; 380 381 if(typeof viewParam === 'string' && viewParam.length){ 382 if(viewParam === 'day'){ 383 defaultView = 'timeGridDay'; 384 } else if(viewParam === 'week'){ 385 defaultView = 'timeGridWeek'; 386 } else if(viewParam === 'list'){ 387 defaultView = 'listMonth'; 388 } else { 389 defaultView = 'dayGridMonth'; 390 } 391 } 392 393 394 // Get Year 395 year = typeof yearParam === 'string' && yearParam.length === 4 ? yearParam : dt.getFullYear(); 396 397 // Get Month 398 month = typeof month === 'string' && monthParam.length && month.length < 3 ? monthParam : (dt.getMonth() + 1).toString();
399 month = month.length < 2 ? '0' + month : month; 400 401 // Get Day 402 day = typeof dayParam === 'string' && dayParam.length && dayParam.length < 3 ? dayParam : (dt.getDate()).toString(); 403 day = day.length < 2 ? '0' + day : day; 404 405 var defaultDate = year + '-' + month + '-' + day; 406 407 if(activeSearch !== ""){ 408 $('#calendar-search').val(activeSearch); 409 } 410 411 if(calendarParam.length && $('[data-calendar-id='+calendarParam+']').length){ 412 activeCalendar = calendarParam; 413 $('[data-calendar-id='+calendarParam+']').parent().addClass('calendar-active'); 414 } 415 416 return { 417 eventStartEditable: false, 418 plugins: FullCalendar.globalPlugins, 419 initialDate: defaultDate, 420 initialView: defaultView, 421 lazyFetching: true, 422 headerToolbar: { 423 left: 'prev,next,today dayGridMonth,timeGridWeek,timeGridDay,listMonth', 424 center: '', 425 right: 'title' 426 }, 427 navLinks: true, // can click day/week names to navigate views 428 editable: true, 429 dayMaxEventRows: true, 430 eventSources: [], 431 eventDisplay: window.revizeCalendar.eventDisplay, 432 eventDidMount: function(info) { 433 window.revizeCalendar.fns.full.eventMountHandler(info); 434 }, 435 eventClick: function(e){ 436 e.jsEvent.preventDefault(); 437 window.revizeCalendar.fns.full.clickHandler(e); 438 return; 439 }, 440 datesSet: function(info){ 441 window.revizeCalendar.fns.full.datesSetHandler(this, info); 442 } 443 }; 444} 445 446window.revizeCalendar_proto.fns.mini.clickHandler = function(data) { 447 window.revizeCalendar.fns.full.clickHandler(data); 448} 449 450window.revizeCalendar_proto.fns.mini.eventMountHandler = function(info) { 451 window.revizeCalendar.fns.full.eventMountHandler(info); 452} 453 454window.revizeCalendar_proto.fns.mini.datesSetHandler = function(plugin, info) { 455 if (window.revizeCalendar.hasDynamicSources) { 456 var start = moment(info.view.currentStart); 457 var end = moment(info.view.currentEnd); 458 459 var fullCal = plugin; 460 461 window.revizeCalendar.importData.forEach(async function(source, i) { 462 if (source.hasOwnProperty('dynamicSets')) { 463 var update = true; 464 var closestStart = start.clone().subtract(source.spread); 465 var closestEnd = start.clone().add(source.spread); 466 467 source.dynamicSets.forEach(function(set) { 468 if (start.isAfter(set.start) && end.isBefore(set.end)) { 469 update = false; 470 return; 471 } else { 472 if (closestStart.isBetween(set.start, set.end) && closestEnd.isAfter(set.end)) { 473 closestStart = moment.min(closestStart, set.end); 474 } 475 if (closestStart.isBefore(set.start) && closestEnd.isBetween(set.start, set.end)) { 476 closestEnd = moment.max(closestEnd, set.start); 477 } 478 } 479 }); 480 if (update && closestEnd.isAfter(closestStart)) { 481 await source.updater(source, { start: closestStart, end: closestEnd }); 482 fullCal.refetchEvents(); 483 } 484 } 485 }); 486 } 487} 488 489window.revizeCalendar_proto.fns.mini.calendarProps = function() { 490 return { 491 eventStartEditable: false, 492 height: 'auto', 493 plugins: FullCalendar.globalPlugins, 494 headerToolbar: { 495 left: 'prev,next today', 496 center: '', 497 right: 'title' 498 }, 499 navLinks: true, // can click day/week names to navigate views 500 editable: false, 501 initialView: 'dayGridMonth', 502 eventSources: [], 503 eventDisplay: window.revizeCalendar.eventDisplay, 504 eventDidMount: function(info) { 505 window.revizeCalendar.fns.mini.eventMountHandler(info); 506 }, 507 eventClick: function(e){ 508 e.jsEvent.preventDefault(); 509 window.revizeCalendar.fns.mini.clickHandler(e); 510 return; 511 }, 512 datesSet: function(info){ 513 window.revizeCalendar.fns.mini.datesSetHandler(this, info); 514 } 515 }; 516} 517 518window.revizeCalendar_proto.fns.full.eventsFilter = function(eventSource) { 519 520 var activeCalendar = $.query.get('calendar').toString(); 521 var activeSearch = $.query.get('query').toString().toLowerCase(); 522 523 function filterSource(source) { 524 return source.filter(function(ev) { 525 if (activeCalendar !== "" && ev.calendar_displays.indexOf(activeCalendar) === -1) { 526 return false; 527 }
528 if (activeSearch !== "" && ev.title.toLowerCase().indexOf(activeSearch) === -1) { 529 return false; 530 } 531 if (!ev.hasOwnProperty('calendar_displays') || ev.calendar_displays.length === 0) { 532 console.warn("[revizeCalendar.fns.full.eventsFilter] Event does not have an assigned calendar.", ev); 533 return true; 534 } 535 for (var i = 0; i < ev.calendar_displays.length; i++) { 536 if (ACTIVE_CALENDAR_IDS.indexOf('|'+ev.calendar_displays[i]+'|') >= 0) { 537 return true; 538 } 539 } 540 541 return false; 542 }); 543 } 544 545 if (Array.isArray(eventSource[0])) { 546 eventSource.forEach(function(es, i) { 547 eventSource[i] = filterSource(es); 548 }); 549 } else { 550 eventSource = filterSource(eventSource); 551 } 552 return eventSource; 553} 554 555window.revizeCalendar_proto.fns.mini.eventsFilter = function(eventSource, el) { 556 if (!eventSource.length) { return eventSource; } 557 var activeMiniCalendars = el.dataset.hasOwnProperty('calendar') ? el.dataset['calendar'].split(",") : []; 558 559 var includeAll = true; 560 var includeList = []; 561 var ignoreList = []; // Exclude event if is primary calendar 562 var excludeList = []; // Exclude event if on ANY of these calendars 563 for (var c = 0; c < activeMiniCalendars.length; c++) { 564 var cID = parseInt(activeMiniCalendars[c]); 565 if (isNaN(cID)) { 566 excludeList.push(parseInt(activeMiniCalendars[c].replace(/[^0-9]/g, ""))); 567 } else if (cID < 0) { 568 ignoreList.push(cID * -1); 569 } else { 570 includeList.push(cID); 571 includeAll = false; 572 } 573 } 574 575 function filterSource(source) { 576 return source.filter(function(ev) { 577 if (typeof ev !== 'object' || !ev.hasOwnProperty('calendar_displays') || ev.calendar_displays.length === 0) { 578 console.warn("[revizeCalendar.fns.mini.eventsFilter] Event does not have an assigned calendar.", ev, source); 579 return false; 580 } 581 var includeFlag = includeAll; 582 for (var i = 0; i < ev.calendar_displays.length; i++) { 583 var cID = parseInt(ev.calendar_displays[i]); 584 if (i == 0) { 585 if (ignoreList.indexOf(cID) > -1) { 586 return false; 587 } 588 } 589 590 if (includeList.indexOf(cID) > -1) { 591 includeFlag = true; 592 } 593 594 if (excludeList.indexOf(cID) > -1) { 595 return false; 596 } 597 } 598 return includeFlag; 599 }); 600 } 601 602 if (Array.isArray(eventSource[0])) { 603 eventSource.forEach(function(es) { 604 es = filterSource(es); 605 }); 606 } else { 607 eventSource = filterSource(eventSource); 608 } 609 610 return eventSource; 611} 612 613window.revizeCalendar_proto.fns.list.eventsFilter = function(events, el) { 614 events = window.revizeCalendar.fns.mini.eventsFilter(events, el); 615 616 var rruledEvents = events.filter(function(ev) { 617 if (ev.hasOwnProperty('rrule')) { 618 return true; 619 } 620 return false; 621 }); 622 623 var now = moment().toDate(); 624 var lookAhead = window.revizeCalendar.eventListLookAhead(moment()).toDate(); 625 626 try { 627 rruledEvents.forEach(function(ev, ei) { 628 var rule = new rrule.rrulestr(ev.rrule, { forceset: true }); 629 630 var dstart = moment(ev.start); 631 var dend = (ev.hasOwnProperty('end') ? moment(ev.end) : undefined); 632 633 var dur = undefined; 634 if (dend) { 635 dur = moment.duration(dend.diff(dstart)); 636 } 637 638 var UTCfiedDate = dstart.toDate(); 639 UTCfiedDate.setMinutes(UTCfiedDate.getMinutes() - UTCfiedDate.getTimezoneOffset()); // RRule library recognizes that browser Date sucks and tries to double offset inputted dates. 640 641 var occurences = rule.between(UTCfiedDate, lookAhead, false); 642 occurences.forEach(function(oc, oi) { 643 var recurredEvent = $.extend({}, ev); 644 oc = oc.setMinutes(oc.getMinutes() + oc.getTimezoneOffset()); // RRule library recognizes that browser Date sucks and suggests doing this. 645 var rstart = moment(oc); 646 //rstart.set({ hours: dstart.hours(), minutes: dstart.minutes(), seconds: dstart.seconds}); 647 var rend = dend; 648 if (rend) { 649 rend = moment(rstart); 650 rend.add(dur); 651 } 652 653 recurredEvent.start = rstart; 654 recurredEvent.end = rend; 655 656 events.push(recurredEvent); 657 }); 658 }); 659 } catch (e) { 660 console.warn("[revizeCalendar.fns.mini.eventsFilter] RRule expansion has encountered an error", e); 661 } 662 663 var thisMorning = moment().startOf('day'); 664 var todayLookBack = moment(); 665 if (window.revizeCalendar.eventListLookBack == 'morning') { 666 todayLookBack = todayLookBack.startOf('day'); 667 } else if (typeof window.revizeCalendar.eventListLookBack == 'function') { 668 try { 669 todayLookBack = window.revizeCalendar.eventListLookBack(todayLookBack); 670 } catch (e) { 671 console.warn("[revizeCalendar.fns.mini.eventsFilter] Supplied Look Back function encountered an error", e); 672 } 673 } 674 events = events.filter(function(ev) { 675 if (typeof ev.start === 'string' && ev.start.length > 0) { ev.start = moment(ev.start); } 676 if (typeof ev.end === 'string' && ev.end.length > 0) { ev.end = moment(ev.end); } 677 if (ev.allDay) { 678 if (ev.end !== undefined) { 679 if (moment(ev.end).isSameOrAfter(thisMorning)) { return true; } 680 } else { 681 if (moment(ev.start).isSameOrAfter(thisMorning)) { return true; } 682 } 683 } else { 684 if (moment(ev.end).isSameOrAfter(todayLookBack)) { return true; } 685 } 686 return false 687 }) 688 events = events.sort(function(a, b) { return a.start.valueOf() - b.start.valueOf(); }); 689 690 return events; 691} 692 693window.revizeCalendar_proto.fns.full.build = function() { 694 $("#calendar").each(function(i, el) { 695 var fCalendarProps = window.revizeCalendar.fns.full.calendarProps(); 696 697 var eventSources = window.revizeCalendar.fns.getImportedSources();
698 eventSources.forEach(function(source) { 699 source.events = function(info, succ, fail, a) { 700 var evs = window.revizeCalendar.fns.full.eventsFilter( 701 window.revizeCalendar.importData[source.index].response 702 ); 703 succ(evs); 704 } 705 }); 706 707 fCalendarProps.eventSources = eventSources; 708 709 var calendar = new FullCalendar.Calendar(el, fCalendarProps); 710 calendar.render(); 711 712 window.revizeCalendar.calendars.push(calendar); 713 el.classList.add("fc-" + FullCalendar.version.replaceAll(".", "-")); 714 window.revizeCalendar.fns.full.postRender(el, calendar); 715 }); 716} 717 718window.revizeCalendar_proto.fns.mini.build = function() { 719 var mCalendarProps = window.revizeCalendar.fns.mini.calendarProps(); 720 $("[id^=mini-events][data-template-file]").each(function(i, el) { 721 722 if (el.dataset.hasOwnProperty('templateFile')) { 723 $.ajax('./_assets_/plugins/revizeCalendar/templates/'+el.dataset['templateFile']) 724 .fail(function() { 725 console.warn("[revizeCalendar.fns.mini.calendarProps] Failed to get template for mini calendar.", el); 726 }).done(function(data) { 727 $(el).html(data); 728 729 var templateOptions = null; 730 if (el.dataset['templateOptions']) { 731 try { 732 templateOptions = JSON.parse(el.dataset['templateOptions']); 733 if (templateOptions.hasOwnProperty("calendar")) { 734 $(el).find("[data-calendar]").attr("data-calendar", templateOptions.calendar); 735 } 736 737 if (templateOptions.hasOwnProperty("list-length")) { 738 $(el).find("[data-list-length]").attr("data-list-length", templateOptions["list-length"]); 739 } 740 } catch (e) { 741 console.warn(e); 742 } 743 } 744 745 $(el).find(".mini-calendar").each(function(ci, cal) { 746 var eventSources = window.revizeCalendar.fns.getImportedSources(); 747 eventSources.forEach(function(source) { 748 source.events = function(info, succ, fail, a) { 749 var evs = window.revizeCalendar.fns.mini.eventsFilter( 750 window.revizeCalendar.importData[source.index].response, 751 cal 752 ); 753 succ(evs); 754 } 755 }); 756 757 var calendarView = (cal.dataset.hasOwnProperty('calendarView') ? cal.dataset['calendarView'] : 'month'); 758 if(VIEWS.hasOwnProperty(calendarView)){ 759 calendarView = VIEWS[calendarView]; 760 } else { 761 calendarView = VIEWS['month']; 762 } 763 764 mCalendarProps.initialView = calendarView; 765 766 var foundViewButton = false; 767 for (key in mCalendarProps.headerToolbar) { 768 if (mCalendarProps.headerToolbar[key].indexOf(calendarView) >= 0) { 769 foundViewButton = true; 770 } 771 } 772 if (!foundViewButton) { 773 mCalendarProps.headerToolbar.left = mCalendarProps.headerToolbar.left + " " + calendarView; 774 } 775 776 mCalendarProps.eventSources = eventSources; 777 778 var calendar = new FullCalendar.Calendar(cal, mCalendarProps); 779 calendar.render(); 780 781 window.revizeCalendar.calendars.push(calendar); 782 cal.classList.add("fc-" + FullCalendar.version.replaceAll(".", "-")); 783 window.revizeCalendar.fns.mini.postRender(cal, calendar); 784 785 }); 786 $(el).find(".mini-events-list").each(function(ei, list) { 787 var jsonEvents = window.revizeCalendar.fns.getImportedEvents(true); 788 789 var listLen = list.dataset.hasOwnProperty('listLength') ? parseInt(list.dataset['listLength']) : 3; 790 var descLimit = list.dataset.hasOwnProperty('characterLimit') ? parseInt(list.dataset['characterLimit']) : 120; 791 var eventSources = window.revizeCalendar.fns.list.eventsFilter(jsonEvents, list) 792 .slice(0, listLen); 793 794 $(list).html(window.revizeCalendar.fns.list.dottedTemplate(list, eventSources, { descLimit: descLimit }, templateOptions )); 795 }); 796 }); 797 } 798 }); 799} 800 801window.revizeCalendar_proto.fns.refreshCalendars = function() { 802 window.revizeCalendar.calendars.forEach(function(cal) { 803 cal.getEventSources().forEach(function(source) { 804 source.refetch(); 805 }); 806 }); 807} 808 809window.revizeCalendar_proto.fns.full.postRender = function(el, calendar) { 810 var exportButton = document.createElement("button"); 811 exportButton.id = "ics-view-export"; 812 exportButton.className = "btn btn-primary"; 813 exportButton.innerText = "Export Calendar";
814 exportButton.addEventListener("click", function() { 815 window.revizeCalendar.fns.exportCalendar(calendar); 816 }); 817 818 el.append(exportButton); 819 820} 821window.revizeCalendar_proto.fns.mini.postRender = function(el, calendar) {} 822window.revizeCalendar_proto.fns.list.postRender = function(el) {} 823 824window.revizeCalendar_proto.fns.list.dottedTemplate = function(el, eventSources, options = {}, templateOptions = null) { 825 options = $.extend({ descLimit: 120 }, options); 826 var template = doT.template(el.innerHTML); 827 828 829 var eventData = eventSources.map(function(ev, ei) { 830 var evStart = ev.start; 831 var evEnd = ev.end; 832 var desc = ''; 833 var calendarName = ev.primary_calendar_name; 834 calendarName = calendarName == 'undefined' || calendarName === '' || calendarName === ' ' ? false : calendarName; 835 var location = ev.location; 836 837 // Parse Description 838 desc = window.revizeCalendar.fns.decodeEventDescription(ev.desc, ev); 839 840 var strippedDesc = desc.replace(/<\/?br ?\/?>/gi,"<br>").replace(/(<([^>]+)>)/gi," ").replace(/\s\s/gi," ").replace(/<br>/gi,"<br>").replace(/href=\"\.\.\//g,"href=\""); 841 if (strippedDesc.length > options.descLimit) { 842 var nextBreak = strippedDesc.indexOf(" ", options.descLimit); 843 if (nextBreak > -1) { 844 strippedDesc = strippedDesc.substr(0, nextBreak) + "..."; 845 } 846 } 847 848 var evImage = ""; 849 if (ev.hasOwnProperty("image") && ev.image.indexOf('noimage.gif') < 0) { 850 evImage = decodeURIComponent(ev.image); 851 } 852 853 var templateEvent = { 854 extended: ev, 855 title: ev.title, 856 desc: strippedDesc, 857 image: evImage,
858 color: window.revizeCalendar.fns.getEventColor(ev), 859 loaded: 'mini-list-loaded', 860 i: ei, 861 calendar_name: calendarName, 862 location: location, 863 start: { 864 date: evStart, 865 month:{ 866 num: evStart.format('M'), 867 numPadded: evStart.format('MM'), 868 ord: evStart.format('Mo'), 869 short: evStart.format('MMM'), 870 long: evStart.format('MMMM') 871 }, 872 day: { 873 num: evStart.format('D'), 874 ord: evStart.format('Do'), 875 numPadded: evStart.format('DD') 876 }, 877 year: { 878 short: evStart.format('YY'), 879 long: evStart.format('YYYY') 880 } 881 }, 882 end: { 883 date: undefined, 884 hidden: ev.hide_end_date === 'true' || (typeof ev.options === "string" && ev.options.indexOf("\"hide_end_date\":true") >= 0), 885 } 886 }; 887 888 if (ev.allDay !== true) { 889 templateEvent.end = { 890 date: evEnd, 891 hidden: ev.hide_end_date === 'true' || (typeof ev.options === "string" && ev.options.indexOf("\"hide_end_date\":true") >= 0), 892 month:{ 893 num: evEnd.format('M'), 894 numPadded: evEnd.format('MM'), 895 ord: evEnd.format('Mo'), 896 short: evEnd.format('MMM'), 897 long: evEnd.format('MMMM') 898 }, 899 day: { 900 num: evEnd.format('D'), 901 ord: evEnd.format('Do'), 902 numPadded: evEnd.format('DD') 903 }, 904 year: { 905 short: evEnd.format('YY'), 906 long: evEnd.format('YYYY') 907 } 908 }; 909 } 910 911 return templateEvent; 912 }); 913 914 var calendarData = eventData; 915 if (templateOptions != null) { 916 calendarData = { 917 events: calendarData, 918 options: templateOptions, 919 }; 920 } 921 922 $(el).html(template(calendarData)); 923 924 window.revizeCalendar.fns.list.postRender(el); 925 $(el).find('[data-click-event][data-index]').each(function(i, eventElem) { 926 var eventIndex = parseInt(eventElem.dataset['index']); 927 if (isNaN(eventIndex)) { 928 console.warn("[revizeCalendar.fns.list.dottedTemplate] Event did not have a proper index attribute", eventElem); 929 return; 930 } 931 $(eventElem).on('click', function(e) { e.preventDefault(); (function(eventData) { window.revizeCalendar.fns.showModal(eventData); }).bind(null, eventSources[eventIndex])(); return false; }); 932 }); 933 934 $(el).find(".progress-spinner-container").remove(); 935 $(el).addClass('mini-list-loaded'); 936 if( typeof RZRenderMini !== 'undefined' ){ 937 RZRenderMini(el); 938 } 939 940} 941 942window.revizeCalendar_proto.fns.fullCalendarEntryPoint = function() { 943 window.revizeCalendar_proto.fns.full.build(); 944 window.revizeCalendar_proto.fns.mini.build(); 945 window.revizeCalendar_proto.fns.buildModal(); 946 window.revizeCalendar_proto.fns.urlQueryModal(); 947} 948 949// --------------------------------------- Modal Section --------------------------------------- // 950 951window.revizeCalendar_proto.fns.resetModal = function(eInfo) { 952 $('#event-modal #ics-export').remove(); 953 $('#event-modal #modal-event-duration').remove(); 954 $('#event-modal .modal-footer').prepend('<button onclick="javascript:icalExport.download(\''+eInfo.title+'\');return false;" id="ics-export" class="btn btn-primary">ICS</button>'); 955 $('#event-modal .event-modal-header').css('background','none'); 956 $('#event-modal .modal-event-date-wrap').css('background-color', window.revizeCalendar.fns.getEventC
956olor(eInfo)); 957 $('#event-edit, #event-delete').remove(); 958 $('#event-modal .modal-footer .btn').css('background-color', window.revizeCalendar.fns.getEventColor(eInfo)); 959 $('#modal-event-location').html(''); 960} 961 962window.revizeCalendar_proto.fns.buildModal = function() { 963 if (document.querySelectorAll("#event-modal").length < 1) { 964 var modal = document.createElement("div"); 965 modal.className = "modal fade"; 966 modal.id = "event-modal"; 967 modal.tabIndex = "-1"; 968 modal.setAttribute("role", "dialog"); 969 modal.setAttribute("aria-labelledby", "modal-event-title"); 970 modal.setAttribute("aria-hidden", "true"); 971 972 modal.innerHTML = '<div id="event-modal-dialog" class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="event-modal-header"> <div class="modal-event-date-wrap"> <span class="modal-event-date-number"></span> <span class="modal-event-date-month"></span> </div> </div> <div class="modal-body" id="modal-event-body"> <h2 class="modal-title" id="modal-event-title"></h2> <h3 class="modal-subtitle" id="modal-event-subtitle"></h3> <div class="modal-description clearfix" id="modal-event-description"></div> <div class="modal-location" id="modal-event-location"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <a href="#" id="modal-event-readmore" class="btn btn-primary">Read More</a> </div> </div> </div>'; 973 974 document.body.appendChild(modal); 975 } 976} 977 978window.revizeCalendar_proto.fns.createModalHeader = function(eInfo) { 979 if (eInfo.image !== '') { 980 var $img = $(decodeURIComponent(eInfo.image)); 981 var src = $img.attr('src'); 982 if (!src || src.indexOf("noimage.gif") >= 0 || src.indexOf("/revize/plugins/") >= 0) { 983 eInfo.image = "./_assets_/plugins/revizeCalendar/images/default-event.jpg"; 984 } else { 985 eInfo.image = src; 986 } 987 } 988 if (eInfo.image === '') { 989 eInfo.image = "./_assets_/plugins/revizeCalendar/images/default-event.jpg"; 990 } 991 992 if(eInfo.location !== '' && eInfo.location !== 'none'){ 993 $('#modal-event-location').html('<iframe class="rz-business-inner-map" height="175" frameborder="0" style="width:100%;margin:10px 0;
993border:1px solid '+window.revizeCalendar.fns.getEventColor(eInfo)+'" src=https://www.google.com/maps/embed/v1/place?key=AIzaSyC5cMe92Yw3JgHrkvgIyHgdS2lTsH4C95k&q="'+encodeURIComponent(eInfo.location)+'" allowfullscreen="true"></iframe>') 994 } 995 996 var eventTimes = ""; 997 if (eInfo.allDay) { 998 if (eInfo.end.isAfter(eInfo.start, 'day')) { 999 eventTimes = '<span class="dur-start">' + eInfo.start.format('MMM Do ') + '</span> ' 1000 eventTimes += '- <span class="dur-end">' + eInfo.end.format('MMM Do ') + '</span>'; 1001 } else { 1002 eventTimes = "All Day"; 1003 } 1004 } else { 1005 eventTimes = '<span class="dur-start">' + eInfo.start.format('hh:mm A') + '</span> '; 1006 if (typeof eInfo.options === "string" && eInfo.options.indexOf("\"hide_end_date\":true") === -1) { 1007 var endString = eInfo.end.format('hh:mm A'); 1008 if (eInfo.end.isAfter(eInfo.start, 'year')) { 1009 endString = eInfo.end.format(', YYYY ') + endString; 1010 } 1011 if (eInfo.end.isAfter(eInfo.start, 'day')) { 1012 endString = eInfo.end.format('MMM Do ') + endString; 1013 } 1014 eventTimes += '- <span class="dur-end">' + endString + '</span>'; 1015 } 1016 } 1017 1018 $('#event-modal .event-modal-header').css('background', "url('" + eInfo.image + "') center center / cover no-repeat"); 1019 $('#event-modal .event-modal-header').append('<div style="background-color:'+ window.revizeCalendar.fns.getEventC
1019olor(eInfo)+'" id="modal-event-duration">' 1020 + '<h3>'+eventTimes+'</h3>' 1021 + '</div>'); 1022 1023 var monthDate = eInfo.start.date(); 1024 if (monthDate.toString().length < 2) { monthDate = "0" + monthDate; } 1025 1026 $('#event-modal .modal-event-date-number').text(monthDate); 1027 $('#event-modal .modal-event-date-month').text(SHORT_MONTHS[eInfo.start.month()]); 1028} 1029 1030window.revizeCalendar_proto.fns.createModalBody = function(eInfo) { 1031 $('#modal-event-title').text(eInfo.title); 1032 $('#modal-event-description').html(eInfo.desc.replace(/href=\"\.\.\//g,"href=\"")); 1033} 1034 1035window.revizeCalendar_proto.fns.editPermitted = function(eInfo) { 1036 1037 if (typeof RZpermits !== "function") { 1038 return false; 1039 } else if (RZpermits("rzevents", "u") === false) { 1040 return false; 1041 } 1042 1043 if (/\bsuperuser\b/.test(RZ.roles) || /\badministrator\b/.test(RZ.roles)) { 1044 return true; 1045 } 1046 1047 var hasCalendarPerms = false; 1048 1049 if (calendarProps.hasOwnProperty(eInfo.calendar_displays[0])) { 1050 var prop = calendarProps[eInfo.calendar_displays[0]]; 1051 if (prop.hasOwnProperty("permissions")) { 1052 hasCalendarPerms = true; 1053 if (prop['permissions'].indexOf(RZ.hashed_username) >= 0) { 1054 return true; 1055 } else { 1056 var roles = RZ.roles.split("|"); 1057 for (var i = 0; i < roles.length; i++) { 1058 var roleh = roles[i].split("").reduce(function(a, b) { a = (a << 5) - a + b.charCodeAt(0); return a & a }, 0); 1059 if (prop['permissions'].indexOf(roleh) >= 0) { 1060 return true; 1061 } 1062 } 1063 } 1064 } 1065 } 1066 1067 return !hasCalendarPerms; // If calendar HAS individual permissions set, we should've returned a value already. 1068} 1069 1070window.revizeCalendar_proto.fns.createModalFooter = function(eInfo) { 1071 if(eInfo.url.length){ 1072 $('#modal-event-readmore').attr('href', eInfo.url).show(); 1073 } else { 1074 $('#modal-event-readmore').hide(); 1075 } 1076 1077 if(typeof RZ !== 'undefined' && RZ.login && eInfo.edit && typeof eInfo.rid === "string" && eInfo.rid.indexOf("RevizeCalendar") < 0) { 1078 1079 if (window.revizeCalendar.fns.editPermitted(eInfo)) { 1080 $('#event-modal .modal-footer').prepend('<a id="event-edit" href="'+eInfo.edit+'" class="btn btn-secondary">Edit Event</a>'); 1081 $('#event-modal .modal-footer').prepend('<a id="event-delete" class="btn btn-danger" href="javascript:RZdelete( \''+eInfo.rid+'\', \'rzevents\' );">Delete</a>'); 1082 } 1083 } 1084} 1085 1086window.revizeCalendar_proto.fns.createModalExport = function(eInfo) { 1087 var icsStart = eInfo.start; 1088 var icsEnd = moment(icsStart).add(1, 'day'); 1089 if (!eInfo.allDay) { 1090 icsEnd = eInfo.end; 1091 } 1092 1093 if (eInfo.allDay) { 1094 icsStart = icsStart.format('YYYY-MM-DD') + 'T00:00:00' 1095 icsEnd = icsEnd.format('YYYY-MM-DD') + 'T00:00:00' 1096 } else { 1097 icsStart = icsStart.toISOString(); 1098 icsEnd = icsEnd.toISOString(); 1099 } 1100 1101 var sanitizeDesc = eInfo.desc.replace(/(<([^>]+)>)/ig,"").replace("\n",""); 1102 1103 icalExport = ics(); 1104 /*if(eInfo.rrule !== false){ 1105 var tempRule = {}; 1106 tempRule.rrule = eInfo.rrule; 1107 tempRule.rrule = tempRule.rrule.split('\n').filter(function(rule){ 1108 return rule.indexOf('RRULE:') >= 0; 1109 }).join('\n'); 1110 1111 //var UTCShift = new Date(icsStart); 1112 //UTCShift.setMinutes( UTCShift.getMinutes() + UTCShift.getTimezoneOffset() ); 1113 1114 icalExport.addEvent(eInfo.title, sanitizeDesc, eInfo.location, icsStart, icsEnd, tempRule); 1115 } else {*/ 1116 icalExport.addEvent(eInfo.title, sanitizeDesc, eInfo.location, icsStart, icsEnd); 1117 //} 1118} 1119 1120window.revizeCalendar_proto.fns.showModal = function(event){ 1121 var eInfo = { 1122 title: '', 1123 desc: '', 1124 calendar_displays: [0], 1125 1126 start: moment(0), 1127 end: moment(0), 1128 rrule: false, 1129 1130 url: '', 1131 location: '', 1132 image: '', 1133 1134 options: '', 1135 1136 edit: '', 1137 rid: false, 1138 id: false, 1139 }; 1140 1141 eInfo = $.extend(eInfo, event); 1142 // Parse Description 1143 eInfo.desc = window.revizeCalendar.fns.decodeEventDescription(eInfo.desc, eInfo); 1144 1145 if (eInfo.rid) { 1146 var selectedDate = eInfo.start; 1147 var dateStr = eInfo.start.format().slice(0,-1).replace(/[-:\.]/g,'').slice(0,-3); //new Date(selectedDate.getTime() - (selectedDate.getTimezoneOffset() * 60000)).toISOString().slice(0,-1).replace(/[-:\.]/g,'').slice(0,-3); 1148 eInfo.edit = 'javascript:RZedit(\''+eInfo.rid+'\',\''+window.revizeCalendar.editformPrefix+'\/calendar_events-editform.jsp?selected_date='+dateStr+'\',\'0\',\'0\',\'\',\'\',\'rzevents\',\'\',\'\',\'editform\',\'*none*\',\'\',\'\')'; 1149 } 1150 1151 window.revizeCalendar.fns.resetModal(eInfo); 1152 1153 window.revizeCalendar.fns.createModalHeader(eInfo); 1154 window.revizeCalendar.fns.createModalBody(eInfo); 1155 window.revizeCalendar.fns.createModalFooter(eInfo); 1156 1157 window.revizeCalendar.fns.createModalExport(eInfo); 1158 1159 if (eInfo.id !== false) { 1160 var queryParam = eInfo.id; 1161 if (eInfo.rrule !== false) { 1162 queryParam += "+" + eInfo.start.format(RZ_ISO_FORMAT); 1163 } 1164 window.revizeCalendar.fns.changeUrlQuery([{ prop: 'event', val: queryParam }]); 1165 } 1166 1167 $('#event-modal').modal('show'); 1168} 1169 1170window.revizeCalendar_proto.fns.urlQueryModal = function() { 1171 var q = $.query.parseNew(location.search, location.hash.split("?").length > 1 ? location.hash.split("?")[1] : ""); 1172 var evId = q.get('event').toString(); 1173 if (evId == "") { return; } 1174 1175 var evParams = evId.split("+"); 1176 var event = null; 1177 1178 for (var i = 0; i < window.revizeCalendar.importData.length; i++) { 1179 if (event !== null) { break; } 1180 if (!window.revizeCalendar.importData[i].hasOwnProperty("response")) { continue; } 1181 1182 for (var e = 0; e < window.revizeCalendar.importData[i].response.length; e++) { 1183 if (window.revizeCalendar.importData[i].response[e].id == evParams[0]) { event = window.revizeCalendar.importData[i].response[e]; break; } 1184 } 1185 } 1186 1187 if (event === null) { return; } 1188 1189 var eInfo = { 1190 title: event.title, 1191 desc: event.desc, 1192 calendar_displays: event.calendar_displays, 1193 1194 start: moment(event.start), 1195 end: moment(0), 1196 allDay: event.allDay, 1197 rrule: event.rrule ?? false, 1198 1199 url: event.url, 1200 location: event.location, 1201 image: event.image, 1202 1203 options: event.options, 1204 1205 rid: event.rid,
1206 id: event.id, 1207 }; 1208 1209 if (eInfo.allDay !== true) { 1210 eInfo.end = moment(event.end); 1211 } 1212 1213 if (evParams.length == 2) { 1214 // Recurring Event 1215 if (!event.hasOwnProperty("rrule") || event.rrule == "") { return; } 1216 1217 var foundOccurence = false; 1218 var specificDate = moment(decodeURIComponent(evParams[1])); 1219 if (!specificDate.isValid()) { return; } 1220 1221 var rule = new rrule.rrulestr(event.rrule, { forceset: true }); 1222 1223 var dstart = moment(event.start); 1224 var dend = (event.hasOwnProperty('end') ? moment(event.end) : undefined); 1225 1226 var dur = undefined; 1227 if (dend) { 1228 dur = moment.duration(dend.diff(dstart)); 1229 } 1230 1231 var lookAhead = moment(specificDate).add('1 day').toDate(); 1232 1233 var UTCfiedDate = dstart.toDate(); 1234 UTCfiedDate.setMinutes(UTCfiedDate.getMinutes() - UTCfiedDate.getTimezoneOffset()); // RRule library recognizes that browser Date sucks and tries to double offset inputted dates. 1235 1236 var occurences = rule.between(UTCfiedDate, lookAhead, true); 1237 for (var i = 0; i < occurences.length; i++) { 1238 occurences[i] = occurences[i].setMinutes(occurences[i].getMinutes() + occurences[i].getTimezoneOffset()); 1239 var rstart = moment(occurences[i]); 1240 1241 if (!specificDate.isSame(rstart)) { continue; } 1242 1243 var rend = dend; 1244 if (rend) { 1245 rend = moment(rstart); 1246 rend.add(dur); 1247 } 1248 1249 eInfo.start = rstart; 1250 eInfo.end = rend; 1251 1252 foundOccurence = true; 1253 } 1254 1255 if (!foundOccurence) { return; } 1256 } 1257 window.revizeCalendar.fns.showModal(eInfo); 1258} 1259 1260// --------------------------------------- Helpers Section --------------------------------------- // 1261 1262window.revizeCalendar_proto.fns.exportCalendar = function(cal) { 1263 if (!cal) { return; } 1264 1265 var fullEvents = cal.getEvents(); 1266 icalExport = ics(); 1267 window.revizeCalendar.fns.addEventsToExport(fullEvents, icalExport); 1268 1269 var exportName = "Full Calendar"; 1270 1271 var activeCalendar = $.query.get('calendar').toString(); 1272 if (activeCalendar !== "") { 1273 exportName = $(".calendar-name-filter[data-calendar-id="+activeCalendar+"]").text(); 1274 } 1275 1276 icalExport.download(exportName); 1277} 1278 1279window.revizeCalendar_proto.fns.addEventsToExport = function(events, ical) { 1280 $.each(events, function(i, ev){ 1281 1282 try { 1283 decodeURIComponent(ev.desc); 1284 } catch (e) { 1285 console.warn("[addEventsToExport] Could not add event " + ev.id + " to the export as the description is malformed."); 1286 return; 1287 } 1288 1289 var startStr = ""; 1290 var endStr = ""; 1291 var locationStr = ""; 1292 var descStr = ""; 1293 1294 if (ev._def.extendedProps.hasOwnProperty("desc")) { 1295 try { 1296 descStr = decodeURIComponent(ev._def.extendedProps.desc); 1297 } catch (e) {} 1298 } 1299 1300 if (ev._def.extendedProps.hasOwnProperty("location")) { 1301 locationStr = ev._def.extendedProps.location; 1302 } 1303 1304 if (ev.allDay) { 1305 startStr = moment(ev.start).startOf('day').toISOString(); 1306 endStr = startStr; 1307 } else { 1308 var startM = moment(ev.start); 1309 var endM = moment(ev.end); 1310 1311 if (startM.isSame(endM)) { 1312 startStr = moment(ev.start).toISOString(); 1313 endStr = moment(ev.end).add(1, 'second').toISOString(); 1314 } else { 1315 startStr = moment(ev.start).toISOString(); 1316 endStr = moment(ev.end).toISOString(); 1317 } 1318 } 1319 1320 /*if (ev._def.extendedProps.hasOwnProperty("rrule")) { 1321 var tempRule = {}; 1322 tempRule.rrule = ev.rrule; 1323 1324 if(tempRule.rrule.indexOf('DTSTART') >= 0 ){ 1325 tempRule.rrule = tempRule.rrule.split('\n').filter(function(dt){ 1326 return dt.indexOf('DTSTART') < 0; 1327 }).join('\n'); 1328 } 1329 1330 if(tempRule.rrule.indexOf('RDATE') >= 0 ){ 1331 tempRule.rrule = tempRule.rrule.split('\n').filter(function(dt){ 1332 return dt.indexOf('RDATE') < 0; 1333 }).join('\n'); 1334 } 1335 1336 ical.addEvent(ev.title, descStr, locationStr, startStr, endStr, tempRule); 1337 } else {*/ 1338 ical.addEvent(ev.title, descStr, locationStr, startStr, endStr, null); 1339 //} 1340 }); 1341} 1342
1343window.revizeCalendar_proto.fns.getEventColor = function(event) { 1344 var color = defaultCalendarColor; // var color = event.backgroundColor; 1345 var ind; 1346 1347 if (event.extendedProps) { 1348 ind = event.extendedProps.calendar_displays[0]; 1349 } else { 1350 ind = event.calendar_displays[0]; 1351 } 1352 if (window.revizeCalendar.calendarProps[ind]) { 1353 color = window.revizeCalendar.calendarProps[ind].color; 1354 } 1355 1356 return color; 1357} 1358 1359window.revizeCalendar_proto.fns.getContrastYIQ = function(color){ 1360 1361 var r, g, b; 1362 var a = 1; 1363 1364 if (color.indexOf("#") !== -1 && color.length === 7) { 1365 color = color.replace("#", ""); 1366 r = parseInt(color.substr(0,2),16); 1367 g = parseInt(color.substr(2,2),16); 1368 b = parseInt(color.substr(4,2),16); 1369 } else if (color.indexOf("rgb") !== -1) { 1370 color = color.split(/[()]/); 1371 if (color.length == 3) { 1372 color = color[1].split(","); 1373 r = parseInt(color[0].trim()); 1374 g = parseInt(color[1].trim()); 1375 b = parseInt(color[2].trim()); 1376 if (color.length > 3) { 1377 a = parseFloat(color[3].trim()); 1378 } 1379 } 1380 } 1381 1382 if (r !== undefined && g !== undefined && b !== undefined) { 1383 var yiq = (((r*299)+(g*587)+(b*114))/a)/1000; 1384 return (yiq >= 150) ? 'dark-text' : 'light-text'; 1385 } 1386 1387 return 'dark-text'; 1388} 1389 1390window.revizeCalendar_proto.fns.tagCalendarDay = function(el) { 1391 var par = el.parentElement; 1392 var colSpan = 0; 1393 1394 if (el.fcSeg) { 1395 colSpan = el.fcSeg.lastCol - el.fcSeg.firstCol; 1396 } 1397 1398 while (par !== null && par.tagName !== 'TABLE') { 1399 par = par.parentElement; 1400 if (par === null || par.tagName === 'TABLE') { break; } 1401 if (par.classList.contains("fc-daygrid-day")) { 1402 par.classList.add("day-has-event"); 1403 if (colSpan > 0) { 1404 var nextCell = par; 1405 for (var i = 0; i < colSpan; i++) { 1406 nextCell = nextCell.nextElementSibling; 1407 if (!nextCell || !nextCell.classList.contains("fc-daygrid-day")) { break; } 1408 nextCell.classList.add("day-has-event"); 1409 } 1410 } 1411 return; 1412 } 1413 } 1414} 1415 1416window.revizeCalendar_proto.fns.tagCalendarDays = function(cal) { 1417 cal.querySelectorAll(".fc-daygrid-event").forEach(function(el, i) { 1418 el.classList.remove("day-has-event"); 1419 }); 1420 cal.querySelectorAll(".fc-daygrid-event").forEach(function(el, i) { 1421 window.revizeCalendar.fns.tagCalendarDay(el); 1422 }); 1423} 1424 1425window.revizeCalendar_proto.fns.changeUrlQuery = function(args) { 1426 var q = $.query.parseNew(location.search, location.hash.split("?").length > 1 ? location.hash.split("?")[1] : ""); 1427 1428 var url = window.location.href.split('?').shift(); 1429 var s; 1430 if (arguments.length){ 1431 if (Array.isArray(args)){ 1432 for (var i = 0; i < args.length; i++){
1433 if (args[i].prop) 1434 q = q.SET(args[i].prop, args[i].val); 1435 } 1436 } else if(typeof args === 'string'){ 1437 q = q.REMOVE(args); 1438 } 1439 } 1440 s = q.toString(); 1441 1442 window.history.replaceState(q, 'Calendar', url + s); 1443} 1444 1445window.revizeCalendar_proto.fns.getDefaultTextColor = function(cal) { 1446 var el = cal; 1447 while (el !== null) { 1448 if (window.getComputedStyle(el).backgroundColor !== 'rgba(0, 0, 0, 0)') { 1449 return window.revizeCalendar.fns.getContrastYIQ(window.getComputedStyle(el).backgroundColor); 1450 } 1451 el = el.parentElement; 1452 } 1453 return window.revizeCalendar.fns.getContrastYIQ("#FFFFFF"); 1454} 1455 1456window.revizeCalendar_proto.fns.decodeEventDescription = function(string, ev) { 1457 try { 1458 var base64 = false; 1459 if (/^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/.test(string)) { 1460 var rzEncodedPrefix = "[RZ:base64]"; 1461 var decoded = atob(string); 1462 if (decoded.indexOf(rzEncodedPrefix) === 0) { 1463 string = decoded.substr(rzEncodedPrefix.length); 1464 base64 = true; 1465 } 1466 } 1467 if (!base64) { 1468 string = decodeURIComponent(string); 1469 } 1470 } catch (e){ 1471 string = unescape(string); 1472 console.warn("[revizeCalendar.fns.list.dottedTemplate] Garbage Characters detected in event", ev); 1473 } 1474 return string; 1475} 1476 1477window.revizeCalendar.fns.__proto__ = window.revizeCalendar_proto.fns; 1478window.revizeCalendar.fns.full.__proto__ = window.revizeCalendar_proto.fns.full; 1479window.revizeCalendar.fns.mini.__proto__ = window.revizeCalendar_proto.fns.mini; 1480window.revizeCalendar.fns.list.__proto__ = window.revizeCalendar_proto.fns.list; 1481 1482// --------------------------------------- Main Calendar Filter Section --------------------------------------- // 1483 1484setTimeout(function() { 1485 1486 $('.calendar-name-filter, .calendar-tab-filter').off('click'); 1487 $('.calendar-name-filter, .calendar-tab-filter').on('click', function(e){ 1488 e.preventDefault(); 1489 if ($(this).data('calendar-id').toString() === "clear") { 1490 $('.calendar-active').removeClass('calendar-active'); 1491 1492 window.revizeCalendar.fns.changeUrlQuery("calendar"); 1493 } else { 1494 if(!$(this).parent().hasClass('calendar-active')){ 1495 $('.calendar-active').removeClass('calendar-active'); 1496 $(this).parent().addClass('calendar-active'); 1497 1498 window.revizeCalendar.fns.changeUrlQuery([{ 1499 prop: 'calendar', 1500 val: $(this).data('calendar-id').toString() 1501 }]); 1502 } else { 1503 $('.calendar-active').removeClass('calendar-active'); 1504 1505 window.revizeCalendar.fns.changeUrlQuery('calendar'); 1506 } 1507 } 1508 window.revizeCalendar.fns.refreshCalendars(); 1509 }); 1510 1511 $('#calendar-search').off('keyup'); 1512 $('#calendar-search').on('keyup', function(e) { 1513 if (e.which === 13) { 1514 window.revizeCalendar.fns.submitSearch($(this).val()); 1515 } 1516 }); 1517 1518 $('#calendar-submit').off('click'); 1519 $('#calendar-submit').on('click',function(e) { 1520 e.preventDefault(); 1521 window.revizeCalendar.fns.submitSearch($('#calendar-search').val()); 1522 }); 1523 1524 $('#event-modal').off('hidden.bs.modal'); 1525 $('#event-modal').on('hidden.bs.modal', function() { 1526 window.revizeCalendar.fns.changeUrlQuery('event',''); 1527 }); 1528 1529}, 1000); 1530 1531window.revizeCalendar.fns.submitSearch = function(searchStr) { 1532 if (searchStr.trim().length > 0) { 1533 window.revizeCalendar.fns.changeUrlQuery([{ 1534 prop: 'query', 1535 val: searchStr.toLowerCase() 1536 }]); 1537 } else { 1538 window.revizeCalendar.fns.changeUrlQuery('query'); 1539 } 1540 window.revizeCalendar.fns.refreshCalendars(); 1541} 1542 1543// --------------------------------------- Init --------------------------------------- // 1544 1545async function scriptToPromise(url, base = "") { 1546 return new Promise(function(resolve, reject) { 1547 var scriptTag = document.createElement("script"); 1548 scriptTag.async = false; 1549 scriptTag.src = base + url; 1550 scriptTag.onload = function() { resolve(); }; 1551 scriptTag.onerror = function() { reject(); }; 1552 document.body.appendChild(scriptTag); 1553 }); 1554} 1555 1556FullCalendar = {}; 1557 1558window.addEventListener('load', async function() { 1559 if (typeof FullCalendar === 'undefined' || !FullCalendar.hasOwnProperty("globalPlugins")) { 1560 await $.getScript("//cdn.jsdelivr.net/npm/[email protected]/index.global.min.js"); 1561 await $.getScript("//cdn.jsdelivr.net/npm/[email protected]/dist/es5/rrule.min.js"); 1562 await $.getScript("//cdn.jsdelivr.net/npm/@fullcalendar/[email protected]/index.global.min.js"); 1563 } 1564 if (typeof $.query === 'undefined') { 1565 await scriptToPromise("/revize/plugins/revize_calendar/jquery.query-object.js"); 1566 } 1567 if (typeof doT === 'undefined') { 1568 await scriptToPromise("/revize/plugins/revize_calendar/doT.min.js"); 1569 } 1570 if (typeof ics === 'undefined') { 1571 await scriptToPromise("/revize/plugins/revize_calendar/ics/ics.min.js"); 1572 } 1573 if (typeof moment === 'undefined') { 1574 await scriptToPromise("/revize/plugins/revize_calendar/moment.min.js"); 1575 } 1576 window.dispatchEvent(new Event('RZCalendar.AssetsLoaded')); 1577}); 1578 1579window.addEventListener('RZCalendar.AssetsLoaded', function() { 1580 window.revizeCalendar.fns.preInit(); 1581 window.revizeCalendar.fns.prepareImportData(); 1582});
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.