PageSourceSearch

https://cuacfm.org/wp-content/plugins/eventprime-advanced-seat-pla…ime-advanced-live-seating-public.js?ver=1.4

js cuacfm.org collected 2026-09-24 09:17:59 UTC 45,942 bytes, 1,057 lines download raw bytes

1(function( $ ) {
2	'use strict';
3
4	/**
5	 * All of the code for your public-facing JavaScript source
6	 * should reside in this file.
7	 *
8	 * Note: It has been assumed you will write jQuery code here, so the
9	 * $ function reference has been prepared for usage within the scope
10	 * of this function.
11	 *
12	 * This enables you to define handlers, for when the DOM is ready:
13	 *
14	 * $(function() {
15	 *
16	 * });
17	 *
18	 * When the window is loaded:
19	 *
20	 * $( window ).load(function() {
21	 *
22	 * });
23	 *
24	 * ...and/or other possibilities.
25	 *
26	 * Ideally, it is not considered best practise to attach more than a
27	 * single DOM-ready or window-load handler for a particular page.
28	 * Although scripts in the WordPress core, Plugins and Themes may be
29	 * practising this, we should strive to set a better example in our own work.
30	 */
31        
32        
33        $('#gridContainerFrontend .seat.selectable').each(function() {
34            var color = $(this).attr('data-available-color');
35            $(this).children('div').children('svg').css('fill',color);
36        });
37        
38        // Initialize Select2 with template for custom color indicators
39        $('#ep_ls_front_ticket_choose_ticket').select2({
40            templateResult: formatOption,
41            templateSelection: formatOption
42        });
43
44         // show/hide the seat info
45    $( document ).on( 'click', '.ep-als-expand-seat-info', function() {
46        let seat_ticket_id = $( this ).data( 'ticket_id' );
47        let expand_html = $( this ).html();
48        if( expand_html == 'expand_less' ) {
49            $( this ).html( 'expand_more' );
50        } else{
51            $( this ).html( 'expand_less' );
52        }
53        $( '#ep_single_ticket'+seat_ticket_id+'_seat_info' ).toggle( 500 );
54    });
55    
56    
57    
58    
59    //Frontend zoom and zoom out
60
61
62
63    let zoomLevel = 1;
64    const supportsZoom = typeof document.body.style.zoom !== 'undefined';
65    const $gridContainerFrontend = $('#gridContainerFrontend');
66    let baseGridHeight = 0;
67
68    $gridContainerFrontend.css('transform-origin', 'top left'); // Fallback for non-zoom browsers
69
70    function updateZoom(isZoomIn = true) {
71        zoomLevel = isZoomIn ? zoomLevel + 0.1 : Math.max(0.1, zoomLevel - 0.1);
72        if (supportsZoom) {
73            if (!baseGridHeight && $gridContainerFrontend.length) {
74                baseGridHeight = $gridContainerFrontend[0].getBoundingClientRect().height;
75            }
76            $gridContainerFrontend.css({
77                zoom: zoomLevel,
78                transform: '',
79                height: baseGridHeight ? (baseGridHeight / zoomLevel) + 'px' : ''
80            });
81        } else {
82            $gridContainerFrontend.css('transform', 'scale(' + zoomLevel + ')');
83        }
84
85        // Class toggles for visual feedback
86        if (isZoomIn) {
87            $gridContainerFrontend.addClass("ep-preview-scale-up").removeClass("ep-preview-scale-down");
88        } else {
89            $gridContainerFrontend.addClass("ep-preview-scale-down").removeClass("ep-preview-scale-up");
90        }
91
92        //console.log('Zoom Level:', zoomLevel);
93    }
94
95// Zoom In
96    $('#ep-zoom-plan-in').on('click', function () {
97        updateZoom(true);
98    });
99
100// Zoom Out
101    $('#ep-zoom-plan-out').on('click', function () {
102        updateZoom(false);
103    });
104        
105        
106
107})( jQuery );
108
109function ep_seat_selection(seat)
110{
111        jQuery(seat).toggleClass('selected');
112        var color = jQuery(seat).attr('data-selected-color');
113        var ticket_id = jQuery(seat).attr('data-ticketid');
114        var available_color = jQuery(seat).attr('data-available-color');
115        var virtual_id = jQuery(seat).attr('data-virtual-id');
116        var seat_id = jQuery(seat).attr('data-ep-als-seat-id');
117        var amenities = jQuery(seat).attr('data-amenities');
118        
119        //console.log(color);
120        var seatObject = {
121            area_id: ticket_id,
122    uniqueIndex: seat_id,
123    seatSequence: virtual_id,
124    seatColor: available_color,
125    ticket_id: ticket_id,
126    amenities:JSON.parse(amenities)
127}; 
128        if(jQuery(seat).hasClass("selected"))
129        {
130            jQuery(seat).children('div').children('svg').css('fill',color);
131            ep_ls_update_cart_tickets_data( 'plus', seatObject );
132        }
133        else
134        {
135            jQuery(seat).children('div').children('svg').css('fill',available_color);
136            ep_ls_update_cart_tickets_data( 'minus', seatObject );
137        }
138}
139
140// Function to style each option
141function formatOption(option) {
142            if (!option.id) {
143                return option.text; // Return text for placeholder
144            }
145            
146            // Get color from data-style attribute
147            const colorStyle = jQuery(option.element).data('style');
148            
149            // Create a color indicator using a span with the background color
150            return jQuery('<span>').css('background-color', colorStyle.split(':')[1])
151                .addClass('color-indicator')
152                .css({
153                    'display': 'inline-block',
154                    'width': '15px',
155                    'height': '15px',
156                    'border-radius': '50%',
157                    'margin-right': '8px',
158                    'vertical-align': 'middle'
159                })
160                .add(jQuery('<span>').text(option.text)); // Add text after color indicator
161        }
162        
163
164function ep_highlight_related_seat(ticket)
165{
166    var id= jQuery(ticket).val();
167    
168    if(id!=="")
169    {
170        jQuery('.seat').addClass('ep-hide-seat');
171        jQuery('.ep-hide-seat').removeAttr('onclick');
172        jQuery('.seat_ticket_'+id).removeClass('ep-hide-seat');
173        jQuery('.seat_ticket_'+id).attr('onclick','ep_seat_selection(this)');
174    }
175    else
176    {
177        jQuery('.seat').removeClass('ep-hide-seat');
178        jQuery('.seat').attr('onclick','ep_seat_selection(this)');
179    }
180    
181}
182
183
184/* seat selection and add to cart */
185function ep_ls_update_cart_tickets_data(action, column_data) {
186    $= jQuery;
187        if( column_data.ticket_id ) {
188            let ticket_id = column_data.ticket_id;
189            //let ticket_price = column_data.price;
190            let ep_added_ticket_option = $( '#ep_event_booking_ticket' ).attr( 'data-ticket_options' );
191            let ep_added_offer_option = $('#ep_event_offer_data').val();
192
193            if( !ep_added_ticket_option ) {
194                ep_added_ticket_option = [];
195            } else{
196                ep_added_ticket_option = JSON.parse( ep_added_ticket_option );
197            }
198
199            if( !ep_added_offer_option ) {
200                ep_added_offer_option = [];
201            } else{
202                ep_added_offer_option = JSON.parse( ep_added_offer_option );
203            }
204            
205            let qty = 0;
206            $.each( ep_added_ticket_option, function( idx, ticket_option ) {
207                if( ticket_option.id == ticket_id ) {
208                    ticket_found = 1;
209                    added_ticket_option_index = idx;
210                    qty = ticket_option.qty;
211                    return false;
212                }
213            });
214
215            if( action == 'plus' ) {
216                qty++;
217            } else{
218                qty--;
219            }
220            
221            if (qty < 0) qty = 0;
222
223            if (qty == 0) {
224                // Remove ticket logic without AJAX request
225                const ticketIndex = ep_added_ticket_option.findIndex(
226                    (ticket) => ticket.id === parseInt(ticket_id)
227                );
228                if (ticketIndex > -1) {
229                    ep_added_ticket_option.splice(ticketIndex, 1); // Remove ticket from data
230                }
231                console.log(ticketIndex);
232                // Remove ticket from UI
233                $('#single_ticket_detail' + ticket_id).remove();
234                // Update ticket options in DOM
235                $('#ep_event_booking_ticket').attr('data-ticket_options', JSON.stringify(ep_added_ticket_option));
236                // Recalculate total
237                ep_ls_calculate_tickets_total();
238
239                if( ep_added_ticket_option.length > 0 ) {
240                    $( '#ep_als_single_event_checkout_btn' ).removeAttr( 'disabled' );
241                } else{
242                    $( '#ep_als_single_event_checkout_btn' ).attr( 'disabled', 'disabled' );
243                }
244
245                return; // Exit the function since no server request is needed
246            }
247
248            // Show loading indicator
249            $('#ep-event-ticket-checkout-modal .ep-loader').show();
250            $('#ep-event-ticket-checkout-modal .ep-loader').parent('.ep-modal-body').addClass('ep-loader-active');
251
252            let data = { 
253                action: 'ep_als_update_tickets_data',
254                ticket_id: ticket_id,
255                qty: qty,
256                security: em_front_event_object.em_event_data.single_event_nonce
257            };
258
259            $.ajax({
260                type        : "POST",
261                url         : eventprime.ajaxurl,
262                data        : data,
263                success     : function( response ) {
264                    if( response.success == true ) {     
265                        const data = response.data;
266                        const single_ticket_detail_id = 'single_ticket_detail' + data.id;
267                        if(response.data) {
268                            console.log(response.data);
269                            let new_seat_data = { 
270                                'area_id': column_data.area_id, 
271                                'seat_data': [{
272                                    'uid' : column_data.uniqueIndex,
273                                    'seat': column_data.seatSequence,
274                                    'amenities':column_data.amenities
275                                }]
276                            }
277                            var ticket_price = response.data.price;
278                            var total_offer_discount_val = response.data.offer;
279                            var ticket_price_subtotal = response.data.subtotal;
280                            let ticket_var_data = {
281                                ...response.data, 
282                                seats: [new_seat_data], 
283                            };
284                            const ticketIndex = ep_added_ticket_option.findIndex(
285                                (ticket) => ticket.id === data.id
286                            );
287                            if (ticketIndex > -1) {
288                                // Update existing ticket
289                                console.log(ticketIndex);
290                                let added_seat_data = ep_added_ticket_option[ticketIndex];
291                                
292                                if( qty == 0 ) {
293                                    ep_added_ticket_option.splice( ticketIndex, 1 );
294                                    $( '#single_ticket_detail' + added_seat_data.id ).remove();
295                                } else{
296                                    added_seat_data.qty = qty;
297                                    added_seat_data.offer = total_offer_discount_val,
298                                    added_seat_data.subtotal = ticket_price_subtotal;
299                                    if( action == 'plus' ) {
300                                        let area_found = 0;
301                                        $.each( added_seat_data.seats, function(idx, old_seat_data ) {
302                                            if( old_seat_data.area_id == column_data.area_id ) {
303                                                area_found = 1;
304                                                let osd = old_seat_data.seat_data;
305                                                let new_seat = {
306                                                    'uid' : column_data.uniqueIndex,
307                                                    'seat': column_data.seatSequence,
308                                                    'amenities':column_data.amenities
309                                                }
310                                                old_seat_data.seat_data.push( new_seat );
311                                                return false;
312                                            }
313                                        });
314                                        if( area_found == 0 ) {
315                                            let new_seat_data = { 
316                                                'area_id': column_data.area_id, 
317                                                'seat_data': [{
318                                                    'uid' : column_data.uniqueIndex,
319                                                    'seat': column_data.seatSequence,
320                                                    'amenities':column_data.amenities
321                                                }]
322                                            }
323                                            added_seat_data.seats.push( new_seat_data );
324                                        }
325                                    } else{
326                                        let seat_found = 0;
327                                        $.each( added_seat_data.seats, function(idx, old_seat_data ) {
328                                            if( old_seat_data.area_id == column_data.area_id ) {
329                                                let osd = old_seat_data.seat_data;
330                                                $.each( osd, function( os_id, os_data ) {
331                                                    if( os_data.uid == column_data.uniqueIndex ) {
332                                                        old_seat_data.seat_data.splice( os_id, 1 );
333                                                        return false;
334                                                    }
335                                                });
336                                            }
337                                        });
338                                    }
339                                    
340                                    ep_added_ticket_option[ticketIndex] = added_seat_data;
341                                }
342                            } else {
343                                // Add new ticket
344                                ep_added_ticket_option.push(ticket_var_data);
345                            }
346                            const ticketHTML = generateTicketHTML(data);
347                            
348                            let formated_price = ep_format_price_with_position( ticket_price );
349                            // Append the HTML to the container
350                            if( $( '#ep_event_booking_ticket #' + single_ticket_detail_id ).length > 0 ) {
351                                $( '#ep_single_ticket'+ ticket_id +'_qty' ).html( qty );
352                                $( '#ep_single_ticket'+ ticket_id +'_price' ).html( formated_price );
353                                // offer applied text
354                                $( '#ep_single_ticket'+ticket_id+'_offer_text' ).html( ticket_var_data.offer_text );
355                                // offer amount
356                                $( '#ep_single_ticket'+ticket_id+'_offer_value' ).html( `-${ep_format_price_with_position(ticket_var_data.offer)}` );
357                
358                                let ticket_price_subtotal = ticket_var_data.subtotal; 
359                                // add additional fees
360                                if( ticket_var_data.additional_fees ) {
361                                    $( JSON.parse( ticket_var_data.additional_fees ) ).each( function(ind, data ) {
362                                        let multi_add_fee = data.price * qty;
363                                        $( '#ep_additional_price_' + ticket_id + '_' + ind ).html( ep_format_price_with_position( multi_add_fee ) );
364                                        ticket_price_subtotal = parseFloat( ticket_price_subtotal ) + parseFloat( multi_add_fee );
365                                    });
366                                }
367                                $( '#ep_single_ticket'+ ticket_id +'_subtotal' ).html( ep_format_price_with_position( ticket_price_subtotal ) );
368                                $( '#ep_single_ticket'+ ticket_id +'_subtotal' ).data( 'row_subtotal',  ticket_price_subtotal);
369                            } else {
370                                $('#ep_event_booking_ticket').append(ticketHTML);
371                            }
372                        }
373                        $('.ep-event-offer-applied_'+ data.id).hide();
374                        data.applied_offer_uid.forEach((offeruid, index) => {
375                            $('#ep_event_offer_'+ data.id+'_'+ offeruid).show();
376                        });
377                        
378                        $('#ep_als_single_event_checkout_btn').prop('disabled', false);
379                        
380                    
381                    } else {
382                        if (response && response.data && response.data.message) {
383                            $('#ep_single_event_before_checkout_error_msg').html(response.data.message);
384                        } else {
385                            $('#ep_single_event_before_checkout_error_msg').html('Error updating tickets.');
386                        }
387                    }
388                    // return 
389                    $( '#ep_event_booking_ticket' ).attr( 'data-ticket_options', JSON.stringify( ep_added_ticket_option ) );
390                    // update seat data to info
391                    // Get seats data for current tic 
392                    const currentTicData = ep_added_ticket_option.find(obj => obj.id == ticket_id);
393                    const currentTicSeatData = currentTicData.seats[0].seat_data; 
394                    for ( seatObj of currentTicSeatData ) {
395                        //let info_html = '<div class="ep-box-col-12 ep-text-end" id="ep_single_ticket'+ticket_id+'_seat_num_'+seatObj.seat+'">'+seatObj.seat+'</div>';
396                        let amenities_html = '';
397                        if (Array.isArray(seatObj.amenities) && seatObj.amenities.length > 0) {
398                            amenities_html = '<ul class="ep-seat-amenities" style="margin-top: 4px; font-size: 12px;">';
399
400                            seatObj.amenities.forEach(function(item) {
401                                amenities_html += '<li>';
402                                
403                                if (item.icon) {
404                                    amenities_html += '<img src="' + item.icon + '" alt="' + item.title + '" title="' + item.title + '" style="width:16px; height:16px; margin-right:4px; vertical-align:middle;" />';
405                                } 
406                                else
407                                {
408                                    amenities_html += '<img src="' + ep_als_front_ticket_object.amenity_icon + '" alt="' + item.title + '" title="' + item.title + '" style="width:16px; height:16px; margin-right:4px; vertical-align:middle;" />';
409                                    
410                                }
411                                if (item.title) {
412                                    amenities_html += '<span>' + item.title + '</span>';
413                                }
414                                amenities_html += '</li>';
415                            });
416
417                            amenities_html += '</ul>';
418                        }
419
420                        let info_html = '<div class="ep-box-col-12 ep-text-end" id="ep_single_ticket' + ticket_id + '_seat_num_' + seatObj.seat + '">' +
421                            seatObj.seat +
422                            amenities_html +
423                            '</div>';
424
425
426                        $( '#ep_single_ticket'+ticket_id+'_seat_info' ).append( info_html );
427                    }
428                    ep_ls_calculate_tickets_total();
429
430                    $('#ep_single_event_before_checkout_error_msg').html('');
431                    $('#ep-event-ticket-checkout-modal .ep-loader').parent('.ep-modal-body').removeClass('ep-loader-active');
432                    $('#ep-event-ticket-checkout-modal .ep-loader').hide();
433                    
434                }
435            });            
436            if( ep_added_ticket_option.length > 0 ) {
437                $( '#ep_als_single_event_checkout_btn' ).removeAttr( 'disabled' );
438            } else{
439                $( '#ep_als_single_event_checkout_btn' ).attr( 'disabled', 'disabled' );
440            }
441        }
442
443    }
444    
445    
446    function generateTicketHTML_single_Ticket(ticketData) {
447        const $ = jQuery;
448        let additionalFeesHTML = '';
449        let offerHtml = '';
450        let seatHTML = "";
451        $( '#ep_single_ticket'+ ticketData.id +'_qty' ).html( ticketData.qty );
452        if (ticketData.additional_fee && ticketData.additional_fee.length > 0) {
453            ticketData.additional_fee.forEach((fee, index) => {
454                additionalFeesHTML += `
455                    <div class="ep-box-col-6 ep-text-small">${fee.label}</div>
456                    <div class="ep-box-col-6 ep-text-end ep-text-small" id="ep_additional_price_${ticketData.id}_${index}">${ep_format_price_with_position(fee.price)}</div>
457                `;
458            });
459        }
460        
461        if(ticketData.offer && ticketData.offer > 0)
462        {
463            offerHtml += ` 
464            <div class="ep-box-col-6 ep-text-small">
465                    <em id="ep_single_ticket${ticketData.id}_offer_text">${ticketData.offer_text}</em>
466                </div>
467                <div class="ep-box-col-6 ep-text-end ep-text-small" id="ep_single_ticket${ticketData.id}_offer_value">- ${ep_format_price_with_position(ticketData.offer)}</div>
468            `;
469        }
470
471        // seats
472        seatHTML += '<div class="ep-box-col-6 ep-text-small">
472<span id="ep_single_ticket'+ticketData.id+'_seats_text">Seats</span></div>';
473        seatHTML += '<div class="ep-box-col-6 ep-text-end ep-text-small" id="ep_single_ticket'+ticketData.id+'_seat_down">';
474        seatHTML += '<span class="material-icons-outlined ep-fs-6 ep-align-middle ep-als-expand-seat-info" data-ticket_id="'+ticketData.id+'">expand_more</span>';
475        seatHTML += '<div class="ep-ls-seat-info" id="ep_single_ticket'+ticketData.id+'_seat_info" style="display:none;"></div>';
476        seatHTML += '</div>';
477        
478        return `
479            <div class="ep-box-col-6">
480                    <span id="ep_single_ticket${ticketData.id}_name">${ticketData.name}</span> x 
481                    <span class="ep-text-muted" id="ep_single_ticket${ticketData.id}_qty">${ticketData.qty}</span>
482                </div>
483                <div class="ep-box-col-6 ep-text-end" id="ep_single_ticket${ticketData.id}_price">${ep_format_price_with_position(ticketData.price)}</div>
484                <!-- Additional Fees Section -->
485                ${additionalFeesHTML}
486                ${offerHtml}
487                ${seatHTML}
488                <div class="ep-box-col-6 ep-fw-bold mt-2">${em_front_event_object.em_event_data.subtotal_text}</div>
489                <div class="ep-box-col-6 ep-text-end ep-fw-bold mt-2 ep-ticket-subtotal-row" id="ep_single_ticket${ticketData.id}_subtotal" data-row_subtotal="${ticketData.subtotal}">
490                    ${ep_format_price_with_position(ticketData.subtotal)}
491                </div>
492            
493        `;
494    }
495
496    function generateTicketHTML(ticketData) {
497        const $ = jQuery;
498        const singleTicketDetailId = 'single_ticket_detail' + ticketData.id;
499        const existingRow = $('#ep_event_booking_ticket #' + singleTicketDetailId);
500
501        // If the ticket row already exists, update the existing values
502        if (existingRow.length > 0) {
503            let ticket_data = generateTicketHTML_single_Ticket(ticketData);
504            $(existingRow).html(ticket_data);
505        } else {
506            // Generate new ticket row
507            let ticData = '<div class="ep-box-row ep-text-small ep-my-2 ep-rounded ep-p-2 ep-single-modal-ticket-row" id="' + singleTicketDetailId + '">';
508            ticData += generateTicketHTML_single_Ticket(ticketData);
509            ticData += '</div>';
510
511            return ticData;
512            // Append the new ticket row
513            // $('#ep_event_booking_ticket').append(ticData);
514        }
515    }
516
517    // Calculate tickets total
518    function ep_ls_calculate_tickets_total() {
519        const $ = jQuery;
520        let ticket_total = 0;
521        $( '#ep_event_booking_ticket .ep-ticket-subtotal-row' ).each( function() {
522            let row_subtotal = $( this ).data( 'row_subtotal' );
523            ticket_total = parseFloat( ticket_total ) + parseFloat( row_subtotal );
524        });
525        // check for fixed event price
526        if( $( '#ep_event_fixed_price' ).length > 0 ) {
527            let fixed_price = $( '#ep_event_fixed_price' ).data( 'fixed_price' );
528            if( fixed_price && fixed_price > 0 ) {
529                ticket_total = parseFloat( ticket_total ) + parseFloat( fixed_price );
530            }
531        }
532        $( '#ep_ticket_price_total' ).html( ep_format_price_with_position( ticket_total ) );
533    }
534    
535    
536
537 // go to checkout
538    jQuery( document ).on( 'click', '#ep_als_single_event_checkout_btn', function() {
539        $ = jQuery;
540        $( '#ep_ls_front_ticket_error_message' ).html( '' );
541        let ep_event_booking_ticket = $( '#ep_event_booking_ticket' ).attr( 'data-ticket_options' );
542        if( ep_event_booking_ticket ) {
543            let event_ticket_data = $( '#ep_ls_event_ticket_checkout_modal' ).data( 'event_tickets_data' );
544            if( event_ticket_data ) {
545                let et_datas = [];
546                $.each( event_ticket_data, function( idx, tic ) {
547                    et_datas[tic.id] = tic;
548                });
549                // check for allowed quantity of tickets
550                var ticket_error = 0;
551                $.each( JSON.parse( ep_event_booking_ticket ), function( idx, tic_data ){
552                    let ticid = tic_data.id;
553                    let this_ticket_data = et_datas[ticid];
554                    // check for minimum
555                    let min_allowed = this_ticket_data.min_ticket_no;
556                    if( min_allowed && tic_data.qty < min_allowed ) {
557                        ticket_error = 1;
558                        let min_er = ep_als_front_ticket_object.min_qty_error + ' ' + this_ticket_data.name + ' ' + ep_als_front_ticket_object.is_text + ' ' + min_allowed;
559                        $( '#ep_ls_front_ticket_error_message' ).html( min_er );
560                        return false;
561                    }
562                    // check for maximum
563                    let max_allowed = this_ticket_data.max_ticket_no;
564                    if( max_allowed > 0 && tic_data.qty > max_allowed ) {
565                        ticket_error = 1;
566                        let max_er = ep_als_front_ticket_object.max_qty_error + ' ' + this_ticket_data.name + ' ' + ep_als_front_ticket_object.is_text + ' ' + max_allowed;
567                        $( '#ep_ls_front_ticket_error_message' ).html( max_er );
568                        return false;
569                    }
570                });
571
572                if ( ! ticket_error ) {
573                    // check if seats are hold
574                    let booking_event_id = $( '#ep_event_booking_event_id' ).val();
575                    let data = { 
576                        action     : 'ep_als_check_ticket_for_hold_before_booking', 
577                        security   : ep_als_front_ticket_object.check_seats_for_hold_nonce, 
578                        ticket_data: ep_event_booking_ticket,
579                        do_hold    : 1,
580                        event_id   : booking_event_id
581                    };
582                    $.ajax({
583                        type: 'POST', 
584                        url :  eventprime.ajaxurl,
585                        data: data,
586                        success: function( response, textStatus, XMLHttpRequest ) {
587                            if( !response.success ) {
588                                ticket_error = 1;
589                                if( response.data.hold_seats_data ) {
590                                    let no_of_hold_seats = response.data.hold_seats_data.length;
591                                    $( '#ep_ls_front_ticket_error_message' ).html( no_of_hold_seats + ' ' + response.data.message );
592                                } else{
593                                    $( '#ep_ls_front_ticket_error_message' ).html( response.data.message );
594                                }
595                                return false;
596                            }
597                            if( ticket_error == 0 ) {
598                                let ep_event_offer_data = $( '#ep_event_offer_data' ).val();
599                                let booking_data = {
600                                    ticket: ep_event_booking_ticket,
601                                    event: booking_event_id, 
602                                    ep_event_offer_data:ep_event_offer_data,
603                                };
604                                // check if rsvp booking data saved in the session
605                                let ep_event_rsvp_booking_data = sessionStorage.getItem( 'ep_event_rsvp_booking_data' );
606                                if( ep_event_rsvp_booking_data ) {
607                                    booking_data.rsvp_booking_data = ep_event_rsvp_booking_data
608                                }
609                                $( '#ep_event_booking_data' ).val( JSON.stringify( booking_data ) );
610                                $( '#ep_event_booking_form' ).submit();
611                            }
612                        }
613                    });
614                }
615                
616                // if( ticket_error == 0 ) {
617                //     let booking_data = {
618                //         ticket: ep_event_booking_ticket,
619                //         event: booking_event_id
620                //     };
621                //     // check if rsvp booking data saved in the session
622                //     let ep_event_rsvp_booking_data = sessionStorage.getItem( 'ep_event_rsvp_booking_data' );
623                //     if( ep_event_rsvp_booking_data ) {
624                //         booking_data.rsvp_booking_data = ep_event_rsvp_booking_data
625                //     }
626                //     $( '#ep_event_booking_data' ).val( JSON.stringify( booking_data ) );
627                //     $( '#ep_event_booking_form' ).submit();
628                // }
629            } else{
630                $( '#ep_ls_front_ticket_error_message' ).html( ep_als_front_ticket_object.no_seat_error );
631            }
632        } else{
633            $( '#ep_ls_front_ticket_error_message' ).html( ep_als_front_ticket_object.no_seat_error );
634        }
635    });
636
637    
638    jQuery('#ep_auto_assign_seats').on('click', function () {
639        const $ = jQuery;
640        const count = parseInt($('#ep_random_seat_count').val());
641        if (!count || count <= 0) {
642            alert('Please enter a valid seat count.');
643            return;
644        }
645        
646        $('#ep_event_booking_ticket').attr('data-ticket_options','');
647        $('#ep_event_booking_ticket').html('');
648        
649
650        // Reset UI selections
651        $('.ep-selectable.selected').removeClass('selected').each(function () {
652            $(this).children('div').children('svg').css('fill', $(this).attr('data-available-color'));
653        });
654
655        const availableSeats = $('.ep-selectable')
656            .not('.ep-booked, .ep-reserved, .ep-unselected, .ep-hide-seat, .selected');
657
658        if (availableSeats.length < count) {
659            alert('Not enough available seats.');
660            return;
661        }
662
663//        const shuffled = availableSeats.sort(() => 0.5 - Math.random()).slice(0, count);
664//
665//        const seatGroups = {}; // {ticket_id: [DOM elements]}
666//        shuffled.each(function () {
667//            const $seat = $(this);
668//            const ticketId = $seat.attr('data-ticketid');
669//            if (!seatGroups[ticketId]) {
670//                seatGroups[ticketId] = [];
671//            }
672//            seatGroups[ticketId].push($seat);
673//        });
674//
675//        const seatPayload = [];
676//
677//        Object.keys(seatGroups).forEach(function (ticketId) {
678//            seatPayload.push({
679//                ticket_id: ticketId,
680//                qty: seatGroups[ticketId].length
681//            });
682//        });
683
684
685const shuffled = availableSeats.sort(() => 0.5 - Math.random()).slice(0, count);
686
687    const seatGroups = {}; // Grouped by ticket ID
688
689    shuffled.each(function () {
690        const $seat = $(this);
691        const ticketId = $seat.attr('data-ticketid');
692        
693        
694        let amenitiesRaw = $seat.attr('data-amenities');
695        let amenitiesParsed = [];
696
697        try {
698            if (amenitiesRaw && amenitiesRaw !== '[]') {
699                amenitiesParsed = JSON.parse(amenitiesRaw);
700            }
701        } catch (e) {
702            // Log error or ignore
703            amenitiesParsed = [];
704        }
705
706        const seatData = {
707            uid: $seat.attr('data-ep-als-seat-id'),
708            seat: $seat.attr('data-virtual-id'),
709            amenities: amenitiesParsed
710        };
711
712        
713        
714//        const seatData = {
715//            uid: $seat.attr('data-ep-als-seat-id'),
716//            seat: $seat.attr('data-virtual-id'),
717//            //seatSequence: $seat.attr('data-virtual-id'),
718//            amenities: $seat.attr('data-amenities')
719//        };
720        console.log(seatData);
721        if (!seatGroups[ticketId]) {
722            seatGroups[ticketId] = [];
723        }
724        seatGroups[ticketId].push({
725            dom: $seat,
726            data: seatData
727        });
728    });
729
730    const payload = []; // For AJAX
731    const uiData = []; // For updating right side cart
732
733    Object.keys(seatGroups).forEach(ticketId => {
734        payload.push({
735            ticket_id: ticketId,
736            qty: seatGroups[ticketId].length,
737            seat_data: seatGroups[ticketId].map(s => s.data)
738            
739        });
740
741//        uiData.push({
742//            id: ticketId,
743//            seats: [{
744//                seat_data: seatGroups[ticketId].map(s => s.data)
745//            }]
746//        });
747
748
749        uiData.push({
750            id: ticketId,
751            price: parseFloat($('#ep_single_ticket' + ticketId + '_price').attr('data-price')) || 0,
752            qty: seatGroups[ticketId].length,
753            total: parseFloat($('#ep_single_ticket' + ticketId + '_price').attr('data-price')) * seatGroups[ticketId].length,
754            seats: [{
755                seat_data: seatGroups[ticketId].map(s => s.data)
756            }]
757        });
758
759
760    });
761console.log("Before sending:", JSON.stringify(payload));
762
763        // AJAX to new endpoint
764        $.ajax({
765            type: 'POST',
766            url: eventprime.ajaxurl,
767            data: {
768                action: 'ep_als_bulk_assign_tickets_data',
769                security: em_front_event_object.em_event_data.single_event_nonce,
770                seats: JSON.stringify(payload)
771            },
772            success: function (response) {
773               // console.log(response);
774                 ep_ls_update_bulk_cart_tickets(response.data.results);
775                if (response.success && response.data.results) {
776                    // On success, update visual seats
777                    Object.keys(seatGroups).forEach(function (ticketId) {
778                        seatGroups[ticketId].forEach(function ($seat) {
779                           // Locate actual seat element using seat UID
780                           //console.log($seat.data);
781                            const seatElement = $(`[data-ep-als-seat-id="${$seat.data.uid}"]`);
782                            seatElement.addClass('selected');
783                            seatElement.children('div').children('svg').css('fill', seatElement.attr('data-selected-color'));
784
785                            //$seat.addClass('selected');
786                            //$seat.children('div').children('svg').css('fill', $seat.attr('data-selected-color'));
787                        });
788                    });
789                } else {
790                    alert('Seat assignment failed.');
791                    //console.warn(response);
792                }
793            },
794            error: function (err) {
795                console.error('Bulk seat AJAX error:', err);
796            }
797        });
798    });
799    
800   /*
801 jQuery('#ep_auto_assign_seats').on('click', function () {
802    const $ = jQuery;
803    const count = parseInt($('#ep_random_seat_count').val());
804    if (!count || count <= 0) {
805        alert('Please enter a valid seat count.');
806        return;
807    }
808
809    // Clear previous selections
810    $('.ep-selectable.selected').removeClass('selected').each(function () {
811        $(this).children('div').children('svg').css('fill', $(this).attr('data-available-color'));
812    });
813
814    const availableSeats = $('.ep-selectable')
815        .not('.ep-booked, .ep-reserved, .ep-unselected, .ep-hide-seat, .selected');
816
817    if (availableSeats.length < count) {
818        alert('Not enough available seats.');
819        return;
820    }
821
822    const shuffled = availableSeats.sort(() => 0.5 - Math.random()).slice(0, count);
823
824    const seatGroups = {}; // Grouped by ticket ID
825
826    shuffled.each(function () {
827        const $seat = $(this);
828        const ticketId = $seat.attr('data-ticketid');
829        const seatData = {
830            uid: $seat.attr('data-ep-als-seat-id'),
831            seat: $seat.attr('data-virtual-id'),
832            //seatSequence: $seat.attr('data-virtual-id'),
833            amenities: $seat.attr('data-amenities') ? JSON.parse($seat.attr('data-amenities')) : []
834        };
835
836        if (!seatGroups[ticketId]) {
837            seatGroups[ticketId] = [];
838        }
839        seatGroups[ticketId].push({
840            dom: $seat,
841            data: seatData
842        });
843    });
844
845    const payload = []; // For AJAX
846    const uiData = []; // For updating right side cart
847
848    Object.keys(seatGroups).forEach(ticketId => {
849        payload.push({
850            ticket_id: ticketId,
851            qty: seatGroups[ticketId].length
852        });
853
854//        uiData.push({
855//            id: ticketId,
856//            seats: [{
857//                seat_data: seatGroups[ticketId].map(s => s.data)
858//            }]
859//        });
860
861
862        uiData.push({
863            id: ticketId,
864            price: parseFloat($('#ep_single_ticket' + ticketId + '_price').attr('data-price')) || 0,
865            qty: seatGroups[ticketId].length,
866            total: parseFloat($('#ep_single_ticket' + ticketId + '_price').attr('data-price')) * seatGroups[ticketId].length,
867            seats: [{
868                seat_data: seatGroups[ticketId].map(s => s.data)
869            }]
870        });
871
872
873    });
874
875    // Send minimal data to backend
876    $.ajax({
877        type: 'POST',
878        url: eventprime.ajaxurl,
879        data: {
880            action: 'ep_als_bulk_assign_tickets_data',
881            security: em_front_event_object.em_event_data.single_event_nonce,
882            seats: payload
883        },
884        success: function (response) {
885            if (response.success) {
886                // Add visual + update right side panel with precompiled data
887                Object.keys(seatGroups).forEach(ticketId => {
888                    seatGroups[ticketId].forEach(({ dom }) => {
889                        dom.addClass('selected');
890                        dom.children('div').children('svg').css('fill', dom.attr('data-selected-color'));
891                    });
892                });
893
894                // Directly update the cart without waiting for backend to return seat details
895                ep_ls_update_bulk_cart_tickets(uiData);
896            } else {
897                alert('Seat assignment failed.');
898                console.warn(response);
899            }
900        },
901        error: function (err) {
902            console.error('Bulk seat AJAX error:', err);
903        }
904    });
905});
906*/
907
908function ep_ls_bulk_assign_seats(seatObjects) {
909    const $ = jQuery;
910    // Step 1: Clone the current ticket_options
911    let ticketOptionsJson = $('#ep_event_booking_ticket').attr('data-ticket_options');
912    let ticketOptions = ticketOptionsJson ? JSON.parse(ticketOptionsJson) : [];
913
914    seatObjects.forEach((seatObj) => {
915        let ticketId = seatObj.id;
916        let seatData = seatObj.seat_data;
917
918        let ticketIndex = ticketOptions.findIndex(opt => opt.id == ticketId);
919
920        if (ticketIndex === -1) {
921            // If not found, create a new ticket entry
922            ticketOptions.push({
923                id: ticketId,
924                category_id: '0',
925                name: seatObj.name || '',
926                price: parseFloat(seatObj.price) || 0,
927                qty: seatObj.qty,
928                offer: 0,
929                additional_fee: [],
930                subtotal: parseFloat(seatObj.price) * seatObj.qty || 0,
931                offer_text: "",
932                total_offer_discount_text: 0,
933                formatted_subtotal: parseFloat(seatObj.price) * seatObj.qty || 0,
934                applied_offer_uid: [],
935                applied_offer_obj: [],
936                seats: [
937                    {
938                        area_id: seatObj.id,
939                        seat_data: [{
940                                    uid : seatObj.uid,
941                                    seat: seatObj.seat,
942                                    amenities:seatObj.amenities
943                                }]
944                       
945                    }
946                ]
947            });
948        } else {
949            // Merge with existing ticket
950            let existing = ticketOptions[ticketIndex];
951            let area = existing.seats.find(s => s.area_id == seatObj.area_id);
952            if (!area) {
953                existing.seats.push({
954                    area_id: seatObj.area_id,
955                    seat_data: [{
956                                    uid : seatObj.uid,
957                                    seat: seatObj.seat,
958                                    amenities:seatObj.amenities
959                                }]
960                });
961            } else {
962                area.seat_data.push(...seatData.map(sd => ({
963                    uid: sd.uid,
964                    seat: sd.seat,
965                    amenities: []
966                })));
967            }
968
969            existing.qty += seatData.length;
970            existing.subtotal += parseFloat(seatObj.ticket_price) * seatData.length;
971            existing.formatted_subtotal = existing.subtotal;
972        }
973    });
974
975    // Step 2: Update DOM attribute
976    $('#ep_event_booking_ticket').attr('data-ticket_options', JSON.stringify(ticketOptions));
977
978    // Step 3: Rerun the cart render logic (simulate click behavior)
979    generateTicketHTML(ticketOptions);
980}
981
982   
983    function ep_ls_update_bulk_cart_tickets(ticketsArray) {
984    const $ = jQuery;
985
986    let ep_added_ticket_option = $('#ep_event_booking_ticket').attr('data-ticket_options');
987    ep_added_ticket_option = ep_added_ticket_option ? JSON.parse(ep_added_ticket_option) : [];
988
989    for (const ticket of ticketsArray) {
990    const ticket_id = ticket.id;
991    const single_ticket_detail_id = 'single_ticket_detail' + ticket_id;
992    const existingIndex = ep_added_ticket_option.findIndex(t => t.id === ticket_id);
993
994    if (existingIndex > -1) {
995        ep_added_ticket_option[existingIndex] = ticket;
996    } else {
997        ep_added_ticket_option.push(ticket);
998    }
999
1000    // Replace or append HTML
1001    const ticketHTML = generateTicketHTML(ticket);
1002    if ($('#ep_event_booking_ticket #' + single_ticket_detail_id).length > 0) {
1003        $('#ep_event_booking_ticket #' + single_ticket_detail_id).replaceWith(ticketHTML);
1004    } else {
1005        $('#ep_event_booking_ticket').append(ticketHTML);
1006    }
1007
1008    // Update seat info section
1009    $('#ep_single_ticket' + ticket_id + '_seat_info').empty();
1010
1011    /** 🛠 FIXED PART **/
1012    if (Array.isArray(ticket.seats)) {
1013        for (const area of ticket.seats) {
1014            for (const seatObj of area.seat_data || []) {
1015                let amenities_html = '';
1016                if (Array.isArray(seatObj.amenities) && seatObj.amenities.length > 0) {
1017                    amenities_html = '<ul class="ep-seat-amenities" style="margin-top: 4px; font-size: 12px;">';
1018                    seatObj.amenities.forEach(function (item) {
1019                        amenities_html += '<li>';
1020                        if (item.icon) {
1021                            amenities_html += `<img src="${item.icon}" alt="${item.title}" title="${item.title}" style="width:16px; height:16px; margin-right:4px; vertical-align:middle;" />`;
1022                        } else {
1023                            amenities_html += `<img src="${ep_als_front_ticket_object.amenity_icon}" alt="${item.title}" title="${item.title}" style="width:16px; height:16px; margin-right:4px; vertical-align:middle;" />`;
1024                        }
1025                        if (item.title) {
1026                            amenities_html += `<span>${item.title}</span>`;
1027                        }
1028                        amenities_html += '</li>';
1029                    });
1030                    amenities_html += '</ul>';
1031                }
1032
1033                const seatInfoHTML = `
1034                    <div class="ep-box-col-12 ep-text-end" id="ep_single_ticket${ticket_id}_seat_num_${seatObj.seat}">
1035                        ${seatObj.seat}
1036                        ${amenities_html}
1037                    </div>`;
1038                $('#ep_single_ticket' + ticket_id + '_seat_info').append(seatInfoHTML);
1039            }
1040        }
1041    }
1042
1043
1044    // Update ticket data attribute
1045    $('#ep_event_booking_ticket').attr('data-ticket_options', JSON.stringify(ep_added_ticket_option));
1046
1047    // Recalculate totals
1048    ep_ls_calculate_tickets_total();
1049
1050    // Enable checkout button
1051    $('#ep_als_single_event_checkout_btn').prop('disabled', false);
1052}
1053    }
1054
1055
1056
1057

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.