1$(function() { 2 //price group toggle events 3 $(document).on('mouseenter', 'div.ticket-categories > ul > li', function() { 4 TicketGroup.select($(this).data('group')); 5 }); 6 $(document).on('mouseleave', 'div.ticket-categories > ul > li', function() { 7 TicketGroup.unselect($(this).data('group')); 8 }); 9 $(document).on('click', 'div.ticket-categories > ul > li', function() { 10 TicketGroup.toggleHoldSelection($(this).data('group')); 11 }); 12 //end of: price group toggle 13 14 $(document).on('click', '#' + Consts.domIds.tooltip + ' a[href="#"]', function() { 15 return false; 16 }); 17 18 //tap event for mobile 19 if (typeof Config.mobile_fast_selection !== 'undefined' && Config.mobile_fast_selection) { 20 //mobile use fast seat selection: one click (without tooltip) 21 Seat.mobileFastSelection(); 22 } else { 23 //fix tooltip hiding on mobile double tap mode 24 $('div#audit').on('click touchstart', function() { 25 setTimeout(function() { 26 if (!audit.seatTooltip.showinit) { 27 audit.seatTooltip.hide(); 28 setTimeout(function() { 29 if (!$('#'+Consts.domIds.tooltip).is(':visible')) { 30 document.dispatchEvent(new CustomEvent("clearHighlight")); 31 } 32 }, 300); 33 } 34 }, 200); 35 }); 36 } 37 //end of: tap 38 39 //minimap enable/disable 40 MiniMAP.init(); 41 42 //testing 43 if (window.location.hash === '#test') { 44 Testing.start(); 45 } 46 47 if (window.location.hash === '#dev') { 48 Seat.collectMode = true; 49 } 50 $(document).on('click', '.pw-eye-btn', function() { 51 if ($(this).find('.fa').hasClass('fa-eye-slash')) { 52 $(this).find('.fa').removeClass('fa-eye-slash'); 53 $(this).find('.fa').addClass('fa-eye'); 54 $(this).closest('.input-group').find('.pw-eye-fld').attr('type', 'text'); 55 } else { 56 $(this).find('.fa').removeClass('fa-eye'); 57 $(this).find('.fa').addClass('fa-eye-slash'); 58 $(this).closest('.input-group').find('.pw-eye-fld').attr('type', 'password'); 59 } 60 }); 61 $('#buttonBlind').click(function() { 62 document.location.search = '?force_arrival=1'; 63 }); 64}); 65 66var Consts = { 67 statusIds: { 68 empty: 0, 69 selected: 1, 70 occupied: 2 71 }, 72 73 domIds: { 74 loadingLabel: 'loading', 75 audit: 'audit', 76 sectorsLayer: 'Bsectors', 77 seatsLayer: 'Bseats', 78 tooltip: 'tooltip', 79 capacityPopup: 'capacityPopup', 80 81 btnZoomIn: 'buttonPlus', 82 btnZoomOut: 'buttonMinus', 83 btnShowSectors: 'buttonSectors', 84 btnReset: 'buttonEye' 85 } 86}; 87 88function auditBasketManager() { 89 this.ticketCount = 0; 90 this.sumPrice = 0; 91 this.ticketPrices = 0; 92 this.serviceCharge = 0; 93 this.collected = false; 94 95 this.addItem = function(quantity, price, ticketprice) { 96 quantity = parseInt(quantity, 10); 97 price = parseFloat(price); 98 ticketprice = typeof ticketprice === 'undefined' ? false : parseFloat(ticketprice); 99 var sc = ticketprice === false 100 ? (this.getServiceCharge(quantity, price) * quantity) 101 : Math.max(0, price - ticketprice); 102 103 this.ticketCount += quantity; 104 this.serviceCharge += sc; 105 if (ticketprice === false) { 106 this.ticketPrices += price; 107 this.sumPrice += price + sc; 108 } else { 109 this.ticketPrices += ticketprice; 110 this.sumPrice += price; 111 } 112 113 this.updateDisplay(); 114 }; 115 116 this.removeItem = function(quantity, price) { 117 var sc = this.getServiceCharge(quantity, price); 118 price = parseFloat(price); 119 120 this.ticketCount -= parseInt(quantity, 10); 121 if (this.ticketCount < 0) { 122 this.ticketCount = 0; 123 } 124 125 this.ticketPrices -= price; 126 if (this.ticketCount === 0 || this.ticketPrices < 0) { 127 this.ticketPrices = 0; 128 } 129 130 this.serviceCharge -= sc; 131 if (this.ticketCount === 0 || this.serviceCharge < 0) { 132 this.serviceCharge = 0; 133 } 134 135 this.sumPrice -= price + sc; 136 if (this.ticketCount === 0 || this.sumPrice < 0) { 137 this.sumPrice = 0; 138 } 139 140 this.updateDisplay(); 141 }; 142 143 this.getServiceCharge = function(quantity, price) { 144 if (audit.showServiceCharge && quantity > 0) { 145 var ticketprice = parseFloat(price) / parseInt(quantity, 10); 146 if (typeof TicketGroup.list[ticketprice] !== 'undefined') { 147 var service_charge = TicketGroup.list[ticketprice]['sum_price'] - ticketprice; 148 if (service_charge > 0) { 149 return service_charge; 150 } 151 } 152 } 153 return 0; 154 }; 155 156 this.clearItems = function() { 157 this.removeItem(this.ticketCount, this.sumPrice); 158 }; 159 160 this.collect = function(sectorsDivId, seatsDivId) { 161 if (!this.collected) { 162 this.collected = true; 163 var self = this; 164 this.sumPrice = 0; 165 this.ticketCount = 0; 166 this.ticketPrices = 0; 167 this.serviceCharge = 0; 168 169 $('#'+sectorsDivId).find('input.sector').each(function() { 170 var type = parseInt($(this).attr('data-type')); 171 var inbasket = parseInt($(this).attr('data-inbasket')); 172 if (inbasket > 0) { 173 if (type != 0) { 174 // capacity or arrival order - inbasket*price 175 var price = parseFloat($(this).attr('data-price')); 176 var ticketprice = parseFloat($(this).attr('data-ticketprice')); 177 self.addItem(inbasket, inbasket * price, inbasket * ticketprice); 178 } else { 179 // normal - inbasket, sumprice, sumticketprice 180 var sumprice = parseFloat($(this).attr('data-sumprice')); 181 var ticketprice = parseFloat($(this).attr('data-sumticketprice')); 182 if (inbasket > 0) { 183 self.addItem(inbasket, sumprice, ticketprice); 184 } 185 } 186 } 187 }); 188 this.updateDisplay(); 189 } 190 }; 191 192 this.updateDisplay = function() { 193 $('span.ticketCount').html(this.ticketCount); 194 $('span.ticketprice').html(it_price_format(this.ticketPrices)); 195 $('span.servicecharge').html(it_price_format(this.serviceCharge)); 196 $('span.total').html(it_price_format(this.sumPrice)); 197 198 if (this.ticketCount) { 199 $('button.toBasket').prop('disabled', false); 200 } else { 201 $('button.toBasket').prop('disabled', true); 202 } 203 }; 204} 205 206function HTML5Audit() { 207 // variables 208 this.auditId; 209 this.eventId; 210 this.programId = 0; 211 this.noSectors; 212 this.loadingLabel = new DivLabel(Consts.domIds.loadingLabel); 213 this.sectorTooltip; 214 this.seatTooltip; 215 this.basketManager = new auditBasketManager(); 216 this.updateInterval = false; // setInterval id for update 217 this.ajaxCallInProgress = 0; 218 this.width; 219 this.height; 220 this.isMobile = false;
221 this.capacityPopup = false; 222 this.auditLoaded = false; 223 this.ticketType = 'event'; 224 this.initialized = false; 225 this.dynamic = false; 226 this.dynamicPrices = false; 227 this.refreshCounter = false; 228 this.basketProcessing = false; 229 this.showServiceCharge = false; 230 231 this.collectingUpdate = false; 232 this.collectedSectors = []; 233 this.updating = false; 234 this.statusUpdateIgnore = []; 235 236 //special sectors 237 this.bestTicketSectors = []; 238 this.availableBestTicketSectors = {}; 239 this.hs = ''; 240 241 //audit seat status updates 242 this.updateElementList = []; 243 this.updateInProgress = false; 244 245 //mlsz settings 246 this.mlszEnabled = false; 247 248 //extends object exists 249 this.mlszAuditObjectExists = false; 250 this.bestTicketObjectExists = false; 251 252 //special sectors: select all seats from sector 253 this.hasSpecialSectors = false; 254 this.specialSectors = []; 255 256 this.obstructedIconSet = false; 257 this.obstructedIconShowed = false; 258 259 //stage pictures 260 this.stagePictures = false; 261 262 //distributed package mode 263 this.isDistributedPackage = false; 264 265 //initialize object (once) 266 this.init = function() { 267 if (this.initialized) { 268 return false; 269 } 270 271 //init ticket type (by default is: event) 272 if (typeof ticketType !== 'undefined') { 273 this.ticketType = ticketType; 274 } 275 276 if (typeof dynamicsetup !== 'undefined') { 277 this.dynamicPrices = true; 278 } 279 280 //add listeners 281 var self = this; 282 if (this.ticketType === 'event' || this.ticketType === 'seasonticket') { 283 document.addEventListener("loadSectorsData", function (e) { 284 if (!self.collectingUpdate) { 285 self.collectingUpdate = true; 286 } 287 if (self.statusUpdateIgnore.length === 0) { 288 self.statusUpdateIgnore = e.detail.ignore; 289 } else { 290 for(var i=0; i<e.detail.ignore.length; i++) { 291 self.statusUpdateIgnore.push(e.detail.ignore[i]); 292 } 293 } 294 self.statusUpdate(1, e.detail.update); 295 }); 296 297 if (this.ticketType === 'event') { 298 document.addEventListener("refreshSectorSeats", function (e) { 299 self.statusUpdate(0, [e.detail], 0, true, true); 300 }); 301 } 302 } 303 304 //init tooltips 305 this.setSeatTooltips(); 306 this.setSectorTooltips(); 307 308 //setup dynamic mode 309 var auditObj = $('#' + Consts.domIds.audit); 310 if ($(auditObj).data('dynamic')) { 311 this.dynamic = true; 312 var setDynamicMode = new CustomEvent("setDynamicMode", { detail: true }); 313 document.dispatchEvent(setDynamicMode); 314 } 315 316 //init MLSZ mode 317 if ($(auditObj).data('mlsz')) { 318 this.mlszEnabled = true; 319 } 320 321 //check venue soloseat 322 if (typeof venue_id !== 'undefined' && typeof Config.soloSeatProtectionVenue === 'object') { 323 venue_id = $.trim(venue_id); 324 if (Config.soloSeatProtectionVenue.hasOwnProperty(venue_id)) { 325 Config.soloSeatProtection = Config.soloSeatProtectionVenue[venue_id] ? true : false; 326 } 327 } 328 329 //check object extends 330 if (this.mlszEnabled) { 331 this.mlszAuditObjectExists = typeof MLSZAudit !== 'undefined'; 332 } else { 333 this.bestTicketObjectExists = typeof BestTicket !== 'undefined'; 334 } 335 336 //bestticket sector (not mlsz page) 337 if (this.dynamic && !this.mlszEnabled && this.bestTicketObjectExists) { 338 document.addEventListener("showBestTicketSelectorEvent", function (e) { 339 var sector_id = e.detail.sectorID; 340 var seat_group_id = e.detail.seatGroupID; 341 342 //open popup 343 BestTicket.openSelector(sector_id, seat_group_id); 344 }); 345 } 346 347 //intialize protected sectors 348 ProtectedSectors.init(); 349 350 if (typeof dpstatus !== 'undefined') { 351 this.isDistributedPackage = true; 352 if (typeof DistributedPackage !== 'undefined') { 353 DistributedPackage.initStatus(dpstatus); 354 } else { 355 var initDPInt = setInterval(function() { 356 if (typeof DistributedPackage !== 'undefined') { 357 DistributedPackage.initStatus(dpstatus); 358 } 359 clearInterval(initDPInt); 360 }, 500); 361 } 362 } 363 364 if (typeof hslist !== 'undefined' && hslist.length > 0) { 365 this.hs = hslist.join(','); 366 } 367 368 //finalize init 369 this.initialized = true; 370 return true; 371 }; 372 373 //reset audit object 374 this.reinit = function() { 375 this.sectorTooltip = null; 376 this.seatTooltip = null; 377 this.capacityPopup = false;
378 this.auditLoaded = false; 379 this.hasSpecialSectors = false; 380 this.specialSectors = []; 381 var reinitAudit = new CustomEvent("reinitAudit"); 382 document.dispatchEvent(reinitAudit); 383 this.setSeatTooltips(); 384 this.setSectorTooltips(); 385 this.stagePictures = false; 386 this.obstructedIconShowed = false; 387 }; 388 389 //calculate auditorium viewer size 390 this.calculateSize = function(auditObj) { 391 this.width = auditObj.width(); 392 if (typeof this.width !== 'number') { 393 this.width = Config.auditBackgroundWidth; 394 } 395 396 this.height = auditObj.height(); 397 if (typeof this.height !== 'number') { 398 this.height = Config.auditBackgroundHeight; 399 } 400 if (this.height > screen.height) { 401 this.height = screen.height; 402 } 403 if (this.height > this.width) { 404 this.height = this.width; 405 } 406 auditObj.height(this.height); 407 }; 408 409 //functions 410 this.loadAudit = function (auditId, eventId, noSectors, isMobile) { 411 this.init(); 412 var auditObj = $('#' + Consts.domIds.audit); 413 if (!$('div#audit-viewer').size()) { 414 $(auditObj).prepend('<div id="audit-viewer" style="visibility:hidden;">'); 415 } 416 417 this.calculateSize(auditObj); 418 419 if (!this.mlszEnabled) { 420 this.loadingLabel.setHeight(this.height); 421 } 422 this.auditId = auditId; 423 this.eventId = eventId; 424 this.noSectors = noSectors; 425 this.isMobile = isMobile; 426 427 this.loadingLabel.showLabel(js_lang.audit_loading_audit); 428 auditObj.addClass('loading'); 429 $('#'+Consts.domIds.sectorsLayer).css('visibility', 'hidden'); 430 $('#'+Consts.domIds.seatsLayer).css('visibility', 'hidden'); 431 432 var data = {}; 433 if (this.dynamic) { 434 this.noSectors = 0; 435 data.dynamic = 1; 436 } 437 if (this.hs !== '') { 438 data.hs = this.hs; 439 } 440 441 var self = this; 442 self.ajaxCallInProgress++; 443 var url = '/auditview/audit/' + self.auditId; 444 $.ajax({ 445 url: url, 446 type: 'get', 447 dataType: 'json', 448 data: data, 449 success: function(data, textStatus, jqXHR) { 450 self.ajaxCallInProgress--; 451 self.loadAuditSuccess(data); 452 }, 453 error: function(jqXHR, textStatus, errorThrown) { 454 self.ajaxCallInProgress--; 455 ErrorManagement.sendError(new Error(0, js_lang.audit_error_loading_audit)); 456 } 457 }); 458 }; 459 460 this.loadAuditSuccess = function(data) { 461 data.mobileFastSelectionEnabled = Seat.mobileFastSelectionEnabled; 462 var loadAuditSuccessEvent = new CustomEvent("loadAuditSuccess", { 463 detail: data 464 }); 465 document.dispatchEvent(loadAuditSuccessEvent); 466 467 //save sector information 468 if (typeof data.snapshot !== 'undefined' && typeof data.snapshot.s !== 'undefined') { 469 for(i=0; i<data.snapshot.s.length; i++) { 470 var sector_id = data.snapshot.s[i].i; 471 var sector_name = data.snapshot.s[i].l.t; 472 var sector_key = 's' + sector_id; 473 sectorData[sector_key] = { 474 id: sector_id, 475 name: sector_name, 476 pricemin: 0, 477 pricemax: 0, 478 free: 0, 479 tooltip: '', 480 graphic: data.snapshot.s[i].t === 2 //sectortype: Fill 481 || (data.snapshot.s[i].t === 1 && data.snapshot.s[i].n === 0) //normal sector without seats 482 } 483 } 484 } 485 486 //store special sectors 487 if (typeof data.specials !== 'undefined' && data.specials.length > 0) { 488 this.hasSpecialSectors = true; 489 this.specialSectors = data.specials; 490 } 491 492 if (typeof data.obstructed_view_icon !== 'undefined' && data.obstructed_view_icon) { 493 this.obstructedIconSet = true; 494 } 495 496 //stage pictures 497 if (typeof data.stage_pictures !== 'undefined' && data.stage_pictures) { 498 this.stagePictures = true; 499 } 500 501 //disable animation if required 502 if ($('body').hasClass('acc-disable-animations')) { 503 this.setAnimation(false); 504 } 505 }; 506 507 this.loadAuditInitialStatus = function() { 508 var self = window.audit; 509 if (self.ajaxCallInProgress > 0) { 510 window.setTimeout(function() { 511 self.loadAuditInitialStatus(); 512 }, 1000); 513 return false; 514 } 515 516 var url = ''; 517 var params = {}; 518 519 if (self.ticketType === 'event' || self.ticketType === 'reservation' || self.ticketType === 'seasonpackage') { 520 url = '/auditview/update'; 521 params = { 522 audit_id: self.auditId, 523 event_id: self.eventId, 524 no_sectors: self.noSectors, 525 sector_ids: [], 526 initial_data: 1 527 }; 528 if (self.programId > 0) { 529 params.program_id = self.programId; 530 } 531 if (self.ticketType === 'reservation') { 532 params.reservation = 1; 533 } else if (self.ticketType === 'seasonpackage') { 534 params.seasonpackage = 1; 535 } 536 if (self.dynamicPrices) { 537 params.dynprice = 1; 538 } 539 } else if (self.ticketType === 'seasonticket') { 540 url = '/seasonticket/audit_update'; 541 params = { 542 venue_id: venue_id, 543 audit_id: self.auditId, 544 season_id: season_id, 545 seasonticket_id: self.eventId, 546 no_sectors: self.noSectors, 547 sector_id: 0, 548 initial_data: 1 549 }; 550 if (audit.isDistributedPackage) { 551 params.distributedp_id = DistributedPackage.getId(); 552 } 553 } else if (self.ticketType === 'freecombined') { 554 url = '/seasonticket/audit_update_freecombined'; 555 params = { 556 venue_id: venue_id, 557 audit_id: self.auditId, 558 season_id: season_id, 559 seasonticket_id: seasonticket_id, 560 event_list: self.eventId, 561 no_sectors: self.noSectors, 562 sector_id: 0, 563 initial_data: 1, 564 seasontickettype: seasontickettype 565 }; 566 FreeCombined.auditload(); 567 } 568 569 if (this.showServiceCharge) { 570 //force service charge 571 params.scen = 1; 572 } 573 if (this.hs !== '') { 574 params.hs = this.hs; 575 } 576 577 if (url !== '') { 578 //valid ticket type 579 if (this.dynamic) { 580 params.dynamic = 1; 581 /*
582 if (!this.auditLoaded) { 583 //on dynamic mode first load must be in sector mode 584 params.sector = 1; 585 } 586 */ 587 } 588 589 self.ajaxCallInProgress++; 590 $.ajax({ 591 url: url, 592 type: 'get', 593 dataType: 'json', 594 data: params, 595 success: function(data, textStatus, jqXHR) { 596 self.ajaxCallInProgress--; 597 data.allSectorsLoaded = self.noSectors; 598 self.loadAuditInitialStatusSuccess(self, data); 599 }, 600 error: function(jqXHR, textStatus, errorThrown) { 601 self.ajaxCallInProgress--; 602 ErrorManagement.sendError(new Error(0, js_lang.audit_error_loading_audit)); 603 }, 604 cache: false 605 }); 606 } else { 607 //invalid ticket type 608 ErrorManagement.sendError(new Error(0, js_lang.audit_error_loading_audit)); 609 } 610 611 return true; 612 }; 613 614 this.loadAuditInitialStatusSuccess = function(self, data) { 615 if (!this.auditLoaded) { 616 if (self.mlszEnabled) { 617 //show delete icons for basket items 618 MLSZAudit.enableDeleteButtons(); 619 } 620 621 if (typeof bestTicketSectors !== 'undefined') { 622 this.bestTicketSectors = bestTicketSectors; 623 } 624 625 //initialize bestTicketSectors 626 if (typeof data.sectorInitialInfos !== 'undefined' && this.bestTicketSectors.length > 0) { 627 this.availableBestTicketSectors = {}; 628 for(var i in this.bestTicketSectors) { 629 var sectorID = this.bestTicketSectors[i]; 630 if (typeof data.sectorInitialInfos[sectorID] !== 'undefined' && data.sectorInitialInfos[sectorID].isFree) { 631 //just available sectors are needed 632 this.availableBestTicketSectors[sectorID] = true; 633 } 634 } 635 636 document.dispatchEvent(new CustomEvent("setBestTicketSectors", { 637 detail: this.availableBestTicketSectors 638 })); 639 } 640 } 641 642 if (self.ticketType === 'freecombined') { 643 FreeCombined.auditloaded(); 644 } else if (self.ticketType === 'seasonticket') { 645 if (typeof data.scen !== 'undefined' && data.scen) { 646 self.showServiceCharge = true; 647 } 648 } 649 650 if (!this.auditLoaded) { 651 //check if audit contains capacity sectors, if required initialize the capacity popup object 652 this.auditLoaded = true; 653 var capacitySectorFound = false; 654 if (typeof data.sectorInitialInfos !== 'undefined') { 655 for(var i in data.sectorInitialInfos) { 656 if (typeof data.sectorInitialInfos[i].priceCatId !== 'undefined' && data.sectorInitialInfos[i].priceCatId) { 657 capacitySectorFound = true; 658 break; 659 } 660 } 661 662 if (Testing.enabled) { 663 Testing.buildSectorList(data.sectorInitialInfos); 664 } 665 } 666 667 if (capacitySectorFound) { 668 self.capacityPopup = new CapacityPopup(); 669 $('#' + Consts.domIds.audit).on('mouseup touchend', function(e) { 670 self.capacityPopup.hide(e, false); 671 }); 672 } 673 } 674 675 //init ticket prices 676 if (typeof data.reverse !== 'undefined' && data.reverse) { 677 TicketGroup.reverse = true; 678 } 679 TicketGroup.init(data.groups, data.sectors, data.groupspecial); 680 681 data.domIds = { 682 sectorsElementId: Consts.domIds.sectorsLayer, 683 seatsElementId: Consts.domIds.seatsLayer 684 }; 685 686 //add sector group color (use owner smallest seat group) 687 var sectorGroups = {}, groupcol=0, sd={}; 688 if (typeof data.sectors !== 'undefined') { 689 $.each(data.sectors, function(sector_id, sector_data) { 690 groupcol = typeof sector_data.groupcol !== 'undefined' ? sector_data.groupcol : 0; 691 sectorGroups[sector_id] = { 692 'groupcolor': groupcol 693 }; 694 }); 695 } 696 data.sectorGroups = sectorGroups; 697 698 var loadAuditInitialStatusSuccessEvent = new CustomEvent("loadAuditInitialStatusSuccess", { 699 detail: data 700 }); 701 document.dispatchEvent(loadAuditInitialStatusSuccessEvent); 702 703 self.basketManager.collect(Consts.domIds.sectorsLayer, Consts.domIds.seatsLayer); 704 705 if (!this.basketProcessing) { 706 $('#'+Consts.domIds.audit).removeClass('loading'); 707 self.loadingLabel.hide(); 708 } else { 709 this.loadingLabel.showLabel(js_lang.label_your_basket_is_currently_in_payment + '<br />' + js_lang.label_goto_basket); 710 } 711 712 $('#audit').addClass('loaded'); 713 $('div#audit-viewer').css({ 714 'visibility': 'visible' 715 }); 716 $('div#audit-viewer').hide(); 717 $('div#audit-viewer').fadeIn(); 718 719 if (self.ticketType === 'seasonticket' || self.ticketType === 'freecombined') {
720 self.startUpdate(); // Handle the frequently automatic update 721 } 722 723 if (typeof data.sectors !== 'undefined') { 724 $.each(data.sectors, function(sector_id, sector_data) { 725 var sector_key = 's' + sector_id; 726 if (typeof sectorData[sector_key] !== 'undefined') { 727 sectorData[sector_key].pricemin = sector_data.min; 728 sectorData[sector_key].pricemax = sector_data.max; 729 if (typeof sector_data.free !== 'undefined') { 730 sectorData[sector_key].free = sector_data.free; 731 } 732 sectorData[sector_key].pricecat_ids = sector_data.pcid; 733 734 if (!TicketGroup.countEnabled && sectorData[sector_key].free === 0) { 735 //when ticketcount is disabled and sector has free seats set count as 1 736 sectorData[sector_key].free = 1; 737 } 738 } 739 }); 740 } 741 742 TicketPriceCategory.updateSelectorPriceCategories(data); 743 if (typeof data.hasSecureSeat !== 'undefined' && data.hasSecureSeat) { 744 TicketGroup.showSecureLabel(); 745 } 746 747 //check obstructed view seat 748 if (this.obstructedIconSet && !this.obstructedIconShowed && typeof data.ticketInitialInfos !== 'undefined') { 749 for(var i in data.ticketInitialInfos) { 750 if (typeof data.ticketInitialInfos[i].is_ov !== 'undefined' && data.ticketInitialInfos[i].is_ov) { 751 $('#obv-seat-label').fadeIn(); 752 this.obstructedIconShowed = true; 753 break; 754 } 755 } 756 } 757 758 if (self.ticketType === 'event' && typeof Config !== 'undefined' && typeof Config.socket !== 'undefined' && Config.socket && parseInt(self.eventId, 10) > 0) { 759 var room_prefix = (typeof Config.socket.room !== 'undefined' && Config.socket.room !== '') ? Config.socket.room : ''; 760 AuditSocket.init(Config.socket.host, Config.socket.port, room_prefix); 761 } 762 }; 763 764 this.setSectorTooltips = function() { 765 this.sectorTooltip = new Tooltip(); 766 var self = this; 767 768 if (!this.seatTooltip.waitingMode) { 769 //standard tooltip 770 document.addEventListener("highlightSector", function (e) { 771 self.sectorTooltip.showSectorsTooltip(e.detail); 772 }); 773 774 document.addEventListener("eliminateHighlight", function (e) { 775 self.sectorTooltip.mouseout(); 776 }); 777 } else { 778 //waiting tooltip 779 document.addEventListener("highlightSector", function (e) { 780 self.sectorTooltip.showSectorsTooltip(e.detail); 781 }); 782 783 document.addEventListener("eliminateHighlight", function (e) { 784 self.sectorTooltip.delayedHide(); 785 }); 786 787 //common for sector and seat 788 var ttobj = $('#'+Consts.domIds.tooltip); 789 $(ttobj).on('mouseover', function() { 790 self.sectorTooltip.clearDelayedHide(); 791 }); 792 $(ttobj).on('mouseout', function() { 793 self.sectorTooltip.delayedHide(); 794 }); 795 } 796 }; 797 798 this.setSeatTooltips = function() { 799 this.seatTooltip = new Tooltip(); 800 var self = this; 801 802 if (!this.seatTooltip.waitingMode) { 803 //standard tooltip 804 document.addEventListener("highlightSeat", function (e) { 805 self.seatTooltip.showSeatsTooltip(e.detail); 806 }); 807 808 document.addEventListener("eliminateHighlight", function (e) { 809 self.seatTooltip.mouseout(); 810 }); 811 } else { 812 //waiting tooltip 813 document.addEventListener("highlightSeat", function (e) { 814 self.seatTooltip.showSeatsTooltip(e.detail); 815 }); 816 817 document.addEventListener("eliminateHighlight", function (e) { 818 self.seatTooltip.delayedHide(); 819 }); 820 } 821 }; 822 823 this.startUpdate = function() { 824 if (!this.isMobile && Config.updateFrequency > 0 && !this.updateInterval === false && !this.dynamic) { 825 this.updateInterval = window.setInterval(this.refreshAudit(), Config.updateFrequency); 826 } 827 }; 828 829 this.refreshAudit = function () { 830 this.refreshCounter = true; 831 var refreshAuditEvent = new CustomEvent("refreshAudit"); 832 document.dispatchEvent(refreshAuditEvent); 833 }; 834 835 this.refreshAuditResult = function (elements) { 836 for (var i=0; i<elements.visibleSectors.length; i++) { 837 this.updateElementList.push({id: elements.visibleSectors[i], request: 'seat'}); 838 } 839 840 this.updateElementList.push({id: elements.sectors, request: 'sector'}); 841 842 for (var i=0; i<elements.dataLoadedSectors.length; i++) { 843 this.updateElementList.push({id: elements.dataLoadedSectors[i], request: 'seat'}); 844 } 845 846 if (!this.updateInProgress) { 847 this.refreshFirstElement(); 848 } 849 }; 850 851 this.refreshSector = function(sectorId, force, seat) { 852 var item = { 853 id: sectorId, 854 request: 'seat', 855 nosnapshot: true 856 }; 857 if (typeof force !== 'undefined' && force === true) { 858 item.force = true; 859 } 860 if (typeof seat !== 'undefined') { 861 item.seat = seat.sector_id + ':' + seat.seat_id; 862 } 863 this.updateElementList.unshift(item); 864 865 if (!this.updateInProgress) { 866 this.refreshFirstElement(); 867 } 868 }; 869 870 this.refreshSectorFast = function(sectorId) { 871 this.statusUpdate(0, [sectorId], 0, true, true, false, null, true); 872 }; 873 874 this.refreshFirstElement = function () { 875 if (this.updateElementList.length > 0) { 876 //update next sector 877 this.updateInProgress = true; 878 var element = this.updateElementList.shift(); 879 var sectors = undefined; 880 var nosnapshot = false;
881 var force = false; 882 var seat = false; 883 if (element.request == 'seat') { 884 sectors = [element.id]; 885 if (typeof element.nosnapshot !== 'undefined' && element.nosnapshot) { 886 nosnapshot = element.nosnapshot; 887 } 888 if (typeof element.force !== 'undefined') { 889 force = element.force; 890 if (force && typeof element.seat !== 'undefined') { 891 seat = element.seat; 892 } 893 } 894 } 895 this.statusUpdate(0, sectors, 0, nosnapshot, false, force, seat); 896 } else { 897 //no next item, updated process was finished 898 this.updateInProgress = false; 899 900 //clear collecting mode 901 if (this.collectingUpdate) { 902 this.collectingUpdate = false; 903 //update all collected sectors together 904 if (this.collectedSectors.length > 0) { 905 var sectors = this.collectedSectors; 906 this.collectedSectors = []; 907 this.statusUpdate(1, sectors); 908 } 909 } 910 911 if (this.refreshCounter) { 912 //update free tickets counter and mini basket 913 this.refreshCounter = false; 914 TicketGroup.countFreeTickets(true); 915 } 916 } 917 }; 918 919 this.statusUpdate = function(initData, sectors, retry, nosnapshot, loading, force, seat, fast) { 920 if (typeof initData === 'undefined') { 921 initData = 0; 922 } 923 if (typeof retry === 'undefined') { 924 retry = 0; 925 } 926 var self = window.audit; 927 if (typeof sectors !== 'undefined') { 928 var ns = 0; 929 } else { 930 sectors = []; 931 var ns = self.noSectors; 932 } 933 if (typeof loading === 'undefined') { 934 loading = false; 935 } 936 if (typeof force === 'undefined') { 937 force = false; 938 } 939 if (typeof fast === 'undefined') { 940 fast = false; 941 } 942 943 var url = ''; 944 var data = {}; 945 946 if (this.ticketType === 'event') { 947 url = '/auditview/update'; 948 data = { 949 audit_id: self.auditId, 950 event_id: self.eventId, 951 no_sectors: ns, 952 sector_ids: sectors, 953 initial_data: initData 954 }; 955 if (force) { 956 data.force = 1; 957 } 958 if (fast) { 959 data.fast = 1; 960 } 961 } else if (this.ticketType === 'seasonticket') { 962 url = '/seasonticket/audit_update'; 963 data = { 964 venue_id: venue_id, 965 audit_id: self.auditId, 966 season_id: season_id, 967 seasonticket_id: self.eventId, 968 no_sectors: ns, 969 initial_data: initData, 970 sector_ids: sectors 971 }; 972 if (this.dynamic) { 973 data.dynamic = 1; 974 } 975 if (force) { 976 data.force = 1; 977 } 978 if (fast) { 979 data.fast = 1; 980 } 981 if (self.isDistributedPackage) { 982 data.distributedp_id = DistributedPackage.getId(); 983 } 984 } 985 if (url === '') { 986 return false; 987 } 988 989 if (this.dynamic && (typeof nosnapshot === 'undefined' || !nosnapshot)) { 990 data.dynamic = 1; 991 } 992 if (self.ticketType === 'reservation') { 993 params.reservation = 1; 994 } 995 if (typeof data.force !== 'undefined' && data.force && typeof seat !== 'undefined') { 996 data.seat = seat; 997 } 998 999 if (this.collectingUpdate && this.updating && sectors.length > 0) { 1000 for(var i=0; i<sectors.length; i++) { 1001 this.collectedSectors.push(sectors[i]); 1002 } 1003 return false; 1004 } 1005 1006 this.updating = true; 1007 if (this.statusUpdateIgnore.length > 0) { 1008 data.ignore = this.statusUpdateIgnore; 1009 self.statusUpdateIgnore = []; 1010 } 1011 1012 if (loading) { 1013 Seat.startLoading(); 1014 } 1015 1016 //check if the updatable sector is bestsector 1017 if (this.mlszEnabled && sectors.length === 1 && this.mlszAuditObjectExists) { 1018 //best - mlsz 1019 var sector_id = sectors[0]; 1020 var sector_not_ignored = typeof data.ignore === 'undefined' || data.ignore.length === 0 || data.ignore.indexOf(sector_id) < 0; 1021 if (sector_not_ignored && MLSZAudit.isBestTicketSector(sector_id, true)) { 1022 //is a best ticket sector 1023 data.bestticket = 1; 1024 } 1025 } else if (this.bestTicketSectors.length > 0 && this.bestTicketObjectExists) { 1026 //best - normal 1027 var sector_id = sectors[0]; 1028 var sector_not_ignored = typeof data.ignore === 'undefined' || data.ignore.length === 0 || data.ignore.indexOf(sector_id) < 0; 1029 if (sector_not_ignored && BestTicket.isBestTicketSector(sector_id, true)) { 1030 //is a best ticket sector 1031 data.bestticket = 1; 1032 } 1033 } 1034 1035 $.ajax({ 1036 url: url, 1037 type: 'get', 1038 dataType: 'json', 1039 data: data, 1040 success: function(data, textStatus, jqXHR) { 1041 self.updating = false;
1042 if (loading) { 1043 Seat.stopLoading(); 1044 } 1045 if (self.dynamic && typeof data.snapshot !== 'undefined') { 1046 self.updateStructure(data.snapshot); 1047 } 1048 self.refreshFirstElement(); 1049 self.statusUpdateSuccess(self, data, fast); 1050 }, 1051 error: function() { 1052 self.updating = false; 1053 if (loading) { 1054 Seat.stopLoading(); 1055 } 1056 if (retry < 3) { 1057 self.statusUpdate(initData, sectors, retry + 1, nosnapshot, loading, force, seat, fast); 1058 } 1059 }, 1060 cache: false 1061 }); 1062 1063 return true; 1064 }; 1065 this.statusUpdateSuccess = function(self, data, fast) { 1066 data.domIds = { 1067 sectorsElementId: Consts.domIds.sectorsLayer, 1068 seatsElementId: Consts.domIds.seatsLayer 1069 }; 1070 1071 var onlyupdate = typeof fast !== 'undefined' && fast; 1072 if (onlyupdate) { 1073 data.onlyupdate = true; 1074 } 1075 var statusUpdateSuccessEvent = new CustomEvent("statusUpdateSuccess", { 1076 detail: data 1077 }); 1078 document.dispatchEvent(statusUpdateSuccessEvent); 1079 1080 self.basketManager.collect(Consts.domIds.sectorsLayer, Consts.domIds.seatsLayer); 1081 1082 if (Testing.enabled && Testing.sectorLoading > 0) { 1083 //collect available seats for testing 1084 var seats = []; 1085 if (typeof data.ticketInitialInfos !== 'undefined') { 1086 for(var seat_id in data.ticketInitialInfos) { 1087 //is an available seat in choosen sector 1088 if (data.ticketInitialInfos[seat_id].status === 0) { 1089 var seat = SeatingChart.getSeat(seat_id); 1090 if (seat && seat.sectorID === Testing.sectorLoading) { 1091 seats.push(parseInt(seat_id, 10)); 1092 } 1093 } 1094 } 1095 } 1096 Testing.builidSeatList(seats); 1097 } 1098 1099 if (typeof data.hasSecureSeat !== 'undefined' && data.hasSecureSeat) { 1100 TicketGroup.showSecureLabel(); 1101 } 1102 1103 if (onlyupdate && SeatingChart.counterFix.active) { 1104 SeatingChart.finishCountFix(); 1105 } 1106 1107 //check obstructed view seat 1108 if (typeof data.ticketInitialInfos !== 'undefined' && this.obstructedIconSet && !this.obstructedIconShowed) { 1109 for(var i in data.ticketInitialInfos) { 1110 if (typeof data.ticketInitialInfos[i].is_ov !== 'undefined' && data.ticketInitialInfos[i].is_ov) { 1111 $('#obv-seat-label').fadeIn(); 1112 this.obstructedIconShowed = true; 1113 break; 1114 } 1115 } 1116 } 1117 1118 //socket update - special sector 1119 if (onlyupdate && AuditSocket.started && typeof data.ticketInfos !== 'undefined' && typeof data.sectorInfos !== 'undefined' 1120 ) { 1121 var sectorIDs = Object.keys(data.sectorInfos); 1122 if (sectorIDs.length === 1) { 1123 AuditSocket.updateSector(parseInt(sectorIDs[0], 10)); 1124 } 1125 } 1126 }; 1127 1128 //update audit structure (adding dynamically) 1129 this.updateStructure = function(snapshot) { 1130 var updateStructureEvent = new CustomEvent("updateStructure", { 1131 detail: snapshot 1132 }); 1133 document.dispatchEvent(updateStructureEvent); 1134 }; 1135 1136 //open capacity selector popup 1137 this.openCapacityPopup = function(sector_id) { 1138 if (this.capacityPopup === false) { 1139 //no capacity popup initialized 1140 return false; 1141 } 1142 1143 if (ProtectedSectors.enabled && ProtectedSectors.codeRequired(sector_id)) { 1144 ProtectedSectors.popup({ 1145 "sector_id": sector_id, 1146 "seat_id": 0, 1147 "capacity": true 1148 }); 1149 return false; 1150 } 1151 1152 var j = $('div#Bsectors > input#sector_' + sector_id); 1153 1154 if ($(j).size() !== 1) { 1155 //no sector data found 1156 return false; 1157 } 1158 1159 var price = $(j).attr('data-price'); 1160 if (typeof price === 'undefined') { 1161 //invalid sector info 1162 return false; 1163 } 1164 1165 var pricecatid = $(j).attr('data-pricecatid'); 1166 if (typeof pricecatid === 'undefined') { 1167 //invalid sector info 1168 return false; 1169 } 1170 1171 var price = parseFloat($(j).attr('data-price')); 1172 var ticketprice = parseFloat($(j).attr('data-ticketprice')); 1173 var pricecatid = parseInt($(j).attr('data-pricecatid'), 10) ; 1174 var self = this; 1175 var e = null; 1176 1177 //small waiting to load cursor position first 1178 startShowCapacity = true; 1179 setTimeout(function() { 1180 self.capacityPopup.showWithDatas( 1181 price, pricecatid, 1182 { 1183 "press_ok" : function(number) { 1184 //check ajax calls under process 1185 if (self.ajaxCallInProgress > 0) { 1186 window.setTimeout(function() { 1187 self.capacityPopup.button_ok.triggerHandler('click'); 1188 }, 1000); 1189 return false;
1190 } 1191 1192 //check quantity 1193 number = parseInt(number); 1194 if (isNaN(number) || number < 1 || number > 40) { 1195 revDialog({ 1196 content: js_lang.audit_max_capacity_tickets, 1197 rightButton: { 1198 label: js_lang.interface_bmit, 1199 class: 'dark', 1200 close: true 1201 } 1202 }); 1203 return false; 1204 } 1205 1206 //preparte ticket selecting parameters 1207 var postData = { 1208 event_id: self.eventId, 1209 sector_id: sector_id, 1210 pricecat_id: pricecatid, 1211 price: ticketprice, 1212 quantity: number 1213 }; 1214 if (self.showServiceCharge) { 1215 postData.service_charge = Math.max(0, price - ticketprice); 1216 } 1217 if (self.ticketType === 'seasonticket') { 1218 postData = { 1219 audit_id: self.auditId, 1220 event_id: self.eventId, 1221 type: 1, 1222 operation: 0, 1223 sector_id: sector_id, 1224 pricecat_id: pricecatid, 1225 price: price, 1226 quantity: number 1227 }; 1228 } else if (self.ticketType === 'seasonpackage') { 1229 postData.audit_id = self.auditId; 1230 } 1231 1232 //select tickets from a capacity sector 1233 Seat.selectCapacity(postData, j); 1234 1235 //hide capacity selector popup 1236 self.capacityPopup.hide(null, true); 1237 return true; 1238 } 1239 } 1240 ); 1241 }, 50); 1242 1243 return true; 1244 }; 1245 1246 //update seat status on a best ticket sector 1247 this.updateBestTicketSector = function(sector_id, tickets_data) { 1248 document.dispatchEvent(new CustomEvent("updateSectorSeatStatus", { detail: { 1249 'sectorID': sector_id, 1250 'ticketsData': tickets_data 1251 }})); 1252 }; 1253 1254 //change animation status (like seat clicked and seat status changed) 1255 this.setAnimation = function(enabled) { 1256 document.dispatchEvent(new CustomEvent("sendActionToSeatingChart", { detail: { 1257 'action': 'setAnimation', 1258 'params': { 1259 'enabled': enabled 1260 } 1261 }})); 1262 }; 1263} 1264 1265//ticket price groups 1266var TicketGroup = { 1267 countEnabled: true, 1268 categoryTooltipEnabled: true, 1269 1270 //list of categories (price, color, count, index) 1271 list: {}, 1272 listIndexed: {}, 1273 firstLoad: true, 1274 reverse: false, 1275 1276 //list of sectors for each price group 1277 sectors: {}, 1278 1279 //list of selected(highlighted) groups 1280 filtered: [], 1281 locked: [], 1282 filteredSectors: [], 1283 1284 //category list container 1285 catListObj: false, 1286 1287 //delayed unselect 1288 delayData: { 1289 unselectTime: 300, //0=disable 1290 timeOut: false, //setTimeout object 1291 groupId: 0 //group 1292 }, 1293 1294 //initialize ticket price groups and sectors 1295 init: function(groups, sectors, sepcialcolors) { 1296 if (typeof ticketcount_disable !== 'undefined' && ticketcount_disable === true) { 1297 this.countEnabled = false; 1298 } 1299 1300 //init list 1301 if (typeof groups !== 'undefined') { 1302 this.list = groups; 1303 } 1304 1305 //build group list 1306 this.catListObj = $('div.ticket-categories > ul'); 1307 if (this.catListObj.length === 0) { 1308 //if group list object not found, create a hidden object 1309 var tempdiv = $('<div class="ticket-categories" style="display:none;">'); 1310 var tempul = $('<ul>'); 1311 $(tempdiv).append(tempul); 1312 $('body').append(tempdiv); 1313 this.catListObj = tempdiv; 1314 } 1315 var catlist_parent = $(this.catListObj).parent(); 1316 1317 //create price cateogory list 1318 $(catlist_parent).hide(); 1319 1320 if (!audit.showServiceCharge) { 1321 this.categoryTooltipEnabled = false; 1322 this.clearStatusBar(); 1323 } 1324 1325 var cssstyle = this.buildPriceList(false); 1326 $(catlist_parent).fadeIn(); 1327 1328 //add css styles for price category 1329 if (cssstyle !== '') { 1330 $(catlist_parent).append('<style>' + cssstyle + '</style>'); 1331 } 1332 1333 //init sector list for each price group 1334 if (typeof sectors !== 'undefined') { 1335 TicketGroup.sectors = {}; 1336 $.each(sectors, function(sector_id, data) { 1337 if (typeof data.groups !== 'undefined') { 1338 for(var i=0; i<data.groups.length; i++) { 1339 var group_id = data.groups[i]; 1340 if (typeof TicketGroup.sectors[group_id] === 'undefined') { 1341 TicketGroup.sectors[group_id] = []; 1342 } 1343 TicketGroup.sectors[group_id].push(sector_id); 1344 } 1345 } 1346 }); 1347 } 1348 1349 //add special colors 1350 if (typeof sepcialcolors !== 'undefined') { 1351 $.each(sepcialcolors, function(group, colors) { 1352 var listelement = $('<input id="special-' + group + '" type="hidden">'); 1353 $(listelement).val(colors.color); 1354 $(listelement).attr('data-lowcolor', colors.lowcolor); 1355 $(catlist_parent).append(listelement); 1356 }); 1357 } 1358 1359 if (!this.countEnabled) { 1360 //remove counter html objects from price category list 1361 $('> li > span.ticketcount', this.catListObj).remove(); 1362 } 1363 1364 //count free tickets 1365 this.countFreeTickets(); 1366 }, 1367 1368 //update groups (for dynamic prices) 1369 update: function(groups, sectors) { 1370 //clear filters 1371 if (this.filtered.length > 0) { 1372 this.filtered = []; 1373 this.locked = []; 1374 this.updateFilter(); 1375 } 1376 1377 //update price groups 1378 this.list = groups; 1379 1380 //update sector groups 1381 this.sectors = {}; 1382 $.each(sectors, function(sector_id, data) { 1383 if (typeof data.groups !== 'undefined') { 1384 for(var i=0; i<data.groups.length; i++) { 1385 var group_id = data.groups[i]; 1386 if (typeof TicketGroup.sectors[group_id] === 'undefined') { 1387 TicketGroup.sectors[group_id] = []; 1388 } 1389 TicketGroup.sectors[group_id].push(sector_id); 1390 } 1391 } 1392 }); 1393 1394 if (this.catListObj.length === 1) { 1395 var catlist_parent = $(this.catListObj).parent(); 1396 var cssstyle = this.buildPriceList(true); 1397 $('style', catlist_parent).html(cssstyle); 1398 } 1399 }, 1400 1401 //clreate price category list design 1402 buildPriceList: function(update) { 1403 var list_sample = $.trim($('div#ticket-category-sample').html()); 1404 if (!list_sample) { 1405 //default price group item sample 1406 list_sample = '%price%<span style="display:none"> - <span class="count">%count%</span> ' + js_lang.label_pcs + '</span>'; 1407 } 1408 1409 var cssstyle = ''; 1410 $(this.catListObj).empty(); 1411 TicketGroup.listIndexed = {}; 1412 1413 var groupPosition = 0; 1414 $.each(this.list, function(price, group) { 1415 TicketGroup.listIndexed[group.index] = price; 1416 var classname = 'ticketpricecat' + group.index; 1417 var listelement, text; 1418 1419 listelement = $('<li>').addClass('seat-available').addClass(classname).attr('id', 'grp' + group.index); 1420 $(listelement).data('price', group.price).data('type', 'seat'); 1421 $(listelement).attr('data-color', group.color).attr('data-lowcolor', group.lowcolor).data('group', group.index); 1422 1423 var price_str = /*audit.showServiceCharge ? group.sum_price_str :*/ group.price; 1424 text = list_sample.replace('%price%', price_str).replace('%count%', group.count); 1425 $(listelement).html(text); 1426 1427 if (TicketGroup.categoryTooltipEnabled) { 1428 groupPosition++; 1429 var toolTipContent = TicketGroup.getTooltipContent(groupPosition, group); 1430 $(listelement).attr('title', toolTipContent); 1431 } 1432 1433 if (!TicketGroup.reverse) { 1434 //prices asc. order 1435 $(TicketGroup.catListObj).append(listelement); 1436 } else { 1437 //prices desc. order 1438 $(TicketGroup.catListObj).prepend(listelement); 1439 } 1440 cssstyle += 'div.ticket-categories li.seat-available.' + classname + ':before { background-color: ' + group.color + '; } '; 1441 }); 1442 1443 if (update && this.countEnabled) { 1444 $('li > span', this.catListObj).show(); 1445 } 1446 1447 if (TicketGroup.categoryTooltipEnabled) { 1448 setTimeout(function() { 1449 $('li', TicketGroup.catListObj).qtip({ 1450 style: {classes: 'dynClass'}, 1451 content: { 1452 /*title: {text: js_lang.label_price_kategory},*/ 1453 content: { text: $(this).attr('title') } 1454 }, 1455 position: { 1456 at: "left center", 1457 my: "right center", 1458 viewport: $(window) 1459 }, 1460 tip: true 1461 }); 1462 }, 200); 1463 } 1464 1465 return cssstyle; 1466 }, 1467 1468 //generate tooltip content for a price category 1469 getTooltipContent: function(position, group) { 1470 return '<div class="tip-title"> <span style="background-color:' + group.color + '"></span> ' + position + '. ' + js_lang.label_price_kategory.toLowerCase() + ' </div>' 1471 + '<div class="tip-table">' 1472 + '<div> <span class="tooltipTextLeft">
1472' + js_lang.audit_price + ':</span> <span class="tooltipTextRight">' + group.price + '</span> </div>' 1473 + '<div> <span class="tooltipTextLeft">' + js_lang.basket_lang_basket_syscharge + ':</span> <span class="tooltipTextRight">' + group.service_charge_str + '</span> </div>' 1474 + '<div> <span class="tooltipTextLeft">' + js_lang.audit_final_price + ':</span> <span class="tooltipTextRight">' + group.sum_price_str + '</span> </div>' 1475 + '</div>'; 1476 }, 1477 1478 //count free tickets for current event 1479 countFreeTickets: function(loadBasketData) { 1480 if (audit.ticketType === 'event' || audit.ticketType === 'reservation' || audit.ticketType === 'seasonpackage') { 1481 if (typeof loadBasketData === 'undefined') { 1482 loadBasketData = false; 1483 } 1484 var seasonpackage_mode = audit.ticketType === 'seasonpackage' ? 1 : 0; 1485 1486 var event_id = audit.eventId; 1487 if (typeof event_id !== 'undefined' && event_id) { 1488 var params = { 1489 'event_id': event_id, 1490 'basket': loadBasketData ? 1 : 0 1491 }; 1492 if (seasonpackage_mode) { 1493 params.sp = seasonpackage_mode; 1494 } 1495 if (audit.dynamicPrices) { 1496 params.dynprice = 1; 1497 } 1498 if (audit.hs !== '') { 1499 params.hs = audit.hs; 1500 } 1501 1502 if (TicketGroup.countEnabled || loadBasketData || audit.dynamicPrices || seasonpackage_mode || Testing.enabled) { 1503 //update ticket count data via ajax 1504 $.ajax({ 1505 url: '/auditview/ticketcount', 1506 type: 'post', 1507 dataType: 'json', 1508 data: params, 1509 cache: false, 1510 1511 success: function(data, textStatus, jqXHR) { 1512 if (typeof data.success !== 'undefined' && data.success) { 1513 //update price categories 1514 if (typeof data.prices !== 'undefined') { 1515 $.each(data.prices, function(price, count) { 1516 if (typeof TicketGroup.list[price] !== 'undefined') { 1517 if (!TicketGroup.firstLoad) { 1518 //reset counter to zero on audit update 1519 TicketGroup.list[price]['count'] = 0; 1520 } 1521 1522 if (TicketGroup.countEnabled) { 1523 TicketGroup.changeTicketCounter(price, count); 1524 $('li.ticketpricecat' + TicketGroup.list[price]['index'] + ' > span', TicketGroup.catListObj).fadeIn(); 1525 } 1526 } 1527 }); 1528 } 1529 1530 //update mini basket 1531 if (loadBasketData && typeof data.basket !== 'undefined') { 1532 if (data.basket) { 1533 //basket has item(s) 1534 updateMiniBasket(data.basket.basketTime, data.basket.basketArray, data.basket.productCount, data.basket.priceTotalSum); 1535 } else { 1536 //basket is empty 1537 updateMiniBasket(0, {}, 0, 0); 1538 } 1539 } 1540 1541 //update sectors free ticket count 1542 if (typeof data.sector !== 'undefined' && data.sector) { 1543 $.each(data.sector, function(sector_id, free_tickets) { 1544 var sector_key = 's' + sector_id; 1545 if (typeof sectorData[sector_key] !== 'undefined') { 1546 sectorData[sector_key].free = free_tickets; 1547 } 1548 }); 1549 if (Testing.enabled) { 1550 Testing.setSectorFreeTickets(data.sector); 1551 } 1552 } 1553 1554 //hide unavailable prices on seasonpackage 1555 if (seasonpackage_mode) { 1556 $('div.ticket-categories li.seat-available').each(function() { 1557 if (!$('span', $(this)).is(':visible')) { 1558 $(this).slideUp(); 1559 } 1560 }); 1561 } 1562 } 1563 1564 if (TicketGroup.firstLoad) { 1565 TicketGroup.firstLoad = false; 1566 } 1567 } 1568 }); 1569 } else { 1570 if (TicketGroup.firstLoad) { 1571 TicketGroup.firstLoad = false; 1572 } 1573 } 1574 } 1575 } else { 1576 $('li > span.ticketcount', this.catListObj).fadeIn(); 1577 } 1578 }, 1579 1580 //increase counter for a group by price 1581 increaseTicket: function(price) { 1582 this.changeTicketCounter(price, 1); 1583 }, 1584 1585 //decrease counter for a group by price 1586 decreaseTicket: function(price) { 1587 this.changeTicketCounter(price, -1); 1588 }, 1589 1590 //change counter for a group by ticket price 1591 changeTicketCounter: function(price, diff) { 1592 if (this.countEnabled && typeof this.list[price] !== 'undefined') { 1593 var new_count = this.list[price]['count'] + diff; 1594 this.list[price]['count'] = new_count; 1595 $('li.ticketpricecat' + this.list[price]['index'] + ' span.count', this.catListObj).text(Math.max(0, new_count)); 1596 } 1597 }, 1598 1599 //highlight a group 1600 select: function(group_id) { 1601 this.checkDelay(); 1602 this.changeSelection(group_id, true, false); 1603 }, 1604 1605 //unhighlight a group 1606 unselect: function(group_id) { 1607 if (this.delayData.unselectTime > 0) { 1608 //delayed unselect 1609 TicketGroup.delayData.groupId = group_id; 1610 this.delayData.timeOut = setTimeout(function() { 1611 TicketGroup.delayedUnselect(); 1612 }, TicketGroup.delayData.unselectTime); 1613 } else { 1614 //instant unselect 1615 this.changeSelection(group_id, false, false); 1616 } 1617 }, 1618 1619 //locked toggle selection 1620 toggleHoldSelection: function(group_id) { 1621 this.checkDelay(); 1622 var add = this.locked.indexOf(group_id) < 0 ? true : false;
1623 this.changeSelection(group_id, add, true); 1624 }, 1625 1626 //delayed unselect: check if is in progress and stop it 1627 checkDelay: function() { 1628 if (this.delayData.unselectTime > 0 && this.delayData.timeOut !== false) { 1629 clearTimeout(this.delayData.timeOut); 1630 this.delayedUnselect(); 1631 } 1632 }, 1633 1634 //delayed unselect: the process 1635 delayedUnselect: function() { 1636 this.delayData.timeOut = false; 1637 this.changeSelection(this.delayData.groupId, false, false); 1638 }, 1639 1640 //(un)highlight a group 1641 changeSelection: function(group_id, add, hold) { 1642 if (typeof this.listIndexed[group_id] !== 'undefined') { 1643 //mark hold property 1644 if (hold) { 1645 var categoryObj = $('li#grp' + group_id, this.catListObj); 1646 if (add) { 1647 this.locked.push(group_id); 1648 if (this.locked.length > 20) { 1649 this.clearLocked(); 1650 } 1651 $(categoryObj).addClass('hold').addClass('highlighted'); 1652 } else { 1653 var group_position = this.locked.indexOf(group_id); 1654 this.locked[group_position] = -1; 1655 $(categoryObj).removeClass('hold').removeClass('highlighted'); 1656 } 1657 } 1658 1659 //build next selection (filtered groups) 1660 var filter_changed = false; 1661 if (add) { 1662 if (this.filtered.indexOf(group_id) < 0) { 1663 //add group to filtered list if not exists 1664 this.filtered.push(group_id); 1665 filter_changed = true; 1666 } 1667 } else { 1668 if (this.locked.indexOf(group_id) < 0) { 1669 //remove group from filtered list 1670 var temp = []; 1671 for(var i=0; i<this.filtered.length; i++) { 1672 if (this.filtered[i] != group_id) { 1673 temp.push(this.filtered[i]); 1674 } else { 1675 filter_changed = true; 1676 } 1677 } 1678 this.filtered = temp; 1679 } 1680 } 1681 1682 if (filter_changed) { 1683 this.updateFilter(); 1684 } 1685 } 1686 }, 1687 1688 //clear locked list: remove "-1" elements 1689 clearLocked: function() { 1690 var temp = []; 1691 for(var i=0; i<this.locked.length; i++) { 1692 if (this.locked[i] >= 0) { 1693 temp.push(this.locked[i]); 1694 } 1695 } 1696 this.locked = temp; 1697 }, 1698 1699 //send new group filters to audit viewer 1700 updateFilter: function() { 1701 var params = { 1702 groups: TicketGroup.filtered, 1703 sectors: TicketGroup.getSectorsByGroups(TicketGroup.filtered), 1704 filteredSectors: TicketGroup.filteredSectors 1705 }; 1706 var updateFilteredGroupsEvent = new CustomEvent("updateFilteredGroupsEvent", { 1707 detail: params 1708 }); 1709 document.dispatchEvent(updateFilteredGroupsEvent); 1710 }, 1711 1712 //collect sectors contains some specified groups 1713 getSectorsByGroups: function(group_list) { 1714 var sectors = []; 1715 for(var i=0; i<group_list.length; i++) { 1716 if (typeof this.sectors[group_list[i]] !== 'undefined') { 1717 var sector_list = this.sectors[group_list[i]]; 1718 for(var j=0; j<sector_list.length; j++) { 1719 var sector_id = parseInt(sector_list[j], 10); 1720 if (sectors.indexOf(sector_id) < 0) { 1721 sectors.push(sector_id); 1722 } 1723 } 1724 } 1725 } 1726 return sectors; 1727 }, 1728 1729 //get prices for a sector 1730 getSectorPrices: function(sector_id) { 1731 var list = []; 1732 sector_id = $.trim(sector_id); 1733 $.each(TicketGroup.sectors, function(group_index, sector_list) { 1734 if (sector_list.indexOf(sector_id) > -1) { 1735 if (typeof TicketGroup.listIndexed[group_index] !== 'undefined') { 1736 var group_id = TicketGroup.listIndexed[group_index]; 1737 if (typeof TicketGroup.list[group_id] !== 'undefined') { 1738 var group = TicketGroup.list[group_id]; 1739 group.pricenum = group_id; 1740 list.push(group); 1741 } 1742 } 1743 } 1744 }); 1745 return list; 1746 }, 1747 1748 //return price group index by ticket price 1749 getGroupIndexByPrice: function(price) { 1750 return typeof this.list[price] !== 'undefined' ? this.list[price].index : false; 1751 }, 1752 1753 //display secure seat label when audit has secure seat 1754 showSecureLabel: function() { 1755 $('#secure-seat-label').fadeIn(); 1756 }, 1757 1758 //clear selected seats status bar - show only ticket price (without service and total) 1759 clearStatusBar: function() { 1760 $('div.ticket-prices').each(function() { 1761 const $divs = $('>div', this); 1762 if ($divs.length === 3) { 1763 $divs.slice(1).hide(); 1764 } 1765 }); 1766 } 1767}; 1768 1769function DivLabel(divId) { 1770 var loadingDiv = $('#'+divId); 1771 var loadingDivTxt = $('#'+divId+' > span'); 1772 this.showLabel = function(label) { 1773 if (label) { 1774 loadingDivTxt.html(label); 1775 } 1776 loadingDiv.fadeIn(200); 1777 }; 1778 this.hide = function() { 1779 loadingDiv.hide(); 1780 }; 1781 this.setHeight = function(h) { 1782 loadingDiv.height(h); 1783 loadingDivTxt.css('margin-top', ((h-100)/2)+'px'); 1784 }; 1785} 1786 1787function Error(errorCode,localizedMessage){ 1788 this.errorCode = errorCode; 1789 this.localizedMessage = localizedMessage; 1790} 1791 1792var ErrorManagement = { 1793 customErrors: { 1794 e1: js_lang.label_recommended_tickets_no_delete_warning 1795 }, 1796
1797 sendErrorMessage: function(error_code) { 1798 if (typeof this.customErrors[error_code] !== 'undefined') { 1799 this.sendError(new Error(0, this.customErrors[error_code])); 1800 } 1801 }, 1802 1803 //open error message popup 1804 sendError: function(error) { 1805 switch (error.errorCode) { 1806 case 10003: 1807 revDialog({ 1808 title: js_lang.audit_error_popup_title, 1809 content: error.localizedMessage, 1810 rightButton: { 1811 label: js_lang.admin_bmit, 1812 href: document.location.href+'?force_arrival=1', 1813 close: true, 1814 class: 'dark' 1815 } 1816 }); 1817 break; 1818 1819 case 99: //default with page reload 1820 var reload_url = document.location.href; 1821 var hash_pos = reload_url.indexOf('#'); 1822 if (hash_pos > 0) { 1823 reload_url = reload_url.substring(0, hash_pos); 1824 } 1825 revDialog({ 1826 title: js_lang.audit_error_popup_title, 1827 content: error.localizedMessage, 1828 rightButton: { 1829 label: js_lang.admin_bmit, 1830 href: reload_url, 1831 close: true, 1832 class: 'dark' 1833 } 1834 }); 1835 break; 1836 1837 case 1234: // just a warning 1838 revDialog({ 1839 title: js_lang.label_attention, 1840 content: error.localizedMessage, 1841 rightButton: { 1842 label: js_lang.admin_bmit, 1843 close: true, 1844 class: 'dark' 1845 } 1846 }); 1847 break; 1848 1849 default: 1850 revDialog({ 1851 title: js_lang.audit_error_popup_title, 1852 content: error.localizedMessage, 1853 rightButton: { 1854 label: js_lang.admin_bmit, 1855 close: true, 1856 class: 'dark' 1857 } 1858 }); 1859 break; 1860 } 1861 } 1862}; 1863 1864document.addEventListener("loadAuditError", function () { 1865 ErrorManagement.sendError(new Error(0, js_lang.audit_error_loading_audit)); 1866}); 1867 1868document.addEventListener("seatEvent", function (e) { 1869 Seat.click(e.detail.method, e.detail.seat); 1870}); 1871 1872document.addEventListener("elementsResult", function (e) { 1873 audit.refreshAuditResult(e.detail); 1874}); 1875 1876document.addEventListener("openCapacityEvent", function (e) { 1877 audit.openCapacityPopup(e.detail.sector_id); 1878}); 1879 1880document.addEventListener("auditLoadedEvent", function (e) { 1881 if (!audit.noSectors) { 1882 audit.noSectors = e.detail.nosectors; 1883 } 1884 audit.loadAuditInitialStatus(); 1885}); 1886 1887document.addEventListener("syncSeatListEvent", function (e) { 1888 SeatingChart.seatList = e.detail.list; 1889 SeatingChart.seatOrderList = e.detail.order; 1890}); 1891 1892document.addEventListener("seatingChartError", function (e) { 1893 var error_code = typeof e.detail !== 'undefined' ? e.detail : ''; 1894 if (error_code !== '') { 1895 ErrorManagement.sendErrorMessage(error_code); 1896 } 1897}); 1898 1899var Sector = { 1900 //return sector information 1901 get: function(sector_id) { 1902 var obj = $('div#Bsectors input#sector_' + sector_id); 1903 if ($(obj).size() !== 1) { 1904 return false; 1905 } 1906 1907 return { 1908 id: sector_id, 1909 is_free: $(obj).attr('data-isfree') === '1', 1910 selected: $(obj).attr('data-inbasket') !== '0' 1911 }; 1912 }, 1913 1914 //check if a sector has available tickets 1915 isAvailable: function(sector_id) { 1916 var item = this.get(sector_id); 1917 if (!item) { 1918 return false; 1919 } 1920 return item.is_free || item.selected; 1921 } 1922}; 1923 1924var Seat = { 1925 seatKeys: false, 1926 seatRows: {}, 1927 1928 collectMode: false, 1929 collection: {}, 1930 collectionObj: false, 1931 1932 //mobile fast selection 1933 mobileFastSelectionEnabled: false, 1934 1935 //enable mobile fast selection: on tap/click 1936 mobileFastSelection: function() { 1937 this.mobileFastSelectionEnabled = true; 1938 }, 1939 1940 //click event for seats 1941 click: function(method, seat) { 1942 if (method === 'add') { 1943 this.select(seat); 1944 } else if (method === 'remove') { 1945 this.unselect(seat); 1946 } else { 1947 this.fail(); 1948 } 1949 }, 1950 1951 //select a seat 1952 select: function(seat) { 1953 if (this.collectMode) { 1954 //no really seat selection just collect them 1955 this.collect(true, seat); 1956 this.feedback(true); 1957 return true; 1958 } 1959 1960 var inSpecialSector = audit.hasSpecialSectors 1961 && audit.specialSectors.indexOf(seat.sector_id) >= 0 1962 && audit.ticketType === 'event'; 1963 1964 //solo seat check (special sectors ignored) 1965 if (Config.soloSeatProtection && !inSpecialSector && !this.checkSelectSoloSeat(seat)) { 1966 audit.seatTooltip.hide(); 1967 setTimeout(function() { 1968 ErrorManagement.sendError(new Error(0, js_lang.audit_error_no_solo_seat)); 1969 }, 50); 1970 this.feedback(false); 1971 return false;
1972 } 1973 1974 //linear seat check (special sectors ignored) 1975 if (Config.linearSeatProtection && !inSpecialSector && !this.checkSelectLinearSeat(seat)) { 1976 audit.seatTooltip.hide(); 1977 setTimeout(function() { 1978 ErrorManagement.sendError(new Error(0, js_lang.audit_error_linear_seat)); 1979 }, 50); 1980 this.feedback(false); 1981 return false; 1982 } 1983 1984 //check seat status - must be free 1985 if (!this.seatStatus(seat.seat_id, Consts.statusIds.empty)) { 1986 this.feedback(false); 1987 return false; 1988 } 1989 1990 //wc must be confirmed 1991 if (seat.iswc && !confirm(js_lang.audit_wheelchair_confirm)) { 1992 this.feedback(false); 1993 return false; 1994 } 1995 1996 if (ProtectedSectors.enabled && ProtectedSectors.codeRequired(seat.sector_id)) { 1997 this.feedback(false); 1998 ProtectedSectors.popup(seat); 1999 return false; 2000 } 2001 2002 //distributed package - select permission 2003 if (audit.isDistributedPackage && !DistributedPackage.canSelectSeat(true)) { 2004 return false; 2005 } 2006 2007 //initalize request 2008 var url = ''; 2009 var postData = {}; 2010 2011 if (audit.ticketType === 'event') { 2012 //standard event (default) 2013 var seatElement = SeatingChart.getSeat(seat.seat_id); 2014 url = '/auditview/select_seat'; 2015 postData = { 2016 event_id: audit.eventId, 2017 seat_id: seat.seat_id, 2018 ticket_id: seat.ticket_id, 2019 sector_id: seat.sector_id 2020 }; 2021 if (audit.showServiceCharge) { 2022 postData.price = seatElement.price; 2023 postData.service_charge = audit.basketManager.getServiceCharge(1, seatElement.price); 2024 } 2025 } else if (audit.ticketType === 'seasonticket') { 2026 //simple season ticket 2027 var seatElement = SeatingChart.getSeat(seat.seat_id); 2028 url = '/seasonticket/audit_select_seat'; 2029 postData = { 2030 venue_id: venue_id, 2031 audit_id: audit.auditId, 2032 //event_id: self.eventId, 2033 seasonticket_id: audit.eventId, 2034 season_id: season_id, 2035 operation: 0, // 0 hozzaad 1 torol 2036 pricecat_id: seatElement.pricecatID, 2037 seat_id: seat.seat_id, 2038 sector_id: seat.sector_id, 2039 ticket_id: seat.ticket_id, 2040 type: 0 // 0 sima 1 kapacitasos 2041 }; 2042 if (audit.showServiceCharge) { 2043 postData.price = seatElement.price; 2044 postData.service_charge = audit.basketManager.getServiceCharge(1, seatElement.price); 2045 }
2046 if (audit.isDistributedPackage) { 2047 if (!DistributedPackage.canSelectSeat(true)) { 2048 return false; 2049 } 2050 postData.distributedp_id = DistributedPackage.getId(); 2051 if (typeof postData.price === 'undefined') { 2052 postData.price = seatElement.price; 2053 } 2054 } 2055 } else if (audit.ticketType === 'freecombined') { 2056 //free combined season ticket 2057 var seatElement = SeatingChart.getSeat(seat.seat_id); 2058 url = '/seasonticket/audit_select_freecombined_seat'; 2059 postData = { 2060 venue_id: venue_id, 2061 audit_id: audit.auditId, 2062 event_id: audit.eventId, 2063 seasonticket_id: seasonticket_id, 2064 season_id: season_id, 2065 operation: 0, // 0 hozzaad 1 torol 2066 pricecat_id: seatElement.pricecatID, 2067 seat_id: seat.seat_id, 2068 sector_id: seat.sector_id, 2069 ticket_id: seat.ticket_id, 2070 type: 0, // 0 sima 1 kapacitasos 2071 seasontickettype: seasontickettype 2072 }; 2073 } else if (audit.ticketType === 'reservation') { 2074 //reservation 2075 var seatElement = SeatingChart.getSeat(seat.seat_id); 2076 var TSeventID = typeof tsevent_id !== 'undefined' ? tsevent_id : 0; 2077 2078 url = '/reservation/ticketoperation'; 2079 postData = { 2080 audit_id: audit.auditId, 2081 event_id: audit.eventId, 2082 operation: 0, // 0 hozzaad 1 torol 2083 pricecat_id: seatElement.pricecatID, 2084 seat_id: seat.seat_id, 2085 sector_id: seat.sector_id, 2086 ticket_id: seat.ticket_id, 2087 type: 0, // 0 sima 1 kapacitasos 2088 tsevent_id: TSeventID 2089 }; 2090 } else if (audit.ticketType === 'seasonpackage') { 2091 //season pachage 2092 url = '/seasonpackage/select_seat'; 2093 postData = { 2094 event_id: audit.eventId, 2095 seat_id: seat.seat_id, 2096 ticket_id: seat.ticket_id, 2097 sector_id: seat.sector_id 2098 }; 2099 } 2100 2101 if (url === '') { 2102 //invalid tickettype 2103 ErrorManagement.sendError(new Error(0, js_lang.unsuccessful_reservation)); 2104 this.feedback(false); 2105 return false; 2106 } 2107 2108 //send request 2109 var self = this; 2110 this.startLoading(); 2111 2112 $.ajax({ 2113 url: url, 2114 type: 'get', 2115 data: postData, 2116 dataType: 'json', 2117 cache: false, 2118 2119 success: function(data) { 2120 self.stopLoading(); 2121 if (data.result) { 2122 self.finalizeSeatSelection('add', seat.seat_id, data, inSpecialSector ? seat.sector_id : 0); 2123 if (audit.ticketType === 'seasonpackage') { 2124 SPBasketExpire.addItemsToSelections(1); 2125 if (typeof data.spbasket !== 'undefined') { 2126 SPBasketExpire.updateExpireTime(data.spbasket.time); 2127 } 2128 } 2129 if (typeof data.warning == 'string') { 2130 ErrorManagement.sendError(new Error(1234, data.warning)); 2131 } 2132 if (audit.ticketType === 'seasonticket' && audit.isDistributedPackage) { 2133 DistributedPackage.increaseSelections(1); 2134 var thisprice = 0; 2135 if (typeof postData.price !== 'undefined') { 2136 thisprice += postData.price; 2137 } 2138 if (typeof postData.service_charge !== 'undefined') { 2139 thisprice += postData.service_charge; 2140 } 2141 DistributedPackage.updatePriceDisplay(DistributedPackage.status.current_price + thisprice); 2142 } 2143 } else { 2144 var errorcode = (typeof data.reload === 'undefined' || !data.reload) ? 0 : 99; 2145 ErrorManagement.sendError(new Error(errorcode, data.error.length ? data.error : js_lang.unsuccessful_reservation)); 2146 var noRefresh = typeof (data.auditUpdate) !== 'undefined' && data.auditUpdate === false; 2147 if (audit.ticketType !== 'freecombined' && !noRefresh) { 2148 audit.refreshSector(seat.sector_id, true, seat); 2149 } 2150 2151 //send feedback to audit viewer (fail) 2152 self.feedback(false); 2153 } 2154 }, 2155 2156 error: function(jqXHR, textStatus, errorThrown) { 2157 self.stopLoading(); 2158 ErrorManagement.sendError(new Error(0, js_lang.unsuccessful_reservation)); 2159 2160 //send feedback to audit viewer (fail) 2161 self.feedback(false); 2162 } 2163 }); 2164 2165 return true; 2166 }, 2167 2168 //unselect the seat 2169 unselect: function(seat) { 2170 if (this.collectMode) { 2171 //no really seat unselection just collect selected seats 2172 this.collect(false, seat); 2173 this.feedback(true); 2174 return true; 2175 } 2176 2177 var inSpecialSector = audit.hasSpecialSectors 2178 && audit.specialSectors.indexOf(seat.sector_id) >= 0 2179 && audit.ticketType === 'event'; 2180 2181 if (Config.soloSeatProtection && !inSpecialSector && !this.checkDeselectSoloSeat(seat)) { 2182 audit.seatTooltip.hide(); 2183 ErrorManagement.sendError(new Error(0, js_lang.audit_error_no_solo_seat)); 2184 this.feedback(false); 2185 return false;
2186 } 2187 2188 if (Config.linearSeatProtection && !inSpecialSector && !this.checkDeselectLinearSeat(seat)) { 2189 audit.seatTooltip.hide(); 2190 ErrorManagement.sendError(new Error(0, js_lang.audit_error_linear_seat)); 2191 this.feedback(false); 2192 return false; 2193 } 2194 2195 //check seat status - must be selected 2196 if (!this.seatStatus(seat.seat_id, Consts.statusIds.selected)) { 2197 this.feedback(false); 2198 return false; 2199 } 2200 2201 //initalize request 2202 var url = ''; 2203 var postData = {}; 2204 2205 if (audit.ticketType === 'event') { 2206 //standard event (default) 2207 url = '/auditview/deselect_seat'; 2208 postData = { 2209 event_id: audit.eventId, 2210 seat_id: seat.seat_id, 2211 ticket_id: seat.ticket_id, 2212 sector_id: seat.sector_id 2213 }; 2214 } else if (audit.ticketType === 'seasonticket') { 2215 //simple season ticket 2216 var seatElement = SeatingChart.getSeat(seat.seat_id); 2217 url = '/seasonticket/audit_deselect_seat'; 2218 postData = { 2219 audit_id: audit.auditId, 2220 event_id: audit.eventId, 2221 operation: 1, // 0 hozzaad 1 torol 2222 pricecat_id: seatElement.pricecatID, 2223 seat_id: seat.seat_id, 2224 sector_id: seat.sector_id, 2225 ticket_id: seat.ticket_id, 2226 type: 0, // 0 sima 1 kapacitasos 2227 season_id: season_id, 2228 seasonticket_id: audit.eventId, 2229 venue_id: venue_id, 2230 price: seatElement.price 2231 }; 2232 if (audit.isDistributedPackage) { 2233 postData.distributedp_id = DistributedPackage.getId(); 2234 } 2235 } else if (audit.ticketType === 'freecombined') { 2236 //free combined season ticket 2237 var seatElement = SeatingChart.getSeat(seat.seat_id); 2238 url = '/seasonticket/audit_select_freecombined_seat'; 2239 postData = { 2240 venue_id: venue_id, 2241 audit_id: audit.auditId, 2242 event_id: audit.eventId, 2243 seasonticket_id: seasonticket_id, 2244 season_id: season_id, 2245 operation: 1, // 0 hozzaad 1 torol 2246 pricecat_id: seatElement.pricecatID, 2247 seat_id: seat.seat_id, 2248 sector_id: seat.sector_id, 2249 ticket_id: seat.ticket_id, 2250 type: 0, // 0 sima 1 kapacitasos 2251 seasontickettype: seasontickettype 2252 }; 2253 } else if (audit.ticketType === 'reservation') { 2254 //reservation 2255 var seatElement = SeatingChart.getSeat(seat.seat_id); 2256 var TSeventID = typeof tsevent_id !== 'undefined' ? tsevent_id : 0; 2257 2258 url = '/reservation/ticketoperation'; 2259 postData = { 2260 audit_id: audit.auditId, 2261 event_id: audit.eventId, 2262 operation: 1, // 0 hozzaad 1 torol 2263 pricecat_id: seatElement.pricecatID, 2264 seat_id: seat.seat_id, 2265 sector_id: seat.sector_id, 2266 ticket_id: seat.ticket_id, 2267 type: 0, // 0 sima 1 kapacitasos 2268 tsevent_id: TSeventID 2269 }; 2270 } else if (audit.ticketType === 'seasonpackage') { 2271 //season pachage 2272 url = '/seasonpackage/deselect_seat'; 2273 postData = { 2274 event_id: audit.eventId, 2275 seat_id: seat.seat_id, 2276 ticket_id: seat.ticket_id, 2277 sector_id: seat.sector_id 2278 }; 2279 } 2280 2281 if (url === '') { 2282 //invalid tickettype 2283 ErrorManagement.sendError(new Error(0, js_lang.label_unsuccess_deletion)); 2284 return false; 2285 } 2286 2287 //send request 2288 var self = this; 2289 this.startLoading(); 2290 $.ajax({ 2291 url: url, 2292 type: 'get', 2293 data: postData, 2294 dataType: 'json', 2295 cache: false, 2296 2297 success: function(data) { 2298 self.stopLoading(); 2299 if (data.result) { 2300 self.finalizeSeatSelection('remove', seat.seat_id, data, inSpecialSector ? seat.sector_id : 0); 2301 if (audit.ticketType === 'seasonpackage') { 2302 SPBasketExpire.addItemsToSelections(-1); 2303 if (typeof data.spbasket !== 'undefined') { 2304 SPBasketExpire.updateExpireTime(data.spbasket.time); 2305 } 2306 } 2307 2308 if (audit.ticketType === 'seasonticket' && audit.isDistributedPackage) { 2309 DistributedPackage.increaseSelections(-1); //-1 = decrease 2310 var thisprice = 0; 2311 if (typeof postData.price !== 'undefined') { 2312 thisprice += postData.price; 2313 } 2314 if (audit.showServiceCharge) { 2315 thisprice += audit.basketManager.getServiceCharge(1, postData.price); 2316 } 2317 DistributedPackage.updatePriceDisplay(DistributedPackage.status.current_price - thisprice); 2318 } 2319 } else { 2320 ErrorManagement.sendError(new Error(0, data.error.length ? data.error : js_lang.label_unsuccess_deletion)); 2321 audit.refreshSector(seat.sector_id); 2322 2323 //send feedback to audit viewer (fail) 2324 self.feedback(false); 2325 } 2326 }, 2327 2328 error: function(jqXHR, textStatus, errorThrown) { 2329 self.stopLoading(); 2330 ErrorManagement.sendError(new Error(0, js_lang.label_unsuccess_deletion)); 2331 2332 //send feedback to audit viewer (fail) 2333 self.feedback(false); 2334 } 2335 }); 2336 2337 return true; 2338 }, 2339 2340 //finalize seat selection on success 2341 finalizeSeatSelection: function(method, seat_id, data, special_sector_id) { 2342 var seat_list = []; 2343 if (typeof special_sector_id !== 'undefined' && special_sector_id > 0) { 2344 var seats = SeatingChart.getSectorSeats(special_sector_id); 2345 if (seats.length > 1) { 2346 for(var i=0; i<seats.length; i++) { 2347 seat_list.push(seats[i].id); 2348 } 2349 } 2350 } 2351 if (seat_list.length === 0) { 2352 seat_list.push(seat_id); 2353 } 2354 2355 for(var i=0; i<seat_list.length; i++) { 2356 var list_seat_id = seat_list[i]; 2357 var price = this.getTicketPrice(list_seat_id); 2358 var add2pb = false;
2359 2360 if (method === 'add') { 2361 this.markSeatAsSelected(list_seat_id); 2362 TicketGroup.decreaseTicket(price); 2363 if (price !== -1) { 2364 audit.basketManager.addItem(1, price); 2365 } 2366 add2pb = true; 2367 } else if (method === 'remove') { 2368 this.markSeatAsUnselected(list_seat_id); 2369 TicketGroup.increaseTicket(price); 2370 if (price !== -1) { 2371 audit.basketManager.removeItem(1, price); 2372 } 2373 } 2374 2375 if (add2pb && audit.ticketType !== 'seasonticket' && audit.ticketType !== 'seasonpackage') { 2376 //Prefixbox 2377 var productId = basic_url.split('-'); 2378 var currency = $('[itemprop=priceCurrency]').attr('content'); 2379 if (productId.length > 0) { 2380 productId = productId[productId.length - 1]; 2381 } 2382 var title = $('div.programInfo h1').text(); 2383 var params = { 2384 'price': (isNaN(price) || price === -1) ? 0 : price, 2385 'title': title, 2386 'productId': productId, 2387 'currency': currency, 2388 'send': false 2389 }; 2390 $(document).trigger('IT:prefixboxAddToCart', params); 2391 } 2392 } 2393 2394 //update mini basket 2395 if (audit.ticketType !== 'seasonpackage') { 2396 if (typeof(data.basketTime) != 'undefined') { 2397 updateMiniBasket(data.basketTime, data.basketArray, data.productCount, data.priceTotalSum); 2398 } else { 2399 updateMiniBasket(0, {}, 0, 0); 2400 } 2401 } 2402 2403 if (audit.ticketType === 'freecombined') { 2404 var basket_data = typeof data.seat_session != 'undefined' ? data.seat_session : {}; 2405 FreeCombined.updatecontinue(basket_data); 2406 FreeCombined.resetclock(); 2407 } 2408 2409 //update basket item list in MLSZ mode 2410 if (audit.mlszEnabled) { 2411 MLSZAudit.basketListUpdate(method, seat_id, data); 2412 if (audit.mlszAuditObjectExists) { 2413 var seat = SeatingChart.getSeat(seat_id); 2414 var sectorID = seat ? seat.sectorID : 0; 2415 if (MLSZAudit.isBestTicketSector(sectorID, true) && !SeatingChart.sectorHasSelection(sectorID)) { 2416 document.dispatchEvent(new CustomEvent("resetSectorData", { detail: { 2417 'sectorID': sectorID, 2418 'selected': false, 2419 'available': true 2420 }})); 2421 } 2422 } 2423 } 2424 2425 //close bestticket sector if is empty after removing seat 2426 if (method === 'remove' && audit.bestTicketSectors.length > 0) { 2427 var seat = SeatingChart.getSeat(seat_id); 2428 var sectorID = seat ? seat.sectorID : 0; 2429 if (sectorID > 0 && BestTicket.isBestTicketSector(sectorID) && !SeatingChart.sectorHasSelection(sectorID)) { 2430 document.dispatchEvent(new CustomEvent("resetSectorData", { detail: { 2431 'sectorID': sectorID, 2432 'selected': false, 2433 'available': true 2434 }})); 2435 } 2436 } 2437 2438 //send feedback to audit viewer (success) 2439 this.feedback(true); 2440 2441 //sector reload status 2442 if (typeof data.sr !== 'undefined') { 2443 SeatingChart.initCountFix(seat_id); 2444 audit.refreshSectorFast(data.sr); 2445 } 2446 2447 // Cross Selling 2448 if (method === 'remove' && typeof data.cs !== 'undefined') { 2449 $('[id^="crossselling_inbasket_"]').val('0'); 2450 $('[id^="crossselling_inbasket_count_"] > span').html('0'); 2451 $('[id^="crossselling_inbasket_count_"]').hide(); 2452 for (var cs_id in data.cs) { 2453 for (var nete_id in data.cs[cs_id]) { 2454 $('#crossselling_inbasket_' + cs_id + '_' + nete_id).val(data.cs[cs_id][nete_id]); 2455 if (parseInt(data.cs[cs_id][nete_id]) > 0) { 2456 $('#crossselling_inbasket_count_' + cs_id + '_' + nete_id).show(); 2457 } else { 2458 $('#crossselling_inbasket_count_' + cs_id + '_' + nete_id).hide(); 2459 } 2460 $('#crossselling_inbasket_count_' + cs_id + '_' + nete_id + ' > span').html(data.cs[cs_id][nete_id]); 2461 } 2462 } 2463 } 2464 2465 //socket sending 2466 if (AuditSocket.started) { 2467 if (method === 'add') { 2468 AuditSocket.selectSeat(seat_id) 2469 } else if (method === 'remove') { 2470 AuditSocket.unselectSeat(seat_id); 2471 } 2472 } 2473 }, 2474 2475 //select tickets from capacity sectors 2476 selectCapacity: function(postData, j) { 2477 var price = postData.price; 2478 var number = postData.quantity; 2479 2480 var url = '/auditview/select_capacity'; 2481 if (audit.ticketType === 'seasonticket') { 2482 url = '/seasonticket/audit_select_capacity'; 2483 } else if (audit.ticketType === 'seasonpackage') { 2484 url = '/seasonpackage/select_capacity'; 2485 } else if (audit.ticketType === 'reservation') { 2486 url = ''; //'/reservation/basket/put'; - no capacity sector in reservation 2487 } 2488 2489 if (url !== '') { 2490 this.startLoading(); 2491 audit.ajaxCallInProgress++; 2492 2493 $.ajax({ 2494 url: url, 2495 dataType: 'json', 2496 type: 'get', 2497 data: postData, 2498 cache: false, 2499 2500 success: function(data) { 2501 if (audit.ticketType !== 'seasonticket' && audit.ticketType !== 'seasonpackage') { 2502 // Prefixbox 2503 var productId = basic_url.split('-'); 2504 if (productId.length > 0) { 2505 productId = productId[productId.length - 1]; 2506 } 2507 var title = $('div.programInfo h1').text(); 2508 var params = { 2509 'price': isNaN(price) ? 0 : price * number, 2510 'productId': productId, 2511 'title': title, 2512 'count': number 2513 }; 2514 $(document).trigger('IT:prefixboxAddToCart', params); 2515 } 2516 2517 audit.ajaxCallInProgress--; 2518 Seat.stopLoading(); 2519 2520 if (data.result == true) { 2521 // sector inbasket 2522 var inbasket = parseInt(j.attr('inbasket')); 2523 inbasket += number; 2524 j.attr('inbasket', inbasket); 2525 2526 // audit basket & mini basket update 2527 audit.basketManager.addItem(number, number * price); 2528 if (audit.ticketType !== 'seasonpackage') { 2529 updateMiniBasket(data.basketTime, data.basketArray, data.productC
2529ount, data.priceTotalSum); 2530 } else { 2531 //Season package updates 2532 SPBasketExpire.addItemsToSelections(number); 2533 if (typeof data.spbasket !== 'undefined') { 2534 SPBasketExpire.updateExpireTime(data.spbasket.time); 2535 } 2536 } 2537 2538 //update sector status on audit viewer 2539 Seat.sectorSelect(postData.sector_id); 2540 TicketGroup.changeTicketCounter(price, -number); 2541 2542 //update MLSZ ticket list 2543 if (audit.mlszEnabled && audit.mlszAuditObjectExists) { 2544 var ticketsData = typeof data.ticketsData !== 'undefined' ? data.ticketsData : []; 2545 if (ticketsData) { 2546 MLSZAudit.addAuditBasketItems(ticketsData); 2547 } 2548 } 2549 if (typeof data.warning == 'string') { 2550 ErrorManagement.sendError(new Error(1234, data.warning)); 2551 } 2552 } else { 2553 ErrorManagement.sendError(new Error(0, data.error.length ? data.error : js_lang.unsuccessful_reservation)); 2554 } 2555 }, 2556 2557 error: function(jqXHR, textStatus, errorThrown) { 2558 audit.ajaxCallInProgress--; 2559 Seat.stopLoading(); 2560 ErrorManagement.sendError(new Error(0, js_lang.unsuccessful_reservation)); 2561 } 2562 }); 2563 } else { 2564 ErrorManagement.sendError(new Error(0, js_lang.unsuccessful_reservation)); 2565 } 2566 }, 2567 2568 //best ticket selection 2569 bestTicketSelection: function(sector_id, price, quantity) { 2570 var sector_key = 's' + sector_id; 2571 price = parseInt(price, 10); 2572 if (typeof sectorData[sector_key] !== 'undefined' && typeof sectorData[sector_key].pricecat_ids[price] !== 'undefined') { 2573 var pricecat_id = sectorData[sector_key].pricecat_ids[price]; 2574 var postData = { 2575 'event_id': audit.eventId, 2576 'sector_id': sector_id, 2577 'pricecat_id': pricecat_id, 2578 'price': price, 2579 'quantity': quantity 2580 }; 2581 2582 this.startLoading(); 2583 $.ajax({ 2584 url: '/auditview/select_bestticket', 2585 dataType: 'json', 2586 type: 'get', 2587 data: postData, 2588 cache: false, 2589 2590 success: function(data) { 2591 if (audit.ticketType !== 'seasonticket') { 2592 // Prefixbox 2593 var productId = basic_url.split('-'); 2594 if (productId.length > 0) { 2595 productId = productId[productId.length - 1]; 2596 } 2597 var title = $('div.programInfo h1').text(); 2598 var params = { 2599 'price': isNaN(price) ? 0 : price * quantity, 2600 'productId': productId, 2601 'title': title, 2602 'count': quantity 2603 }; 2604 $(document).trigger('IT:prefixboxAddToCart', params); 2605 } 2606 2607 audit.ajaxCallInProgress--; 2608 Seat.stopLoading(); 2609 2610 if (data.result == true) { 2611 // sector inbasket 2612 var j = $('div#Bsectors input#sector_' + sector_id); 2613 if ($(j).size() === 1) { 2614 var inbasket = parseInt(j.attr('inbasket')); 2615 inbasket += quantity; 2616 j.attr('inbasket', inbasket); 2617 } 2618 2619 // audit basket & mini basket update 2620 audit.basketManager.addItem(quantity, quantity * price); 2621 if (audit.ticketType !== 'seasonpackage') { 2622 updateMiniBasket(data.basketTime, data.basketArray, data.productCount, data.priceTotalSum); 2623 } 2624 2625 var ticketsData = typeof data.ticketsData !== 'undefined' ? data.ticketsData : []; 2626 if (ticketsData) { 2627 //update MLSZ ticket list 2628 if (audit.mlszEnabled && audit.mlszAuditObjectExists) { 2629 MLSZAudit.addAuditBasketItems(ticketsData); 2630 } 2631 2632 //update selection groups 2633 var selection_group = []; 2634 for(var i=0; i<ticketsData.length; i++) { 2635 selection_group.push({ 2636 'seatID': ticketsData[i].seat_id, 2637 'selectionGroup': ticketsData[i].group_guid 2638 }); 2639 Seat.markSeatAsSelected(ticketsData[i].seat_id); 2640 } 2641 document.dispatchEvent(new CustomEvent("setSelectionGroup", { detail: selection_group })); 2642 } 2643 2644 //update sector status on audit viewer 2645 Seat.sectorSelect(sector_id); 2646 2647 audit.updateBestTicketSector(sector_id, ticketsData); 2648 TicketGroup.changeTicketCounter(price, -quantity); 2649 } else { 2650 var errorMessage = (typeof data.errorMessage !== 'undefined' && data.errorMessage !== '') 2651 ? data.errorMessage 2652 : (data.error.length ? data.error : js_lang.unsuccessful_reservation); 2653 ErrorManagement.sendError(new Error(0, errorMessage)); 2654 } 2655 }, 2656 2657 error: function(jqXHR, textStatus, errorThrown) { 2658 audit.ajaxCallInProgress--; 2659 Seat.stopLoading(); 2660 ErrorManagement.sendError(new Error(0, js_lang.unsuccessful_reservation)); 2661 } 2662 }); 2663 } 2664 }, 2665 2666 //best ticket unselection by group 2667 bestTicketUnselection: function(sector_id, group, callback) { 2668 this.startLoading(); 2669 audit.ajaxCallInProgress++; 2670 sector_id = parseInt(sector_id, 10); 2671 2672 $.ajax({ 2673 url: '/auditview/deselect_group', 2674 dataType: 'json', 2675 type: 'post', 2676 data: { 2677 'event_id': audit.eventId, 2678 'sector_id': sector_id, 2679 'group': group 2680 }, 2681 cache: false, 2682 2683 success: function(data) { 2684 audit.ajaxCallInProgress--; 2685 Seat.stopLoading(); 2686 if (audit.mlszEnabled) { 2687 MLSZAudit.enableDeleteButtons(); 2688 } 2689 2690 if (data.result == true) { 2691 //BSector update (inbasket and sumprice data) 2692 var j = $('div#Bsectors input#sector_' + sector_id); 2693 if ($(j).size() === 1) { 2694 var inbasket = parseInt(j.attr('data-inbasket'), 10); 2695 inbasket -= data.removed.item_count; 2696 j.attr('data-inbasket', inbasket); 2697 2698 var sumprice = parseFloat(j.attr('data-sumprice')); 2699 sumprice -= data.removed.item_sumprice; 2700 j.attr('data-sumprice', inbasket); 2701 } 2702 2703 // audit basket & mini basket update 2704 audit.basketManager.removeItem(data.removed.item_count, data.removed.sum_price); 2705 if (audit.ticketType !== 'seasonpackage') { 2706 if (typeof data.basketArray !== 'undefined') { 2707 updateMiniBasket(data.basketTime, data.basketArray, data.productC
2707ount, data.priceTotalSum); 2708 } else { 2709 updateMiniBasket(0, {}, 0, 0); 2710 } 2711 } 2712 TicketGroup.changeTicketCounter(data.removed.item_price, data.removed.item_count); 2713 2714 if (data.unselected_sector) { 2715 //all seats was unselected from sector 2716 //remove seats and reset the sector data + mark as available 2717 document.dispatchEvent(new CustomEvent("resetSectorData", { detail: { 2718 'sectorID': sector_id, 2719 'selected': false, 2720 'available': true 2721 }})); 2722 } else { 2723 //some selected seats remains in sector - update seat status list & sync seat status 2724 document.dispatchEvent(new CustomEvent("unselectMultipleSeats", { detail: { 2725 'sectorID': sector_id, 2726 'seats': data.removed.seats 2727 }})); 2728 } 2729 2730 //call callback function to finalize the unselection (if is set) 2731 if (typeof callback === 'function') { 2732 callback(true); 2733 } 2734 } else { 2735 ErrorManagement.sendError(new Error(0, data.error.length ? data.error : js_lang.label_unsuccess_deletion)); 2736 if (typeof callback === 'function') { 2737 callback(false); 2738 } 2739 } 2740 }, 2741 2742 error: function(jqXHR, textStatus, errorThrown) { 2743 audit.ajaxCallInProgress--; 2744 Seat.stopLoading(); 2745 if (audit.mlszEnabled) { 2746 MLSZAudit.enableDeleteButtons(); 2747 } 2748 ErrorManagement.sendError(new Error(0, js_lang.label_unsuccess_deletion)); 2749 } 2750 }); 2751 }, 2752 2753 //show loading message 2754 startLoading: function() { 2755 audit.seatTooltip.hide(); 2756 audit.loadingLabel.showLabel(js_lang.audit_selecting_ticket); 2757 $('#' + Consts.domIds.audit).addClass('loading'); 2758 }, 2759 2760 //hide loading message 2761 stopLoading: function() { 2762 audit.loadingLabel.hide(); 2763 $('#' + Consts.domIds.audit).removeClass('loading'); 2764 }, 2765 2766 //check solo seat on selection 2767 checkSelectSoloSeat: function(seat) { 2768 var neighbours = this.getNeighbours(seat, 2, 1); 2769 2770 //cant select 2771 if ((neighbours.right1 === 0 && neighbours.right2 !== 0 && neighbours.endleft !== 2) || (neighbours.left1 === 0 && neighbours.left2 !== 0 && neighbours.endright !== 2)) { 2772 return false; 2773 } else if ((neighbours.right1 === 0 && neighbours.right2 === 1) || (neighbours.left1 === 0 && neighbours.left2 === 1)) { 2774 return false; 2775 } 2776 2777 //selectable 2778 return true; 2779 }, 2780 2781 //check solo seat on unselect 2782 checkDeselectSoloSeat: function(seat) { 2783 var neighbours = this.getNeighbours(seat, -1, 1); 2784 2785 //unselectable 2786 if ((neighbours.endright !== 0 && neighbours.endleft !== 0) && (neighbours.left1 !== 1 || neighbours.right1 !== 1)) { 2787 return true; 2788 } else if (neighbours.left1 === 0 || neighbours.right1 === 0) { 2789 return true; 2790 } 2791 2792 //cant unselect 2793 return false; 2794 }, 2795 2796 //check linear seat on selection (ids in the row must be picked in increasing order) 2797 checkSelectLinearSeat: function(seat) { 2798 var row = this.getSeatRow(seat).slice().sort(function(a, b) { 2799 return a.id - b.id; 2800 }); 2801 2802 //the seat being selected must be the first empty seat in the row 2803 for (var i = 0; i < row.length; i++) { 2804 if (row[i].status === Consts.statusIds.empty) { 2805 return row[i].id === seat.seat_id; 2806 } 2807 } 2808 2809 return false; 2810 }, 2811 2812 //check linear seat on unselect (only the last selected seat in the row may be released) 2813 checkDeselectLinearSeat: function(seat) { 2814 var row = this.getSeatRow(seat).slice().sort(function(a, b) { 2815 return a.id - b.id; 2816 }); 2817 2818 //the seat being deselected must be the last selected seat in the row 2819 for (var i = row.length - 1; i >= 0; i--) { 2820 if (row[i].status === Consts.statusIds.selected) { 2821 return row[i].id === seat.seat_id; 2822 } 2823 } 2824 2825 return false; 2826 }, 2827 2828 //collect seat's neighbours 2829 getNeighbours: function(seat, default_status, end_status) { 2830 var row = this.getSeatRow(seat); 2831 var list = { 2832 'left1': default_status, 2833 'left2': default_status, 2834 'right1': default_status, 2835 'right2': default_status, 2836 'endleft': default_status, 2837 'endright': default_status 2838 }; 2839 2840 var index = -1; 2841 $.each(row, function(seat_index, seat_data) { 2842 if (seat_data.id === seat.seat_id) { 2843 index = seat_index; 2844 } 2845 }); 2846 2847 if (index >= 0) { 2848 //left seats 2849 if (index > 0) { 2850 list.left1 = row[index - 1].status; 2851 if (index > 1) { 2852 list.left2 = row[index - 2].status; 2853 } 2854 } 2855 2856 //right seats 2857 if (index < (row.length - 1)) { 2858 list.right1 = row[index + 1].status; 2859 if (index < (row.length - 2)) { 2860 list.right2 = row[index + 2].status; 2861 } 2862 } 2863 2864 //left-end 2865 var i; 2866 for(i=index-1; i>=0; i--) { 2867 if (row[i].status !== end_status) { 2868 break; 2869 } 2870 } 2871 list.endleft = i >= 0 ? row[i].status : default_status; 2872 2873 //right-end 2874 for(i=index+1; i<row.length; i++) { 2875 if (row[i].status !== end_status) { 2876 break; 2877 } 2878 } 2879 list.endright = i < row.length ? row[i].status : default_status; 2880 } 2881 2882 return list; 2883 }, 2884 2885 //return entire row for a seat 2886 getSeatRow: function(seat) { 2887 if (!this.seatKeys) { 2888 this.seatKeys = Object.keys(SeatingChart.seatList); 2889 } 2890 2891 //seat properties 2892 var sector_id = seat.sector_id; 2893 var row_id = seat.row_id; 2894 2895 //collect seats from row 2896 var cache_key = sector_id + '-' + row_id; 2897 var seats = typeof this.seatRows[cache_key] !== 'undefined' ? this.seatRows[cache_key] : []; 2898 if (seats.length === 0) { 2899 for(var i=0; i<SeatingChart.seatOrderList.length; i++) { 2900 var seat_id = SeatingChart.seatOrderList[i]; 2901 var seat_data = SeatingChart.seatList[seat_id]; 2902 if (seat_data.sectorID === sector_id && seat_data.rowID === row_id) { 2903 seats.push(parseInt(seat_id, 10)); 2904 } 2905 } 2906 /* 2907 $.each(SeatingChart.seatList, function(seat_id, seat_data) { 2908 if (seat_data.sectorID === sector_id && seat_data.rowID === row_id) { 2909 seats.push(parseInt(seat_id, 10)); 2910 } 2911 }); 2912 */ 2913 this.seatRows[cache_key] = seats; 2914 } 2915 2916 var list = []; 2917 var seatElement; 2918 for(var i=0; i<seats.length; i++) { 2919 seatElement = SeatingChart.getSeat(seats[i]); 2920 if (seatElement) { 2921 list.push({ 2922 id: seats[i], 2923 status: seatElement.status 2924 }); 2925 } 2926 } 2927 2928 return list; 2929 }, 2930 2931 //check if a seat has a required status 2932 seatStatus: function(seat_id, required_status) { 2933 var seatElement = SeatingChart.getSeat(seat_id); 2934 if (seatElement) { 2935 var status = seatElement.status; 2936 if (typeof status !== 'undefined' && parseInt(status, 10) === required_status) { 2937 return true; 2938 } 2939 } 2940 2941 return false;
2942 }, 2943 2944 //return ticket price by seat 2945 getTicketPrice: function(seat_id) { 2946 var price = -1; 2947 var seatElement = SeatingChart.getSeat(seat_id); 2948 2949 if (seatElement) { 2950 var value = seatElement.price; 2951 if (typeof value !== 'undefined') { 2952 price = value; 2953 } 2954 } 2955 2956 return price; 2957 }, 2958 2959 //change seat status to selected 2960 markSeatAsSelected: function(seat_id) { 2961 this.changeStatus(seat_id, 1); 2962 }, 2963 2964 //change seat status to free 2965 markSeatAsUnselected: function(seat_id) { 2966 this.changeStatus(seat_id, 0); 2967 }, 2968 2969 //change status on html seat list 2970 changeStatus: function(seat_id, status) { 2971 SeatingChart.updateSeatStatus(seat_id, status); 2972 }, 2973 2974 //change status on html seat list 2975 changeStatusWithRefresh: function(seat_id, status, group_id) { 2976 SeatingChart.updateSeatStatus(seat_id, status, true, group_id); 2977 }, 2978 2979 //click event failed 2980 fail: function() { 2981 this.feedback(false); 2982 }, 2983 2984 //send seat event results to viewer 2985 feedback: function(success) { 2986 var seatEventResult = new CustomEvent("seatEventResult", { detail: { 2987 'success': success 2988 }}); 2989 document.dispatchEvent(seatEventResult); 2990 }, 2991 2992 //remove selections from audit viewer 2993 clearSelection: function() { 2994 var clearSelectionEvent = new CustomEvent("clearSelectionEvent"); 2995 audit.basketManager.clearItems(); 2996 document.dispatchEvent(clearSelectionEvent); 2997 2998 //audit.refreshAudit(); 2999 TicketGroup.countFreeTickets(false); 3000 3001 //$('div#Bseats > input[data-status="1"]').attr('data-status', 0); 3002 $('div#Bsectors > input:not([data-inbasket="0"])').attr('data-inbasket', 0).attr('data-sumprice', 0); 3003 }, 3004 3005 //send sector selection evento to audit viewer 3006 sectorSelect: function(sector_id) { 3007 var sectorSelectionResult = new CustomEvent("sectorSelectionResult", { detail: { 3008 'sectorID': sector_id 3009 }}); 3010 document.dispatchEvent(sectorSelectionResult); 3011 }, 3012 3013 //collect selected seats 3014 collect: function(add, seat) { 3015 var sector_id = typeof seat.sector_id !== 'undefined' ? seat.sector_id : 0; 3016 var seat_id = typeof seat.seat_id !== 'undefined' ? seat.seat_id : 0; 3017 3018 if (sector_id > 0 && seat_id > 0) { 3019 if (add) { 3020 //select a new seat 3021 if (typeof this.collection[sector_id] === 'undefined') { 3022 this.collection[sector_id] = []; 3023 } 3024 this.collection[sector_id].push(seat_id); 3025 } else { 3026 //seat unselection 3027 if (typeof this.collection[sector_id] !== 'undefined') { 3028 var pos = this.collection[sector_id].indexOf(seat_id); 3029 if (pos >= 0) { 3030 this.collection[sector_id].splice(pos, 1); 3031 } 3032 if (!this.collection[sector_id].length) { 3033 delete this.collection[sector_id]; 3034 } 3035 } 3036 } 3037 3038 if (this.collectionObj === false) { 3039 var box = $('<div id="seat_collection" style="position:fixed; top: 10px; left: 10px; width: 200px; height: 20px; overflow:hidden; z-index:15000;">').html(''); 3040 $("body").append(box); 3041 this.collectionObj = $('<input type="text" id="collection_input" style="width: 200xp; height: 18px; border: solid 1 px #000" onclick="this.select()">'); 3042 $(box).append(this.collectionObj); 3043 } 3044 3045 var collect_json = JSON.stringify(this.collection); 3046 $(this.collectionObj).val(collect_json); 3047 } 3048 } 3049}; 3050 3051 3052var startShowCapacity = false; 3053function CapacityPopup() { 3054 var capacityIsShowed = false; 3055 var capacityPopupDiv = $('#'+Consts.domIds.capacityPopup); 3056 var button_ok; 3057 var button_minus; 3058 var button_plus; 3059 var inp_number; 3060 var price; 3061 var service_charge; 3062 var total; 3063 var mouseX=0, mouseY=0; 3064 var priceId = 0; 3065 3066 var init = function() { 3067 inp_number = $('<input type="text" onclick="" id="inp_numberCapacityPopup" style="margin:0 6px;width:50px;display:inline-block;text-align:center;vertical-align:middle" />'); 3068 button_ok = $('<input type="button" class="button right dark" value="ok" id="button_OKcapacityPopup" />'); 3069 button_minus = $('<input type="button" class="button" value="-" id="button_minuscapacityPopup" style="width:33px;height:33px;min-width:unset" />'); 3070 button_plus = $('<input type="button" class="button" value="+" id="button_pluscapacityPopup" style="width:33px;height:33px;min-width:unset" />'); 3071 price = $('<p style="display:inline;font-weight:bold;"></p>'); 3072 service_charge = $('<p style="display:inline;font-weight:bold;"></p>'); 3073 total = $('<p style="display:inline;font-weight:bold;"></p>'); 3074 var br = '<br />'; 3075 capacityPopupDiv.html('');
3076 capacityPopupDiv.append(js_lang.audit_price + ': '); 3077 capacityPopupDiv.append(price); 3078 if (audit.showServiceCharge) { 3079 capacityPopupDiv.append(br); 3080 capacityPopupDiv.append(js_lang.basket_lang_basket_syscharge + ': '); 3081 capacityPopupDiv.append(service_charge); 3082 capacityPopupDiv.append(br); 3083 capacityPopupDiv.append(js_lang.audit_final_price + ': '); 3084 capacityPopupDiv.append(total); 3085 } 3086 capacityPopupDiv.append(br); 3087 capacityPopupDiv.append(js_lang.audit_quantity + ': '); 3088 capacityPopupDiv.append(br); 3089 capacityPopupDiv.append($('<div>').append(button_minus).append(inp_number).append(button_plus).addClass('fullMarginBottom smallMarginTop')); 3090 capacityPopupDiv.append(button_ok); 3091 capacityPopupDiv.append('<style>#inp_numberCapacityPopup { text-indent:0;transition:text-indent 30ms linear; } .capacity_movetoleft { text-indent: -35px!important; } .capacity_movetoright { text-indent: 16px!important; } .capacity_movestop { transition:text-indent 0ms!important; }</style>'); 3092 3093 //store mouse position on mouseup 3094 $(document).on("mouseup touchend", function(event) { 3095 mouseX = event.pageX; 3096 mouseY = event.pageY; 3097 }); 3098 }; 3099 3100 init(); 3101 3102 return { 3103 "showWithDatas": function(priceVal, priceCatId, delegates) { 3104 price.html(it_price_format(priceVal)); 3105 var serviceChargeVal = audit.basketManager.getServiceCharge(1, priceVal); 3106 service_charge.html(it_price_format(serviceChargeVal)); 3107 total.html(it_price_format(priceVal + serviceChargeVal)); 3108 var okDelegate = delegates.press_ok; 3109 3110 if (!capacityIsShowed || priceId != priceCatId) { 3111 inp_number.val('1'); 3112 } 3113 priceId = priceCatId; 3114 3115 button_ok.click(function() { 3116 if ($.isNumeric(inp_number.val())) { 3117 okDelegate(inp_number.val()); 3118 } else { 3119 okDelegate(undefined); 3120 } 3121 }); 3122 3123 var qchanging = false; 3124 button_minus.unbind('click').bind('click', function() { 3125 if (!qchanging) { 3126 var val = inp_number.val(), 3127 newVal = ($.isNumeric(val) && parseInt(val) > 1) ? parseInt(val) - 1 : 1; 3128 3129 if (parseInt(val, 10) !== parseInt(newVal, 10)) { 3130 inp_number.addClass('capacity_movestop').addClass('capacity_movetoright'); 3131 qchanging = true; 3132 setTimeout(function() { 3133 inp_number.val(newVal); 3134 inp_number.removeClass('capacity_movestop').removeClass('capacity_movetoright'); 3135 qchanging = false; 3136 }, 10); 3137 } 3138 } 3139 }); 3140 button_plus.unbind('click').bind('click', function() { 3141 if (!qchanging) { 3142 var val = inp_number.val(), 3143 newVal = ($.isNumeric(val) && parseInt(val) < 40) ? parseInt(val) + 1 : 40; 3144 3145 if (parseInt(val, 10) !== parseInt(newVal, 10)) { 3146 inp_number.addClass('capacity_movestop').addClass('capacity_movetoleft'); 3147 qchanging = true; 3148 setTimeout(function() { 3149 inp_number.val(newVal); 3150 inp_number.removeClass('capacity_movestop').removeClass('capacity_movetoleft'); 3151 qchanging = false; 3152 }, 10); 3153 } 3154 } 3155 }); 3156 3157 var auditpos = $('#'+Consts.domIds.audit).offset(); 3158 var x = mouseX-auditpos.left-10; 3159 var y = mouseY-auditpos.top-10; 3160 3161 capacityPopupDiv.css('top', y+'px'); 3162 capacityPopupDiv.css('left', x+'px'); 3163 capacityPopupDiv.css('z-index', 1); 3164 capacityPopupDiv.show(); 3165 capacityIsShowed = true; 3166 setTimeout(function() { 3167 startShowCapacity = false; 3168 }, 100); 3169 }, 3170 3171 "hide": function(e, isForce) { 3172 if (isForce || (!startShowCapacity && capacityIsShowed && !$.contains(capacityPopupDiv[0], e.target))) { 3173 button_ok.unbind('click'); 3174 capacityIsShowed = false; 3175 capacityPopupDiv.hide(); 3176 return true; 3177 } 3178 return false; 3179 }, 3180 3181 "button_ok": button_ok 3182 }; 3183} 3184 3185var mousePos = {}; 3186var sectorData = {}; 3187var delayTimer = false; 3188 3189function Tooltip() { 3190 var popupdiv = $('#'+Consts.domIds.tooltip), 3191 showTimer = false, 3192 auditId = window.netaudit_id, 3193 currentSeat = false, 3194 3195 tooltipObj = { 3196 waitingMode: typeof waiting_tooltip !== 'undefined' && waiting_tooltip, 3197 stageImage360: typeof auditview_stageimg360 !== 'undefined' && auditview_stageimg360, 3198 sitelang: typeof current_language !== 'undefined' ? current_language : 'hu', 3199 3200 'over': false, 3201 'arrowOrientation': { 3202 'X': 'arrowleft', 3203 'Y': 'arrowmiddle' 3204 }, 3205 'showSectorsTooltip': function(j) { 3206 var sector_id = j.id.sectorID; 3207 clearTimeout(showTimer); 3208 3209 showTimer = setTimeout(function() { 3210 if (tooltipObj.waitingMode) { 3211 tooltipObj.clearDelayedHide(); 3212 } 3213 3214 var name = ''; 3215 var sector_key = 's' + sector_id; 3216 var more = false;
3217 3218 if (typeof sectorData[sector_key] !== 'undefined') { 3219 if (sectorData[sector_key].tooltip === '') { 3220 //add sector name 3221 if (!sectorData[sector_key].graphic || sectorData[sector_key].free > 0) { 3222 name = '<div><span class="tooltipTextLeft">' + js_lang.audit_sector + ':</span><span class="tooltipTextRight">' + sectorData[sector_key].name + '</span></div>'; 3223 //add more data only when sector has available tickets 3224 if (sectorData[sector_key].free > 0) { 3225 if (TicketGroup.countEnabled) { 3226 //add free/available tickets 3227 name += '<div><span class="tooltipTextLeft">' + js_lang.label_available_seats + ':</span><span class="tooltipTextRight">' + sectorData[sector_key].free + '</span></div>'; 3228 } 3229 3230 if (audit.showServiceCharge) { 3231 //prices with servic charge 3232 if (typeof sectorData[sector_key] !== 'undefined') { 3233 name += '<div class="tip-table">'; 3234 name += '<div><span class="tooltipTextLeft">' + js_lang.audit_price 3235 + ':</span><span class="tooltipTextLeft">' + js_lang.basket_lang_basket_syscharge 3236 + ':</span><span class="tooltipTextLeft">' + js_lang.audit_final_price + ':</span></div>'; 3237 for (var price in sectorData[sector_key].pricecat_ids) { 3238 var service_charge = audit.basketManager.getServiceCharge(1, price); 3239 name += '<div><span class="tooltipTextRight">' + it_price_format(price) + '</span>' 3240 + '<span class="tooltipTextRight">' + it_price_format(service_charge) + '</span>' 3241 + '<span class="tooltipTextRight">' + it_price_format(parseFloat(price) + service_charge) + '</span></div>'; 3242 } 3243 name += '</div>'; 3244 } 3245 } else { 3246 //only ticket prices (interval for more prices) 3247 name += '<div><span class="tooltipTextLeft">' + js_lang.audit_price + ':</span> <span class="tooltipTextRight">' + it_price_format(sectorData[sector_key].pricemin); 3248 if (sectorData[sector_key].pricemax > sectorData[sector_key].pricemin) { 3249 name += ' - ' + it_price_format(sectorData[sector_key].pricemax); 3250 } 3251 name += '</span></div>'; 3252 } 3253 3254 //show special sector alert 3255 if (audit.hasSpecialSectors && audit.specialSectors.indexOf(sector_id) >= 0) { 3256 name += '<div>' + js_lang.label_sepcial_sector_tooltip + '</div>'; 3257 } 3258 3259 if (ProtectedSectors.enabled) { 3260 var protection = ProtectedSectors.isProtected(sector_id); 3261 if (protection !== false) { 3262 name += '<div>' + js_lang.label_audit_coupon_protected_sector.replace('%name%', protection) + '</div>'; 3263 } 3264 } 3265 3266 //add id row in #dev mode 3267 if (Seat.collectMode) { 3268 name += '<div><span class="tooltipTextLeft">SectorID:</span> <span class="tooltipTextRight">' + sector_id + '</span></div>'; 3269 } 3270 3271 sectorData[sector_key].tooltip = name; 3272 more = true; 3273 } else if (Seat.collectMode) { 3274 //add id row in #dev mode 3275 name += '<div><span class="tooltipTextLeft">SectorID:</span> <span class="tooltipTextRight">' + sector_id + '</span></div>'; 3276 } 3277 } else { 3278 //is a graphic (fill type) sector 3279 name = '<div><span class="tooltipTextLeft">' + sectorData[sector_key].name + '</span></div>'; 3280 3281 //add id row in #dev mode 3282 if (Seat.collectMode) { 3283 name += '<div><span class="tooltipTextLeft">SectorID:</span> <span class="tooltipTextRight">' + sector_id + '</span></div>'; 3284 } 3285 } 3286 } else { 3287 //sector tooltip already set 3288 name = sectorData[sector_key].tooltip; 3289 more = true; 3290 } 3291 } else { 3292 var sectorNode = $('#sector_' + sector_id); 3293 var name = sectorNode.attr('data-name'); 3294 if (name !== undefined) { 3295 name = '<span class="tooltipTextLeft">' + js_lang.audit_sector + ':</span> <span class="tooltipTextRight">' + name + '</span>'; 3296 if (Seat.collectMode) { 3297 name += '<div><span class="tooltipTextLeft">SectorID:</span> <span class="tooltipTextRight">' + sector_id + '</span></div>'; 3298 } 3299 } 3300 } 3301 3302 if (name !== undefined && name !== '') { 3303 if ( 3304 //sector has html content 3305 typeof sector_html !== 'undefined' 3306 && typeof sector_html[sector_id] !== 'undefined' 3307 //sector is free to use 3308 && typeof sectorData[sector_key] !== 'undefined' 3309 && sectorData[sector_key].free > 0 3310 ) { 3311 //add html content - tooltip top and bottom contents (if is free) 3312 name = sector_html[sector_id].top + name + sector_html[sector_id].bottom; 3313 } 3314 3315 popupdiv.html(name); 3316 popupdiv.show(); 3317 if (!more) { 3318 popupdiv.addClass('simple-data'); 3319 } else { 3320 popupdiv.removeClass('simple-data'); 3321 } 3322 tooltipObj.setPosition(); 3323 } 3324 }, tooltipObj.waitingMode ? 150 : 300); 3325 }, 3326 3327 'showinit': false, 3328 'showSeatsTooltip': function (j) { 3329 currentSeat = j; 3330 if (showTimer !== false) { 3331 clearTimeout(showTimer); 3332 } 3333 3334 tooltipObj.showinit = true; 3335 showTimer = setTimeout(function() { 3336 tooltipObj.displayTooltip(); 3337 tooltipObj.showinit = false;
3338 }, tooltipObj.waitingMode ? 150 : 250); 3339 }, 3340 3341 'displayTooltip': function() { 3342 showTimer = false; 3343 if (currentSeat !== false) { 3344 if (tooltipObj.waitingMode) { 3345 tooltipObj.clearDelayedHide(); 3346 } 3347 3348 var seat = currentSeat.seat; 3349 var row = currentSeat.row; 3350 var sector = currentSeat.sector; 3351 var seatId = seat.id.seatID, 3352 overSeatId = tooltipObj.over; 3353 tooltipObj.over = seatId; 3354 var seatElement = SeatingChart.getSeat(seatId); 3355 var seatName = seat.label.getText(); 3356 var rowName = ''; 3357 if (row) { 3358 if (row.labelLeft) { 3359 rowName = row.labelLeft.getText(); 3360 } else if (row.labelRight) { 3361 rowName = row.labelRight.getText(); 3362 } 3363 } 3364 var sectorName = sector ? sector.label.getText() : ''; 3365 3366 //best ticket sector setup 3367 var isBestTicketSector = false; 3368 if (audit.mlszEnabled && audit.mlszAuditObjectExists) { 3369 isBestTicketSector = MLSZAudit.isBestTicketSector(seat.id.sectorID, true); 3370 } else if (audit.bestTicketSectors.length > 0 && audit.bestTicketObjectExists) { 3371 isBestTicketSector = BestTicket.isBestTicketSector(seat.id.sectorID, true); 3372 } 3373 3374 var obstructedView = seatElement.isOV; 3375 var is_wheelchair = seatElement.isWC; 3376 seatName = seatName.length ? seatName : '-'; 3377 rowName = rowName.length ? rowName : '-'; 3378 sectorName = sectorName.length ? sectorName : '-'; 3379 var status = seatElement.status, 3380 price = seatElement.price, 3381 figureHtml = ''; 3382 3383 if (audit.stagePictures) { 3384 var stageimage = StageImages.getItem(seatId); 3385 var stageImageParam = { 3386 'seatName': seatName, 3387 'rowName': rowName, 3388 'sectorName': sectorName 3389 }; 3390 3391 if (stageimage) { 3392 if (stageimage !== 'false') { 3393 figureHtml = tooltipObj.getStageImageHtml( 3394 $.extend({}, stageImageParam, {'StagePictureUrl': stageimage}) 3395 ); 3396 } 3397 } else { 3398 self.ajaxCallInProgress++; 3399 popupdiv.find('figure').remove(); 3400 $.ajax({ 3401 url: '/auditview/stage_picture/' + auditId + '/'+ seatId, 3402 type: 'get', 3403 dataType: 'json', 3404 success: function(data) { 3405 self.ajaxCallInProgress--; 3406 if (!data.errorcode && data.StagePictureUrl) { 3407 StageImages.setItem(seatId, data.StagePictureUrl) 3408 popupdiv.find('figure').remove(); 3409 popupdiv 3410 .append(tooltipObj.getStageImageHtml($.extend({}, stageImageParam, {'StagePictureUrl': data.StagePictureUrl}))) 3411 .find('figure img').one("load", function() { 3412 tooltipObj.setPosition(); 3413 }).each(function() { 3414 if (this.complete) { 3415 $(this).load(); 3416 } 3417 }); 3418 tooltipObj.setPosition(); 3419 } else { 3420 StageImages.setItem(seatId, 'false'); 3421 } 3422 }, 3423 error: function(jqXHR, textStatus, errorThrown) { 3424 self.ajaxCallInProgress--; 3425 j.data('stageimage', 'false'); 3426 }, 3427 cache: true 3428 }); 3429 } 3430 } 3431 3432 var showPrice = status == '0' || status == '1' || (isBestTicketSector && price > 0); 3433 var divHTML = ''; 3434 3435 if (audit.showServiceCharge && showPrice) { 3436 divHTML += '<div class="tip-title"><span class="tooltipTextLeft">' + js_lang.audit_location + ':</span>'; //todo: add js_lang.audit_position 3437 if (is_wheelchair) { 3438 divHTML += '<img src="' + Config.wheelchair_seat_icon + '" style="width: 40px; height: 40px; float: right; background-color: ' + Config.wheelchair_seat_bgcolor + ';" />'; 3439 } 3440 var positionArr = []; 3441 var pattern = this.sitelang === 'hu' ? '%name%. %level%' : '%level% %name%'; 3442 if (sectorName !== '-') { 3443 positionArr.push(sectorName); 3444 } 3445 if (rowName !== '-') { 3446 positionArr.push(pattern.replace('%name%', rowName).replace('%level%', js_lang.audit_row)); 3447 } 3448 if (seatName !== '-') { 3449 positionArr.push(pattern.replace('%name%', seatName).replace('%level%', js_lang.audit_seat)); 3450 } 3451 divHTML += '<span class="tooltipTextRight">' + (positionArr.length ? positionArr.join(', ') : '-') + '</span></div>'; 3452 } else { 3453 divHTML += '<div><span class="tooltipTextLeft">
3453' + js_lang.audit_seat + ':</span>'; 3454 if (is_wheelchair) { 3455 divHTML += '<img src="' + Config.wheelchair_seat_icon + '" style="width: 40px; height: 40px; float: right; background-color: ' + Config.wheelchair_seat_bgcolor + ';" />'; 3456 } 3457 divHTML += '<span class="tooltipTextRight">' + seatName + '</span></div>' 3458 + '<div><span class="tooltipTextLeft">' + js_lang.audit_row + ':</span>' 3459 + '<span class="tooltipTextRight">' + rowName + '</span></div>' 3460 + '<div><span class="tooltipTextLeft">' + js_lang.audit_sector + ':</span>' 3461 + '<span class="tooltipTextRight">' + sectorName + '</span></div>'; 3462 } 3463 3464 if (showPrice) { 3465 if (typeof category_names !== 'undefined') { 3466 var sectorID = seat.id.sectorID; 3467 if (typeof category_names[sectorID] !== 'undefined' && typeof category_names[sectorID][price] !== 'undefined') { 3468 divHTML += '<div><span class="tooltipTextLeft">' + js_lang.label_ticket_category + ":</span>" 3469 + '<span class="tooltipTextRight" id="tooltipTextRightPrice">' + category_names[sectorID][price] + '</span></div>'; 3470 } 3471 } 3472 3473 if (audit.showServiceCharge && typeof TicketGroup.list[price] !== 'undefined') { 3474 divHTML += '<div><span class="tooltipTextLeft">' + js_lang.audit_price + ":</span>" 3475 + '<span class="tooltipTextRight">' + it_price_format(price) + '</span></div>' 3476 + '<div><span class="tooltipTextLeft">' + js_lang.basket_lang_basket_syscharge + ":</span>" 3477 + '<span class="tooltipTextRight">' + TicketGroup.list[price].service_charge_str + '</span></div>' 3478 + '<div class="tip-total"><span class="tooltipTextLeft">' + js_lang.audit_final_price + ":</span>" 3479 + '<span class="tooltipTextRight" id="tooltipTextRightPrice">' + TicketGroup.list[price].sum_price_str + '</span></div>'; 3480 } else { 3481 divHTML += '<div><span class="tooltipTextLeft">' + js_lang.audit_price + ":</span>" 3482 + '<span class="tooltipTextRight" id="tooltipTextRightPrice">' + it_price_format(price) + '</span></div>'; 3483 } 3484 } 3485 3486 if (obstructedView) { 3487 divHTML += "<div class=\"tip-warning\"><span class=\"tooltipTextLeft tooltipObstructedView\">" + js_lang.audit_seat_obstructed_view + "</span></div>"; 3488 } 3489 3490 //show special sector alert 3491 if (audit.hasSpecialSectors && audit.specialSectors.indexOf(seat.id.sectorID) >= 0) { 3492 divHTML += '<div>' + js_lang.label_sepcial_sector_tooltip + '</div>'; 3493 } 3494 3495 if (ProtectedSectors.enabled) { 3496 var protection = ProtectedSectors.isProtected(seat.id.sectorID); 3497 if (protection !== false) { 3498 divHTML += '<div>' + js_lang.label_audit_coupon_protected_sector.replace('%name%', protection) + '</div>'; 3499 } 3500 } 3501 3502 //add id row in #dev mode 3503 if (Seat.collectMode) { 3504 divHTML += '<div><span class="tooltipTextLeft">SectorID:</span> <span class="tooltipTextRight">' + seat.id.sectorID + '</span></div>' 3505 + '<div><span class="tooltipTextLeft">SeatID:</span> <span class="tooltipTextRight">' + seat.id.seatID + '</span></div>'; 3506 var seatobj = SeatingChart.getSeat(seat.id.seatID); 3507 divHTML += '<div><span class="tooltipTextLeft">TicketID:</span> <span class="tooltipTextRight">' + seatobj.ticketID + '</span></div>' 3508 + '<div><span class="tooltipTextLeft">PriceCatID:</span> <span class="tooltipTextRight">' + seatobj.pricecatID + '</span></div>'; 3509 } 3510 3511 3512 //sector has html content 3513 if (typeof seat_html !== 'undefined' && typeof seat_html[seat.id.sectorID] !== 'undefined') { 3514 //add html content - tooltip bottom contents 3515 divHTML += seat_html[seat.id.sectorID]; 3516 } 3517 3518 divHTML += "</div>"; 3519 divHTML += figureHtml; 3520 3521 if (this.waitingMode) { 3522 divHTML += '<div id="waitinghoverfix" style="position:absolute; width:16px; height:20px;"></div>'; 3523 } 3524 3525 popupdiv.html(divHTML); 3526 popupdiv.show(); 3527 popupdiv.removeClass('simple-data'); 3528 tooltipObj.setPosition(); 3529 } else { 3530 //no current seat - force hide tooltip 3531 tooltipObj.hide(); 3532 } 3533 }, 3534 3535 'initMouse': function() { 3536 $('#audit').off('mousemove').on('mousemove', function(e) { 3537 mousePos = { 3538 'X': e.pageX, 3539 'Y': e.pageY 3540 }; 3541 if (!tooltipObj.waitingMode && popupdiv.is(':visible')) { 3542 tooltipObj.setPosition(true); 3543 } 3544 }); 3545 }, 3546 3547 'getStageImageHtml': function(data) { 3548 if (!this.stageImage360) { 3549 //standard image 3550 return '<figure>' 3551 + '<a class="preview" href="#"><img src="' + data.StagePictureUrl + '" alt="' 3552 + js_lang.audit_seat + ': ' + data.seatName + ' / ' 3553 + js_lang.audit_row + ': ' + data.rowName + ' / ' 3554 + js_lang.audit_sector + ': ' + data.sectorName 3555 + '" /></a>' 3556 + '<figcaption>' + js_lang.audit_tooltip_picture_disclaimer + '</figcaption>' 3557 + '</figure>'; 3558 } else { 3559 //rotate picture 3560 var imgwidth = Config.stageImageWidth; 3561 var imgheight = Config.stageImageHeight; 3562 if (!imgwidth || !imgheight) { 3563 imgwidth = 320; 3564 imgheight = 160; 3565 } 3566 3567 return '<figure>' 3568 + '<div id="panorama" style="width:'+imgwidth+'px;height:'+imgheight+'px;"></div>' 3569 + '<figcaption>' + js_lang.audit_tooltip_picture_disclaimer + '</figcaption>' 3570 + '</figure>' 3571 + '<script>pannellum.viewer("panorama", {"type": "equirectangular", "panorama": "' + data.StagePictureUrl + '", "autoLoad":true});</script>'; 3572 } 3573 }, 3574 3575 'mouseout': function() { 3576 tooltipObj.hide(); 3577 }, 3578 'hide': function() { 3579 if (showTimer !== false) { 3580 clearTimeout(showTimer); 3581 showTimer = false;
3582 } 3583 currentSeat = false; 3584 popupdiv.css('display', 'none'); 3585 popupdiv.empty(); 3586 tooltipObj.over = false; 3587 }, 3588 'delayedHide': function() { 3589 if (delayTimer === false) { 3590 delayTimer = setTimeout(function() { 3591 tooltipObj.delayTimer = false; 3592 tooltipObj.hide(); 3593 }, 500); 3594 } 3595 }, 3596 'clearDelayedHide': function() { 3597 if (delayTimer !== false) { 3598 clearTimeout(delayTimer); 3599 delayTimer = false; 3600 } 3601 }, 3602 'setPosition': function(force) { 3603 var calcPos = tooltipObj.calculatePosition(tooltipObj.arrowOrientation); 3604 recalculate = false, 3605 arrowX = tooltipObj.arrowOrientation.X = popupdiv.hasClass('arrowright') ? 'arrowright' : 'arrowleft', 3606 arrowY = tooltipObj.arrowOrientation.Y = popupdiv.hasClass('arrowtop') ? 'arrowtop' : popupdiv.hasClass('arrowbottom') ? 'arrowbottom' : 'arrowmiddle', 3607 borderLimit = 30; 3608 3609 if (!force && arrowX == 'arrowleft' && calcPos.left + popupdiv.outerWidth() >= calcPos.auditWidth - borderLimit) { 3610 arrowX = 'arrowright'; 3611 } else if (!force && arrowX == 'arrowright' && calcPos.left <= borderLimit) { 3612 arrowX = 'arrowleft'; 3613 } 3614 if (arrowY != 'arrowmiddle' && mousePos.Y - popupdiv.outerHeight() / 2 > calcPos.auditTop + borderLimit && mousePos.Y + popupdiv.height() / 2 < calcPos.auditTop + calcPos.auditHeight - borderLimit) { 3615 arrowY = 'arrowmiddle'; 3616 } else if (arrowY != 'arrowtop' && mousePos.Y- popupdiv.outerHeight() / 2 < calcPos.auditTop) { 3617 arrowY = 'arrowtop'; 3618 } else if (arrowY != 'arrowbottom' && mousePos.Y + popupdiv.outerHeight() / 2 > calcPos.auditTop + calcPos.auditHeight) { 3619 arrowY = 'arrowbottom'; 3620 } 3621 if (tooltipObj.arrowOrientation.X !== arrowX || tooltipObj.arrowOrientation.Y !== arrowY) { 3622 popupdiv.removeClass(); 3623 tooltipObj.arrowOrientation = { 3624 'X': arrowX, 3625 'Y': arrowY 3626 }; 3627 calcPos = tooltipObj.calculatePosition(tooltipObj.arrowOrientation); 3628 } 3629 popupdiv 3630 .css({ 3631 left: calcPos.left, 3632 top: calcPos.top 3633 }) 3634 .addClass(tooltipObj.arrowOrientation.X + ' ' + tooltipObj.arrowOrientation.Y); 3635 3636 if (this.waitingMode) { 3637 this.waitingHoverFix(tooltipObj.arrowOrientation); 3638 } 3639 }, 3640 'calculatePosition': function(arrowOrientation) { 3641 var auditObj = $('#' + Consts.domIds.audit), 3642 auditPos = auditObj.offset(), 3643 result = { 3644 'auditTop': auditPos.top, 3645 'auditLeft': auditPos.left, 3646 'auditHeight': auditObj.outerHeight(), 3647 'auditWidth': auditObj.outerWidth() 3648 }, 3649 fineTune = { 3650 'arrowright': [-15, 0], 3651 'arrowleft': [20, 0], 3652 'arrowtop': [10, -10], 3653 'arrowbottom': [10, 10], 3654 'arrowmiddle': [10, 0] 3655 }; 3656 3657 switch(arrowOrientation.X) { 3658 case 'arrowright': 3659 result = $.extend({}, result, { 3660 'left': mousePos.X - popupdiv.outerWidth() - auditPos.left + fineTune[arrowOrientation.X][0] 3661 } 3662 ); 3663 break; 3664 case 'arrowleft': 3665 default: 3666 result = $.extend({}, result, { 3667 'left': mousePos.X - auditPos.left + fineTune[arrowOrientation.X][0] 3668 } 3669 ); 3670 } 3671 switch(arrowOrientation.Y) { 3672 case 'arrowtop': 3673 result = $.extend({}, result, { 3674 'top': mousePos.Y - auditPos.top + fineTune[arrowOrientation.Y][1] 3675 } 3676 ); 3677 break; 3678 case 'arrowbottom': 3679 result = $.extend({}, result, { 3680 'top': mousePos.Y - auditPos.top - popupdiv.outerHeight() + fineTune[arrowOrientation.Y][1] 3681 } 3682 ); 3683 break; 3684 case 'arrowmiddle': 3685 default: 3686 result = $.extend({}, result, { 3687 'top': mousePos.Y - auditPos.top - popupdiv.outerHeight() / 2 + fineTune[arrowOrientation.Y][1] 3688 } 3689 ); 3690 } 3691 return result; 3692 }, 3693 'waitingHoverFix': function(arrowOrientation) { 3694 var css = { 3695 'left': 'none', 3696 'right': 'none', 3697 'top': 'none', 3698 'bottom': 'none' 3699 }; 3700 3701 //horizontal position 3702 if (arrowOrientation.X === 'arrowright') { 3703 css.right = "-14px"; 3704 } else if (arrowOrientation.X === 'arrowleft') { 3705 css.left = "-14px"; 3706 } 3707 3708 //vertical position 3709 if (arrowOrientation.Y === 'arrowtop') { 3710 css.top = '0'; 3711 } else if (arrowOrientation.Y === 'arrowbottom') { 3712 css.bottom = '0'; 3713 } else if (arrowOrientation.Y === 'arrowmiddle') { 3714 css.top = Math.round(popupdiv.outerHeight() / 2) - 12 + 'px'; 3715 } 3716 3717 $('div#waitinghoverfix').css(css); 3718 } 3719 }; 3720 3721 tooltipObj.initMouse(); 3722 return tooltipObj; 3723} 3724 3725//store loaded stage images 3726var StageImages = { 3727 //list of items 3728 list: {}, 3729 3730 //get one item 3731 getItem: function(seat_id) { 3732 if (typeof this.list[seat_id]) { 3733 return this.list[seat_id]; 3734 } 3735 return null; 3736 }, 3737 3738 //update an item 3739 setItem: function(seat_id, value) { 3740 this.list[seat_id] = value; 3741 } 3742}; 3743 3744var SeatingChart = { 3745 //additional data of loaded seats 3746 seatList: {}, 3747 seatOrderList: [], 3748 3749 //ticket count fix for special sectors (multiple select/deselect) 3750 counterFix: { 3751 active: false, 3752 sectorID: 0, 3753 price: 0, 3754 initCount: 0, 3755 seatIDs: [] 3756 }, 3757 3758 //return addition data of a loaded seat - by seatID 3759 getSeat: function(seatID) { 3760 if (typeof this.seatList[seatID] !== 'undefined') { 3761 return this.seatList[seatID]; 3762 } 3763 return false;
3764 }, 3765 3766 //return seats data from a sector 3767 getSectorSeats: function(sectorID) { 3768 var list = []; 3769 for(var seatID in this.seatList) { 3770 if (this.seatList[seatID].sectorID === sectorID) { 3771 list.push({ 3772 'id': seatID, 3773 'status': this.seatList[seatID].status 3774 }); 3775 } 3776 } 3777 return list; 3778 }, 3779 3780 //update status of a loaded seat 3781 updateSeatStatus: function(seatID, status, update_viewer, group_id) { 3782 seatID = parseInt(seatID, 10); 3783 if (typeof this.seatList[seatID] !== 'undefined') { 3784 this.seatList[seatID].status = status; 3785 var params = { 3786 seat_id: seatID, 3787 status: status 3788 }; 3789 if (typeof update_viewer !== 'undefined' && update_viewer) { 3790 params.update_viewer = true; 3791 if (typeof group_id !== 'undefined' && group_id !== false) { 3792 params.group_id = group_id; 3793 } 3794 } 3795 var updateSeatStatusEvent = new CustomEvent("updateSeatStatusEvent", { detail: params }); 3796 document.dispatchEvent(updateSeatStatusEvent); 3797 } 3798 }, 3799 3800 //update seat price in dynamic price mode (engough here, sync to seat-viewer not needed) 3801 updateSeatPrice: function(pricecatList, sectors) { 3802 $.each(SeatingChart.seatList, function(seatID, seat) { 3803 if (seat.pricecatID in pricecatList && SeatingChart.seatList[seatID].price != pricecatList[seat.pricecatID]) { 3804 //price changed for current PriceCat 3805 SeatingChart.seatList[seatID].price = pricecatList[seat.pricecatID]; 3806 } 3807 }); 3808 3809 var data = { 3810 sectorGroups: {}, 3811 mapColors: {}, 3812 pricecats: {} 3813 }; 3814 3815 $.each(sectors, function(sid, sector) { 3816 data.sectorGroups[sid] = { 3817 'groupcolor': Math.min(sector.groups) 3818 }; 3819 data.mapColors[sid] = sector.groupcol; 3820 }); 3821 3822 $.each(pricecatList, function(pcid, price) { 3823 data.pricecats[pcid] = { 3824 'price': price, 3825 'group': price in TicketGroup.list ? TicketGroup.list[price].index : TicketGroup.getGroupIndexByPrice(price) 3826 }; 3827 }); 3828 3829 var dynamicUpdateGroupsEvent = new CustomEvent("dynamicUpdateGroups", { 3830 detail: data 3831 }); 3832 document.dispatchEvent(dynamicUpdateGroupsEvent); 3833 }, 3834 3835 //return true if sector has selection 3836 sectorHasSelection: function(sectorID) { 3837 for(var seatID in this.seatList) { 3838 if (this.seatList[seatID].status === 1 && this.seatList[seatID].sectorID === sectorID) { 3839 //selection found in sector 3840 return true; 3841 } 3842 } 3843 3844 //no selection found in the sector 3845 return false; 3846 }, 3847 3848 //on special sectors (auto multiple seat selection) need to fix available seat counter 3849 initCountFix: function(seat_id) { 3850 if (seat_id && !this.counterFix.active) { 3851 var seat = this.getSeat(seat_id); 3852 if (seat) { 3853 var sector_id = seat.sectorID; 3854 var seat_ids = []; 3855 var selected = 0; 3856 var price = seat.price; 3857 $.each(this.seatList, function(sid, seat) { 3858 if (seat.sectorID === sector_id) { 3859 seat_ids.push(sid); 3860 if (seat.status === 1) { 3861 selected++; 3862 } 3863 } 3864 }); 3865 3866 this.counterFix.active = true; 3867 this.counterFix.sectorID = sector_id; 3868 this.counterFix.price = price; 3869 this.counterFix.initCount = selected; 3870 this.counterFix.seatIDs = seat_ids; 3871 } 3872 } 3873 }, 3874 3875 //finalize available ticket counter on multiple selection (special sector) 3876 finishCountFix: function() { 3877 if (this.counterFix.active) { 3878 var selected = 0; 3879 for(var i=0; i<this.counterFix.seatIDs.length; i++) { 3880 var seat = this.getSeat(this.counterFix.seatIDs[i]); 3881 if (seat.status === 1) { 3882 selected++; 3883 } 3884 } 3885 var diff = this.counterFix.initCount - selected; 3886 if (diff !== 0) { 3887 TicketGroup.changeTicketCounter(this.counterFix.price, diff); 3888 } 3889 3890 //reset counter fix 3891 this.counterFix.active = false; 3892 this.counterFix.sectorID = 0; 3893 this.counterFix.price = 0; 3894 this.counterFix.initCount = 0; 3895 this.counterFix.seatIDs = []; 3896 } 3897 } 3898}; 3899 3900//minimap setup object 3901var MiniMAP = { 3902 initialized: false, 3903 3904 //initialize minimap 3905 init: function() { 3906 //initialize once 3907 if (this.initialized) { 3908 return false; 3909 } 3910 this.initialized = true; 3911 3912 //check minimap status (enabled/disabled) 3913 if (typeof ticketType !== 'undefined' && ticketType === 'freecombined') {
3914 //minimap disabled for free combined season ticket 3915 Config.minimap.enabled = false; 3916 } 3917 if (!Config.minimap.enabled) { 3918 return false; 3919 } 3920 3921 //check minimap html dom object 3922 this.checkMinimapObject(); 3923 3924 //add triggers 3925 var minimap = $('div#minimap'); 3926 3927 if (!$(minimap).is(':visible')) { 3928 //disable minimap when minimap object is not visible (on start) 3929 document.dispatchEvent(new CustomEvent("blockMinimap", { 3930 detail: true 3931 })); 3932 } 3933 $(window).resize(function() { 3934 //disable minimap when minimap object is not visible (on window resize) 3935 document.dispatchEvent(new CustomEvent("blockMinimap", { 3936 detail: !$(minimap).is(':visible') 3937 })); 3938 }); 3939 3940 return true; 3941 }, 3942 3943 //check minimap dom object and create if not exists 3944 checkMinimapObject: function() { 3945 if (Config.minimap.enabled && !$('div#minimap').size()) { 3946 var minimapObj = $('<div id="minimap"></div>').css({ 3947 "display": "block", 3948 "position": "absolute", 3949 "width": Config.minimap.size[0] + "px", 3950 "height": Config.minimap.size[1] + "px", 3951 "right": Config.minimap.offset[0] + "px", 3952 "bottom": Config.minimap.offset[1] + "px", 3953 "border": "solid 1px " + Config.minimap.border, 3954 "background-color": Config.minimap.background, 3955 "z-index": 5 3956 }); 3957 3958 $('div#' + Consts.domIds.audit).append(minimapObj); 3959 minimapFound = true; 3960 } 3961 } 3962}; 3963 3964//Protected sectors with coupon codes 3965var ProtectedSectors = { 3966 enabled: false, 3967 filterEnabled: false, 3968 3969 sector: null, 3970 name: null, 3971 used: null, 3972 customLabels: null, 3973 couponInputObj: null, 3974 pinInputObj: null, 3975 3976 //intialize 3977 init: function() { 3978 this.sector = {}; 3979 this.name = {}; 3980 this.used = []; 3981 this.customLabels = {}; 3982 3983 if (typeof protected_sectors !== 'undefined') { 3984 $.each(protected_sectors, function(protection_id, protection) { 3985 ProtectedSectors.enabled = true; 3986 ProtectedSectors.name[protection_id] = protection.name; 3987 for(var i=0; i<protection.sectors.length; i++) { 3988 ProtectedSectors.sector[protection.sectors[i]] = protection_id; 3989 } 3990 if (protection.title || protection.info) { 3991 ProtectedSectors.customLabels[protection_id] = { 3992 "title": protection.title, 3993 "info": protection.info 3994 }; 3995 } 3996 }); 3997 } 3998 3999 if (typeof used_permissions !== 'undefined') { 4000 for(var i=0; i<used_permissions.length; i++) { 4001 if (typeof ProtectedSectors.name[used_permissions[i]] !== 'undefined') { 4002 ProtectedSectors.used.push(used_permissions[i].toString()); 4003 } 4004 } 4005 } 4006 4007 $(document).on('focus', 'input.pretected_sector_couponcode', function() { 4008 ProtectedSectors.couponInputObj = $(this); 4009 }); 4010 4011 $(document).on('focus', 'input.pretected_sector_pin_code', function() { 4012 ProtectedSectors.pinInputObj = $(this); 4013 }); 4014 4015 //add coupon code filters 4016 if (ProtectedSectors.enabled && typeof Config.showCouponFilter !== 'undefined' && Config.showCouponFilter) { 4017 ProtectedSectors.addFilters(); 4018 if (this.used.length > 0) { 4019 for (var i=0; i<this.used.length; i++) { 4020 this.markActivatedFilter(this.used[i]); 4021 } 4022 } 4023 } 4024 }, 4025 4026 //check if a sector is protected and return protecion name 4027 isProtected: function(sector_id) { 4028 var protection_id = typeof this.sector[sector_id] !== 'undefined' ? this.sector[sector_id] : 0; 4029 if (protection_id) { 4030 return this.name[protection_id]; 4031 } 4032 return false; 4033 }, 4034 4035 //seat selection require coupon code 4036 codeRequired: function(sector_id) { 4037 var protection_id = typeof this.sector[sector_id] !== 'undefined' ? this.sector[sector_id] : 0; 4038 if (protection_id > 0 && this.used.indexOf(protection_id) < 0) { 4039 //sector is protected and coupon code not used yet 4040 return true; 4041 } 4042 return false; 4043 }, 4044 4045 getPopupText: function(sector_id) { 4046 var data = { 4047 'title': '', 4048 'info': '' 4049 }; 4050 var protection_id = typeof this.sector[sector_id] !== 'undefined' ? this.sector[sector_id] : 0; 4051 if (protection_id && typeof this.customLabels[protection_id] !== 'undefined') { 4052 data.title = this.customLabels[protection_id].title; 4053 data.info = this.customLabels[protection_id].info; 4054 } 4055 if (!data.title) { 4056 data.title = js_lang.label_audit_coupon_protected_sector_title; 4057 } 4058 if (!data.info) { 4059 var protection_name = this.isProtected(sector_id); 4060 if (protection_name === false) { 4061 protection_name = ''; 4062 } 4063 data.info = js_lang.label_audit_coupon_protected_sector.replace("%name%", protection_name); 4064 } 4065 return data; 4066 }, 4067 4068 //show coupon code popup 4069 popup: function(seat) { 4070 var text = this.getPopupText(seat.sector_id); 4071 if (mlsz_coupon_is_clubcard) { 4072 var popup_message = text.info + '<input type="text" class="pretected_sector_couponcode" placeholder="' + js_lang.label_fancard_number + '" />' 4073 + '<div class="input-group">' 4074 + '<input type="password" class="pretected_sector_pin_code input-group-field pw-eye-fld" placeholder="' + js_lang.pin_code + '" />' 4075 + '<span class="input-group-label pw-eye-btn"><i class="fa fa-eye-slash"></i></span>' 4076 + '</div>'; 4077 } else { 4078 var popup_message = text.info + '<input type="text" class="pretected_sector_couponcode" placeholder="' + js_lang.admin_coupon_code + '" />'; 4079 } 4080 4081 //show popup 4082 revDialog({
4083 title: text.title, 4084 content: popup_message, 4085 leftButton: { 4086 label: js_lang.label_audit_coupon_send, 4087 onClick: function(obj) { 4088 var popupObj = $(obj.currentTarget).parents('div.revdialog_body'); //standard popup 4089 var inputObj = popupObj.length > 0 ? $('input.pretected_sector_couponcode', popupObj[0]) : ProtectedSectors.couponInputObj; //use last focused input if standard popup fails 4090 var couponcode = inputObj && inputObj.length > 0 ? $.trim($(inputObj).val()) : ''; 4091 var inputObj2 = popupObj.length > 0 ? $('input.pretected_sector_pin_ccode', popupObj[0]) : ProtectedSectors.pinInputObj; //use last focused input if standard popup fails 4092 var pinCode = inputObj2 && inputObj2.length > 0 ? $.trim($(inputObj2).val()) : ''; 4093 ProtectedSectors.checkCouponCode(seat.sector_id, couponcode, seat, pinCode); 4094 }, 4095 close: true 4096 }, 4097 rightButton: { 4098 label: js_lang.label_audit_coupon_eject, 4099 class: 'dark', 4100 onClick: function() { 4101 ProtectedSectors.closeProtectedSectors(seat.sector_id); 4102 }, 4103 close: true 4104 } 4105 }); 4106 4107 //focus to input field 4108 setTimeout(function() { 4109 var inputObj = $('input.pretected_sector_couponcode:visible')[0]; 4110 if (inputObj && $(inputObj).length === 1) { 4111 $(inputObj).focus(); 4112 } 4113 }, 100); 4114 }, 4115 4116 //check a coupon code 4117 checkCouponCode: function(sector_id, couponcode, seat, pinCode) { 4118 var url = false; 4119 var params = { 4120 "sector_id": sector_id, 4121 "couponcode": couponcode, 4122 "pin_code": pinCode 4123 }; 4124 if (audit.ticketType === 'event') { 4125 url = '/auditview/check_coupon'; 4126 params.event_id = audit.eventId; 4127 } else if (audit.ticketType === 'seasonticket') { 4128 //todo for season tickets 4129 } else { 4130 //other types: reservation, seasonpackage 4131 } 4132 4133 if (url !== false) { 4134 $.ajax({ 4135 url: url, 4136 type: 'get', 4137 dataType: 'json', 4138 data: params, 4139 success: function(data, textStatus, jqXHR) { 4140 if (typeof data.success !== 'undefined' && data.success) { 4141 ProtectedSectors.checkCouponCodeResult(seat, true, ''); 4142 } else { 4143 var message = typeof data.message !== 'undefined' ? data.message : ''; 4144 ProtectedSectors.checkCouponCodeResult(null, false, message); 4145 } 4146 }, 4147 error: function(jqXHR, textStatus, errorThrown) { 4148 ProtectedSectors.checkCouponCodeResult(null, false, ''); 4149 }, 4150 cache: false 4151 }); 4152 } 4153 }, 4154 4155 //process coupon code checking result - show error or select seat on success 4156 checkCouponCodeResult: function(seat, success, message) { 4157 if (success) { 4158 //coupon code accepted - select seat 4159 var protection_id = typeof this.sector[seat.sector_id] !== 'undefined' ? this.sector[seat.sector_id] : 0; 4160 if (protection_id && seat) { 4161 this.used.push(protection_id); 4162 if (typeof seat.capacity === 'undefined') { 4163 //select seat 4164 document.dispatchEvent(new CustomEvent("seatForceSelect", { 4165 detail: { 4166 'seat': seat 4167 } 4168 })); 4169 } else { 4170 //capacity sector 4171 audit.openCapacityPopup(seat.sector_id); 4172 } 4173 4174 if (this.filterEnabled) { 4175 this.markActivatedFilter(protection_id); 4176 } 4177 } 4178 } else { 4179 //bad coupon code 4180 if (message === '') { 4181 message = js_lang.invlid_coupon_code; 4182 } 4183 revDialog({ 4184 title: js_lang.audit_error_popup_title, 4185 content: message, 4186 rightButton: { 4187 label: js_lang.admin_bmit, 4188 close: true, 4189 class: 'dark' 4190 } 4191 }); 4192 } 4193 }, 4194 4195 //mark protected sectors as unavailable 4196 closeProtectedSectors: function(sector_id) { 4197 var protection_id = typeof this.sector[sector_id] !== 'undefined' ? this.sector[sector_id] : 0; 4198 var sectors = []; 4199 if (protection_id) { 4200 for(var i in this.sector) { 4201 if (this.sector[i] === protection_id) { 4202 sectors.push(parseInt(i, 10)); 4203 } 4204 } 4205 document.dispatchEvent(new CustomEvent("closeSectors", { 4206 detail: { 4207 'sectors': sectors 4208 } 4209 })); 4210 } 4211 }, 4212 4213 //try to add coupon filters 4214 addFilters: function() { 4215 var parent = $('div.usagepart'); 4216 4217 if ($(parent).length === 0) { 4218 var tc = $('div.ticket-categories'); 4219 if ($(tc).length === 1) { 4220 parent = $('<div>').attr('id', 'sector-filters'); 4221 $(parent).insertAfter(tc); 4222 } 4223 } 4224 4225 if ($(parent).length === 1) { 4226 this.filterEnabled = true; 4227 var filterObj = $('<div>').html('<h4>' + js_lang.label_coupon_sector_title + '</h4><ul id="coupon-filters"></ul>'); 4228 $(parent).append(filterObj); 4229 var item_class = audit.mlszEnabled ? 'soldout' : 'seat-soldout'; 4230 4231 for(var permission_id in this.name) { 4232 var item = $('<li>').addClass(item_class).text(this.name[permission_id]).attr('id', 'secperm' + permission_id); 4233 var sector_ids = []; 4234 for(var sector_id in this.sector) { 4235 if (this.sector[sector_id] == permission_id) { 4236 sector_ids.push(sector_id); 4237 } 4238 } 4239 item.attr('data-sectors', sector_ids.join(',')); 4240 $('ul#coupon-filters').append(item); 4241 } 4242 4243 $(document).on('mouseenter', 'ul#coupon-filters > li', function() { 4244 $(this).addClass('highlighted'); 4245 ProtectedSectors.updateFilters(); 4246 }); 4247 $(document).on('mouseleave', 'ul#coupon-filters > li', function() { 4248 if (!$(this).hasClass('hold')) { 4249 $(this).removeClass('highlighted'); 4250 ProtectedSectors.updateFilters(); 4251 } 4252 }); 4253 $(document).on('click', 'ul#coupon-filters > li', function() { 4254 if ($(this).hasClass('hold')) { 4255 $(this).removeClass('hold').removeClass('highlighted'); 4256 } else { 4257 $(this).addClass('hold').addClass('highlighted'); 4258 } 4259 ProtectedSectors.updateFilters(); 4260 }); 4261 } 4262 }, 4263 4264 markActivatedFilter: function(permission_id) { 4265 $('li#secperm' + permission_id).attr('class', ''); 4266 $('li#secperm' + permission_id).addClass(audit.mlszEnabled ? 'taken' : 'seat-available'); 4267 }, 4268 4269 //update sector filters for price highlights 4270 updateFilters: function() { 4271 var filteredSectors = []; 4272 $('ul#coupon-filters li.highlighted').each(function() { 4273 var sectors = $(this).attr('data-sectors').split(','); 4274 for(var i=0; i<sectors.length; i++) { 4275 var sector_id = parseInt(sectors[i], 10); 4276 if (sector_id > 0 && filteredSectors.indexOf(sector_id) === -1) { 4277 filteredSectors.push(sector_id); 4278 } 4279 } 4280 }); 4281 if (TicketGroup.filteredSectors.join(',') !== filteredSectors.join(',')) { 4282 TicketGroup.filteredSectors = filteredSectors; 4283 TicketGroup.updateFilter(); 4284 } 4285 } 4286}; 4287 4288//seat selection test 4289var Testing = { 4290 enabled: false, 4291 sectorsDiv: false, 4292 seatsDiv: false, 4293 sectorLoading: 0, 4294 4295 //create objects 4296 init: function() { 4297 //initialize custom event listeners 4298 if (this.seatsDiv === false && this.sectorsDiv === false) { 4299 //update seat list after sector selection 4300 document.addEventListener("seatListToTest", function (e) { 4301 if (typeof e.detail.list !== 'undefined') { 4302 Testing.builidSeatList(e.detail.list); 4303 } 4304 }); 4305 } 4306 4307 //initialize html dom objects 4308 if (this.sectorsDiv === false) {
4309 this.sectorsDiv = $('<div>').attr('id', 'testing-sectors').attr('data-loading', 'true'); 4310 $(this.sectorsDiv).attr('style', 'position:fixed; width:400px; height:120px; top:10px; left:10px; background-color:white; border:1px solid black; padding:5px 10px; overflow:auto; z-index: 10001;'); 4311 $('body').append(this.sectorsDiv); 4312 } 4313 if (this.seatsDiv === false) { 4314 this.seatsDiv = $('<div>').attr('id', 'testing-seats').attr('data-loading', 'false').attr('data-sector', '0'); 4315 $(this.seatsDiv).attr('style', 'position:fixed; width:400px; height:120px; top:10px; left:450px; background-color:white; border:1px solid black; padding:5px 10px; overflow:auto; z-index: 10001;'); 4316 $('body').append(this.seatsDiv); 4317 } 4318 4319 //add ID for basket item 4320 var basketObj = $('a.mini-basket')[0]; 4321 if (!$(basketObj).attr('id')) { 4322 $(basketObj).attr('id', 'mini-basket-link'); 4323 } 4324 }, 4325 4326 //tesing setup and intializing 4327 start: function() { 4328 this.enabled = true; 4329 this.init(); 4330 4331 $(this.sectorsDiv).on('click', 'a', function() { 4332 if (!$('div#loading').is(':visible')) { 4333 Testing.mark(this); 4334 Testing.clickSector($(this).attr('data-id')); 4335 } 4336 }); 4337 $(this.seatsDiv).on('click', 'a', function() { 4338 if (!$('div#loading').is(':visible')) { 4339 Testing.mark(this); 4340 Testing.clickSeat($(this).attr('data-id')); 4341 } 4342 }); 4343 }, 4344 4345 //create a link list of available sectors 4346 buildSectorList: function(sectorInitialInfos) { 4347 var best = audit.bestTicketSectors; 4348 $(this.sectorsDiv).html(''); 4349 for(var id in sectorInitialInfos) { 4350 if (sectorInitialInfos[id].isFree === 1 && sectorInitialInfos[id].extraSector === 'N') { 4351 var isBest = best.indexOf(parseInt(id, 10)) > -1; 4352 var name = 'SECTOR' + id; 4353 var link = $('<a>').attr('id', 'testing-sector-' + id).attr('href', '#test').attr('data-id', id).attr('data-best', isBest ? 'true' : 'false'); 4354 if (isBest) { 4355 name = 'BEST' + name; 4356 } 4357 $(link).text('[' + name + ']'); 4358 $(this.sectorsDiv).append(link); 4359 } 4360 } 4361 $(this.sectorsDiv).attr('data-loading', 'false'); 4362 }, 4363 4364 //create a link list of available seats 4365 builidSeatList: function(seatIDList) { 4366 $(this.seatsDiv).html('').attr('data-sector', this.sectorLoading); 4367 for(var i=0; i<seatIDList.length; i++) { 4368 var id = seatIDList[i]; 4369 var link = $('<a>').attr('id', 'testing-seat-' + id).attr('href', '#test').text('[' + id + ']').attr('data-id', id); 4370 $(this.seatsDiv).append(link); 4371 } 4372 $(this.seatsDiv).attr('data-loading', 'false'); 4373 this.sectorLoading = 0; 4374 }, 4375 4376 //set free tickets attribute for sectors 4377 setSectorFreeTickets: function(sectors) { 4378 for(var sector_id in sectors) { 4379 var sectorObj = $('a#testing-sector-' + sector_id, this.sectorsDiv); 4380 if ($(sectorObj).size() === 1) { 4381 $(sectorObj).attr('data-seats', sectors[sector_id]); 4382 } 4383 } 4384 }, 4385 4386 //symulate a click event on a sector object 4387 clickSector: function(sectorID) { 4388 if (this.sectorLoading === 0) { 4389 sectorID = parseInt(sectorID, 10); 4390 if (sectorID > 0) { 4391 this.sectorLoading = sectorID; 4392 $(this.seatsDiv).attr('data-loading', 'true'); 4393 document.dispatchEvent(new CustomEvent("testSelection", { detail: { 4394 type: 'click-sector', 4395 data: { 4396 id: sectorID 4397 } 4398 }})); 4399 } 4400 } 4401 }, 4402 4403 //symulate a click event on a seat object 4404 clickSeat: function(seatID) { 4405 seatID = parseInt(seatID, 10); 4406 if (seatID > 0) { 4407 document.dispatchEvent(new CustomEvent("testSelection", { detail: { 4408 type: 'click-seat', 4409 data: { 4410 id: seatID 4411 } 4412 }})); 4413 } 4414 }, 4415 4416 //mark clicked object 4417 mark: function(domObj) { 4418 $(domObj).attr('style', 'color:YELLOW; background:BLUE;'); 4419 } 4420}; 4421 4422var AuditSocket = { 4423 socket: false, 4424 started: false, 4425 room: '', 4426 4427 //my sendings - ignore on response 4428 mySeatActions: {}, 4429 lastSeatID: 0, 4430 4431 //queue sending 4432 queueList: [], 4433 queueIndex: 0, 4434 queueRun: false, 4435 4436 init: function(host, port, room_prefix) { 4437 if (typeof auditview_token === 'undefined' || this.started) { 4438 //token required or is already started 4439 return false; 4440 } 4441 4442 this.room = room_prefix + audit.eventId.toString();
4443 this.socket = new WebSocket('wss://' + host + ':' + port + '?token=' + auditview_token); 4444 4445 this.socket.addEventListener('open', (event) => { 4446 AuditSocket.started = true; 4447 //console.log('Socket ready'); 4448 setTimeout(() => { 4449 AuditSocket.setRoom(); 4450 }, 50); 4451 }); 4452 4453 this.socket.addEventListener('close', (event) => { 4454 //console.log('Socket is closed', JSON.stringify(event)); 4455 AuditSocket.started = false; 4456 }); 4457 4458 this.socket.addEventListener('message', (event) => { 4459 const message = event.data; 4460 //console.log("Received message: " + message); 4461 if (message === 'ok') { 4462 if (AuditSocket.queueRun) { 4463 AuditSocket.processQueue(); 4464 } 4465 } else if (message !== '') { 4466 var operation = message.substring(0, 1); 4467 var parameters = message.substring(1); 4468 AuditSocket.processResult(operation, parameters); 4469 } 4470 }); 4471 4472 return true; 4473 }, 4474 4475 setRoom: function() { 4476 this.send('>' + this.room); 4477 }, 4478 4479 selectSeat: function(seatID) { 4480 this.lastSeatID = seatID; 4481 this.mySeatActions[seatID] = true; 4482 this.queue('+' + this.room + ':' + seatID); 4483 }, 4484 4485 unselectSeat: function(seatID) { 4486 this.lastSeatID = seatID; 4487 this.mySeatActions[seatID] = true; 4488 this.queue('-' + this.room + ':' + seatID); 4489 }, 4490 4491 updateSector: function(sectorID) { 4492 var seats = SeatingChart.getSectorSeats(sectorID); 4493 var lastSeatID = this.lastSeatID; 4494 if (seats.length < 15) { 4495 //special sectors are small 4496 for(var i=0; i<seats.length; i++) { 4497 if (seats[i].id == lastSeatID) { 4498 //not send again clicket seat 4499 continue; 4500 } 4501 if (seats[i].status === 0) { 4502 this.unselectSeat(seats[i].id); 4503 } else { 4504 this.selectSeat(seats[i].id); 4505 } 4506 } 4507 } 4508 }, 4509 4510 queue: function(message) { 4511 this.queueList.push(message); 4512 if (!this.queueRun) { 4513 this.processQueue(); 4514 } 4515 }, 4516 4517 processQueue: function() { 4518 if (!this.queueRun && this.queueList.length > 0) { 4519 //start queue 4520 this.queueRun = true; 4521 this.queueIndex = 0; 4522 } 4523 4524 if (this.queueRun) { 4525 if (typeof this.queueList[this.queueIndex] !== 'undefined') { 4526 //send next message 4527 var message = this.queueList[this.queueIndex]; 4528 this.queueIndex++; 4529 this.send(message); 4530 } else { 4531 //queue finished - reset 4532 this.queueList = []; 4533 this.queueRun = false; 4534 } 4535 } 4536 }, 4537 4538 send: function(message) { 4539 if (!this.started) { 4540 //not started 4541 //console.error('Socket not started'); 4542 } else if (this.socket.readyState === WebSocket.OPEN) { 4543 //socket is ready: send message 4544 //console.log('send message: ' + message); 4545 this.socket.send(message); 4546 } else { 4547 //socket bad status 4548 //console.error('Socket not ready'); 4549 } 4550 }, 4551 4552 processResult: function(operation, parameters) { 4553 if (operation === '+' || operation === '-') { 4554 //+ a seat has been selected - mark as unavailable 4555 //- a seat has been unselected - mark as available 4556 if (typeof this.mySeatActions[parameters] !== 'undefined' && this.mySeatActions[parameters]) { 4557 //ignore operation - is my action 4558 this.mySeatActions[parameters] = false; 4559 } else { 4560 var seat_new_status = operation === '+' ? 2 : 0; //2-unavailable 0-available 4561 var seat_id = parseInt(parameters, 10); 4562 var price = Seat.getTicketPrice(seat_id); 4563 var groupd_id = operation === '+' 4564 ? 0 //remove group on select or add group on release 4565 : (price in TicketGroup.list ? TicketGroup.list[price].index : TicketGroup.getGroupIndexByPrice(price)); 4566 if (groupd_id === false) { 4567 //calculate group if required 4568 groupd_id = price > 0 ? (price * 1000 + 1) : 0; 4569 } 4570 Seat.changeStatusWithRefresh(seat_id, seat_new_status, groupd_id); 4571 if (operation === '+') { 4572 TicketGroup.decreaseTicket(price); 4573 } else { 4574 TicketGroup.increaseTicket(price); 4575 } 4576 document.dispatchEvent(new CustomEvent("viewerRedraw")); 4577 } 4578 } 4579 } 4580};
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.