1 2 3<!DOCTYPE html> 4<html> 5<head> 6 <!-- CCU 03/2006 meta tags settings start --> 7 <title>CincyTicket</title> 8 <meta name="description" content="Visit CincyTicket.com to get tickets for the hottest events in Cincinnati, OH and the surrounding area."> 9 <meta name="keywords" content="CincyTicket, tickets,Buy Tickets, events, performances, shows, online ticketing"> 10 <meta name="author" content="CincyTicket"> 11 <meta name="abstract" content="Buy tickets and see performance listings from CincyTicket"> 12 <meta name="robots" content="INDEX, FOLLOW"> 13 14 <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.8, minimum-scale=1.0' name='viewport' /> 15 <meta name="google-translate-customization" content="9aaf36daf6e43103-a12f76fcd2014ac8-g804c3b886a9cdf60-11"></meta> 16 17 <link rel="stylesheet" type="text/css" href="//www.cincyticket.com/include/structure.css?ver=20228"> 18 <link rel="stylesheet" type="text/css" href="//www.cincyticket.com/include/style.css?ver=20228"> 19 <link rel='stylesheet' content='text/css' href='/include/jqueryui-themes/default/jquery-ui.css' /> 20 21 <link rel="stylesheet" type="text/css" media="only screen and (max-width: 1024px)" href="//www.cincyticket.com/include/mobile.css?ver=20228"> 22 23
23<script type="text/javascript" src="//www.cincyticket.com/include/javascript.js?ver=20228"></script>
23 24
24<script type="text/javascript" src="//www.cincyticket.com/include/jq.js"></script>
24 25 26
26<script type='text/javascript' src='/include/jquery-3.5.1.min.js'></script>
26<script type='text/javascript' src='/include/jqueryui-themes/jquery-ui.min.js'></script>
26 27
27<script type="text/javascript" src="//www.cincyticket.com/include/mobile.js"></script>
27 28
29<script type="text/javascript"> 30 if (!navigator.cookieEnabled) { 31 alert("Your browser settings are currently configured to not allow cookies. Please enable cookies and try again."); 32 window.stop(); 33 document.execCommand("Stop"); //works in IE, 34 } 35</script>
35 36 37 38
39<script type="text/javascript" src="//www.cincyticket.com/include/swApi.js"></script>
vendor: 2 bytes, line 39
39
40<script type="text/javascript" src="//www.cincyticket.com/include/swApiPublic.js"></script>
vendor: 2 bytes, line 40
40
41<script type="text/javascript"> 42 43var window = window || {}; 44var Showare = Showare || {}; 45var document = document || undefined; 46 47Showare.Logger = { 48 Settings: { 49 ShouldLogInDev: true 50 }, 51 data: null, 52 env: {} 53} 54 55window.onerror = function(msg, url, lineNo, _, error) { 56 var envInfo = Showare.Logger._getEnvironmentDetails(); 57 58 var message = { 59 Description: msg, 60 SourceFile: url, 61 SourceLine: lineNo, 62 Referer: envInfo.referer, 63 QueryString: envInfo.querystring, 64 ErrorType: Showare.Logger.Settings.ErrorType, 65 Website: envInfo.website, 66 ShouldLogInDev: Showare.Logger.Settings.ShouldLogInDev, 67 Browser: envInfo.browser, 68 IPAddress: envInfo.ipaddress 69 }; 70 71 if (error != undefined) { 72 message.Exception = error.stack; 73 } 74 75 if (Showare.Logger.data) { 76 message.StateVariables = JSON.stringify(Showare.Logger.data); 77 } 78 79 swApiPublic.sendRequest("POST", "/v1/errorlog/", message); 80 Showare.Logger.data = null; 81 return false; 82 83 function shouldfilterError() { 84 return !( 85 // This error gets thrown by third party includes, to see full error, we need 86 // to do https://blog.sentry.io/2016/05/17/what-is-script-error.html 87 (msg.search("\s*Script error.*") == -1) && 88 // Related to iOS issue: https://github.com/getsentry/raven-js/issues/756 89 (msg.search(".*evaluating 'elt.parentNode'.*") == -1)) 90 } 91}; 92 93Showare.Logger.log = function(exception, data) { 94 Showare.Logger.data = data; 95 96 if (Object.prototype.toString.call(exception) == "[object Error]") { 97 if (exception.stack) { 98 var ex = exception.stack.split('\n'); 99 // Parse exceptions in the format of 100 // ' at src (javascript.js?ver=20228:510)' 101 var data = ex[1].match(/.+\((.+):(\d+):(\d+)\)/); 102 // and 103 // ' at src javascript.js?ver=20228:510' 104 if (!data) { 105 data = ex[1].match(/.+\s(.+):(\d+):(\d+)/); 106 } 107 window.onerror(ex[0], data[1], data[2], '', exception); 108 } else { 109 window.onerror(exception.name + ": " + exception.message, '', ''); 110 } 111 } else { 112 window.onerror(exception, '', ''); 113 } 114}; 115 116Showare.Logger.warn = function(msg, data) { 117 var logDetails = { 118 environment: Showare.Logger._getEnvironmentDetails(), 119 message: msg, 120 data: data 121 } 122 123 swApiPublic.sendRequest("POST", "/v1/errorlog/warn", logDetails); 124 return; 125}; 126 127Showare.Logger._getEnvironmentDetails = function() { 128 Showare.Logger.Settings.ErrorType = 'Javascript'; 129 return { 130 browser: "Mozilla/5.0 AppleWebKit/537.36 KHTML, like Gecko compatible PageSourceSearchBot/1.0 https//pagesourcesearch.com/bot Chrome/128.0.0.0 Safari/537.36", 131 ipaddress: "181.215.65.76", 132 querystring: window.location.href, 133 referer: "", 134 website: "www.cincyticket.com", 135 basketid: "0FkQ0UVTLSTMzgwTMTgE10CMD2IyMMDNykxTNTIEx0CNDuExMOjL1E1jLjcY2xULEK9KRRUSRx__U_g_" 136 } 137} 138 139</script>
139<script type="text/javascript"> 140//---------------------------DATEPICKER--------------------------------- 141function buildDatepicker(options) { 142 //Calling this function should be sufficient to create a calendar within a designated div, with and 143 //EX: headerDP = buildDatepicker({"calendarID":"headerCalendar","linkedInputID":"headerCalendarInput","isModal":false,"forceDates":true, "defaultDate": "{{Output date from server Here}}"}); <~ would create a calendar object for the calendar presented at #headerCalendar, and link it to #headerCalendarInput 144 //most calendar methods are specific to the document the calendar resides on, and should be handled via the onChange event for the linked input 145 //Available Options: 146 // calendarID (required) == string, ID of calendar div 147 // linkedInput (required) == string, ID of input which will change when a date is selected 148 // isModal == boolean, if true, calendar will be hidden, and display when the designated input recieves focus. If false, the calendar will be present and display as an inline block at all times. 149 // forceDates == boolean, if true only highlighted dates will be clickable 150 // detailedCalendar == boolean, if true data is pulled to determine pricing information, sold out days, limited availablility - requires eventID 151 // defaultDate == string, mm/dd/yyyy date that calendar should start on (this will only represent the month displayed at the begining) 152 // type == string: defaults to "performancedates", which will add all visible performances 153 // eventID == integer: defaults to -1 which means no event. Other values will filter by events with that ID, allowing for a search of performance dates for a specific event only 154 // isMultiplePerformanceIndicator == boolean: if true, shows indicator for dates with multiple performance times 155 // 156 //Methods: 157 // showDlg()/hideDlg() : shows/hides modal calendars, no valid for non-modal calendars 158 // addHighlightDay(mm/dd/yyyy) : adds a date (presented as a mm/dd/yyyy string) to the list of highlight dates for the calendar - REQUIRES HighlightDays() function call to visually represent this change on the calendar 159 // clearHihghlightDays() : removes all stored highlight dates 160 // highlightDays() : adds highlight class to stored days, visually highlighting them ont he calendar. 161 162 var myID = options.calendarID; //required 163 var myLinkedInput = options.linkedInputID; //required 164 var isModal = options.isModal || false; 165 var showLoader = options.showLoader || false; 166 var forceDates = options.forceDates || false; 167 var myDefault = new Date(); 168 if (options.defaultDate) { 169 try{ 170 171 myDefault = new Date(options.defaultDate); 172 } catch (e) { 173 console.log("date no valid for calendar: " + myID); 174 console.log(e); 175 } 176 } 177 var type = options.type || "performancedates"; 178 var eventID = options.eventID || -1; 179 var detailedCalendar = options.detailedCalendar && eventID != -1 || false; 180 var bundleID = options.bundleID || -1; 181 var categoryID = options.CategoryID || -1; 182 var corporatePartnerPage = options.corporatePartnerPage || 0; 183 var bValidCoupon = options.bValidCoupon || 0; 184 var couponCode = options.couponCode || ""; 185 var isMultiplePerformanceIndicator = options.isMultiplePerformanceIndicatorFlag || 0; 186 187 return new swDatepicker(myID, myLinkedInput, isModal, showLoader, forceDates, detailedCalendar, myDefault, type, eventID, bundleID, categoryID, corporatePartnerPage,bValidCoupon,couponCode,isMultiplePerformanceIndicator) 188} 189function swDatepicker(id, target, modal, loader, force, detailed, defaultDate, type, eventID, bundleID, categoryID, corporatePartnerPage,bValidCoupon,couponCode,isMultiplePerformanceIndicator) { 190 191 this.$id = $('#' + id); // element to attach widget to 192 this.$monthObj = this.$id.find('.month'); 193 this.$prev = this.$id.find('.bn_prev'); 194 this.$next = this.$id.find('.bn_next'); 195 this.$grid = this.$id.find('.cal'); 196 this.$target = $('#' + target); // div or text box that will receive the selected date string and focus (if modal) 197 this.bModal = modal; // true if datepicker should appear in a modal dialog box. 198 this.showLoader = loader; 199 this.forceDateSelection = force; //if true, will only allow users to click on highlighted dates - see addHighlightDay() 200 this.detailedCalendar = detailed; 201 this.active = !modal; 202 this.type = type; 203 this.eventID = eventID; 204 this.bundleID = bundleID; 205 this.categoryID = categoryID; 206 this.corporatePartnerPage = corporatePartnerPage; 207 this.fromDateRange = ""; 208 this.toDateRange = ""; 209 this.dateRangeEvents = []; 210 this.calendarName = id; 211 212 this.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 213 'July', 'August', 'September', 'October', 'November', 'December']; 214 215 this.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 216 217 this.dateObj = new Date(); 218 219 this.curYear = this.dateObj.getFullYear(); 220 this.year = defaultDate.getFullYear(); 221 222 this.curMonth = this.dateObj.getMonth(); 223 this.month = defaultDate.getMonth(); 224 this.getFirstDate(defaultDate.getMonth()); //update the month to the first performance ASAP 225 226 this.curDate = this.dateObj.getDate(); 227 this.date = defaultDate.getDate(); 228 this.currentDate = (this.month == this.curMonth && this.year == this.curYear); 229 this.activeMonth = (String(this.month + 1) + "/1/" + this.year); 230 231 this.keys = { 232 tab: 9, 233 enter: 13, 234 esc: 27, 235 space: 32, 236 pageup: 33, 237 pagedown: 34, 238 end: 35, 239 home: 36, 240 left: 37, 241 up: 38, 242 right: 39, 243 down: 40 244 }; 245 246 this.bValidCoupon = bValidCoupon; 247 this.couponCode = couponCode; 248 this.isMultiplePerformanceIndicator = isMultiplePerformanceIndicator; 249 250 this.highlightDates = []; 251 252 // display the current month 253 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 254 255 // populate the calendar grid
256 this.popGrid(); 257 258 // update the table's activedescdendant to point to the current day 259 this.$grid.attr('aria-activedescendant', this.$grid.find('.today').attr('id')); 260 261 this.bindHandlers(); 262 263 //show selected day 264 $('#' + this.calendarName + '-day' + this.date).addClass('focus').attr('aria-selected', 'true'); 265 266 // hide dialog if in modal mode 267 if (this.bModal == true) { 268 this.$id.attr('aria-hidden', 'true'); 269 //show/hide functionality may vary based on use, so should be handled after the datepicker is created. 270 //if we're on mobile, disable keyboard for the input: 271 if ($(window).width() < 1024) { 272 this.$target.attr("readonly", "true"); 273 } 274 } 275 276 this.currencySymbol = "$"; 277 this.buyTicketsButtonText = "Buy Tickets"; 278} 279 280// 281// popGrid() is a member function to populate the datepicker grid with calendar days 282// representing the current month 283// 284// @return N/A 285// 286swDatepicker.prototype.popGrid = function () { 287 if(this.showLoader) 288 $(".calendar-loading").show(); 289 var numDays = this.calcNumDays(this.year, this.month); 290 var startWeekday = this.calcStartWeekday(this.year, this.month); 291 //var lastMonth = this.month - 1; 292 //var lastMonthYear = this.year; 293 var weekday = 0; 294 var curDay = 1; 295 var rowCount = 1; 296 var $tbody = this.$grid.find('tbody'); 297 298 var currentDateDay = this.dateObj.getDate(); 299 var currentDateMonth = this.dateObj.getMonth(); 300 var currentDateYear = this.dateObj.getFullYear(); 301 302 var gridCells = '\t<tr id="row1">\n'; 303 304 // Keeping in case the client (Gaylord) pushes back on not having previous month's dates selectable 305 // If the last month is -1, roll it over to December (11) and subtract 1 from the last month's year 306 /*if (lastMonth < 0) { 307 lastMonth = 11; 308 lastMonthYear = lastMonthYear - 1; 309 } 310 311 var lastMonthNumDays = this.calcNumDays(lastMonthYear, lastMonth); 312 var lastMonthStartDay = lastMonthNumDays - (startWeekday - 1);*/ 313 314 // clear the grid 315 $tbody.empty(); 316 $('#msg').empty(); 317 318 // Keeping in case the client (Gaylord) pushes back on not having previous month's dates selectable 319 // Insert the leading empty cells 320 /*for (var weekday = 0; weekday < startWeekday; weekday++) { 321 gridCells += '\t\t<td id="' + this.calendarName + '-day' + lastMonthStartDay + '" class="day-cell muted last-month" headers="row' + 322 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false" data-year="' + lastMonthYear + '"><span class="calendar-day notranslate" data-month="' + lastMonth + '">' + lastMonthStartDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 323 //gridCells += '\t\t<td class="empty" data-month="' + lastMonth + '" data-year="' + lastMonthYear + '" data-day="' + lastMonthStartDay + '"> </td>\n'; 324 lastMonthStartDay++; 325 }*/ 326 327 for (var weekday = 0; weekday < startWeekday; weekday++) { 328 gridCells += '\t\t<td class="empty"> </td>\n'; 329 } 330 331 // insert the days of the month. 332 for (curDay = 1; curDay <= numDays; curDay++) { 333 334 if (curDay == this.curDate && this.currentDate == true) { 335 336 gridCells += '\t\t<td id="' + this.calendarName + '-day' + curDay + '" class="today day-cell" aria-label="row' + 337 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false"><span class="calendar-day notranslate">' + curDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 338 } 339 else { 340 var addMuted = ""; 341 342 // Only mute dates in the past for the date range selector widget 343 if (this.type == 'dateRangeSelect') { 344 // If the year is in the past, or the year is the same but the month is in the past, or the month and year are the same but the day is in the past, mute the date 345 if (this.year < currentDateYear 346 || (this.year == currentDateYear && this.month < currentDateMonth) 347 || (this.year == currentDateYear && this.month == currentDateMonth && curDay < currentDateDay) 348 ) { 349 addMuted = " muted"; 350 } 351 } 352 353 gridCells += '\t\t<td id="' + this.calendarName + '-day' + curDay + '" class="day-cell' + addMuted + '" aria-label="row' + 354 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false"><span class="calendar-day notranslate">' + curDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 355 } 356 357 358 if (weekday == 6 && curDay < numDays) { 359 // This was the last day of the week, close it out 360 // and begin a new one 361 gridCells += '\t</tr>\n\t<tr id="row' + rowCount + '">\n'; 362 rowCount++; 363 weekday = 0; 364 } 365 else { 366 weekday++; 367 } 368 } 369 370 // Insert any trailing empty cells 371 for (weekday; weekday < 7; weekday++) { 372 373 gridCells += '\t\t<td class="empty"> </td>\n'; 374 } 375 376 gridCells += '\t</tr>'; 377 378 $tbody.append(gridCells); 379 if(this.detailedCalendar){ 380 this.getCalendarDetails(); 381 }else{ 382 this.fetchDates();
383 } 384 385} 386 387// 388// calcNumDays() is a member function to calculate the number of days in a given month 389// 390// @return (integer) number of days 391// 392swDatepicker.prototype.calcNumDays = function (year, month) { 393 394 return 32 - new Date(year, month, 32).getDate(); 395} 396 397// 398// calcstartWeekday() is a member function to calculate the day of the week the first day of a 399// month lands on 400// 401// @return (integer) number representing the day of the week (0=Sunday....6=Saturday) 402// 403swDatepicker.prototype.calcStartWeekday = function (year, month) { 404 405 return new Date(year, month, 1).getDay(); 406 407} // end calcStartWeekday() 408 409// 410// showPrevMonth() is a member function to show the previous month 411// 412// @param (offset int) offset may be used to specify an offset for setting 413// focus on a day the specified number of days from 414// the end of the month. 415// @return N/A 416// 417swDatepicker.prototype.showPrevMonth = function (offset) { 418 // show the previous month 419 if (this.month < 1) { 420 this.month = 11; 421 this.year--; 422 } 423 else { 424 this.month--; 425 } 426 427 if (this.month != this.curMonth || this.year != this.curYear) { 428 this.currentDate = false; 429 } 430 else { 431 this.currentDate = true; 432 } 433 434 this.activeMonth = (String(this.month + 1) + "/1/" + this.year) 435 436 // populate the calendar grid 437 this.popGrid(); 438 439 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 440 441 // if offset was specified, set focus on the last day - specified offset 442 if (offset != null) { 443 var numDays = this.calcNumDays(this.year, this.month); 444 var day = 'day' + (numDays - offset); 445 446 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + day); 447 $('#' + this.calendarName + '-' + day).addClass('focus').attr('aria-selected', 'true'); 448 } 449 450 451} // end showPrevMonth() 452 453// 454// showNextMonth() is a member function to show the next month 455// 456// @param (offset int) offset may be used to specify an offset for setting 457// focus on a day the specified number of days from 458// the beginning of the month. 459// @return N/A 460// 461swDatepicker.prototype.showNextMonth = function (offset) { 462 463 // show the next month 464 if (this.month == 11) { 465 this.month = 0; 466 this.year++; 467 } 468 else { 469 this.month++; 470 } 471 472 if (this.month != this.curMonth || this.year != this.curYear) { 473 this.currentDate = false; 474 } 475 else { 476 this.currentDate = true; 477 } 478 479 this.activeMonth = (String(this.month + 1) + "/1/" + this.year) 480 481 // populate the calendar grid 482 this.popGrid(); 483 484 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 485 486 // if offset was specified, set focus on the first day + specified offset 487 if (offset != null) { 488 var day = 'day' + offset; 489 490 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + day); 491 $('#' + this.calendarName + '-' + day).addClass('focus').attr('aria-selected', 'true'); 492 } 493 494} // end showNextMonth() 495 496// 497// showPrevYear() is a member function to show the previous year 498// 499// @return N/A 500// 501swDatepicker.prototype.showPrevYear = function () { 502 503 // decrement the year 504 this.year--; 505 506 if (this.month != this.curMonth || this.year != this.curYear) { 507 this.currentDate = false; 508 } 509 else { 510 this.currentDate = true; 511 } 512 513 // populate the calendar grid 514 this.popGrid(); 515 516 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 517 518} // end showPrevYear() 519 520// 521// showNextYear() is a member function to show the next year 522// 523// @return N/A 524// 525swDatepicker.prototype.showNextYear = function () { 526 527 // increment the year 528 this.year++; 529 530 if (this.month != this.curMonth || this.year != this.curYear) { 531 this.currentDate = false; 532 } 533 else { 534 this.currentDate = true; 535 } 536 537 // populate the calendar grid
538 this.popGrid(); 539 540 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 541 542} // end showNextYear() 543 544// 545// bindHandlers() is a member function to bind event handlers for the widget 546// 547// @return N/A 548// 549swDatepicker.prototype.bindHandlers = function () { 550 551 var thisObj = this; 552 553 ////////////////////// bind button handlers ////////////////////////////////// 554 this.$prev.click(function (e) { 555 return thisObj.handlePrevClick(e); 556 }); 557 558 this.$next.click(function (e) { 559 return thisObj.handleNextClick(e); 560 }); 561 562 this.$prev.keydown(function (e) { 563 return thisObj.handlePrevKeyDown(e); 564 }); 565 566 this.$next.keydown(function (e) { 567 return thisObj.handleNextKeyDown(e); 568 }); 569 570 ///////////// bind grid handlers ////////////// 571 572 this.$grid.keydown(function (e) { 573 return thisObj.handleGridKeyDown(e); 574 }); 575 576 this.$grid.keypress(function (e) { 577 return thisObj.handleGridKeyPress(e); 578 }); 579 580 this.$grid.focus(function (e) { 581 return thisObj.handleGridFocus(e); 582 }); 583 584 this.$grid.blur(function (e) { 585 return thisObj.handleGridBlur(e); 586 }); 587 588 this.$grid.delegate('td', 'click', function (e) { 589 return thisObj.handleGridClick(this, e); 590 }); 591 592} // end bindHandlers(); 593 594function scrollToFirstHighlightDay() { 595 // find all the heights of elements before the calendar 596 var EventInfoHeight = $('#EventInformationWrap').outerHeight() + 64; // 64 is the height mobile navigation 597 var EventLabelAndOptionsHeight = $('#eventCalendarLabelAndOptions').outerHeight(); 598 var CalendarMonthHeight = $('.sw-datepicker.large-datepicker .month-wrap').outerHeight(); 599 600 var EventInfoAndOptionsHeight = EventInfoHeight + EventLabelAndOptionsHeight; 601 var CalendarTopInfoHeaderHeights = EventInfoHeight + EventLabelAndOptionsHeight + CalendarMonthHeight + 10; // 10 is just a gap added so it is not sticking against the month section 602 603 // set the Top section sticky so when it focuses on the first hightlight day you can still see the informations 604 $('#EventInformationWrap').addClass("make-this-section-sticky"); 605 $('#eventCalendarLabelAndOptions').addClass("make-this-section-sticky"); 606 $('#eventCalendarLabelAndOptions').css("top", EventInfoHeight); 607 $('.sw-datepicker.large-datepicker .month-wrap').addClass("make-this-section-sticky"); 608 $('.sw-datepicker.large-datepicker .month-wrap').css("top", EventInfoAndOptionsHeight); 609 610 // Check if any elements with the class .highlight-day exist 611 var highlightDay = $('.performance-list-calendar .highlight-day').first(); 612 613 // set the first day cell 614 var firstDayCel = $('.day-cell').first(); 615 var scrollToPosition = 0; 616 617 if (highlightDay.length > 0) { // Get the offset only if .highlight-day element exists 618 scrollToPosition = highlightDay.offset().top; 619 scrollToPosition = scrollToPosition - CalendarTopInfoHeaderHeights; 620 $('html, body').animate({scrollTop: scrollToPosition}, 'slow'); 621 } else { // if there's no highlights on this month, focus on the first day of the month 622 scrollToPosition = firstDayCel.offset().top; 623 scrollToPosition = scrollToPosition - (CalendarTopInfoHeaderHeights * 2); 624 $('html, body').animate({scrollTop: scrollToPosition}, 'slow'); 625 } 626} 627 628// 629// handlePrevClick() is a member function to process click events for the prev month button 630// 631// @input (e obj) e is the event object associated with the event 632// 633// @return (boolean) false if consuming event, true if propagating 634// 635swDatepicker.prototype.handlePrevClick = function (e) { 636 637 var active = this.$grid.attr('aria-activedescendant'); 638 639 if (e.ctrlKey) { 640 this.showPrevYear(); 641 } 642 else { 643 this.showPrevMonth(); 644 } 645 646 if (this.currentDate == false) { 647 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 648 } 649 else { 650 this.$grid.attr('aria-activedescendant', active); 651 } 652 653 e.stopPropagation(); 654 return false; 655 656} // end handlePrevClick() 657 658// 659// handleNextClick() is a member function to process click events for the next month button 660// 661// @input (e obj) e is the event object associated with the event 662// 663// @return (boolean) false if consuming event, true if propagating 664// 665swDatepicker.prototype.handleNextClick = function (e) { 666 667 var active = this.$grid.attr('aria-activedescendant'); 668 669 if (e.ctrlKey) { 670 this.showNextYear(); 671 } 672 else { 673 this.showNextMonth(); 674 } 675 676 if (this.currentDate == false) { 677 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 678 } 679 else { 680 this.$grid.attr('aria-activedescendant', active); 681 } 682 683 e.stopPropagation(); 684 return false; 685 686} // end handleNextClick() 687 688// 689// handlePrevKeyDown() is a member function to process keydown events for the prev month button 690// 691// @input (e obj) e is the event object associated with the event 692// 693// @return (boolean) false if consuming event, true if propagating 694// 695swDatepicker.prototype.handlePrevKeyDown = function (e) { 696 697 if (e.altKey) { 698 return true; 699 } 700 701 switch (e.keyCode) { 702 case this.keys.tab: { 703 if (this.bModal == false || !e.shiftKey || e.ctrlKey) { 704 return true; 705 } 706 707 this.$grid.focus(); 708 e.stopPropagation(); 709 return false; 710 } 711 case this.keys.enter: 712 case this.keys.space: { 713 if (e.shiftKey) { 714 return true; 715 } 716 717 if (e.ctrlKey) { 718 this.showPrevYear(); 719 } 720 else { 721 this.showPrevMonth(); 722 } 723 724 e.stopPropagation(); 725 return false; 726 } 727 } 728 729 return true; 730 731} // end handlePrevKeyDown() 732 733// 734// handleNextKeyDown() is a member function to process keydown events for the next month button 735// 736// @input (e obj) e is the event object associated with the event 737// 738// @return (boolean) false if consuming event, true if propagating 739// 740swDatepicker.prototype.handleNextKeyDown = function (e) { 741 742 if (e.altKey) { 743 return true; 744 } 745 746 switch (e.keyCode) { 747 case this.keys.enter: 748 case this.keys.space: { 749 750 if (e.ctrlKey) { 751 this.showNextYear(); 752 } 753 else { 754 this.showNextMonth(); 755 } 756 757 e.stopPropagation(); 758 return false; 759 } 760 } 761 762 return true; 763 764} // end handleNextKeyDown() 765 766// 767// handleGridKeyDown() is a member function to process keydown events for the datepicker grid 768// 769// @input (e obj) e is the event object associated with the event 770// 771// @return (boolean) false if consuming event, true if propagating 772// 773swDatepicker.prototype.handleGridKeyDown = function (e) { 774 775 var $rows = this.$grid.find('tbody tr'); 776 var $curDay = $('#' + this.$grid.attr('aria-activedescendant'));
777 var $days = this.$grid.find('td').not('.empty'); 778 var $curRow = $curDay.parent(); 779 780 if (e.altKey) { 781 return true; 782 } 783 784 switch (e.keyCode) { 785 case this.keys.tab: { 786 787 if (this.bModal == true) { 788 if (e.shiftKey) { 789 this.$next.focus(); 790 } 791 else { 792 this.$prev.focus(); 793 } 794 e.stopPropagation() 795 return false; 796 } 797 break; 798 } 799 case this.keys.enter: 800 case this.keys.space: { 801 802 if (e.ctrlKey) { 803 return true; 804 } 805 806 // update the target box 807 this.$target.val((this.month + 1) + '/' + $curDay.find(".calendar-day").text() + '/' + this.year).change(); 808 809 // fall through 810 } 811 case this.keys.esc: { 812 // dismiss the dialog box 813 this.hideDlg(); 814 815 e.stopPropagation(); 816 return false; 817 } 818 case this.keys.left: { 819 820 if (e.ctrlKey || e.shiftKey) { 821 return true; 822 } 823 824 var dayIndex = $days.index($curDay) - 1; 825 var $prevDay = null; 826 827 if (dayIndex >= 0) { 828 $prevDay = $days.eq(dayIndex); 829 830 $curDay.removeClass('focus').attr('aria-selected', 'false'); 831 $prevDay.addClass('focus').attr('aria-selected', 'true'); 832 833 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 834 } 835 else { 836 this.showPrevMonth(0); 837 } 838 839 e.stopPropagation(); 840 return false; 841 } 842 case this.keys.right: { 843 844 if (e.ctrlKey || e.shiftKey) { 845 return true; 846 } 847 848 var dayIndex = $days.index($curDay) + 1; 849 var $nextDay = null; 850 851 if (dayIndex < $days.length) { 852 $nextDay = $days.eq(dayIndex); 853 $curDay.removeClass('focus').attr('aria-selected', 'false'); 854 $nextDay.addClass('focus').attr('aria-selected', 'true'); 855 856 this.$grid.attr('aria-activedescendant', $nextDay.attr('id')); 857 } 858 else { 859 // move to the next month 860 this.showNextMonth(1); 861 } 862 863 e.stopPropagation(); 864 return false; 865 } 866 case this.keys.up: { 867 868 if (e.ctrlKey || e.shiftKey) { 869 return true; 870 } 871 872 var dayIndex = $days.index($curDay) - 7; 873 var $prevDay = null; 874 875 if (dayIndex >= 0) { 876 $prevDay = $days.eq(dayIndex); 877 878 $curDay.removeClass('focus').attr('aria-selected', 'false'); 879 $prevDay.addClass('focus').attr('aria-selected', 'true'); 880 881 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 882 } 883 else { 884 // move to appropriate day in previous month 885 dayIndex = 6 - $days.index($curDay); 886 887 this.showPrevMonth(dayIndex); 888 } 889 890 e.stopPropagation(); 891 return false; 892 } 893 case this.keys.down: { 894 895 if (e.ctrlKey || e.shiftKey) { 896 return true; 897 } 898 899 var dayIndex = $days.index($curDay) + 7; 900 var $prevDay = null; 901 902 if (dayIndex < $days.length) { 903 $prevDay = $days.eq(dayIndex); 904 905 $curDay.removeClass('focus').attr('aria-selected', 'false'); 906 $prevDay.addClass('focus').attr('aria-selected', 'true'); 907 908 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 909 } 910 else { 911 // move to appropriate day in next month 912 dayIndex = 8 - ($days.length - $days.index($curDay)); 913 914 this.showNextMonth(dayIndex); 915 } 916 917 e.stopPropagation(); 918 return false; 919 } 920 case this.keys.pageup: { 921 var active = this.$grid.attr('aria-activedescendant'); 922 923 924 if (e.shiftKey) { 925 return true; 926 } 927 928 929 if (e.ctrlKey) { 930 this.showPrevYear(); 931 } 932 else { 933 this.showPrevMonth(); 934 } 935 936 if ($('#' + active).attr('id') == undefined) { 937 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 938 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 939 } 940 else { 941 $('#' + this.calendarName + '-' + active).addClass('focus').attr('aria-selected', 'true'); 942 } 943 944 e.stopPropagation(); 945 return false; 946 } 947 case this.keys.pagedown: { 948 var active = this.$grid.attr('aria-activedescendant'); 949 950 951 if (e.shiftKey) { 952 return true; 953 } 954 955 if (e.ctrlKey) { 956 this.showNextYear(); 957 } 958 else { 959 this.showNextMonth(); 960 } 961 962 if ($('#' + active).attr('id') == undefined) { 963 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 964 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 965 } 966 else { 967 $('#' + this.calendarName + '-' + active).addClass('focus').attr('aria-selected', 'true'); 968 } 969 970 e.stopPropagation(); 971 return false; 972 } 973 case this.keys.home: { 974 975 if (e.ctrlKey || e.shiftKey) { 976 return true; 977 } 978 979 $curDay.removeClass('focus').attr('aria-selected', 'false'); 980 981 $('#' + this.calendarName + '-day1').addClass('focus').attr('aria-selected', 'true'); 982 983 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 984 985 e.stopPropagation(); 986 return false; 987 } 988 case this.keys.end: { 989 990 if (e.ctrlKey || e.shiftKey) { 991 return true; 992 } 993 994 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 995 996 $curDay.removeClass('focus').attr('aria-selected', 'false'); 997 998 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 999 1000 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + lastDay); 1001 1002 e.stopPropagation(); 1003 return false; 1004 } 1005 } 1006 1007 return true; 1008 1009} // end handleGridKeyDown() 1010 1011//
1012// handleGridKeyPress() is a member function to consume keypress events for browsers that 1013// use keypress to scroll the screen and manipulate tabs 1014// 1015// @input (e obj) e is the event object associated with the event 1016// 1017// @return (boolean) false if consuming event, true if propagating 1018// 1019swDatepicker.prototype.handleGridKeyPress = function (e) { 1020 1021 if (e.altKey) { 1022 return true; 1023 } 1024 1025 switch (e.keyCode) { 1026 case this.keys.tab: 1027 case this.keys.enter: 1028 case this.keys.space: 1029 case this.keys.esc: 1030 case this.keys.left: 1031 case this.keys.right: 1032 case this.keys.up: 1033 case this.keys.down: 1034 case this.keys.pageup: 1035 case this.keys.pagedown: 1036 case this.keys.home: 1037 case this.keys.end: { 1038 e.stopPropagation(); 1039 return false; 1040 } 1041 } 1042 1043 return true; 1044 1045} // end handleGridKeyPress() 1046 1047// 1048// handleGridClick() is a member function to process mouse click events for the datepicker grid 1049// 1050// @input (id obj) e is the id of the object triggering the event 1051// 1052// @input (e obj) e is the event object associated with the event 1053// 1054// @return (boolean) false if consuming event, true if propagating 1055// 1056swDatepicker.prototype.handleGridClick = function (id, e) { 1057 var $cell = $(id); 1058 1059 if ($cell.is('.empty')) { 1060 return true; 1061 } 1062 1063 this.$grid.find('.focus').removeClass('focus').attr('aria-selected', 'false'); 1064 $cell.addClass('focus').attr('aria-selected', 'true'); 1065 this.$grid.attr('aria-activedescendant', $cell.attr('id')); 1066 1067 var $curDay = $('#' + this.$grid.attr('aria-activedescendant')); 1068 1069 /*console.log($curDay); 1070 var isLastMonth = $curDay.hasClass('last-month'); 1071 1072 var monthSelected = this.month + 1; 1073 var yearSelected = this.year; 1074 1075 if (isLastMonth) { 1076 monthSelected--; 1077 1078 if (monthSelected == 0) 1079 monthSelected = 12; 1080 1081 yearSelected = $curDay.data('year'); 1082 } 1083 1084 console.log("month selected: " + monthSelected); 1085 console.log("year selected: " + yearSelected);*/ 1086 1087 // update the target box 1088 if(this.type == 'dateRangeSelect'){ 1089 if ($curDay.hasClass('muted')) 1090 return true; 1091 1092 var $rangeSelDate = new Date((this.month + 1) + '/' + $curDay.children('.calendar-day').text() + '/' + this.year); 1093 if(this.fromDateRange == '' && this.toDateRange == ''){ 1094 //no dates selected yet, store this in the from date range for now 1095 this.fromDateRange = $rangeSelDate; 1096 }else{ 1097 //we've previously selected at least one date here, so figure out which one it should be 1098 if($rangeSelDate < this.fromDateRange){ 1099 this.toDateRange = this.fromDateRange; 1100 this.fromDateRange = $rangeSelDate; 1101 }else{ 1102 this.toDateRange = $rangeSelDate; 1103 } 1104 } 1105 1106 var objDateRange = {} 1107 objDateRange.from = this.fromDateRange; 1108 objDateRange.to = this.toDateRange; 1109 this.$target.val(JSON.stringify(objDateRange)).change(); 1110 if(objDateRange.from != '' && objDateRange.to != ''){ 1111 this.hideDlg(); //NOTE: this only works if the date range is a modal, for other calendars you'll need to manage display according to needs based on current values. 1112 } 1113 e.stopPropagation(); 1114 return false; 1115 } 1116 if (!this.forceDateSelection || $cell.hasClass("highlight-day")) { 1117 this.$target.val((this.month + 1) + '/' + $curDay.children('.calendar-day').text() + '/' + this.year).change(); 1118 // dismiss the dialog box 1119 this.hideDlg(); 1120 } 1121 e.stopPropagation(); 1122 return false; 1123 1124} // end handleGridClick() 1125 1126// 1127// handleGridFocus() is a member function to process focus events for the datepicker grid 1128// 1129// @input (e obj) e is the event object associated with the event 1130// 1131// @return (boolean) true 1132// 1133swDatepicker.prototype.handleGridFocus = function (e) { 1134 var active = this.$grid.attr('aria-activedescendant'); 1135 1136 if ($('#' + active).attr('id') == undefined) { 1137 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 1138 $('#' + lastDay).addClass('focus').attr('aria-selected', 'true'); 1139 } 1140 else { 1141 $('#' + active).addClass('focus').attr('aria-selected', 'true'); 1142 } 1143 1144 return true; 1145 1146} // end handleGridFocus() 1147 1148// 1149// handleGridBlur() is a member function to process blur events for the datepicker grid 1150// 1151// @input (e obj) e is the event object associated with the event 1152// 1153// @return (boolean) true 1154// 1155swDatepicker.prototype.handleGridBlur = function (e) { 1156 $('#' + this.$grid.attr('aria-activedescendant')).removeClass('focus').attr('aria-selected', 'false'); 1157 1158 return true; 1159 1160} // end handleGridBlur() 1161 1162//
1163// showDlg() is a member function to show the datepicker and give it focus. This function is only called if 1164// the datepicker is used in modal dialog mode. 1165// 1166// @return N/A 1167// 1168swDatepicker.prototype.showDlg = function () { 1169 if (!this.bModal) 1170 return; 1171 1172 var thisObj = this; 1173 var thisNode = this.$id; 1174 1175 this.highlightDays(); 1176 1177 this.active = true; 1178 1179 //prevent calendar from pushing out of the right side of the window 1180 if (thisNode.parent()[0].getBoundingClientRect().left > (window.innerWidth / 2)) 1181 thisNode.addClass("right-side"); 1182 1183 $(".content-wrap").bind('click', function (e) { 1184 if (!thisNode[0].contains(e.target) && e.target != thisObj.$target[0]) { 1185 thisObj.hideDlg(); 1186 } 1187 }); 1188 1189 // show the dialog 1190 this.$id.attr('aria-hidden', 'false'); 1191 1192 this.$grid.focus(); 1193 1194} // end showDlg() 1195 1196// 1197// hideDlg() is a member function to hide the datepicker and remove focus. This function is only called if 1198// the datepicker is used in modal dialog mode. 1199// 1200// @return N/A 1201// 1202swDatepicker.prototype.hideDlg = function () { 1203 if (!this.bModal) 1204 return; 1205 1206 this.active = false; 1207 var thisNode = this.$id; 1208 1209 // unbind the modal event sinks 1210 $(document).unbind('click'); 1211 1212 // hide the dialog 1213 this.$id.attr('aria-hidden', 'true'); 1214 1215 // set focus on the focus target 1216 //this.$target.focus(); 1217 1218} // end showDlg() 1219 1220//function to highlight days with performances or valid information 1221//to prevent rewriting the calendar each time a date is added, popGrid() should be called after all dates have been added 1222swDatepicker.prototype.addHighlightDay = function (date) { 1223 var datesplit = String(date).split("/"); 1224 for(var i = 0;i < datesplit.length; i++){ 1225 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1226 } 1227 date = datesplit.join("/"); 1228 if (datesplit.length != 3) { 1229 //date didn't come in in m/d/yyyy format, kick it back in the console 1230 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1231 console.log(date); 1232 return; 1233 1234 } 1235 this.highlightDates.push(date); 1236 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1237 $("#" + this.calendarName + "-day" + datesplit[1]).addClass("highlight-day"); 1238 } 1239} 1240swDatepicker.prototype.addDateInfoBox = function (date, infoBoxText) { 1241 var datesplit = String(date).split("/"); 1242 for(var i = 0;i < datesplit.length; i++){ 1243 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1244 } 1245 date = datesplit.join("/"); 1246 if (datesplit.length != 3) { 1247 //date didn't come in in m/d/yyyy format, kick it back in the console 1248 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1249 console.log(date); 1250 return; 1251 1252 } 1253 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1254 $("#" + this.calendarName + "-day" + datesplit[1]).append('<span class="date-info-box">' + infoBoxText + '</span>'); 1255 } 1256} 1257swDatepicker.prototype.addDateSubNote = function (date, noteText) { 1258 var datesplit = String(date).split("/"); 1259 for(var i = 0;i < datesplit.length; i++){ 1260 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1261 } 1262 date = datesplit.join("/"); 1263 if (datesplit.length != 3) { 1264 //date didn't come in in m/d/yyyy format, kick it back in the console 1265 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1266 console.log(date); 1267 return; 1268 1269 } 1270 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1271 var spanClass = this.isMultiplePerformanceIndicator ? 'date-info-box date-sub-note multiple-performancetime-subnote' : 'date-info-box date-sub-note'; 1272 $("#" + this.calendarName + "-day" + datesplit[1]).append('<span class="' + spanClass + '">' + noteText + '</span>'); 1273 } 1274} 1275swDatepicker.prototype.setDaySoldOut = function (date) { 1276 var datesplit = String(date).split("/"); 1277 for(var i = 0;i < datesplit.length; i++){ 1278 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1279 } 1280 date = datesplit.join("/"); 1281 if (datesplit.length != 3) { 1282 //date didn't come in in m/d/yyyy format, kick it back in the console 1283 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1284 console.log(date); 1285 return; 1286 1287 } 1288 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1289 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('sold-out'); 1290 1291 this.addDateInfoBox(date, "Sold Out"); 1292 $("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 1293 } 1294} 1295swDatepicker.prototype.setcustomStatus = function (date,showPhoneNumber,currenStatus) { 1296 var datesplit = String(date).split("/"); 1297 for(var i = 0;i < datesplit.length; i++){ 1298 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1299 } 1300 date = datesplit.join("/"); 1301 if (datesplit.length != 3) { 1302 //date didn't come in in m/d/yyyy format, kick it back in the console 1303 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1304 console.log(date); 1305 return; 1306 1307 } 1308 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1309 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('sold-out'); 1310 var phoneNumber = " <br> [email protected] " 1311 if (!showPhoneNumber) 1312 phoneNumber=""; 1313 this.addDateInfoBox(date, currenStatus +phoneNumber); 1314 1315 $("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 1316 } 1317} 1318swDatepicker.prototype.setDayLimitedAvailabilty = function (date) { 1319 var datesplit = String(date).split("/"); 1320 for(var i = 0;i < datesplit.length; i++){ 1321 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1322 } 1323 date = datesplit.join("/"); 1324 if (datesplit.length != 3) { 1325 //date didn't come in in m/d/yyyy format, kick it back in the console 1326 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1327 console.log(date); 1328 return; 1329 1330 } 1331 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1332 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('limited-availability'); 1333 1334 this.addDateSubNote(date, 'Selling Quickly'); 1335 //$("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 1336 } 1337 if($(".limited-availability-legend-item").length == 0){ 1338 1339 $(".calendar-notes-wrap").append('<div class="limited-availability-legend-item"><span classs="calendar-limited-availability-legend-icon">!</span> - Selling Quickly</div>') 1340 1341 // $("#streamlinedCalendarLimitedAvailabilityLegend").append('<div class="limited-availability-legend-item"><span class="calendar-limited-availability-legend-icon">!</span> - Selling Quickly</div>') 1342 } 1343} 1344swDatepicker.prototype.setMultiplePerformanceTimes = function (date) { 1345 var datesplit = String(date).split("/"); 1346 for(var i = 0;i < datesplit.length; i++){ 1347 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1348 } 1349 1350 date = datesplit.join("/"); 1351 if (datesplit.length != 3) { 1352 //date didn't come in in m/d/yyyy format, kick it back in the console 1353 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1354 return; 1355 1356 } 1357 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1358 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('multipleperformancetimes'); 1359 1360 } 1361 if($(".multiple-performancetimes-notes").length == 0){ 1362 1363 } 1364 1365} 1366swDatepicker.prototype.setMutedDay = function (date) { 1367 var datesplit = String(date).split("/"); 1368 for(var i = 0;i < datesplit.length; i++){ 1369 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1370 } 1371 date = datesplit.join("/"); 1372 if (datesplit.length != 3) { 1373 //date didn't come in in m/d/yyyy format, kick it back in the console 1374 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1375 return; 1376 1377 } 1378 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1379 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('muted'); 1380 } 1381} 1382swDatepicker.prototype.clearMutedDay = function (date) { 1383 var datesplit = String(date).split("/"); 1384 for(var i = 0;i < datesplit.length; i++){ 1385 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1386 } 1387 date = datesplit.join("/"); 1388 if (datesplit.length != 3) { 1389 //date didn't come in in m/d/yyyy format, kick it back in the console 1390 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1391 return; 1392 1393 } 1394 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1395 $("#" + this.calendarName + "-day" + datesplit[1]).removeClass('muted'); 1396 } 1397} 1398swDatepicker.prototype.setCouponMutedDay = function (date) { 1399 var datesplit = String(date).split("/"); 1400 for(var i = 0;i < datesplit.length; i++){ 1401 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1402 } 1403 date = datesplit.join("/"); 1404 if (datesplit.length != 3) { 1405 //date didn't come in in m/d/yyyy format, kick it back in the console 1406 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1407 return; 1408 1409 } 1410 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1411 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('coupon-muted'); 1412 } 1413}
1414swDatepicker.prototype.setPasswordHiddenDay = function (date) { 1415 var datesplit = String(date).split("/"); 1416 for(var i = 0;i < datesplit.length; i++){ 1417 datesplit[i] = datesplit[i].replace(/^0+/, ''); 1418 } 1419 date = datesplit.join("/"); 1420 if (datesplit.length != 3) { 1421 //date didn't come in in m/d/yyyy format, kick it back in the console 1422 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 1423 return; 1424 1425 } 1426 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 1427 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('password-hidden'); 1428 $("#" + this.calendarName + "-day" + datesplit[1]).removeClass('highlight-day'); 1429 } 1430} 1431swDatepicker.prototype.clearAllMutedDays = function () { 1432 $(".muted").removeClass('muted'); 1433} 1434swDatepicker.prototype.clearHighlightDays = function () { 1435 this.highlightDates = []; 1436 this.highlightDays(); 1437} 1438//highlights all days in the highlightDates array 1439swDatepicker.prototype.highlightDays = function () { 1440 $("#" + this.calendarName + " .highlight-day").removeClass("highlight-day"); 1441 var curYear = this.year; 1442 var curMonth = this.month; 1443 var calName = this.calendarName; 1444 var IEFix = new RegExp(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g); 1445 1446 this.highlightDates.forEach(function (o, i, a) { 1447 var datesplit = o.split("/"); 1448 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 1449 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '')).addClass("highlight-day"); 1450 } 1451 }); 1452 this.setColors(); 1453} 1454swDatepicker.prototype.setColors = function () { 1455 /* 1456 Custom color functionality. Utilized by dropping calendar-colors.txt file in root of custom folder 1457 requires json content of text file formatted as follows: 1458 { 1459 "events": 1460 {"528": 1461 [ 1462 {"date":"12/1/2025", "color": "#ccc"}, 1463 {"date":"12/2/2025", "color": "#ccc"} 1464 ] 1465 , 1466 "529": 1467 [ 1468 {"date":"12/8/2025", "color": "#ccc"}, 1469 {"date":"12/9/2025", "color": "#ccc"} 1470 ] 1471 } 1472 , 1473 "bundles":[], 1474 "generic": 1475 {"dates": 1476 [ 1477 {"date":"12/23/2025", "color": "#def"}, 1478 {"date":"12/22/2025", "color": "#1a1"} 1479 ] 1480 , 1481 "weekdays": 1482 [ 1483 {"day":"Saturday", "color": "#2a2"}, 1484 {"day":"Thursday", "color": "#3a3"} 1485 ] 1486 } 1487 } 1488 } 1489 */ 1490 var thisDP = this; 1491 try{ 1492 $.getJSON("/calendar-colors.txt") 1493 .done(function (data) { 1494 thisDP.renderColors(data); 1495 }) 1496 .fail(function (jqxhr, textStatus, error) { 1497 console.log("No Custom Calendar Colors Found"); 1498 return; 1499 }); 1500 }catch(e){ 1501 console.log("parsing error:"); 1502 console.log(e); 1503 return; 1504 } 1505} 1506swDatepicker.prototype.renderColors = function (colorData) { 1507 var curYear = this.year; 1508 var curMonth = this.month; 1509 var calName = this.calendarName; 1510 var IEFix = new RegExp(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g); 1511 //set generic colors 1512 if(colorData.generic){ 1513 if(colorData.generic.dates.length > 0){ 1514 colorData.generic.dates.forEach(function (o, i, a) { 1515 var datesplit = o.date.split("/"); 1516 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 1517 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 1518 } 1519 }); 1520 } 1521 if(colorData.generic.weekdays && colorData.generic.weekdays.length > 0){ 1522 colorData.generic.weekdays.forEach(function (o, i, a) { 1523 $("td[headers*=" + o.day + "] .calendar-day").css("background-color", o.color); 1524 }); 1525 } 1526 } 1527 if(colorData.events && colorData.events[this.eventID] && this.eventID !== -1){
1528 colorData.events[this.eventID].forEach(function (o, i, a) { 1529 var datesplit = o.date.split("/"); 1530 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 1531 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 1532 } 1533 }); 1534 } 1535 if(colorData.bundles && colorData.bundles[this.bundleID] && this.bundleID !== -1){ 1536 colorData.bundles[this.bundleID].forEach(function (o, i, a) { 1537 var datesplit = o.date.split("/"); 1538 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 1539 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 1540 } 1541 }); 1542 } 1543} 1544swDatepicker.prototype.fetchDates = function(){ 1545 var thisCalendar = this; 1546 var haveDates = thisCalendar.fetchLocalDates(); 1547 if (thisCalendar.categoryID >= 0) 1548 haveDates = false; 1549 this.clearHighlightDays(); 1550 if(haveDates){ 1551 //valid local dates stored 1552 try{ 1553 haveDates = JSON.parse(haveDates); 1554 if (haveDates.length > 0) { 1555 haveDates.forEach(function(o){ 1556 thisCalendar.addHighlightDay(o); 1557 }) 1558 thisCalendar.highlightDays(); 1559 } 1560 } catch (e) { 1561 console.log("Failed to grab dates. Date object not valid: ", haveDates); 1562 console.log(e); 1563 } 1564 } else { 1565 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 1566 { 1567 action: thisCalendar.type, 1568 calMonth: thisCalendar.activeMonth, 1569 iEvent: thisCalendar.eventID, 1570 iBundle: thisCalendar.bundleID, 1571 iCategory : thisCalendar.categoryID, 1572 cp : thisCalendar.corporatePartnerPage 1573 }) 1574 .done(function (data) { 1575 thisCalendar.storeDates(data.performancedates); 1576 try { 1577 if (data.performancedates.length > 0) { 1578 data.performancedates.forEach(function (o) { 1579 1580 thisCalendar.addHighlightDay(o); 1581 }) 1582 thisCalendar.highlightDays(); 1583 } 1584 } catch (e) { 1585 console.log("Failed to grab dates. Date object not valid: " + haveDates); 1586 console.log(e); 1587 } 1588 $(".calendar-loading").hide(); 1589 }) 1590 .fail(function (jqxhr, textStatus, error) { 1591 var err = textStatus + ", " + error; 1592 console.log("Request Failed: " + err); 1593 $(".calendar-loading").hide(); 1594 }); 1595 } 1596} 1597swDatepicker.prototype.getCalendarDetails = function(){ 1598 var thisCalendar = this; 1599 this.clearHighlightDays(); 1600 $("#" + this.calendarName).removeClass("has-muted-days"); 1601 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 1602 { 1603 action: thisCalendar.type, 1604 calMonth: thisCalendar.activeMonth, 1605 iEvent: thisCalendar.eventID, 1606 iBundle: thisCalendar.bundleID, 1607 iCategory : thisCalendar.categoryID, 1608 cp : thisCalendar.corporatePartnerPage, 1609 bValidCoupon : thisCalendar.bValidCoupon, 1610 couponCode : thisCalendar.couponCode 1611 }) 1612 .done(function (data) { 1613 //to save on request time, we need to resolve the data on the client a bit before we store it 1614 var performanceDates = []; 1615 data.performanceDateData.forEach(function(dd){ 1616 1617 if(dd.DoNotShowPublic == 0){ 1618 var detailsObj = {}; 1619 var currentDateIndex = fetchDateIndex(dd.CalendarDate, performanceDates); 1620 if(currentDateIndex == -1){ 1621 detailsObj.date = dd.CalendarDate; 1622 detailsObj.performances = []; 1623 detailsObj.performances.push(dd.PerformanceCode); 1624 detailsObj.defaultPrice = dd.LowestDefaultPrice; 1625 detailsObj.PerformanceName = dd.PerformanceName; 1626 detailsObj.PerformanceTime = dd.PerfTime; 1627 detailsObj.PerformanceStartTimeAlias = dd.PerformanceStartTimeAlias; 1628 detailsObj.DisplayType = dd.DisplayType; 1629 detailsObj.CalendarViewShowPrice = dd.CalendarViewShowPrice; 1630 detailsObj.CalendarViewShowPerformanceName = dd.CalendarViewShowPerformanceName; 1631 detailsObj.CalendarViewShowPerformanceTime = dd.CalendarViewShowPerformanceTime; 1632 detailsObj.CalendarViewShowBuyButton = dd.CalendarViewShowBuyButton; 1633 detailsObj.defaultPricingCode = dd.LowestDefaultPricingCode; 1634 detailsObj.secondaryPrice = dd.LowestSecondaryPrice; 1635 detailsObj.secondaryPricingCode =dd.LowestSecondaryPricingCode; 1636 detailsObj.NoCouponAvailable = dd.NoCouponAvailable; 1637 detailsObj.passwordMatch = dd.passwordMatch; 1638 detailsObj.qualifierPasswordMatch = dd.qualifierPasswordMatch; 1639 detailsObj.hasPassword = dd.hasPassword; 1640 detailsObj.hasQualifierPassword = dd.hasQualifierPassword; 1641 detailsObj.hasCoupons = dd.hasCoupons; 1642 detailsObj.IsSalesPeriodEnded = dd.IsSalesPeriodEnded; 1643 detailsObj.SaleIcon = dd.SaleIcon; 1644 detailsObj.BSaleIcon = dd.BSaleIcon; 1645 1646 detailsObj.hasQualifiers = dd.hasQualifiers;
1647 performanceDates.push(detailsObj) 1648 1649 }else{ 1650 performanceDates[currentDateIndex].performances.push(dd.PerformanceCode); 1651 performanceDates[currentDateIndex].NoCouponAvailable = dd.NoCouponAvailable; 1652 performanceDates[currentDateIndex].passwordMatch = dd.passwordMatch; 1653 performanceDates[currentDateIndex].acMatch = dd.acMatch; 1654 performanceDates[currentDateIndex].qualifierPasswordMatch = dd.qualifierPasswordMatch; 1655 performanceDates[currentDateIndex].hasPassword = dd.hasPassword; 1656 performanceDates[currentDateIndex].hasQualifierPassword = dd.hasQualifierPassword; 1657 performanceDates[currentDateIndex].hasCoupons = dd.hasCoupons; 1658 performanceDates[currentDateIndex].PerformanceName = dd.PerformanceName; 1659 performanceDates[currentDateIndex].PerformanceTime = dd.PerfTime; 1660 performanceDates[currentDateIndex].PerformanceStartTimeAlias = dd.PerformanceStartTimeAlias; 1661 performanceDates[currentDateIndex].CalendarViewShowPrice = dd.CalendarViewShowPrice; 1662 performanceDates[currentDateIndex].CalendarViewShowPerformanceName = dd.CalendarViewShowPerformanceName; 1663 performanceDates[currentDateIndex].CalendarViewShowPerformanceTime = dd.CalendarViewShowPerformanceTime; 1664 performanceDates[currentDateIndex].CalendarViewShowBuyButton = dd.CalendarViewShowBuyButton; 1665 performanceDates[currentDateIndex].IsSalesPeriodEnded = dd.IsSalesPeriodEnded; 1666 performanceDates[currentDateIndex].SaleIcon = dd.SaleIcon; 1667 performanceDates[currentDateIndex].BSaleIcon = dd.BSaleIcon; 1668 performanceDates[currentDateIndex].hasQualifiers = dd.hasQualifiers; 1669 //check for lowest price 1670 if(performanceDates[currentDateIndex].defaultPrice > dd.LowestDefaultPrice && dd.LowestDefaultPrice != null){ 1671 performanceDates[currentDateIndex].defaultPrice = dd.LowestDefaultPrice; 1672 performanceDates[currentDateIndex].defaultPricingCode = dd.LowestDefaultPricingCode; 1673 } 1674 if(performanceDates[currentDateIndex].hasCoupons == 1 && performanceDates[currentDateIndex].defaultPrice < dd.LowestDefaultPrice && dd.LowestDefaultPrice != null && false){ 1675 performanceDates[currentDateIndex].defaultPrice = dd.LowestDefaultPrice; 1676 performanceDates[currentDateIndex].defaultPricingCode = dd.LowestDefaultPricingCode; 1677 } 1678 if(performanceDates[currentDateIndex].secondaryPrice > dd.LowestSecondaryPrice && dd.LowestSecondaryPrice != null){ 1679 performanceDates[currentDateIndex].secondaryPrice = dd.LowestSecondaryPrice; 1680 performanceDates[currentDateIndex].secondaryPricingCode = dd.LowestSecondaryPricingCode; 1681 } 1682 1683 1684 } 1685 //set limited availaibility by matching up results from query with performances 1686 for(perf in data.performances){ 1687 if(data.performances[perf].id == dd.PerformanceID){ 1688 data.performances[perf].LimitedAvailability = dd.LimitedAvailability; 1689 data.performances[perf].TimeZone = dd.TimeZone.replace('"', ""); 1690 data.performances[perf].SingleAreaVenueAreaID = dd.SingleAreaVenueAreaID; 1691 data.performances[perf].NoCouponAvailable = dd.NoCouponAvailable; 1692 data.performances[perf].passwordMatch = dd.passwordMatch; 1693 data.performances[perf].acMatch = dd.acMatch; 1694 data.performances[perf].qualifierPasswordMatch = dd.qualifierPasswordMatch; 1695 data.performances[perf].hasPassword = dd.hasPassword; 1696 data.performances[perf].hasQualifierPassword = dd.hasQualifierPassword; 1697 } 1698 } 1699 } 1700 1701 }) 1702 1703 data.performanceDates = performanceDates; 1704 delete data.performanceDateData; 1705 try { 1706 if (thisCalendar.couponCode != "" && $("#couponCode").length > 0) 1707 { 1708 if($("#coupon-notify").length > 0) 1709 $("#coupon-notify").remove(); 1710 1711 var notifyMessage = document.createElement("div"); 1712 notifyMessage.setAttribute("id","coupon-notify"); 1713 notifyMessage.setAttribute("class",data.hasValidCoupon ? 'coupon-notify-message' : 'coupon-error-message'); 1714 notifyMessage.innerHTML = (data.hasValidCoupon ? "Code <b>" + thisCalendar.couponCode + "</b> has been applied to valid dates and times." : "The code entered is either invalid, or no longer available."); 1715 $("#plCalendar").prepend(notifyMessage); 1716 window.scrollTo(0,0); 1717 } 1718 1719 thisCalendar.doCalendarDetailed(data); 1720 } catch (e) { 1721 console.log("Failed to parse details. Date object not valid: ", data); 1722 console.log(e); 1723 } 1724 }) 1725 .fail(function (jqxhr, textStatus, error) { 1726 var err = textStatus + ", " + error; 1727 console.log("Request Failed: " + err); 1728 }); 1729} 1730swDatepicker.prototype.doCalendarDetailed = function(detailData){ 1731 var thisCalendar = this; 1732 this.detailData = detailData; 1733 var defaultPricingLegend = [], secondaryPricingLegend = [];
1734 detailData.performanceDates.forEach(function(d){ 1735 thisCalendar.addHighlightDay(d.date); 1736 if (d.NoCouponAvailable > 0) 1737 thisCalendar.setCouponMutedDay(d.date); 1738 1739 //check if date sold out 1740 var dateSoldOut = true; 1741 var customStatus = false; 1742 var showPhoneNumber =false; 1743 var dateLimitedAvailability = false; 1744 var performanceStatus=""; 1745 var performanceOnSale = false; 1746 var IsSalesPeriodEnded = false; 1747 var aggregatedMentaInfo = { 1748 buttonVisible: false, 1749 buttonText: "", 1750 buttonUrl: "", 1751 totalCount: 0 1752 }; 1753 1754 var isMentaResaleAvailable = false; 1755 var performanceTimesLength = 0; 1756 var QualiferButton = false; 1757 d.performances.forEach(function(datePerformance){ 1758 var performanceKey = String(datePerformance).toLowerCase(); 1759 var currentPerformance = detailData.performances[performanceKey]; 1760 1761 if (!currentPerformance) { 1762 var perfIndex = d.performances.indexOf(datePerformance); 1763 if (perfIndex !== -1) { 1764 d.performances.splice(perfIndex, 1); 1765 } 1766 console.log("Date Trimmed, child performance not contained in performance data: " + datePerformance); 1767 return; 1768 } 1769 1770 //let currentPerformance = detailData.performances[String(datePerformance).toLowerCase()]; 1771 performanceTimesLength ++; 1772 1773 if(detailData.performances[String(datePerformance).toLowerCase()] && detailData.performances[String(datePerformance).toLowerCase()].status == "On Sale"){ 1774 dateSoldOut = false; 1775 performanceOnSale=true; 1776 if(currentPerformance.LimitedAvailability == 1) 1777 dateLimitedAvailability = true; 1778 1779 IsSalesPeriodEnded = currentPerformance.IsSalesPeriodEnded==1 1780 } 1781 else{ 1782 1783 if ((currentPerformance.status != "Sold Out") && (currentPerformance.status != "On Sale") ){ 1784 1785 customStatus=true; 1786 performanceStatus=currentPerformance.status; 1787 dateSoldOut = false; 1788 //dateLimitedAvailability=false; 1789 if ( currentPerformance.bSalePhone==1 || currentPerformance.SalePhone==1){ 1790 showPhoneNumber=true; 1791 } 1792 } 1793 var mentaMarketplace = currentPerformance.MentaMarketplace; 1794 var hasMentaOption = currentPerformance.IsMentaEnabled == 1 && mentaMarketplace && mentaMarketplace.buttonVisible; 1795 1796 if (hasMentaOption) { 1797 var availableCount = parseInt(mentaMarketplace.totalCount, 10); 1798 if (!isNaN(availableCount) && availableCount > 0) { 1799 aggregatedMentaInfo.totalCount += availableCount; 1800 } 1801 if (mentaMarketplace.buttonText && aggregatedMentaInfo.buttonText === "") { 1802 aggregatedMentaInfo.buttonText = mentaMarketplace.buttonText; 1803 } 1804 if (mentaMarketplace.buttonUrl && aggregatedMentaInfo.buttonUrl === "") { 1805 aggregatedMentaInfo.buttonUrl = mentaMarketplace.buttonUrl; 1806 } 1807 aggregatedMentaInfo.buttonVisible = true; 1808 dateSoldOut = false; 1809 showPhoneNumber=false; 1810 customStatus=true; 1811 } 1812 } 1813 1814 // If date is sold out or custom status (not 'on sale'), check if qualifier access code or password match 1815 if (dateSoldOut || customStatus) { 1816 if (currentPerformance.acMatch == 1 || (currentPerformance.qualifierPasswordMatch == 1 && currentPerformance.hasQualifierPassword == 1)) { 1817 dateSoldOut = false; 1818 customStatus = false; 1819 performanceOnSale = true; 1820 showPhoneNumber = false; 1821 } 1822 } 1823 // If date is sold out or custom status (not 'on sale'), check if it has a public qualifier -- hasQualifiers is set on CalendarRequests.asp when qualifiers exist for performance 1824 if (currentPerformance.hasQualifiers) { 1825 dateSoldOut = false; 1826 customStatus = false; 1827 performanceOnSale = true; 1828 showPhoneNumber = false; 1829 QualiferButton = true; 1830 // If performance has qualifier but status is "On Sale", do not show "Premium Access" text on calendar date 1831 if (currentPerformance.status == "On Sale") { 1832 QualiferButton = false; 1833 } 1834 1835 } 1836 }) 1837 1838 if (aggregatedMentaInfo.buttonVisible && aggregatedMentaInfo.buttonText === "") { 1839 aggregatedMentaInfo.buttonText = "Official Resale Available"; 1840 } 1841 var hasMentaCtaForDate = aggregatedMentaInfo.buttonVisible && (aggregatedMentaInfo.totalCount > 0 || aggregatedMentaInfo.buttonUrl !== ""); 1842 isMentaResaleAvailable = hasMentaCtaForDate && !performanceOnSale; 1843 d.MentaMarketplace = aggregatedMentaInfo; 1844 1845 if(dateLimitedAvailability && !dateSoldOut){ 1846 thisCalendar.setDayLimitedAvailabilty(d.date); 1847 } 1848 if (thisCalendar.isMultiplePerformanceIndicator == 1 && performanceTimesLength > 1) { 1849 thisCalendar.setMultiplePerformanceTimes(d.date); 1850 } 1851 if ( IsSalesPeriodEnded) { 1852 performanceStatus=d.SaleIcon; 1853 } 1854 else{ 1855 if(isMentaResaleAvailable && !performanceOnSale){ 1856 1857 thisCalendar.addDateSubNote(d.date, 'Sold Out'); 1858 //thisCalendar.setDaySoldOut(d.date); 1859 //thisCalendar.addDateInfoBox(d.date, "Sold Out"); 1860 thisCalendar.configureMentaSettings(d); 1861 } 1862 else{ 1863 performanceStatus=d.BSaleIcon; 1864 } 1865 1866 } 1867 1868 if (performanceStatus == null || performanceStatus == "") 1869 performanceStatus="sold out"; 1870 1871 if(dateSoldOut){ 1872 thisCalendar.setDaySoldOut(d.date); 1873 }else{ 1874 if ( (customStatus && !dateLimitedAvailability && !performanceOnSale && !isMentaResaleAvailable) || IsSalesPeriodEnded) 1875 { 1876 thisCalendar.setcustomStatus(d.date,showPhoneNumber,performanceStatus) 1877 } 1878 else{ 1879 //date not sold out, add details, add to legend if one exists 1880 var detailString = ""; 1881 1882 // if the price option is checked in event landing page in the admin 1883 if(d.CalendarViewShowPrice != 0){ 1884 //for now, we'll just add the pricing, this would be a spot to modify what is displayed on the dates by changing the contents of this string 1885 if(d.defaultPrice != null){ 1886 if (QualiferButton) { // SHOWDEV-22142 - If date has public qualifier, show qualifier text (Premium Access) instead of price and buy button 1887 detailString = detailString + "<span class='display-perfbuybutton'>Premium Access</span>"; 1888 }else { 1889 1890 detailString = "<span class='display-perfprice'>" + thisCalendar.currencySymbol + d.defaultPrice.toFixed(2).replace('.00','') + "</span>"; 1891 1892 } 1893 1894 if(defaultPricingLegend.indexOf(d.defaultPricingCode) === -1) 1895 defaultPricingLegend.push(d.defaultPricingCode); 1896 } 1897 if(d.secondaryPricingCode != "" && d.secondaryPricingCode != null){ 1898 if(secondaryPricingLegend.indexOf(d.secondaryPricingCode) === -1) 1899 secondaryPricingLegend.push(d.secondaryPricingCode); 1900 1901 if (d.DisplayType === "calendar" || d.DisplayType === "streamlined") { 1902 1903 detailString = "<span class='display-perfprice-withchild'>" + thisCalendar.currencySymbol + d.secondaryPrice.toFixed(2).replace('.00','') + "/</span>" + detailString; 1904 1905 } 1906 } 1907 } 1908 if(d.CalendarViewShowPerformanceName != 0){ 1909 detailString = detailString + "<span class='display-perfname'>" + d.PerformanceName + "</span> "; 1910 } 1911 1912 if(d.CalendarViewShowPerformanceTime != 0){ 1913 if(d.PerformanceStartTimeAlias != ""){ // Performance Alias time is present 1914 detailString = detailString + " <span class='display-perft
1914ime'>" + d.PerformanceStartTimeAlias + "</span>"; 1915 } else { 1916 detailString = detailString + " <span class='display-perftime'>" + d.PerformanceTime + "</span>"; 1917 } 1918 1919 } 1920 if(d.CalendarViewShowBuyButton != 0){ 1921 var styleString = ""; 1922 if (d.DisplayType === "streamlined") 1923 styleString = " style='width: 100%;'"; 1924 var buttonText = (isMentaResaleAvailable && d.OverrideBuyTicketsButtonText) ? d.OverrideBuyTicketsButtonText : thisCalendar.buyTicketsButtonText; 1925 detailString = detailString + "<span class='button display-perfbuybutton'"+styleString+">" + buttonText + "</span>"; 1926 } 1927 1928 thisCalendar.addDateInfoBox(d.date, detailString); 1929 } 1930 } 1931 1932 }) 1933 //for now, we only generate the legend if there are one or two prices pesent 1934 if(defaultPricingLegend.length === 1 && secondaryPricingLegend.length === 1){ 1935 $("#calendarLegend").html(secondaryPricingLegend[0] +" / " + defaultPricingLegend[0]) 1936 1937 $("#calendarLegend").show(); 1938 }else{ 1939 if(defaultPricingLegend.length === 1){ 1940 $("#calendarLegend").html(defaultPricingLegend[0]) 1941 1942 $("#calendarLegend").show(); 1943 }else{ 1944 $("#calendarLegend").hide(); 1945 } 1946 } 1947 if(typeof(setFilterOptions) == 'function'){ 1948 setFilterOptions(thisCalendar); 1949 } 1950 if (detailData.hasValidCoupon) { 1951 $("#plCalendar").append("<input type='hidden' id='hasValidCoupon' value='1' />"); 1952 } else { 1953 $("#plCalendar").append("<input type='hidden' id='hasValidCoupon' value='0' />"); 1954 } 1955 $(".calendar-loading").hide(); 1956} 1957swDatepicker.prototype.configureMentaSettings = function (dateDetail) { 1958 // Set Menta Resale Settings 1959 1960} 1961 1962swDatepicker.prototype.getFirstDate = function(defaultMonth){ 1963 var thisCalendar = this; 1964 //this should only happen once on calendar load - currently only enabled for bundles 1965 if(thisCalendar.bundleID == 0 || thisCalendar.bundleID == -1) 1966 return defaultMonth; //currently only developed for bundles TODO: add event, category, standard support. 1967 1968 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 1969 { 1970 action: 'initialBundleDate', 1971 iBundle: thisCalendar.bundleID, 1972 cp : thisCalendar.corporatePartnerPage 1973 }) 1974 .done(function (data) { 1975 try { 1976 if (data.performancedates.length > 0) { 1977 1978 1979 var firstMonth = Number(String(data.performancedates).split("/")[0]) - 1; 1980 var firstYear = Number(String(data.performancedates).split("/")[2]); 1981 thisCalendar.month = firstMonth - 1; //to make this simple, we're using the showNextMonth() function, which means we need to set the month to 1 less than our target, as that function increments the month itself 1982 thisCalendar.year = firstYear; 1983 thisCalendar.showNextMonth(); 1984 }else{ 1985 return defaultMonth; 1986 } 1987 }catch(e){ 1988 console.log("getFirstDate returned invalid date. Default used"); 1989 console.log(e); 1990 return defaultMonth; 1991 } 1992 }) 1993 .fail(function (jqxhr, textStatus, error) { 1994 var err = textStatus + ", " + error; 1995 console.log("Request Failed: " + err); 1996 }); 1997} 1998swDatepicker.prototype.fetchLocalDates = function () { 1999 //utliize storage to store months 2000 var CalendarExpireTime = new Date().getTime(); var isExpired = false; var datesData = ""; 2001 var calendarIDString = this.calendarName + this.type + this.eventID + this.bundleID + "-" + this.corporatePartnerPage + "_" + this.activeMonth; 2002 try { 2003 //check for local storage support 2004 isExpired = CalendarExpireTime > Number(localStorage.getItem("CalendarExpireTime_" + calendarIDString)); 2005 if (isExpired) { 2006 //item expired, clear local results 2007 localStorage.setItem("ShowareDates_" + calendarIDString, ""); 2008 localStorage.setItem("CalendarExpireTime_" + calendarIDString, CalendarExpireTime + (1000 * 60 * 30)); //item information expires after 30 minutes 2009 return false; 2010 } 2011 localStorage.setItem("CalendarExpireTime_" + calendarIDString, CalendarExpireTime + (1000 * 60 * 30)); //item information expires after 30 minutes 2012 if (localStorage.getItem("ShowareDates_" + calendarIDString) != null && localStorage.getItem("ShowareDates_" + calendarIDString) != "" && localStorage.getItem("ShowareDates_" + calendarIDString) != []) { 2013 return localStorage.getItem("ShowareDates_" + calendarIDString); 2014 } else { 2015 //date info not stored 2016 return false; 2017 } 2018 } catch (e) { 2019 return false; 2020 } 2021} 2022swDatepicker.prototype.storeDates = function (dateData) { 2023 2024 var calendarIDString = this.calendarName + this.type + this.eventID + this.bundleID + "-" + this.corporatePartnerPage + "_" + this.activeMonth; 2025 try { 2026 localStorage.setItem("ShowareDates_" + calendarIDString, JSON.stringify(dateData)); 2027 } catch (e) { 2028 //no local storage 2029 } 2030} 2031swDatepicker.prototype.getDateRangeEvents = function (dateRangeData) { 2032 var thisCalendar = this; 2033 try{ 2034 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 2035 { 2036 action: 'getDateRangeEvents', 2037 dateRange: JSON.stringify(dateRangeData), 2038 }) 2039 .done(function (data) { 2040 try { 2041 thisCalendar.dateRangeEvents = data; 2042 }catch(e){ 2043 console.log("getDateRangeEvents returned invali
2043d response."); 2044 console.log(data, e); 2045 return []//return empty array; 2046 } 2047 }) 2048 .fail(function (jqxhr, textStatus, error) { 2049 var err = textStatus + ", " + error; 2050 console.log("Request Failed: " + err); 2051 }); 2052 2053 }catch(e){ 2054 console.log("Unable to fetch date range events:", e) 2055 } 2056} 2057swDatepicker.prototype.clearDateRange = function () { 2058 this.fromDateRange = ''; 2059 this.toDateRange = ''; 2060} 2061function fetchDateIndex(dateString, dateObjectArray){ 2062 try{ 2063 for(var i = 0;i < dateObjectArray.length;i++){ 2064 if(dateObjectArray[i].date == dateString){ 2065 return i; 2066 break; 2067 } 2068 } 2069 return -1; 2070 }catch(e){ 2071 //this function requires specific objects with a date property, it will fail otherwise and we'll just return what one would expect from a failed indexof 2072 return -1; 2073 } 2074} 2075function swapMonthDay(d){ 2076 //expects dd/mm/yyyy format 2077 try{ 2078 let splitDate = d.split("/"); 2079 let newDate = splitDate[1] + '/' + splitDate[0] + "/" + splitDate[2]; 2080 return newDate; 2081 }catch(e){ 2082 console.log("could not swap date:",d,e); 2083 return d; 2084 } 2085} 2086 2087</script>
2087 2088
2088<script type="text/javascript"> 2089 if (typeof localStorage === 'object') { 2090 try { 2091 localStorage.setItem('localStorage', 1); 2092 localStorage.removeItem('localStorage'); 2093 } catch (e) { 2094 Storage.prototype._setItem = Storage.prototype.setItem; 2095 Storage.prototype.setItem = function () { }; 2096 console.log("local storage not availalbe, data tracking limited"); 2097 } 2098 } 2099 function persistDataLayer(layerName, pageVal) { 2100 var ShoWareExpTime = new Date().getTime(); var isExpired = false; 2101 2102 try { 2103 isExpired = ShoWareExpTime > Number(localStorage.getItem("swExpTime")); 2104 if (isExpired) { 2105 removeDataLayer(); 2106 } 2107 localStorage.setItem("swExpTime", ShoWareExpTime + 1000 * 60 * 30); //tag information expires after 30 minutes of inactivity 2108 2109 //grab anything we might have in storage= 2110 var existVal = localStorage.getItem(layerName); 2111 if (pageVal != "") { 2112 //page val trumps all, store it and send it back 2113 localStorage.setItem(layerName, pageVal); 2114 return pageVal; 2115 } else { 2116 //page val was empty, so we'll try to pull a value out of local storage 2117 if (existVal != "" && existVal != null && existVal != undefined && !isExpired) { 2118 return existVal; 2119 } else { 2120 //no value exists, or the values stored have expired; 2121 return ""; 2122 } 2123 } 2124 } catch(e) { 2125 //no local storage, or other error, we'll just return the page value. Calls to this function should assume the possibility of failure as local storage does not work on IOS devices with private browsing enabled. 2126 return pageVal; 2127 } 2128 } 2129 function addDataLayer(layerName, setVal) { 2130 try { 2131 //the data layer MUST be set up before the container is introduced. 2132 //We will rely on future loads to address these variables as they are added after the pageload. 2133 localStorage.setItem(layerName, setVal); 2134 //push data to dataLayer so we can retrieve it with non-load events (clicks, changes, etc...) 2135 dataLayer.push({[layerName]: setVal}); 2136 } 2137 catch (e) { 2138 //local storage failed, or the data layer was not available. 2139 } 2140 } 2141 function removeDataLayer() { 2142 //empty showare data layer from local storage. 2143 for (var i = localStorage.length - 1; i >= 0; i--) { 2144 layerName = localStorage.key(i); 2145 if (layerName.indexOf("Ticketing") > -1) { 2146 localStorage.removeItem(layerName); 2147 } 2148 } 2149 } 2150 function tryParse(jsonString) { 2151 if (jsonString == "" || jsonString == null || jsonString == undefined) { 2152 return ''; 2153 } 2154 try { 2155 JSON.parse(jsonString); 2156 } catch (e) { 2157 console.log(e); 2158 return ''; 2159 } 2160 return JSON.parse(jsonString); 2161 } 2162 </script>
2162 2163 2164
2164<script> 2165 window.dataLayer = window.dataLayer || []; 2166 dataLayer.push({ 2167 'TicketingHasActivePerformances': 'True', 2168 'TicketingPage': 'basket.asp', 2169 'TicketingEventID': persistDataLayer("TicketingEventID", ""), 2170 'TicketingBundleID': persistDataLayer("TicketingBundleID", ""), 2171 'TicketingPerformanceID': persistDataLayer("TicketingPerformanceID", ""), 2172 'TicketingPerformanceCode': persistDataLayer("TicketingPerformanceCode", ""), 2173 'TicketingPerformanceDate': persistDataLayer("TicketingPerformanceDate", ""), 2174 'TicketingOrderID': persistDataLayer("TicketingOrderID", "0"), 2175 'TicketingNewCustomer': persistDataLayer("TicketingNewCustomer", ""), 2176 'TicketingCustomerID': "", 2177 'TicketingCustomerZipCode': persistDataLayer("TicketingCustomerZipCode", ""), 2178 'TicketingCustomerState': persistDataLayer("TicketingCustomerState", ""), 2179 'TicketingCustomerCountry': persistDataLayer("TicketingCustomerCountry", ""), 2180 'TicketingCustomerCity': persistDataLayer("TicketingCustomerCity", ""), 2181 'TicketingCurrencyCode': persistDataLayer("TicketingCurrencyCode", "USD"), 2182 'TicketingOrderTotal': persistDataLayer("TicketingOrderTotal", ""), 2183 'TicketingCoupon': persistDataLayer("TicketingCoupon", ""), 2184 'TicketingPromo': persistDataLayer("TicketingPromo", ""), 2185 'TicketingDiscountAmount': persistDataLayer("TicketingDiscountAmount", ""), //promo code dicount value only 2186 'TicketingHasMixedBasket': persistDataLayer("TicketingHasMixedBasket", ""), 2187 'TicketingOrderSubTotal': persistDataLayer("TicketingOrderSubTotal", ""), 2188 'TicketingItemCount': persistDataLayer("TicketingItemCount", ""), 2189 'TicketingBundleCount': persistDataLayer("TicketingBundleCount", ""), 2190 'TicketingShippingMethod': persistDataLayer("TicketingShippingMethod", ""), 2191 'TicketingIsWillCall': persistDataLayer("TicketingIsWillCall", ""), 2192 'TicketingHeardAbout': persistDataLayer("TicketingHeardAbout", ""), 2193 'TicketingShippingTotal': persistDataLayer("TicketingShippingTotal", ""), 2194 'TicketingTaxTotal': persistDataLayer("TicketingTaxTotal", ""), 2195 'TicketingFeesTotal': persistDataLayer("TicketingFeesTotal", ""), 2196 'TicketingProcessingFee': persistDataLayer("TicketingProcessingFee", ""), 2197 'TicketingTicketFeesTotal': persistDataLayer("TicketingTicketFeesTotal", ""), 2198 'TicketingTicketItems': persistDataLayer("TicketingTicketItems", ""), 2199 'TicketingDonationItems': persistDataLayer("TicketingDonationItems", ""), 2200 'TicketingMembershipItems': persistDataLayer("TicketingMembershipItems", ""), 2201 'TicketingSalesChannel': persistDataLayer("TicketingSalesChannel", ""), 2202 'TicketingPaymentType': persistDataLayer("TicketingPaymentType", ""), 2203 'TicketingEventName': persistDataLayer("TicketingEventName", ""), 2204 'TicketingPerformanceName': persistDataLayer("TicketingPerformanceName", ""), 2205 'TicketingBundleName': persistDataLayer("TicketingBundleName", ""), 2206 'TicketingPromoterID': persistDataLayer("TicketingPromoterID", ""), 2207 'TicketingEventCategories': persistDataLayer("TicketingEventCategories", ""), 2208 'GAClientID': persistDataLayer("GAClientID", ""), 2209 'transactionId': 0, 2210 'transactionTotal': parseFloat(persistDataLayer("transactionTotal", "")), 2211 'transactionAffiliation' : 'CincyTicket', 2212 'transactionTax': parseFloat(persistDataLayer("transactionTax", "")), 2213 'transactionShipping': parseFloat(persistDataLayer("transactionShipping", "")), 2214 'transactionProducts': tryParse(persistDataLayer("transactionProducts", "")) 2215 }); 2216 if(typeof(customDataLayerPush) === "function"){ 2217 customDataLayerPush(); //custom function can be defined in local files and values pushed prior to GTM loading to simplify tag implimentation 2218 } 2219 </script>
2219 2220 2221 <!-- CLIENT Google Tag Manager --> 2222
2222<script>
vendor: 373 bytes, lines 2222-2226
2222(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 2223 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 2224 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 2225 '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 2226 })(window,document,'script','dataLayer','
2226GTM-WZ8HC5
vendor: 3 bytes, line 2226
2226');
2226</script>
2226 2227 <!-- End CLIENT Google Tag Manager --> 2228 2229 <!-- PRIMARY Google Tag Manager --> 2230
2230<script>
vendor: 389 bytes, lines 2230-2234
2230(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 2231 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 2232 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 2233 '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 2234 })(window,document,'script','dataLayer','
2234GTM-MDGF2K
vendor: 3 bytes, line 2234
2234');
2234</script>
2234 2235 <!-- End PRIMARY Google Tag Manager --> 2236 2237 2238 2239
2239<script type="text/javascript"> 2240 var simpleCacheBuster = { 2241 beforeLength: 0, 2242 afterLength: 0 2243 }; 2244 2245 simpleCacheBuster.beforeLength = document.cookie.length; 2246 simpleCacheBuster.afterLength = document.cookie.replace("ShowareVersion=newUI", " ").length; 2247 2248 // If length is the same, then we haven't set this version cookie before, clear the cache. 2249 // If after length is smaller, then we have replaced the same version, do nothing. 2250 // After length shouldn't be greater, do nothing. 2251 if (simpleCacheBuster.beforeLength == simpleCacheBuster.afterLength) { 2252 document.cookie = "ShowareVersion=newUI"; 2253 2254 // This will force browser to reload all includes from server instead of cache. 2255 // Sadly, this doesn't work on Chrome due to a bug that they refuse to fix. 2256 // https://bugs.chromium.org/p/chromium/issues/detail?id=443462 2257 location.reload(true); 2258 } 2259 </script>
2259 2260 2261
2261<script language="JavaScript"> 2262 $(document).ready(function () { 2263 var sessionKey; 2264 sessionKey = ''; 2265 //v1Session variable declared in jq.js 2266 v1Session.setSessionKey(sessionKey); 2267 }); 2268 2269 </script>
2269 2270
2270<script type="text/javascript"> 2271 /* 2272 * Replace all SVG images with inline SVG - allows for image modificcation via CSS 2273 */ 2274 function extractIcons() { 2275 $('img.sw-icon').each(function () { 2276 var $img = $(this); 2277 var imgID = $img.attr('id'); 2278 var imgClass = $img.attr('class'); 2279 var imgURL = $img.attr('src'); 2280 2281 $.get(imgURL, function (data) { 2282 // Get the SVG tag, ignore the rest 2283 var $svg = jQuery(data).find('svg'); 2284 2285 // Add replaced image's ID to the new SVG 2286 if (typeof imgID !== 'undefined') { 2287 $svg = $svg.attr('id', imgID); 2288 } 2289 // Add replaced image's classes to the new SVG 2290 if (typeof imgClass !== 'undefined') { 2291 $svg = $svg.attr('class', imgClass + ' replaced-svg'); 2292 } 2293 // Remove any invalid XML tags as per http://validator.w3.org 2294 $svg = $svg.removeAttr('xmlns:a'); 2295 // Replace image with new SVG 2296 $img.replaceWith($svg); 2297 }, 'xml'); 2298 }); 2299 } 2300 </script>
2300 2301
2301<script type="text/javascript"> 2302 function getGAClientID() { 2303 try { 2304 return ga.getAll()[0].get('clientId'); 2305 } catch (e) { 2306 return "0"; 2307 } 2308 } 2309 function addGAClient(){ 2310 var gaID = getGAClientID(); 2311 if(gaID == "0"){ 2312 //no analytics (unlikely), or analytics not loaded yet 2313 setTimeout(function(){addGAClient()}, 500); 2314 }else{ 2315 try{ 2316 addDataLayer('GAClientID', gaID); 2317 }catch(e){ 2318 console.log("Failed to add data layer object: GAClientID:"); 2319 console.log(e); 2320 } 2321 } 2322 } 2323 addGAClient(); 2324 2325 </script>
2325 2326 2327 2328 2329 <!-- Comodo SSL Seal --> 2330 2331
2331<script type="text/javascript"> 2332 //<![CDATA[ 2333 var tlJsHost = ((window.location.protocol == "https:") ? "https://secure.comodo.com/" : "http://www.trustlogo.com/"); document.write(unescape("%3Cscript src='" + tlJsHost + "trustlogo/javascript/trustlogo.js' type='text/javascript'%3E%3C/script%3E")); 2334 //]]> 2335 </script>
2335 2336 2337
2338<script type="text/javascript"> 2339 2340 var swEnhancedEcommerce = { 2341 basketProducts: [], 2342 myImpressions: [], 2343 myProducts: [], 2344 2345 //Building Up items to pass to analytics 2346 addImpressions: function (name, id, price, category, list, position) { 2347 //adds a product impression to myImpressions - represents a user being presented a specific product 2348 if (price != '') { //price is optional 2349 this.myImpressions.push( 2350 { 2351 'name': name, // Name or ID is required. 2352 'id': id, 2353 'price': price, 2354 'category': category, 2355 'list': list, 2356 'position': position 2357 } 2358 ); 2359 } else { 2360 this.myImpressions.push( 2361 { 2362 'name': name, // Name or ID is required. 2363 'id': id, 2364 'category': category, 2365 'list': list, 2366 'position': position 2367 } 2368 ); 2369 } 2370 }, 2371 2372 addProducts: function (name, id, price, category, position) { 2373 //product clicks represent a product being selected. For showare currently this will always be a single product, but future use may require allowing users to select multiple products 2374 //this represents a click on a product, NOT adding a product to the basket 2375 if (price != '') { //price is optional 2376 2377 this.myProducts.push( 2378 { 2379 'name': name, // Name or ID is required. 2380 'id': id, 2381 'price': price, 2382 'category': category, 2383 'position': position 2384 } 2385 ); 2386 } else { 2387 this.myProducts.push( 2388 { 2389 'name': name, // Name or ID is required. 2390 'id': id, 2391 'category': category, 2392 'position': position 2393 } 2394 ); 2395 } 2396 }, 2397 2398 //object management functions 2399 clearImpressions: function(){ 2400 this.myImpressions = []; 2401 }, 2402 clearProducts: function () { 2403 this.myProducts = []; 2404 }, 2405 2406 //Passing data to analytics 2407 sendImpressions: function(){ 2408 window.dataLayer.push({ 2409 'event': 'impressionsPushed', 2410 'ecommerce': { 2411 'impressions': this.myImpressions 2412 } 2413 }); 2414 }, 2415 sendProducts: function (list) { 2416 //list should be a string of the originator of the product click, for instance a performance list, event list, callout, or other 2417 window.dataLayer.push({ 2418 'event': 'productClick', 2419 'ecommerce': { 2420 'click': { 2421 'actionField': { 'list': list }, // Optional list property. 2422 'products': this.myProducts 2423 } 2424 } 2425 }); 2426 }, 2427 sendDetails: function (name, id, category) { 2428 //tracks a user's view of product details 2429 window.dataLayer.push({ 2430 'event': 'detailView', 2431 'ecommerce': { 2432 'detail': { 2433 'products': [{ 2434 'name': name, // Name or ID is required. 2435 'id': id, 2436 'category': category, 2437 }] 2438 } 2439 } 2440 }); 2441 }, 2442 2443 sendAddToBasket: function(){ 2444 var newAddedProducts = this.compareBasketProducts(this.basketProducts); 2445 if (newAddedProducts.length === 0) { 2446 return; 2447 } 2448 console.log("added items to basket:", newAddedProducts); 2449 //REQUIRES basketProducts populated via fetchBasketProducts or directly 2450 window.dataLayer.push({ 2451 'event': 'addToCart', 2452 'ecommerce': { 2453 'add': { // 'add' actionFieldObject measures. 2454 'products': newAddedProducts // adding a product to a shopping cart. 2455 } 2456 } 2457 }); 2458 }, 2459 2460 sendAddItemToBasket: function(name, id, price, category, quantity){ 2461 //REQUIRES basketProducts populated via fetchBasketProducts or directly 2462 window.dataLayer.push({ 2463 'event': 'addToCart', 2464 'ecommerce': { 2465 'add': { // 'add' actionFieldObject measures. 2466 'products': [{ // removing a product to a shopping cart. 2467 'name': name, 2468 'id': id, 2469 'price': price, 2470 'category': category, 2471 'quantity': quantity 2472 }] 2473 } 2474 } 2475 }); 2476 }, 2477 2478 sendRemoveFromBasket: function (name, id, price, category, quantity, doUpdate) { 2479 //the item should be removed from the actual basket before this is called, as the basket is updated immediately 2480 window.dataLayer.push({ 2481 'event': 'removeFromCart', 2482 'ecommerce': { 2483 'remove': { // 'remove' actionFieldObject measures. 2484 'products': [{ // removing a product to a shopping cart. 2485 'name': name, 2486 'id': id, 2487 'price': price, 2488 'category': category, 2489 'quantity': quantity 2490 }] 2491 } 2492 } 2493 }); 2494 if (doUpdate) { 2495 this.fetchBasketProducts(); 2496 } 2497 }, 2498 2499 sendRemoveAllFromBasket: function () { 2500 //the item should be removed from the actual basket before this is called, as the basket is updated immediately 2501 window.dataLayer.push({ 2502 'event': 'removeFromCart', 2503 'ecommerce': { 2504 'remove': { // 'remove' actionFieldObject measures. 2505 'products': this.basketProducts 2506 } 2507 } 2508 }); 2509 this.basketProducts = []; 2510 localStorage.removeItem('swAddedBasketProducts'); 2511 }, 2512 2513 //method to fetch basket - we should only call this if we intend to send products to analytics 2514 fetchBasketProducts: function (type, orderID, doAddToCartAfter) { 2515 if (typeof type === 'undefined') type = 'basket'; //defaults to grabbing basket items 2516 if (typeof orderID === 'undefined') orderID = 0; 2517 doAddToCartAfter = doAddToCartAfter || false; 2518 var fetchURL = "include/modules/enhancedEcommerceBasket.asp?type=" + type + "&orderid=" + orderID; 2519 2520 try { 2521 $.ajax({
2522 context: this, 2523 url: fetchURL 2524 }) 2525 .done(function (data) { 2526 //note that we'll only have basket details if this method is called. Functions like sendAddToBasket, and sendPurchase will not function if this method has not completed. 2527 try{ 2528 this.basketProducts = JSON.parse(data); 2529 } catch (e) { 2530 console.log(e); 2531 this.basketProducts = []; 2532 } 2533 //try to update the data layer with the most current products 2534 try{ 2535 addDataLayer("TicketingTicketItems",data); 2536 } catch (e){ 2537 console.log(e); 2538 } 2539 if(doAddToCartAfter){ 2540 this.sendAddToBasket(); 2541 } 2542 }); 2543 //grab the basket and store contents 2544 } catch (e) { 2545 console.log(e); 2546 return 2547 } 2548 }, 2549 2550 sendOrder: function (orderID, orderTotal, taxFees, shippingFees, couponCodes, orderCode) { 2551 var fetchURL = "include/modules/enhancedEcommerceBasket.asp?type=order&orderid=" + orderID + "&orderCode=" + orderCode; 2552 orderProducts = []; 2553 2554 try { 2555 $.ajax({
2556 context: this, 2557 url: fetchURL 2558 }) 2559 .done(function (data) { 2560 //note that we'll only have basket details if this method is called. Functions like sendAddToBasket, and sendPurchase will not function if this method has not completed. 2561 try { 2562 orderProducts = JSON.parse(data); 2563 } catch (e) { 2564 console.log(e); 2565 orderProducts = []; 2566 } 2567 dataLayer.push({ 2568 'event': 'purchaseMade', 2569 'ecommerce': { 2570 'purchase': { 2571 'actionField': { 2572 'id': orderID, // Transaction ID. Required for purchases and refunds. 2573 'affiliation': 'Online Ticketing', 2574 'revenue': orderTotal, // Total transaction value (incl. tax and shipping) 2575 'tax': taxFees, 2576 'shipping': shippingFees, 2577 'coupon': couponCodes 2578 }, 2579 'products': orderProducts 2580 } 2581 } 2582 }); 2583 }); 2584 //grab the basket and store contents 2585 } catch (e) { 2586 console.log(e); 2587 return 2588 } 2589 2590 2591 }, 2592 2593 // -------------------------------------------- CHECKOUT STEPS -------------------------------------------- 2594 // 1. Basket Page "Checkout" Clicked 2595 // 2. login/guest/create 2596 // 3. Streamlined - select shipping method 2597 // 4. Streamlined - enter payment information 2598 // 5. Streamlined - complete clicked 2599 // 6. view order 2600 sendCheckoutStep: function(stepID, option){ 2601 dataLayer.push({ 2602 'event': 'checkout', 2603 'ecommerce': { 2604 'checkout': { 2605 'actionField': { 'step': stepID, 'option': option }, 2606 'products': this.basketProducts 2607 } 2608 } 2609 }); 2610 }, 2611 sendViewPromotion: function(promotionItems){ 2612 //promotion items should be an array of promotion items 2613 dataLayer.push({ 2614 'event': 'view_promotion', 2615 'ecommerce': { 2616 'items': promotionItems 2617 } 2618 }); 2619 console.log("sent promotions"); 2620 console.log(promotionItems); 2621 }, 2622 sendSelectPromotion: function(promotionItems){ 2623 //promotion items should be an array of promotion items 2624 dataLayer.push({ 2625 'event': 'select_promotion', 2626 'ecommerce': { 2627 'items': promotionItems 2628 } 2629 }); 2630 console.log("selected promotions"); 2631 console.log(promotionItems); 2632 }, 2633 2634 getStoredAddedBasketProducts: function () { 2635 if (typeof localStorage === 'undefined') { 2636 return []; 2637 } 2638 try { 2639 var storedRaw = localStorage.getItem('swAddedBasketProducts'); 2640 if (!storedRaw) { 2641 return []; 2642 } 2643 var parsed = JSON.parse(storedRaw); 2644 return Array.isArray(parsed) ? parsed : []; 2645 } catch (e) { 2646 console.log(e); 2647 return []; 2648 } 2649 }, 2650 cloneBasketProduct: function (product) { 2651 if (!product || typeof product !== 'object') { 2652 return product; 2653 } 2654 var clone = {}; 2655 for (var prop in product) { 2656 if (Object.prototype.hasOwnProperty.call(product, prop)) { 2657 clone[prop] = product[prop]; 2658 } 2659 } 2660 return clone; 2661 }, 2662 cloneBasketProducts: function (source) { 2663 var cloned = []; 2664 if (!Array.isArray(source)) { 2665 return cloned; 2666 } 2667 for (var i = 0; i < source.length; i++) { 2668 cloned.push(this.cloneBasketProduct(source[i])); 2669 } 2670 return cloned; 2671 }, 2672 buildBasketProductSignature: function (product) { 2673 if (!product || typeof product !== 'object') { 2674 return ''; 2675 } 2676 var keys = Object.keys(product).sort(); 2677 var normalized = {}; 2678 for (var i = 0; i < keys.length; i++) { 2679 var key = keys[i];
2680 normalized[key] = product[key]; 2681 } 2682 try { 2683 return JSON.stringify(normalized); 2684 } catch (e) { 2685 console.log(e); 2686 return ''; 2687 } 2688 }, 2689 persistAddedBasketProducts: function (products) { 2690 if (typeof localStorage === 'undefined') { 2691 return; 2692 } 2693 try { 2694 localStorage.setItem('swAddedBasketProducts', JSON.stringify(this.cloneBasketProducts(products))); 2695 } catch (e) { 2696 console.log(e); 2697 } 2698 }, 2699 storeAddedBasketProducts: function(basketProducts) { 2700 this.compareBasketProducts(basketProducts); 2701 }, 2702 compareBasketProducts: function(basketProducts, options){ 2703 var opts = options || {}; 2704 var products = Array.isArray(basketProducts) ? basketProducts : []; 2705 if (typeof localStorage === 'undefined') { 2706 return opts.returnCombined ? { unmatched: products, combined: this.cloneBasketProducts(products) } : products; 2707 } 2708 2709 var storedProducts = this.getStoredAddedBasketProducts(); 2710 var storedCounts = {}; 2711 for (var i = 0; i < storedProducts.length; i++) { 2712 var storedSignature = this.buildBasketProductSignature(storedProducts[i]); 2713 if (storedSignature) { 2714 storedCounts[storedSignature] = (storedCounts[storedSignature] || 0) + 1; 2715 } 2716 } 2717 2718 var unmatchedProducts = []; 2719 var combinedProducts = this.cloneBasketProducts(storedProducts); 2720 var pendingCounts = {}; 2721 2722 for (var j = 0; j < products.length; j++) { 2723 var product = products[j]; 2724 var productSignature = this.buildBasketProductSignature(product); 2725 2726 if (!productSignature) { 2727 unmatchedProducts.push(product); 2728 combinedProducts.push(this.cloneBasketProduct(product)); 2729 continue; 2730 } 2731 2732 var alreadyTracked = pendingCounts[productSignature] || 0; 2733 var existingCount = storedCounts[productSignature] || 0; 2734 2735 if (alreadyTracked < existingCount) { 2736 pendingCounts[productSignature] = alreadyTracked + 1; 2737 } else { 2738 unmatchedProducts.push(product); 2739 pendingCounts[productSignature] = alreadyTracked + 1; 2740 combinedProducts.push(this.cloneBasketProduct(product)); 2741 } 2742 } 2743 2744 if (opts.persist !== false) { 2745 this.persistAddedBasketProducts(combinedProducts); 2746 } 2747 2748 if (opts.returnCombined) { 2749 return { unmatched: unmatchedProducts, combined: combinedProducts }; 2750 } 2751 2752 return unmatchedProducts; 2753 } 2754 2755 2756 } 2757</script>
2757
2758<script type="text/javascript"> 2759//---------------------------DATEPICKER--------------------------------- 2760function buildDatepicker(options) { 2761 //Calling this function should be sufficient to create a calendar within a designated div, with and 2762 //EX: headerDP = buildDatepicker({"calendarID":"headerCalendar","linkedInputID":"headerCalendarInput","isModal":false,"forceDates":true, "defaultDate": "{{Output date from server Here}}"}); <~ would create a calendar object for the calendar presented at #headerCalendar, and link it to #headerCalendarInput 2763 //most calendar methods are specific to the document the calendar resides on, and should be handled via the onChange event for the linked input 2764 //Available Options: 2765 // calendarID (required) == string, ID of calendar div 2766 // linkedInput (required) == string, ID of input which will change when a date is selected 2767 // isModal == boolean, if true, calendar will be hidden, and display when the designated input recieves focus. If false, the calendar will be present and display as an inline block at all times. 2768 // forceDates == boolean, if true only highlighted dates will be clickable 2769 // detailedCalendar == boolean, if true data is pulled to determine pricing information, sold out days, limited availablility - requires eventID 2770 // defaultDate == string, mm/dd/yyyy date that calendar should start on (this will only represent the month displayed at the begining) 2771 // type == string: defaults to "performancedates", which will add all visible performances 2772 // eventID == integer: defaults to -1 which means no event. Other values will filter by events with that ID, allowing for a search of performance dates for a specific event only 2773 // isMultiplePerformanceIndicator == boolean: if true, shows indicator for dates with multiple performance times 2774 // 2775 //Methods: 2776 // showDlg()/hideDlg() : shows/hides modal calendars, no valid for non-modal calendars 2777 // addHighlightDay(mm/dd/yyyy) : adds a date (presented as a mm/dd/yyyy string) to the list of highlight dates for the calendar - REQUIRES HighlightDays() function call to visually represent this change on the calendar 2778 // clearHihghlightDays() : removes all stored highlight dates 2779 // highlightDays() : adds highlight class to stored days, visually highlighting them ont he calendar. 2780 2781 var myID = options.calendarID; //required 2782 var myLinkedInput = options.linkedInputID; //required 2783 var isModal = options.isModal || false; 2784 var showLoader = options.showLoader || false; 2785 var forceDates = options.forceDates || false; 2786 var myDefault = new Date(); 2787 if (options.defaultDate) { 2788 try{ 2789 2790 myDefault = new Date(options.defaultDate); 2791 } catch (e) { 2792 console.log("date no valid for calendar: " + myID); 2793 console.log(e); 2794 } 2795 } 2796 var type = options.type || "performancedates"; 2797 var eventID = options.eventID || -1; 2798 var detailedCalendar = options.detailedCalendar && eventID != -1 || false; 2799 var bundleID = options.bundleID || -1; 2800 var categoryID = options.CategoryID || -1; 2801 var corporatePartnerPage = options.corporatePartnerPage || 0; 2802 var bValidCoupon = options.bValidCoupon || 0; 2803 var couponCode = options.couponCode || ""; 2804 var isMultiplePerformanceIndicator = options.isMultiplePerformanceIndicatorFlag || 0; 2805 2806 return new swDatepicker(myID, myLinkedInput, isModal, showLoader, forceDates, detailedCalendar, myDefault, type, eventID, bundleID, categoryID, corporatePartnerPage,bValidCoupon,couponCode,isMultiplePerformanceIndicator) 2807} 2808function swDatepicker(id, target, modal, loader, force, detailed, defaultDate, type, eventID, bundleID, categoryID, corporatePartnerPage,bValidCoupon,couponCode,isMultiplePerformanceIndicator) { 2809 2810 this.$id = $('#' + id); // element to attach widget to 2811 this.$monthObj = this.$id.find('.month'); 2812 this.$prev = this.$id.find('.bn_prev'); 2813 this.$next = this.$id.find('.bn_next'); 2814 this.$grid = this.$id.find('.cal'); 2815 this.$target = $('#' + target); // div or text box that will receive the selected date string and focus (if modal) 2816 this.bModal = modal; // true if datepicker should appear in a modal dialog box. 2817 this.showLoader = loader; 2818 this.forceDateSelection = force; //if true, will only allow users to click on highlighted dates - see addHighlightDay() 2819 this.detailedCalendar = detailed; 2820 this.active = !modal; 2821 this.type = type; 2822 this.eventID = eventID; 2823 this.bundleID = bundleID; 2824 this.categoryID = categoryID; 2825 this.corporatePartnerPage = corporatePartnerPage; 2826 this.fromDateRange = ""; 2827 this.toDateRange = ""; 2828 this.dateRangeEvents = []; 2829 this.calendarName = id; 2830 2831 this.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 2832 'July', 'August', 'September', 'October', 'November', 'December']; 2833 2834 this.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 2835 2836 this.dateObj = new Date(); 2837 2838 this.curYear = this.dateObj.getFullYear(); 2839 this.year = defaultDate.getFullYear(); 2840 2841 this.curMonth = this.dateObj.getMonth(); 2842 this.month = defaultDate.getMonth(); 2843 this.getFirstDate(defaultDate.getMonth()); //update the month to the first performance ASAP 2844 2845 this.curDate = this.dateObj.getDate(); 2846 this.date = defaultDate.getDate(); 2847 this.currentDate = (this.month == this.curMonth && this.year == this.curYear); 2848 this.activeMonth = (String(this.month + 1) + "/1/" + this.year); 2849 2850 this.keys = { 2851 tab: 9, 2852 enter: 13, 2853 esc: 27, 2854 space: 32, 2855 pageup: 33, 2856 pagedown: 34, 2857 end: 35, 2858 home: 36, 2859 left: 37, 2860 up: 38, 2861 right: 39, 2862 down: 40 2863 }; 2864 2865 this.bValidCoupon = bValidCoupon; 2866 this.couponCode = couponCode; 2867 this.isMultiplePerformanceIndicator = isMultiplePerformanceIndicator; 2868 2869 this.highlightDates = []; 2870 2871 // display the current month 2872 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 2873 2874 // populate the calendar grid
2875 this.popGrid(); 2876 2877 // update the table's activedescdendant to point to the current day 2878 this.$grid.attr('aria-activedescendant', this.$grid.find('.today').attr('id')); 2879 2880 this.bindHandlers(); 2881 2882 //show selected day 2883 $('#' + this.calendarName + '-day' + this.date).addClass('focus').attr('aria-selected', 'true'); 2884 2885 // hide dialog if in modal mode 2886 if (this.bModal == true) { 2887 this.$id.attr('aria-hidden', 'true'); 2888 //show/hide functionality may vary based on use, so should be handled after the datepicker is created. 2889 //if we're on mobile, disable keyboard for the input: 2890 if ($(window).width() < 1024) { 2891 this.$target.attr("readonly", "true"); 2892 } 2893 } 2894 2895 this.currencySymbol = "$"; 2896 this.buyTicketsButtonText = "Buy Tickets"; 2897} 2898 2899// 2900// popGrid() is a member function to populate the datepicker grid with calendar days 2901// representing the current month 2902// 2903// @return N/A 2904// 2905swDatepicker.prototype.popGrid = function () { 2906 if(this.showLoader) 2907 $(".calendar-loading").show(); 2908 var numDays = this.calcNumDays(this.year, this.month); 2909 var startWeekday = this.calcStartWeekday(this.year, this.month); 2910 //var lastMonth = this.month - 1; 2911 //var lastMonthYear = this.year; 2912 var weekday = 0; 2913 var curDay = 1; 2914 var rowCount = 1; 2915 var $tbody = this.$grid.find('tbody'); 2916 2917 var currentDateDay = this.dateObj.getDate(); 2918 var currentDateMonth = this.dateObj.getMonth(); 2919 var currentDateYear = this.dateObj.getFullYear(); 2920 2921 var gridCells = '\t<tr id="row1">\n'; 2922 2923 // Keeping in case the client (Gaylord) pushes back on not having previous month's dates selectable 2924 // If the last month is -1, roll it over to December (11) and subtract 1 from the last month's year 2925 /*if (lastMonth < 0) { 2926 lastMonth = 11; 2927 lastMonthYear = lastMonthYear - 1; 2928 } 2929 2930 var lastMonthNumDays = this.calcNumDays(lastMonthYear, lastMonth); 2931 var lastMonthStartDay = lastMonthNumDays - (startWeekday - 1);*/ 2932 2933 // clear the grid 2934 $tbody.empty(); 2935 $('#msg').empty(); 2936 2937 // Keeping in case the client (Gaylord) pushes back on not having previous month's dates selectable 2938 // Insert the leading empty cells 2939 /*for (var weekday = 0; weekday < startWeekday; weekday++) { 2940 gridCells += '\t\t<td id="' + this.calendarName + '-day' + lastMonthStartDay + '" class="day-cell muted last-month" headers="row' + 2941 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false" data-year="' + lastMonthYear + '"><span class="calendar-day notranslate" data-month="' + lastMonth + '">' + lastMonthStartDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 2942 //gridCells += '\t\t<td class="empty" data-month="' + lastMonth + '" data-year="' + lastMonthYear + '" data-day="' + lastMonthStartDay + '"> </td>\n'; 2943 lastMonthStartDay++; 2944 }*/ 2945 2946 for (var weekday = 0; weekday < startWeekday; weekday++) { 2947 gridCells += '\t\t<td class="empty"> </td>\n'; 2948 } 2949 2950 // insert the days of the month. 2951 for (curDay = 1; curDay <= numDays; curDay++) { 2952 2953 if (curDay == this.curDate && this.currentDate == true) { 2954 2955 gridCells += '\t\t<td id="' + this.calendarName + '-day' + curDay + '" class="today day-cell" aria-label="row' + 2956 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false"><span class="calendar-day notranslate">' + curDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 2957 } 2958 else { 2959 var addMuted = ""; 2960 2961 // Only mute dates in the past for the date range selector widget 2962 if (this.type == 'dateRangeSelect') { 2963 // If the year is in the past, or the year is the same but the month is in the past, or the month and year are the same but the day is in the past, mute the date 2964 if (this.year < currentDateYear 2965 || (this.year == currentDateYear && this.month < currentDateMonth) 2966 || (this.year == currentDateYear && this.month == currentDateMonth && curDay < currentDateDay) 2967 ) { 2968 addMuted = " muted"; 2969 } 2970 } 2971 2972 gridCells += '\t\t<td id="' + this.calendarName + '-day' + curDay + '" class="day-cell' + addMuted + '" aria-label="row' + 2973 rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false"><span class="calendar-day notranslate">' + curDay + '</span> <span class="calendar-dayoftheweek" style="display: none;">' + this.dayNames[weekday] + '</span></td>'; 2974 } 2975 2976 2977 if (weekday == 6 && curDay < numDays) { 2978 // This was the last day of the week, close it out 2979 // and begin a new one 2980 gridCells += '\t</tr>\n\t<tr id="row' + rowCount + '">\n'; 2981 rowCount++; 2982 weekday = 0; 2983 } 2984 else { 2985 weekday++; 2986 } 2987 } 2988 2989 // Insert any trailing empty cells 2990 for (weekday; weekday < 7; weekday++) { 2991 2992 gridCells += '\t\t<td class="empty"> </td>\n'; 2993 } 2994 2995 gridCells += '\t</tr>'; 2996 2997 $tbody.append(gridCells); 2998 if(this.detailedCalendar){ 2999 this.getCalendarDetails(); 3000 }else{ 3001 this.fetchDates();
3002 } 3003 3004} 3005 3006// 3007// calcNumDays() is a member function to calculate the number of days in a given month 3008// 3009// @return (integer) number of days 3010// 3011swDatepicker.prototype.calcNumDays = function (year, month) { 3012 3013 return 32 - new Date(year, month, 32).getDate(); 3014} 3015 3016// 3017// calcstartWeekday() is a member function to calculate the day of the week the first day of a 3018// month lands on 3019// 3020// @return (integer) number representing the day of the week (0=Sunday....6=Saturday) 3021// 3022swDatepicker.prototype.calcStartWeekday = function (year, month) { 3023 3024 return new Date(year, month, 1).getDay(); 3025 3026} // end calcStartWeekday() 3027 3028// 3029// showPrevMonth() is a member function to show the previous month 3030// 3031// @param (offset int) offset may be used to specify an offset for setting 3032// focus on a day the specified number of days from 3033// the end of the month. 3034// @return N/A 3035// 3036swDatepicker.prototype.showPrevMonth = function (offset) { 3037 // show the previous month 3038 if (this.month < 1) { 3039 this.month = 11; 3040 this.year--; 3041 } 3042 else { 3043 this.month--; 3044 } 3045 3046 if (this.month != this.curMonth || this.year != this.curYear) { 3047 this.currentDate = false; 3048 } 3049 else { 3050 this.currentDate = true; 3051 } 3052 3053 this.activeMonth = (String(this.month + 1) + "/1/" + this.year) 3054 3055 // populate the calendar grid 3056 this.popGrid(); 3057 3058 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 3059 3060 // if offset was specified, set focus on the last day - specified offset 3061 if (offset != null) { 3062 var numDays = this.calcNumDays(this.year, this.month); 3063 var day = 'day' + (numDays - offset); 3064 3065 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + day); 3066 $('#' + this.calendarName + '-' + day).addClass('focus').attr('aria-selected', 'true'); 3067 } 3068 3069 3070} // end showPrevMonth() 3071 3072// 3073// showNextMonth() is a member function to show the next month 3074// 3075// @param (offset int) offset may be used to specify an offset for setting 3076// focus on a day the specified number of days from 3077// the beginning of the month. 3078// @return N/A 3079// 3080swDatepicker.prototype.showNextMonth = function (offset) { 3081 3082 // show the next month 3083 if (this.month == 11) { 3084 this.month = 0; 3085 this.year++; 3086 } 3087 else { 3088 this.month++; 3089 } 3090 3091 if (this.month != this.curMonth || this.year != this.curYear) { 3092 this.currentDate = false; 3093 } 3094 else { 3095 this.currentDate = true; 3096 } 3097 3098 this.activeMonth = (String(this.month + 1) + "/1/" + this.year) 3099 3100 // populate the calendar grid 3101 this.popGrid(); 3102 3103 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 3104 3105 // if offset was specified, set focus on the first day + specified offset 3106 if (offset != null) { 3107 var day = 'day' + offset; 3108 3109 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + day); 3110 $('#' + this.calendarName + '-' + day).addClass('focus').attr('aria-selected', 'true'); 3111 } 3112 3113} // end showNextMonth() 3114 3115// 3116// showPrevYear() is a member function to show the previous year 3117// 3118// @return N/A 3119// 3120swDatepicker.prototype.showPrevYear = function () { 3121 3122 // decrement the year 3123 this.year--; 3124 3125 if (this.month != this.curMonth || this.year != this.curYear) { 3126 this.currentDate = false; 3127 } 3128 else { 3129 this.currentDate = true; 3130 } 3131 3132 // populate the calendar grid 3133 this.popGrid(); 3134 3135 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 3136 3137} // end showPrevYear() 3138 3139// 3140// showNextYear() is a member function to show the next year 3141// 3142// @return N/A 3143// 3144swDatepicker.prototype.showNextYear = function () { 3145 3146 // increment the year 3147 this.year++; 3148 3149 if (this.month != this.curMonth || this.year != this.curYear) { 3150 this.currentDate = false; 3151 } 3152 else { 3153 this.currentDate = true; 3154 } 3155 3156 // populate the calendar grid
3157 this.popGrid(); 3158 3159 this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year); 3160 3161} // end showNextYear() 3162 3163// 3164// bindHandlers() is a member function to bind event handlers for the widget 3165// 3166// @return N/A 3167// 3168swDatepicker.prototype.bindHandlers = function () { 3169 3170 var thisObj = this; 3171 3172 ////////////////////// bind button handlers ////////////////////////////////// 3173 this.$prev.click(function (e) { 3174 return thisObj.handlePrevClick(e); 3175 }); 3176 3177 this.$next.click(function (e) { 3178 return thisObj.handleNextClick(e); 3179 }); 3180 3181 this.$prev.keydown(function (e) { 3182 return thisObj.handlePrevKeyDown(e); 3183 }); 3184 3185 this.$next.keydown(function (e) { 3186 return thisObj.handleNextKeyDown(e); 3187 }); 3188 3189 ///////////// bind grid handlers ////////////// 3190 3191 this.$grid.keydown(function (e) { 3192 return thisObj.handleGridKeyDown(e); 3193 }); 3194 3195 this.$grid.keypress(function (e) { 3196 return thisObj.handleGridKeyPress(e); 3197 }); 3198 3199 this.$grid.focus(function (e) { 3200 return thisObj.handleGridFocus(e); 3201 }); 3202 3203 this.$grid.blur(function (e) { 3204 return thisObj.handleGridBlur(e); 3205 }); 3206 3207 this.$grid.delegate('td', 'click', function (e) { 3208 return thisObj.handleGridClick(this, e); 3209 }); 3210 3211} // end bindHandlers(); 3212 3213function scrollToFirstHighlightDay() { 3214 // find all the heights of elements before the calendar 3215 var EventInfoHeight = $('#EventInformationWrap').outerHeight() + 64; // 64 is the height mobile navigation 3216 var EventLabelAndOptionsHeight = $('#eventCalendarLabelAndOptions').outerHeight(); 3217 var CalendarMonthHeight = $('.sw-datepicker.large-datepicker .month-wrap').outerHeight(); 3218 3219 var EventInfoAndOptionsHeight = EventInfoHeight + EventLabelAndOptionsHeight; 3220 var CalendarTopInfoHeaderHeights = EventInfoHeight + EventLabelAndOptionsHeight + CalendarMonthHeight + 10; // 10 is just a gap added so it is not sticking against the month section 3221 3222 // set the Top section sticky so when it focuses on the first hightlight day you can still see the informations 3223 $('#EventInformationWrap').addClass("make-this-section-sticky"); 3224 $('#eventCalendarLabelAndOptions').addClass("make-this-section-sticky"); 3225 $('#eventCalendarLabelAndOptions').css("top", EventInfoHeight); 3226 $('.sw-datepicker.large-datepicker .month-wrap').addClass("make-this-section-sticky"); 3227 $('.sw-datepicker.large-datepicker .month-wrap').css("top", EventInfoAndOptionsHeight); 3228 3229 // Check if any elements with the class .highlight-day exist 3230 var highlightDay = $('.performance-list-calendar .highlight-day').first(); 3231 3232 // set the first day cell 3233 var firstDayCel = $('.day-cell').first(); 3234 var scrollToPosition = 0; 3235 3236 if (highlightDay.length > 0) { // Get the offset only if .highlight-day element exists 3237 scrollToPosition = highlightDay.offset().top; 3238 scrollToPosition = scrollToPosition - CalendarTopInfoHeaderHeights; 3239 $('html, body').animate({scrollTop: scrollToPosition}, 'slow'); 3240 } else { // if there's no highlights on this month, focus on the first day of the month 3241 scrollToPosition = firstDayCel.offset().top; 3242 scrollToPosition = scrollToPosition - (CalendarTopInfoHeaderHeights * 2); 3243 $('html, body').animate({scrollTop: scrollToPosition}, 'slow'); 3244 } 3245} 3246 3247// 3248// handlePrevClick() is a member function to process click events for the prev month button 3249// 3250// @input (e obj) e is the event object associated with the event 3251// 3252// @return (boolean) false if consuming event, true if propagating 3253// 3254swDatepicker.prototype.handlePrevClick = function (e) { 3255 3256 var active = this.$grid.attr('aria-activedescendant'); 3257 3258 if (e.ctrlKey) { 3259 this.showPrevYear(); 3260 } 3261 else { 3262 this.showPrevMonth(); 3263 } 3264 3265 if (this.currentDate == false) { 3266 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 3267 } 3268 else { 3269 this.$grid.attr('aria-activedescendant', active); 3270 } 3271 3272 e.stopPropagation(); 3273 return false; 3274 3275} // end handlePrevClick() 3276 3277// 3278// handleNextClick() is a member function to process click events for the next month button 3279// 3280// @input (e obj) e is the event object associated with the event 3281// 3282// @return (boolean) false if consuming event, true if propagating 3283// 3284swDatepicker.prototype.handleNextClick = function (e) { 3285 3286 var active = this.$grid.attr('aria-activedescendant'); 3287 3288 if (e.ctrlKey) { 3289 this.showNextYear(); 3290 } 3291 else { 3292 this.showNextMonth(); 3293 } 3294 3295 if (this.currentDate == false) { 3296 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 3297 } 3298 else { 3299 this.$grid.attr('aria-activedescendant', active); 3300 } 3301 3302 e.stopPropagation(); 3303 return false; 3304 3305} // end handleNextClick() 3306 3307// 3308// handlePrevKeyDown() is a member function to process keydown events for the prev month button 3309// 3310// @input (e obj) e is the event object associated with the event 3311// 3312// @return (boolean) false if consuming event, true if propagating 3313// 3314swDatepicker.prototype.handlePrevKeyDown = function (e) { 3315 3316 if (e.altKey) { 3317 return true; 3318 } 3319 3320 switch (e.keyCode) { 3321 case this.keys.tab: { 3322 if (this.bModal == false || !e.shiftKey || e.ctrlKey) { 3323 return true; 3324 } 3325 3326 this.$grid.focus(); 3327 e.stopPropagation(); 3328 return false; 3329 } 3330 case this.keys.enter: 3331 case this.keys.space: { 3332 if (e.shiftKey) { 3333 return true; 3334 } 3335 3336 if (e.ctrlKey) { 3337 this.showPrevYear(); 3338 } 3339 else { 3340 this.showPrevMonth(); 3341 } 3342 3343 e.stopPropagation(); 3344 return false; 3345 } 3346 } 3347 3348 return true; 3349 3350} // end handlePrevKeyDown() 3351 3352// 3353// handleNextKeyDown() is a member function to process keydown events for the next month button 3354// 3355// @input (e obj) e is the event object associated with the event 3356// 3357// @return (boolean) false if consuming event, true if propagating 3358// 3359swDatepicker.prototype.handleNextKeyDown = function (e) { 3360 3361 if (e.altKey) { 3362 return true; 3363 } 3364 3365 switch (e.keyCode) { 3366 case this.keys.enter: 3367 case this.keys.space: { 3368 3369 if (e.ctrlKey) { 3370 this.showNextYear(); 3371 } 3372 else { 3373 this.showNextMonth(); 3374 } 3375 3376 e.stopPropagation(); 3377 return false; 3378 } 3379 } 3380 3381 return true; 3382 3383} // end handleNextKeyDown() 3384 3385// 3386// handleGridKeyDown() is a member function to process keydown events for the datepicker grid 3387// 3388// @input (e obj) e is the event object associated with the event 3389// 3390// @return (boolean) false if consuming event, true if propagating 3391// 3392swDatepicker.prototype.handleGridKeyDown = function (e) { 3393 3394 var $rows = this.$grid.find('tbody tr'); 3395 var $curDay = $('#' + this.$grid.attr('aria-activedescendant'));
3396 var $days = this.$grid.find('td').not('.empty'); 3397 var $curRow = $curDay.parent(); 3398 3399 if (e.altKey) { 3400 return true; 3401 } 3402 3403 switch (e.keyCode) { 3404 case this.keys.tab: { 3405 3406 if (this.bModal == true) { 3407 if (e.shiftKey) { 3408 this.$next.focus(); 3409 } 3410 else { 3411 this.$prev.focus(); 3412 } 3413 e.stopPropagation() 3414 return false; 3415 } 3416 break; 3417 } 3418 case this.keys.enter: 3419 case this.keys.space: { 3420 3421 if (e.ctrlKey) { 3422 return true; 3423 } 3424 3425 // update the target box 3426 this.$target.val((this.month + 1) + '/' + $curDay.find(".calendar-day").text() + '/' + this.year).change(); 3427 3428 // fall through 3429 } 3430 case this.keys.esc: { 3431 // dismiss the dialog box 3432 this.hideDlg(); 3433 3434 e.stopPropagation(); 3435 return false; 3436 } 3437 case this.keys.left: { 3438 3439 if (e.ctrlKey || e.shiftKey) { 3440 return true; 3441 } 3442 3443 var dayIndex = $days.index($curDay) - 1; 3444 var $prevDay = null; 3445 3446 if (dayIndex >= 0) { 3447 $prevDay = $days.eq(dayIndex); 3448 3449 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3450 $prevDay.addClass('focus').attr('aria-selected', 'true'); 3451 3452 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 3453 } 3454 else { 3455 this.showPrevMonth(0); 3456 } 3457 3458 e.stopPropagation(); 3459 return false; 3460 } 3461 case this.keys.right: { 3462 3463 if (e.ctrlKey || e.shiftKey) { 3464 return true; 3465 } 3466 3467 var dayIndex = $days.index($curDay) + 1; 3468 var $nextDay = null; 3469 3470 if (dayIndex < $days.length) { 3471 $nextDay = $days.eq(dayIndex); 3472 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3473 $nextDay.addClass('focus').attr('aria-selected', 'true'); 3474 3475 this.$grid.attr('aria-activedescendant', $nextDay.attr('id')); 3476 } 3477 else { 3478 // move to the next month 3479 this.showNextMonth(1); 3480 } 3481 3482 e.stopPropagation(); 3483 return false; 3484 } 3485 case this.keys.up: { 3486 3487 if (e.ctrlKey || e.shiftKey) { 3488 return true; 3489 } 3490 3491 var dayIndex = $days.index($curDay) - 7; 3492 var $prevDay = null; 3493 3494 if (dayIndex >= 0) { 3495 $prevDay = $days.eq(dayIndex); 3496 3497 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3498 $prevDay.addClass('focus').attr('aria-selected', 'true'); 3499 3500 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 3501 } 3502 else { 3503 // move to appropriate day in previous month 3504 dayIndex = 6 - $days.index($curDay); 3505 3506 this.showPrevMonth(dayIndex); 3507 } 3508 3509 e.stopPropagation(); 3510 return false; 3511 } 3512 case this.keys.down: { 3513 3514 if (e.ctrlKey || e.shiftKey) { 3515 return true; 3516 } 3517 3518 var dayIndex = $days.index($curDay) + 7; 3519 var $prevDay = null; 3520 3521 if (dayIndex < $days.length) { 3522 $prevDay = $days.eq(dayIndex); 3523 3524 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3525 $prevDay.addClass('focus').attr('aria-selected', 'true'); 3526 3527 this.$grid.attr('aria-activedescendant', $prevDay.attr('id')); 3528 } 3529 else { 3530 // move to appropriate day in next month 3531 dayIndex = 8 - ($days.length - $days.index($curDay)); 3532 3533 this.showNextMonth(dayIndex); 3534 } 3535 3536 e.stopPropagation(); 3537 return false; 3538 } 3539 case this.keys.pageup: { 3540 var active = this.$grid.attr('aria-activedescendant'); 3541 3542 3543 if (e.shiftKey) { 3544 return true; 3545 } 3546 3547 3548 if (e.ctrlKey) { 3549 this.showPrevYear(); 3550 } 3551 else { 3552 this.showPrevMonth(); 3553 } 3554 3555 if ($('#' + active).attr('id') == undefined) { 3556 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 3557 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 3558 } 3559 else { 3560 $('#' + this.calendarName + '-' + active).addClass('focus').attr('aria-selected', 'true'); 3561 } 3562 3563 e.stopPropagation(); 3564 return false; 3565 } 3566 case this.keys.pagedown: { 3567 var active = this.$grid.attr('aria-activedescendant'); 3568 3569 3570 if (e.shiftKey) { 3571 return true; 3572 } 3573 3574 if (e.ctrlKey) { 3575 this.showNextYear(); 3576 } 3577 else { 3578 this.showNextMonth(); 3579 } 3580 3581 if ($('#' + active).attr('id') == undefined) { 3582 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 3583 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 3584 } 3585 else { 3586 $('#' + this.calendarName + '-' + active).addClass('focus').attr('aria-selected', 'true'); 3587 } 3588 3589 e.stopPropagation(); 3590 return false; 3591 } 3592 case this.keys.home: { 3593 3594 if (e.ctrlKey || e.shiftKey) { 3595 return true; 3596 } 3597 3598 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3599 3600 $('#' + this.calendarName + '-day1').addClass('focus').attr('aria-selected', 'true'); 3601 3602 this.$grid.attr('aria-activedescendant', this.calendarName + '-day1'); 3603 3604 e.stopPropagation(); 3605 return false; 3606 } 3607 case this.keys.end: { 3608 3609 if (e.ctrlKey || e.shiftKey) { 3610 return true; 3611 } 3612 3613 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 3614 3615 $curDay.removeClass('focus').attr('aria-selected', 'false'); 3616 3617 $('#' + this.calendarName + '-' + lastDay).addClass('focus').attr('aria-selected', 'true'); 3618 3619 this.$grid.attr('aria-activedescendant', this.calendarName + '-' + lastDay); 3620 3621 e.stopPropagation(); 3622 return false; 3623 } 3624 } 3625 3626 return true; 3627 3628} // end handleGridKeyDown() 3629 3630//
3631// handleGridKeyPress() is a member function to consume keypress events for browsers that 3632// use keypress to scroll the screen and manipulate tabs 3633// 3634// @input (e obj) e is the event object associated with the event 3635// 3636// @return (boolean) false if consuming event, true if propagating 3637// 3638swDatepicker.prototype.handleGridKeyPress = function (e) { 3639 3640 if (e.altKey) { 3641 return true; 3642 } 3643 3644 switch (e.keyCode) { 3645 case this.keys.tab: 3646 case this.keys.enter: 3647 case this.keys.space: 3648 case this.keys.esc: 3649 case this.keys.left: 3650 case this.keys.right: 3651 case this.keys.up: 3652 case this.keys.down: 3653 case this.keys.pageup: 3654 case this.keys.pagedown: 3655 case this.keys.home: 3656 case this.keys.end: { 3657 e.stopPropagation(); 3658 return false; 3659 } 3660 } 3661 3662 return true; 3663 3664} // end handleGridKeyPress() 3665 3666// 3667// handleGridClick() is a member function to process mouse click events for the datepicker grid 3668// 3669// @input (id obj) e is the id of the object triggering the event 3670// 3671// @input (e obj) e is the event object associated with the event 3672// 3673// @return (boolean) false if consuming event, true if propagating 3674// 3675swDatepicker.prototype.handleGridClick = function (id, e) { 3676 var $cell = $(id); 3677 3678 if ($cell.is('.empty')) { 3679 return true; 3680 } 3681 3682 this.$grid.find('.focus').removeClass('focus').attr('aria-selected', 'false'); 3683 $cell.addClass('focus').attr('aria-selected', 'true'); 3684 this.$grid.attr('aria-activedescendant', $cell.attr('id')); 3685 3686 var $curDay = $('#' + this.$grid.attr('aria-activedescendant')); 3687 3688 /*console.log($curDay); 3689 var isLastMonth = $curDay.hasClass('last-month'); 3690 3691 var monthSelected = this.month + 1; 3692 var yearSelected = this.year; 3693 3694 if (isLastMonth) { 3695 monthSelected--; 3696 3697 if (monthSelected == 0) 3698 monthSelected = 12; 3699 3700 yearSelected = $curDay.data('year'); 3701 } 3702 3703 console.log("month selected: " + monthSelected); 3704 console.log("year selected: " + yearSelected);*/ 3705 3706 // update the target box 3707 if(this.type == 'dateRangeSelect'){ 3708 if ($curDay.hasClass('muted')) 3709 return true; 3710 3711 var $rangeSelDate = new Date((this.month + 1) + '/' + $curDay.children('.calendar-day').text() + '/' + this.year); 3712 if(this.fromDateRange == '' && this.toDateRange == ''){ 3713 //no dates selected yet, store this in the from date range for now 3714 this.fromDateRange = $rangeSelDate; 3715 }else{ 3716 //we've previously selected at least one date here, so figure out which one it should be 3717 if($rangeSelDate < this.fromDateRange){ 3718 this.toDateRange = this.fromDateRange; 3719 this.fromDateRange = $rangeSelDate; 3720 }else{ 3721 this.toDateRange = $rangeSelDate; 3722 } 3723 } 3724 3725 var objDateRange = {} 3726 objDateRange.from = this.fromDateRange; 3727 objDateRange.to = this.toDateRange; 3728 this.$target.val(JSON.stringify(objDateRange)).change(); 3729 if(objDateRange.from != '' && objDateRange.to != ''){ 3730 this.hideDlg(); //NOTE: this only works if the date range is a modal, for other calendars you'll need to manage display according to needs based on current values. 3731 } 3732 e.stopPropagation(); 3733 return false; 3734 } 3735 if (!this.forceDateSelection || $cell.hasClass("highlight-day")) { 3736 this.$target.val((this.month + 1) + '/' + $curDay.children('.calendar-day').text() + '/' + this.year).change(); 3737 // dismiss the dialog box 3738 this.hideDlg(); 3739 } 3740 e.stopPropagation(); 3741 return false; 3742 3743} // end handleGridClick() 3744 3745// 3746// handleGridFocus() is a member function to process focus events for the datepicker grid 3747// 3748// @input (e obj) e is the event object associated with the event 3749// 3750// @return (boolean) true 3751// 3752swDatepicker.prototype.handleGridFocus = function (e) { 3753 var active = this.$grid.attr('aria-activedescendant'); 3754 3755 if ($('#' + active).attr('id') == undefined) { 3756 var lastDay = 'day' + this.calcNumDays(this.year, this.month); 3757 $('#' + lastDay).addClass('focus').attr('aria-selected', 'true'); 3758 } 3759 else { 3760 $('#' + active).addClass('focus').attr('aria-selected', 'true'); 3761 } 3762 3763 return true; 3764 3765} // end handleGridFocus() 3766 3767// 3768// handleGridBlur() is a member function to process blur events for the datepicker grid 3769// 3770// @input (e obj) e is the event object associated with the event 3771// 3772// @return (boolean) true 3773// 3774swDatepicker.prototype.handleGridBlur = function (e) { 3775 $('#' + this.$grid.attr('aria-activedescendant')).removeClass('focus').attr('aria-selected', 'false'); 3776 3777 return true; 3778 3779} // end handleGridBlur() 3780 3781//
3782// showDlg() is a member function to show the datepicker and give it focus. This function is only called if 3783// the datepicker is used in modal dialog mode. 3784// 3785// @return N/A 3786// 3787swDatepicker.prototype.showDlg = function () { 3788 if (!this.bModal) 3789 return; 3790 3791 var thisObj = this; 3792 var thisNode = this.$id; 3793 3794 this.highlightDays(); 3795 3796 this.active = true; 3797 3798 //prevent calendar from pushing out of the right side of the window 3799 if (thisNode.parent()[0].getBoundingClientRect().left > (window.innerWidth / 2)) 3800 thisNode.addClass("right-side"); 3801 3802 $(".content-wrap").bind('click', function (e) { 3803 if (!thisNode[0].contains(e.target) && e.target != thisObj.$target[0]) { 3804 thisObj.hideDlg(); 3805 } 3806 }); 3807 3808 // show the dialog 3809 this.$id.attr('aria-hidden', 'false'); 3810 3811 this.$grid.focus(); 3812 3813} // end showDlg() 3814 3815// 3816// hideDlg() is a member function to hide the datepicker and remove focus. This function is only called if 3817// the datepicker is used in modal dialog mode. 3818// 3819// @return N/A 3820// 3821swDatepicker.prototype.hideDlg = function () { 3822 if (!this.bModal) 3823 return; 3824 3825 this.active = false; 3826 var thisNode = this.$id; 3827 3828 // unbind the modal event sinks 3829 $(document).unbind('click'); 3830 3831 // hide the dialog 3832 this.$id.attr('aria-hidden', 'true'); 3833 3834 // set focus on the focus target 3835 //this.$target.focus(); 3836 3837} // end showDlg() 3838 3839//function to highlight days with performances or valid information 3840//to prevent rewriting the calendar each time a date is added, popGrid() should be called after all dates have been added 3841swDatepicker.prototype.addHighlightDay = function (date) { 3842 var datesplit = String(date).split("/"); 3843 for(var i = 0;i < datesplit.length; i++){ 3844 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3845 } 3846 date = datesplit.join("/"); 3847 if (datesplit.length != 3) { 3848 //date didn't come in in m/d/yyyy format, kick it back in the console 3849 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3850 console.log(date); 3851 return; 3852 3853 } 3854 this.highlightDates.push(date); 3855 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3856 $("#" + this.calendarName + "-day" + datesplit[1]).addClass("highlight-day"); 3857 } 3858} 3859swDatepicker.prototype.addDateInfoBox = function (date, infoBoxText) { 3860 var datesplit = String(date).split("/"); 3861 for(var i = 0;i < datesplit.length; i++){ 3862 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3863 } 3864 date = datesplit.join("/"); 3865 if (datesplit.length != 3) { 3866 //date didn't come in in m/d/yyyy format, kick it back in the console 3867 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3868 console.log(date); 3869 return; 3870 3871 } 3872 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3873 $("#" + this.calendarName + "-day" + datesplit[1]).append('<span class="date-info-box">' + infoBoxText + '</span>'); 3874 } 3875} 3876swDatepicker.prototype.addDateSubNote = function (date, noteText) { 3877 var datesplit = String(date).split("/"); 3878 for(var i = 0;i < datesplit.length; i++){ 3879 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3880 } 3881 date = datesplit.join("/"); 3882 if (datesplit.length != 3) { 3883 //date didn't come in in m/d/yyyy format, kick it back in the console 3884 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3885 console.log(date); 3886 return; 3887 3888 } 3889 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3890 var spanClass = this.isMultiplePerformanceIndicator ? 'date-info-box date-sub-note multiple-performancetime-subnote' : 'date-info-box date-sub-note'; 3891 $("#" + this.calendarName + "-day" + datesplit[1]).append('<span class="' + spanClass + '">' + noteText + '</span>'); 3892 } 3893} 3894swDatepicker.prototype.setDaySoldOut = function (date) { 3895 var datesplit = String(date).split("/"); 3896 for(var i = 0;i < datesplit.length; i++){ 3897 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3898 } 3899 date = datesplit.join("/"); 3900 if (datesplit.length != 3) { 3901 //date didn't come in in m/d/yyyy format, kick it back in the console 3902 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3903 console.log(date); 3904 return; 3905 3906 } 3907 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3908 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('sold-out'); 3909 3910 this.addDateInfoBox(date, "Sold Out"); 3911 $("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 3912 } 3913} 3914swDatepicker.prototype.setcustomStatus = function (date,showPhoneNumber,currenStatus) { 3915 var datesplit = String(date).split("/"); 3916 for(var i = 0;i < datesplit.length; i++){ 3917 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3918 } 3919 date = datesplit.join("/"); 3920 if (datesplit.length != 3) { 3921 //date didn't come in in m/d/yyyy format, kick it back in the console 3922 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3923 console.log(date); 3924 return; 3925 3926 } 3927 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3928 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('sold-out'); 3929 var phoneNumber = " <br> [email protected] " 3930 if (!showPhoneNumber) 3931 phoneNumber=""; 3932 this.addDateInfoBox(date, currenStatus +phoneNumber); 3933 3934 $("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 3935 } 3936} 3937swDatepicker.prototype.setDayLimitedAvailabilty = function (date) { 3938 var datesplit = String(date).split("/"); 3939 for(var i = 0;i < datesplit.length; i++){ 3940 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3941 } 3942 date = datesplit.join("/"); 3943 if (datesplit.length != 3) { 3944 //date didn't come in in m/d/yyyy format, kick it back in the console 3945 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3946 console.log(date); 3947 return; 3948 3949 } 3950 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3951 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('limited-availability'); 3952 3953 this.addDateSubNote(date, 'Selling Quickly'); 3954 //$("#" + this.calendarName + "-day" + datesplit[1]).children(".date-info-box").removeClass("date-info-box").addClass("sold-out-info-box"); 3955 } 3956 if($(".limited-availability-legend-item").length == 0){ 3957 3958 $(".calendar-notes-wrap").append('<div class="limited-availability-legend-item"><span classs="calendar-limited-availability-legend-icon">!</span> - Selling Quickly</div>') 3959 3960 // $("#streamlinedCalendarLimitedAvailabilityLegend").append('<div class="limited-availability-legend-item"><span class="calendar-limited-availability-legend-icon">!</span> - Selling Quickly</div>') 3961 } 3962} 3963swDatepicker.prototype.setMultiplePerformanceTimes = function (date) { 3964 var datesplit = String(date).split("/"); 3965 for(var i = 0;i < datesplit.length; i++){ 3966 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3967 } 3968 3969 date = datesplit.join("/"); 3970 if (datesplit.length != 3) { 3971 //date didn't come in in m/d/yyyy format, kick it back in the console 3972 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3973 return; 3974 3975 } 3976 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3977 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('multipleperformancetimes'); 3978 3979 } 3980 if($(".multiple-performancetimes-notes").length == 0){ 3981 3982 } 3983 3984} 3985swDatepicker.prototype.setMutedDay = function (date) { 3986 var datesplit = String(date).split("/"); 3987 for(var i = 0;i < datesplit.length; i++){ 3988 datesplit[i] = datesplit[i].replace(/^0+/, ''); 3989 } 3990 date = datesplit.join("/"); 3991 if (datesplit.length != 3) { 3992 //date didn't come in in m/d/yyyy format, kick it back in the console 3993 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 3994 return; 3995 3996 } 3997 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 3998 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('muted'); 3999 } 4000} 4001swDatepicker.prototype.clearMutedDay = function (date) { 4002 var datesplit = String(date).split("/"); 4003 for(var i = 0;i < datesplit.length; i++){ 4004 datesplit[i] = datesplit[i].replace(/^0+/, ''); 4005 } 4006 date = datesplit.join("/"); 4007 if (datesplit.length != 3) { 4008 //date didn't come in in m/d/yyyy format, kick it back in the console 4009 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 4010 return; 4011 4012 } 4013 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 4014 $("#" + this.calendarName + "-day" + datesplit[1]).removeClass('muted'); 4015 } 4016} 4017swDatepicker.prototype.setCouponMutedDay = function (date) { 4018 var datesplit = String(date).split("/"); 4019 for(var i = 0;i < datesplit.length; i++){ 4020 datesplit[i] = datesplit[i].replace(/^0+/, ''); 4021 } 4022 date = datesplit.join("/"); 4023 if (datesplit.length != 3) { 4024 //date didn't come in in m/d/yyyy format, kick it back in the console 4025 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 4026 return; 4027 4028 } 4029 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 4030 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('coupon-muted'); 4031 } 4032}
4033swDatepicker.prototype.setPasswordHiddenDay = function (date) { 4034 var datesplit = String(date).split("/"); 4035 for(var i = 0;i < datesplit.length; i++){ 4036 datesplit[i] = datesplit[i].replace(/^0+/, ''); 4037 } 4038 date = datesplit.join("/"); 4039 if (datesplit.length != 3) { 4040 //date didn't come in in m/d/yyyy format, kick it back in the console 4041 console.log("invalid date sent, datepicker accepts m/d/yyyy only - " + date); 4042 return; 4043 4044 } 4045 if (parseInt(datesplit[0]) - 1 == this.month && parseInt(datesplit[2]) == this.year) { 4046 $("#" + this.calendarName + "-day" + datesplit[1]).addClass('password-hidden'); 4047 $("#" + this.calendarName + "-day" + datesplit[1]).removeClass('highlight-day'); 4048 } 4049} 4050swDatepicker.prototype.clearAllMutedDays = function () { 4051 $(".muted").removeClass('muted'); 4052} 4053swDatepicker.prototype.clearHighlightDays = function () { 4054 this.highlightDates = []; 4055 this.highlightDays(); 4056} 4057//highlights all days in the highlightDates array 4058swDatepicker.prototype.highlightDays = function () { 4059 $("#" + this.calendarName + " .highlight-day").removeClass("highlight-day"); 4060 var curYear = this.year; 4061 var curMonth = this.month; 4062 var calName = this.calendarName; 4063 var IEFix = new RegExp(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g); 4064 4065 this.highlightDates.forEach(function (o, i, a) { 4066 var datesplit = o.split("/"); 4067 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 4068 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '')).addClass("highlight-day"); 4069 } 4070 }); 4071 this.setColors(); 4072} 4073swDatepicker.prototype.setColors = function () { 4074 /* 4075 Custom color functionality. Utilized by dropping calendar-colors.txt file in root of custom folder 4076 requires json content of text file formatted as follows: 4077 { 4078 "events": 4079 {"528": 4080 [ 4081 {"date":"12/1/2025", "color": "#ccc"}, 4082 {"date":"12/2/2025", "color": "#ccc"} 4083 ] 4084 , 4085 "529": 4086 [ 4087 {"date":"12/8/2025", "color": "#ccc"}, 4088 {"date":"12/9/2025", "color": "#ccc"} 4089 ] 4090 } 4091 , 4092 "bundles":[], 4093 "generic": 4094 {"dates": 4095 [ 4096 {"date":"12/23/2025", "color": "#def"}, 4097 {"date":"12/22/2025", "color": "#1a1"} 4098 ] 4099 , 4100 "weekdays": 4101 [ 4102 {"day":"Saturday", "color": "#2a2"}, 4103 {"day":"Thursday", "color": "#3a3"} 4104 ] 4105 } 4106 } 4107 } 4108 */ 4109 var thisDP = this; 4110 try{ 4111 $.getJSON("/calendar-colors.txt") 4112 .done(function (data) { 4113 thisDP.renderColors(data); 4114 }) 4115 .fail(function (jqxhr, textStatus, error) { 4116 console.log("No Custom Calendar Colors Found"); 4117 return; 4118 }); 4119 }catch(e){ 4120 console.log("parsing error:"); 4121 console.log(e); 4122 return; 4123 } 4124} 4125swDatepicker.prototype.renderColors = function (colorData) { 4126 var curYear = this.year; 4127 var curMonth = this.month; 4128 var calName = this.calendarName; 4129 var IEFix = new RegExp(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g); 4130 //set generic colors 4131 if(colorData.generic){ 4132 if(colorData.generic.dates.length > 0){ 4133 colorData.generic.dates.forEach(function (o, i, a) { 4134 var datesplit = o.date.split("/"); 4135 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 4136 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 4137 } 4138 }); 4139 } 4140 if(colorData.generic.weekdays && colorData.generic.weekdays.length > 0){ 4141 colorData.generic.weekdays.forEach(function (o, i, a) { 4142 $("td[headers*=" + o.day + "] .calendar-day").css("background-color", o.color); 4143 }); 4144 } 4145 } 4146 if(colorData.events && colorData.events[this.eventID] && this.eventID !== -1){
4147 colorData.events[this.eventID].forEach(function (o, i, a) { 4148 var datesplit = o.date.split("/"); 4149 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 4150 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 4151 } 4152 }); 4153 } 4154 if(colorData.bundles && colorData.bundles[this.bundleID] && this.bundleID !== -1){ 4155 colorData.bundles[this.bundleID].forEach(function (o, i, a) { 4156 var datesplit = o.date.split("/"); 4157 if (parseInt(datesplit[0].replace(IEFix, '')) - 1 == parseInt(curMonth) && parseInt(datesplit[2].replace(IEFix, '')) == parseInt(curYear)) { 4158 $("#" + calName + "-day" + datesplit[1].replace(IEFix, '') + ' .calendar-day').css("background-color", o.color); 4159 } 4160 }); 4161 } 4162} 4163swDatepicker.prototype.fetchDates = function(){ 4164 var thisCalendar = this; 4165 var haveDates = thisCalendar.fetchLocalDates(); 4166 if (thisCalendar.categoryID >= 0) 4167 haveDates = false; 4168 this.clearHighlightDays(); 4169 if(haveDates){ 4170 //valid local dates stored 4171 try{ 4172 haveDates = JSON.parse(haveDates); 4173 if (haveDates.length > 0) { 4174 haveDates.forEach(function(o){ 4175 thisCalendar.addHighlightDay(o); 4176 }) 4177 thisCalendar.highlightDays(); 4178 } 4179 } catch (e) { 4180 console.log("Failed to grab dates. Date object not valid: ", haveDates); 4181 console.log(e); 4182 } 4183 } else { 4184 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 4185 { 4186 action: thisCalendar.type, 4187 calMonth: thisCalendar.activeMonth, 4188 iEvent: thisCalendar.eventID, 4189 iBundle: thisCalendar.bundleID, 4190 iCategory : thisCalendar.categoryID, 4191 cp : thisCalendar.corporatePartnerPage 4192 }) 4193 .done(function (data) { 4194 thisCalendar.storeDates(data.performancedates); 4195 try { 4196 if (data.performancedates.length > 0) { 4197 data.performancedates.forEach(function (o) { 4198 4199 thisCalendar.addHighlightDay(o); 4200 }) 4201 thisCalendar.highlightDays(); 4202 } 4203 } catch (e) { 4204 console.log("Failed to grab dates. Date object not valid: " + haveDates); 4205 console.log(e); 4206 } 4207 $(".calendar-loading").hide(); 4208 }) 4209 .fail(function (jqxhr, textStatus, error) { 4210 var err = textStatus + ", " + error; 4211 console.log("Request Failed: " + err); 4212 $(".calendar-loading").hide(); 4213 }); 4214 } 4215} 4216swDatepicker.prototype.getCalendarDetails = function(){ 4217 var thisCalendar = this; 4218 this.clearHighlightDays(); 4219 $("#" + this.calendarName).removeClass("has-muted-days"); 4220 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 4221 { 4222 action: thisCalendar.type, 4223 calMonth: thisCalendar.activeMonth, 4224 iEvent: thisCalendar.eventID, 4225 iBundle: thisCalendar.bundleID, 4226 iCategory : thisCalendar.categoryID, 4227 cp : thisCalendar.corporatePartnerPage, 4228 bValidCoupon : thisCalendar.bValidCoupon, 4229 couponCode : thisCalendar.couponCode 4230 }) 4231 .done(function (data) { 4232 //to save on request time, we need to resolve the data on the client a bit before we store it 4233 var performanceDates = []; 4234 data.performanceDateData.forEach(function(dd){ 4235 4236 if(dd.DoNotShowPublic == 0){ 4237 var detailsObj = {}; 4238 var currentDateIndex = fetchDateIndex(dd.CalendarDate, performanceDates); 4239 if(currentDateIndex == -1){ 4240 detailsObj.date = dd.CalendarDate; 4241 detailsObj.performances = []; 4242 detailsObj.performances.push(dd.PerformanceCode); 4243 detailsObj.defaultPrice = dd.LowestDefaultPrice; 4244 detailsObj.PerformanceName = dd.PerformanceName; 4245 detailsObj.PerformanceTime = dd.PerfTime; 4246 detailsObj.PerformanceStartTimeAlias = dd.PerformanceStartTimeAlias; 4247 detailsObj.DisplayType = dd.DisplayType; 4248 detailsObj.CalendarViewShowPrice = dd.CalendarViewShowPrice; 4249 detailsObj.CalendarViewShowPerformanceName = dd.CalendarViewShowPerformanceName; 4250 detailsObj.CalendarViewShowPerformanceTime = dd.CalendarViewShowPerformanceTime; 4251 detailsObj.CalendarViewShowBuyButton = dd.CalendarViewShowBuyButton; 4252 detailsObj.defaultPricingCode = dd.LowestDefaultPricingCode; 4253 detailsObj.secondaryPrice = dd.LowestSecondaryPrice; 4254 detailsObj.secondaryPricingCode =dd.LowestSecondaryPricingCode; 4255 detailsObj.NoCouponAvailable = dd.NoCouponAvailable; 4256 detailsObj.passwordMatch = dd.passwordMatch; 4257 detailsObj.qualifierPasswordMatch = dd.qualifierPasswordMatch; 4258 detailsObj.hasPassword = dd.hasPassword; 4259 detailsObj.hasQualifierPassword = dd.hasQualifierPassword; 4260 detailsObj.hasCoupons = dd.hasCoupons; 4261 detailsObj.IsSalesPeriodEnded = dd.IsSalesPeriodEnded; 4262 detailsObj.SaleIcon = dd.SaleIcon; 4263 detailsObj.BSaleIcon = dd.BSaleIcon; 4264 4265 detailsObj.hasQualifiers = dd.hasQualifiers;
4266 performanceDates.push(detailsObj) 4267 4268 }else{ 4269 performanceDates[currentDateIndex].performances.push(dd.PerformanceCode); 4270 performanceDates[currentDateIndex].NoCouponAvailable = dd.NoCouponAvailable; 4271 performanceDates[currentDateIndex].passwordMatch = dd.passwordMatch; 4272 performanceDates[currentDateIndex].acMatch = dd.acMatch; 4273 performanceDates[currentDateIndex].qualifierPasswordMatch = dd.qualifierPasswordMatch; 4274 performanceDates[currentDateIndex].hasPassword = dd.hasPassword; 4275 performanceDates[currentDateIndex].hasQualifierPassword = dd.hasQualifierPassword; 4276 performanceDates[currentDateIndex].hasCoupons = dd.hasCoupons; 4277 performanceDates[currentDateIndex].PerformanceName = dd.PerformanceName; 4278 performanceDates[currentDateIndex].PerformanceTime = dd.PerfTime; 4279 performanceDates[currentDateIndex].PerformanceStartTimeAlias = dd.PerformanceStartTimeAlias; 4280 performanceDates[currentDateIndex].CalendarViewShowPrice = dd.CalendarViewShowPrice; 4281 performanceDates[currentDateIndex].CalendarViewShowPerformanceName = dd.CalendarViewShowPerformanceName; 4282 performanceDates[currentDateIndex].CalendarViewShowPerformanceTime = dd.CalendarViewShowPerformanceTime; 4283 performanceDates[currentDateIndex].CalendarViewShowBuyButton = dd.CalendarViewShowBuyButton; 4284 performanceDates[currentDateIndex].IsSalesPeriodEnded = dd.IsSalesPeriodEnded; 4285 performanceDates[currentDateIndex].SaleIcon = dd.SaleIcon; 4286 performanceDates[currentDateIndex].BSaleIcon = dd.BSaleIcon; 4287 performanceDates[currentDateIndex].hasQualifiers = dd.hasQualifiers; 4288 //check for lowest price 4289 if(performanceDates[currentDateIndex].defaultPrice > dd.LowestDefaultPrice && dd.LowestDefaultPrice != null){ 4290 performanceDates[currentDateIndex].defaultPrice = dd.LowestDefaultPrice; 4291 performanceDates[currentDateIndex].defaultPricingCode = dd.LowestDefaultPricingCode; 4292 } 4293 if(performanceDates[currentDateIndex].hasCoupons == 1 && performanceDates[currentDateIndex].defaultPrice < dd.LowestDefaultPrice && dd.LowestDefaultPrice != null && false){ 4294 performanceDates[currentDateIndex].defaultPrice = dd.LowestDefaultPrice; 4295 performanceDates[currentDateIndex].defaultPricingCode = dd.LowestDefaultPricingCode; 4296 } 4297 if(performanceDates[currentDateIndex].secondaryPrice > dd.LowestSecondaryPrice && dd.LowestSecondaryPrice != null){ 4298 performanceDates[currentDateIndex].secondaryPrice = dd.LowestSecondaryPrice; 4299 performanceDates[currentDateIndex].secondaryPricingCode = dd.LowestSecondaryPricingCode; 4300 } 4301 4302 4303 } 4304 //set limited availaibility by matching up results from query with performances 4305 for(perf in data.performances){ 4306 if(data.performances[perf].id == dd.PerformanceID){ 4307 data.performances[perf].LimitedAvailability = dd.LimitedAvailability; 4308 data.performances[perf].TimeZone = dd.TimeZone.replace('"', ""); 4309 data.performances[perf].SingleAreaVenueAreaID = dd.SingleAreaVenueAreaID; 4310 data.performances[perf].NoCouponAvailable = dd.NoCouponAvailable; 4311 data.performances[perf].passwordMatch = dd.passwordMatch; 4312 data.performances[perf].acMatch = dd.acMatch; 4313 data.performances[perf].qualifierPasswordMatch = dd.qualifierPasswordMatch; 4314 data.performances[perf].hasPassword = dd.hasPassword; 4315 data.performances[perf].hasQualifierPassword = dd.hasQualifierPassword; 4316 } 4317 } 4318 } 4319 4320 }) 4321 4322 data.performanceDates = performanceDates; 4323 delete data.performanceDateData; 4324 try { 4325 if (thisCalendar.couponCode != "" && $("#couponCode").length > 0) 4326 { 4327 if($("#coupon-notify").length > 0) 4328 $("#coupon-notify").remove(); 4329 4330 var notifyMessage = document.createElement("div"); 4331 notifyMessage.setAttribute("id","coupon-notify"); 4332 notifyMessage.setAttribute("class",data.hasValidCoupon ? 'coupon-notify-message' : 'coupon-error-message'); 4333 notifyMessage.innerHTML = (data.hasValidCoupon ? "Code <b>" + thisCalendar.couponCode + "</b> has been applied to valid dates and times." : "The code entered is either invalid, or no longer available."); 4334 $("#plCalendar").prepend(notifyMessage); 4335 window.scrollTo(0,0); 4336 } 4337 4338 thisCalendar.doCalendarDetailed(data); 4339 } catch (e) { 4340 console.log("Failed to parse details. Date object not valid: ", data); 4341 console.log(e); 4342 } 4343 }) 4344 .fail(function (jqxhr, textStatus, error) { 4345 var err = textStatus + ", " + error; 4346 console.log("Request Failed: " + err); 4347 }); 4348} 4349swDatepicker.prototype.doCalendarDetailed = function(detailData){ 4350 var thisCalendar = this; 4351 this.detailData = detailData; 4352 var defaultPricingLegend = [], secondaryPricingLegend = [];
4353 detailData.performanceDates.forEach(function(d){ 4354 thisCalendar.addHighlightDay(d.date); 4355 if (d.NoCouponAvailable > 0) 4356 thisCalendar.setCouponMutedDay(d.date); 4357 4358 //check if date sold out 4359 var dateSoldOut = true; 4360 var customStatus = false; 4361 var showPhoneNumber =false; 4362 var dateLimitedAvailability = false; 4363 var performanceStatus=""; 4364 var performanceOnSale = false; 4365 var IsSalesPeriodEnded = false; 4366 var aggregatedMentaInfo = { 4367 buttonVisible: false, 4368 buttonText: "", 4369 buttonUrl: "", 4370 totalCount: 0 4371 }; 4372 4373 var isMentaResaleAvailable = false; 4374 var performanceTimesLength = 0; 4375 var QualiferButton = false; 4376 d.performances.forEach(function(datePerformance){ 4377 var performanceKey = String(datePerformance).toLowerCase(); 4378 var currentPerformance = detailData.performances[performanceKey]; 4379 4380 if (!currentPerformance) { 4381 var perfIndex = d.performances.indexOf(datePerformance); 4382 if (perfIndex !== -1) { 4383 d.performances.splice(perfIndex, 1); 4384 } 4385 console.log("Date Trimmed, child performance not contained in performance data: " + datePerformance); 4386 return; 4387 } 4388 4389 //let currentPerformance = detailData.performances[String(datePerformance).toLowerCase()]; 4390 performanceTimesLength ++; 4391 4392 if(detailData.performances[String(datePerformance).toLowerCase()] && detailData.performances[String(datePerformance).toLowerCase()].status == "On Sale"){ 4393 dateSoldOut = false; 4394 performanceOnSale=true; 4395 if(currentPerformance.LimitedAvailability == 1) 4396 dateLimitedAvailability = true; 4397 4398 IsSalesPeriodEnded = currentPerformance.IsSalesPeriodEnded==1 4399 } 4400 else{ 4401 4402 if ((currentPerformance.status != "Sold Out") && (currentPerformance.status != "On Sale") ){ 4403 4404 customStatus=true; 4405 performanceStatus=currentPerformance.status; 4406 dateSoldOut = false; 4407 //dateLimitedAvailability=false; 4408 if ( currentPerformance.bSalePhone==1 || currentPerformance.SalePhone==1){ 4409 showPhoneNumber=true; 4410 } 4411 } 4412 var mentaMarketplace = currentPerformance.MentaMarketplace; 4413 var hasMentaOption = currentPerformance.IsMentaEnabled == 1 && mentaMarketplace && mentaMarketplace.buttonVisible; 4414 4415 if (hasMentaOption) { 4416 var availableCount = parseInt(mentaMarketplace.totalCount, 10); 4417 if (!isNaN(availableCount) && availableCount > 0) { 4418 aggregatedMentaInfo.totalCount += availableCount; 4419 } 4420 if (mentaMarketplace.buttonText && aggregatedMentaInfo.buttonText === "") { 4421 aggregatedMentaInfo.buttonText = mentaMarketplace.buttonText; 4422 } 4423 if (mentaMarketplace.buttonUrl && aggregatedMentaInfo.buttonUrl === "") { 4424 aggregatedMentaInfo.buttonUrl = mentaMarketplace.buttonUrl; 4425 } 4426 aggregatedMentaInfo.buttonVisible = true; 4427 dateSoldOut = false; 4428 showPhoneNumber=false; 4429 customStatus=true; 4430 } 4431 } 4432 4433 // If date is sold out or custom status (not 'on sale'), check if qualifier access code or password match 4434 if (dateSoldOut || customStatus) { 4435 if (currentPerformance.acMatch == 1 || (currentPerformance.qualifierPasswordMatch == 1 && currentPerformance.hasQualifierPassword == 1)) { 4436 dateSoldOut = false; 4437 customStatus = false; 4438 performanceOnSale = true; 4439 showPhoneNumber = false; 4440 } 4441 } 4442 // If date is sold out or custom status (not 'on sale'), check if it has a public qualifier -- hasQualifiers is set on CalendarRequests.asp when qualifiers exist for performance 4443 if (currentPerformance.hasQualifiers) { 4444 dateSoldOut = false; 4445 customStatus = false; 4446 performanceOnSale = true; 4447 showPhoneNumber = false; 4448 QualiferButton = true; 4449 // If performance has qualifier but status is "On Sale", do not show "Premium Access" text on calendar date 4450 if (currentPerformance.status == "On Sale") { 4451 QualiferButton = false; 4452 } 4453 4454 } 4455 }) 4456 4457 if (aggregatedMentaInfo.buttonVisible && aggregatedMentaInfo.buttonText === "") { 4458 aggregatedMentaInfo.buttonText = "Official Resale Available"; 4459 } 4460 var hasMentaCtaForDate = aggregatedMentaInfo.buttonVisible && (aggregatedMentaInfo.totalCount > 0 || aggregatedMentaInfo.buttonUrl !== ""); 4461 isMentaResaleAvailable = hasMentaCtaForDate && !performanceOnSale; 4462 d.MentaMarketplace = aggregatedMentaInfo; 4463 4464 if(dateLimitedAvailability && !dateSoldOut){ 4465 thisCalendar.setDayLimitedAvailabilty(d.date); 4466 } 4467 if (thisCalendar.isMultiplePerformanceIndicator == 1 && performanceTimesLength > 1) { 4468 thisCalendar.setMultiplePerformanceTimes(d.date); 4469 } 4470 if ( IsSalesPeriodEnded) { 4471 performanceStatus=d.SaleIcon; 4472 } 4473 else{ 4474 if(isMentaResaleAvailable && !performanceOnSale){ 4475 4476 thisCalendar.addDateSubNote(d.date, 'Sold Out'); 4477 //thisCalendar.setDaySoldOut(d.date); 4478 //thisCalendar.addDateInfoBox(d.date, "Sold Out"); 4479 thisCalendar.configureMentaSettings(d); 4480 } 4481 else{ 4482 performanceStatus=d.BSaleIcon; 4483 } 4484 4485 } 4486 4487 if (performanceStatus == null || performanceStatus == "") 4488 performanceStatus="sold out"; 4489 4490 if(dateSoldOut){ 4491 thisCalendar.setDaySoldOut(d.date); 4492 }else{ 4493 if ( (customStatus && !dateLimitedAvailability && !performanceOnSale && !isMentaResaleAvailable) || IsSalesPeriodEnded) 4494 { 4495 thisCalendar.setcustomStatus(d.date,showPhoneNumber,performanceStatus) 4496 } 4497 else{ 4498 //date not sold out, add details, add to legend if one exists 4499 var detailString = ""; 4500 4501 // if the price option is checked in event landing page in the admin 4502 if(d.CalendarViewShowPrice != 0){ 4503 //for now, we'll just add the pricing, this would be a spot to modify what is displayed on the dates by changing the contents of this string 4504 if(d.defaultPrice != null){ 4505 if (QualiferButton) { // SHOWDEV-22142 - If date has public qualifier, show qualifier text (Premium Access) instead of price and buy button 4506 detailString = detailString + "<span class='display-perfbuybutton'>Premium Access</span>"; 4507 }else { 4508 4509 detailString = "<span class='display-perfprice'>" + thisCalendar.currencySymbol + d.defaultPrice.toFixed(2).replace('.00','') + "</span>"; 4510 4511 } 4512 4513 if(defaultPricingLegend.indexOf(d.defaultPricingCode) === -1) 4514 defaultPricingLegend.push(d.defaultPricingCode); 4515 } 4516 if(d.secondaryPricingCode != "" && d.secondaryPricingCode != null){ 4517 if(secondaryPricingLegend.indexOf(d.secondaryPricingCode) === -1) 4518 secondaryPricingLegend.push(d.secondaryPricingCode); 4519 4520 if (d.DisplayType === "calendar" || d.DisplayType === "streamlined") { 4521 4522 detailString = "<span class='display-perfprice-withchild'>" + thisCalendar.currencySymbol + d.secondaryPrice.toFixed(2).replace('.00','') + "/</span>" + detailString; 4523 4524 } 4525 } 4526 } 4527 if(d.CalendarViewShowPerformanceName != 0){ 4528 detailString = detailString + "<span class='display-perfname'>" + d.PerformanceName + "</span> "; 4529 } 4530 4531 if(d.CalendarViewShowPerformanceTime != 0){ 4532 if(d.PerformanceStartTimeAlias != ""){ // Performance Alias time is present 4533 detailString = detailString + " <span class='display-perft
4533ime'>" + d.PerformanceStartTimeAlias + "</span>"; 4534 } else { 4535 detailString = detailString + " <span class='display-perftime'>" + d.PerformanceTime + "</span>"; 4536 } 4537 4538 } 4539 if(d.CalendarViewShowBuyButton != 0){ 4540 var styleString = ""; 4541 if (d.DisplayType === "streamlined") 4542 styleString = " style='width: 100%;'"; 4543 var buttonText = (isMentaResaleAvailable && d.OverrideBuyTicketsButtonText) ? d.OverrideBuyTicketsButtonText : thisCalendar.buyTicketsButtonText; 4544 detailString = detailString + "<span class='button display-perfbuybutton'"+styleString+">" + buttonText + "</span>"; 4545 } 4546 4547 thisCalendar.addDateInfoBox(d.date, detailString); 4548 } 4549 } 4550 4551 }) 4552 //for now, we only generate the legend if there are one or two prices pesent 4553 if(defaultPricingLegend.length === 1 && secondaryPricingLegend.length === 1){ 4554 $("#calendarLegend").html(secondaryPricingLegend[0] +" / " + defaultPricingLegend[0]) 4555 4556 $("#calendarLegend").show(); 4557 }else{ 4558 if(defaultPricingLegend.length === 1){ 4559 $("#calendarLegend").html(defaultPricingLegend[0]) 4560 4561 $("#calendarLegend").show(); 4562 }else{ 4563 $("#calendarLegend").hide(); 4564 } 4565 } 4566 if(typeof(setFilterOptions) == 'function'){ 4567 setFilterOptions(thisCalendar); 4568 } 4569 if (detailData.hasValidCoupon) { 4570 $("#plCalendar").append("<input type='hidden' id='hasValidCoupon' value='1' />"); 4571 } else { 4572 $("#plCalendar").append("<input type='hidden' id='hasValidCoupon' value='0' />"); 4573 } 4574 $(".calendar-loading").hide(); 4575} 4576swDatepicker.prototype.configureMentaSettings = function (dateDetail) { 4577 // Set Menta Resale Settings 4578 4579} 4580 4581swDatepicker.prototype.getFirstDate = function(defaultMonth){ 4582 var thisCalendar = this; 4583 //this should only happen once on calendar load - currently only enabled for bundles 4584 if(thisCalendar.bundleID == 0 || thisCalendar.bundleID == -1) 4585 return defaultMonth; //currently only developed for bundles TODO: add event, category, standard support. 4586 4587 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 4588 { 4589 action: 'initialBundleDate', 4590 iBundle: thisCalendar.bundleID, 4591 cp : thisCalendar.corporatePartnerPage 4592 }) 4593 .done(function (data) { 4594 try { 4595 if (data.performancedates.length > 0) { 4596 4597 4598 var firstMonth = Number(String(data.performancedates).split("/")[0]) - 1; 4599 var firstYear = Number(String(data.performancedates).split("/")[2]); 4600 thisCalendar.month = firstMonth - 1; //to make this simple, we're using the showNextMonth() function, which means we need to set the month to 1 less than our target, as that function increments the month itself 4601 thisCalendar.year = firstYear; 4602 thisCalendar.showNextMonth(); 4603 }else{ 4604 return defaultMonth; 4605 } 4606 }catch(e){ 4607 console.log("getFirstDate returned invalid date. Default used"); 4608 console.log(e); 4609 return defaultMonth; 4610 } 4611 }) 4612 .fail(function (jqxhr, textStatus, error) { 4613 var err = textStatus + ", " + error; 4614 console.log("Request Failed: " + err); 4615 }); 4616} 4617swDatepicker.prototype.fetchLocalDates = function () { 4618 //utliize storage to store months 4619 var CalendarExpireTime = new Date().getTime(); var isExpired = false; var datesData = ""; 4620 var calendarIDString = this.calendarName + this.type + this.eventID + this.bundleID + "-" + this.corporatePartnerPage + "_" + this.activeMonth; 4621 try { 4622 //check for local storage support 4623 isExpired = CalendarExpireTime > Number(localStorage.getItem("CalendarExpireTime_" + calendarIDString)); 4624 if (isExpired) { 4625 //item expired, clear local results 4626 localStorage.setItem("ShowareDates_" + calendarIDString, ""); 4627 localStorage.setItem("CalendarExpireTime_" + calendarIDString, CalendarExpireTime + (1000 * 60 * 30)); //item information expires after 30 minutes 4628 return false; 4629 } 4630 localStorage.setItem("CalendarExpireTime_" + calendarIDString, CalendarExpireTime + (1000 * 60 * 30)); //item information expires after 30 minutes 4631 if (localStorage.getItem("ShowareDates_" + calendarIDString) != null && localStorage.getItem("ShowareDates_" + calendarIDString) != "" && localStorage.getItem("ShowareDates_" + calendarIDString) != []) { 4632 return localStorage.getItem("ShowareDates_" + calendarIDString); 4633 } else { 4634 //date info not stored 4635 return false; 4636 } 4637 } catch (e) { 4638 return false; 4639 } 4640} 4641swDatepicker.prototype.storeDates = function (dateData) { 4642 4643 var calendarIDString = this.calendarName + this.type + this.eventID + this.bundleID + "-" + this.corporatePartnerPage + "_" + this.activeMonth; 4644 try { 4645 localStorage.setItem("ShowareDates_" + calendarIDString, JSON.stringify(dateData)); 4646 } catch (e) { 4647 //no local storage 4648 } 4649} 4650swDatepicker.prototype.getDateRangeEvents = function (dateRangeData) { 4651 var thisCalendar = this; 4652 try{ 4653 $.getJSON("/include/widgets/calendar/calendarRequests.asp", 4654 { 4655 action: 'getDateRangeEvents', 4656 dateRange: JSON.stringify(dateRangeData), 4657 }) 4658 .done(function (data) { 4659 try { 4660 thisCalendar.dateRangeEvents = data; 4661 }catch(e){ 4662 console.log("getDateRangeEvents returned invali
4662d response."); 4663 console.log(data, e); 4664 return []//return empty array; 4665 } 4666 }) 4667 .fail(function (jqxhr, textStatus, error) { 4668 var err = textStatus + ", " + error; 4669 console.log("Request Failed: " + err); 4670 }); 4671 4672 }catch(e){ 4673 console.log("Unable to fetch date range events:", e) 4674 } 4675} 4676swDatepicker.prototype.clearDateRange = function () { 4677 this.fromDateRange = ''; 4678 this.toDateRange = ''; 4679} 4680function fetchDateIndex(dateString, dateObjectArray){ 4681 try{ 4682 for(var i = 0;i < dateObjectArray.length;i++){ 4683 if(dateObjectArray[i].date == dateString){ 4684 return i; 4685 break; 4686 } 4687 } 4688 return -1; 4689 }catch(e){ 4690 //this function requires specific objects with a date property, it will fail otherwise and we'll just return what one would expect from a failed indexof 4691 return -1; 4692 } 4693} 4694function swapMonthDay(d){ 4695 //expects dd/mm/yyyy format 4696 try{ 4697 let splitDate = d.split("/"); 4698 let newDate = splitDate[1] + '/' + splitDate[0] + "/" + splitDate[2]; 4699 return newDate; 4700 }catch(e){ 4701 console.log("could not swap date:",d,e); 4702 return d; 4703 } 4704} 4705 4706</script>
4706 4707<link rel="stylesheet" type="text/css" href="//www.cincyticket.com/include/accessodesign-core-addition.css?ver=20228b0075"> 4708 4709<link rel="stylesheet" type="text/css" href="//www.cincyticket.com/include/style.css?ver=20228b0075"> 4710 4711 <link rel="stylesheet" type="text/css" media="only screen and (max-width: 1024px)" href="//www.cincyticket.com/include/mobile.css?ver=20228b0075"> 4712 4713</head> 4714 4715<body class="body-class default-font"> 4716 4717 <!-- CLIENT Google Tag Manager -->
vendor: 75 bytes, lines 4717-4718
4717 4718 <noscript><iframe src="//www.googletagmanager.com/ns.html?id=
4718GTM-WZ8HC5
vendor: 109 bytes, lines 4718-4720
4718" 4719 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 4720
4720<!-- End CLIENT Google Tag Manager --> 4721 4722 <!-- PRIMARY Google Tag Manager -->
vendor: 79 bytes, lines 4722-4723
4722 4723 <noscript><iframe src="//www.googletagmanager.com/ns.html?id=
4723GTM-MDGF2K
vendor: 117 bytes, lines 4723-4725
4723" 4724 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 4725
4725<!-- End PRIMARY Google Tag Manager --> 4726 4727<div style="position:relative;"> 4728<button class="skip-nav" title="Skip to Main Content">Skip to Main Content</button> 4729</div>
4730<script type="text/javascript"> 4731 $(function(){ 4732 $(".main-container").attr("tabindex", 0); 4733 }) 4734 $(".skip-nav").on("click", function(){ 4735 console.log("s"); 4736 $(".main-container").focus(); 4737 }); 4738</script>
4738 4739
4740<script type="text/javascript"> 4741 window.SW_ADS_CONFIG = { 4742 cacheUrl: "//www.cincyticket.com/data/adLocations/adLocationCache.txt?ver=20228", 4743 writerUrl: "https://www.cincyticket.com/include/modules/Advertising/request/saveAdLocationCache.asp", 4744 logUrl: "https://www.cincyticket.com/include/modules/Advertising/request/logAdImpression.asp" 4745 }; 4746</script>
vendor: 2 bytes, line 4746
4746
4747<script type="text/javascript" src="//www.cincyticket.com/include/modules/Advertising/banner-ads.js?ver=20228"></script>
4747 4748 4749 4750 4751 <div id="page-wrap"><!--Main Page Wrap - Ends in HTMLfooter--> 4752 <div id="fb-root"></div> 4753 4754
4754<script> 4755 (function(d, s, id) { 4756 var js, fjs = d.getElementsByTagName(s)[0]; 4757 if (d.getElementById(id)) return; 4758 js = d.createElement(s); js.id = id; 4759 js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=0"; 4760 fjs.parentNode.insertBefore(js, fjs); 4761 }(document, 'script', 'facebook-jssdk')); 4762 </script>
4762 4763 4764 4765 <!-- BEGIN Mobile Navigation BEGIN --> 4766 <nav class="navigation sw-nav mobile-only"> 4767 <i id="menu-icon" class="sw-icon-menu" style="display:inline-block;" onClick="actMenu();hideWidgets();"></i> 4768 <div class="tab-nav-wrap"> 4769 4770 <a class="tab-nav" HREF="https://www.cincyticket.com/myaccount.asp?gifrompage=1&gitopage=1">my account</a> 4771 </div> 4772 <ul id="mobile-menu" onClick="actMenu();"> 4773 <!--<li><a HREF="/">home</a></li> <!--CLIENT Home URL--> 4774 <li><a HREF="https://www.cincyticket.com/default.asp">ticketing home</a></li> 4775 <li class="mobile-only"><a HREF="https://www.cincyticket.com/myaccount.asp?gifrompage=1&gitopage=1">my account</a></li> 4776 <li class="sw-sep mobile-only"></li> 4777 4778 <li class="sw-sep no-tab"></li> 4779 4780 <li><a onClick="actSearch();actMenu();return 0">search</a></li> 4781 4782 <li class="mobile-calendar-option"><a onClick="actWidget('calendar');return 0;">calendar</a></li> 4783 4784 <li><a onClick="actWidget('categories');return 0;">categories</a></li> 4785 4786 <li><a onClick="actWidget('venues');return 0;">venues</a></li> 4787 4788 <li class="sw-sep"></li> 4789 <li><a HREF="https://www.cincyticket.com/basket.asp">shopping cart</a></li> 4790 4791 <li class="sw-sep"></li> 4792 <li><a href="https://www.cincyticket.net/help">contact us</a></li> 4793 <li><a href="https://www.cincyticket.net/faq">FAQ</a></li> 4794 <li><a href="https://www.cincyticket.net/">Sell Tickets With Us</a></li> 4795 <li class="sw-sep"></li> 4796 <li onClick="actMenu();hideWidgets();"><a >close</a></li> 4797 </ul> 4798 <a style="color:inherit;" href="http://www.cincyticket.com/basket.asp"><i class="sw-icon-basket" style="float:right;"></i></a> 4799 4800 <i class="sw-icon-search" style="float:right;" onClick="actSearch();"></i> 4801 <div id="swSearch" style="display:none;"> 4802 <input type="text" id="swSearchTxt" value="" placeholder="search events, venues, artists etc..." /> 4803
4803<script type="text/javascript"> 4804 $('#swSearchTxt').keyup(function (e) { 4805 if (e.which === 13) { 4806 //update the performance list 4807 updatePerformanceList_Search($("#swSearchTxt").val()) 4808 } 4809 }) 4810 4811 </script>
4811 4812 </div> 4813 4814 </nav> 4815 <!--END Mobile Navigation END --> 4816 <header class="mobile-header mobile-only"> 4817 <!--custom branding location for mobile --> 4818 <!--Header Ads can be placed here if client desires: 4819 <div class='sw-banner-ad' data-sw-ad-location='header_mobile'></div> 4820 --> 4821 <a href="https://www.cincyticket.com/"><img src="../Images/mobile-logo.png"></a> 4822 </header> 4823
4823<script type="text/javascript"> 4824 $(function () { 4825 $(".control-box").append("<a class='close-widget mobile-only' onclick='hideWidgets()'>close</a>"); 4826 }) 4827 </script>
4827 4828 4829 <header class="head-wrap no-mobile"> 4830 <!--This header will not be present on mobile. Use the mobile header area if a branding location for mobile is required.--> 4831 <div class="head-inner center-div site-width"> 4832 <a href="https://www.cincyticket.com/"><img src="../Images/top_header.jpg" border="0" hidefocus="true" style="width: 100%;"></a> 4833 4834 <div class="clear-float"></div> 4835 <div class="nav-container"> 4836 <ul class="showare-nav"> 4837 <li><img src="../Images/left_nav.gif" border="0" usemap="#Map2" hidefocus="true"> 4838 <map name="Map2"> 4839 <area shape="rect" coords="8,4,84,22" href="http://www.cincyticket.com/default.asp"> 4840 <area shape="rect" coords="119,4,178,23" href="https://www.cincyticket.net/faq"> 4841 <area shape="rect" coords="217,4,336,23" href="https://www.cincyticket.net/help"> 4842 <area shape="rect" coords="370,4,550,23" href="https://www.cincyticket.net/"></map> 4843 </li> 4844 <li class="basket-widget"><div id="ShoWareBasketWidget" class="internal"></div></li> 4845 <li style="float: right;"><a href="http://www.cincyticket.com/myaccount.asp?gifrompage=1&gitopage=1"><img src="../Images/nav-account.gif"></a></li> 4846 </ul> 4847 <div class="clear-float"></div> 4848 </div> 4849 4850 </div><!--END head-inner END--> 4851 </header><!--END head-wrap END--> 4852 4853 4854 4855 4856 <!--MAIN BODY--> 4857 <div class="content-wrap"><!--Main Content Wrap - this and content-inner end in HTMLfooter--> 4858 <div class="content-inner center-div site-width"> 4859 4860 <!--LEFT SIDE--> 4861 <div class="control-wrap hide-wrap"> 4862 4863 <div class="control-box search-control"> 4864 <span class="heading-text">Search</span> 4865 <!--<img src="images/hdrCategories.gif" width="162" height="20" alt="" border="0"><br>--> 4866 4867<input class="search-text showare-text" type="text" size="16" name="SearchText" value="" placeholder="search..."><input id="searchButton" class="search-button; " type="button" name="Go" value="Go"/>
4868<script language="javascript"> 4869 $('.search-text').keyup(function(e) { 4870 if(e.which === 13){ 4871 //update the performance list 4872 4873 updatePerformanceList_Search($(".search-text").val()); 4874 4875 } 4876 }) 4877 $("#searchButton").click(function(){ 4878 4879 updatePerformanceList_Search($(".search-text").val()) 4880 4881 }); 4882 function updatePerformanceList_Search(searchVal) { 4883 4884 window.location.href= "/default.asp?search="+searchVal 4885 4886 } 4887 function updateStreamlinedEventList_Search(searchVal) { 4888 4889 window.location.href= "/default.asp?search="+searchVal 4890 4891 } 4892</script>
4892 4893 </div> 4894 4895 <div id="categoriesWidget" class="control-box categories-control"> 4896 <span class="heading-text">Categories</span> 4897 <!--<img src="images/hdrCategories.gif" width="162" height="20" alt="" border="0"><br>--> 4898 4899 4900<select id="categorySelect" class="showare-select" aria-label="Select a Category"> 4901 <option value="0">Select a Category</option> 4902</select>
4903<script language="javascript"> 4904 var CategoriesExpireTime = new Date().getTime(); var isExpired = false; var CategoriesData = ""; 4905 try { 4906 //check for local storage support 4907 isExpired = CategoriesExpireTime > Number(localStorage.getItem("CategoriesExpireTime")); 4908 if(isExpired){ 4909 //item expired, clear local results 4910 localStorage.setItem("ShoWareCategories", ""); 4911 } 4912 localStorage.setItem("CategoriesExpireTime", CategoriesExpireTime + (1000 * 60 * 60 * 24)); //item information expires after 24 hours 4913 CategoriesData = localStorage.getItem("ShoWareCategories"); 4914 } catch(e){ 4915 CategoriesData = ""; 4916 } 4917 function getCategories(){ 4918 //attempt to get local data for widget 4919 if(CategoriesData == "" || CategoriesData == null){ 4920 //no data found, pull data from request 4921 $.getJSON("https://www.cincyticket.com/include/widgets/controls/RequestCategories.asp") 4922 .done(function (data) { 4923 //build select box 4924 populateCategories(data); 4925 try{ 4926 localStorage.setItem("ShoWareCategories",JSON.stringify(data)); 4927 }catch(e){ 4928 console.log("No local storage"); 4929 } 4930 }) 4931 .fail(function (jqxhr, textStatus, error) { 4932 var err = textStatus + ", " + error; 4933 console.log("Request Failed: " + err); 4934 }) 4935 }else{ 4936 CategoriesData = JSON.parse(CategoriesData); 4937 populateCategories(CategoriesData); 4938 } 4939 } 4940 function populateCategories(categoryOptions){ 4941 oSelect = document.getElementById("categorySelect"); 4942 for(var i = 0; i < categoryOptions.length; i++){ 4943 //add an option for each category in data 4944 if (categoryOptions[i].CatActive == 1 && categoryOptions[i].IsHidden != 1) 4945 { 4946 var opt = document.createElement("option"); 4947 opt.value = categoryOptions[i].ID; 4948 if(categoryOptions[i].Rank == 1){ 4949 opt.innerHTML = categoryOptions[i].Name; 4950 opt.style.fontWeight = "bold"; 4951 }else{ 4952 opt.innerHTML = " " + categoryOptions[i].Name; 4953 } 4954 oSelect.appendChild(opt); 4955 } 4956 } 4957 $("#categorySelect").val(0); 4958 } 4959 getCategories(); 4960 var gCategoryVal = 0 4961 $("#categorySelect").change(function(){ 4962 updatePerformanceList_Category($(this).val()) 4963 gCategoryVal = $(this).val(); 4964 }); 4965 function updatePerformanceList_Category(categoryVal) { 4966 4967 window.location.href= "/default.asp?category="+categoryVal; 4968 4969 } 4970 4971 var headerDP = ""; 4972 if ($("#categorySelect").length == 0 || 'True' == 'False'){ 4973 headerDP = buildDatepicker({ "calendarID": "headerCalendar", "linkedInputID": "headerCalendarInput", "isModal": false, "forceDates": true, "defaultDate": "9/1/2026"}); 4974 } 4975 function updateCalendarDateByCategory(categoryVal) 4976 { 4977 4978 return; 4979 4980 4981 } 4982</script>
4982 4983 </div> 4984 4985 <div id="calendarWidget" class="control-box calendar-control"> 4986 <span class="heading-text">Browse Dates</span> 4987 <!--<img src="images/hdrDates.gif" width="162" height="20" alt="" border="0"><br>--> 4988 4989<input type="hidden" id="headerCalendarInput" value=""/> 4990<div id="headerCalendar" class="sw-datepicker"><link rel="stylesheet" href="/include/font-awesome/css/font-awesome.min.css" /> 4991<div tabindex="0" class="calendar-object" style="position:relative;"> 4992 <style type="text/css" scoped> 4993 .sw-datepicker 4994 { 4995 font-size:inherit;/*Calendar size is determined by parent's font size.*/ 4996 } 4997 .sw-datepicker.large-datepicker 4998 { 4999 margin-top: 20px; 5000 } 5001 .sw-datepicker[aria-hidden=true] 5002 { 5003 display:none; 5004 } 5005 5006 .sw-datepicker.is-modal{ 5007 margin: 10px; 5008 padding: 2px; 5009 -webkit-border-radius: 4px; 5010 -moz-border-radius: 4px; 5011 border-radius: 4px; 5012 position: absolute; 5013 top:30px; 5014 left:0px; 5015 z-index:99; 5016 background-color: #fff; 5017 border: 1px solid #ccc; 5018 box-shadow: 0px 0px 6px RGBA(0,0,0,0.4); 5019 } 5020 .sw-datepicker.is-modal.right-side 5021 { 5022 left:auto; 5023 right:0px; 5024 } 5025 .sw-datepicker .month-wrap 5026 { 5027 background-color: #337ab7; 5028 border: 1px solid #2e6da4; 5029 -webkit-border-radius: 4px; 5030 -moz-border-radius: 4px; 5031 border-radius: 4px; 5032 text-align:center; 5033 } 5034 .sw-datepicker .bn_next, div.bn_prev{ 5035 margin: 2px; 5036 border:1px solid transparent; 5037 line-height:1.3em; 5038 color:#fff; 5039 padding:0 .25em; 5040 font-weight:bold; 5041 cursor:pointer; 5042 } 5043 .sw-datepicker .bn_prev 5044 { 5045 float: left; 5046 } 5047 5048 .sw-datepicker .bn_next 5049 { 5050 float: right; 5051 } 5052 5053 .sw-datepicker .bn_prev:hover, 5054 .sw-datepicker .bn_prev:focus, 5055 .sw-datepicker .bn_next:hover, 5056 .sw-datepicker .bn_next:focus 5057 { 5058 margin: 2px; 5059 background-color: #4fbae0; 5060 border: 1px solid #00a4df; 5061 -webkit-border-radius: 4px; 5062 -moz-border-radius: 4px; 5063 border-radius: 4px; 5064 } 5065 5066 .sw-datepicker .bn_img 5067 { 5068 margin: 0; 5069 padding: 2px; 5070 } 5071 5072 .sw-datepicker .month 5073 { 5074 display:inline-block; 5075 line-height:1.5em; 5076 font-weight: bold; 5077 font-size: 1.2em; 5078 color:#fff; 5079 } 5080 5081 .sw-datepicker .cal 5082 { 5083 font-size: 1.2em; 5084 text-align: center; 5085 } 5086 5087 5088 .sw-datepicker .offscreen 5089 { 5090 position: absolute; 5091 left: -200em; 5092 top: -100em; 5093 } 5094 .sw-datepicker td.day-cell.highlight-day{ 5095 cursor:pointer; 5096 } 5097 td span.calendar-day{ 5098 display:inline-block; 5099 height:1.5em; 5100 width:1.5em; 5101 line-height:1.5em; 5102 border-radius:3px; 5103 margin:.1em; 5104 position:relative; 5105 } 5106 td.highlight-day span.calendar-day{ 5107 border:1px solid #337ab7; 5108 background:#fcfcfc; 5109 color:#00458A; 5110 cursor:pointer; 5111 } 5112 td.limited-availability:after{ 5113 content:'!'; 5114 display:inline-block; 5115 font-weight:bold; 5116 position:absolute; 5117 top:3px; 5118 right:5px; 5119 font-size:3vw; 5120 color:#aa0; 5121 } 5122 .sw-datepicker abbr{ 5123 text-decoration:none; 5124 opacity:1; 5125 display:inline-block; 5126 margin:.3em 0; 5127 } 5128 td.today{ 5129 background:#eee; 5130 } 5131 td.focus{ 5132 background:#8ecae0; 5133 } 5134 .sw-datepicker td{ 5135 position:relative; 5136 } 5137 .sw-datepicker.large-datepicker, .sw-datepicker.large-datepicker table{ 5138 width:100%; 5139 } 5140 .sw-datepicker.large-datepicker .month-wrap{ 5141 font-size:1.5em; 5142 background:RGBA(255,255,255,0.0); 5143 border:none; 5144 border-bottom:1px solid #eee; 5145 } 5146 .sw-datepicker.large-datepicker .month-wrap *{ 5147 color:inherit!important; 5148 } 5149 .sw-datepicker.large-datepicker .day-cell{ 5150 height:8vh; 5151 width:14%; 5152 border:1px solid #eee; 5153 opacity:.7; 5154 transition:opacity .5s; 5155 } 5156 .sw-datepicker.large-datepicker .day-cell.highlight-day{ 5157 opacity:1; 5158 } 5159 .sw-datepicker.large-datepicker td span.calendar-day{ 5160 position:absolute; 5161 top:5px; 5162 left:5px; 5163 font-size:.7em; 5164 text-align:center; 5165 font-weight:bold; 5166 height:2em; 5167 width:2em; 5168 padding:.25em; 5169 line-height:1.3em; 5170 display:inline-block; 5171 background:RGBA(255,255,255,0.0); 5172 border:none; 5173 pointer-events:none; 5174 } 5175 .sw-datepicker .date-info-box{ 5176 font-size: 1.5vw; 5177 padding: 30px 5px 15px; 5178 display: block; 5179 position: relative; 5180 } 5181 .sw-datepicker .date-info-box .display-perfstatus{ 5182 font-size: .72vw; 5183 display: block; 5184 text-align: center!important; 5185 padding: 5px 10px; 5186 border: 1px solid var(--gap-error); 5187 border-radius: 8px; 5188 color: var(--gap-error); 5189 width: 90%; 5190 margin: auto; 5191 box-sizing: border-box; 5192 background: rgba(222,27,60,.05); 5193 } 5194 .sw-datepicker .date-info-box .display-perfprice{ 5195 font-size: 1vw; 5196 } 5197 .sw-datepicker .date-info-box .display-perfprice-withchild{ 5198 font-size: 1vw; 5199 } 5200 .sw-datepicker .date-info-box .display-perfname{ 5201 font-size: .8vw; 5202 display: block; 5203 text-align: center; 5204 padding: 0px 10px; 5205 5206 }
5207 .sw-datepicker .date-info-box .display-perftime{ 5208 font-size: .93vw; 5209 display: block; 5210 padding-top: 5px; 5211 } 5212 .sw-datepicker .date-info-box .display-perfbuybutton{ 5213 font-size: .7vw; 5214 display: block; 5215 padding: 5px 10px; 5216 width: 90%; 5217 margin: 5px auto; 5218 } 5219 .sw-datepicker .date-sub-note{ 5220 font-style: italic; 5221 font-size: .93vw; 5222 opacity: .8; 5223 position: absolute; 5224 bottom: auto; 5225 top: 0px; 5226 padding-bottom: 20px; 5227 padding-top: 15px; 5228 margin-bottom: 30px; 5229 width: 100%; 5230 } 5231 @media only screen and (max-width: 1500px){ 5232 .sw-datepicker .date-info-box .display-perfname{ 5233 font-size: 1.1vw; 5234 } 5235 .sw-datepicker .date-info-box .display-perftime, 5236 .sw-datepicker .date-info-box .display-perfprice, 5237 .sw-datepicker .date-info-box .display-perfprice-withchild{ 5238 font-size: 1.2vw; 5239 } 5240 .sw-datepicker .date-info-box .display-perfbuybutton{ 5241 font-size: 1vw; 5242 } 5243 } 5244 @media only screen and (max-width: 1300px){ 5245 .sw-datepicker .date-info-box .display-perfname{ 5246 font-size: 1.3vw; 5247 } 5248 .sw-datepicker .date-info-box .display-perftime, 5249 .sw-datepicker .date-info-box .display-perfprice, 5250 .sw-datepicker .date-info-box .display-perfprice-withchild{ 5251 font-size: 1.3vw; 5252 } 5253 } 5254 @media only screen and (max-width: 1024px){ 5255 .sw-datepicker .date-sub-note{ 5256 display:none!important; 5257 } 5258 .sw-datepicker .date-info-box .display-perfname{ 5259 font-size: 12px; 5260 } 5261 .sw-datepicker .date-info-box .display-perftime, 5262 .sw-datepicker .date-info-box .display-perfprice, 5263 .sw-datepicker .date-info-box .display-perfprice-withchild{ 5264 font-size: 12px; 5265 } 5266 .sw-datepicker .date-info-box .display-perfbuybutton{ 5267 font-size: 12px; 5268 white-space: unset; 5269 line-height: 1.2; 5270 } 5271 /* adjustment for coupon codes on mobile*/ 5272 .couponecode-wrap { 5273 display: flex; 5274 flex-direction: row-reverse; 5275 align-items: stretch; 5276 flex-wrap: nowrap; 5277 gap: 20px; 5278 width: 100%; 5279 } 5280 #FilterSelect { 5281 margin-bottom: 8px; 5282 } 5283 #couponCodeSubmitButton { 5284 margin-top: 0; 5285 } 5286 #couponCode { 5287 flex: 1; 5288 height: auto; 5289 } 5290 } 5291 @media only screen and (max-width: 800px){ 5292 .sw-datepicker.large-datepicker .day-cell { 5293 height: auto!important; 5294 width: 14%; 5295 min-height: 50px; 5296 border: 1px solid #eee; 5297 opacity: .7; 5298 transition: opacity .5s; 5299 } 5300 .sw-datepicker.large-datepicker table td.empty, 5301 .sw-datepicker.large-datepicker table th { 5302 width: 14%; 5303 min-width: 14%; 5304 } 5305 .sw-datepicker .date-info-box .display-perfbuybutton { 5306 width: 100%; 5307 line-height: 1.1!important; 5308 font-size: 11px!important; 5309 white-space: unset; 5310 padding: 5px!important; 5311 } 5312 .sw-datepicker .date-info-box .display-perftime, 5313 .sw-datepicker .date-info-box .display-perfprice, 5314 .sw-datepicker .date-info-box .display-perfprice-withchild, 5315 .sw-datepicker .date-info-box .display-perfname{ 5316 font-size: 11px; 5317 5318 } 5319 .sw-datepicker table tr { 5320 display: flex; 5321 justify-content: space-evenly; 5322 } 5323 .sw-datepicker .date-info-box .display-perfname{ 5324 padding: 5px 0px 0; 5325 } 5326 .sw-datepicker .date-info-box { 5327 overflow-wrap: normal; 5328 } 5329 .sw-datepicker.large-datepicker table td.empty, 5330 .sw-datepicker.large-datepicker table th, 5331 .sw-datepicker table td.empty, 5332 .sw-datepicker table th 5333 { 5334 width: calc((100% / 7) - 4px); 5335 min-width: 10%; 5336 } 5337 .sw-datepicker.large-datepicker .day-cell, 5338 .sw-datepicker .day-cell { 5339 width: calc((100% / 7) - 4px); 5340 } 5341 .sw-datepicker .day-cell.sold-out{ 5342 padding-top: 35px!important; 5343 line-height: 1.2!important; 5344 } 5345 } 5346 @media only screen and (max-width: 550px){ 5347 #epPerformanceList #eventCalendar { 5348 width: 100%; 5349 } 5350 .sw-datepicker .date-info-box .display-perfbuybutton { 5351 font-size: 7px!important; 5352 font-weight: 400!important; 5353 }
5354 .sw-datepicker .date-info-box .display-perftime, 5355 .sw-datepicker .date-info-box .display-perfprice, 5356 .sw-datepicker .date-info-box .display-perfprice-withchild, 5357 .sw-datepicker .date-info-box .display-perfname{ 5358 font-size: 10px; 5359 5360 } 5361 .sw-datepicker .day-cell.sold-out{ 5362 padding-top: 30px!important; 5363 line-height: .9!important; 5364 } 5365 .sw-datepicker.large-datepicker table tr{ 5366 display: flex; 5367 justify-content: space-evenly; 5368 } 5369 .sw-datepicker.large-datepicker table td.empty, 5370 .sw-datepicker.large-datepicker table th, 5371 .sw-datepicker.large-datepicker table td, 5372 .sw-datepicker.large-datepicker .day-cell { 5373 width: calc(96vw / 7); 5374 } 5375 #TimeSelectModalBody { 5376 width: 100%!important; 5377 } 5378 } 5379 .sw-datepicker .day-cell.sold-out{ 5380 opacity:.7!important; 5381 color:#a00; 5382 pointer-events:none; 5383 } 5384 .sw-datepicker .day-cell.muted{ 5385 opacity:.3!important; 5386 } 5387 5388 .sw-datepicker .day-cell.coupon-muted{ 5389 opacity:.3!important; 5390 } 5391 5392 .sw-datepicker .day-cell.password-hidden .date-info-box{ 5393 display: none!important; 5394 } 5395 5396 .sw-datepicker .day-cell.muted .calendar-day{ 5397 color:inherit!important; 5398 border:none!important; 5399 cursor:default!important; 5400 } 5401 5402 .sw-datepicker .day-cell.coupon-muted .calendar-day{ 5403 color:inherit!important; 5404 border:none!important; 5405 } 5406 .sw-datepicker .day-cell.sold-out .date-info-box{ 5407 display:none; 5408 } 5409 .sw-datepicker .day-cell.sold-out .calendar-day{ 5410 color:#a00; 5411 border:none; 5412 text-decoration:line-through; 5413 } 5414 @media only screen and (max-width: 1024px){ 5415 .sw-datepicker .date-info-box, .sw-datepicker .sold-out-info-box{ 5416 font-size:2vw; 5417 } 5418 } 5419 .calendar-loading{ 5420 position:absolute; 5421 top:50%; 5422 left:50%; 5423 font-size:4vw; 5424 font-weight:bold; 5425 color:RGBA(0,0,0,0.4); 5426 width:66vw; 5427 margin-left:-33vw; 5428 height:20vw; 5429 margin-top:-10vh; 5430 line-height:20vw; 5431 text-align:center; 5432 background:RGBA(255,255,255,0.9); 5433 border-radius:1em; 5434 border:1px solid RGBA(0,0,0,0.4); 5435 box-shadow:2px 2px 4px RGBA(0,0,0,0.2); 5436 } 5437 .limited-availability-legend-item{ 5438 text-align:right; 5439 } 5440 .calendar-limited-availability-legend-icon{ 5441 font-weight:bold; 5442 color:#aa0; 5443 } 5444 .calendar-dayoftheweek {display: none!important;} 5445 #calendarWidget .calendar-dayoftheweek {display: none!important;} 5446 </style> 5447 5448 <div class="month-wrap"> 5449 <div class="bn_prev" role="button" aria-labelledby="bn_prev-label" tabindex="0" title="Previous Month"><i class="fa fa-backward" aria-hidden="true"></i></div> 5450 <div tabindex="0" class="month" role="heading" aria-live="assertive" aria-atomic="true">Loading...</div> 5451 <div class="bn_next" role="button" aria-labelledby="bn_next-label" tabindex="0" title="Next Month"><i class="fa fa-forward" aria-hidden="true"></i></div> 5452 </div> 5453 <table title="Search Date - Select a date to search" class="cal" role="grid" aria-labelledby="month" tabindex="0" style="margin: 0px auto;outline:none!important;"> 5454 <thead> 5455 <tr class="weekdays"> 5456 <th class="Sunday"><abbr title="Sunday">Su</abbr></th> 5457 <th class="Monday"><abbr title="Monday">Mo</abbr></th> 5458 <th class="Tuesday"><abbr title="Tuesday">Tu</abbr></th> 5459 <th class="Wednesday"><abbr title="Wednesday">We</abbr></th> 5460 <th class="Thursday"><abbr title="Thursday">Th</abbr></th> 5461 <th class="Friday"><abbr title="Friday">Fr</abbr></th> 5462 <th class="Saturday"><abbr title="Saturday">Sa</abbr></th> 5463 </tr> 5464 </thead> 5465 <tbody> 5466 <tr><td class="errMsg" colspan="7">Loading...</td></tr> 5467 </tbody> 5468 </table> 5469 <div class="bn_prev-label offscreen">Go to previous month</div> 5470 <div class="bn_next-label offscreen">Go to next month</div> 5471 <div class="calendar-loading" style="display:none;"><i class="fa fa-spin fa-spinner" style="margin-right:.5em;"></i>Loading...</div> 5472</div> 5473<div class="calendar-notes-wrap"></div> 5474</div>
5475<script type="text/javascript"> 5476 var headerDP = ""; 5477 if ($("#categorySelect").length == 0 || 'True' == 'False') 5478 headerDP = buildDatepicker({ "calendarID": "headerCalendar", "linkedInputID": "headerCalendarInput", "isModal": false, "forceDates": true, "defaultDate": "9/1/2026", "corporatePartnerPage":0}); 5479 $("#headerCalendarInput").on("change", function () { 5480 var properDate = /^\d{1,2}\/\d{1,2}\/\d{4}$/; 5481 if (!properDate.test($(this).val())) { 5482 console.log("Main calendar attempted an invalid date: " + $(this).val()); 5483 return;//invalid date 5484 } 5485 5486 window.location.href= "/default.asp?searchdate="+$(this).val()+""; 5487 }); 5488 extractIcons(); 5489</script>
5489 5490 5491 5492 5493 </div> 5494 5495 <div id="venuesWidget" class="control-box venue-control"> 5496 <span class="heading-text">Browse by Venue</span> 5497 5498 5499 5500 5501<select id="venueSelect" class="showare-select" name="venue" aria-label="Choose Venue"> 5502 <option value="0"> Choose Venue </option> 5503</select> 5504<div align="right"> 5505 <a class="button small-button sw-button-muted" style="margin-top:1em;margin-right:0px;" href="//www.cincyticket.com/venuelisting.asp">View Venue listing</a> 5506</div> 5507
5508<script language="javascript"> 5509 var VenuesExpireTime = new Date().getTime(); var isExpired = false; var VenuesData = ""; 5510 try { 5511 //check for local storage support 5512 isExpired = VenuesExpireTime > Number(localStorage.getItem("VenuesExpireTime")); 5513 if(isExpired){ 5514 //item expired, clear local results 5515 localStorage.setItem("ShoWareVenues", ""); 5516 } 5517 localStorage.setItem("VenuesExpireTime", VenuesExpireTime + (1000 * 60 * 60 * 24)); //item information expires after 24 hours 5518 VenuesData = localStorage.getItem("ShoWareVenues"); 5519 } catch(e){ 5520 VenuesData = ""; 5521 } 5522 function getVenues(){ 5523 //attempt to get local data for widget 5524 if(VenuesData == "" || VenuesData == null){ 5525 //no data found, pull data from request 5526 $.getJSON("https://www.cincyticket.com/include/widgets/controls/RequestVenues.asp") 5527 .done(function (data) { 5528 //build select box 5529 populateVenues(data); 5530 try{ 5531 localStorage.setItem("ShoWareVenues",JSON.stringify(data)); 5532 }catch(e){ 5533 console.log("No local storage"); 5534 } 5535 }) 5536 .fail(function (jqxhr, textStatus, error) { 5537 var err = textStatus + ", " + error; 5538 console.log("Request Failed: " + err); 5539 }); 5540 }else{ 5541 VenuesData = JSON.parse(VenuesData); 5542 populateVenues(VenuesData); 5543 } 5544 } 5545 function populateVenues(venueOptions){ 5546 oSelect = document.getElementById("venueSelect"); 5547 for(var i = 0; i < venueOptions.length; i++){ 5548 //add an option for each venue in data 5549 var opt = document.createElement("option"); 5550 opt.value = venueOptions[i].ID; 5551 opt.innerHTML = venueOptions[i].Name; 5552 oSelect.appendChild(opt); 5553 } 5554 $("#venueSelect").val(0); 5555 } 5556 getVenues(); 5557 5558 $("#venueSelect").change(function(){ 5559 updatePerformanceList_Venue($(this).val()) 5560 }); 5561 function updatePerformanceList_Venue(venueVal) { 5562 5563 window.location.href= "/default.asp?venue="+venueVal; 5564 5565 } 5566</script>
5566 5567 </div> 5568 5569 <div id="infoWidget" class="control-box info-control"> 5570 <span class="heading-text">Information</span> 5571 <!--<img src="images/hdrInfo.gif" width="162" height="20" alt="" border="0"><br>--> 5572 <span class="info-text small-text"><p><strong>Customer Service:</strong><br /> <span style="text-decoration: underline;"><span style="font-size: medium;"><a href="https://www.cincyticket.net/help">CONTACT US</a></span></span><br /><br /> 9891 Montgomery Rd.<br />Suite 189<br /> Cincinnati, OH 45242</p> 5573<a href="https://www.facebook.com/cincyticket" target="_blank"><img src="https://www.cincyticket.com/uplimage/icon_facebook.png" alt="" width="35" height="35" /></a> <a href="https://www.twitter.com/cincyticket" target="_blank"><img src="https://www.cincyticket.com/uplimage/icon_twitter.png" alt="" width="35" height="35" /><br /></a> 5574<p><a href="https://www.cincyticket.net" target="_blank"><img src="../uplimage/sellticketswithus_new.png" alt="" border="0" /></a></p> 5575<center><em><br />Ticketing System by</em><br /><a href="https://www.cincyticket.net" target="_blank"><img src="../uplimage/cincyticket_logo_clearbg.png" alt="" border="0" /></a></center><!-- Meta Pixel Code -->
5576<script>// <![CDATA[
vendor: 408 bytes, lines 5576-5585
5576 5577!function(f,b,e,v,n,t,s) 5578{if(f.fbq)return;n=f.fbq=function(){n.callMethod? 5579n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 5580if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 5581n.queue=[];t=b.createElement(e);t.async=!0; 5582t.src=v;s=b.getElementsByTagName(e)[0]; 5583s.parentNode.insertBefore(t,s)}(window, document,'script', 5584'https://connect.facebook.net/en_US/fbevents.js'); 5585fbq('init', '
5585802935397828854
vendor: 32 bytes, lines 5585-5586
5585'); 5586fbq('track', 'PageView');
5587// ]]></script>
5587 5588<noscript><img height="1" width="1" style="display:none" 5589src="https://www.facebook.com/tr?id=802935397828854&ev=PageView&noscript=1" 5590/></noscript><!-- End Meta Pixel Code --></span> 5591 </div> 5592 5593 <a class="reporting-link" href="/reporting/login.asp">Promoter Login</a> 5594 5595 <div class="ads-control"> 5596 <center> 5597 <div class='sw-banner-ad' data-sw-ad-location='side_01'></div><div class='sw-banner-ad' data-sw-ad-location='side_02'></div><div class='sw-banner-ad' data-sw-ad-location='side_03'></div><div class='sw-banner-ad' data-sw-ad-location='side_04'></div><div class='sw-banner-ad' data-sw-ad-location='side_05'></div><div class='sw-banner-ad' data-sw-ad-location='side_06'></div><div class='sw-banner-ad' data-sw-ad-location='side_07'></div><div class='sw-banner-ad' data-sw-ad-location='side_08'></div><div class='sw-banner-ad' data-sw-ad-location='side_09'></div><div class='sw-banner-ad' data-sw-ad-location='side_10'></div> 5598 </center> 5599 </div> 5600 5601 <!--Special basket widget to notify users that a ticket has changed--> 5602 <div id="basketChangeWidget" class="control-box basket-change" style="width:100%;"> 5603 <span style="text-align:center;font-weight:bold;display:block;">Your basket has been updated.</span> 5604 <span style="text-align:center;display:block;">You will have a chance to review your order during <a style="font-weight:bold;" href='#' onclick='$("#checkout-button").click();'>checkout</a></span> 5605 </div> 5606 5607 </div><!--END control-wrap END--> 5608 <!--END LEFT SIDE--> 5609 <div id="epImage2"></div> 5610 5611 <div class="main-container "> 5612 <!-- Main Area --> 5613 5614 <!-- end HTMLheader.asp --> 5615 5616<div id="ng-app" ng-app='Showare' class="basket-wrap"> 5617 <link rel="stylesheet" type="text/css" href="/admin/include/select.css?ver=20228b0075"/>
5618<script src="/admin/include/angular.1.8.min.js?ver=20228b0075"></script>
vendor: 2 bytes, line 5618
5618
5619<script src="/admin/include/ui-bootstrap-custom-tpls-2.1.3.min.js?ver=20228b0075"></script>
vendor: 2 bytes, line 5619
5619
5620<script src="/admin/include/select.js?ver=20228b0075"></script>
vendor: 2 bytes, line 5620
5620
5621<script type="text/javascript" src='/admin/include/angular/dependencies/date.angular1.5.js'></script>
vendor: 2 bytes, line 5621
5621
5622<script type="text/javascript" src='/admin/include/angular/dependencies/tinymce.angular1.5.js'></script>
vendor: 2 bytes, line 5622
5622
5623<script> 5624 5625var app = angular.module('Showare', ['Showare.Controllers', 'Showare.Services', 'Showare.Directives'], function ($httpProvider) { 5626 // Use x-www-form-urlencoded Content-Type 5627 $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; 5628 5629 // Override $http service's default transformRequest to use form serialization 5630 $httpProvider.defaults.transformRequest = [function(data) { 5631 if(angular.isObject(data) && String(data) !== '[object File]') { 5632 data.sessionKey = v1Session.sessionKey; 5633 5634 return jQuery.param(data); 5635 } else { 5636 return data; 5637 } 5638 }]; 5639}) 5640.config([ 5641 '$provide', function($provide) { 5642 return $provide.decorator('$rootScope', [ 5643 '$delegate', function($delegate) { 5644 $delegate.$safeApply = function(fn) { 5645 var phase = $delegate.$$phase; 5646 if (phase === "$apply" || phase === "$digest") { 5647 if (fn && typeof fn === 'function') { 5648 fn(); 5649 } 5650 } else { 5651 $delegate.$apply(fn); 5652 } 5653 }; 5654 return $delegate; 5655 } 5656 ]); 5657 } 5658]) 5659.value('tinymceOptions', { 5660 theme: "modern", 5661 skin: 'light', 5662 statusbar: false, 5663 menubar: false, 5664 plugins: 'code textcolor image link paste', 5665 paste_as_text: true, 5666 width: 620, 5667 height: 145, 5668 force_br_newlines: false, 5669 force_p_newlines: false, 5670 convert_urls: false, 5671 remove_script_host: false, 5672 forced_root_block: '', 5673 extended_valid_elements: "script[charset|defer|language|src|type], style[type|media]", 5674 valid_children : "+body[style]", 5675 toolbar: 'undo redo | bold italic underline strikethrough | alignleft alignjustify alignright al
5675igncenter | bullist numlist | forecolor backcolor fontsizeselect | link unlink code removeformat | image' 5676}); 5677 5678var controllerModule = angular.module('Showare.Controllers', ['ui.select', 'ui.bootstrap', 'ui.date', 'ui.timepicker', 'ui.tinymce']); 5679var serviceModule = angular.module('Showare.Services', []); 5680var directiveModule = angular.module('Showare.Directives', []); 5681 5682 5683</script>
5683 5684 5685
5685<script type="text/javascript" src="include/underscore.min.js"></script>
5685 5686
5686<script type="text/javascript" src='admin/include/angular/controllers/BasketCtrl.js'></script>
5686 5687
5687<script type="text/javascript" src='admin/include/angular/services/UnderscoreService.js'></script>
5687 5688
5688<script type="text/javascript" src="//www.cincyticket.com/include/modules/paymentPlans/ppFunctions.js"></script>
5688 5689
5689<script type="text/javascript"> 5690/** 5691 * Basket Payment Plan Widget - Client-side functionality 5692 * Handles payment plan selection, calculations, and UI updates in basket.asp 5693 */ 5694 5695(function() { 5696 'use strict'; 5697 5698 var basketPaymentPlan = { 5699 currentTotal: 0, 5700 selectedPlanId: 0, 5701 selectedInstallments: 0, 5702 // --- new --- 5703 tilaDataCache: {}, 5704 tilaAccepted: false, 5705 tilaModalShowing: false, 5706 5707 /** 5708 * Initialize the basket payment plan widget 5709 */ 5710 init: function() { 5711 // Get current basket total from the page 5712 this.updateBasketTotal(); 5713 5714 // Set up event listeners 5715 this.bindEvents(); 5716 5717 // No longer calculate amounts client-side - they come pre-calculated from server 5718 // this.updateAllPlanAmounts(); 5719 5720 // Set initial selection 5721 this.updateSelection(); 5722 // Read any pre-selected radio (server may have marked one based on session) 5723 var $checked = $('input[name="basket_pp_option"]:checked'); 5724 if ($checked.length) { 5725 this.selectedPlanId = parseInt($checked.data('plan-id')) || 0; 5726 this.selectedInstallments = parseInt($checked.data('installments')) || 0; 5727 $('#basket_selected_payment_plan_id').val(this.selectedPlanId); 5728 if (this.selectedPlanId > 0) { 5729 // Preload TILA terms for preselected plan 5730 this.preloadTila(this.selectedPlanId); 5731 } 5732 } 5733 this.ensureHiddenFields(); 5734 5735 // Update Due Today if a plan was preselected 5736 if (this.selectedPlanId > 0) { 5737 this.updateDueToday(); 5738 } 5739 }, 5740 5741 /** 5742 * Bind event listeners 5743 */ 5744 bindEvents: function() { 5745 var self = this; 5746 5747 // Handle payment plan selection 5748 $(document).on('change', 'input[name="basket_pp_option"]', function() { 5749 self.handlePlanSelection($(this)); 5750 }); 5751 5752 // Show the payment schedule detail modal for a specific plan 5753 $(document).on('click', '.basket-pp-view-schedule', function(e) { 5754 e.preventDefault(); 5755 e.stopPropagation(); 5756 var planId = parseInt($(this).data('plan-id')) || 0; 5757 var planName = $(this).data('plan-name') || ''; 5758 self.showScheduleModal(planId, planName); 5759 }); 5760 5761 // // Listen for basket total changes (if basket updates dynamically) 5762 $(document).on('basketTotalUpdated', function(event, newTotal) { 5763 self.currentTotal = parseFloat(newTotal); 5764 self.updateAllPlanAmounts(); 5765 }); 5766 }, 5767 5768 // --- new: ensure hidden field for TILA acceptance --- 5769 ensureHiddenFields: function() { 5770 if ($('#basket_tila_accepted').length === 0) { 5771 var $form = $('#basketForm'); 5772 if ($form.length === 0) { $form = $('form').first(); } 5773 $form.append('<input type="hidden" id="basket_tila_accepted" name="basket_tila_accepted" value="0">'); 5774 } 5775 }, 5776 5777 shouldRequireTila: function() { 5778 return this.selectedPlanId > 0 && typeof this.tilaDataCache[this.selectedPlanId] !== 'undefined'; 5779 }, 5780 5781 /** 5782 * Handle payment plan selection change 5783 */ 5784 handlePlanSelection: function($radio) { 5785 var planId = parseInt($radio.data('plan-id')) || 0; 5786 var installments = parseInt($radio.data('installments')) || 0; 5787 5788 this.selectedPlanId = planId; 5789 this.selectedInstallments = installments; 5790 this.tilaAccepted = false; 5791 $('#basket_tila_accepted').val('0'); 5792 5793 // Preload TILA si plan > 0 5794 if (planId > 0) { 5795 this.preloadTila(planId); 5796 } else { 5797 // Pay in Full selected: clear any previously stored payment plan 5798 // data from the user session (mirrors the TILA modal'
5798s Pay in Full path) 5799 $.ajax({ 5800 url: '/include/modules/paymentPlans/requests/ppAjax.asp', 5801 method: 'POST', 5802 dataType: 'json', 5803 async: true, 5804 data: { 5805 action: 'removePaymentPlanSessions', 5806 sessionKey: '' 5807 } 5808 }); 5809 } 5810 5811 // Update hidden field 5812 $('#basket_selected_payment_plan_id').val(planId); 5813 5814 // Update visual selection 5815 this.updateSelection(); 5816 5817 // Update "Due Today" section if payment plan is selected 5818 this.updateDueToday(); 5819 5820 // Trigger event for other components 5821 $(document).trigger('basketPaymentPlanChanged', { 5822 planId: planId, 5823 installments: installments, 5824 total: this.currentTotal 5825 }); 5826 5827 }, 5828 5829 /** 5830 * Update visual selection state 5831 */ 5832 updateSelection: function() { 5833 // Remove selected class from all options 5834 $('.payment-option-row').removeClass('selected'); 5835 5836 // Add selected class to current selection 5837 $('input[name="basket_pp_option"]:checked').closest('.payment-option-row').addClass('selected'); 5838 }, 5839 5840 /** 5841 * Get current basket total from the page 5842 */ 5843 updateBasketTotal: function() { 5844 //basketTotalCell is for basket.asp; OrderTotal is for bundleBasket.asp 5845 var totalText = ''; 5846 var $basketTotalCell = $('#basketTotalCell'); 5847 if ($basketTotalCell.length && $.trim($basketTotalCell.text()) !== '') { 5848 totalText = $.trim($basketTotalCell.text()); 5849 } else { 5850 var $orderTotal = $('#OrderTotal'); 5851 totalText = $.trim($orderTotal.text()); 5852 } 5853 // Remove currency symbol and parse 5854 var match = totalText.match(/[\d,]+\.?\d*/); 5855 if (match) { 5856 this.currentTotal = parseFloat(match[0].replace(/,/g, '')); 5857 } 5858 5859 // Update the "Pay in Full" amount display 5860 $('#basket-total-value').text(this.formatCurrency(this.currentTotal)); 5861 }, 5862 5863 /** 5864 * Calculate and update amounts for all payment plans 5865 */ 5866 updateAllPlanAmounts: function(iOrderFee) { 5867 var self = this; 5868 $.ajax({
5869 url: '/include/modules/paymentPlans/requests/ppAjax.asp', 5870 method: 'GET', 5871 dataType: 'json', 5872 data: { 5873 action: 'updateAsyncPaymentPlanAmounts' 5874 }, 5875 success: function(response) { 5876 // Update payment plan amounts in the UI 5877 self.updatePaymentPlanAmounts(response, iOrderFee); 5878 }, 5879 error: function(xhr, status, error) { 5880 console.error('Error updating payment plan amounts:', status, error); 5881 } 5882 }); 5883 }, 5884 5885 /** 5886 * Update payment plan amounts in the UI based on server response 5887 * @param {Array} planData - Array of plan objects with paymentPlanID, firstPayment, monthlyPayment, numberOfPayments 5888 */ 5889 updatePaymentPlanAmounts: function(planData, orderProcessingFee) { 5890 if (!planData || !Array.isArray(planData) || planData.length === 0) { 5891 console.warn('No plan data to update'); 5892 return; 5893 } 5894 5895 // Update basket total first (in case it changed with promo codes) 5896 this.updateBasketTotal(); 5897 5898 // Iterate through each plan in the response 5899 planData.forEach(function(plan) { 5900 var planID = plan.planID; 5901 var firstPayment = parseFloat(plan.firstPayment || 0); 5902 var monthlyPayment = parseFloat(plan.monthlyPayment || 0); 5903 var numberOfPayments = parseInt(plan.numberOfPayments || 0); 5904 var remainingPayments = numberOfPayments - 1; 5905 5906 // Update first payment amount 5907 var $firstPaymentSpan = $('[data-plan-first-id="' + planID + '"]'); 5908 if ($firstPaymentSpan.length > 0) { 5909 $firstPaymentSpan.text(basketPaymentPlan.formatCurrency(firstPayment + orderProcessingFee)); 5910 } 5911 5912 // Update monthly payment amount 5913 var $monthlyPaymentSpan = $('[data-plan-monthly-id="' + planID + '"]'); 5914 if ($monthlyPaymentSpan.length > 0) { 5915 $monthlyPaymentSpan.text(basketPaymentPlan.formatCurrency(monthlyPayment)); 5916 } 5917 5918 // Update remaining payments count 5919 var $remainingCountSpan = $('[data-plan-remaining-id="' + planID + '"]'); 5920 if ($remainingCountSpan.length > 0) { 5921 $remainingCountSpan.text(remainingPayments); 5922 } 5923 5924 // Update total installments count 5925 var $installmentsSpan = $('[data-plan-installments-id="' + planID + '"]'); 5926 if ($installmentsSpan.length > 0) { 5927 $installmentsSpan.text(numberOfPayments); 5928 } 5929 5930 // Update the data-installments attribute on the radio button 5931 var $radioButton = $('input[name="basket_pp_option"][data-plan-id="' + planID + '"]'); 5932 if ($radioButton.length > 0) { 5933 $radioButton.attr('data-installments', numberOfPayments); 5934 } 5935 }); 5936 5937 // Trigger event for other components that might need to react 5938 $(document).trigger('basketPaymentPlanAmountsUpdated', { plans: planData }); 5939 }, 5940 5941 /** 5942 * Calculate payment plan amounts 5943 * @param {number} total - Total order amount 5944 * @param {number} installments - Number of installments 5945 * @returns {object} - Object with firstPayment, monthlyPayment, remainingPayments 5946 */ 5947 calculatePlanAmounts: function(total, installments) { 5948 if (installments <= 0 || total <= 0) { 5949 return { 5950 firstPayment: 0, 5951 monthlyPayment: 0, 5952 remainingPayments: 0 5953 }; 5954 } 5955 5956 // Use the calculateInstalments function from ppFunctions.js if available 5957 var instalmentAmounts; 5958 if (typeof calculateInstalments === 'function') { 5959 instalmentAmounts = calculateInstalments(total, installments, 'ROUND_UP'); //from ppFunctions.js.asp 5960 } else { 5961 // Fallback calculation
5962 var monthlyPayment = Math.ceil((total / installments) * 100) / 100; 5963 var firstPayment = total - (monthlyPayment * (installments - 1)); 5964 instalmentAmounts = [firstPayment].concat(Array(installments - 1).fill(monthlyPayment)); 5965 } 5966 5967 return { 5968 firstPayment: instalmentAmounts[0], 5969 monthlyPayment: instalmentAmounts[1] || 0, 5970 remainingPayments: installments - 1 5971 }; 5972 }, 5973 5974 /** 5975 * Update "Due Today" section based on selected plan 5976 */ 5977 updateDueToday: function() { 5978 if (this.selectedPlanId === 0) { 5979 // Pay in Full - due today is full amount 5980 // The existing Due Today section should be hidden or show full amount 5981 return; 5982 } 5983 5984 // Calculate first payment for selected plan 5985 var amounts = this.calculatePlanAmounts(this.currentTotal, this.selectedInstallments); 5986 5987 // Update Due Today display if it exists 5988 var $dueToday = $('#basketDueTodayCell'); 5989 if ($dueToday.length > 0) { 5990 $dueToday.show(); 5991 var currencySymbol = $dueToday.text().match(/^[^\d]+/)[0] || '$'; 5992 $dueToday.html(currencySymbol + '<strong>' + this.formatCurrency(amounts.firstPayment) + '</strong>'); 5993 } 5994 }, 5995 5996 /** 5997 * Format number as currency 5998 */ 5999 formatCurrency: function(amount) { 6000 return parseFloat(amount).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ','); 6001 }, 6002 6003 // --- new: load TILA via AJAX --- 6004 preloadTila: function(planId) { 6005 var self = this; 6006 if (self.tilaDataCache[planId]) { 6007 return; // already cached 6008 } 6009 $.ajax({
6010 url: '/include/modules/paymentPlans/requests/ppAjax.asp', 6011 method: 'GET', 6012 data: { 6013 action: 'getPaymentPlanTILA', 6014 paymentPlanSelection: planId 6015 }, 6016 cache: false, 6017 success: function(resp) { 6018 // Could be HTML or JSON. If JSON parse. 6019 var tilaContent = resp; 6020 try { 6021 if (typeof resp === 'string' && resp.trim().charAt(0) === '{') { 6022 var j = JSON.parse(resp); 6023 tilaContent = j.tilaText || resp; 6024 } 6025 } catch(e) { /* keep resp as-is */ } 6026 self.tilaDataCache[planId] = tilaContent; 6027 $(document).trigger('basketTilaPreloaded', { planId: planId }); 6028 }, 6029 error: function() { 6030 console.warn('Failed to preload TILA for plan ' + planId); 6031 self.tilaDataCache[planId] = '<div style="padding:12px;">Terms unavailable.</div>'; 6032 } 6033 }); 6034 }, 6035 6036 6037 showTilaModal: function(onAccept) { 6038 var self = this; 6039 if (self.tilaModalShowing) return; 6040 self.tilaModalShowing = true; 6041 6042 var planId = self.selectedPlanId; 6043 var html = self.tilaDataCache[planId] || '<div style="padding:12px;">Terms not loaded.</div>'; 6044 6045 // Build overlay
6046 var $overlay = $('<div id="tilaOverlay" style="position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:9998;"></div>'); 6047 var $modal = $('<div id="tilaModal" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;max-width:640px;width:92%;max-height:80vh;overflow:auto;border-radius:8px;box-shadow:0 10px 28px rgba(0,0,0,.35);z-index:9999;font-family:Arial,sans-serif;"></div>'); 6048 var $header = $('<div style="padding:14px 18px;border-bottom:1px solid #eee;font-weight:600;font-size:15px;letter-spacing:.3px;">Payment Plan Terms (TILA)</div>'); 6049 var $body = $('<div style="padding:16px;font-size:12px;line-height:1.45;color:#222;"></div>').html(html); 6050 6051 // Checkbox agreement section 6052 var $checkboxSection = $('<div style="padding:12px 16px;border-top:1px solid #eee;display:flex;align-items:center;gap:8px;"></div>'); 6053 var $checkbox = $('<input type="checkbox" id="tilaAgreeCheckbox" style="width:16px;height:16px;cursor:pointer;margin:0;">'); 6054 var $checkboxLabel = $('<label for="tilaAgreeCheckbox" style="cursor:pointer;font-size:13px;color:#333;margin:0;user-select:none;">I have read and agree to the payment plan terms and conditions</label>'); 6055 $checkboxSection.append($checkbox, $checkboxLabel); 6056 6057 // Action buttons 6058 var $actions = $('<div style="padding:12px 16px;border-top:1px solid #eee;display:flex;justify-content:flex-end;gap:10px;"></div>'); 6059 var $btnPayInFull = $('<button type="button" style="background:#888;color:#fff;border:0;padding:8px 14px;border-radius:4px;font-size:12px;cursor:pointer;">Pay in Full</button>'); 6060 var $btnAccept = $('<button type="button" disabled style="background:#ccc;color:#999;border:0;padding:8px 18px;border-radius:4px;font-size:12px;cursor:not-allowed;font-weight:600;">Accept & Continue</button>'); 6061 var $errorBar = $('<div class="tila-error" style="display:none;margin:0 16px 8px 16px;background:#fbe9e9;color:#b32626;border:1px solid #e5b6b6;padding:8px 10px;border-radius:4px;font-size:12px;line-height:1.3;"></div>'); 6062 6063 $actions.append($btnPayInFull, $btnAccept); 6064 $modal.append($header, $body, $errorBar, $checkboxSection, $actions); 6065 $('body').append($overlay, $modal); 6066 6067 // Enable/disable Accept button based on checkbox 6068 $checkbox.on('change', function() { 6069 if ($(this).is(':checked')) { 6070 $btnAccept.prop('disabled', false) 6071 .css({ 6072 'background': '#2f5d9f', 6073 'color': '#fff', 6074 'cursor': 'pointer' 6075 }); 6076 } else { 6077 $btnAccept.prop('disabled', true) 6078 .css({ 6079 'background': '#ccc', 6080 'color': '#999', 6081 'cursor': 'not-allowed' 6082 }); 6083 } 6084 }); 6085 6086 function closeModal() { 6087 $overlay.remove(); 6088 $modal.remove(); 6089 self.tilaModalShowing = false; 6090 } 6091 6092 // Pay in Full button - closes modal and resets to pay-in-full option 6093 $btnPayInFull.on('click', function() { 6094 closeModal(); 6095 // Reset to pay in full option (planId = 0) 6096 // Triggering 'change' will invoke handlePlanSelection which already posts removePaymentPlanSessions 6097 $('input[name="basket_pp_option"][data-plan-id="0"]').prop('checked', true).trigger('change'); 6098 }); 6099 6100 // Accept button - only enabled when checkbox is checked 6101 $btnAccept.on('click', function() { 6102 if (!$checkbox.is(':checked') || $btnAccept.prop('disabled')) return; // safety 6103 $errorBar.hide(); 6104 // Lock UI 6105 $btnAccept.prop('disabled', true).data('origText', $btnAccept.text()) 6106 .html('<span class="spinner" style="display:inline-block;width:14px;
6106height:14px;border:2px solid #fff;border-right-color:transparent;border-radius:50%;animation:tilaSpin .7s linear infinite;vertical-align:-2px;margin-right:6px;"></span>Processing...') 6107 .css({ cursor: 'wait' }); 6108 $btnPayInFull.prop('disabled', true).css({ opacity: .6, cursor: 'not-allowed' }); 6109 $checkbox.prop('disabled', true); 6110 6111 // Perform single AJAX call to confirmTILA and fill session data 6112 $.ajax({ 6113 url: '/include/modules/paymentPlans/requests/ppAjax.asp', 6114 method: 'POST', 6115 dataType: 'json', 6116 async: false, 6117 data: { 6118 action: 'confirmTILA', 6119 paymentPlanSelection: planId, 6120 sessionKey: '' 6121 }, 6122 timeout: 15000, 6123 success: function(resp){ 6124 if (resp && resp.success){ 6125 closeModal(); 6126 if (typeof onAccept === 'function') { 6127 onAccept(); 6128 } 6129 } else { 6130 showTilaError(resp && resp.message ? resp.message : 'Unable to confirm payment plan. Please try again.'); 6131 } 6132 }, 6133 error: function(xhr, status, error){ 6134 showTilaError('Network or server error. Please try again.'); 6135 console.error('Error confirming TILA:', status, error); 6136 6137 }, 6138 complete: function(){ 6139 if ($modal.parent().length){ // still open 6140 restoreAcceptButton(); 6141 } 6142 } 6143 }); 6144 }); 6145 6146 function showTilaError(msg){ 6147 $errorBar.text(msg).fadeIn(150); 6148 } 6149 6150 function restoreAcceptButton(){ 6151 $btnAccept.prop('disabled', !$checkbox.is(':checked')) 6152 .html($btnAccept.data('origText') || 'Accept & Continue') 6153 .css({ cursor: $checkbox.is(':checked') ? 'pointer' : 'not-allowed', background: $checkbox.is(':checked') ? '#2f5d9f' : '#ccc', color: $checkbox.is(':checked') ? '#fff' : '#999' }); 6154 $btnPayInFull.prop('disabled', false).css({ opacity: 1, cursor: 'pointer' }); 6155 $checkbox.prop('disabled', false); 6156 } 6157 }, 6158 6159 /** 6160 * Get the currency symbol rendered by the widget 6161 */ 6162 getCurrencySymbol: function() { 6163 var sym = $('#basket-payment-plan-selection').data('currency-symbol'); 6164 return (sym === undefined || sym === null || sym === '') ? '$' : String(sym); 6165 }, 6166 6167 /** 6168 * Advance a date by a number of months, preserving the day of month 6169 * (clamped to the last day of the target month). Mirrors the server-side 6170 * getNextMonthDatePreservingDay logic used to schedule installments. 6171 */ 6172 addMonthsPreservingDay: function(originalDate, monthsToAdd) { 6173 var original = new Date(originalDate); 6174 var targetMonth = original.getMonth() + monthsToAdd; 6175 var firstOfTarget = new Date(original.getFullYear(), targetMonth, 1); 6176 var daysInTargetMonth = new Date(firstOfTarget.getFullYear(), firstOfTarget.getMonth() + 1, 0).getDate(); 6177 var targetDay = Math.min(original.getDate(), daysInTargetMonth); 6178 return new Date(firstOfTarget.getFullYear(), firstOfTarget.getMonth(), targetDay); 6179 }, 6180 6181 /** 6182 * Format a Date as a localized short date (falls back to ISO if needed) 6183 */ 6184 formatScheduleDate: function(date) { 6185 try { 6186 return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }); 6187 } catch (e) { 6188 return date.toISOString().split('T')[0]; 6189 } 6190 }, 6191 6192 /** 6193 * Build the installment schedule for a plan from the amounts currently 6194 * rendered in the widget. Returns an array of { number, date, amount }. 6195 */ 6196 buildScheduleForPlan: function(planId) { 6197 var firstText = $.trim($('[data-plan-first-id="' + planId + '"]').first().text()); 6198 var monthlyText = $.trim($('[data-plan-monthly-id="' + planId + '"]').first().text()); 6199 var firstPayment = parseFloat(firstText.replace(/,/g, '')) || 0; 6200 var monthlyPayment = parseFloat(monthlyText.replace(/,/g, '')) || 0; 6201 var $radio = $('input[name="basket_pp_option"][data-plan-id="' + planId + '"]'); 6202 var numberOfPayments = parseInt($radio.data('installments'), 10) || 0; 6203 6204 var schedule = []; 6205 var today = new Date(); 6206 for (var i = 0; i < numberOfPayments; i++) { 6207 schedule.push({ 6208 number: i + 1, 6209 date: (i === 0) ? today : this.addMonthsPreservingDay(today, i), 6210 amount: (i === 0) ? firstPayment : monthlyPayment 6211 }); 6212 } 6213 return schedule; 6214 }, 6215 6216 /**
6217 * Display a modal with the full payment schedule (dates + amounts) for a plan 6218 */ 6219 showScheduleModal: function(planId, planName) { 6220 var self = this; 6221 if (planId <= 0) { return; } 6222 6223 var currencySymbol = self.getCurrencySymbol(); 6224 var safeCurrencySymbol = $('<div/>').text(currencySymbol).html(); 6225 var schedule = self.buildScheduleForPlan(planId); 6226 if (!schedule.length) { return; } 6227 6228 var total = 0; 6229 var rowsHtml = ''; 6230 for (var i = 0; i < schedule.length; i++) { 6231 var item = schedule[i]; 6232 total += item.amount; 6233 var label = (item.number === 1) ? 'Today' : self.formatScheduleDate(item.date); 6234 rowsHtml += '<tr>' + 6235 '<td style="padding:6px 10px;border-bottom:1px solid #f0f0f0;color:#555;">' + item.number + '</td>' + 6236 '<td style="padding:6px 10px;border-bottom:1px solid #f0f0f0;color:#333;">' + label + '</td>' + 6237 '<td style="padding:6px 10px;border-bottom:1px solid #f0f0f0;text-align:right;font-weight:600;color:#222;">' + safeCurrencySymbol + self.formatCurrency(item.amount) + '</td>' + 6238 '</tr>'; 6239 } 6240 6241 var title = planName ? String(planName) : 'Payment Schedule'; 6242 6243 // Ensure only one schedule modal exists at a time 6244 $('#ppScheduleOverlay, #ppScheduleModal').remove(); 6245
6246 var $overlay = $('<div id="ppScheduleOverlay" style="position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:9998;"></div>'); 6247 var $modal = $('<div id="ppScheduleModal" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;max-width:520px;width:92%;max-height:80vh;overflow:auto;border-radius:8px;box-shadow:0 10px 28px rgba(0,0,0,.35);z-index:9999;font-family:Arial,sans-serif;"></div>'); 6248 var $header = $('<div style="padding:14px 18px;border-bottom:1px solid #eee;font-weight:600;font-size:15px;letter-spacing:.3px;display:flex;justify-content:space-between;align-items:center;"></div>'); 6249 $header.append($('<span></span>').text(title)); 6250 var $close = $('<button type="button" aria-label="Close" style="background:none;border:0;font-size:20px;line-height:1;cursor:pointer;color:#888;">×</button>'); 6251 $header.append($close); 6252 6253 var $body = $('<div style="padding:12px 16px;"></div>'); 6254 var $table = $('<table style="width:100%;border-collapse:collapse;font-size:12px;"></table>'); 6255 $table.append('<thead><tr>' + 6256 '<th style="padding:6px 10px;text-align:left;border-bottom:2px solid #e4e4e4;color:#666;font-weight:600;">#</th>' + 6257 '<th style="padding:6px 10px;text-align:left;border-bottom:2px solid #e4e4e4;color:#666;font-weight:600;">Due date</th>' + 6258 '<th style="padding:6px 10px;text-align:right;border-bottom:2px solid #e4e4e4;color:#666;font-weight:600;">Amount</th>' + 6259 '</tr></thead>'); 6260 $table.append('<tbody>' + rowsHtml + '</tbody>'); 6261 $table.append('<tfoot><tr>' + 6262 '<td colspan="2" style="padding:8px 10px;text-align:right;font-weight:600;color:#333;">Total</td>' + 6263 '<td style="padding:8px 10px;text-align:right;font-weight:700;color:#2f5d9f;">' + currencySymbol + self.formatCurrency(total) + '</td>' + 6264 '</tr></tfoot>'); 6265 $body.append($table); 6266 6267 var $note = $('<div style="padding:0 16px 14px 16px;font-size:10px;color:#666;line-height:1.3;">First payment may adjust for shipping, taxes, fees, and rounding differences. Dates and amounts shown are illustrative only.</div>'); 6268 6269 $modal.append($header, $body, $note); 6270 $('body').append($overlay, $modal); 6271 6272 function closeModal() { 6273 $overlay.remove(); 6274 $modal.remove(); 6275 } 6276 $close.on('click', closeModal); 6277 $overlay.on('click', closeModal); 6278 }, 6279 6280 /** 6281 * Public method to refresh payment plan amounts (called after promo code application) 6282 */ 6283 refreshAmounts: function(iOrderFee) { 6284 this.updateAllPlanAmounts(iOrderFee); 6285 }, 6286 6287 clearPaymentPlanSessions: function() { 6288 $.ajax({
6289 url: '/include/modules/paymentPlans/requests/ppAjax.asp', 6290 method: 'POST', 6291 dataType: 'json', 6292 async: true, 6293 data: { 6294 action: 'removePaymentPlanSessions', 6295 sessionKey: '' 6296 } 6297 }); 6298 }, 6299 6300 isPayInFullSelected: function() { 6301 return this.selectedPlanId === 0; 6302 } 6303 }; 6304 6305 // Initialize when document is ready 6306 $(document).ready(function() { 6307 // Check if payment plans are enabled and widget exists 6308 if ($('#basket-payment-plan-selection').length > 0) { 6309 basketPaymentPlan.init(); 6310 } 6311 }); 6312 6313 // Expose for external access if needed 6314 window.basketPaymentPlan = basketPaymentPlan; 6315 6316})(); 6317</script>
6317<div class='sw-banner-ad' data-sw-ad-location='basket_top1'></div> 6318<div class="clear"> 6319 <span class="heading-text sub-head-text" style="float:left;">Shopping Cart</span> 6320</div> 6321 6322<div class="basketSystemMessage"> 6323<p><!-- Meta Pixel Code -->
6324<script>// <![CDATA[
vendor: 408 bytes, lines 6324-6333
6324 6325!function(f,b,e,v,n,t,s) 6326{if(f.fbq)return;n=f.fbq=function(){n.callMethod? 6327n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 6328if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 6329n.queue=[];t=b.createElement(e);t.async=!0; 6330t.src=v;s=b.getElementsByTagName(e)[0]; 6331s.parentNode.insertBefore(t,s)}(window, document,'script', 6332'https://connect.facebook.net/en_US/fbevents.js'); 6333fbq('init', '
6333802935397828854
vendor: 32 bytes, lines 6333-6334
6333'); 6334fbq('track', 'PageView');
6335// ]]></script>
6335 6336<noscript><img height="1" width="1" style="display:none" 6337src="https://www.facebook.com/tr?id=802935397828854&ev=PageView&noscript=1" 6338/></noscript><!-- End Meta Pixel Code --><!-- Google tag (gtag.js) -->
6339<script src="https://www.googletagmanager.com/gtag/js?id=AW-11164002043">// <![CDATA[ 6340 6341// ]]></script>
vendor: 2 bytes, line 6341
6341
6342<script>// <![CDATA[ 6343
vendor: 138 bytes, lines 6343-6347
6343window.dataLayer = window.dataLayer || []; 6344 function gtag(){dataLayer.push(arguments);} 6345 gtag('js', new Date()); 6346 6347 gtag('config', '
6347AW-11164002043
vendor: 5 bytes, line 6347
6347');
6348// ]]></script>
6348</p> 6349 6350</div> 6351 6352<style> 6353.event-header{ 6354 float:left; 6355 display:inline-block; 6356 margin: 5px 0px 5px 20px; 6357 max-width:300px; 6358} 6359 6360.select-all{ 6361 width:2em; 6362 height:2em; 6363} 6364 6365.membership-remove{ 6366 display:none; 6367} 6368.mobile-only.mobile-remove.membership-remove{ 6369display:none !important; 6370} 6371.orderpromo-wrap {display: block; width: 100%; padding-bottom: 32px;} 6372</style> 6373<link rel="stylesheet" type="text/css" href="../Include/callout.css?v=2"> 6374 6375 6376 6377 6378 <!--Messages--> 6379 <span id="error-messages" class=""></span> 6380 6381 6382 <br> 6383 <br> 6384 <center> 6385 <span>Your Shopping Cart is empty</span> 6386 <br> 6387 <br> 6388 6389 6390 <input type="button" id="EmptyCartContinueButton" aria-label="Empty Cart Continue button" class="button sw-button-primary" value="Continue" onclick="window.location.href='default.asp'"> 6391 </center> 6392 6393 6394 <br> 6395 <br> 6396 <br> 6397 6398 <!--GEM21073 - Seatmap in Basket Includes - thickbox jquery plugin - Begin--> 6399
6399<script type="text/javascript" src="include/thickbox-compressed.js"></script>
6399 6400 <style type="text/css" media="all">@import "include/thickbox.css";</style> 6401 <!--GEM21073 - Seatmap in basket END --> 6402
6402<script type="text/javascript"> 6403 6404 6405 6406 //update orderinfo in data layer for Tag Manager and tracking 6407 if (typeof addDataLayer == 'function') { 6408 addDataLayer('TicketingOrderTotal', '0'); 6409 addDataLayer('TicketingTicketItems', ''); 6410 addDataLayer('TicketingDonationItems', ''); 6411 addDataLayer('TicketingMembershipItems', ''); 6412 addDataLayer('TicketingOrderSubTotal', '0'); 6413 addDataLayer('TicketingItemCount', '0'); 6414 addDataLayer('TicketingProcessingFee', '0'); 6415 addDataLayer('TicketingSalesChannel', '0'); 6416 addDataLayer('TicketingHasMixedBasket', '0'); 6417 addDataLayer('TicketingEventCategories', ''); 6418 } 6419 6420 6421 var hasSaneDeliveryOption = true; 6422 6423 /*If we don't have a set of compatible delivery options warn the user, since they won't be able to continue*/ 6424 if(!hasSaneDeliveryOption){ 6425 $("#checkout-button").attr("disabled","disabled"); 6426 $("#checkout-button").attr("title", "The basket's items don't have compatible delivery options, please order the items individually."); 6427 } 6428 6429 //add even-item class to every other basket-item 6430 $(".basket-item:odd").addClass("even-item"); 6431 6432 var Basket = function(basketID, bundleID){ 6433 this.expiredTickets = []; 6434 6435 var isChangePriceSaveMode = {}; 6436 6437 this.selectAll = function(selector) { 6438 $(selector).prop("checked", true); 6439 } 6440 6441 this.deselectAll = function(selector) { 6442 $(selector).prop("checked", false); 6443 } 6444 6445 this.deleteItems = function(options) { 6446 var hasItemsChecked = $(".line-item-checkbox").is(":checked"), 6447 defaults = { 6448 bypassPrompt: false, 6449 reloadBasket: true 6450 }; 6451 6452 options = _.extend(defaults, options); 6453 6454 if (hasItemsChecked) { 6455 if (options.bypassPrompt || confirm('Are you sure that you want to remove the selected items?')) { 6456 document.getElementById("activity").value = "deleteItems"; 6457 document.basket.action = "BasketUpdate.asp"; 6458 var removeTickets = document.getElementById("RemoveTickets"); 6459 if(removeTickets){ 6460 removeTickets.disabled = true; 6461 } 6462 this.postToBasketUpdate(function(){ 6463 if (options.reloadBasket) { 6464 window.location.reload(); 6465 } 6466 }); 6467 } 6468 } else { 6469 alert('No items selected.'); 6470 } 6471 } 6472 6473 this.deleteBasket = function() { 6474 if (confirm('Are you sure, that you want to remove ALL items from the Shopping Cart?')) { 6475 document.getElementById("activity").value = 'deleteBasket'; 6476 document.basket.action = "BasketUpdate.asp"; 6477 var removeTickets = document.getElementById("RemoveTickets"); 6478 if(removeTickets){ 6479 removeTickets.disabled = true; 6480 } 6481 try{ 6482 //update tag manager if present 6483 addDataLayer('TicketingTicketItems', ''); 6484 dataLayer.push({'event': 'BasketEmptied'}); 6485 //update enhanced ecommerce 6486 swEnhancedEcommerce.sendRemoveAllFromBasket(); 6487 }catch(e){ 6488 console.log(e); 6489 } 6490 this.postToBasketUpdate(function(){ 6491 window.location.reload(); 6492 }); 6493 } 6494 } 6495 6496 this.addCoupon = function(){ 6497 var couponCodeParameter = encodeURIComponent($("#couponCode").val().replace(/[^0-9a-zA-Z_]+/g,"")); //coupon codes only allows alphanumeric and underscores 6498 var basketIDParameter = encodeURIComponent(basketID); 6499 var updateURL = "BasketUpdate.asp?couponcode=" + couponCodeParameter + "&basketid=" + basketIDParameter + "&activity=addCoupon" ; 6500 6501 $.get(updateURL, function(data){ 6502 var url = window.location.href; 6503 url = url.replace(/([&?])((ic|doAutoApply)=[a-zA-Z0-9])/g, (match, p1, p2) => { 6504 if (match.charAt(0) === "?") { 6505 return p1 === "?" ? "?" : ""; 6506 } else { 6507 return ""; 6508 } 6509 }); 6510 var hasQueryStringParams = /\?/.test(url) && url[url.length-1] != "?"; 6511 var additionalParam = "?doAutoApply=x"; 6512 6513 if(hasQueryStringParams){ 6514 additionalParam = "&doAutoApply=x"; 6515 } 6516 6517 additionalParam = additionalParam + "&ic=" + (data.messages.hasInvalidCoupon ? "1" : "0"); 6518 6519 window.location.href = (url + additionalParam); 6520 }); 6521 } 6522 6523 this.removeCoupon = function(couponCode){ 6524 var couponCodeParameter = encodeURIComponent(couponCode); 6525 var basketIDParameter = encodeURIComponent(basketID); 6526 var updateURL = "BasketUpdate.asp?couponcode=" + couponCodeParameter + "&basketid=" + basketIDParameter + "&activity=removeCoupon" ; 6527 6528 $.get(updateURL, function(data){ 6529 window.location.reload(); 6530 }); 6531 } 6532 6533 this.changeMembershipPricing = function(context){ 6534 var $item = $(context).parents(".basket-item"); 6535 var itemID = ($item.attr("id")).replace("item-", ""); 6536 var $priceSpan = $item.find(".level-price-value"); 6537 6538 if(isChangePriceSaveMode[itemID]){ 6539 $(context).text("change"); 6540 isChangePriceSaveMode[itemID] = false; 6541 6542 var previousValue = isChangePriceSaveMode["prev" + itemID]; 6543 var enteredVal = $priceSpan.find("#changePrice").val().replace(/[^0-9\.]+/g,""); 6544 6545 $priceSpan.html(""); 6546 6547 enteredVal = isNaN(enteredVal) ? 0.00 : enteredVal; 6548 6549 /*format as currency*/ 6550 enteredVal = $.trim('$' + parseFloat(enteredVal, 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString()); 6551 6552 $priceSpan.text(enteredVal); 6553 6554 var updateURL ="BasketUpdate.asp?activity=changeMembershipPrice&membershipPrice=" + encodeURIComponent(enteredVal.replace("$", "")) + "&basketItemID=" + encodeURIComponent(itemID) + "&basketID="+ encodeURIComponent(basketID); 6555 6556 this.sendGet(updateURL, function(data){ 6557 if(data){ 6558 if (data.messages.errors[0]){ 6559 //revert on error 6560 $priceSpan.text(previousValue); 6561 return; 6562 } 6563 $priceSpan.text(enteredVal); 6564 6565 // Update price in basket.items.memberships object 6566 if(basket.items && basket.items.memberships){ 6567 var numericPrice = parseFloat(enteredVal.replace(/[^0-9\.]+/g,"")); 6568 for(var i = 0; i < basket.items.memberships.length; i++){ 6569 if(basket.items.memberships[i].BasketItemID == itemID){ 6570 basket.items.memberships[i].Price = numericPrice; 6571 break; 6572 } 6573 } 6574 } 6575 6576 // Reload basket and update totals 6577 getClientBasket(function() { 6578 calculateTotals(); 6579 updatePaymentPlansTotals(); 6580 });
6581 }else{ 6582 window.location.reload(); 6583 } 6584 }); 6585 }else{ 6586 $(context).text("save"); 6587 isChangePriceSaveMode[itemID] = true; 6588 6589 /*Add Textbox if editing*/ 6590 if($("#changePrice").length <= 0){ 6591 var priceValue = $priceSpan.text(); 6592 isChangePriceSaveMode["prev" + itemID] = priceValue; 6593 6594 if($("#changePrice").length <= 0){ 6595 $priceSpan.html("<input class='showare-text' id='changePrice' aria-label='Change Price' type='text' style='width:5.5em;margin-bottom:.5em;' />"); 6596 6597 $("#changePrice").val(priceValue.replace(/[^0-9\.]+/g,"")) 6598 } 6599 } 6600 } 6601 } 6602 6603 this.changePricingCode = function(context){ 6604 var pcErrors = "" 6605 6606 $(context).attr("disabled", "true"); 6607 $(context).css("background","RGBA(0,0,0,0.5)"); 6608 6609 var updateURL = "/BasketUpdate.asp?pricingcode=" + encodeURIComponent($(context).val()) + "&activity=changePricing" 6610 6611 var ticketIDs = "&ticketID=" + encodeURIComponent($(context).attr("id").replace("pricingCode-", "")); 6612 6613 updateURL += ticketIDs; 6614 6615 $.get(updateURL) 6616 .then(function(data){ 6617 if(data.messages.errors[0]){ 6618 if (data.messages.errors[0].message == undefined) 6619 pcErrors += "The pricing code you selected is not valid.<br>"; 6620 else 6621 pcErrors += data.messages.errors[0].message; 6622 revertCart(pcErrors, context); 6623 }else{ 6624 updateCart(context, data); 6625 updatePaymentPlansTotals(); 6626 //re-apply any promo codes if we have basket discounts 6627 //this is needed because changing ticket pricing codes will need to re-apply promos to the new pricings 6628 //and get and render the correct totals again 6629 if (basket.discounts.HasBasketDiscounts) 6630 { 6631 applyPromoCode(); 6632 getClientBasket(); 6633 } 6634 } 6635 }) 6636 .catch(function(){ 6637 pcErrors += "We were unable to process your request.<br>" 6638 revertCart(pcErrors, context); 6639 }); 6640 6641 } 6642 this.changeSinglePricingCode = function(context){ 6643 var pcErrors = "" 6644 6645 $(context).attr("disabled", "true"); 6646 $(context).css("background","RGBA(0,0,0,0.5)"); 6647 6648 var updateURL = "/BasketUpdate.asp?pricingcode=" + encodeURIComponent($(context).val()) + "&activity=changeSingleTicketPricing" 6649 6650 var ticketIDs = "&ticketID=" + encodeURIComponent($(context).attr("id").replace("pricingCode-", "")); 6651 6652 updateURL += ticketIDs; 6653 6654 $.get(updateURL) 6655 .then(function(data){ 6656 if(data.messages.errors[0]){ 6657 if (data.messages.errors[0].message == undefined) 6658 pcErrors += "The pricing code you selected is not valid.<br>"; 6659 else 6660 pcErrors += data.messages.errors[0].message; 6661 6662 revertCart(pcErrors, context); 6663 }else{ 6664 updateCart(context, data); 6665 updatePaymentPlansTotals(); 6666 //re-apply any promo codes if we have basket discounts 6667 //this is needed because changing ticket pricing codes will need to re-apply promos to the new pricings 6668 //and get and render the correct totals again 6669 if (basket.discounts.HasBasketDiscounts) 6670 { 6671 applyPromoCode(); 6672 getClientBasket(); 6673 } 6674 6675 } 6676 }) 6677 .catch(function(){ 6678 pcErrors += "We were unable to process your request.<br>" 6679 revertCart(pcErrors, context); 6680 }); 6681 6682 } 6683 6684 function updateCart(context, data){ 6685 var currencySymbol = '$' 6686 var basketTickets = data.items.tickets; var basketDonations = data.items.donations; var basketMemberships = data.items.memberships; var orderProcessingFees = data.items.orderFee[0]; 6687 var workingTicketID =0; 6688 try{ 6689 workingTicketID = parseInt($(context).attr("id").replace("pricingCode-", "")); 6690 }catch(e){ 6691 console.log(e); 6692 } 6693 6694 var orderProcessingFee = 0; 6695 if (typeof(orderProcessingFees) === 'undefined'){ 6696 orderProcessingFees = 0; 6697 }else{ 6698 orderProcessingFee = orderProcessingFees.OrderFee; 6699 } 6700 6701 var extFee3Total = 0; 6702 var basketTotal = 0; 6703 var ticketTotal = 0; 6704 var ticketPrintedPriceTotal = 0; 6705 var extFee1Total = 0; 6706 var extFee2Total = 0; 6707 var donationTotal = 0; 6708 var membershipTotal = 0; 6709 console.log(data); 6710 //update totals 6711 for(var i = 0;i<basketDonations.length;i++){ 6712 donationTotal += basketDonations[i].Price; 6713 basketTotal += basketDonations[i].Price; 6714 } 6715 for(var i = 0;i<basketMemberships.length;i++){ 6716 membershipTotal += basketMemberships[i].Price; 6717 basketTotal += basketMemberships[i].Price; 6718 } 6719 for(var i = 0;i<basketTickets.length;i++){ 6720 if(basketTickets[i].TicketID == workingTicketID){ 6721 var totalPrice = basketTickets[i].Price + basketTickets[i].ExtFee2 + basketTickets[i].ExtFee3 + basketTickets[i].Tax + basketTickets[i].TransactionFee; 6722 //update fees for this item here/////////////////////// 6723 $("#" + basketTickets[i].TicketID + "-Price .fees-item").html(currencySymbol + basketTickets[i].Price.toFixed(2)); 6724 $("#" + basketTickets[i].TicketID + "-TransactionFee .fees-item").html(currencySymbol + basketTickets[i].TransactionFee.toFixed(2)); 6725 $("#" + basketTickets[i].TicketID + "-PriceWithFees .fees-item").html(currencySymbol + totalPrice.toFixed(2)); 6726 6727 $("#" + basketTickets[i].TicketID + "-ExtFee2 .fees-item").html(currencySymbol + basketTickets[i].ExtFee2.toFixed(2)); 6728 6729 } 6730 6731 ticketTotal += basketTickets[i].Price; 6732 ticketPrintedPriceTotal += basketTickets[i].PrintedPrice; 6733 6734 ticketTotal += basketTickets[i].ExtFee2 + basketTickets[i].ExtFee3 + basketTickets[i].TransactionFee; 6735 ticketPrintedPriceTotal += basketTickets[i].ExtFee2 + basketTickets[i].ExtFee3 + basketTickets[i].TransactionFee; 6736 6737 extFee1Total += basketTickets[i].TransactionFee; 6738 extFee2Total += basketTickets[i].ExtFee2; 6739 basketTotal += basketTickets[i].Price + basketTickets[i].ExtFee2 + basketTickets[i].ExtFee3 + basketTickets[i].Tax + basketTickets[i].TransactionFee; 6740 6741 // Update strikethrough pricing if applicable 6742 6743 $("#" + basketTickets[i].TicketID + "-strikethrough-display").hide(); 6744 6745 } 6746 6747 6748 if (basketTotal == 0 && true) 6749 $(".basket-processing-fee").html(currencySymbol + 0.00); 6750 else 6751 { 6752 $(".basket-processing-fee").html(currencySymbol + orderProcessingFee.toFixed(2)); 6753 basketTotal = basketTotal + orderProcessingFee; 6754 } 6755 6756 $(".basket-extFee3").html(currencySymbol + extFee3Total.toFixed(2)); 6757 $("#basketTotalCell").html(currencySymbol + basketTotal.toFixed(2)); 6758 $(".basket-item-updated-alert").remove(); 6759 $(context).parent().parent().append("<span class='no-mobie basket-item-updated-alert'>updated</span>"); 6760 $(context).removeAttr("disabled"); 6761 $("#error-messages").html(""); 6762 $("#error-messages").removeClass("error-message"); 6763 $(context).css("background","RGBA(0,255,0,0.05)"); 6764 $(".basket-toggle-fees").removeClass("mobile-only"); //class forces item to be visible on mobile to prevent confusion, we have to remove it to hide properly. 6765 //actWidget("basketChange"); 6766 6767 $(".baskettotal-wrap .ordertotal-subtotal").html(currencySymbol + (ticketTotal + donationTotal + membershipTotal).toFixed(2)); 6768 $(".baskettotal-wrap .ordertotal-offfer").html(currencySymbol + (ticketPrintedPriceTotal - ticketTotal).toFixed(2)); 6769 $(".baskettotal-wrap .fee1 .ordertotal-tax").html(currencySymbol + extFee1Total.toFixed(2)); 6770 $(".baskettotal-wrap .fee2 .ordertotal-tax").html(currencySymbol + extFee2Total.toFixed(2)); 6771 $(".baskettotal-wrap .fee3 .ordertotal-tax").html(currencySymbol + extFee3Total.toFixed(2)); 6772 $(".baskettotal-wrap .ordertotal-ordertotal").html(currencySymbol + basketTotal.toFixed(2)); 6773 } 6774 6775 function revertCart(errors, context){ 6776 $(context).removeAttr("disabled"); 6777 $("#error-messages").html("<div id='pricingCodeErrors'>" + errors + "<div>"); 6778 $("#error-messages").addClass("error-message"); 6779 $(window).scrollTop( 0 ); 6780 $(context).val($(context).data("default")); 6781 $(context).css("background","RGBA(255,0,0,0.05)"); 6782 } 6783 6784 this.sendGet = function(updateURL, callback){ 6785 $.get(updateURL, function(basketData){ 6786 if($("#pricingCodeErrors").length > 0){ 6787 $("#pricingCodeErrors").remove(); 6788 6789 if(parseInt($("#error-messages").text().length) <= 0){ 6790 $("#error-messages").removeClass("error-message") 6791 } 6792 } 6793 6794 if(_.isObject(basketData) && _.isArray(basketData.messages.errors) && basketData.messages.errors.length > 0){ 6795 for(var i = 0; i < basketData.messages.errors.length; i++){ 6796 $("#error-messages").html("<div id='pricingCodeErrors'>" + basketData.messages.errors[i].message + "<div>"); 6797 } 6798 6799 if(!$("#error-messages").hasClass("error-message")){ 6800 $("#error-messages").addClass("error-message") 6801 } 6802 } 6803 6804 callback(basketData); 6805 }, "json"); 6806 } 6807 6808 6809 this.postToBasketUpdate = function(callback){ 6810 var o = {}; 6811 var a = $("#basket").serializeArray(); 6812 $.each(a, function() { 6813 if (o[this.name]) { 6814 if (!o[this.name].push) { 6815 o[this.name] = [o[this.name]]; 6816 } 6817 o[this.name].push(this.value || ''); 6818 } else { 6819 o[this.name] = this.value || ''; 6820 } 6821 }); 6822 6823 $.ajax({
6824 type: "POST", 6825 url: "/BasketUpdate.asp", 6826 data: o, 6827 success: function(data) { 6828 6829 if (data.messages.errors.length > 0 ) 6830 { 6831 for (var i =0;i<data.messages.errors.length;i++) 6832 { 6833 alert(data.messages.errors[i].message); 6834 } 6835 } 6836 callback(); 6837 } 6838 6839 }); 6840 } 6841 6842 this.startTicketTimers = function() { 6843 var timer, 6844 self = this; 6845 6846 for(var i = 0; i < Basket.expirationTimers.length; i++) { 6847 timer = Basket.expirationTimers[i]; 6848 _startExpirationTimer(timer.id, timer.remainingSeconds, timer.serverTime); 6849 } 6850 6851 6852 function _startExpirationTimer(id, remainingSeconds, serverTime) { 6853 var counter, 6854 secondsOffset = (Date() - Date(serverTime))/1000, 6855 $timerDiv = $("#" + id); 6856 6857 $timerDiv.text(""); 6858 counter = setInterval(timer, 1000); 6859 6860 function timer(){ 6861 remainingSeconds--; 6862 if (remainingSeconds <= 0){ 6863 clearInterval(counter); 6864 self.setTicketExpired(id); 6865 } 6866 displayRemainingText(); 6867 } 6868 6869 function displayRemainingText() { 6870 var timeDisplay; 6871 6872 if(remainingSeconds <= 0){ 6873 timeDisplay = "expired"; 6874 }else if(remainingSeconds < 3600){ 6875 timeDisplay = parseInt(remainingSeconds/60) + ":" + ("0"+(remainingSeconds%60)).slice(-2); 6876 }else{ 6877 timeDisplay = parseInt(remainingSeconds/3600) + "+ hours"; 6878 } 6879 6880 $timerDiv.text(timeDisplay); 6881 } 6882 }; 6883 }; 6884 6885 6886 this.setTicketExpired = function(id) { 6887 $("#expired-error").show(); 6888 this.expiredTickets.push(id); 6889 }; 6890 6891 this.removeExpiredTickets = function() { 6892 var id, 6893 isBasketEmpty, 6894 $ticketCheckbox; 6895 6896 for(var i = 0; i < this.expiredTickets.length; i++) { 6897 id = "#" + this.expiredTickets[i]; 6898 $ticketCheckbox = $(id).parents(".basket-ticket-item").first().find(".ticket-line-item-checkbox"); 6899 $ticketCheckbox.prop('checked', true); 6900 } 6901 6902 isBasketEmpty = $(".basket-item").length == this.expiredTickets.length; 6903 this.deleteItems({bypassPrompt: true, reloadBasket: isBasketEmpty}); 6904 } 6905 } 6906 Basket.expirationTimers = []; 6907 6908 $(document).ready(function(){ 6909 var basket = new Basket("0FkQ0UVTLSTMzgwTMTgE10CMD2IyMMDNykxTNTIEx0CNDuExMOjL1E1jLjcY2xULEK9KRRUSRx~__U_g_", 0); 6910 basket.startTicketTimers(); 6911 6912 $(".select-all-button").on("click", function(){ 6913 basket.selectAll('.line-item-checkbox'); 6914 }); 6915 6916 $(".deselect-all-button").on("click", function(){ 6917 basket.deselectAll('.line-item-checkbox'); 6918 }); 6919 6920 $(".add-coupon").on("click", function(){ 6921 basket.addCoupon(); 6922 }); 6923 $("#couponCode").on("keypress",function(e){ 6924 if(e.keyCode === 13){ 6925 basket.addCoupon(); 6926 e.preventDefault(); 6927 } 6928 }) 6929 6930 $(".delete-coupon").on("click", function(){ 6931 basket.removeCoupon($(this).siblings(".coupon-value").text()); 6932 }); 6933 6934 $("#RemoveTickets").on("click", function(){ 6935 basket.deleteItems(); 6936 }); 6937 6938 $("#delete-basket").on("click", function(){ 6939 basket.deleteBasket(); 6940 }); 6941 6942 $(".change-price-anchor").on("click", function(e){ 6943 e.preventDefault(); 6944 basket.changeMembershipPricing(this); 6945 }); 6946 6947 $(".pricingcode-dropdown").on("change", function(){ 6948 basket.changeSinglePricingCode(this); 6949 }); 6950 6951 6952 6953 $(".mobile-remove, .item-remove").click(function(){ 6954 var thisIndex = $(this).data("removeid"); 6955 $(".line-item-checkbox-"+thisIndex).prop("checked", true); 6956 6957 basket.deleteItems(); 6958 }); 6959 }); 6960 6961 function makedonation() { 6962 window.location = "Donate.asp"; 6963 } 6964 6965 function buildCallout(tagId, productType, productId, areaID, message, actionLink){ 6966 var productHref; 6967 6968 //Construct link 6969 switch(productType){ 6970 case "event": 6971 productHref = "eventperformances.asp?evt=" + productId; 6972 break; 6973 case "performance": 6974 if(areaID > 0){ 6975 productHref = "orderticketsarea.asp?p=" + productId + "&a=" + areaID; 6976 }else{ 6977 productHref = "ordertickets.asp?p=" + productId; 6978 } 6979 break; 6980 case "bundle": 6981 productHref = "BundlePurchase_Qty.asp?BundleID=" + productId; 6982 break; 6983 case "campaign": 6984 productHref = "DonationAddToBasket.asp?camp=" + productId; 6985 break; 6986 case "membership": 6987 productHref = "MembershipSelection.asp?type=" + productId; 6988 break; 6989 case "fund" : 6990 productHref = "DonationSelection.asp?acc=" + productId; 6991 break; 6992 case "0": 6993 productHref="" 6994 break; 6995 } 6996 6997 //construct bubble text and attach to bubble 6998 6999 $(tagId).html("<p id=\"message-paragraph\"></p>"); 7000 $(tagId + " #message-paragraph").html(message); 7001 if($(tagId + " #message-paragraph p").length){ 7002 if (productHref.length>0){ 7003 $(tagId + " #message-paragraph p").last().append("<a href=\"" + productHref + "\" style='float:none;'> (" + actionLink + ")</a>"); 7004 } 7005 }else{ 7006 if (productType != "0"){ 7007 $(tagId + " #message-paragraph").append("<a href=\"" + productHref + "\" style='float:none;'> ( " + actionLink + " )</a>"); 7008 } 7009 } 7010 $(".bubble-container").css("visibility", "inherit"); //show with the text already rendered. 7011 7012 } 7013 7014 function startExpirationTimer(id, remainingSeconds, serverTime){ 7015 Basket.expirationTimers.push({'id': id, 'remainingSeconds': remainingSeconds, 'serverTime': serverTime}); 7016 } 7017 function toggleFees(){ 7018 $("#basket").toggleClass("basket-hide-fees"); 7019 $(".ticket-legend-total a.basket-toggle-fees").html("Hide Fees"); 7020 $(".basket-hide-fees .ticket-legend-total a.basket-toggle-fees").html("Show Fees"); 7021 $("a.basket-toggle-fees").html("Hide Fees"); 7022 $(".basket-hide-fees a.basket-toggle-fees").html("Show Fees"); 7023 } 7024 </script>
7024 7025</div> 7026<!--footer here--> 7027 7028 <div class="clear-float"></div> 7029 </div><!--End main-container #END--> 7030 <!-- end main arean --> 7031 <div class="clear-float"></div><!--force inner-content pas floated left and right sections--> 7032 7033 </div><!--END content-inner END--> 7034 </div><!--END content-wrap END--> 7035 7036 <div class="foot-wrap"> 7037 <div class="foot-inner center-div site-width"> 7038 7039 <center><div class='sw-banner-ad' data-sw-ad-location='footer'></div> </center> 7040 7041 <span class="copyright-text"> 7042 Copyright © 2026 CincyTicket, All Rights Reserved. <span class="no-mobile">-</span> <br class="mobile-only" /> 7043 Ticketing System by <a class="Copyrightlink" target="_blank" href="https://www.cincyticket.net">CincyTicket Solutions</a><br><br> 7044 <span class="copyright-text">Please read our <a href="Javascript:popUp('Privacy Statement','privacystatement.asp',350,420,'no','yes','no','no')">Privacy Statement</a> and <a href="Javascript:popUp('Terms of Use','termsofuse.asp',350,420,'no','yes','no','no')">Terms of Use</a>.</span> 7045 <br><br> 7046 </span><!--END copyright-text span END--> 7047 7048 7049
7049<script language="JavaScript" type="text/javascript"> 7050 //variable defined via external script from HTMLHeadClose.asp 7051 if (typeof TrustLogo !== "undefined") { 7052 TrustLogo("https://www.cincyticket.com/images/comodo.png", "CL1", "none"); 7053 } 7054 </script>
7054 7055 7056 </div><!--END foot-inner END--> 7057 </div><!--END foot-wrap END--> 7058 7059 7060 7061</div><!--END page-wrap END--> 7062 7063
7064<script language="javascript"> 7065 $(function () { 7066 //activate modals 7067 hoverModal(); 7068 }); 7069</script>
7069 7070 7071 7072
7072<script async src="//www.cincyticket.com/include/widgets/basket/basketwidget.js?ver=20228b0075" id="showarebasketscript" type="text/javascript"></script>
7072 7073 7074
7075<script> 7076 var cb = function() { 7077 var l = document.createElement('link'); l.rel = 'stylesheet'; 7078 l.href = '/include/jqueryui-themes/default/jquery-ui.css'; 7079 var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h); 7080 }; 7081 var raf = window.requestAnimationFrame || 7082 window.webkitRequestAnimationFrame || 7083 window.mozRequestAnimationFrame || 7084 window.oRequestAnimationFrame || 7085 window.msRequestAnimationFrame ; 7086 if (raf) raf(cb); 7087 else window.addEventListener('load', cb); 7088</script>
7088 7089
7090<script type="text/javascript"> 7091 $("body").addClass("basket"); 7092 if(window.location.hostname.toLowerCase() != "www.cincyticket.com"){ 7093 Showare.Logger.warn("Bad Domain Request","www.cincyticket.com - " + window.location.hostname); 7094 window.location.replace("//www.cincyticket.com"); 7095 } 7096 7097</script>
7097 7098 7099<!-- ARIA ACCESSABILITY FEATURES -->
7100<script type="text/javascript"> 7101 try{ 7102 7103 $(".main-container").attr("role","main"); 7104 $("ul.showare-nav").attr("role","list"); 7105 $("ul.showare-nav li").attr("role","listitem"); 7106 $("ul.showare-nav li a").attr("role","button"); 7107 $(".search-control").attr("role","listitem"); 7108 $("input.search-text").attr("aria-label","Search"); 7109 $(".theme-custom-field-set input").attr("aria-labelledby","custom-field-label").attr("aria-label","Additional Information box"); 7110 $(".theme-custom-field-set select").attr("role","listbox").attr("aria-labelledby","custom-field-label").attr("aria-label","Additional Information list"); 7111 $(".control-wrap").attr("role","complementary").attr("aria-label","Side Navigation"); 7112 $("header.head-wrap").attr("role","banner"); 7113 $("div.foot-wrap").attr("role","contentinfo"); 7114 $("a.header-logo-link h1").attr("aria-hidden","true"); 7115 $(".copyright-text:last").find("a").attr("role", "button"); 7116 $(".tab-nav-wrap").find("a").attr("role", "button"); 7117 $("#mobile-menu").attr("role","list"); 7118 $("#mobile-menu li").attr("role","listitem"); 7119 $("#mobile-menu li a").attr("role","button"); 7120 $(".heading-text").attr("role","heading").attr("aria-level","2"); 7121 7122 $("a.bodylink").attr("role","button"); 7123 $("a.getmembership-link").attr("role","button"); 7124 7125 $("a.header-logo-link h1").attr("aria-level","1"); 7126 $("#demo-div").attr("role","region").attr("aria-label","Only a Demo Site"); 7127 $("#swCustomListings").attr("aria-label","Featured Custom Listing"); 7128 7129 7130 $(".ad-image").attr("role","presentation"); 7131 7132 7133 //add a basket link for aria to read 7134 $("li.basket-widget").prepend('<a tabindex="0" class="aria-basket-link" href="basket.asp?fw=1">Shopping Cart</a>'); 7135 7136 //adds aria-label explaining that the link is opening a new tab if the link has target="blank" on it and no aria-label added 7137 $('a[target="_blank"]').each(function() { 7138 if (!$(this).attr('aria-label')) { 7139 $(this).attr('aria-label', 'Opens in a new tab.'); 7140 } 7141 }); 7142 // address the "button can not be empty" - add the Next Month and Previous month to the arrow buttons 7143 var spanNextMonth = $('<span>', {id: 'bn_next-label', class: 'sr-only', text: 'Next Month'}); 7144 var spanPrevMonth = $('<span>', {id: 'bn_prev-label', class: 'sr-only', text: 'Previous Month'});
7145 $('.bn_next').prepend(spanNextMonth); 7146 $('.bn_prev').prepend(spanPrevMonth); 7147 7148 // add ID attribute to main sections 7149 $("header.head-wrap.no-mobile").attr("id","mainheadwrap"); 7150 $("div.content-wrap").attr("id","maincontentwrap"); 7151 $("div.foot-wrap").attr("id","mainfootwrap"); 7152 7153 // adding Skip link 7154 var skipLinkToHeader = $('<a>', {href: '#mainheadwrap', class: 'skip-link', text: 'Skip to header content', 'aria-label': 'Skip to header content', 'role': 'link'}); 7155 var skipLinkToMainContent = $('<a>', {href: '#maincontentwrap', class: 'skip-link', text: 'Skip to main content', 'aria-label': 'Skip to main content', 'role': 'link'}); 7156 var skipLinkToFooterContent = $('<a>', {href: '#mainfootwrap', class: 'skip-link', text: 'Skip to footer content', 'aria-label': 'Skip to footer content', 'role': 'link'}); 7157 7158 // add created skip link above the main sections 7159 $(skipLinkToHeader).insertBefore("header.head-wrap.no-mobile"); 7160 $(skipLinkToMainContent).insertBefore("div.content-wrap"); 7161 $(skipLinkToFooterContent).insertBefore("div.foot-wrap"); 7162 7163 // use setTimeout to make sure all are loaded before adding attributes 7164 setTimeout(function() { 7165 $('html').attr('lang', 'en'); 7166 $(".day-cell.highlight-day").attr("tabindex", "0"); // address the interactive elements should be navigable using the keyboard 7167 $("#ShoWareBasketWidget").find(".cart-item").attr("role", "button").attr("tabindex", "0"); 7168 $("#ShoWareBasketWidget .cart-item .cart-item-pic").attr("role", "cart presentation"); 7169 $("#ShoWareBasketWidget .cart-item .cart-item-pic .sw-i-cart").attr("role", "cart presentation"); 7170 $(".featured-items-item .streaming-note").attr("role","presentation"); 7171 $(".pl-item a.pl-popup-link").attr("role","button"); 7172 $(".pl-date-block-image").attr("role","img"); 7173 $("#epImage2 img").attr("alt","Event Banner"); 7174 $('.navigation.sw-nav > a[href*="basket.asp"]').attr({ 7175 'title': 'View Basket', 7176 'aria-label': 'View Basket' 7177 }); 7178 7179 // address the "Incorrect use of aria-describedy" - this is used in the header cart but there's no ID to refer it to 7180 var cartTitle = $('.cart-item-desc').attr('title'); 7181 var spanCartItemDesc = $('<span>', {id: 'cart-text', class: 'sr-only', text: cartTitle}); 7182 $('.cart-item-desc').prepend(spanCartItemDesc); 7183 7184 // address the "Incorrect use of aria-describedy" - this is used in the calendar and no ID to refer it to 7185 var calendarTableTitle = $('.calendar-object table:first').attr('title'); 7186 var spanCalendarIDAdded = $('<span>', {id: 'month', class: 'sr-only', text: calendarTableTitle}); 7187 $('.calendar-object table:first').prepend(spanCalendarIDAdded); 7188 $('img[src$="sectigo_trust_seal_lg_140x54.png"]').attr({alt: "Sectigo Seal", 'aria-label': "Sectigo Seal"}); 7189 $("a.aria-basket-link").attr("role","button").attr("aria-label","Shopping Cart"); 7190 $(".month-wrap .month").attr("aria-level","3"); 7191 7192 var $metaViewport = $('meta[name="viewport"]'); 7193 if ($metaViewport.length) { 7194 $metaViewport.attr('content', 'width=device-width, initial-scale=1.0, minimum-scale=1.0'); 7195 } else { 7196 $('head').append('<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0">'); 7197 } 7198 7199 }, 1200); 7200 7201 setTimeout(function() { 7202 $('[data-index]').removeAttr('data-index'); 7203 $('[tabindex]').removeAttr('tabindex'); 7204 $('[tabindes]').removeAttr('tabindes'); 7205 7206 let HeaderElements = $('.head-inner').find('.logo-container a, .showare-nav-inner a, select, textarea, input, a.button,#ShoWareBasketWidget .cart-item'); 7207 let SideBarElements = $('.show-wrap').find('a, .sw-datepicker td.highlight-day, .bn_prev, .month, .bn_next'); 7208 let allElements = $('.main-container').find('input, select, textarea, a.button, .info-box a, button, h2 a, h3 a, a.pl-popup-link, #basket a, .login-form a'); // find all elements that needed tab index 7209 7210 // Header 7211 HeaderElements.each(function() { 7212 $(this).removeAttr('tabindex'); 7213 }); 7214 $(".showare-nav li").removeAttr('tabindex'); 7215 $("#ShoWareBasketWidget .cart-item").removeAttr('tabindex'); 7216 $(".aria-basket-link").removeAttr('tabindex'); 7217 $("#searchButton").removeAttr('tabindex'); 7218 $(".show-wrap .control-box").removeAttr('tabindex'); 7219 7220 HeaderElements.each(function(index) { 7221 $(this).attr('tabindex', 0); 7222 }); 7223 // Sidebar 7224 SideBarElements.each(function() { 7225 $(this).removeAttr('tabindex'); 7226 }); 7227 7228 SideBarElements.each(function(index) { 7229 $(this).attr('tabindex', 0); 7230 }); 7231 7232 // Main Content 7233 allElements.each(function() { 7234 $(this).removeAttr('tabindex'); 7235 }); 7236 7237 allElements.each(function(index) { 7238 if (!$(this).attr('tabindex')) { 7239 $(this).attr('tabindex', 0); 7240 } 7241 }); 7242 7243 $(".performance-block-date-link").attr('tabindex', -1); 7244 $(".basket-widget a.aria-basket-link").attr('tabindex', -1); 7245 $("a.skip-link").attr('tabindex', -1); 7246 $(".copyright-text a").each(function(index) { 7247 $(this).attr('tabindex', 0); 7248 }); 7249 7250 $(".highlightinfo-wrap .prevevent-btn").attr("aria-label", "Previous Event"); 7251 $(".highlightinfo-wrap .nextevent-btn").attr("aria-label", "Next Event"); 7252 $(".highlightinfo-wrap .button-wrap a.button").attr("role", "button").attr("aria-label", "Buy Tickets"); 7253 $(".featuredevent-box .bottominfo-wrap a.button.featured-togglelink").attr("role", "button").attr("aria-label", "Toggle Down to Open event information"); 7254 $('img[src$="sectigo_trust_seal_lg_140x54.png"]').attr({alt: "Sectigo Seal", 'aria-label': "Sectigo Seal"}); 7255 $(".info-box a").attr("role", "button").attr("aria-label", "Venue Link"); 7256 $("a.forgot-password-link").attr("role", "button").attr("aria-label", "Forgot Password"); 7257 7258 $("#EventInformationWrap").attr("tabindex", "0"); 7259 $("#venuesWidget .right a.button").attr("role", "button"); 7260 $("table.cal thead th").attr('scope', 'col'); 7261 $('.otherimages img').each(function () { 7262 var src = $(this).attr('src'); 7263 if (src) { 7264 var filename = src.substring(src.lastIndexOf('/') + 1); // Get the filename 7265 $(this).attr('alt', filename); // Set as alt 7266 } 7267 }); 7268 $('.mainimage img').each(function () { 7269 var src = $(this).attr('src'); 7270 if (src) { 7271 var filename = src.substring(src.lastIndexOf('/') + 1); // Get the filename 7272 $(this).attr('alt', filename); // Set as alt 7273 } 7274 }); 7275 $('.bundle-event-container').each(function() { 7276 var altText = $(this).find('.event-container-header').text().trim(); 7277 $(this).find('.bundle-event-image').attr('alt', altText); 7278 }); 7279 $('.related-event').each(function() { 7280 var altTextH3 = $(this).find('h3').text().trim(); 7281 $(this).find('img').attr('alt', altTextH3); 7282 }); 7283 7284 }, 3500); 7285 7286 7287 }catch(e){ 7288 console.log("Failed to update header for accessability:"); 7289 console.log(e); 7290 } 7291</script>
7291 7292<style> 7293*:focus {box-shadow: 0 0 0 3px #fff,0 0 4px 6px #ccc!important;} 7294 7295/* Hide visually but keep accessible to screen readers */ 7296 .sr-only { 7297 position: absolute !important; 7298 width: 1px !important; 7299 height: 1px !important; 7300 padding: 0 !important; 7301 margin: -1px !important; 7302 overflow: hidden !important; 7303 clip: rect(0, 0, 0, 0) !important; 7304 border: 0 !important; 7305 } 7306 .skip-link { 7307 position: absolute; 7308 left: -10000px; 7309 top: auto; 7310 width: 1px; 7311 height: 1px; 7312 overflow: hidden; 7313 } 7314/* Style for focused interactive elements visible to accessibility readers */ 7315 :focus-visible { 7316 outline: 2px solid #ccc; /* Show the outline for accessibility readers */ 7317 outline-offset: 2px; /* Optional: Adjust the spacing between the element and the outline */ 7318 } 7319</style> 7320
7321<script> 7322setTimeout(function() { 7323 $( document ).ready(function() { 7324 $('#mobile-menu li a').each(function(){ 7325 if($(this).is(':contains("close")')) { 7326 $(this).attr("onclick","actWidget('');"); 7327 } 7328 if($(this).is(':contains("search")')) { 7329 $(this).attr("onclick","actSearch();return 0;"); 7330 } 7331 7332 if($(this).is(':contains("shopping cart")')) { 7333 $(this).attr("HREF","https://www.cincyticket.com/basket.asp?fw=1"); 7334 } 7335 }); 7336 $('#mobile-menu').removeAttr("onclick"); 7337 }); 7338}, 300); 7339</script>
7339 7340
7341<script> 7342// Add control wrap's height as the min-height for main-constrain-width so the sidebar won't overlap to the footer 7343setTimeout(function() { 7344 $( document ).ready(function() { 7345 varControlWrapHeight = $(".control-wrap").height() + "px"; 7346 $(".main-constrain-width").css( "min-height", varControlWrapHeight ); 7347 }); 7348}, 300); 7349</script>
7349 7350 7351 7352 7353</body> 7354</html>
7355<script type="text/javascript"> 7356 7357try{ 7358 swEnhancedEcommerce.fetchBasketProducts('basket', 0, true); 7359 7360}catch(e){ 7361 console.log(e); 7362} 7363extractIcons(); 7364$("#checkout-button").click(function(){ 7365 //add ecommerce 7366 try{ 7367 swEnhancedEcommerce.sendCheckoutStep(1, "checkout"); 7368 }catch(e){ 7369 console.log(e); 7370 } 7371 if(false){ 7372 //OPS-CS functionality 7373 //validate heard about 7374 var heardAbout = $("#heard-about").val(); 7375 var soldFor = $("#soldfor").val(); 7376 if(heardAbout == "" && true){ 7377 alert('Please select a value for "How did you hear about us"'); 7378 return 0; 7379 }else{ 7380 $.get("/include/ajax.asp", 7381 { 7382 action: "setBasketSoldforHeardabout", 7383 HeardAboutValue: heardAbout, 7384 soldForValue: soldFor 7385 }) 7386 .done(function (data) { 7387 goToCheckoutTicketInfo(); 7388 }) 7389 .fail(function (jqxhr, textStatus, error) { 7390 var err = textStatus + ", " + error; 7391 goToCheckoutTicketInfo(); 7392 }) 7393 7394 } 7395 }else{ 7396 goToCheckoutTicketInfo(); 7397 } 7398 7399}); 7400 7401// Consolidated checkout navigation ensuring TILA acceptance when required 7402function goToCheckoutTicketInfo(){ 7403 // Use the payment plan state if available (tilaAccepted lives inside basketPaymentPlan closure) 7404 if (window.basketPaymentPlan) { 7405 if (typeof basketPaymentPlan.isPayInFullSelected === 'function' && basketPaymentPlan.isPayInFullSelected()) { 7406 basketPaymentPlan.clearPaymentPlanSessions(); 7407 } 7408 if (basketPaymentPlan.tilaAccepted) { 7409 window.location.href="Checkout_TicketInfo.asp"; 7410 return; 7411 } 7412 // If a plan is selected that requires TILA and not yet accepted, invoke modal then proceed 7413 if (typeof basketPaymentPlan.shouldRequireTila === 'function' && basketPaymentPlan.shouldRequireTila()) { 7414 basketPaymentPlan.showTilaModal(function(){ 7415 // If TILA is accepted, proceed to checkout 7416 //if (basketPaymentPlan.tilaAccepted) { 7417 window.location.href="Checkout_TicketInfo.asp"; 7418 //} 7419 }); 7420 return; 7421 } 7422 } 7423 // Fallback (no payment plan) 7424 window.location.href="Checkout_TicketInfo.asp"; 7425} 7426 7427 7428 toggleFees(); 7429 7430var cartTotal, basket = {}; 7431 7432function getClientBasket(callback) { 7433 $.ajax({
7434 type: "GET", 7435 dataType: "json", 7436 url: "/include/modules/checkout/client_basket.asp", 7437 data: {}, 7438 timeout: 30000 7439 }).done(function(data) { 7440 loadBasket(data); 7441 if(callback && typeof callback === 'function') { 7442 callback(); 7443 } 7444 }).fail(function(xhr, errorText, error) { 7445 return 0; 7446 }); 7447} 7448 7449function loadBasket(data) { 7450 if (data.basket) { 7451 console.log(basket) 7452 basket = data.basket; 7453 if(basket.discounts.HasBasketDiscounts == 1){ 7454 if(basket.appliedPromoCode.PromoCode){ 7455 $("#PromoCodeInput").val(basket.appliedPromoCode.PromoCode); 7456 applyPromoCode(); 7457 }else{ 7458 calculateTotals() 7459 } 7460 } 7461 } 7462} 7463getClientBasket(); 7464 7465function updatePaymentPlansTotals(){ 7466 if(typeof basketPaymentPlan !== 'undefined'){ 7467 basketPaymentPlan.refreshAmounts(0); 7468 } 7469} 7470 7471function applyPromoCode(){ 7472 clearErrors($("#PromoCodeWrap")) 7473 $.ajax({
7474 url: '/include/modules/checkout/applyPromoCode.asp', 7475 method: 'GET', 7476 headers: { 7477 'Content-Type': "application/x-www-form-urlencoded;charset=utf-8" 7478 }, 7479 data: { 7480 "promocode" : $("#PromoCodeInput").val() 7481 }, 7482 success: function(resp) { 7483 resp = JSON.parse(resp); 7484 if (resp.success == 1){ 7485 try { 7486 addDataLayer("TicketingPromo", String($("#PromoCodeInput").val())); 7487 } catch (e) { 7488 console.log(e); 7489 } 7490 $(".applied-code-info").html(resp.promoCode); 7491 $("#ActivePromoInfo").show(); 7492 basket.discounts = resp; 7493 basket.discounts.HasBasketDiscounts = basket.discounts.HasBasketDiscounts ? 1 : 0; 7494 basket.discounts.discountAmount = basket.discounts.TotalBasketDiscountAmount; 7495 addDataLayer("TicketingDiscountAmount", basket.discounts.discountAmount); 7496 7497 if (basket.discounts.HasBasketDiscounts === 1) { 7498 updatePaymentPlansTotals(); 7499 } 7500 7501 if($("#checkoutPayment").hasClass("active")){ 7502 calculateTotals(true); 7503 }else{ 7504 calculateTotals(false); 7505 $("#paymentChangeType").show(); 7506 } 7507 7508 }else{ 7509 displayPromoCodeError($("#PromoCodeWrap"), resp.error) 7510 } 7511 } 7512 }) 7513} 7514$("#PromoCodeInput").on('keyup', function(e){ 7515 if(e.key === 'Enter' || e.keyCode === 13){ 7516 console.log(e); 7517 applyPromoCode(); 7518 } 7519}); 7520function clearErrors(myForm) { 7521 myForm.find(".promocode-error-msg").remove(); 7522 7523} 7524function displayPromoCodeError(blockObj, message) { 7525 //blockObj should be an instance of a DOM element 7526 if (!(blockObj[0] instanceof HTMLElement)) return; 7527 $("<div tabindex='0' class='promocode-error-msg' role='alert'><span class='error-message floating-error'>" + message + "</span></div>").insertAfter("#PromoControlsWrap"); 7528 $(".error-message").focus(); 7529 setTimeout(function() { 7530 $("#PromoApplyCodeButton").css("margin-bottom","2px"); 7531 $('#PromoCodeInput').addClass("has-error"); 7532 }, 10); 7533 7534} 7535function calculateTotals() { 7536 var ticketTotal = 0, membershipTotal = 0, donationTotal = 0; 7537 if (basket.items.tickets) { 7538 $.each(basket.items.tickets, function(index, ticket) { 7539 ticketTotal += ticket.PriceWithFees; 7540 }); 7541 } 7542 if (basket.items.donations) { 7543 $.each(basket.items.donations, function(index, donation) { 7544 donationTotal += donation.Price; 7545 }); 7546 } 7547 if (basket.items.memberships) { 7548 $.each(basket.items.memberships, function(index, membership) { 7549 membershipTotal += membership.Price; 7550 }); 7551 } 7552 7553 //basket item total 7554 cartTotal = ticketTotal + membershipTotal + donationTotal; 7555 if(basket.discounts.HasBasketDiscounts === 1){ 7556 basket.discounts.discountAmount = Math.round(basket.discounts.discountAmount * 1e2)/1e2; 7557 basket.discounts.TotalAdjustedExtFee1 = Math.round(basket.discounts.TotalAdjustedExtFee1 * 1e2)/1e2; 7558 basket.discounts.TotalAdjustedExtFee2 = Math.round(basket.discounts.TotalAdjustedExtFee2 * 1e2)/1e2; 7559 basket.discounts.TotalAdjustedExtFee3 = Math.round(basket.discounts.TotalAdjustedExtFee3 * 1e2)/1e2; 7560 7561 cartTotal = cartTotal - basket.discounts.discountAmount - basket.discounts.TotalAdjustedExtFee1 - basket.discounts.TotalAdjustedExtFee2 - basket.discounts.TotalAdjustedExtFee3; 7562 cartTotal += basket.orderFee; 7563 cartTotal = parseFloat(cartTotal).toFixed(2); 7564 } 7565 updateBasketTotals(cartTotal); 7566} 7567function updateBasketTotals(cartTotal) { 7568 if(basket.discounts.HasBasketDiscounts === 1){
7569 $("#promoCodeLabel").text("Promo Code Discount:"); 7570 $("#promoCodeLabel, #promoCodeDiscount").show(); 7571 $("#promoCodeDiscount").html(formatCurrency((basket.discounts.discountAmount + basket.discounts.TotalAdjustedExtFee1 + basket.discounts.TotalAdjustedExtFee2 + basket.discounts.TotalAdjustedExtFee3)*-1)); 7572 } 7573 $("#basketTotalCell").html(formatCurrency(cartTotal)); 7574} 7575function formatCurrency(num) { 7576 if (typeof num != 'undefined' && num != null) { 7577 num = num.toString().replace(basket.currencySymbol, '').replace(',', ''); 7578 if (isNaN(num)) 7579 num = "0"; 7580 sign = (num == (num = Math.abs(num))); 7581 num = Math.floor(num * 100 + 0.50000000001); 7582 cents = num % 100; 7583 num = Math.floor(num / 100).toString(); 7584 if (cents < 10) 7585 cents = "0" + cents; 7586 for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) 7587 num = num.substring(0, num.length - (4 * i + 3)) + ',' + 7588 num.substring(num.length - (4 * i + 3)); 7589 return (((sign) ? '' : '-') + basket.currencySymbol + num + '.' + cents); 7590 } else { 7591 return ''; 7592 } 7593} 7594 7595</script>
vendor: 2 bytes, line 7595
7595
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.