1 2var calendar = true; 3 4var sortMode = 2;// date/time 5var view = 1;// Visual 6var h3s = true; 7var ft_currentMenu = ""; 8var selectedOptions = new Array(); 9var sessionDates = new Array(); 10var attributeGroups, venues, items; 11var throttled = false, throttleIndex = 1, throttleCount = 10; 12var optionSelected = false; 13var pageTitle = document.title; 14var useLocalStorage = false; 15var searchDescription = true; 16var searchOr = null;// true / false / null (dynamically worked out) 17var searchAND = true;// Setting controls this 18var calloutToggle = true; 19var wishlist = true, ws = true, childEvents = false; 20 21 22// #mark ------ Initialisation ------ 23 24var browseInitComplete = false; 25var browseMode = "Browse"; 26var label = "Event"; 27var image = "browse"; 28 29var x = document.querySelectorAll("[ft-data-label]"); 30if (x && x.length > 0) label = x[0].getAttribute("ft-data-label"); 31 32if (window.addEventListener) { 33 window.addEventListener("load", ft_initBrowse, false); 34} else if (window.attachEvent) { 35 window.attachEvent("onload", ft_initBrowse); 36} 37if (document.readyState === "complete") setTimeout(function () { ft_initBrowse(); }, 100); 38 39function logBrowse(s) { 40 ferve.log(s, "border-left:2px solid purple;padding-left: 4px;"); 41} 42 43var script = document.createElement("script"); 44script.type = "text/javascript"; 45script.src = (typeof ferve != "undefined" ? ferve.url : "../../") + "js/echo.js"; 46document.getElementsByTagName("head")[0].appendChild(script); 47script.onreadystatechange = function () { 48 if (this.readyState == "complete" || this.readyState == "loaded") { 49 ft_initEcho(); 50 } 51}; 52script.onload = function () { 53 logBrowse("echo.js script.onload"); 54 ft_initEcho(); 55}; 56 57var scrollY = 0; 58function ft_scrollBrowse(event) { 59 scrollY = (document.all ? document.scrollTop : window.pageYOffset); 60 if (browseMode == "Browse") ft_browseOptionsSave(); 61 echo.render(); 62} 63 64function ft_initBrowse(e) { 65 logBrowse("ft_initBrowse()"); 66 67 if (!e.isTrusted) { 68 logBrowse("exiting !e.isTrusted", "info"); 69 return; 70 } 71 72 var js = document.getElementById("ft_browseJS"); 73 if (js) { 74 var src = js.getAttribute("src").replace("/js/browse.js", ""); 75 var urlSearchParams = new URLSearchParams(src); 76 var sa = urlSearchParams.get("sa"); 77 if (sa) searchAND = (sa == "1"); 78 } 79 80 var x = document.getElementById("ft_events"); 81 if (x && x.className.indexOf("ft_grid1") != -1) image = "thumbnail"; 82 83 if (window.addEventListener) { 84 window.addEventListener("scroll", ft_scrollBrowse, false); 85 } else if (window.attachEvent) { 86 window.attachEvent("onscroll", ft_scrollBrowse); 87 } 88 89 if (browseMode == "Venues" || browseMode == "Exchange") return; 90 91 if (document.URL.indexOf("/Wishlist") > -1) { 92 browseMode = "Wishlist"; 93 useLocalStorage = false; 94 if (ferve.visitor.loggedIn != "1") { 95 var x = document.getElementById("ft_accountMenu"); 96 if (x) x.style.display = "none"; 97 } 98 } 99 100 if (document.URL.indexOf("/Play") > -1) { 101 browseMode = "Play"; 102 useLocalStorage = false; 103 } 104 105 if (document.URL.toLowerCase().indexOf("/merchandise") > -1) browseMode = "Merchandise"; 106 if (document.URL.toLowerCase().indexOf("/passes") > -1) browseMode = "Passes"; 107 if (document.URL.toLowerCase().indexOf("/vouchers") > -1) browseMode = "Vouchers"; 108 if (document.URL.toLowerCase().indexOf("/memberships") > -1) browseMode = "Memberships"; 109 if (document.URL.toLowerCase().indexOf("/donate") > -1) browseMode = "Donations"; 110 if (document.URL.toLowerCase().indexOf("/passbookings") > -1) browseMode = "BrowsePass"; 111 112 if (browseMode != "Browse") { 113 init_data(); 114 return; 115 } 116 117 118 if (calendar) { 119 var x = document.getElementById("ft_menuD"); 120 if (x) { 121 x.style.width = "263px"; 122 x.style.height = "318px"; 123 } 124 } else { 125 var x = document.getElementById("ft_calendarContainer"); 126 if (x) x.style.display = "none"; 127 } 128 129 if (navigator.userAgent.match(/iPod; CPU iPhone OS 6/i) && window.screen.height == 480) { 130 throttled = true; 131 throttleCount = 20; 132 var x = document.getElementById("ft_background"); 133 x.style.backgroundImage = ""; 134 x.style.background = "#fff"; 135 } else if (navigator.userAgent.match(/iPhone/i) && window.screen.height == 480) { 136 throttled = true; 137 throttleCount = 50; 138 } else if (navigator.userAgent.match(/iPhone/i) && window.screen.height == 568) { 139 throttled = true; 140 throttleCount = 200; 141 } 142 143 if (useLocalStorage && browseMode != "Wishlist" && ferve.utility.queryStringValue("refresh") != "1") { 144 var localData = localStorage.getItem("FTBR_" + ferve_h + "_" + browseMode); 145 var localTimeStamp = localStorage.getItem("FTBRTS_" + ferve_h + "_" + browseMode); 146 if (localData && localData.length > 0 && localTimeStamp && localTimeStamp.length > 0) { 147 localTimeStamp = Date.parse(localTimeStamp); 148 if (new Date().getTime() - localTimeStamp > 60000) {// cache data for one minute 149 logBrowse("localStorage [removing _" + browseMode + "]", "info"); 150 localStorage.removeItem("FTBR_" + ferve_h + "_" + browseMode); 151 localStorage.removeItem("FTBRTS_" + ferve_h + "_" + browseMode); 152 } else { 153 ft_initBrowse_delegate(localData); 154 return; 155 } 156 } 157 } 158 159 init_data(); 160} 161 162 163function ft_initBrowse_delegate(s) { 164 logBrowse("ft_initBrowse_delegate()"); 165 var start = new Date().getTime(); 166 167 var data = unescape(s); 168 169 if (useLocalStorage) { 170 logBrowse("localStorage [adding _" + browseMode + "]", "info"); 171 localStorage.setItem("FTBR_" + ferve_h + "_" + browseMode, data); 172 localStorage.setItem("FTBRTS_" + ferve_h + "_" + browseMode, new Date()); 173 } 174 175 if (browseMode == "Wishlist" || browseMode == "Play") { 176 attributeGroups = null; 177 venues = null; 178 items = JSON.parse(data); 179 if (items && typeof (items.Success) !== "undefined" && items.Success == false) { 180 logBrowse("Reloading Items"); 181 if (ferve.visitor.hash.length == 0) ferve.visitor.updatePropertiesFromCookie(); 182 setTimeout(function () { init_data(); }, 250); 183 return; 184 } 185 186 } else { 187 var jsonData = JSON.parse(data); 188 wishlist = jsonData.Wishlist; 189 attributeGroups = jsonData.AttributeGroups; 190 venues = jsonData.Venues; 191 items = jsonData.Items; 192 childEvents = jsonData.ChildEvents; 193 } 194 195 if (!items || items.length == 0) { 196 var message = "<p> </p><p> </p><p>No " + (browseMode == "Browse" || browseMode == "Play" ? label.toLowerCase() + (label.substring(label.length - 1) != 's' ? "s" : "") : browseMode) + " are available.</p<p> </p><p> </p>"; 197 198 if (browseMode == "Wishlist") { 199 message = "<p> </p><p>The wishlist is a list of sessions you are interested in.</p><p>Click a heart icon next to a session to add it to your wishlist.</p>"; 200 if (ferve.visitor.loggedIn != "1") message += "<p>You are not currently logged in, <a href=\"javascript:ferve.utility.openLink('account',0)\">log in now</a>.</p>"; 201 } else if (browseMode == "BrowsePass") { 202 message = "<p>No events are available to book. </p>"; 203 } 204 205 var x = document.getElementById("ft_browseOptions"); 206 if (x) x.style.display = "none"; 207 x = document.getElementById("ft_events"); 208 if (x) x.innerHTML = message; 209 return; 210 } 211 if (browseMode != "BrowsePass") { 212 var parent = document.getElementById("ft_menuAttributes") 213 if (browseMode != "Browse" || (browseMode == "Browse" && !parent)) { 214 browseInitComplete = true; 215 for (var i = 0; i < items.length; i++) { 216 items[i].DateTime = parseDateTime(items[i].DateTime); 217 } 218 sort(sortMode, false); 219 logBrowse("ft_initBrowse(1) calling ft_renderItems"); 220 ft_renderItems(true, searchOr); 221 222 try { 223 ft_browseInitted(); 224 } 225 catch (e) { } 226 227 return; 228 } 229 } 230 231 if (ferve.utility.queryStringValue("os").length > 0) searchAND = (ferve.utility.queryStringValue("os") == "0"); 232 233 var div, html, calloutHTML = ""; 234 235 var cssAttributeHash = -1; 236 var cssAttributeLoc = -1; 237 238 // Attributes 239 parent = document.getElementById("ft_menuAttributes"); 240 if (attributeGroups && parent) { 241 for (var i = 0; i < attributeGroups.length; i++) { 242 if (attributeGroups[i].Name == "CSS") { 243 cssAttributeHash = attributeGroups[i].Hash; 244 cssAttributeLoc = i; 245 continue;// no menu 246 } 247 248 html = "<a href=\"Javascript:ft_toggleMenu('" + attributeGroups[i].Hash + "')\">" + attributeGroups[i].Name + "</a><div id=\"ft_menu" + attributeGroups[i].Hash + "\" class=\"ft_menu ft_itemHidden\" style=\"display:none;\">"; 249 for (var j = 0; j < attributeGroups[i].Attributes.length; j++) { 250 html += "<div><input type=\"checkbox\" onclick=\"Javascript:ft_toggleOption('" + attributeGroups[i].Hash + "','" + attributeGroups[i].Attributes[j].Hash + "')\" id=\"ft_c_" + attributeGroups[i].Hash + "o" + attributeGroups[i].Attributes[j].Hash + "\" /> <a href=\"Javascript:ft_toggleCheckbox('" + attributeGroups[i].Hash + "','" + attributeGroups[i].Attributes[j].Hash + "')\">" + attributeGroups[i].Attributes[j].Value + "</a></div>"; 251 252 if (attributeGroups[i].Attributes[j].Callout) { 253 // To allow more than one callout selected set true to false on ft_toggleCheckbox call 254 calloutHTML += "<div class=\"ft_callout\" id=\"co_" + attributeGroups[i].Hash + "o" + attributeGroups[i].Attributes[j].Hash + "\" name=\"ft_callout\"><a href=\"Javascript:ft_toggleCheckbox('" + attributeGroups[i].Hash + "','" + attributeGroups[i].Attributes[j].Hash + "',true);\">" + attributeGroups[i].Attributes[j].Value + "</a></div>"; 255 } 256 } 257 if (!attributeGroups[i].Browse) continue; 258 259 html += "</div>"; 260 261 div = document.createElement("div"); 262 div.className = "ft_menuBox"; 263 div.innerHTML = html 264 parent.parentNode.insertBefore(div, parent.nextSibling); 265 } 266 var x = document.getElementById("ft_callouts"); 267 if (calloutHTML.length > 0) { 268 if (x) { 269 x.innerHTML = calloutHTML; 270 x.style.display = ""; 271 } 272 } else { 273 if (x) x.style.display = "none"; 274 } 275 276 try { 277 ft_browseInitted(); 278 } 279 catch (e) { } 280 } 281 282 283 // Venues 284 parent = document.getElementById("ft_menuV"); 285 if (venues && parent) { 286 for (var i = 0; i < venues.length; i++) { 287 if (venues[i].ParentHash.length > 0) continue; 288 html = "<div><input type=\"checkbox\" onclick=\"Javascript:ft_toggleOption('V','" + venues[i].Hash + "')\" id=\"ft_c_Vo" + venues[i].Hash + "\" /> <a href=\"Javascript:ft_toggleCheckbox('V','" + venues[i].Hash + "')\">" + venues[i].Name + "</a></div>"; 289 290 div = document.createElement("div"); 291 div.innerHTML = html 292 parent.appendChild(div); 293 } 294 } 295 296 // No venues (online events) 297 if (typeof venues != "undefined" && venues.length == 0) { 298 if (parent) parent.parentNode.style.display = "none"; 299 } 300 301 // Dates 302 parent = document.getElementById("ft_menuD"); 303 var previousDate = new Date(1974, 16, 5, 0, 0, 0, 0); 304 for (var i = 0; i < items.length; i++) { 305 var sd = items[i].DateTime; 306 items[i].DateTime = parseDateTime(items[i].DateTime); 307 if (noSessionDate(items[i].DateTime)) continue; 308 if (previousDate.toDateString() != items[i].DateTime.toDateString()) { 309 sessionDates[sessionDates.length] = returnDateTime(items[i].DateTime, true, false); 310 if (!calendar) { 311 var option = items[i].DateTime.getFullYear() + "-" + (items[i].DateTime.getMonth() + 1) + "-" + items[i].DateTime.getDate(); 312 html = "<div><input type=\"checkbox\" onclick=\"Javascript:ft_toggleOption('D','" + option + "')\" id=\"ft_c_Do" + option + "\" /> <a href=\"Javascript:ft_toggleCheckbox('D','" + option + "')\">" + returnDateTime(items[i].DateTime, true, false) + "</a></div>"; 313 div = document.createElement("div"); 314 div.innerHTML = html; 315 parent.appendChild(div); 316 } 317 previousDate = items[i].DateTime; 318 } 319 } 320 // No dates (online events) 321 if (typeof sessionDates != "undefined" && sessionDates.length == 0) { 322 if (parent) parent.parentNode.style.display = "none"; 323 } else { 324 sessionDates.sort(orderBySessionDate);
325 renderCalendar(); 326 } 327 328 329 330 331 // Count, venue, attributes && accessibility 332 items.sort(orderByName); 333 var previousName = (items[0] != undefined ? items[0].Name : ""), previousLoc = 0, count = 0; 334 for (var i = 0; i < items.length; i++) { 335 if (previousName != items[i].Name) { 336 for (var j = previousLoc; j < i; j++) { 337 items[j].Count = count; 338 } 339 count = 1; 340 previousLoc = i; 341 previousName = items[i].Name 342 } else { 343 count++; 344 } 345 items[i].DescriptionBrief = items[i].DescriptionBrief.replace(/</g, "<") 346 items[i].DescriptionBrief = items[i].DescriptionBrief.replace(/>/g, ">") 347 items[i].VenueName = items[i].VenueName; 348 items[i].AttributeHashes = items[i].AttributeHashes.split(","); 349 items[i].CSS = ""; 350 if (cssAttributeHash != -1 && items[i].AttributeHashes.length > 0) { 351 for (var j = 0; j < items[i].AttributeHashes.length; j++) { 352 var attribute = items[i].AttributeHashes[j].split("o"); 353 if (attribute[0] == cssAttributeHash) { 354 for (var k = 0; k < attributeGroups[cssAttributeLoc].Attributes.length; k++) { 355 if (attributeGroups[cssAttributeLoc].Attributes[k].AttributeHashes == attribute[1]) { 356 items[i].CSS += attributeGroups[cssAttributeLoc].Attributes[k].Value + " "; 357 break; 358 } 359 } 360 } 361 } 362 if (items[i].CSS.length > 0) items[i].CSS = items[i].CSS.substring(0, items[i].CSS.length - 1); 363 } 364 365 items[i].AccessibilityIcons = ""; 366 if (items[i].AccessibilityString && items[i].AccessibilityString.length > 0) { 367 var accessibilityIcons = items[i].AccessibilityString.split(","); 368 for (var j = 0; j < accessibilityIcons.length; j++) { 369 var accessibilityIcon = accessibilityIcons[j].split(";"); 370 items[i].AccessibilityIcons += 371 "<div class='ft_tooltipWrapper'>" + 372 "<div class='" + accessibilityIcon[1] + " ft_tooltip'></div>" + 373 "<div class='ft_tooltipContent ft_centered'>" + accessibilityIcon[0] + "</div>" + 374 "</div>"; 375 } 376 } 377 } 378 for (var j = previousLoc; j < i; j++) { 379 items[j].Count = count; 380 } 381 382 var url = document.URL.split("/"); 383 384 if (ferve.utility.queryStringValue("s") == "0") { 385 x = document.getElementById("ft_browseOptions"); 386 if (x) x.style.display = "none"; 387 } 388 var keyword = ferve.utility.queryStringValue("k"); 389 if (keyword.length > 0) { 390 var x = document.getElementById("ft_keyword"); 391 if (x) x.value = keyword; 392 ft_addSelectedOption("K", keyword); 393 } 394 var venue = ferve.utility.queryStringValue("v", null, true); 395 if (venue != "") { 396 venue = unescape(venue); 397 venue = returnVenueFromName(venue); 398 } else if (url.length == 6 && url[4] == "Venue") { 399 venue = unescape(url[5]); 400 if (venue.indexOf("?") > -1) venue = venue.slice(0, venue.lastIndexOf("?")); 401 venue = returnVenueFromName(venue); 402 } 403 if (venue) ft_toggleCheckbox("V", venue.Hash); 404 405 var group = ferve.utility.queryStringValue("g", null, true); 406 var option = ferve.utility.queryStringValue("o", null, true); 407 if (group == "") { 408 if (url.length == 6) { 409 group = url[4]; 410 option = url[5]; 411 if (option.indexOf("?") > -1) option = option.slice(0, option.lastIndexOf("?")); 412 childEvents = true; 413 } 414 } 415 group = decodeURIComponent(group); 416 option = decodeURIComponent(option); 417 var groupHash = ""; 418 var optionHash = ""; 419 if (group.length != 0 && option.length != 0) { 420 for (var i = 0; i < attributeGroups.length; i++) { 421 if (attributeGroups[i].Name == group) { 422 groupHash = attributeGroups[i].Hash; 423 for (var j = 0; j < attributeGroups[i].Attributes.length; j++) { 424 if (attributeGroups[i].Attributes[j].Value == option || (attributeGroups[i].Attributes[j].Value.replace(/[<>*%&:?+]/g, "")).trim() == option) { 425 optionHash = attributeGroups[i].Attributes[j].Hash; 426 break; 427 } 428 } 429 } 430 if (groupHash.length > 0 && option.length > 0) { 431 selectedOptions.length = 0; 432 ft_toggleCheckbox(groupHash, optionHash); 433 break; 434 } 435 } 436 } else { 437 // ft_browseOptionsRead(); - moved to after UI is ready 438 } 439 440 var date = ferve.utility.queryStringValue("d"); 441 if (date.length > 0) { 442 calendarDateClicked(date); 443 } 444 445 var sm = ferve.utility.queryStringValue("sm"); 446 if (!isNaN(parseFloat(sm)) && isFinite(sm) && sm > 0 && sm < 4) sortMode = sm; 447 448 for (var i = 1; i < 4; i++) { 449 x = document.getElementById("ft_sort" + i); 450 if (x) x.checked = (i == sortMode); 451 } 452 453 sort(sortMode, false); 454 455 var vm = ferve.utility.queryStringValue("vm");
456 if (vm && vm == "ft_grid2" || vm == "ft_list") browseView(vm); 457 458 var h3 = ferve.utility.queryStringValue("h"); 459 if (h3 && h3 == "0") h3s = false; 460 461 browseInitComplete = true; 462 463 logBrowse("ft_initBrowse(2) calling ft_renderItems"); 464 ft_renderItems(true, searchOr); 465 466 467 logBrowse("init complete in " + (new Date().getTime() - start) + "ms", "info"); 468} 469 470 471function init_data() { 472 logBrowse("init_data()"); 473 var browseImage = (ft_fta() ? "?" + ferve.returnUniqueID() + "=" + ferve.returnUniqueID() : ""); 474 if (browseMode == "Wishlist") { 475 var src = document.getElementById("ft_browse").getAttribute("src"); 476 src = src.substring(src.indexOf("?") + 1, src.length); 477 var share = ferve.utility.queryStringValue("h", src); ws = (share.length == 0); 478 ferve.xmlHttpRequest(ferve.url + "api/v1/Items/Schedule?hash=" + ferve.visitor.hash + (share.length > 0 ? "&share=" + share : ""), "GET", "", "", "", "ft_initBrowse_delegate("); 479 } else if (browseMode == "Browse") { 480 var url = document.URL.split("/"); 481 var group = ""; 482 if (url.length == 6) group = url[4]; 483 ferve.xmlHttpRequest(ferve.url + "api/v1/Items/Browse" + browseImage + (group.length > 0 ? (browseImage.length == 0 ? "?" : "&") + "group=" + group : ""), "GET", "", "", "", "ft_initBrowse_delegate(", true); 484 } else if (browseMode == "BrowsePass") { 485 if (passBooking.getPassNumber() != "") { 486 ferve.xmlHttpRequest(ferve.url + "api/v1/Items/BrowsePass?passId=" + passBooking.getPassNumber(), "GET", "", "", "", "ft_initBrowse_delegate("); 487 } 488 } else if (browseMode == "Play") { 489 ferve.xmlHttpRequest(ferve.url + "api/v1/Items/Play?hash=" + ferve.visitor.hash, "GET", "", "", "", "ft_initBrowse_delegate("); 490 } else { 491 ferve.xmlHttpRequest(ferve.url + "api/v1/Items/" + browseMode + browseImage, "GET", "", "", "", "ft_initBrowse_delegate("); 492 } 493} 494 495 496function ft_initEcho() { 497 logBrowse("ft_initEcho()"); 498 echo.init({ 499 offset: '0', 500 throttle: '250' 501 }); 502} 503 504 505// #mark ------ Search UI ------ 506 507 508function ft_resetBrowse(callout) { 509 for (var i = 0; i < selectedOptions.length; i++) { 510 var group = selectedOptions[i].substring(0, selectedOptions[i].indexOf("o")); 511 var option = selectedOptions[i].substring(selectedOptions[i].indexOf("o") + 1); 512 var x = document.getElementById("ft_so_" + group + "o" + option); 513 if (x) { 514 x.className = x.className.replace("ft_itemVisible", "ft_itemHidden"); 515 if (callout) ferve.toggleDisplay("ft_so_" + group + "o" + option, "none"); 516 } 517 ft_resetBrowseDiv(group, option); 518 x = document.getElementById("ft_c_" + group + "o" + option); 519 if (x) x.checked = false; 520 } 521 var x = document.getElementById("ft_keyword"); 522 if (x) x.value = ""; 523 x = document.getElementById("ft_resetOptions"); 524 if (x) { 525 x.className = x.className.replace("ft_itemVisible", "ft_itemHidden"); 526 setTimeout(function () { ferve.toggleDisplay("ft_resetOptions", "none"); }, 550); 527 } 528 renderCalendar(); 529 x = document.getElementById("tMorning"); 530 if (x) x.className = x.className.replace("tabSelected", ""); 531 x = document.getElementById("tAfternoon"); 532 if (x) x.className = x.className.replace("tabSelected", ""); 533 x = document.getElementById("tEvening"); 534 if (x) x.className = x.className.replace("tabSelected", ""); 535 if (callout) { 536 selectedOptions.length = 0; 537 } else { 538 setTimeout(function () { selectedOptions.length = 0; ft_renderItems(true, searchOr); ft_updateCallouts(); }, 550); 539 } 540} 541function ft_resetBrowseDiv(ot, ov) { 542 setTimeout(function () { var x = document.getElementById("ft_so_" + ot + "o" + ov); if (x) x.parentNode.removeChild(x); }, 550); 543} 544 545 546function ft_toggleMenu(option, click) { 547 logBrowse("ft_toggleMenu(" + option + ", " + click + ")"); 548 var x; 549 if (ft_currentMenu != "") { 550 x = document.getElementById("ft_menu" + ft_currentMenu); 551 if (x) { 552 if (ft_currentMenu == "D") { 553 x.className = x.className.replace("ft_itemVisible", "ft_itemHidden"); 554 } else { 555 x.className = x.className.replace("ft_itemVisible95", "ft_itemHidden"); 556 } 557 } 558 var currentOption = ft_currentMenu; 559 setTimeout(function () { ferve.toggleDisplay("ft_menu" + currentOption, "none"); }, 550); 560 if (ft_currentMenu == option) { 561 ft_currentMenu = ""; 562 return; 563 } else { 564 ft_currentMenu = ""; 565 } 566 } 567 x = document.getElementById("ft_menu" + option); 568 if (x) { 569 ferve.toggleDisplay("ft_menu" + option, ""); 570 var rect = x.getBoundingClientRect(); 571 if ((rect.left + 250) > window.innerWidth) { 572 x.style.left = (window.innerWidth - 255) + "px"; 573 } 574 setTimeout(function () { x.className = x.className.replace("ft_itemHidden", (option == "D" ? "ft_itemVisible" : "ft_itemVisible95")); }, 25); 575 ft_currentMenu = option; 576 if (document.addEventListener) { 577 document.addEventListener("click", ft_clickedBrowse, false); 578 if ("ontouchend" in window) document.body.addEventListener("touchend", ft_clickedBrowse, false); 579 580 581 } else { 582 document.attachEvent("onclick", ft_clickedBrowse); 583 } 584 } 585} 586 587function ft_clickedBrowse(e) { 588 logBrowse("ft_clickedBrowse()"); 589 if (!e) e = window.event; 590 var t = e.target || e.srcElement; 591 var x = document.getElementById("ft_menu" + ft_currentMenu); 592 if (!x) return; 593 while (t.parentNode) { 594 if (t == x) { 595 logBrowse("exiting ft_clickedBrowse"); 596 return; 597 } else if (t.className == "ft_menuBox") { 598 if (document.addEventListener) { 599 document.removeEventListener("click", ft_clickedBrowse, false); 600 if ("ontouchend" in window) document.body.removeEventListener("touchend", ft_clickedBrowse, false); 601 } else { 602 document.detachEvent("onclick", ft_clickedBrowse); 603 } 604 return; 605 } 606 t = t.parentNode; 607 } 608 if (document.addEventListener) { 609 document.removeEventListener("click", ft_clickedBrowse, false); 610 if ("ontouchend" in window) document.body.removeEventListener("touchend", ft_clickedBrowse, false); 611 } else { 612 document.detachEvent("onclick", ft_clickedBrowse); 613 } 614 615 ft_toggleMenu(ft_currentMenu, true); 616 617 618 return false; 619} 620 621 622function ft_updateCallouts() { 623 logBrowse("ft_updateCallouts()"); 624 var callouts = document.getElementsByName("ft_callout"); 625 for (var i = 0; i < callouts.length; i++) { 626 var option = callouts[i].id.replace("co_", ""); 627 var selected = false; 628 for (var j = 0; j < selectedOptions.length; j++) { 629 if (option == selectedOptions[j]) { 630 selected = true; 631 break; 632 } 633 } 634 if (selected) { 635 callouts[i].className = "ft_callout ft_calloutSelected"; 636 } else { 637 callouts[i].className = "ft_callout"; 638 } 639 } 640} 641 642function ft_toggleCheckbox(group, option, callout) { 643 logBrowse("ft_toggleCheckbox(" + group + ", " + option + ")"); 644 if (callout) { 645 if (calloutToggle) { 646 // Reset if not the currently selected callout 647 if (selectedOptions.indexOf(group + "o" + option) == -1) ft_resetBrowse(true); 648 } else { 649 ft_resetBrowse(true); 650 } 651 } 652 653 var x = document.getElementById("ft_c_" + group + "o" + option); 654 if (x) x.checked = !x.checked; 655 ft_toggleOption(group, option); 656 ft_updateCallouts(); 657} 658 659function ft_toggleOption(group, option) { 660 logBrowse("ft_toggleOption(" + group + ", " + option + ")"); 661 var x = document.getElementById("ft_c_" + group + "o" + option); 662 if (x) { 663 if (x.checked) { 664 ft_addSelectedOption(group, option); 665 } else { 666 ft_removeSelectedOption(group, option); 667 } 668 return; 669 } 670 671 logBrowse("ft_toggleOption() no x"); 672 if (selectedOptions.indexOf(group + "o" + option) > -1) { 673 ft_removeSelectedOption(group, option); 674 return; 675 } 676 ft_addSelectedOption(group, option); 677 return; 678} 679 680function ft_addSelectedOption(group, option) { 681 logBrowse("ft_addSelectedOption(" + group + ", " + option + ")"); 682 var x = document.getElementById("ft_selectedOptions"); 683 if (x) { 684 var name = ""; 685 var exit = false; 686 687 if (group == "D") { 688 name = returnDateTime(option, true, false); 689 690 } else if (group == "T") { 691 name = option; 692 693 } else if (group == "V") { 694 for (var i = 0; i < venues.length; i++) { 695 if (venues[i].Hash == option || venues[i].ParentHash == option) { 696 name = venues[i].Name; 697 break; 698 } 699 } 700 } else if (group == "K") { 701 name = option; 702 } else { 703 for (var i = 0; i < attributeGroups.length; i++) { 704 if (attributeGroups[i].Hash == group) { 705 for (var j = 0; j < attributeGroups[i].Attributes.length; j++) { 706 if (attributeGroups[i].Attributes[j].Hash == option) { 707 name = attributeGroups[i].Attributes[j].Value; 708 exit = true; 709 break; 710 } 711 } 712 } 713 if (exit) break; 714 } 715 } 716 var div = document.createElement("div"); 717 div.id = "ft_so_" + group + "o" + (group != "K" ? option : ""); 718 div.className = "ft_selectedOption " + (browseInitComplete ? "ft_itemHidden" : "ft_itemVisible"); 719 div.innerHTML = "<a href=\"Javascript:ft_removeSelectedOption('" + group + "','" + (group != "K" ? option : "") + "')\"><span>X</span>
719 " + name + "</a>"; 720 x.appendChild(div); 721 div.style.width = div.offsetWidth + "px"; 722 selectedOptions[selectedOptions.length] = group + "o" + (group != "K" ? option : ""); 723 if (browseInitComplete) setTimeout(function () { div.className = div.className.replace("ft_itemHidden", "ft_itemVisible"); }, 25); 724 x = document.getElementById("ft_resetOptions"); 725 if (x) { 726 ferve.toggleDisplay("ft_resetOptions", ""); 727 setTimeout(function () { x.className = x.className.replace("ft_itemHidden", "ft_itemVisible"); }, 25); 728 } 729 730 // Save options when a filter is added 731 if (browseMode == "Browse") { 732 ft_browseOptionsSave(); 733 } 734 } 735 if (group != "K") { 736 logBrowse("ft_addSelectedOption calling ft_renderItems"); 737 ft_renderItems(true, searchOr); 738 } 739} 740 741function ft_removeSelectedOption(group, option) { 742 var x = document.getElementById("ft_c_" + group + "o" + (group != "K" ? option : "")); 743 if (x) x.checked = false; 744 var index = selectedOptions.indexOf(group + "o" + (group != "K" ? option : "")) 745 if (index > -1) selectedOptions = removeElement(selectedOptions, index); 746 747 x = document.getElementById("ft_so_" + group + "o" + (group != "K" ? option : "")); 748 if (x) { 749 x.className = x.className.replace("ft_itemVisible", "ft_itemHidden"); 750 x.className += " ft_selectedOptionWidth"; 751 x.style.width = "0"; 752 setTimeout(function () { 753 var x = document.getElementById("ft_so_" + group + "o" + (group != "K" ? option : "")); 754 if (x) x.parentNode.removeChild(x); 755 if (selectedOptions.length == 0) { 756 x = document.getElementById("ft_resetOptions"); 757 if (x) { 758 x.className = x.className.replace("ft_itemVisible", "ft_itemHidden"); 759 setTimeout(function () { ferve.toggleDisplay("ft_resetOptions", "none"); }, 550); 760 } 761 } 762 }, 550); 763 } 764 765 if (group == "D") { 766 var selDate = parseDate(option); 767 x = document.getElementById("d" + selDate.getFullYear() + "-" + (selDate.getMonth() + 1) + "-" + selDate.getDate()); 768 if (x) x.className = x.className.replace(" calSelected", ""); 769 } else if (group == "T") { 770 x = document.getElementById("t" + option); 771 if (x) x.className = x.className = ""; 772 } else if (group == "K") { 773 x = document.getElementById("ft_keyword"); 774 if (x) x.value = ""; 775 } 776 777 ft_updateCallouts(); 778 779 // Save options when a filter is removed 780 if (browseMode == "Browse") { 781 ft_browseOptionsSave(); 782 } 783 784 logBrowse("ft_removeSelectedOption calling ft_renderItems"); 785 ft_renderItems(true, searchOr); 786 787} 788 789 790// #mark ------ Rendering ------ 791 792// Helper function to group events by NameSort and select the best event from each group 793function groupEventsByNameSortAndSelectBest(items) { 794 var grouped = {}; 795 items.forEach(function(item) { 796 if (!grouped[item.NameSort]) grouped[item.NameSort] = []; 797 grouped[item.NameSort].push(item); 798 }); 799 800 return Object.keys(grouped).map(function(nameSort) { 801 var group = grouped[nameSort].sort(function(a, b) { 802 return new Date(b.DateTime || 0) - new Date(a.DateTime || 0); 803 }); 804 return group.find(function(item) { return item.Status != 6; }) || group[0]; 805 }); 806} 807 808var membershipAvailable; 809function ft_renderItems(clearSessionList, orSearch, parent = null) { 810 811 if (!browseInitComplete) return; 812 813 logBrowse("\n\nft_renderItems(" + clearSessionList + ", " + orSearch + ")"); 814 if (clearSessionList) throttleIndex = 1; 815 816 if (!parent) parent = document.getElementById("ft_events"); 817 if (clearSessionList) parent.innerHTML = ""; 818 var previousItem = ""; 819 820 var keyword = ""; 821 var x = document.getElementById("ft_keyword"); 822 if (x) keyword = x.value; 823 x = document.getElementById("ft_so_Ko"); 824 if (keyword.length > 0) { 825 if (x) { 826 x.innerHTML = "<a href=\"Javascript:ft_removeSelectedOption('K','')\"><span>X</span> " + keyword + "</a>"; 827 var ruler = document.getElementById("ruler"); 828 ruler.innerHTML = keyword; 829 var width = ruler.offsetWidth; 830 x.style.width = (width + 25) + "px"; 831 } else if (keyword.length > 0) { 832 ft_addSelectedOption("K", keyword); 833 } 834 } else { 835 if (x && x.className.indexOf("ft_itemVisible") > -1) ft_removeSelectedOption("K", ""); 836 } 837 838 var html = ""; 839 840 document.title = pageTitle; 841 842 // ft_browseOptionsSave(); - REMOVED: This was called too early before any filters were selected 843 844 if (selectedOptions.length == 1 && (!throttled || (throttled && throttleIndex == 1))) { 845 var attributeHash = selectedOptions[0].substring(selectedOptions[0].indexOf("o") + 1); 846 if (selectedOptions[0].substring(0, 1) == "V") { 847 var venueName = returnVenueName(attributeHash); 848 parent.innerHTML = "<h2>" + venueName + "</h2>"; 849 document.title = venueName + " | " + pageTitle; 850 } else { 851 var attribute = returnAttribute(attributeHash); 852 var attributeGroup = returnAttributeGroup(attributeHash); 853 if (attributeGroup) { 854 var title = (attributeGroup.Name != attribute.Value ? attributeGroup.Name + " >> " + attribute.Value : attributeGroup.Name); 855 parent.innerHTML = "<div class=\"ft_attribute\"><h2>" + title + "</h2>"; 856 document.title = title + " | " + pageTitle; 857 } 858 if (attribute && attribute.Description && attribute.Description.length > 0) parent.innerHTML += attribute.Description; 859 parent.innerHTML += "</div><div class=\"ft_clear\" style=\"margin-bottom:15px;\"></div>"; 860 } 861 } 862 863 var sessionCount = 0; 864 var throttleStart = ((throttleIndex - 1) * throttleCount) + 1; 865 var throttleEnd = (throttleIndex * throttleCount); 866 867 var foundKeyword, foundDate, foundTime, foundVenue, foundAttribute; 868 var dateCount = 0, timeCount = 0, venueCount = 0, attributeCount = 0; 869 870 // and / or : if eg. date and category use and, if category and category use or 871 if (orSearch == null) { 872 var multiple = false, optionsFound = (keyword.length > 0 ? "K" : ""); 873 for (var i = 0; i < selectedOptions.length; i++) { 874 var optionType = selectedOptions[i].substring(0, selectedOptions[i].indexOf("o")); 875 if (optionType == "D") { 876 dateCount++; 877 } else if (optionType == "T") { 878 timeCount++; 879 } else if (optionType == "V") { 880 venueCount++; 881 } else { 882 attributeCount++; 883 } 884 } 885
886 var optionsFound = (dateCount + timeCount + venueCount + attributeCount); 887 logBrowse("optionsFound: " + optionsFound); 888 889 if (optionsFound == 1) { 890 orSearch = true; 891 } else if (optionsFound > 1 && !searchAND) { 892 orSearch = true; 893 } else if (searchAND) { 894 orSearch = false; 895 } 896 } 897 logBrowse(" orSearch: " + orSearch + "\n dateCount: " + dateCount + "\n timeCount: " + timeCount + "\n venueCount: " + venueCount + "\n attributeCount: " + attributeCount); 898 899 // Group events by NameSort when in alphabetical mode and select the best event from each group 900 if (sortMode == 1) { 901 items = groupEventsByNameSortAndSelectBest(items); 902 } 903 904 for (var i = 0; i < items.length; i++) { 905 // REMOVED: Original skip logic that caused "Sold Out" status to apply to entire alphabetical groups 906 // Replaced with grouping that selects the next available event from each group 907 // if (sortMode == 1 && previousItem == items[i].NameSort) continue; 908 if (browseMode == "Wishlist" && !ft_sessionVisible(items[i])) continue; 909 if (!childEvents && items[i].Child) continue; 910 911 if (selectedOptions.length > 0 || keyword.length > 0) { 912 foundKeyword = false; 913 foundDate = (dateCount <= 1 ? !orSearch : false); 914 foundTime = (timeCount <= 1 ? !orSearch : false); 915 foundVenue = (venueCount <= 1 ? !orSearch : false); 916 foundAttribute = (attributeCount <= 1 ? !orSearch : false); 917 //logBrowse("\n\n\n Defaults\n\n foundKeyword: " + foundKeyword + "\n foundDate: " + foundDate + "\n foundTime: " + foundTime + "\n foundVenue: " + foundVenue + "\n foundAttribute: " + foundAttribute); 918 919 920 if (keyword.length > 0) { 921 var sessionString = (items[i].Code != undefined ? items[i].Code : "") + items[i].Name + items[i].Keywords + (searchDescription ? items[i].DescriptionBrief : "") + items[i].AttributeString + items[i].VenueName + items[i].VenueKeywords; 922 if (sessionString.toLowerCase().indexOf(keyword.toLowerCase()) != -1) foundKeyword = true; 923 } else { 924 foundKeyword = !orSearch; 925 } 926 927 if (!foundKeyword || !orSearch) { 928 929 for (var j = 0; j < selectedOptions.length; j++) { 930 931 var optionType = selectedOptions[j].substring(0, selectedOptions[j].indexOf("o")); 932 var optionValue = selectedOptions[j].substring(selectedOptions[j].indexOf("o") + 1); 933 934 if (optionType == "D") { 935 if (dateCount <= 1) foundDate = false; 936 optionValue = parseDate(optionValue); 937 if (items[i].DateTime instanceof Date && optionValue.getDate() == items[i].DateTime.getDate() && optionValue.getMonth() == items[i].DateTime.getMonth() && optionValue.getFullYear() == items[i].DateTime.getFullYear()) { 938 foundDate = true; 939 if (orSearch) break; 940 } 941 942 } else if (optionType == "T") { 943 if (timeCount <= 1) foundTime = false; 944 var hour = items[i].DateTime.getHours(); 945 if (optionValue == "Morning" && (hour >= 0 && hour < 12)) { 946 foundTime = true; 947 if (orSearch) break; 948 } else if (optionValue == "Afternoon" && (hour >= 12 && hour < 18)) { 949 foundTime = true; 950 if (orSearch) break; 951 } else if (optionValue == "Evening" && (hour >= 18 && hour <= 23)) { 952 foundTime = true; 953 if (orSearch) break; 954 } 955 956 } else if (optionType == "V") { 957 foundVenue = false; 958 if (venueCount <= 1) foundVenue = false; 959 if (items[i].VenueHash == optionValue || items[i].ParentVenueHash == optionValue) { 960 foundVenue = true; 961 if (orSearch) break; 962 } 963 964 } else if (optionType != "K") { 965 if (attributeCount <= 1) foundAttribute = false; 966 for (var k = 0; k < items[i].AttributeHashes.length; k++) { 967 if (items[i].AttributeHashes[k] == optionType + "o" + optionValue) { 968 foundAttribute = true; 969 if (orSearch) break; 970 } 971 } 972 if (orSearch && foundAttribute) break; 973 } 974 } 975 } 976 977 //logBrowse(items[i].Name + "\n orSearch: " + orSearch + "\n foundKeyword: " + foundKeyword + "\n foundDate: " + foundDate + "\n foundTime: " + foundTime + "\n foundVenue: " + foundVenue + "\n foundAttribute: " + foundAttribute); 978 979 if (!orSearch && (!foundKeyword || !foundDate || !foundTime || !foundVenue || !foundAttribute)) { 980 foundKeyword = false; 981 foundDate = false; 982 foundTime = false; 983 foundVenue = false; 984 foundAttribute = false; 985 } 986 987 if (!foundKeyword && !foundDate && !foundTime && !foundVenue && !foundAttribute) continue; 988 } 989 990 sessionCount++; 991 992 if (throttled) { 993 if (sessionCount < throttleStart) { 994 continue; 995 } else if (sessionCount > throttleEnd) { 996 break; 997 } else { 998 if (previousItem.length == 0 && throttleIndex != 1) { 999 if (sortMode == 1) { 1000 previousItem = items[i].Name; 1001 } else if (sortMode == 2) { 1002 previousItem = returnDateTime(items[i].DateTime, true, false); 1003 } else if (sortMode == 3) { 1004 previousItem = items[i].VenueName; 1005 } 1006 } 1007 } 1008 1009 } 1010 1011 if (browseMode == "Browse" || browseMode == "Exchange" || (browseMode == "Wishlist" && view == 2)) { 1012 if (h3s && sortMode == 1 && previousItem.substring(0, 1) != items[i].NameSort.substring(0, 1)) { 1013 var s = items[i].NameSort.substring(0, 1); 1014 if (!/^[a-zA-Z0-9]+$/.test(s)) s = "*"; 1015 if (/^[0-9]+$/.test(s)) s = "#"; 1016 var p = previousItem.substring(0, 1); 1017 if (p.length > 0 && !/^[a-zA-Z0-9]+$/.test(p)) p = "*"; 1018 if (/^[0-9]+$/.test(p)) p = "#"; 1019 if ((s != "#" && s != "*") || (s == "#" && p != "#") || (s == "*" && p != "*")) { 1020 var h3 = document.createElement("h3"); 1021 h3.innerHTML = s; 1022 parent.appendChild(h3); 1023 } 1024 1025 } else if (sortMode == 2 && !noSessionDate(items[i].DateTime) && previousItem != returnDateTime(items[i].DateTime, true, false)) { 1026 var h3 = document.createElement("h3"); 1027 h3.innerHTML = returnDateTime(items[i].DateTime, true, false); 1028 parent.appendChild(h3); 1029 1030 } else if (sortMode == 2 && !ferve.isNullOrEmpty(previousItem) && items[i].VenueName == "Online") { 1031 var h3 = document.createElement("h3"); 1032 h3.innerHTML = "Online"; 1033 parent.appendChild(h3); 1034 1035 } else if (sortMode == 3 && previousItem != items[i].VenueName) { 1036 var h3 = document.createElement("h3"); 1037 h3.innerHTML = items[i].VenueName; 1038 parent.appendChild(h3); 1039 } 1040 } 1041 1042 html = ft_renderItem(items[i]); 1043 1044 div = document.createElement("div"); 1045 div.className = "ft_event"; 1046 1047 1048 1049 if (items[i].CSS && items[i].CSS.length > 0) div.className += " " + items[i].CSS; 1050 div.innerHTML = html; 1051 parent.appendChild(div); 1052 1053 if (sortMode == 1) { 1054 previousItem = items[i].NameSort; 1055 } else if (sortMode == 2) { 1056 previousItem = returnDateTime(items[i].DateTime, true, false); 1057 } else if (sortMode == 3) { 1058 previousItem = items[i].VenueName; 1059 } 1060 } 1061 1062 logBrowse("\n\nsessionCount:" + sessionCount + "\n\n"); 1063 if (sessionCount == 0 && !orSearch && searchOr) { 1064 logBrowse("ft_renderItems calling ft_renderItems (no items)"); 1065 ft_renderItems(clearSessionList, true); 1066 return; 1067 } 1068 1069 if (throttled && sessionCount < items.length) { 1070 div = document.createElement("div"); 1071 div.className = "ft_eventMore"; 1072 div.id = "lm" + throttleIndex; 1073 div.innerHTML = "<a href=\"Javascript:ft_renderMoreItems(" + throttleIndex + ");\">Load More Sessions...</a>"; 1074 parent.appendChild(div); 1075 } 1076 1077 1078 if (parent && html.indexOf("ft_image") == -1) { 1079 parent.innerHTML = "<div style=\"padding:25px;\">No items match your query.</div>"; 1080 } 1081 1082 var x = document.getElementById("BrOptions"); 1083 if (x) x.className = "ft_itemVisible ft_fade ft_noPrint"; 1084 1085 if (browseMode == "Browse" && scrollY != 0) { 1086 var currentScrollY = (document.all ? document.scrollTop : window.pageYOffset); 1087 if (scrollY != currentScrollY) window.scrollTo(0, scrollY); 1088 } 1089 1090 1091 echo.render(); 1092 1093 ferve.renderWishlistStars(); 1094 1095 if (browseMode == "BrowsePass") { 1096 passBooking.changeViewRender(); 1097 var passBookingQty = document.getElementsByClassName("btn-widget"); 1098 for (var i = 0; i < passBookingQty.length; i++) { 1099 passBookingQty[i].addEventListener("click", passBooking.selectPassQty); 1100 } 1101 } 1102 1103 //Get the list of membership 1104 membershipAvailable = document.querySelectorAll('#ft_events .ft_event .ft_select').length; 1105 1106} 1107 1108 1109function ft_renderItem(item) { 1110 var html = "", url = ""; 1111 1112 if (browseMode == "Exchange") { 1113 url = "Javascript:ft_exchangeItem('" + item.Hash + "');" 1114 html += "<div class=\"ft_select\">"; 1115 var ignore = [1, 2, 5, 6]; 1116 if (ignore.indexOf(item.Status) == -1) html += "<input type=\"radio\" name=\"itemHash\" value=\"" + item.Hash + "\" data-hash=\"" + item.Hash + "\" onclick=\"ft_exchangeItem('" + item.Hash + "')\" />"; 1117 html += "</div>"; 1118 } else if (browseMode == "MemberRenew") { 1119 url = "Javascript:ft_renewItem('" + item.Hash + "');" 1120 html += "<div class=\"ft_select\">"; 1121 var ignore = [1, 2, 5, 6]; 1122 //MP : If there is only one membership type to renew, radio button should be pre-selected 1123 if (ignore.indexOf(item.Status) == -1) html += "<input type=\"radio\" name=\"itemHash\" value=\"" + item.Hash + "\" data-hash=\"" + item.Hash + "\" " + (membershipAvailable == 1 ? "checked" : "") + " onclick=\"ft_renewItem('" + item.Hash + "')\" />"; 1124 if (membershipAvailable == 1) ft_renewItem(item.Hash); 1125 html += "</div>"; 1126 } else { 1127 url = item.URL; 1128 } 1129 1130 var href = "<a href=\"" + url + "\"" + (url.indexOf("Redirect") != -1 ? " target=\"_blank\"" : "") + ">"; 1131 1132 html += "<div class=\"ft_image\">" + href + "<img src=\"" + ft_link("/img/ferve/loading_browse.gif") + "\" data-echo=\"" + ft_link(image == "browse" ? item.ImageBrowse : item.ImageThumbnail) + "\" onerror=\"ft_image404(this);this.style.display='none';\" alt=\"" + item.Name + "\" /></a></div>"; 1133 1134 html += "<div class=\"ft_info\">"; 1135 html += href; 1136 html += "<div class=\"ft_status\">"; 1137 if (item.Status == 1) { 1138 html += "<div class=\"fticon-status-cancelled ft_cancelled\" title=\"Cancelled\"><span class=\"ft_cancelled\">Cancelled</span></div>"; 1139 } else if (item.Status == 2) { 1140 html += "<div class=\"fticon-status-postponed ft_postponed\" title=\"Postponed\"><span class=\"ft_postponed\">Postponed</span></div>"; 1141 } else if (item.Status == 4) { 1142 html += "<div class=\"fticon-status-sellingfast ft_sellingfast\" title=\"Selling Fast\"><span class=\"ft_sellingfast\">Selling Fast</span></div>"; 1143 } else if (item.Status == 5) { 1144 html += "<div class=\"fticon-status-standby ft_standby\" title=\"Standby\"><span class=\"ft_standby\">Standby</span></div>"; 1145 } else if (item.Status == 6) { 1146 html += "<div class=\"fticon-status-soldout ft_soldout\" title=\"Sold Out\"><span class=\"ft_soldout\">Sold Out</span></div>"; 1147 } 1148 html += "</div>"; 1149 1150 if (wishlist && !ws) { 1151 var name = document.getElementById("ft_heading").innerHTML; 1152 name = name.substring(0, name.indexOf("'")); 1153 if (item.Purchased) html += "<div class=\"fticon-status-purchased1\" title=\"" + name + " has purchased tickets\"><img src=\"/img/ferve/status_purchased.svg\" /></div>"; 1154 //if (item.Wishlist) html += "<div class=\"fticon-wishlist-on fticon-status-wishlist" + (item.Purchased ? "2" : "1") + "\" title=\"In " + name + "'s wishlist\"></div>"; 1155 } else if (item.Purchased) { 1156 html += "<div class=\"fticon-status-purchased\" title=\"Purchased Tickets\"><img src=\"/img/ferve/status_purchased.svg\" /></div>"; 1157 } 1158 1159 html += (item.Code != undefined && item.Code.length > 0 ? "<div class=\"ft_code\">" + item.Code + "</div>" : ""); 1160 html += "<div class=\"ft_title\">" + item.Name + "</div>"; 1161 html += "<div class=\"ft_attributes\">" + item.AttributeString + "</div>"; 1162 html += "<div class=\"ft_date\">"; 1163 if (sortMode == 1) { 1164 var arr = item.URL.split("/"); 1165 html += item.Count + " " + (arr.length > 2 ? arr[1].slice(0, -1) : "Session") + (item.Count == 1 ? "" : "s"); 1166 } else { 1167 if (item.TimeSlots > 0) html += "From "; 1168 html += returnDateTime(item.DateTime, (view == 1), true); 1169 } 1170 html += "</div>"; 1171 html += "<div class=\"ft_venue\">"; 1172 if (sortMode == 1) { 1173 if (item.Count == 1) { 1174 html += (item.VenueName != null ? item.VenueName : ""); 1175 } else { 1176 html += " "; 1177 } 1178 } else { 1179 html += (item.VenueName != null ? item.VenueName : ""); 1180 } 1181 html += "</div>"; 1182 html += "<div class=\"ft_runtime\">" + item.Runtime + " mins</div>"; 1183 if (item.AccessibilityIcons && item.AccessibilityIcons.length > 0) html += "<div class=\"ft_accessibility\">" + item.AccessibilityIcons + "</div>"; 1184 html += "<div class=\"ft_description\">" + item.DescriptionBrief + "</div>"; 1185 html += "<div class=\"ft_priceRange\">" + item.PriceRange + "</div>"; 1186 html += "<div class=\"ft_btnView\">View</div>"; 1187 html += "</a>"; 1188 1189 if (browseMode == "BrowsePass") { 1190 var htmlWidget = ""; 1191 for (var i = 0;
1191 i <= passBooking.getTotalRedeemPerEvent(); i++) { 1192 if (i == 0) { 1193 htmlWidget += "<label class=\"btn btn-default btn-widget active " + passBooking.lockWidget(item.Status) + "\"><input value=\"" + i + "\" type=\"radio\" name=\"options\" id=\"option" + i + "\" autocomplete=\"off\">" + i + "</label>"; 1194 } else { 1195 htmlWidget += "<label class=\"btn btn-default btn-widget " + passBooking.lockWidget(item.Status) + "\"><input value=\"" + i + "\" type=\"radio\" name=\"options\" id=\"option" + i + "\" autocomplete=\"off\">" + i + "</label>"; 1196 } 1197 } 1198 1199 html += "<div data-itemName='" + item.Name + "' data-itemhash=" + item.Hash + " data-status='" + item.Status + "' data-thumbnail='" + ft_link(item.ImageThumbnail) + "' data-Allocated=" + item.Allocated + " class=\"btn-group btn-group-toggle browsepass\" role=\"group\" data-toggle=\"buttons\"><label class=\"btn btn-default widgetlabel\">Tickets</label>" + htmlWidget + "</div>"; 1200 } 1201 1202 html += "<div class=\"ft_btnTrailer" + (ferve.isNullOrEmpty(item.Trailer) ? " ft_trailerNone" : "") + "\"><a href=\"Javascript:playTrailer('" + item.Trailer + "')\">Trailer</a></div>"; 1203 html += "</div>";// ft_info 1204 1205 if (wishlist) { 1206 html += "<div class=\"ft_wishlist\"><a href=\"Javascript:" + (sortMode == 1 && item.Count > 1 ? "ferve.wishlist.toggleSeason('" + item.Id + "')" : "ferve.wishlist.toggle('" + item.Id + "')") + ";\" title=\"Add/remove from your wishlist\"><div class=\"fticon-wishlist-off\" data-wishlist=\"" + item.Id + "\"></div></a></div>"// if (wishlist && ws) 1207 } 1208 1209 if (item.Keywords.substring(item.Keywords.length - 3) == "[H]") html += "<div class=\"corner-ribbon\" title=\"Set as web hidden and is not visible to non admin users.\">Hidden</div>"; 1210 if (item.Keywords.substring(item.Keywords.length - 3) == "[E]") html += "<div class=\"corner-ribbon\">Expired</div>"; 1211 1212 return html; 1213} 1214 1215 1216function ft_renderMoreItems(ti) { 1217 throttleIndex++; 1218 1219 var x = document.getElementById("lm" + ti); 1220 if (x) x.parentNode.removeChild(x); 1221 1222 1223 setTimeout(function () { ft_renderItems(false, searchOr); }, 100); 1224 1225} 1226 1227 1228// #mark ------ Sorting ------ 1229 1230function sort(mode, click) { 1231 1232 sortMode = mode; 1233 1234 // Save options when sort mode changes 1235 if (browseMode == "Browse") { 1236 ft_browseOptionsSave(); 1237 } 1238 1239 var x; 1240 1241 if (click) ft_toggleMenu("S"); 1242 1243 for (var i = 1; i < 4; i++) { 1244 x = document.getElementById("ft_sort" + i); 1245 if (x) x.checked = (i == mode); 1246 } 1247 1248 if (mode == 1) { 1249 items.sort(orderByName); 1250 } else if (mode == 2) { 1251 items.sort(orderBySessionDate); 1252 } else if (mode == 3) { 1253 items.sort(orderByVenue); 1254 } 1255 1256 if (click) ft_renderItems(true, searchOr); 1257 1258 1259 1260} 1261 1262/* Array sorting */ 1263function orderByName(a, b) { 1264 var x = a.NameSort.toString().toLowerCase(), y = b.NameSort.toString().toLowerCase(); 1265 if (!/^[a-zA-Z0-9]+$/.test(x.substring(0, 1))) x = "*"; 1266 if (!/^[a-zA-Z0-9]+$/.test(y.substring(0, 1))) y = "*"; 1267 return x < y ? -1 : x > y ? 1 : 0; 1268} 1269 1270function orderBySessionDate(a, b) { 1271 if (a.VenueName == "Online") return 1; 1272 if (b.VenueName == "Online") return -1; 1273 var x = a.DateTime, y = b.DateTime; 1274 return x - y; 1275} 1276 1277function orderByVenue(a, b) { 1278 var x = a.VenueName.toLowerCase(), y = b.VenueName.toLowerCase(); 1279 return x < y ? -1 : x > y ? 1 : 0; 1280} 1281 1282function returnAttributeGroup(hash) { 1283 if (!attributeGroups || attributeGroups.length == 0) return null; 1284 for (var i = 0; i < attributeGroups.length; i++) { 1285 for (var j = 0; j < attributeGroups[i].Attributes.length; j++) { 1286 if (attributeGroups[i].Attributes[j].Hash == hash) return attributeGroups[i]; 1287 } 1288 } 1289 return null; 1290} 1291 1292function returnAttribute(hash) { 1293 if (!attributeGroups || attributeGroups.length == 0) return null; 1294 for (var i = 0; i < attributeGroups.length; i++) { 1295 for (var j = 0; j < attributeGroups[i].Attributes.length; j++) { 1296 if (attributeGroups[i].Attributes[j].Hash == hash) return attributeGroups[i].Attributes[j]; 1297 } 1298 } 1299 return null; 1300} 1301 1302function returnVenue(hash) { 1303 if (!venues) return null; 1304 for (var i = 0; i < venues.length; i++) { 1305 if (venues[i].Hash == hash) return venues[i]; 1306 } 1307 return ""; 1308} 1309 1310function returnVenueName(hash) { 1311 if (!venues) return "NAV"; 1312 for (var i = 0; i < venues.length; i++) { 1313 if (venues[i].Hash == hash) return venues[i].Name; 1314 } 1315 return ""; 1316} 1317 1318function returnVenueFromName(name) { 1319 if (!venues) return null; 1320 for (var i = 0; i < venues.length; i++) { 1321 if (venues[i].Name == name) return venues[i]; 1322 } 1323 return null; 1324} 1325 1326var searchTimeout; 1327function startSearch() { 1328 logBrowse("startSearch (" + (typeof (searchTimeout) != "undefined") + ")"); 1329 if (typeof (searchTimeout) != "undefined") clearTimeout(searchTimeout); 1330 searchTimeout = setTimeout(function () { 1331 logBrowse("startSearch calling ft_renderItems"); 1332 ft_renderItems(true, searchOr); 1333 }, 400); 1334} 1335
1336function browseView(c) { 1337 logBrowse("browseView(" + c + ")"); 1338 var x = document.getElementById("ft_events"); 1339 if (!x) x = document.getElementById("ft_venuess"); 1340 if (!x) return; 1341 x.className = c; 1342 view = (x.className.indexOf("ft_list") > -1 ? 2 : 1); 1343 1344 ft_renderItems(true, searchOr);// Always render 1345 1346 // Save options when view changes 1347 if (browseMode == "Browse") { 1348 ft_browseOptionsSave(); 1349 } 1350 1351 // Wishlist 1352 //var x = document.getElementById("ft_events"); 1353 //if (x && x.innerHTML.indexOf("ft_scheduler") > -1) ft_renderItems(true, false); 1354} 1355 1356 1357// #mark ------ Calendar ------ 1358 1359var clickedDates = new Array(); 1360var clickedTimes = new Array(); 1361function renderCalendar(m, y) { 1362 logBrowse("\n\nrenderCalendar(" + m + ", " + y + ")"); 1363 // Calendar rendering borrowed from tix iPhone app 1364 var html = ""; 1365 var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; 1366 1367 var selectedDate; 1368 if (isNaN(m) || isNaN(y)) { 1369 selectedDate = new Date(); 1370 for (var i = 0; i < items.length; i++) { 1371 if (items[i].DateTime > selectedDate) { 1372 m = items[i].DateTime.getMonth() 1373 y = items[i].DateTime.getFullYear() 1374 break; 1375 } 1376 } 1377 if (isNaN(m) || isNaN(y)) { 1378 m = selectedDate.getMonth() 1379 y = selectedDate.getFullYear() 1380 } 1381 } 1382 selectedDate = new Date(y, m, 1); 1383 1384 // Work out 1st day of month 1385 var dayMonthStarts = selectedDate.getDay(); 1386 if (dayMonthStarts == 0) dayMonthStarts = 7; 1387 1388 // Days in current month 1389 var daysInCurrentMonth = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate(); 1390 1391 // Days in previous month 1392 var previousMonth = new Date(selectedDate.getTime()); 1393 previousMonth.setMonth(previousMonth.getMonth() - 1); 1394 daysInPreviousMonth = new Date(previousMonth.getFullYear(), previousMonth.getMonth() + 1, 0).getDate(); 1395 1396 var nextMonth = new Date(selectedDate.getTime()); 1397 nextMonth.setMonth(nextMonth.getMonth() + 1); 1398 1399 // Header 1400 html += "<div class='calHeader'><div class='calPrev'><a href='Javascript:renderCalendar(" + previousMonth.getMonth() + "," + previousMonth.getFullYear() + ")'><</a></div><div class='calDate'>" + monthName(selectedDate.getMonth(), false) + " " + selectedDate.getFullYear() + "</div><div class='calNext'><a href='Javascript:renderCalendar(" + nextMonth.getMonth() + "," + nextMonth.getFullYear() + ")'>></a></div></div><div class='calCells calWeek'><div>M</div><div>T</div><div>W</div><div>T</div><div>F</div><div class='calDisabled'>S</div><div class='calDisabled'>S</div></div>"; 1401 1402 1403 // Tiles 1404 var noRows = 0; 1405 var dayCounter = 1; 1406 1407 for (var rowCounter = 1; rowCounter < 7; rowCounter++) { 1408 1409 html += "<div class='calCells'>"; 1410 1411 for (var columnCounter = 1; columnCounter < 8; columnCounter++) { 1412 1413 var cellOutsideCurrentMonth = false; 1414 var cellSelected = false; 1415 var cellFestivalDate = false;// Sessions on that day 1416 var cellToday = false; 1417 var tileDate = new Date(selectedDate.getTime()); 1418 1419 var day = 0; 1420 if (dayMonthStarts != 1 && dayCounter == 1) dayCounter = ((dayMonthStarts - 2) * -1); 1421 1422 if (rowCounter == 1 && columnCounter < dayMonthStarts) { 1423 // First row and listing previous month tile 1424 day = daysInPreviousMonth + dayCounter; 1425 cellOutsideCurrentMonth = true; 1426 tileDate.setMonth(tileDate.getMonth() - 1); 1427 dayCounter++; 1428 1429 } else { 1430 if (rowCounter == 1 && columnCounter == dayMonthStarts) dayCounter = 1; 1431 1432 if (dayCounter > daysInCurrentMonth) { 1433 // Next month 1434 day = dayCounter - daysInCurrentMonth; 1435 cellOutsideCurrentMonth = true; 1436 tileDate.setMonth(tileDate.getMonth() + 1); 1437 } else { 1438 // Current month 1439 day = dayCounter; 1440 } 1441 1442 dayCounter++; 1443 } 1444 1445 tileDate.setDate(day); 1446 1447 // Has the date been selected 1448 if (clickedDates.length > 0) { 1449 1450 for (var i = 0; i < clickedDates.length; i++) { 1451 1452 if (clickedDates.getDate() == tileDate.getDate() && clickedDates.getMonth() == tileDate.getMonth() && clickedDates.getFullYear() == tileDate.getFullYear()) { 1453 cellSelected = true; 1454 break; 1455 } 1456 } 1457 1458 } 1459 1460 var today = new Date(); 1461 if (today.getDate() == tileDate.getDate() && today.getMonth() == tileDate.getMonth() && today.getFullYear() == tileDate.getFullYear()) { 1462 // today 1463 cellToday = true; 1464 } 1465 1466 for (var i = 0; i < items.length; i++) { 1467 if (items[i].DateTime instanceof Date && items[i].DateTime.getDate() == tileDate.getDate() && items[i].DateTime.getMonth() == tileDate.getMonth() && items[i].DateTime.getFullYear() == tileDate.getFullYear()) { 1468 // Festival date 1469 cellFestivalDate = true; 1470 break; 1471 } 1472 } 1473 1474 var className = ""; 1475 1476 if (cellToday && cellFestivalDate && cellSelected) { 1477 className = "calOrganiser calToday calSelected"; 1478 1479 } else if (cellToday && !cellFestivalDate && cellSelected) { 1480 className = "calToday calSelected"; 1481 1482 } else if (cellToday && !cellFestivalDate && !cellSelected && cellOutsideCurrentMonth) { 1483 className = "calDisabled calToday"; 1484 1485 } else if (cellToday && !cellFestivalDate && !cellSelected) { 1486 className = "calToday"; 1487 1488 } else if (cellToday && cellFestivalDate && !cellSelected) { 1489 className = "calOrganiser calToday"; 1490 1491 } else if (!cellToday && cellFestivalDate && !cellSelected) { 1492 className = "calOrganiser"; 1493 1494 } else if (!cellToday && cellFestivalDate && cellSelected) { 1495 className = "calOrganiser calSelected"; 1496 1497 } else if (!cellToday && !cellFestivalDate && cellSelected) { 1498 className = "calSelected"; 1499 1500 } else if (cellOutsideCurrentMonth) { 1501 className = "calDisabled"; 1502 1503 } else { 1504 className = ""; 1505 } 1506 1507 1508 html += "<div class='" + className + "' id='d" + tileDate.getFullYear() + "-" + (tileDate.getMonth() + 1) + "-" + tileDate.getDate() + "'><a href=\"Javascript:calendarDateClicked('" + tileDate.getFullYear() + "-" + (tileDate.getMonth() + 1) + "-" + tileDate.getDate() + "');\">" + tileDate.getDate() + "</a></div>"; 1509 1510 1511 } 1512 1513 html += "</div>";// calCells 1514 1515 noRows++; 1516 1517 if (dayCounter > daysInCurrentMonth) break; 1518 } 1519 1520 var x = document.getElementById("ft_calendar") 1521 if (x) x.innerHTML = html; 1522} 1523 1524function calendarDateClicked(selectedDate) { 1525 var selDate = parseDate(selectedDate); 1526 var x = document.getElementById("d" + selDate.getFullYear() + "-" + (selDate.getMonth() + 1) + "-" + selDate.getDate()); 1527 var y = document.getElementById("ft_so_Do" + selectedDate); 1528 if (y) { 1529 x.className = x.className.replace("calSelected", ""); 1530 ft_removeSelectedOption("D", selectedDate); 1531 } else { 1532 if (x) x.className += " calSelected"; 1533 ft_addSelectedOption("D", selectedDate); 1534 } 1535} 1536 1537function calendarTimeClicked(selectedTime) { 1538 var x = document.getElementById("t" + selectedTime); 1539 var y = document.getElementById("ft_so_To" + selectedTime); 1540 var y = document.getElementById("ft_so_To" + selectedTime); 1541 if (y) { 1542 x.className = ""; 1543 ft_removeSelectedOption("T", selectedTime); 1544 } else { 1545 x.className = "tabSelected"; 1546 ft_addSelectedOption("T", selectedTime); 1547 } 1548} 1549 1550 1551 1552 1553 1554// #mark ------ Utility - Prefs ------ 1555 1556 1557function ft_browseOptionsRead() { 1558 console.log("=== ft_browseOptionsRead() called ==="); 1559 console.log("ferve_h:", ferve_h); 1560 1561 var savedOptions = window.sessionStorage.getItem("FTBR_" + ferve_h + "-options"); 1562 1563 if (savedOptions == null) {
1564 console.log("No saved options found, returning early"); 1565 return; 1566 } 1567 1568 var keyword = window.sessionStorage.getItem("FTBR_" + ferve_h + "-keyword"); 1569 if (keyword.length > 0 && document.getElementById("ft_keyword")) document.getElementById("ft_keyword").value = keyword; 1570 1571 sortMode = window.sessionStorage.getItem("FTBR_" + ferve_h + "-sortMode"); 1572 scrollY = window.sessionStorage.getItem("FTBR_" + ferve_h + "-scrollY"); 1573 console.log("Saved sortMode:", sortMode, "scrollY:", scrollY); 1574 1575 var tmpSelectedOptions = savedOptions; 1576 if (tmpSelectedOptions.length > 0) { 1577 tmpSelectedOptions = JSON.parse(tmpSelectedOptions); 1578 } 1579 1580 1581 for (var i = 0; i < tmpSelectedOptions.length; i++) { 1582 var group = tmpSelectedOptions[i].substring(0, tmpSelectedOptions[i].indexOf("o")).toUpperCase(); 1583 var option = tmpSelectedOptions[i].substring(tmpSelectedOptions[i].indexOf("o") + 1); 1584 1585 if (group.length == 0 || option.length == 0) { 1586 continue; 1587 } 1588 if (group == "D") { 1589 calendarDateClicked(option); 1590 } else if (group == "T") { 1591 calendarTimeClicked(option); 1592 } else if (group != "K") { 1593 ft_toggleCheckbox(group, option); 1594 } 1595 } 1596} 1597 1598function ft_browseOptionsSave() { 1599 window.sessionStorage.setItem("FTBR_" + ferve_h + "-options", JSON.stringify(selectedOptions)); 1600 window.sessionStorage.setItem("FTBR_" + ferve_h + "-keyword", (document.getElementById("ft_keyword") ? document.getElementById("ft_keyword").value : "")); 1601 window.sessionStorage.setItem("FTBR_" + ferve_h + "-sortMode", sortMode); 1602 window.sessionStorage.setItem("FTBR_" + ferve_h + "-scrollY", scrollY); 1603} 1604 1605 1606// #mark ------ Utility ------ 1607 1608function ft_link(l) { 1609 if (l.indexOf("http") > -1) return l; 1610 1611 if (window.location.protocol == "https:") { 1612 return ferve.url + l.substring(1); 1613 } else { 1614 return l; 1615 } 1616} 1617 1618 1619function removeElement(array, itemNo) { 1620 size = array.length; 1621 validNo = (itemNo != "NaN"); 1622 inRange = ((itemNo >= 0) && (itemNo <= array.length)); 1623 if (validNo && inRange) { 1624 for (var i = 0; i <= size; i++) 1625 array[i] = ((i == itemNo) ? "delete" : array[i]); 1626 for (var j = itemNo; j < size - 1; j++) 1627 if (j != size) array[j] = array[j + 1]; 1628 array.length = size - 1; 1629 return array 1630 } 1631 return array 1632} 1633 1634 1635function switchCSS(cn) { 1636 var x = document.getElementById("ft_events"); 1637 if (x) x.className = cn; 1638 1639 // reset echo 1640 var elem, nodes = document.querySelectorAll("img[data-echoFT]"), length = nodes.length; 1641 for (var i = 0; i < length; i++) { 1642 elem = nodes[i]; 1643 elem.setAttribute("data-echo", elem.getAttribute("data-echoFT")); 1644 elem.removeAttribute("data-echoFT"); 1645 } 1646 echo.render(); 1647} 1648
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.