PageSourceSearch

https://www.greyhound.com.au/App_Plugins/GreyhoundAustralia/BookingWidget/BookingWidget.bundle.js?ts=20251030

js greyhound.com.au collected 2026-09-24 18:41:41 UTC 104,320 bytes, 2,773 lines download raw bytes

1var nursedInfantFareCode = 'NIF';
2var mobileWidth = 768;
3
4var fareData = null;
5
6var localFares = sessionStorage.getItem('travel_fares');
7var saStopMessage = null;
8
9function loadFromUmbraco() {
10    var origin = $("#default-origin").val();
11    var destination = $("#default-destination").val();
12    
13    if (origin != '') {
14        if (origin != null) {
15
16            var originIndex = stops.filter(function (i) { return i.Code.toLowerCase() === origin.toLowerCase() || i.Description.toLowerCase() === origin.toLowerCase(); });
17            if (originIndex.length > 0) { 
18                $('#bat-origin').typeahead('val', originIndex[0].Description);
19                $('#tt-origin').typeahead('val', originIndex[0].Description);
20            }
21            $('#bat-departure').val(moment().format('DD/MM/YYYY'));
22            $('#bat-return').val('');
23            $('#bat-promo-value').val('');
24        }
25    }
26
27    if (destination != '') {
28        if (destination != null) {
29
30            var destinationIndex = stops.filter(function (i) { return i.Code.toLowerCase() === destination.toLowerCase() || i.Description.toLowerCase() === destination.toLowerCase(); });
31            if (destinationIndex.length > 0) {
32                $('#bat-destination').typeahead('val', destinationIndex[0].Description);
33                $('#tt-destination').typeahead('val', destinationIndex[0].Description);
34            }
35            $('#bat-departure').val(moment().format('DD/MM/YYYY'));
36            $('#bat-return').val('');
37            $('#bat-promo-value').val('');
38        }
39    }
40}
41
42function loadFromParameters() {
43    var url_string = window.location.href.toUpperCase();
44    var url = new URL(url_string);
45
46    var origin = url.searchParams.get("ORIGIN");
47    var destination = url.searchParams.get("DESTINATION");
48
49    var travelDate = url.searchParams.get("TRAVELDATE");
50    if (travelDate === null) {
51        if ($('#bat-departure').val().length > 0)
52        {
53            travelDate = $('#bat-departure').val();
54        }
55    }
56    var returnDate = url.searchParams.get("RETURNDATE");
57    if (returnDate === null) {
58        if ($('#bat-return').val().length > 0) {
59            returnDate = $('#bat-return').val();
60        }
61    }
62    var isReturn = url.searchParams.get("ISRETURN");
63    var promoCode = url.searchParams.get("PROMOCODE");
64
65    if (origin != null) {
66        var originIndex = stops.filter(function (i) { return i.Code.toLowerCase() === origin.toLowerCase() || i.Description.toLowerCase() === origin.toLowerCase(); });
67        if (originIndex.length > 0) {
68            try {
69                $('#bat-origin').typeahead('val', originIndex[0].Description);
70                $('#tt-origin').typeahead('val', originIndex[0].Description);
71            } catch (ex) { }
72        }
73    }
74
75    if (destination != null) {
76        var destinationIndex = stops.filter(function (i) { return i.Code.toLowerCase() === destination.toLowerCase() || i.Description.toLowerCase() === destination.toLowerCase(); });
77        if (destinationIndex.length > 0) {
78            try {
79            $('#bat-destination').typeahead('val', destinationIndex[0].Description);
80                $('#tt-destination').typeahead('val', originIndex[0].Description);
81            } catch (ex) { }
82        }
83    }
84
85    if (isReturn != null) {
86        if (isReturn !== 'TRUE') {
87            $('#bt-trip-oneway').parent().children('.radio-label').click();
88        }
89    }
90
91    if (travelDate != null) {
92        $('#bat-departure').datepicker('setDate', moment(travelDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
93        $('#bat-departure').val(moment(travelDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
94    }
95
96    if (returnDate != null) {
97        $('#bat-return').datepicker('setDate', moment(returnDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
98        $('#bat-return').val(moment(returnDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
99    }
100
101    if (promoCode != null) {
102        $('#bat-promo-toggle').click();
103        $('#bat-promo-value').val(promoCode);
104    }
105}
106
107function loadFromStorage() {
108    var travel_options = window.localStorage.getItem('travel_options');
109
110    if (travel_options == null) {
111        return;
112    }
113
114
115    travel_options = JSON.parse(travel_options);
116
117    var origin = travel_options.from.Code;
118    var destination = travel_options.to.Code; 
119
120    var travelDate = travel_options.options.TravelLegs[0].travelDate;
121    var returnDate = null;
122    if (travel_options.options.TravelLegs.length > 1) {
123        returnDate = travel_options.options.TravelLegs[1].travelDate;
124    }
125     
126    var isReturn = travel_options.options.isReturn;
127
128    var specialAssistance = travel_options.options.specialAssistance;
129    var specialAssistanceId = travel_options.options.sATypeId;
130
131    var promoCode = travel_options.options.TravelLegs[0].promotionCode;
132    if (moment(travelDate).isBefore(moment())) {
133        travelDate = moment();
134    }
135    if (returnDate != null && moment(returnDate).isBefore(moment(travelDate))) {
136        returnDate = travelDate;
137    }
138
139    $(".bat-passenger-faretype[farecode='000']").val(travel_options.passengers.adults);
140    $(".bat-passenger-faretype[farecode='041']").val(travel_options.passengers.concessions);
141    $(".bat-passenger-faretype[farecode='418']").val(travel_options.passengers.accompaniedChildren);
142    $(".bat-passenger-faretype[farecode='451']").val(travel_options.passengers.infants);
143    $(".bat-passenger-faretype[farecode='NIF']").val(travel_options.options.nursedInfants);
144    $(".bat-passenger-faretype[farecode='220']").val(travel_options.passengers.students);
145    updatePassengerInput();
146
147    if (origin != null) {
148        var originIndex = stops.filter(function (i) { return i.Code.toLowerCase() === origin.toLowerCase() || i.Description.toLowerCase() === origin.toLowerCase(); });
149        if (originIndex.length > 0) {
150            $('#bat-origin').typeahead('val', originIndex[0].Description);
151        }
152    }
153
154    if (destination != null) {
155        var destinationIndex = stops.filter(function (i) { return i.Code.toLowerCase() === destination.toLowerCase() || i.Description.toLowerCase() === destination.toLowerCase(); });
156        if (destinationIndex.length > 0) {
157            $('#bat-destination').typeahead('val', destinationIndex[0].Description);
158        }
159    }
160
161    if (isReturn != null) {
162        if (isReturn !== true) {
163            $('#bt-trip-oneway').parent().children('.radio-label').click();
164        }
165    }
166
167    if (travelDate != null) {
168        $('#bat-departure').val(moment(travelDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
169    }
170    if (returnDate != null) {
171        $('#bat-return').val(moment(returnDate, 'YYYY-MM-DD').format('DD/MM/YYYY'));
172    }
173    setTimeout(function () {
174        if (specialAssistance === true) {
175            $('.bat-special-assistance-toggle').click();
176            $('input[satype="' + specialAssistanceId + '"]').parentsUntil('.pax-sa-option').click();
177            $('input[satype="' + specialAssistanceId + '"]').parentsUntil('.pax-sa-option').parent().addClass('selected');
178            $('input[satype="' + specialAssistanceId + '"]').parent().children().children('.bat-sat-description').click();
179            $('input[satype="' + specialAssistanceId + '"]').parentsUntil('.pax-sa-sub-option').children('input').prop("checked", true);
180            updatePassengerInput();
181        }
182    }, 200);
183
184    if (promoCode != null && promoCode != '') {
185        $('#bat-promo-toggle').click();
186        $('#bat-promo-value').val(promoCode);
187    }
188}
189
190function loadFares() {
191    if (localFares != null) {
192        fareTypes = JSON.parse(localFares);
193        processFares(fareTypes);
194    } else {
195        $.get(" /umbraco/api/travel/GetFareTypes", function (data) {
196            fareTypes = data;
197            sessionStorage.setItem('travel_fares', JSON.stringify(fareTypes));
198            processFares(fareTypes);
199        });
200    }
201}
202
203function processFares(fareTypes) {
204
205    var index = 0;
206    var tabIndex = 6;
207    tabIndex = tabIndex + fareTypes.length;
208    fareTypes.reverse();
209    fareTypes.forEach(function (fare) {
210        index++;
211        var fullDisplay = fare.Display.split('(')[0];
212        var subDisplay = '';
213        if (fare.Display.split('(').length > 1) {
214            subDisplay = '(' + fare.Display.split('(')[1];
215        }
216
217        $('.bat-passenger-window-fares').prepend('<div class="col-xs-12 bat-passenger-row bat-faretype-' + fare.Code + '">' +
218            '<div class= "bat-passenger-fare-label">' +
219            fullDisplay +
220            '<span class="bat-passenger-subtitle">' + subDisplay + '</span>' +
221            (fare.AdditionalInfo != null ? ' <span fareCode="' + fare.Code + '" class="bat-passenger-info-toggle" style="white-space: nowrap;" title="' + fare.AdditionalInfo + '" >more info</span>' : '') +
222            '<br/>' +
223            '<span class="bat-passenger-info" fareCode="' + fare.Code + '">' + '</span>' +
224
225            '</div>' +
226            '<div class="bat-passenger-input">' +
227            '<a class="bat-passenger-button subtract" fareCode="' + fare.Code + '">–</a>' +
228            '<span class="bat-passenger-value"><input tabindex="7" class="bat-passenger-faretype" concession="' + fare.ConcessionCardRequired + '" IsChild="' + fare.IsChild + '" IsInfant="' + fare.IsInfant + '" fareDescription="' + fare.Description + '" fareCode="' + fare.Code + '" fareSummary="' + fare.Reporting3 + '" type="number" value="0" /></span>' +
229            '<a class="bat-passenger-button add" fareCode="' + fare.Code + '">+</a>' +
230            '</div><span class="bat-passenger-error" fareCode="' + fare.Code + '">' + '</span>' +
231            '</div>');
232
233        if (fare.AdditionalInfo != null) {
234            $('.bat-passenger-info[fareCode="' + fare.Code + '"]').tooltip({
235                placement: "top",
236                trigger: 'click',
237                template: '<div class="tooltip" role="tooltip">' +
238                    '<div class="tooltip-inner eh"></div>' +
239                    '<div class="arrow"></div><div class="inner-arrow"></div>' +
240                    '</div>'
241            });
242            $('.bat-passenger-info-toggle[fareCode="' + fare.Code + '"]').on('click', function (e) {
243                if ($('.bat-passenger-info[fareCode="' + fare.Code + '"]').html() === "") {
244                    $('.bat-passenger-info[fareCode="' + fare.Code + '"]').html(fare.AdditionalInfo);
245                } else {
246                    $('.bat-passenger-info[fareCode="' + fare.Code + '"]').html("");
247                }
248            });
249        }
250
251        function getCurrentFareTotal() {
252            return parseInt($(".bat-passenger-faretype[fareCode='" + fare.Code + "']").val());
253        }
254
255        $(".bat-passenger-button[fareCode='" + fare.Code + "']").on('click', function (e) {
256            if ($(this).parent().hasClass('disabled')) {
257                return;
258            }
259            if ($(this).hasClass('add')) {
260                if (!$(this).parent().hasClass('add-disabled')) {
261                    $(".bat-passenger-faretype[fareCode='" + fare.Code + "']").val(getCurrentFareTotal() + 1);
262                }
263            } else {
264                if (getCurrentFareTotal() > 0 && !$(this).parent().hasClass('subtract-disabled')) {
265                    $(".bat-passenger-faretype[fareCode='" + fare.Code + "']").val(getCurrentFareTotal() - 1);
266                }
267            }
268
269            updatePassengerInput();
270        });
271    });
272
273    $('.bat-faretype-' + nursedInfantFareCode).css('margin', '0px');
274    $('.bat-faretype-' + nursedInfantFareCode).css('max-height', '0px');
275    $('.bat-faretype-' + nursedInfantFareCode).css('padding', '0px');
276    $('.bat-faretype-' + nursedInfantFareCode).css('margin-top', '-11px');
277
278    $('.bat-passenger-faretype').on('change', function () {
279        if (parseInt($(this).val()) < 0) {
280            $(this).val(0);
281        }
282        updatePassengerInput();
283    });
284
285    getSpecialAssistanceTypes();
286    updatePassengerInput();
287}
288
289function getSpecialAssistanceTypes() {
290    $.get("/umbraco/api/travel/GetSpecialAssistanceTypes", function (data) {
291        var satTypes = data;
292        saData = data;
293        // satTypes.reverse();
294        var index = 0;
295
296
297        var currentCategories = [];
298        satTypes.forEach(function (satType) {
299
300            var category = satType.Description.split(' - ')[0];
301            var description = '';
302            if (satType.Description.split(' - ').length > 1) {
303                description = '<div class="bat-sat-description">' + satType.Description.split(' - ')[1] + '</div>';
304            }
305            var warning = '';
306            if (satType.Instructions != null && satType.Instructions.length > 0) {
307                warning = '<br/><div class="radio-warning' + (satType.StopBooking == true ? ' critical' : '') + '"><div class="error-icon"><i class="ga ga-info-notice"></i></div><div id="warning-' + satType.Index + '" class="warning-text">' + satType.Instructions + '</div></div>';
308            }
309
310            if (currentCategories.indexOf(category) < 0) {
311                // New category
312                $('.bat-special-assistance-options').append('<div class="col-xs-12 pax-sa-option">' +
313                    '<div class="col-xs-12 description" tabindex="9">' + category + '</div>' +
314                    '<div class="col-xs-12 warning" category="' + category + '" style="max-height: 0px;">' +
315                    '<div class="error-icon"><i class="ga ga-error-notice"></i></div>' +
316                    '<div class="warning-text">Choosing a different Travel Assistance type will replace the option you have already selected.</div></div>' +
317                    '<div class="col-xs-12 pax-sa-sub-option" category="' + category + '">' +
318                    '</div>' +
319                    '</div>');
320
321                $('.pax-sa-sub-option[category="' + category + '"]').append('<div class="radio" for="radio-' + index + '" >' +
322                    '<input id="radio-' + index + '" saType="' + satType.Index + '" fare="' + satType.ExtraFarebasis + '" for="radio-' + index + '"  name="bat-sat" type="radio">' +
323                    '<label for="radio-' + index + '" class="radio-label hide-radio-background" tabindex="9">' + description + warning + '</label>' +
324                    '</div>');
325                if(warning != '') {
326                    var warningDiv = $('#warning-' + satType.Index);
327                    if (satType.Instructions.indexOf('<a') > -1) {
328                        console.log('found <a', warningDiv.children('a'));
329                        warningDiv.children('a').attr('target', "_parent");
330                        warningDiv.children('a').on('click', function () {
331                            console.log('clicked!', warningDiv);
332                            return true;
333                        });
334                    }
335                }
336                currentCategories.push(category);
337            } else {
338                $('.pax-sa-sub-option[category="' + category + '"]').append('<div class="radio" for="radio-' + index + '" >' +
339                    '<input id="radio-' + index + '" saType="' + satType.Index + '"  fare="' + satType.ExtraFarebasis + '" name="bat-sat" type="radio" for="radio-' + index + '"  >' +
340                    '<label for="radio-' + index + '" class="radio-label hide-radio-background" tabindex="9">' + description + warning + '</label>' +
341                    '</div>');
342            }
343            $('label[for="radio-' + index + '"]').on('click', function (e) {
344                $(this).parentsUntil('.pax-sa-sub-option').children('input').prop("checked", true);
345            });
346            $('#radio-' + index).parent('.radio').on('click keypress touchstart', function (e) {
347
348                $('.show-radio-warning').removeClass('show-radio-warning');
349                $(this).children('.radio-label').addClass('show-radio-warning');
350
351
352                if (e.type === 'click' || e.type === 'touchstart' || e.which === 13 || e.which === 32) {
353                    console.log('sa type', e);
354                    var input = $(e.target).parent('.radio').children('input')[0];
355                    if ($(e.target).attr('for') != null) {
356                        $('#' + $(e.target).attr('for')).prop("checked", true);
357                    } else {
358                        $('#' + $(e.target).parent().attr('for')).prop("checked", true);
359                    }
360
361                    $('.warning[category="' + category + '"]').css('max-height', '0px');
362                    $('.warning[category="' + category + '"]').css('opacity', '0');
363                    $('.warning[category="' + category + '"]').css('margin-top', '0px');
364
365                    $('.warning[category!="' + category + '"]').css('max-height', '100px');
366                    $('.warning[category!="' + category + '"]').css('opacity', '1');
367                    $('.warning[category!="' + category + '"]').css('margin-top', '10px');
368                    updatePassengerInput();
369
370                    validateBATSA();
371
372                    //e.preventDefault();
373                }
374            });
375
376            index = index + 1;
377        });
378
379        $('.pax-sa-option .description').on('click keypress', function (e) {
380            if (e.type === 'click' || e.type === 'touchstart' || e.which === 13 || e.which === 32) {
381
382
383                if ($(this).parent('.pax-sa-option').hasClass('selected')) {
384                    $(this).parent('.pax-sa-option').removeClass('selected');
385                } else {
386                    $('.pax-sa-option').removeClass('selected');
387                    $(this).parent('.pax-sa-option').addClass('selected');
388                }
389
390                validateBATSA();
391            }
392        });
393    });
394}
395
396function updatePassengerInput() {
397    console.log('updatePassengerInput');
398    passengerTotal = 0;
399    passengerSummary = '';
400
401    totalFareTypes = 0;
402
403    totalGuardians = 0;
404    totalInfants = 0;
405    totalChildren = 0;
406    totalConcessions = 0;
407    hasErrors = false;
408
409    var saType = null;
410    var nursedInfantFareCode = 'NIF';
411    //  clearError("bat-pax-toggle > .dropdown");
412
413    // Special assistance have a faretype?
414    $('.pax-sa-option.selected').children('.pax-sa-sub-option').first().children().each(function (element) {
415        var input = $(this).children('input[type="radio"]:checked');
416        if (input.length > 0) {
417            saType = input.attr('satype');
418            var saFare = input.attr('fare');
419            if (saFare !== null && saFare !== '') {
420                totalFareTypes += 1;
421            }
422        }
423    });
424
425    $('.bat-passenger-faretype').each(function () {
426        var fareTotal = parseInt($(this).val());
427        var fareDescription = $(this).attr('fareDescription');
428        var fareSummary = $(this).attr('fareSummary');
429        var fareCode = $(this).attr('farecode');
430
431        var fareIsChild = $(this).attr('ischild') === 'true' && $(this).attr('isinfant') !== 'true';
432        var fareIsInfant = $(this).attr('isinfant') === 'true';
433        var fareIsConcession = $(this).attr('concession') === 'true';
434
435        passengerTotal += fareTotal;
436        if (fareTotal > 0) {
437            if (fareCode !== nursedInfantFareCode) {
438                totalFareTypes++;
439            }
440
441            if (fareIsChild !== true && fareIsInfant !== true) {
442                totalGuardians += fareTotal;
443            }
444
445            if (fareIsChild === true) {
446                totalChildren += fareTotal;
447            }
448
449            if (fareIsInfant === true) {
450                totalInfants += fareTotal;
451            }
452
453            if (fareIsConcession === true) {
454                totalConcessions += fareTotal;
455            }
456
457            if (fareTotal > 1) {
458                passengerSummary += fareTotal + "x " + fareSummary + ', ';
459            } else {
460                passengerSummary += fareTotal + "x " + fareSummary + ', ';
461            }
462        }
463    });
464
465    $('.bat-passenger-faretype').each(function () {
466        var fareTotal = parseInt($(this).val());
467        var fareCode = $(this).attr('farecode');
468        var fareIsChild = $(this).attr('ischild') === 'true' && $(this).attr('isinfant') !== 'true';
469        var fareIsInfant = $(this).attr('isinfant') === 'true';
470        var fareIsConcession = $(this).attr('concession') === 'true';
471
472        var input = $(this);
473
474
475        function disable(reason) {
476            input.parent('.bat-passenger-value').parent('.bat-passenger-input').addClass('disabled');
477            input.attr('readonly', 'readonly');
478
479            if (reason) {
480                input.parent('.bat-passenger-value').parent('.bat-passenger-input').attr('title', reason);
481            }
482        }
483
484        function enable() {
485            input.parent('.bat-passenger-value').parent('.bat-passenger-input').removeClass('disabled');
486            input.removeAttr('readonly');
487
488            input.parent('.bat-passenger-value').parent('.bat-passenger-input').removeAttr('title');
489        }
490
491        function disableAdd(reason) {
492            input.parent('.bat-passenger-value').parent('.bat-passenger-input').addClass('add-disabled');
493        }
494
495        function enableAdd() {
496            input.parent('.bat-passenger-value').parent('.bat-passenger-input').removeClass('add-disabled');
497        }
498
499        function disableSubtract(reason) {
500            input.parent('.bat-passenger-value').parent('.bat-passenger-input').addClass('subtract-disabled');
501        }
502
503        function enableSubtract() {
504            input.parent('.bat-passenger-value').parent('.bat-passenger-input').removeClass('subtract-disabled');
505        }
506
507        function error(error) {
508            hasErrors = true;
509            $('.bat-passenger-error[farecode="' + fareCode + '"]').html('<span class="col-xs-1 error-icon"><i class="ga ga-error-notice"></i></span><span class="col-xs-11">' + error + '</span>');
510        }
511
512        function clearError() {
513            $('.bat-passenger-error[farecode="' + fareCode + '"]').html('');
514        }
515
516        if (totalFareTypes >= 3 && fareCode !== nursedInfantFareCode) {
517            if (fareTotal <= 0) {
518                disable();
519            } else {
520                enable();
521            }
522        } else {
523            enable();
524        }
525
526
527        if (fareTotal <= 0) {
528            disableSubtract();
529        } else {
530            enableSubtract();
531        }
532
533        if (fareTotal >= 7) {
534            disableAdd();
535        } else {
536            enableAdd();
537        }
538        if (fareIsConcession === true) {
539            if (totalConcessions >= 2) {
540                disableAdd();
541            } else {
542                enableAdd();
543            }
544        }
545
546        if (fareIsChild === true) {
547            if (totalGuardians < 1) { // Is there at least 1 guardian?
548                disableAdd();
549            } else {
550                if (fareTotal + 1 <= 7) {
551                    enableAdd();
552                }
553            }
554
555
556            if (fareTotal > 0 && (totalGuardians) < 1) {
557                error('A Child must travel with a passenger 15 years and older.');
558            } else {
559                clearError();
560            }
561
562        }
563
564        if (fareIsInfant === true) {
565            disableAdd();
566
567            if (totalGuardians < 1) { // Is there at least 1 guardian?
568                // Not enough guardians
569                disableAdd();
570            } else {
571                if ((totalGuardians + totalChildren) > 1) { // Is there more than 1 guardian?
572                    // Enable
573                    enableAdd();
574                } else { // Only 1 guardian
575                    if (totalInfants <= 1) { // Is this our first infant?
576                        enableAdd();
577                    } else {
578                        if (fareCode !== nursedInfantFareCode) { // Is it a seated infant?
579                            disableAdd();
580                        } else {
581                            enableAdd();
582                        }
583                    }
584                }
585            }
586
587            if (fareTotal + 1 <= totalGuardians) {
588                //if (totalInfants >= 4) {
589                //    disableAdd();
590                //}
591            } else {
592                disableAdd();
593            }
594
595
596            if (fareTotal > totalGuardians) {
597                if (totalChildren > 0 && totalGuardians === 0) {
598                    error('All infants and children must travel with a person aged 15 years and older.');
599                } else {
600                    error('A maximum of 2 Infants (1 seated / 1 nursed) can be booked per passenger 15 years and older.');
601                }
602            } else {
603                clearError();
604            }
605
606        }
607
608        if (input.attr('readonly') === 'readonly' && !input.parent('.bat-passenger-value').parent('.bat-passenger-input').hasClass('disabled')) {
609            input.removeAttr('readonly');
610        }
611
612        if (input.parent('.bat-passenger-value').parent('.bat-passenger-input').hasClass('subtract-disabled') && input.parent('.bat-passenger-value').parent('.bat-passenger-input').hasClass('add-disabled') && !input.parent('.bat-passenger-value').parent('.bat-passenger-input').hasClass('disabled')) {
613            input.attr('readonly', 'readonly');
614        }
615
616    });
617
618    $('.bat-faretype-' + nursedInfantFareCode).attr('style', '');
619
620    if ($('.bat-faretype-451 > .bat-passenger-fare-label').length > 0) {
621        $('.bat-faretype-451 > .bat-passenger-fare-label').first().html($('.bat-faretype-451 > .bat-passenger-fare-label').first().html().replaceAll('SEATED INFANT', 'Seated Infant'));
622    }
623
624    if (hasErrors || !validateBATSA() || passengerTotal < 1) {
625        $('#bat-pax-button').addClass('disabled');
626        if (passengerTotal > 0) {
627            //  addError("bat-pax-toggle > .dropdown", "Invalid passengers");
628        }
629        //else {
630        //clearError("bat-pax-toggle > .dropdown");
631        //}
632    } else {
633        $('#bat-pax-button').removeClass('disabled');
634        //clearError("bat-pax-toggle > .dropdown");
635    }
636
637    if (passengerTotal > 0) {
638        if (saType != null) {
639            passengerSummary += 'TRAVEL ASSISTANCE, ';
640        }
641        passengerSummary = passengerSummary.slice(0, -2);
642    }
643
644    if (passengerSummary !== '' && validateBATSA() === true) {
645        //  clearError("bat-pax-toggle > .dropdown");
646    }
647
648    $('#bat-passengers').val(passengerSummary);
649    $('#bat-passengers').attr('title', passengerSummary);
650}
651function validateBATPAX(ignoreEmpty) {
652    if (ignoreEmpty === null) {
653        ignoreEmpty = false;
654    }
655
656    if(($('#bat-passengers').val() === '' && ignoreEmpty === true)) {
657        return true;
658    }
659    if ($('#bat-pax-button').hasClass('disabled')) {
660        return false;
661    }
662    return true;
663}
664function validateBAT(ignoreEmpty) {
665    if (ignoreEmpty === null) {
666        ignoreEmpty = false;
667    }
668    // $('.tooltip.error').remove();
669    $('.tooltip.error').each(function (index, element) {
670        console.log('deleting', element);
671        setTimeout(function () {
672            $(element).remove();
673        }, 200);
674    });
675
676    console.log('validateBAT');
677    var errorCount = 0;
678    var origin = $('#bat-origin').val();
679    var destination = $('#bat-destination').val();
680    var returnVal = $('#bat-return').val();
681    var departure = $('#bat-departure').val();
682    var passengers = $('#bat-passengers').val();
683
684    var originVal = $('#bat-origin').val().toLowerCase();
685    $('#bat-origin').val($('#bat-origin').val().toUpperCase());
686    var originResult = false;
687
688    if (stops.filter(function (x) { return x.Description.toLowerCase() === originVal; }).length > 0) {
689        originResult = true;
690    }
691    if (origin == '' && !ignoreEmpty) {
692        addError("bat-origin", "Please select an origin");
693        errorCount++;
694        return false;
695    }
696
697
698    if (originResult === false && origin != '') {
699        addError("bat-origin", "Please select a valid origin");
700        errorCount++;
701        return false;
702    }
703
704    var destinationVal = $('#bat-destination').val().toLowerCase();
705    $('#bat-destination').val($('#bat-destination').val().toUpperCase());
706    var destinationResult = false;
707
708    if (stops.filter(function (x) { return x.Description.toLowerCase() === destinationVal; }).length > 0) {
709        destinationResult = true;
710    }
711
712
713    if (destination == '' && !ignoreEmpty) {
714        addError("bat-destination", "Please select a destination");
715        errorCount++;
716        return false;
717    }
718
719    if (destinationResult === false && destination != '') {
720        addError("bat-destination", "Please select a valid destination");
721        errorCount++;
722        return false;
723    }
724
725    if (departure == '' && !ignoreEmpty) {
726        addError("bat-departure", "Please select a departure date");
727        errorCount++;
728        return false;
729    }
730
731    if (returnVal == '' && getTripType() == "return" && !ignoreEmpty ) {
732        addError("bat-return", "Please select a return date");
733        errorCount++;
734        return false;
735    }
736
737    if ((passengers == '' && !ignoreEmpty) || passengers == null && !ignoreEmpty) {
738        addError("bat-pax-toggle > .dropdown", "Please select passengers");
739        errorCount++;
740        return false;
741    }
742
743
744    if (!validateBATPAX(ignoreEmpty)) {
745        addError("bat-pax-toggle > .dropdown", "Invalid passenger selection"); 
746        errorCount++;
747        return false;
748    }
749
750    if (validateBATSA() == false) {
751        addError("bat-pax-toggle > .dropdown", "Travel Assistance details missing");
752        errorCount++;
753        return false;
754    }
755
756    if (errorCount < 1) {
757        console.log('error count < 1!');
758        $("#bat-pax-toggle > .dropdown").tooltip('hide');
759        //clearError("bat-pax-toggle > .dropdown");
760    }
761
762    return errorCount == 0;
763}
764
765function validateBATSA() {
766    console.log('validateBATSA');
767    var sa = $('.bat-special-assistance-toggle').children('.checked').length > 0;
768    var saType = null;
769    saStopMessage = null;
770    if (sa === true) {
771        $('.pax-sa-option.selected').children('.pax-sa-sub-option').first().children().each(function (element) {
772            var input = $(this).children('input[type="radio"]:checked');
773            if (input.length > 0) {
774                saType = input.attr('satype');
775                var messageElm = input.siblings(".radio-label").find(".radio-warning").first();
776                if (messageElm.length > 0 && messageElm.hasClass("critical")) {
777                    saStopMessage = messageElm.children(".warning-text").html();
778                }
779            }
780        });
781
782        if (saType == null) {
783            return false;
784        } else {
785            return true;
786        }
787    } else {
788        return true;
789    }
790
791}
792
793function setupBAT() {
794    if (stopData == null) {
795        setTimeout(function () {
796            setupBAT();
797        }, 200);
798
799        return;
800    }
801
802    function hideErrorModal() {
803        $('#bat-error-modal').hide();
804        $('.bat-form').css('opacity', 1);
805    }
806
807    function showErrorModal() {
808        $('#bat-error-modal').css('display', 'inline-block');
809        $('.bat-form').css('opacity', 0.3);
810    }
811
812    $('.tab-pane').on('click', function (e) {
813        hideErrorModal();
814    });
815
816    $('#bat-pax-modal').on('show.bs.modal', function () {
817        $('.bat-passenger-window').appendTo('#bat-pax-modal-body');
818
819    });
820
821    $('#bat-pax-modal').on('hide.bs.modal', function () {
822        $("#bat-pax-toggle > .dropdown").blur();
823        $('.bat-passenger-window').appendTo('#bat-passenger-dropdown');
824    });
825
826
827    $('#bat-origin-modal').on('hide.bs.modal', function () {
828        $('#bat-origin').typeahead('val', $('#bat-origin-modal-input').val());
829        $('#bat-origin').blur();
830    });
831
832    $('#bat-origin-modal').on('hidden.bs.modal', function () {
833        $('#bat-origin-modal-input').blur();
834        setTimeout(function () {
835            $('#bat-origin-modal-input').blur();
836        }, 200);
837    });
838
839    $('#bat-destination-modal').on('hide.bs.modal', function () {
840        $('#bat-destination').typeahead('val', $('#bat-destination-modal-input').val());
841        $('#bat-destination').blur();
842    });
843
844    $('#bat-destination-modal').on('hidden.bs.modal', function () {
845        $('#bat-destination-modal-input').blur();
846        setTimeout(function () {
847            $('#bat-destination-modal-input').blur();
848        }, 200);
849    });
850
851    $('#bat-origin-modal').on('shown.bs.modal', function () {
852        $('#bat-origin-modal-input').focus();
853        setTimeout(function () {
854
855            $('#bat-origin-modal-input').focus();
856        }, 200);
857    });
858
859
860    $('#bat-pax-toggle > .dropdown').on('hide.bs.dropdown', function () {
861        console.log('pax close');
862        validateBAT(true);
863        if (window.screen.width >= mobileWidth) {
864        }
865    });
866
867
868    $('#bat-pax-toggle > .dropdown').on('show.bs.dropdown', function () {
869        console.log('pax open');
870    });
871    
872    $('.input-overlay').on('click touchstart', function(){
873        //$('.input-overlay').removeClass('visible');
874    });
875    // TODO: Use classes, not IDs
876    $("input:radio[name='tripType']").first().attr('checked', 'checked');
877    $(".radio-label").on('click keypress touchstart', function () {
878
879        tripType = $(this).parent('.radio').children("input[name='tripType']").val();
880        ctDirection = $(this).parent('.radio').children("input[name='ct-tripType']").val();
881
882        if ($(this).attr('for') === 'bt-trip-return') {
883            tripType = 'return';
884        } else {
885            tripType = 'one-way';
886        }
887
888        if (tripType !== "return") {
889            console.log('swapping to one-way');
890            $('#bat-return').val('');
891            $('#bat-return').attr('disabled', 'disabled');
892        } else {
893            console.log('swapping to return');
894            $('#bat-return').removeAttr('disabled');
895        }
896
897        $('#bat-return').first().tooltip('hide');
898        $('#bat-return').first().removeClass('error');
899
900    });
901
902    $('#bat-error-modal-close').on('click', function () {
903        hideErrorModal();
904    });
905
906    $("input:radio[name='tripType']").on('change', function () {
907        if (getTripType() != "return") {
908            $('#bat-return').val('');
909            $('#bat-return').attr('disabled', 'disabled');
910        } else {
911            $('#bat-return').removeAttr('disabled');
912        }
913    });
914
915    $('#bat-pax-button').on('click', function (e) {
916        if ($(this).hasClass('disabled')) {
917            return;
918        }
919        if (e.type === 'click' || e.type === 'touchend' || e.which === 13 || e.which === 32) {
920            if (screen.width < 768) {
921                // $('#bat-pax-modal').modal('hide');
922            } else {
923                $('#pax-menu').click();
924            }
925            $('#searchTripsButton').focus();
926        }
927    });
928
929
930    $('#bat-swap-locations').on('click', function () {
931        var origin = $('#bat-origin').val();
932        var destination = $('#bat-destination').val();
933        $('#bat-origin').typeahead('val', destination);
934        $('#bat-destination').typeahead('val', origin);
935        $('#bat-origin-modal-input').typeahead('val', destination);
936        $('#bat-destination-modal-input').typeahead('val', origin);
937
938        setTimeout(function () {
939            $('#bat-orgin').blur();
940            $('#bat-destination').blur();
941            document.activeElement.blur();
942        }, 200);
943    });
944
945    $('#bat-origin').on('focus', function (e, a, b) {
946        if (screen.width < 768) {
947            $('#bat-origin-modal').modal('show');
948            $('#bat-origin-modal-input').typeahead('val', $('#bat-origin').val());
949            $('#bat-origin-modal-input').focus();
950            setTimeout(function () {
951                $('#bat-origin-modal-input').focus();
952                setTimeout(function () {
953                    $('#bat-origin-modal-input').trigger('touchstart');
954                }, 100);
955            }, 200);
956        }
957    });
958
959    $('#bat-destination').on('click', function () {
960        if (screen.width < 768) {
961            $('#bat-destination-modal').modal('show');
962            $('#bat-destination-modal-input').typeahead('val', $('#bat-destination').val());
963            $('#bat-destination-modal-input').focus();
964            setTimeout(function () {
965                $('#bat-destination-modal-input').focus();
966                setTimeout(function () {
967                    $('#bat-destination-modal-input').trigger('touchstart');
968                }, 100);
969            }, 200);
970        }
971    });
972
973    $('#bat-origin').on('change typeahead:select blur', function (e) {
974
975        var val = $(this).val().toLowerCase();
976        $(this).val($(this).val().toUpperCase());
977        validateBAT(true);
978    });
979
980    $('#bat-origin-modal-input, #bat-destination-modal-input').on('change typeahead:select', function (e) {
981
982        $('#bat-origin-modal').modal('hide');
983        $('#bat-destination-modal').modal('hide');
984
985        var val = $(this).val().toLowerCase();
986        $(this).val($(this).val().toUpperCase());
987        var result = false;
988        if (stops.filter(function (x) { x.Description.toLowerCase() === val; }).length > 0) {
989            result = true;
990        }
991
992        if (result === false) {
993            $(this).typeahead('val', $(this).val().toUpperCase());
994        }
995        validateBAT(true);
996    });
997
998    $('#bat-destination').on('change typeahead:select blur', function (e) {
999        var val = $(this).val().toLowerCase();
1000        $(this).val($(this).val().toUpperCase());
1001        validateBAT(true);
1002    });
1003
1004    function customRange() {
1005        var target = $('#bat-datepicker').attr('target');
1006        var selectedDate = $("#bat-datepicker").datepicker("getDate");
1007        var departing = null;
1008
1009        if (selectedDate != null) {
1010            $('#' + target).val(moment(selectedDate).format('DD/MM/YYYY'));
1011        }
1012
1013        if (target.indexOf('departing') > -1) {
1014            departing = true;
1015        }
1016
1017        if (target.indexOf('return') > -1) {
1018            departing = false;
1019        }
1020
1021
1022        $("#ui-datepicker-div").focus();
1023
1024        if (getTripType() == 'return') {
1025            if (departing === false) {
1026                $('#bat-datepicker').hide();
1027
1028            } else {
1029                $('#bat-return').focus();
1030
1031                setTimeout(function () {
1032                    $('#bat-datepicker .first-date').removeClass('first-date');
1033                    $('#bat-datepicker td:not(.ui-state-disabled)').first().addClass('first-date');
1034                }, 300);
1035            }
1036        } else {
1037            $('#bat-datepicker').hide();
1038        }
1039    }
1040
1041    function customRangeMobileDeparture(input, a, b, c) {
1042        var target = $('#bat-modal-departure-datepicker').attr('target');
1043        var selectedDate = $("#bat-modal-departure-datepicker").datepicker("getDate");
1044        var departing = null;
1045        if (selectedDate != null) {
1046            $('#' + target).val(moment(selectedDate).format('DD/MM/YYYY'));
1047        }
1048
1049        if (target.indexOf('bat-depart') > -1) {
1050            departing = true;
1051        }
1052
1053        if (target.indexOf('bat-return') > -1) {
1054            departing = false;
1055        }
1056
1057        if (departing === true && selectedDate != null) {
1058            $('#bat-modal-return-datepicker').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
1059        }
1060
1061        var returnDate = moment($('#bat-return').val(), "DD/MM/YYYY", true).toDate();
1062        if (selectedDate > returnDate) {
1063            $('#bat-return').val(moment(selectedDate).format("DD/MM/YYYY"));
1064        }
1065
1066        $('#bat-departure-modal').modal('hide');
1067    }
1068
1069    function customRangeMobileReturn(input, a, b, c) {
1070        var target = $('#bat-modal-return-datepicker').attr('target');
1071        var selectedDate = $("#bat-modal-return-datepicker").datepicker("getDate");
1072        var departing = null;
1073
1074
1075        if (selectedDate != null) {
1076            $('#' + target).val(moment(selectedDate).format('DD/MM/YYYY'));
1077        }
1078
1079        if (target.indexOf('bat-departing') > -1) {
1080            departing = true;
1081        }
1082
1083        if (target.indexOf('bat-return') > -1) {
1084            departing = false;
1085        }
1086
1087        $('#bat-return-modal').modal('hide');
1088
1089    }
1090
1091    function addDateRangeModal() {
1092        var departDate = moment($('#bat-modal-departure-datepicker').val(), "DD/MM/YYYY", true).toDate();
1093        var returnDate = moment($('#bat-modal-return-datepicker').val(), "DD/MM/YYYY", true).toDate();
1094
1095    }
1096
1097    $('#bat-return-modal').on('shown.bs.modal', function () {
1098
1099        $('#bat-modal-return-datepicker').attr('target', $(this).attr('id'));
1100
1101        $('#bat-modal-return-datepicker .arrow').removeClass('left');
1102        $('#bat-modal-return-datepicker .arrow').addClass('right');
1103
1104        $('.ui-datepicker-prev').click();
1105
1106        $("#bat-modal-return-datepicker td").removeClass("highlight");
1107        $('#bat-modal-return-datepicker .ui-state-active').parent('td').parent('tr').addClass("finalRow");
1108        $('#bat-modal-return-datepicker .ui-state-active').parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1109        $("#bat-modal-return-datepicker .finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1110        $('#bat-modal-return-datepicker .ui-state-active').parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1111        $('#bat-modal-return-datepicker .first-date').removeClass('first-date');
1112        $('#bat-modal-return-datepicker .highlight').first().addClass('first-date');
1113    });
1114
1115    var displayMonths = 1;
1116    if (window.screen.width < 768) {
1117        displayMonths = 2;
1118    }
1119
1120    if (window.screen.width < 768) {
1121
1122        $('#bat-modal-departure-datepicker').datepicker({
1123            autoclose: true,
1124            numberOfMonths: 13,
1125            minDate: new Date(),
1126            maxDate: moment().add(365, 'days').toDate(),
1127            dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1128            dateFormat: 'dd/mm/yy',
1129            assumeNearbyYear: true,
1130            firstDay: 1,
1131            orientation: 'bottom',
1132            format: 'dd/mm/yyyy',
1133            startDate: moment().format('DD/MM/YYYY'),
1134            rangeSelect: true,
1135            beforeShow: customRangeMobileDeparture,
1136            onSelect: customRangeMobileDeparture
1137        });
1138
1139        $('#bat-modal-return-datepicker').datepicker({
1140            autoclose: true,
1141            numberOfMonths: 13,
1142            minDate: 13,
1143            maxDate: moment().add(365, 'days').toDate(),
1144            dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1145            dateFormat: 'dd/mm/yy',
1146            assumeNearbyYear: true,
1147            firstDay: 1,
1148            orientation: 'bottom',
1149            format: 'dd/mm/yyyy',
1150            startDate: moment().format('DD/MM/YYYY'),
1151            rangeSelect: true,
1152            beforeShow: customRangeMobileReturn,
1153            onSelect: customRangeMobileReturn
1154        });
1155
1156        $('#bat-departure').on('focus', function (e) {
1157            var depart = moment($('#bat-departure').val(), "DD/MM/YYYY", true).toDate();
1158            $('#bat-modal-departure-datepicker').datepicker('option', 'minDate', new Date()).datepicker('refresh');
1159            $('#bat-modal-departure-datepicker').datepicker('setDate', depart).datepicker('refresh');
1160            console.log('flag a');
1161            $('#bat-departure-modal').modal('show');
1162            $('.ui-datepicker-current-day').trigger('mouseenter');
1163            $('.ui-datepicker-current-day').trigger('mouseover');
1164            $('#bat-modal-departure-datepicker').attr('target', 'bat-departure');
1165
1166        });
1167        $('#bat-departure-container #bat-departure').on('click', function (e) {
1168            $('#bat-departure-modal').modal('show');
1169            $('.ui-datepicker-current-day').trigger('mouseenter');
1170            $('.ui-datepicker-current-day').trigger('mouseover');
1171            $('#bat-modal-departure-datepicker').attr('target', 'bat-departure');
1172        });
1173
1174        /// DEPART/RETURN 
1175        $('#bat-return').on('focus', function (e) {
1176            var depart = moment($('#bat-departure').val(), "DD/MM/YYYY", true).toDate();
1177            var returnDate = moment($('#bat-return').val(), "DD/MM/YYYY", true).toDate();
1178            $('#bat-modal-return-datepicker').datepicker('option', 'minDate', depart).datepicker('refresh');
1179            if (depart > returnDate) {
1180                returnDate = depart;
1181            }
1182            $('#bat-modal-return-datepicker').datepicker('setDate', returnDate).datepicker('refresh');
1183            $('#bat-return-modal').modal('show');
1184            $('.ui-datepicker-current-day').trigger('mouseenter');
1185            $('.ui-datepicker-current-day').trigger('mouseover');
1186            $('#bat-modal-return-datepicker').attr('target', 'bat-return');
1187        });
1188
1189        $('#bat-return-container #bat-return').on('click', function (e) {
1190            console.log('flag d');
1191            $('#bat-return-modal').modal('show');
1192            $('.ui-datepicker-current-day').trigger('mouseenter');
1193            $('.ui-datepicker-current-day').trigger('mouseover');
1194            $('#bat-modal-return-datepicker').attr('target', 'bat-return');
1195        });
1196    }
1197
1198    $(document).on('click', function (e) {
1199        if (e.target.id.indexOf('depart') < 0 &&
1200            e.target.id.indexOf('return') < 0 &&
1201            e.target.id.indexOf('tt') < 0 &&
1202            !$(e.target).hasClass('stop-location') &&
1203            $(e.target).parents('.ui-datepicker').length === 0 &&
1204            $(e.target).parents('.ui-datepicker-group').length === 0 &&
1205            $(e.target).parents('#bat-datepicker').length === 0 &&
1206            $('#bat-datepicker').css('display') != 'none') {
1207
1208            $('#bat-datepicker').hide();
1209        }
1210
1211    });
1212    $('.radio').on('click touchstart',
1213        function(e) {
1214            if (screen.width < 768) {
1215                // fix for showing pax field on any form selection
1216                var elm = $('#bat-pax-toggle');
1217                elm.show();
1218                elm.children('.dropdown').children('.dropdown-toggle').show();
1219                $('.promo-code-row').show();
1220                $('#bat-promo-toggle').show();
1221                return;
1222            }
1223        });
1224
1225    $('#bat-departure, #bat-return, #bat-passengers').on('click focus touchstart', function (e) {
1226
1227        if (screen.width < 768) {
1228            return;
1229        }
1230        ////$('#bat-datepicker').show();
1231        if (e.target.id === "bat-passengers") {
1232            $('#bat-datepicker').hide();
1233        } else {
1234            if (!$('#bat-datepicker').is(':visible')) {
1235                $('#bat-datepicker').show();
1236            }
1237        }
1238
1239        if ($('.dropdown-toggle.open').length > 0) {
1240            $('#pax-menu').dropdown('toggle');
1241        }
1242        if (document.documentMode || /Edge/.test(navigator.userAgent) || /Edg/.test(navigator.userAgent)) {
1243            console.log('ie/edge detected');
1244        } else {
1245            setTimeout(function () {
1246                $(".tabbable")[0].scrollIntoView({
1247                    behavior: "smooth",
1248                    block: "start"
1249                });
1250            }, 100);
1251        }
1252
1253        if (e.type === "touchstart") {
1254            $(this).focus();
1255        }
1256
1257        if ($(this).val() != null) {
1258            $("#bat-datepicker").datepicker("setDate", $(this).val());
1259        }
1260
1261        $('#bat-datepicker').attr('target', $(this).attr('id'));
1262        if ($(this).attr('id').indexOf('departure') > -1) {
1263            $('#bat-datepicker .arrow').removeClass('right');
1264            $('#bat-datepicker .arrow').addClass('left');
1265            $('#bat-datepicker').datepicker('option', 'minDate', new Date()).datepicker('refresh');
1266        } else {
1267            $('#bat-datepicker .arrow').removeClass('left');
1268            $('#bat-datepicker .arrow').addClass('right');
1269            var depart = moment($('#bat-departure').val(), "DD/MM/YYYY", true).toDate();
1270            $('#bat-datepicker').datepicker('option', 'minDate', depart);
1271            $('.ui-datepicker-prev').click();
1272            if ($("#bat-datepicker").attr('target') == 'bat-return') {
1273                $("#bat-datepicker td").removeClass("highlight");
1274                if ($("#bat-datepicker").attr('target') === 'bat-return') {
1275                    $('#bat-datepicker .ui-state-active').parent('td').parent('tr').addClass("finalRow");
1276                    $('#bat-datepicker .ui-state-active').parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1277                    $("#bat-datepicker .finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1278                    $('#bat-datepicker .ui-state-active').parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1279
1280                    $('#bat datepicker .first-date').removeClass('first-date');
1281                    $('#bat-datepicker .highlight').first().addClass('first-date');
1282                }
1283            }
1284        }
1285
1286    });
1287
1288
1289    $('#bat-datepicker').datepicker({
1290        autoclose: true,
1291        numberOfMonths: 2,
1292        minDate: new Date(),
1293        maxDate: moment().add(365, 'days').toDate(),
1294        dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1295        dateFormat: 'dd/mm/yy',
1296        assumeNearbyYear: true,
1297        firstDay: 1,
1298        orientation: 'bottom',
1299        format: 'dd/mm/yyyy',
1300        startDate: moment().format('DD/MM/YYYY'),
1301        rangeSelect: true,
1302        beforeShow: customRange,
1303        onSelect: customRange
1304    });
1305
1306
1307
1308    function addDateRangeHighlight() {
1309        if (screen.width < 768) {
1310
1311            $("#bat-modal-departure-datepicker td > a").each(function () {
1312
1313                var that = $(this);
1314                $(this).off('mouseenter mouseover');
1315                $(this).on('mouseenter mouseover', function () { //mouseenter
1316                    if ($("#bat-modal-departure-datepicker").attr('target') === 'bat-return') {
1317                        $(this).parent('td').parent('tr').addClass("finalRow");
1318                        $(this).parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1319                        $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1320                        $(this).parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1321                    }
1322                });
1323                $(this).off('mouseleave mouseout');
1324                $(this).on('mouseleave mouseout', function () { //mouseenter
1325                    if ($("#bat-modal-departure-datepicker").attr('target') === 'bat-return') {
1326                        // $(this).parent('td').parent('tr').removeClass("finalRow");
1327                        $('.finalRow').removeClass('finalRow');
1328                        $("#bat-modal-departure-datepicker td").removeClass("highlight");
1329
1330                        if ($("#bat-modal-departure-datepicker td.highlight").length === 3) {
1331                            $('.ui-datepicker-current-day').trigger('mouseenter');
1332                            $('.ui-datepicker-current-day').trigger('mouseover');
1333                        }
1334
1335                        $('.ui-state-active').parent('td').parent('tr').addClass("finalRow");
1336                        $('.ui-state-active').parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1337                        $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1338                        $('.ui-state-active').parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1339                    }
1340                });
1341            });
1342
1343            $("#bat-modal-return-datepicker td > a").each(function () {
1344
1345                var that = $(this);
1346                $(this).off('mouseenter mouseover');
1347                $(this).on('mouseenter mouseover', function () { //mouseenter
1348                    if ($("#bat-modal-return-datepicker").attr('target') === 'bat-return') {
1349                        $(this).parent('td').parent('tr').addClass("finalRow");
1350                        $(this).parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1351                        $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1352                        $(this).parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1353
1354                    }
1355                });
1356                $(this).off('mouseleave mouseout');
1357                $(this).on('mouseleave mouseout', function () { //mouseenter
1358                    if ($("#bat-modal-return-datepicker").attr('target') === 'bat-return') {
1359                        // $(this).parent('td').parent('tr').removeClass("finalRow");
1360                        $('.finalRow').removeClass('finalRow');
1361                        $("#bat-modal-return-datepicker td").removeClass("highlight");
1362
1363                        if ($("#bat-modal-return-datepicker td.highlight").length === 3) {
1364                            $('.ui-datepicker-current-day').trigger('mouseenter');
1365                            $('.ui-datepicker-current-day').trigger('mouseover');
1366                        }
1367
1368                        $('.ui-state-active').parent('td').parent('tr').addClass("finalRow");
1369                        $('.ui-state-active').parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1370                        $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1371                        $('.ui-state-active').parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1372                    }
1373                });
1374            });
1375        } else {
1376            $("#bat-datepicker td > a").each(function () {
1377
1378                var that = $(this);
1379                $(this).off('mouseenter mouseover');
1380                $(this).on('mouseenter mouseover', function () { //mouseenter
1381
1382                    $("#bat-datepicker td").removeClass("highlight");
1383                    if ($("#bat-datepicker").attr('target') === 'bat-return') {
1384                        $('#bat-datepicker .finalRow').removeClass('finalRow');
1385                        $(this).parent('td').parent('tr').addClass("finalRow");
1386                        $(this).parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1387                        $("#bat-datepicker .finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1388                        $(this).parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1389                    }
1390                });
1391                $(this).off('mouseleave mouseout');
1392                $(this).on('mouseleave mouseout', function () { //mouseenter
1393                    if ($("#bat-datepicker").attr('target') === 'bat-return') {
1394
1395                        $("#bat-datepicker td").removeClass("highlight");
1396                        $('#bat-datepicker .finalRow').removeClass('finalRow');
1397                        $('#bat-datepicker .ui-state-active').parent('td').parent('tr').addClass("finalRow");
1398                        $('#bat-datepicker .ui-state-active').parentsUntil('.ui-datepicker-group').parent().prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1399                        $("#bat-datepicker .finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1400                        $('#bat-datepicker .ui-state-active').parent('td').prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
1401                    }
1402                });
1403            });
1404        }
1405
1406        //setTimeout(function () {
1407        //    addDateRangeHighlight();
1408        //}, 500);
1409    }
1410    setTimeout(function () {
1411        addDateRangeHighlight();
1412    }, 1000);
1413    //addDateRangeHighlight();
1414
1415    setTimeout(function () {
1416        $('#bat-departure').on('change', function () {
1417            if (getTripType() == "return") {
1418                $('#bat-return').focus();
1419                //setTimeout(function () {
1420                //    $('#bat datepicker .first-date').removeClass('first-date');
1421                //    $('#bat-datepicker td:not(.ui-state-disabled)').first().addClass('first-date');
1422                //}, 300);
1423            } else {
1424                $('#bat-passengers').focus();
1425            }
1426        });
1427    }, 2500);
1428
1429    $('#bat-return').on('change', function (e) {
1430        $('#bat-passengers').focus();
1431    });
1432
1433    $('#bat-departure').datepicker('setDate', "+0d");
1434
1435
1436    $('#bat-origin').typeahead({
1437        hint: true,
1438        highlight: true,
1439        minLength: 0,
1440        autoselect: true
1441    }, {
1442        name: 'stopData',
1443        display: 'Description',
1444        source: stopData,
1445        limit: 10,
1446        templates: {
1447            empty: function (data) {
1448                if (data.query.length >= 3) {
1449                    return [
1450                        '<div class="typeahead-error"><span>No matching location for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
1451                    ].join('\n');
1452                } else {
1453                    return [
1454                        ''
1455                    ].join('\n');
1456                }
1457            },
1458            suggestion: function (data) {
1459                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
1460            }
1461        }
1462    });
1463
1464    $('#bat-origin-modal-input').typeahead({
1465        hint: true,
1466        highlight: true,
1467        limit: 10,
1468        minLength: 0,
1469        autoselect: true
1470    }, {
1471        name: 'stopData',
1472        display: 'Description',
1473        source: stopData,
1474        limit: 10,
1475        templates: {
1476            empty: function (data) {
1477                if (data.query.length >= 3) {
1478                    return [
1479                        '<div class="typeahead-error"><span>Can\'t find a match for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
1480                    ].join('\n');
1481                } else {
1482                    return [
1483                        ''
1484                    ].join('\n');
1485                }
1486            },
1487            suggestion: function (data) {
1488                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
1489            }
1490        }
1491    });
1492
1493    $('#bat-origin-modal-input').on('change typeahead:select', function () {
1494
1495        var val = $(this).val().toLowerCase();
1496        var result = false;
1497        if (stops.filter(function (x) { x.Description.toLowerCase() === val; }).length > 0) {
1498            result = true;
1499        }
1500
1501        $("#bat-origin").tooltip('hide');
1502        $("#bat-origin").removeClass('error');
1503
1504        if (result === false) {
1505            $('#bat-origin').typeahead('val', $('#bat-origin-modal-input').val());
1506
1507            $('#bat-origin').blur();
1508            // addError("bat-origin", "Please select an origin");
1509        } else {
1510            $('#bat-origin-modal').modal('hide');
1511            $('#bat-origin').typeahead('val', $('#bat-origin-modal-input').val());
1512
1513            $('#bat-origin').blur();
1514        }
1515
1516        validateBAT(true);
1517    });
1518
1519
1520    $('#bat-destination-modal-input').typeahead({
1521        hint: true,
1522        highlight: true,
1523        minLength: 0,
1524        autoselect: true
1525    }, {
1526        name: 'stopData',
1527        display: 'Description',
1528        source: stopData,
1529        limit: 10,
1530        templates: {
1531            empty: function (data) {
1532                if (data.query.length >= 3) {
1533                    return [
1534                        '<div class="typeahead-error"><span>Can\'t find a match for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
1535                    ].join('\n');
1536                } else {
1537                    return [
1538                        ''
1539                    ].join('\n');
1540                }
1541            },
1542            suggestion: function (data) {
1543                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
1544            }
1545        }
1546    });
1547
1548    $('#bat-destination-modal-input').on('change typeahead:select', function () {
1549        var val = $(this).val().toLowerCase();
1550        var result = false;
1551        if (stops.filter(function (x) { x.Description.toLowerCase() === val; }).length > 0) {
1552            result = true;
1553        }
1554
1555        $("#bat-destination").tooltip('hide');
1556        $("#bat-destination").removeClass('error');
1557
1558
1559        if (result === false) {
1560            $('#bat-destination').typeahead('val', $('#bat-destination-modal-input').val());
1561            $('#bat-destination').blur();
1562            //   addError("bat-destination", "Please select a destination");
1563        } else {
1564            $('#bat-destination-modal').modal('hide');
1565            $('#bat-destination').typeahead('val', $('#bat-destination-modal-input').val());
1566            $('#bat-destination').blur();
1567        }
1568
1569        validateBAT(true);
1570    });
1571
1572
1573
1574    if ($('#bat-origin').val().length === 3) {
1575        var origin = stops.filter(function (s) {
1576            return s.Code === $('#bat-origin').val();
1577        });
1578        if (origin.length > 0) {
1579            $('#bat-origin').typeahead('val', origin[0].Description);
1580        }
1581    }
1582
1583
1584    if ($('#bat-destination').val().length === 3) {
1585        var destination = stops.filter(function (s) {
1586            return s.Code == $('#bat-destination').val();
1587        });
1588        if (destination.length > 0) {
1589            $('#bat-destination').typeahead('val', destination[0].Description);
1590        }
1591    }
1592
1593    $(".bat-form").submit(function (e) {
1594        $('#searchTripsButton').click();
1595        e.preventDefault();
1596        e.stopPropagation();
1597    });
1598
1599    $('#bat-destination').typeahead({
1600        hint: true,
1601        highlight: true,
1602        minLength: 0,
1603        autoselect: true
1604    }, {
1605        name: 'stopData',
1606        display: 'Description',
1607        source: stopData,
1608        templates: {
1609            empty: function (data) {
1610                if (data.query.length >= 3) {
1611                    return [
1612                        '<div class="typeahead-error"><span>Can\'t find a match for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
1613                    ].join('\n');
1614                } else {
1615                    return [
1616                        ''
1617                    ].join('\n');
1618                }
1619            },
1620            suggestion: function (data) {
1621                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
1622            }
1623        }
1624    });
1625
1626
1627    $('.bat-special-assistance-toggle').on('click keypress', function (e) {
1628        if (e.type === 'click' || e.type === 'touchstart' || e.which === 13 || e.which === 32) {
1629            if ($(this).children('span').hasClass('checked')) {
1630                $(this).children('span').removeClass('checked');
1631                $('.bat-special-assistance-options').removeClass('visible');
1632                $('input[name="bat-sat"]').prop('checked', false);
1633                $('input[name="bat-sat"]').parent().children().removeClass('show-radio-warning');
1634            } else {
1635                $('.bat-special-assistance-options').addClass('visible');
1636
1637                $(this).children('span').addClass('checked');
1638            }
1639            if (document.documentMode || /Edge/.test(navigator.userAgent) || /Edg/.test(navigator.userAgent)) {
1640                console.log('ie/edge detected');
1641            } else {
1642                setTimeout(function () {
1643                    $(".tabbable")[0].scrollIntoView({
1644                        behavior: "smooth",
1645                        block: "start"
1646                    });
1647                }, 100);
1648            }
1649            updatePassengerInput();
1650            validateBATSA();
1651        }
1652    });
1653
1654    $('.radio label').on('click keypress touchstart', function (e) {
1655        if (e.type === 'click' || e.type === 'touchstart' || e.which === 13 || e.which === 32) {
1656            var input = $(this).parent('.radio').children('input')[0];
1657            $(input).prop("checked", true);
1658            e.preventDefault();
1659        }
1660    });
1661
1662    $('#bat-promo-toggle').on('click', function () {
1663        if (promoOpen === true) {
1664            $('#bat-origin').parent('span').parent('.large').removeClass('promo-open');
1665            $('#bat-destination').parent('span').parent('.large').removeClass('promo-open');
1666            $('#bat-promo-input').removeClass('promo-open');
1667            $('#searchTripsButton').parent().removeClass('promo-open');
1668            promoOpen = false;
1669        } else {
1670            $('#bat-origin').parent('span').parent('.large').addClass('promo-open');
1671            $('#bat-destination').parent('span').parent('.large').addClass('promo-open');
1672            $('#bat-promo-input').addClass('promo-open');
1673            $('#searchTripsButton').parent().addClass('promo-open');
1674
1675            $('#bat-promo-value').focus();
1676            $('#bat-promo-toggle').hide();
1677            $('.promo-code-row').hide();
1678            promoOpen = true;
1679        }
1680    });
1681
1682    $('.bat-passenger-window').on("click.bs.dropdown", function (e) {
1683        if (e.target.localName != 'a' || $(e.target).attr('fareCode') != null) {
1684            console.log('stopped propagation'); 
1685            e.stopPropagation();
1686            e.preventDefault();
1687        } else {
1688            console.log('continued propagation');
1689
1690        }
1691    });
1692
1693    $("#bat-passengers").on('focus', function (e) {
1694        if (screen.width < 768) {
1695            $('#bat-pax-modal').modal();
1696            $('.bat-passenger-faretype').first().focus();
1697        } else {
1698            $('#pax-menu').click();
1699        }
1700        e.stopPropagation();
1701        e.preventDefault();
1702    });
1703
1704    $('#bat-origin, #bat-destination, #bat-passengers').on('focus', function () {
1705        $('#bat-datepicker').hide();
1706    });
1707
1708    $('#bat-pax-button').on('click', function () {
1709        if (screen.width < 768) {
1710            $('#bat-pax-modal').modal('hide');
1711        }
1712    });
1713
1714    $('#searchTripsButton').on('click keypress touchstart', function (e) {
1715        ////if (e.type === 'click' || e.type === 'touchstart' || e.which === 13 || e.which === 32) {
1716        ////} else {
1717        ////    return;
1718        ////}
1719        if (!validateBAT(false)) {
1720            return;
1721        }
1722
1723        var origin, destination;
1724
1725        if (stops.length > 0) {
1726            origin = stops.filter(function (s) {
1727                return s.Description.toLowerCase() === $('#bat-origin').val().toLowerCase();
1728            })[0];
1729            destination = stops.filter(function (s) {
1730                return s.Description.toLowerCase() === $('#bat-destination').val().toLowerCase();
1731            })[0];
1732        }
1733
1734        var travelLegs = [{
1735            "origin": origin.Code,
1736            "destination": destination.Code,
1737            "travelDate": moment($('#bat-departure').val(), "DD/MM/YYYY").format('YYYY-MM-DD'),
1738            "promotionCode": $('#bat-promo-value').val()
1739        }];
1740        if (getTripType() === "return") {
1741            travelLegs.push({
1742                "destination": origin.Code,
1743                "origin": destination.Code,
1744                "travelDate": moment($('#bat-return').val(), "DD/MM/YYYY").format('YYYY-MM-DD'),
1745                "promotionCode": $('#bat-promo-value').val()
1746            });
1747        }
1748        var fares = [];
1749        $('.bat-passenger-faretype').each(function (index, fareType) {
1750            var fareTotal = parseInt($(this).val());
1751            var fareDescription = $(this).attr('fareDescription');
1752            var fareCode = $(this).attr('farecode');
1753
1754            var fareIsChild = $(this).attr('ischild') === 'true' && $(this).attr('isinfant') !== 'true';
1755            var fareIsInfant = $(this).attr('isinfant') === 'true';
1756
1757            var ft = $(fareType);
1758            var total = parseInt(ft.val());
1759
1760            if (fareIsInfant === true && fareCode !== nursedInfantFareCode) {
1761                total += parseInt($('.bat-passenger-faretype[farecode="' + nursedInfantFareCode + '"]').val());
1762            }
1763
1764            if (total > 0 && fareCode !== nursedInfantFareCode) {
1765                var code = ft.attr('fareCode');
1766                var returnCode = fareTypes.filter(function (eft) { return eft.Code == code; })[0].ReturnCode;
1767                fares.push({
1768                    fareCode: code,
1769                    fareTotal: total,
1770                    fareReturnCode: returnCode
1771                });
1772            }
1773        });
1774
1775        var sa = $('.bat-special-assistance-toggle').children('.checked').length > 0;
1776        var saType = null;
1777        if (sa === true) {
1778            $('.pax-sa-option.selected').children('.pax-sa-sub-option').first().children().each(function (element) {
1779                var input = $(this).children('input[type="radio"]:checked');
1780                if (input.length > 0) {
1781                    saType = input.attr('satype');
1782                }
1783            });
1784        }
1785
1786        var data = {
1787            "isReturn": travelLegs.length > 1,
1788            "nursedInfants": $('.bat-passenger-faretype[farecode="' + nursedInfantFareCode + '"]').val(),
1789            "TravelLegs": travelLegs,
1790            "currentSlide": 0,
1791            "sATypeId": saType,
1792            "specialAssistance": sa
1793        };
1794
1795        if (fares.length > 0) {
1796            data.fareBasis1Code = fares[0].fareCode;
1797            data.fareBasis1Count = fares[0].fareTotal;
1798        }
1799
1800        if (fares.length > 1) {
1801            data.fareBasis2Code = fares[1].fareCode;
1802            data.fareBasis2Count = fares[1].fareTotal;
1803        }
1804        if (fares.length > 2) {
1805            data.fareBasis3Code = fares[2].fareCode;
1806            data.fareBasis3Count = fares[2].fareTotal;
1807        }
1808
1809        var travelPassengers = {
1810            "adults": parseInt($(".bat-passenger-faretype[fareCode='000']").val()),
1811            "concessions": parseInt($(".bat-passenger-faretype[fareCode='041']").val()),
1812            "children": parseInt($(".bat-passenger-faretype[fareCode='418']").val()),
1813            "seatedInfant": parseInt($(".bat-passenger-faretype[fareCode='451']").val()),
1814            "nursedInfant": 0,
1815            "seatedInfants": parseInt($(".bat-passenger-faretype[fareCode='451']").val()),
1816            "nursedInfants": 0,
1817            "accompaniedChildren": parseInt($(".bat-passenger-faretype[fareCode='418']").val()),
1818            "infants": parseInt($(".bat-passenger-faretype[fareCode='451']").val()),
1819            "concessionCard1": null,
1820            "concessionCard2": null,
1821            "concessionLater": null,
1822            "studentCard1": "",
1823            "studentCard2": "",
1824            "studentLater": null,
1825            "students": parseInt($(".bat-passenger-faretype[fareCode='220']").val())
1826        };
1827
1828        var travelOptions = {
1829            "options": data,
1830            "to": {
1831                "Code": destination.Code,
1832                "Description": destination.Description
1833            },
1834            "from": {
1835                "Code": origin.Code,
1836                "Description": origin.Description
1837            },
1838            "passengers": travelPassengers
1839        };
1840
1841        localStorage.setItem("travel_options", JSON.stringify(travelOptions));
1842        localStorage.setItem("travel_passengers", JSON.stringify(travelPassengers));
1843
1844        $('#searchTripsButtonText').hide();
1845        $('#searchTripsButtonSpinner').css('display', 'inline-block');
1846
1847        showOverlay("SEARCHING TRIPS...");
1848
1849        var csrf = $('#csrf').val();
1850
1851        $.ajax({
1852            url: 'umbraco/surface/travel/postexpressavailability',
1853            contentType: "application/json",
1854            dataType: 'json',
1855            type: 'post',
1856            data: JSON.stringify(travelOptions),
1857            headers: {
1858                '__RequestVerificationToken': csrf
1859            },
1860            success: function (response) {
1861                if (response.status === "error" || response.data.length == 0) {
1862                    hideOverlay();
1863                    $('#searchTripsButtonText').show();
1864                    $('#searchTripsButtonSpinner').hide();
1865                    $('#bat-error-modal-message').html(response.responseMessage || "An unknown error has occurred.");
1866                    showErrorModal();
1867                } else if (response.status === "success") {
1868                    localStorage.setItem('travel_availability', JSON.stringify(response.data));
1869                    localStorage.setItem('offline_booking', '');
1870                    $('[data-toggle="tooltip"]').tooltip();
1871                    window.location.href = '/book-a-ticket/availability?origin=' + origin.Code + '&destination=' + destination.Code;
1872
1873                    $('#searchTripsButtonText').show();
1874                    $('#searchTripsButtonSpinner').hide();
1875                } else {
1876                    hideOverlay();
1877                    $('#searchTripsButtonText').show();
1878                    $('#searchTripsButtonSpinner').hide();
1879                    $('#bat-error-modal-message').html("An unknown error has occurred.");
1880                }
1881            },
1882            error: function (err) {
1883                var data = JSON.parse(err.responseJSON.data);
1884                hideOverlay();
1885                $('#searchTripsButtonText').show();
1886                $('#searchTripsButtonSpinner').hide();
1887                if (!!data.Message) {
1888                    $('#bat-error-modal-message').html(data.Message);
1889                    showErrorModal();
1890                } else {
1891                    if (!!data.ErrorSummary) {
1892                        $('#bat-error-modal-message').html(data.ErrorSummary + ' - Please contact Greyhound on <a href="tel: 1300473946">1300 473 946</a> for more help.');
1893                        showErrorModal();
1894                    } else {
1895                        $('#bat-error-modal-message').html('An unknown error has occurred. Please contact Greyhound on <a href="tel: 1300473946">1300 473 946</a> for more help.');
1896                        showErrorModal();
1897                    }
1898                }
1899            }
1900        });
1901
1902    });
1903    $('#bat-departure').val(moment().format('DD/MM/YYYY'));
1904    
1905 // var url = new URL(url_string);
1906
1907    var url_string = window.location.href;
1908    function getUrlVars() {
1909        var vars = [];
1910        var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
1911            vars[key] = value;
1912        });
1913        return vars;
1914    }
1915
1916    var vars = getUrlVars();
1917    console.log('vars len', Object.keys(vars).length);
1918
1919    setTimeout(function () {
1920        loadFromUmbraco();
1921        if (Object.keys(vars).length > 0) {
1922            loadFromStorage();
1923            loadFromParameters();
1924        } else {
1925            loadFromStorage();
1926            loadFromUmbraco();
1927        }
1928    }, 100);
1929}
1930
1931// This has been moved to /Views/Components/Component.CoachTrackerForm.cshtml
1932
1933var stops = [];
1934var fareTypes = [];
1935var stopData = null;
1936var saData = null;
1937
1938var resizeFunctions = [];
1939
1940// Passenger vars
1941var passengerTotal = 0;
1942var passengerSummary = '';
1943var totalFareTypes = 0;
1944var totalGuardians = 0;
1945var totalInfants = 0;
1946var totalChildren = 0;
1947var totalConcessions = 0;
1948var hasErrors = false;
1949
1950var localStops = localStorage.getItem('travel_stops');
1951var tripType = 'return';
1952var ctDirection = 'departing';
1953var promoOpen = false;
1954var fullCollapse = false;
1955var originalPathName = window.location.pathname;
1956
1957jQuery.fn.extend({
1958    groupVal: function () {
1959        return $(this).filter(':checked').val();
1960    }
1961});
1962
1963function getTripType() {
1964    return tripType;
1965}
1966
1967var substringMatcher = function (stops) {
1968    return function findMatches(q, cb) {
1969        var matches, substringRegex;
1970
1971        var startsWithMatches = [];
1972        var descriptionMatches = [];
1973        var codeMatches = [];
1974        var addressMatches = [];
1975
1976        // an array that will be populated with substring matches
1977        matches = [];
1978
1979        // regex used to determine if a string contains the substring `q`
1980        substrRegex = new RegExp(q, 'i');
1981
1982        // iterate through the pool of strings and for any string that
1983        // contains the substring `q`, add it to the `matches` array
1984        $.each(stops, function (i, stop) {
1985            var code = stop.Code.toLowerCase();
1986            var address = stop.Address.toLowerCase();
1987            var description = stop.Description.toLowerCase();
1988            var qq = q.toLowerCase();
1989            if (description.indexOf(qq) === 0) {
1990                startsWithMatches.push(stop);
1991            } else if (code.indexOf(qq) > -1) {
1992                codeMatches.push(stop);
1993            } else if (description.indexOf(qq) > -1) {
1994                descriptionMatches.push(stop);
1995            } else if (address.indexOf(qq) > -1) {
1996                addressMatches.push(stop);
1997            } else {
1998                //
1999            }
2000        });
2001
2002        matches = startsWithMatches.concat(descriptionMatches).concat(codeMatches).concat(addressMatches);
2003
2004        cb(matches);
2005    };
2006};
2007
2008function getTimeStampedStorageObject(data) {
2009    return { data: data, timestamp: new Date() };
2010}
2011
2012function storageItemHasExpired(data) {
2013    if (!data.timestamp) {
2014        return true;
2015    } else {
2016        var dataTimestamp = new Date(data.timestamp);
2017        var timeStampExpiration = dataTimestamp.setDate(dataTimestamp.getDate() + 1);
2018        var currentTimeStamp = new Date();
2019        if (timeStampExpiration < currentTimeStamp) {
2020            return true;
2021        }
2022    }
2023    return false;
2024}
2025
2026function getStops() {
2027    $.get("umbraco/api/travel/getstops",
2028        function(data) {
2029            stops = data;
2030            stopData = substringMatcher(stops);
2031            var storageDate = getTimeStampedStorageObject(stops); // add timestamp to the object
2032            localStops = JSON.stringify(storageDate);
2033            localStorage.setItem('travel_stops', localStops);
2034        });
2035}
2036
2037function loadStops() {
2038    if (localStops != null) {
2039        var data = JSON.parse(localStops);
2040        if (!storageItemHasExpired(data)) {
2041            stops = data.data; // grab data from timestamped object
2042            stopData = substringMatcher(stops);
2043        } else {
2044            getStops();
2045        }
2046    } else {
2047        getStops();
2048    }
2049}
2050
2051function addError(elementId, message) {
2052    console.log('addError', $("#" + elementId));
2053    if ($("#" + elementId).tooltip() != null) {
2054        $("#" + elementId).tooltip('destroy');
2055    }
2056
2057    $('.tooltip.error').each(function (index, element) {
2058        $(element).remove();
2059    });
2060    setTimeout(function () {
2061        $("#" + elementId).tooltip({
2062            placement: "top",
2063            html: true,
2064            title: "<span>" + message + "</span>",
2065            trigger: 'manual',
2066            template: '<div class="tooltip error tooltip-top" role="tooltip">' +
2067                '<div class="tooltip-inner"></div>' +
2068                '<div class="arrow"></div><div class="inner-arrow"></div>' +
2069                '</div>'
2070        });
2071        $("#" + elementId).addClass('error');
2072        $("#" + elementId).tooltip('show');
2073    }, 200);
2074}
2075
2076function clearError(elementId) {
2077    console.log('clearError', elementId);
2078    $("#" + elementId).removeClass('error');
2079
2080    console.log('$("#" + ' + elementId + ').tooltip', $("#" + elementId).tooltip());
2081    if ($("#" + elementId).tooltip() != null) {
2082        $("#" + elementId).tooltip('destroy');
2083    }
2084}
2085
2086function setupGlobalEvents() {
2087
2088    $(window).on('resize', function () {
2089        resizeFunctions.forEach(function (func) {
2090            func();
2091        });
2092    });
2093
2094    resizeFunctions.push(function () {
2095        if (window.screen.width < 852 && window.screen.width >= 768) {
2096            $('#searchTripsButtonText').html("SEARCH");
2097        } else {
2098            $('#searchTripsButtonText').html("SEARCH TRIPS");
2099        }
2100    });
2101
2102    $(window).trigger('resize');
2103
2104    $("input").on('focus', function () {
2105        if (!$('.booking-widget').hasClass('focused')) {
2106            $('.booking-widget').addClass('focused')
2107        }
2108        $(this).first().tooltip('hide');
2109        $(this).first().removeClass('error');
2110    });
2111    fullCollapse = $('#full-collapse-val').val().toLowerCase() === 'true';
2112
2113    $('#booking-widget-tabs li').each(function (li, index) {
2114        $(this).on('click', function (e) {
2115            var targetTab = $(this).children('a').attr('href');
2116            var that = this;
2117            var gap = '/'
2118
2119            if (originalPathName == '') {
2120                gap = '';
2121            }
2122
2123            console.log('originalPathName', originalPathName);
2124
2125            //history.replaceState(null, null, originalPathName + $(this).children('a').attr('title'));
2126            history.replaceState(null, null, getChildPath($(this).children('a').attr('title')));
2127            if (fullCollapse === true) {
2128                if ($(that).hasClass('active') === true) {
2129                    setTimeout(function () {
2130                        $(that).removeClass('active');
2131                        $(targetTab).removeClass('active');
2132                    }, 0);
2133                }
2134            }
2135            setTimeout(function () {
2136                console.log('active tabs:', $('#booking-widget-tabs li.active').length);
2137                if ($('#booking-widget-tabs li.active').length > 0) {
2138                    $('#booking-widget-tabs').removeClass('inactive');
2139                    $('.ga-zip-widget').show();
2140                } else {
2141                    $('#booking-widget-tabs').addClass('inactive');
2142                    $('.ga-zip-widget').hide();
2143                }
2144            }, 10);
2145        });
2146    });
2147
2148    if ($('#booking-widget-tabs li.active').length > 0) {
2149        $('#booking-widget-tabs').removeClass('inactive');
2150        $('.ga-zip-widget').show();
2151    } else {
2152        $('#booking-widget-tabs').addClass('inactive');
2153        $('.ga-zip-widget').hide();
2154
2155    }
2156
2157}
2158
2159function getChildPath(title) {
2160    var pathParts = window.location.href.split('/');
2161    var lastPathPartIndex = pathParts.length - 1;
2162    if (pathParts[lastPathPartIndex] == "") {
2163        pathParts.pop();
2164        lastPathPartIndex--;
2165    }
2166    if (bookingWidgetTabs.indexOf(pathParts[lastPathPartIndex]) > -1) {
2167        pathParts[lastPathPartIndex] = title;
2168    } else {
2169        pathParts.push(title);
2170    }
2171    return pathParts.join("/");
2172}
2173
2174function showOverlay(message) {
2175    if (message != null) {
2176        $('.bw-overlay .loader-text').html(message);
2177    } else {
2178
2179        $('.bw-overlay .loader-text').html('LOADING...');
2180    }
2181    $('.bw-overlay').addClass('visible');
2182}
2183
2184function hideOverlay() {
2185    $('.bw-overlay').removeClass('visible');
2186}
2187
2188const bookingWidgetTabs = [
2189    'book-a-ticket',
2190    'manage-booking',
2191    'coach-tracker',
2192    'timetables'
2193]
2194
2195$(document).ready(function () {
2196    // Getting data
2197    loadStops();
2198    loadFares();
2199
2200    // Common events
2201    setupGlobalEvents();
2202
2203    // Setup forms
2204    setupBAT();
2205    setupMB();
2206    setupCT();
2207    setupTT();
2208
2209    $('.booking-widget form').disableAutoFill();
2210
2211});
2212
2213function loginWithEmail() {
2214
2215    $.getJSON("https://api.ipify.org?format=json",
2216        function (ipData) {
2217
2218            var checkData = {
2219                "bookingNumber": $('#mb-booking-number').val(),
2220                "Email": $('#mb-booking-email').val(),
2221                "IpAddress": ipData.ip
2222            };
2223
2224            var csrf = $('#csrf').val();
2225
2226            $.ajax({
2227                url: 'umbraco/api/booking/manageBooking',
2228                contentType: "application/json",
2229                type: 'post',
2230                data: JSON.stringify(checkData),
2231                headers: {
2232                    '__RequestVerificationToken': csrf
2233                },
2234                success: function (result) {
2235                    window.location.href = "/my-greyhound/booking-management/details?bookingGuid=" + result.BookingGuid;
2236                },
2237                error: function (err) {
2238                    hideOverlay();
2239                    $('#mb-error-modal-message').html(err.responseJSON.ErrorSummary);
2240                    $('#manageBookingButtonText').show();
2241                    $('#manageBookingButtonSpinner').css('display', 'none');
2242                    showErrorModal();
2243                },
2244                always: function (result) {
2245                    $('#manageBookingButtonText').show();
2246                    $('#manageBookingButtonSpinner').hide();
2247                }
2248            });
2249
2250        });
2251
2252}
2253
2254function setupMB() {
2255    $('#manageBookingButton').on('click', function () {
2256        if (validateMB_submit(false) === false) {
2257            return;
2258        }
2259
2260        $('#manageBookingButtonText').hide();
2261        $('#manageBookingButtonSpinner').css('display', 'inline-block');
2262        showOverlay("LOADING BOOKING...");
2263        loginWithEmail();
2264    });
2265
2266    $('.tab-pane').on('click', function (e) {
2267        hideErrorModal();
2268    });
2269
2270    $('#mb-booking-number, #mb-booking-email').on('blur change', function (e) {
2271        validateMB(true);
2272    });
2273
2274    $('#mb-booking-number').on('blur change keyup', function (e) {
2275        validateMB(true);
2276    });
2277
2278}
2279
2280function validateMB(ignoreEmpty) {
2281    $('.tooltip.error').each(function (index, element) {
2282        console.log('deleting', element);
2283        setTimeout(function () {
2284            $(element).remove();
2285        }, 200);
2286    });
2287
2288    var bookingEmail = $('#mb-booking-email').val();
2289    var bookingNumber = $('#mb-booking-number').val();
2290
2291    if (bookingEmail == '' && bookingNumber != '') {
2292        addError("mb-booking-email", "Please enter the email address linked to this booking number");
2293        return false;
2294    }
2295
2296    if (bookingEmail != '' && bookingNumber == '') {
2297        addError("mb-booking-number", "Please enter a booking number");
2298        return false;
2299    }
2300
2301    return true;
2302}
2303
2304function validateMB_submit(ignoreEmpty) {
2305    $('.tooltip.error').each(function (index, element) {
2306        console.log('deleting', element);
2307        setTimeout(function () {
2308            $(element).remove();
2309        }, 200);
2310    });
2311
2312    var bookingEmail = $('#mb-booking-email').val();
2313    var bookingNumber = $('#mb-booking-number').val();
2314
2315    if (bookingEmail == '') {
2316        addError("mb-booking-email", "Please enter the email address linked to this booking number");
2317        return false;
2318    }
2319
2320    if (bookingNumber == '') {
2321        addError("mb-booking-number", "Please enter a booking number");
2322        return false;
2323    }
2324
2325    //if (bookingEmail != '' && bookingNumber != '' && (isNaN(bookingNumber) || bookingNumber.length != 8)) {
2326    //    addError("mb-booking-number", "The booking number provided is not valid.  Please contact customer service on <a href='tel:1300473946'>1300 473 946</a> for assistance.");
2327    //    return false;
2328    //}
2329
2330    return true;
2331}
2332
2333function hideErrorModal() {
2334    $('#mb-error-modal').hide();
2335    $('.mb-form').css('opacity', 1);
2336}
2337
2338function showErrorModal() {
2339    $('#mb-error-modal').css('display', 'inline-block');
2340    $('.mb-form').css('opacity', 0.3);
2341}
2342
2343function setupTT() {
2344    $('#tt-origin').typeahead({
2345        hint: true,
2346        highlight: true,
2347        limit: 10,
2348        minLength: 0,
2349        autoselect: true
2350    }, {
2351        name: 'stopData',
2352        display: 'Description',
2353        source: stopData,
2354        templates: {
2355            empty: function (data) {
2356                if (data.query.length >= 3) { 
2357                    return [
2358                        '<div class="typeahead-error"><span>No matching location for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
2359                    ].join('\n');
2360                } else {
2361                    return [
2362                        ''
2363                    ].join('\n');
2364                }
2365            },
2366            suggestion: function (data) {
2367                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
2368            }
2369        }
2370    });
2371
2372    $('#tt-destination').typeahead({
2373        hint: true,
2374        highlight: true,
2375        limit: 10,
2376        minLength: 0,
2377        autoselect: true
2378    }, {
2379        name: 'stopData',
2380        display: 'Description',
2381        source: stopData,
2382        templates: {
2383            empty: function (data) {
2384                if (data.query.length >= 3) {
2385                    return [
2386                        '<div class="typeahead-error"><span>No matching location for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
2387                    ].join('\n');
2388                } else {
2389                    return [
2390                        ''
2391                    ].join('\n');
2392                }
2393            },
2394            suggestion: function (data) {
2395                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
2396            }
2397        }
2398    });
2399
2400    // Mobile Modals
2401
2402    $('#tt-origin-modal-input').typeahead({
2403        hint: true,
2404        highlight: true,
2405        limit: 10,
2406        minLength: 0,
2407        autoselect: true
2408    }, {
2409        name: 'stopData',
2410        display: 'Description',
2411        source: stopData,
2412        templates: {
2413            empty: function (data) {
2414                if (data.query.length >= 3) {
2415                    return [
2416                        '<div class="typeahead-error"><span>No matching location for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
2417                    ].join('\n');
2418                } else {
2419                    return [
2420                        ''
2421                    ].join('\n');
2422                }
2423            },
2424            suggestion: function (data) {
2425                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
2426            }
2427        }
2428    });
2429
2430    $('#tt-destination-modal-input').typeahead({
2431        hint: true,
2432        highlight: true,
2433        limit: 10,
2434        minLength: 0,
2435        autoselect: true
2436    }, {
2437        name: 'stopData',
2438        display: 'Description',
2439        source: stopData,
2440        templates: {
2441            empty: function (data) {
2442                if (data.query.length >= 3) {
2443                    return [
2444                        '<div class="typeahead-error"><span>No matching location for <strong>\'' + data.query.toUpperCase() + '\'</strong></span></div>'
2445                    ].join('\n');
2446                } else {
2447                    return [
2448                        ''
2449                    ].join('\n');
2450                }
2451            },
2452            suggestion: function (data) {
2453                return '<p><strong  class="stop-description">' + data.Description + '</strong> <br/> <span class="stop-location">' + data.Address + '</span></p>';
2454            }
2455        }
2456    });
2457
2458
2459    $('#tt-origin').on('focus', function (e, a, b) {
2460        if (screen.width < 768) {
2461
2462            $('#tt-origin-modal').modal('show');
2463
2464            $('#tt-origin-modal-input').focus();
2465            setTimeout(function () {
2466                $('#tt-origin-modal-input').focus();
2467                setTimeout(function () {
2468                    $('#tt-origin-modal-input').trigger('touchstart');
2469                }, 100);
2470            }, 200);
2471        }
2472    });
2473
2474
2475
2476    $('#tt-destination').on('focus', function (e, a, b) {
2477        if (screen.width < 768) {
2478
2479            $('#tt-destination-modal').modal('show');
2480
2481            $('#tt-destination-modal-input').focus();
2482            setTimeout(function () {
2483                $('#tt-destination-modal-input').focus();
2484                setTimeout(function () {
2485                    $('#tt-destination-modal-input').trigger('touchstart');
2486                }, 100);
2487            }, 200);
2488        }
2489    });
2490
2491    $('#tt-origin-modal').on('hide.bs.modal', function () {
2492        $('#tt-origin').typeahead('val', $('#tt-origin-modal-input').val());
2493        $('#tt-origin').blur();
2494    });
2495
2496    $('#tt-origin-modal').on('hidden.bs.modal', function () {
2497        $('#tt-origin-modal-input').blur();
2498        setTimeout(function () {
2499            $('#tt-origin-modal-input').blur();
2500        }, 200);
2501    });
2502
2503    $('#tt-destination-modal').on('hide.bs.modal', function () {
2504        $('#tt-destination').typeahead('val', $('#tt-destination-modal-input').val());
2505        $('#tt-destination').blur();
2506    });
2507
2508    $('#tt-destination-modal').on('hidden.bs.modal', function () {
2509        $('#tt-destination-modal-input').blur();
2510        setTimeout(function () {
2511            $('#tt-destination-modal-input').blur();
2512        }, 200);
2513    });
2514
2515    $('#tt-origin-modal-input').on('change typeahead:select', function () {
2516
2517        var val = $(this).val().toLowerCase();
2518        var result = false;
2519        if (stops.filter(function (x) { return x.Description.toLowerCase() === val; }).length > 0) {
2520            result = true;
2521        }
2522
2523        $("#tt-origin").tooltip('hide');
2524        $("#tt-origin").removeClass('error');
2525
2526        if (result === false) {
2527            $('#tt-origin').typeahead('val', $('#tt-origin-modal-input').val());
2528
2529            $('#tt-origin').blur();
2530        } else {
2531            $('#tt-origin-modal').modal('hide');
2532            $('#tt-origin').typeahead('val', $('#tt-origin-modal-input').val());
2533
2534            $('#tt-origin').blur();
2535        }
2536
2537    });
2538
2539
2540    $('#tt-destination-modal-input').on('change typeahead:select', function () {
2541
2542        var val = $(this).val().toLowerCase();
2543        var result = false;
2544        if (stops.filter(function (x) { return x.Description.toLowerCase() === val; }).length > 0) {
2545            result = true;
2546        }
2547
2548        $("#tt-destination").tooltip('hide');
2549        $("#tt-destination").removeClass('error');
2550
2551        if (result === false) {
2552            $('#tt-destination').typeahead('val', $('#tt-destination-modal-input').val());
2553
2554            $('#tt-destination').blur();
2555        } else {
2556            $('#tt-destination-modal').modal('hide');
2557            $('#tt-destination').typeahead('val', $('#tt-destination-modal-input').val());
2558
2559            $('#tt-destination').blur();
2560        }
2561
2562    });
2563
2564
2565    function customRange(input, a, b, c) {
2566        if (window.screen.width < 768) {
2567            var target = $('#tt-datepicker').attr('target');
2568            var selectedDate = $("#tt-mobile-datepicker").datepicker("getDate");
2569
2570            if (selectedDate != null) {
2571                $('#' + target).val(moment(selectedDate).format('DD/MM/YYYY'));
2572            }
2573            $('#tt-modal-datepicker').modal('hide');
2574        } else {
2575            var target = $('#tt-datepicker').attr('target');
2576            var selectedDate = $("#tt-datepicker").datepicker("getDate");
2577
2578            if (selectedDate != null) {
2579                $('#' + target).val(moment(selectedDate).format('DD/MM/YYYY'));
2580            }
2581
2582            $('#tt-datepicker').hide();
2583        }
2584    }
2585
2586
2587    $('#tt-date').on('click', function () {
2588        if (window.screen.width < 768) {
2589            $('#tt-modal-datepicker').modal('show');
2590        } else {
2591            if ($('#tt-datepicker').css('display') != 'none') {
2592                $('#tt-datepicker').hide();
2593
2594            } else {
2595                $('#tt-datepicker').show();
2596                if (document.documentMode || /Edge/.test(navigator.userAgent) || /Edg/.test(navigator.userAgent)) {
2597                    console.log('ie/edge detected.');
2598                } else {
2599                    setTimeout(function () {
2600                        $(".tabbable")[0].scrollIntoView({
2601                            behavior: "smooth",
2602                            block: "start"
2603                        });
2604                    }, 100);
2605                }
2606            }
2607        }
2608    });
2609
2610    $('#tt-datepicker').datepicker({
2611        autoclose: true,
2612        numberOfMonths: 2,
2613        minDate: new Date(),
2614        maxDate: moment().add(365, 'days').toDate(),
2615        dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
2616        dateFormat: 'dd/mm/yy',
2617        assumeNearbyYear: true,
2618        firstDay: 1,
2619        orientation: 'bottom',
2620        format: 'dd/mm/yyyy',
2621        startDate: moment().format('DD/MM/YYYY'),
2622        rangeSelect: true,
2623        beforeShow: customRange,
2624        onSelect: customRange
2625        ////autoclose: true,
2626        ////numberOfMonths: 2, //window.screen.width >= 991 && window.screen.width < 1640 ? 1 : 2,
2627        ////minDate: new Date(),
2628        ////dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
2629        ////dateFormat: 'dd/mm/yy',
2630        ////assumeNearbyYear: true,
2631        ////firstDay: 1,
2632        ////orientation: 'bottom',
2633        ////format: 'dd/mm/yyyy',
2634        ////startDate: moment().format('DD/MM/YYYY'),
2635        ////rangeSelect: true,
2636        ////beforeShow: customRange,
2637        ////onSelect: customRange
2638    });
2639     
2640
2641    $('#tt-date').val(moment().format('DD/MM/YYYY'));
2642
2643
2644    $(document).on('click', function (e) {
2645        if (
2646            !$(e.target).hasClass('ui-datepicker-next') &&
2647            !$(e.target).hasClass('ui-datepicker-prev') &&
2648            !$(e.target).hasClass('ui-icon') &&
2649            $(e.target).parents('.ui-datepicker').length === 0 &&
2650            $(e.target).parents('.ui-datepicker-group').length === 0 &&
2651            $(e.target).parents('#bat-datepicker').length === 0 &&
2652            $('#tt-datepicker').css('display') != 'none'
2653            && e.target.id.indexOf('tt-date') < 0) {
2654            $('#tt-datepicker').hide();
2655        }
2656    });
2657
2658
2659    if (window.screen.width < 768) {
2660        $('#tt-mobile-datepicker').datepicker({
2661            autoclose: true,
2662            numberOfMonths: 9,
2663            minDate: new Date(),
2664            maxDate: moment().add(365, 'days').toDate(),
2665            dayNamesMin: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
2666            dateFormat: 'dd/mm/yy',
2667            assumeNearbyYear: true,
2668            firstDay: 1,
2669            orientation: 'bottom',
2670            format: 'dd/mm/yyyy',
2671            startDate: moment().format('DD/MM/YYYY'),
2672            rangeSelect: true,
2673            beforeShow: customRange,
2674            onSelect: customRange
2675        });
2676    }
2677
2678    $('#tt-origin, #tt-destination').on('blur change', function () {
2679        validateTT(true);
2680    });
2681
2682    $('#tt-date').on('blur change', function () {
2683        validateTT(false);
2684    });
2685
2686    $('#tt-swap-locations').on('click', function () {
2687        var origin = $('#tt-origin').val();
2688        var destination = $('#tt-destination').val();
2689        $('#tt-origin').typeahead('val', destination);
2690        $('#tt-destination').typeahead('val', origin);
2691    });
2692
2693    $('#tt-button').on('click', function () {
2694        if (validateTT(false) === false) {
2695            return false;
2696        } 
2697        showOverlay("LOADING TIMETABLES...");
2698        var origin = $('#tt-origin').val();
2699        var destination = $('#tt-destination').val();
2700        var date = moment($('#tt-date').val(), 'DD/MM/YYYY').format('YYYY-MM-DD');
2701
2702        if (stops.length > 0) {
2703            origin = stops.filter(function(stop)  {
2704                return stop.Description == $('#tt-origin').val();
2705            })[0];
2706            destination = stops.filter(function (stop) {
2707                return stop.Description == $('#tt-destination').val();
2708            })[0];
2709        }
2710
2711        window.location.href = '/travel-information/timetables?origin=' + origin.Code + "&destination=" + destination.Code + "&date=" + date;
2712    });
2713
2714
2715}
2716
2717
2718
2719function validateTT(ignoreEmpty) {
2720
2721    $('.tooltip.error').each(function (index, element) {
2722        console.log('deleting', element);
2723        setTimeout(function () {
2724            $(element).remove();
2725        }, 200);
2726    });
2727
2728    var origin = $('#tt-origin').val();
2729    var destination = $('#tt-destination').val();
2730    var date = $('#tt-date').val();
2731    if (origin == '' && ignoreEmpty === false) {
2732        addError("tt-origin", "Please select an origin");
2733        return false;
2734    }
2735
2736    if (destination == '' && ignoreEmpty === false) {
2737        addError("tt-destination", "Please select a destination");
2738        return false;
2739    }
2740
2741    if (date == '') {
2742        addError("tt-date", "Please select a date");
2743        return false;
2744    }
2745
2746    var originVal = $('#tt-origin').val().toLowerCase();
2747    $('#tt-origin').val($('#tt-origin').val().toUpperCase());
2748    var originResult = false;
2749
2750    if (stops.filter(function (x) { return x.Description.toLowerCase() === originVal; }).length > 0) {
2751        originResult = true;
2752    }
2753
2754    var destinationVal = $('#tt-destination').val().toLowerCase();
2755    $('#tt-destination').val($('#tt-destination').val().toUpperCase());
2756    var destinationResult = false;
2757
2758    if (stops.filter(function (x) { return x.Description.toLowerCase() === destinationVal; }).length > 0) {
2759        destinationResult = true;
2760    }
2761
2762    if (originResult === false && ignoreEmpty === false) {
2763        addError("tt-origin", "Please select a valid origin");
2764        return false;
2765    }
2766    
2767    if (destinationResult === false && ignoreEmpty === false) {
2768        addError("tt-destination", "Please select a valid destination");
2769        return false;
2770    }
2771
2772    return true;
2773}

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.