PageSourceSearch

https://tiogatours.nl/static/TiogaTours/js/quote.js

js tiogatours.nl collected 2026-10-02 21:24:54 UTC 51,930 bytes, 1,334 lines download raw bytes

1$().ready(function () {
2    "use strict";
3
4
5    $(function () {
6        $.validator.setDefaults({ ignore: ":hidden:not(.chosen-select)" });
7    });
8
9    $('#input-route_type').on('change', function (e) {
10
11        $('input[data-open-on-route-types]').each(function (index) {
12            $(this).prop('checked', false);
13            $(this).parent('.component-toggler').next().hide();
14        });
15
16        $("input[data-open-on-route-types*='" + $(this).val() + "']").each(function (index) {
17            $(this).prop('checked', true);
18            var container = $(this).parent('.component-toggler').next();
19
20            container.show()
21            container.find('input, select, textarea').prop('disabled', '');
22            container.find('select').trigger('chosen:updated');
23            container = null;
24
25        });
26    });
27
28    var saveInterval = null;
29
30    var $dateReturn = $('#date-return'),
31        $dateLeave = $('#date-leave'),
32        $length = $('#length'),
33        $quoteForm = $('#quote-form');
34
35    $('#date-leave, #date-return, #length').on('change', function (e) {
36        if (!$dateLeave.val()) {
37            return;
38        }
39        let dateLeave = $dateLeave.prop('valueAsDate'),
40            dateReturn = new Date(dateLeave),
41            length = parseInt($length.val()),
42            animateElement = null,
43            bgColor = null;
44
45        if (e.target === $dateLeave[0]) {
46            $dateReturn[0].min = dateLeave.getFullYear() + '-' + (dateLeave.getMonth() + 1).toString().padStart(2, '0') + '-' + dateLeave.getDate().toString().padStart(2, '0');
47        }
48
49        if (e.target === $dateReturn[0]) {
50            dateReturn = $dateReturn.prop('valueAsDate');
51            if (!dateReturn) {
52                return;
53            }
54
55            length = Math.round((dateReturn.getTime() - dateLeave.getTime()) / (1000 * 60 * 60 * 24)) + 1;
56            if (length > 0) {
57                $length.val(length);
58                animateElement = $length;
59            } else {
60                $length.val(null);
61            }
62        } else if (e.target === $length[0] || e.target === $dateLeave[0]) {
63            if (!length) {
64                return;
65            }
66            dateReturn.setDate(dateLeave.getDate() + length - 1);
67            $dateReturn.prop('valueAsDate', dateReturn);
68            animateElement = $dateReturn;
69        } else {
70            return;
71        }
72
73        if (animateElement) {
74            animateElement.finish();
75            bgColor = animateElement.css('backgroundColor');
76            animateElement.animate({ backgroundColor: '#BBE' }, function () {
77                animateElement.animate({ backgroundColor: bgColor });
78            });
79        }
80
81        TiogaTours.Quote.updateDaysSelect(dateLeave, length);
82    });
83
84    if (document.getElementById('price-indication-target')) {
85        $dateLeave.on('change', () => {
86            const elem = document.getElementById('price-indication-target');
87            if ($dateLeave.val()) {
88                const uri = elem.dataset.url.replace('__date__', $dateLeave.val());
89
90                const httpRequest = new XMLHttpRequest();
91                httpRequest.onreadystatechange = () => {
92                    if (httpRequest.readyState === XMLHttpRequest.DONE) {
93                        let priceData = JSON.parse(httpRequest.responseText);
94
95                        document.querySelectorAll('select[name="motorhome_rental[model]"] option[data-name]').forEach((opt) => {
96                            let camperName = opt.dataset.name;
97
98                            if (priceData[camperName]) {
99                                opt.disabled = false;
100                                opt.dataset.priceIndication = priceData[camperName];
101                                opt.innerText = opt.dataset.name + '    (kale huurprijs indicatie ' + ' ' + priceData[camperName] + ')';
102                            } else {
103                                opt.disabled = true;
104                                opt.dataset.priceIndication = 'Niet beschikbaar voor vertrekdatum';
105                                opt.innerText = opt.dataset.name + '    (niet beschikbaar voor vertrekdatum)';
106                            }
107                        });
108
109                        elem.innerHTML = '';
110                        if (priceData['_view_']) {
111                            elem.innerHTML = priceData['_view_'];
112                        }
113
114                        $('select[name="motorhome_rental[model]"]').trigger('chosen:updated');
115                    }
116                };
117                httpRequest.open('GET', uri, true);
118                httpRequest.send();
119            } else {
120                elem.innerHTML = '';
121            }
122        });
123    }
124
125
126    var checkedBoxes = $('.component-toggler input:checked'),
127        formData = $quoteForm.getFormData();
128
129
130    TiogaTours.Quote.initFlightSegment(formData && formData.flights && formData.flights.segment ? formData.flights.segment : null);
131
132    $quoteForm.fancyForm();
133    $('[data-toggle="tooltip"]').tooltip();
134
135    window.location.hash = '#0';
136    TiogaTours.Quote.initSteps();
137
138    if ($('#save-form-data')) {
139        $quoteForm.loadFormData();
140    }
141
142    checkedBoxes.each(function () {
143        $(this).prop('checked', 'checked');
144    });
145
146    if ($dateLeave.val() === '') {
147        $dateLeave.focus();
148    }
149
150    setTimeout(function () {
151        saveInterval = setInterval(function () {
152            if ($('#save-form-data').is(':checked')) {
153                $quoteForm.saveFormData(false, 60 * 60);
154            } else {
155                $quoteForm.clearFormData();
156            }
157        }, 1500);
158    }, 8000);
159
160    var slideCheckboxStatus = function (chkbox) {
161        chkbox = $(chkbox);
162        if (chkbox.is(':checked') === true) {
163            $(chkbox.attr('data-slide-element')).slideDown();
164            $(chkbox.attr('data-slide-element')).prop('disabled', '');
165
166            // Do not disable/enable field elements, post all data
167            //$(chkbox.attr('data-slide-element')).find('input, textarea, select').prop('disabled', '');
168
169            if (chkbox.attr('data-slide-scrollto') === '1') {
170                $('html, body').animate({
171                    scrollTop: $(chkbox.attr('data-slide-element')).offset().top
172                }, 500);
173            }
174
175        } else {
176            $(chkbox.attr('data-slide-element')).slideUp();
177            $(chkbox.attr('data-slide-element')).prop('disabled', 'disabled');
178            // Do not disable field elements, post all data
179            //$(chkbox.attr('data-slide-element')).find('input, textarea, select').prop('disabled', 'disabled');
180        }
181    };
182
183    var slideElEventHandler = function () {
184        var chkbox = $(this);
185        slideCheckboxStatus(chkbox);
186    };
187
188    $('[data-slide-element]').each(function (idx, item) {
189        item = $(item);
190        slideCheckboxStatus(item);
191
192        item.on('click keyup change', slideElEventHandler);
193    });
194
195    TiogaTours.Quote.toggleCloseShown = false;
196    $('.component-toggler input[type=checkbox]').change(function () {
197        var container = $(this).parent().next();
198
199        if ($(this).prop('checked') === true) {
200            container.find('input, select, textarea').prop('disabled', '');
201            container.slideDown(400, function () {
202                container.find('input, select, textarea').prop('disabled', '');
203                container.find('select').trigger('chosen:updated');
204            });
205        } else if ($(this).prop('required') !== true) {
206            container.slideUp(400, function () {
207                container.find('input, select, textarea').prop('disabled', 'disabled');
208                container.find('select').trigger('chosen:updated');
209            });
210        } else if ($(this).prop('required') !== false) {
211            $(this).prop('checked', true);
212        }
213    });
214
215    $('.component-toggler input[type=checkbox]').change();
216
217    $('#quote-form .btn-reset').click(function () {
218        clearInterval(saveInterval);
219        $quoteForm.clearFormData();
220        $quoteForm[0].reset();
221        $('#quote-form select').trigger('chosen:updated');
222    });
223
224    TiogaTours.Quote.Motorhome.init($('#quote-component-motorhome'));
225    TiogaTours.Quote.CarRental.init($('#quote-component-car-rental'));
226    TiogaTours.Quote.MotorcycleRental.init($('#quote-component-motorcycle-rental'));
227    //TiogaTours.Quote.SyncCities.init($quoteForm);
228    TiogaTours.Quote.UpdateChildInput($quoteForm);
229    TiogaTours.Quote.PickCountry($quoteForm);
230    TiogaTours.Quote.PostalCodeCheck($quoteForm);
231
232    if (true === TiogaTours.chosenIsSupported()) {
233        $('select').filter(function () {
234            let $t = $(this);
235            return !$t.is('[data-quote-day-select="true"]')
236                && $t.parents('#flightticket-segment').length === 0
237                && $t.attr('name').indexOf('child') === -1;
238        }).each(function () {
239            $(this).chosen({
240                no_results_text: "-",
241                width: '100%',
242                display_disabled_options: false
243            });
244            $(this).css('display', 'none');
245        });
246    }
247
248    $('#camperSupplier').change(function () {
249        var supplier = $(this).val();
250
251        $('#camperModel').find('optgroup').removeAttr('disabled');
252        if (supplier !== '') {
253            $('#camperModel').find('optgroup:not(optgroup[label="' + supplier + '"])').attr('disabled', 'disabled');
254        }
255        $('#camperModel').trigger('chosen:updated');
256    });
257
258    $('#input-route_type').trigger('change');
259    $('#date-leave').trigger('change');
260    /**
261     * Autofill invoice-address
262     * /
263     var delay = (function () {
264     var timer = 0;
265     return function (callback, ms) {
266     clearTimeout(timer);
267     timer = setTimeout(callback, ms);
268     };
269     })();
270
271     function getAddress(zipCode, houseNumber, streetElement, townElement) {
272     if (houseNumber.length > 0 && zipCode.length === 6 || zipCode.length === 7) {
273     $.post('', {postalcode: zipCode, housenr: houseNumber}, function (data) {
274     if (data._embedded.addresses[0] !== undefined) {
275     streetElement.val(data._embedded.addresses[0].street);
276     townElement.val(data._embedded.addresses[0].city.label);
277     }
278     }, 'json');
279     }
280     }
281
282     var postalCode = $('#postalcode');
283     var houseNumber = $('#housenr');
284
285     postalCode.keyup(function () {
286     delay(function () {
287     getAddress(postalCode.val(), houseNumber.val(), $('#street'), $('#city'));
288     }, 1000);
289     });
290
291     houseNumber.keyup(function () {
292     delay(function () {
293     getAddress(postalCode.val(), houseNumber.val(), $('#street'), $('#city'));
294     }, 1000);
295     });
296
297     /**
298     * Manual invoice-address
299     * /
300     $('#manual-invoice-address').change(function () {
301     if ($(this).prop('checked')) {
302     $('#street').removeAttr('readonly');
303     $('#city').removeAttr('readonly');
304     }
305     else {
306     $('#street').attr('readonly', true);
307     $('#city').attr('readonly', true);
308     }
309     });
310     */
311});
312
313if (typeof TiogaTours === 'undefined') {
314    TiogaTours = {};
315}
316
317if (typeof TiogaTours.Quote === 'undefined') {
318    TiogaTours.Quote = {};
319}
320
321
322TiogaTours.chosenIsSupported = function () {
323    if (window.navigator.appName === "Microsoft Internet Explorer") {
324        return document.documentMode >= 8;
325    }
326    if (/iP(od|hone|ad)/i.test(window.navigator.userAgent)) {
327        return false;
328    }
329    if (/Android/i.test(window.navigator.userAgent)) {
330        if (/Mobile/i.test(window.navigator.userAgent)) {
331            return false;
332        }
333    }
334    return true;
335};
336
337
338TiogaTours.Quote.initFlightSegment = function (segmentData) {
339
340    var originalRow = $('#flightticket-segment');
341    originalRow.hide();
342    originalRow.parents('form').first().after(originalRow);
343    var addSegment = function (id) {
344        var row = originalRow.clone();
345        row.show();
346        if (id === undefined) {
347            do {
348                id = 's' + parseInt(Math.random() * 1000);
349            } while ($('#' + id).length > 0);
350        }
351
352        row.attr('id', id);
353        $(':input', row).each(function () {
354            $(this).attr('name', $(this).attr('name').replace('][][', '][' + id + ']['));
355            $(this).prop('disabled', false);
356        });
357
358        $('#flightticket-segment-control').before(row);
359        if (true === TiogaTours.chosenIsSupported()) {
360            $('select', row).filter(function () {
361                return $(this).find('option').length > 20 && !$(this).is('[data-quote-day-select="true"]');
362            }).chosen({
363                no_results_text: "-",
364                width: '100%',
365                display_disabled_options: false
366            });
367        }
368    };
369    $('#flightticket-add-segment').click(function () {
370        addSegment();
371    });
372
373    for (var id in segmentData) {
374        id = '' + id;
375        if (id.match(new RegExp('^s')) === null) {
376            continue;
377        }
378        addSegment(id);
379    }
380
381    $('#quote-component-flights').on('click', '.flightticket-delete-segment', function () {
382        $(this).parents('.row').first().remove();
383    });
384};
385
386
387TiogaTours.Quote.updateDaysSelect = function (startDate, duration) {
388    "use strict";
389
390    duration = parseInt(duration);
391
392    $('[data-quote-day-select]').each(function () {
393        var $i = $(this), $newEl, opts, currDate, currVal, offsetFromEnd;
394
395        currVal = parseInt($i.val());
396        offsetFromEnd = $i.find('option').length - 1 - currVal;
397        if (offsetFromEnd < currVal) {
398            currVal = '' + (duration - offsetFromEnd);
399        }
400
401        if ($i.prop('tagName') === 'INPUT') {
402            $newEl = $('<select>');
403            $.each($i.prop('attributes'), function () {
404                $newEl.attr(this.name, this.value);
405            });
406            $newEl.attr('type', null);
407            $i.after($newEl);
408            $i.remove();
409            $i = $newEl;
410        }
411
412        opts = { minVal: null, maxVal: null, defaultVal: null },
413            currDate = new Date(startDate);
414
415        $.each([{ name: 'minVal', suffix: '-min' }, { name: 'maxVal', suffix: '-max' }, {
416            name: 'defaultVal',
417            suffix: '-default'
418        }], function (idx, o) {
419            opts[o.name] = $i.attr('data-quote-day-select' + o.suffix) !== undefined ? parseInt($i.attr('data-quote-day-select' + o.suffix)) : null;
420
421            if (opts[o.name] < 0) {
422                opts[o.name] = duration + opts[o.name] + 1;
423            }
424
425        });
426        console.log(opts);
427        $i.empty();
428
429        $i.append($('<option value=""></option>'));
430        for (let i = 1; i <= duration; i++) {
431            $i.append('<option value="' + i + '"'
432                + ((opts.minVal !== null && i < opts.minVal) || (
432opts.maxVal !== null && i > opts.maxVal) ? ' disabled' : '')
433                + (opts.defaultVal === i ? ' selected' : '')
434                + '>'
435                + i + '. ' + currDate.toLocaleDateString()
436                + (window.quoteRouteCities && window.quoteRouteCities[i] ?
437                    ' ' + (window.quoteRouteCities[i - 1] !== window.quoteRouteCities[i] ? window.quoteRouteCities[i - 1] + ' - ' : '')
438                    + (window.quoteRouteCities[i]??'') : ''
439                )
440                + '</option>');
441            currDate.setDate(currDate.getDate() + 1);
442        }
443
444        if (currVal !== null && currVal !== "" && !isNaN(currVal)) {
445            $i.val(currVal);
446        }
447    });
448};
449
450
451TiogaTours.Quote.SyncCities = {
452    init: function (target) {
453        var syncFrom = '[name*="outbound][airport_to"], [name*="pickup][location"]',
454            syncTo = '[name*="inbound][airport_from"], [name*="dropoff][location"]';
455        $(target).on('change', syncFrom, function (e) {
456            TiogaTours.Quote.SyncCities.sync(e.target, syncFrom);
457        });
458        $(target).on('change', syncTo, function (e) {
459            TiogaTours.Quote.SyncCities.sync(e.target, syncTo);
460        });
461
462        TiogaTours.Quote.SyncCities.storeCurrentValues(syncFrom);
463        TiogaTours.Quote.SyncCities.storeCurrentValues(syncTo);
464    },
465
466    sync: function (changedEl, selector) {
467        var selectedValue = $(changedEl).val(),
468            prevVal = $(changedEl).data('previous-value');
469
470        if (selectedValue === '') {
471            return;
472        }
473
474        $(selector).each(function () {
475            if (typeof $(this).val() === 'string'
476                && $(this).val().indexOf(prevVal) === 0
477                && $(this).find('option').filter(function () {
478                    return $(this).attr('value').indexOf(selectedValue) === 0;
479                }).length > 0
480            ) {
481                var newVal = $(this).find('[value^="' + selectedValue + '"]').attr('value');
482                if ($(this).val() !== newVal) {
483                    $(this).val(newVal);
484                    $(this).change();
485                    $(this).trigger('chosen:updated');
486                }
487            }
488        });
489
490        TiogaTours.Quote.SyncCities.storeCurrentValues(selector);
491    },
492
493    storeCurrentValues: function (selector) {
494        $(selector).each(function () {
495            $(this).data('previous-value', $(this).val());
496        });
497    }
498};
499
500
501TiogaTours.Quote.UpdateChildInput = function (target) {
502    var updateChildInputs = function (e) {
503        var childCount = parseInt($(target).find('[name*="child-num"]').val()),
504            $childDetails = $('#children-details');
505
506        if (true === isNaN(childCount) || childCount === 0) {
507            $childDetails.hide();
508        } else {
509            $childDetails.show();
510            var $chg = $('.form-group', $childDetails), i;
511            $chg.hide();
512            $($chg[i]).prop('required', 'required');
513            for (i = 0; i < childCount; i++) {
514                $($chg[i]).prop('required', 'required');
515                $($chg[i]).show();
516            }
517        }
518    };
519
520    updateChildInputs();
521    $(target).find('[name*="child-num"]').change(updateChildInputs);
522};
523
524
525TiogaTours.Quote.PickCountry = function (target) {
526    var updateCountryInputs = function (e) {
527        var $dropdownContainer = $('.country-select-list', target),
528            $dropdownList = $('select[name*=country]', target),
529            $quickSelected = $('[name*="country-quickselect"]:checked', target);
530
531        if ($quickSelected.val() === 'Anders') {
532            if (!$dropdownContainer.is(':visible')) {
533                $dropdownContainer.slideDown();
534                $dropdownContainer.val('');
535                $dropdownContainer.focus();
536            }
537        } else {
538            $dropdownContainer.slideUp(function () {
539                $dropdownContainer.val($('[name*="country"]:checked').val());
540            });
541
542            if ($quickSelected.val() !== $dropdownList.val()) {
543                $dropdownList.val($quickSelected.val());
544                $dropdownList.trigger('chosen:updated');
545                $dropdownList.change();
546            }
547        }
548    };
549
550    updateCountryInputs();
551    $('[name*=country], [name*=country-quickselect]', target).change(updateCountryInputs);
552};
553
554
555TiogaTours.Quote.Motorhome = {
556    init: function (target) {
557        TiogaTours.Quote.Motorhome.watchForm(target);
558
559        TiogaTours.Quote.Motorhome.initMapPick(target);
560        TiogaTours.Quote.Motorhome.initModelPick(target);
561        TiogaTours.Quote.Motorhome.initDistance(target);
562    },
563
564    initDistance: function (target) {
565        var fn = function () {
566            if ($(target).find('[name*=distance][value=custom]:checked').length > 0) {
567                $(target).find('[name*=distance_custom]').focus();
568            } else {
569                $(target).find('[name*=distance_custom]').val('');
570            }
571        };
572        $(target).on('change', '[name*=distance][type=radio]', fn);
573        $(target).on('focus', '[name*=distance_custom]', function () {
574            $(target).find('[name*=distance][value=custom]').attr('checked', 'checked');
575        });
576        fn();
577    },
578
579    initModelPick: function (target) {
580        $(target).find('.show-model-picker').click(function (e) {
581            e.preventDefault();
582            $('#quote-motorhome-model-modal').modal();
583            if (top !== self) {
584                var $dialog = $('#quote-motorhome-model-modal .modal-dialog'),
585                    $modalContainer = $('<div class="modal" style="z-index:2000; display:block; clear:both; position:relative;"></div>');
586                $($(e.target).parents('.row')[0]).after($modalContainer);
587                $modalContainer.append($dialog);
588                $('.modal-body', $dialog).css({ 'overflow-y': 'auto', 'max-height': 700 });
589
590                $dialog.css('zIndex', 2000);
591                var hide = function (e) {
592                    if (e.target.tagName === 'button') {
593                        e.preventDefault();
594                    }
595                    $('#quote-motorhome-model-modal').append($dialog);
596                    $modalContainer.remove();
597                };
598
599                $dialog.find('button[data-dismiss="modal"]').on('click', function () {
600                    $('#quote-motorhome-model-modal').modal('hide');
601                });
602                $dialog.on('click', 'button', function (e) {
603                    e.preventDefault();
604                });
605                $('#quote-motorhome-model-modal').on('hide.bs.modal', hide);
606            }
607
608
609            $('#quote-motorhome-model-modal-dialog .hidden-models-msg').hide();
610
611            var inputEl = $($(e.target).prevAll('select')),
612                elList = $('#quote-motorhome-model-modal-dialog ul'),
613                i;
614
615            elList.empty();
616
617            if (!$('#quote-motorhome-model-modal .map').data('event-initialized')) {
618                $('#quote-motorhome-model-modal .map').data('event-initialized', true);
619
620                $('#quote-motorhome-model-modal-dialog').on('click', '[data-value]', function (e) {
621                    e.preventDefault();
622                    $('#quote-motorhome-model-modal').modal('hide');
623                    inputEl.val($(this).attr('data-value'));
624                    inputEl.change();
625                    inputEl.trigger('chosen:updated');
626                });
627            }
628
629            inputEl.find('option').each(function () {
630                var $option = $(this);
631                if ($option.attr('value') === '') {
632                    return;
633                } else if ($option.attr('data-invalid') === 'true') {
634                    $('#quote-motorhome-model-modal-dialog .hidden-models-msg').show();
635                    return;
636                }
637
638                var html = '<li>'
639                html += '<h3>' + $option.attr('data-name') + '</h3><dl class="dl-horizontal col-xs-12 col-md-6">';
640                html += '<dt>Verhuurder:</dt><dd>' + $option.attr('data-suppliers') + '</dd>';
641                html += '<dt>Campertype:</dt><dd>' + $option.attr('data-camper-class') + '</dd>';
642                if ($option.attr('data-price-indication')) {
643                    html += '<dt>Kale huurprijs indicatie:</dt><dd>' + $option.attr('data-price-indication')
644                        + ' <a data-toggle="tooltip" data-placement="top" title="Deze kale huurprijs is een prijsindicatie voor dit campertype (' + $option.attr('data-camper-class') + '). Naast de kale huurprijs\n' +
645                        '        zijn er allerlei extra kosten voor bijvoorbeeld de camperinventaris, beddengoed, kilometerpakketten, one-way\n' +
646                        '        kosten en verzekeringen. Eventuele kortingen en acties zijn ook niet toegepast."><i class="glyphicons glyphicons-info-sign" style="margin-top:2px;"></i></a>'
647                        + '</dd>';
648                }
649                html += '<dt>Lengte:</dt><dd>' + (
650                    $option.attr('data-vehicle-length-min') === $option.attr('data-vehicle-length-max') || $option.attr('data-vehicle-length-max') === ''
651                        ? $option.attr('data-vehicle-length-min') : ('' + $option.attr('data-vehicle-length-min') + ' tot ' + $option.attr('data-vehicle-length-max'))
652                ) + ' meter' + '</dd>';
653                html += '<dt>Volwassenen:</dt><dd class="camper-icons">'
654                for (i = 0; i < parseInt($option.attr('data-capacity-adults')); i++) {
655                    html += '<i class="adult" title="volwassene"></i>';
656                }
657                html += '</dd>';
658                if (parseInt($option.attr('data-capacity-children')) > 0) {
659                    html += '<dt>Kinderen:</dt><dd class="camper-icons">'
660                    for (i = 0; i < parseInt($option.attr('data-capacity-children')); i++) {
661                        html += '<i class="child" title="kind"></i>';
662                    }
663                    html += '</dd>';
664                }
665
666                html += '<dt>&nbsp;</dt><dd style="margin-top:10px;"><button class="btn btn-primary" data-value="' + $option.attr('value') + '">Kies dit model</button></dd>';
667                html += '</dl>';
668
669                if ($option.attr('data-image') !== '') {
670                    html += '<a href="javascript:void null;" data-value="' + $option.attr('value') + '">';
671                    html += '<img src="' + $option.attr('data-image') + '" alt="' + $option.text() + '">';
672                    html += '</a>';
673                }
674                html += '</li>';
675                elList.append($(html));
676                $('[data-toggle="tooltip"]').tooltip();
677            });
678        });
679    },
680
681    initMapPick: function (target) {
682        $(target).find('.show-map-picker').click(function (e) {
683            e.preventDefault();
684            $('#quote-motorhome-location-modal').modal();
685
686            if (top !== self) {
687                var $dialog = $('#quote-motorhome-location-modal .modal-dialog'),
688                    $modalContainer = $('<div class="modal" style="z-index:2000; display:block; clear:both; position:relative;"></div>');
689                $($(e.target).parents('.row')[0]).after($modalContainer);
690                $modalContainer.append($dialog);
691                $('.modal-body', $dialog).css({ 'overflow-y': 'auto', 'max-height': 700 });
692
693                $dialog.css('zIndex', 2000);
694                var hide = function (e) {
695                    if (e.target.tagName === 'button') {
696                        e.preventDefault();
697                    }
698                    $('#quote-motorhome-location-modal').append($dialog);
699                    $modalContainer.remove();
700                };
701
702                $dialog.find('button[data-dismiss="modal"]').on('click', function () {
703                    $('#quote-motorhome-location-modal').modal('hide');
704                });
705                $dialog.on('click', 'button', function (e) {
706                    e.preventDefault();
707                });
708                $('#quote-motorhome-location-modal').on('hide.bs.modal', hide);
709            }
710
711            if (!$('#quote-motorhome-location-modal-dialog .map').data('map-initialized')) {
712                $('#quote-motorhome-location-modal-dialog .map').data('map-initialized', true);
713
714                TiogaTours.Quote.Motorhome.locationMap = new google.maps.Map($('#quote-motorhome-location-modal-dialog .map')[0], {
715                    center: { lat: 0, lng: 0 },
716                    zoom: 8
717                });
718
719                // Resize map after modal is shown
720                $('#quote-motorhome-location-modal').on('shown.bs.modal', function () {
721                    google.maps.event.trigger(TiogaTours.Quote.Motorhome.locationMap, 'resize');
722                });
723            }
724
725            var inputEl = $($(e.target).prevAll('select'));
726
727            if (TiogaTours.Quote.Motorhome.locationMarkers) {
728                $.each(TiogaTours.Quote.Motorhome.locationMarkers, function () {
729                    this.setMap(null);
730                });
731            }
732            TiogaTours.Quote.Motorhome.locationMarkers = [];
733
734            var addMarkerClickEvent = function (marker, inputEl) {
735                google.maps.event.addListener(marker, 'click', function () {
736                    var contentEl = $('<div><strong>' + marker.getTitle() + '</strong><br><br>'
737                        + '<a class="btn btn-primary">Kies deze locatie</a></div>');
738                    var infowin = new google.maps.InfoWindow({
739                        content: contentEl[0]
740                    });
741                    infowin.open(marker.getMap(), marker);
742
743                    contentEl.on('click', '.btn', function () {
744                        inputEl.val(marker.getTitle());
745                        $('#quote-motorhome-location-modal').modal('hide');
746                        inputEl.change();
747                        inputEl.trigger('chosen:updated');
748                    });
749                });
750            };
751
752            var bounds = new google.maps.LatLngBounds();
753            $('#quote-motorhome-location-modal-dialog .hidden-locations-msg').hide();
754            inputEl.find('option').each(function () {
755                if (!$(this).attr('data-position')) {
756                    return;
757                } else if ($(this).attr('data-invalid') === 'true') {
758                    $('#quote-motorhome-location-modal-dialog .hidden-locations-msg').show();
759                    return;
760                }
761                var lat = $(this).attr('data-position').split(',')[0],
762                    lng = $(this).attr('data-position').split(',')[1],
763                    latLng = new google.maps.LatLng(lat, lng),
764                    marker = new google.maps.Marker({
765                        position: latLng,
766                        map: TiogaTours.Quote.Motorhome.locationMap,
767                        title: $(this).val()
768                    });
769
770                addMarkerClickEvent(marker, inputEl);
771
772                TiogaTours.Quote.Motorhome.locationMarkers.push(marker);
773                bounds.extend(latLng);
774            });
775            setTimeout(function () {
776                TiogaTours.Quote.Motorhome.locationMap.fitBounds(bounds);
777            }, 1000);
778
779        });
780    },
781
782    watchForm: function (target) {
783        var $target = $(target);
784
785        $target.on('change', 'select, input', function (e) {
786            if ($(e.target).parents('.chosen-container').length > 0) {
787                // Ignore chosen input fields
788                return;
789            }
790            TiogaTours.Quote.Motorhome.updateSelects($target, e.target);
791        });
792
793        TiogaTours.Quote.Motorhome.updateSelects($target);
794    },
795
796    updateSelects: function (target, eventTarget) {
797
798        var $target = $(target),
799            els = $target.find('[name*="pickup][location"], [name*="dropoff][location"], [name*="model"], [name*="supplier"]'),
800            invalidOptionText = 'Andere opties?',
801            breakFn = false;
802
803        // Reset everything
804        $.each(els, function () {
805            var $el = $(this),
806                val;
807
808            if ($el.data('all-options') === undefined) {
809                var allOptions = [];
810                $.each($el.find('option'), function () {
811                    allOptions.push({ 'p': $(this).parent(), 'e': this });
812                });
813                $el.data('all-options', allOptions);
814            }
815
816            if ($el.find('option:selected')
817                && $el.find('option:selected').data('option-invalid') === true
818                && $(eventTarget)[0] === $el[0]
819            ) {
820                currentEl = this,
821                    Tioga.confirm('Let op!',
822                        '<p>Het formulier is slim en behulpzaam, zo wordt er voorkomen dan je een combinatie aanvraagt die onmogelijk is. Elke verhuurder heeft namelijk andere locaties en campermodellen.</p>'
823                        + '<p>Om de velden die je eerder had geselecteerd, te laten staan, klik je op <span style="color:#D9534F;font-weight:bold;">vasthouden</span>. Wil je alle opties zien, kies dan <span style="color:#5CB85C;font-weight:bold;">alle opties</span>.</p>'
824                        + '<p><strong>Kom je er niet uit?</strong> Vul dan het tekstveld "Overige wensen camperhuur in" en we denken met je mee.</p>',
825                        function () {
826                            $.each(els, function () {
827                                if (this !== currentEl) {
828                                    $(this).val('');
829                                }
830                            });
831                            TiogaTours.Quote.Motorhome.updateSelects($target);
832                        },
833                        function () {
834                            $(currentEl).val('');
835                            TiogaTours.Quote.Motorhome.updateSelects($target);
836                        }, {
837                            cancelButtonText: 'Vasthouden',
838                            okButtonText: 'Alle opties <small>(andere velden terugzetten)</small>'
839                        }
840                    );
841                breakFn = true;
842            }
843            val = $el.val();
844
845            $el.find('option').remove();
846            $.each($el.data('all-options'), function () {
847                if (this.p[0].tagName === 'SELECT') {
848                    this.p.prepend(this.e);
849                } else {
850                    this.p.append(this.e);
851                }
852            });
853            $el.val(val);
854
855            if ($el.val() !== val) {
856                $el.val('');
857            }
858
859            $el.find('option').attr('data-invalid', null);
860        });
861        if (breakFn) {
862            return;
863        }
864
865        $.each(els, function () {
866            var $t = $(this),
867                suppliersValid = null,
868                currentEl = this,
869                runEls = $.grep(els, function (value) {
870                    return value !== currentEl;
871                }),
872                invalidOptions = false;
873
874            $.each(runEls, function () {
875                var $t = $(this);
876                if ($t.val() !== '' && $t.find('option:selected').length > 0) {
877                    var $soption = $t.find('option:selected'),
878                        suppliers = $soption.attr('data-suppliers').split(',');
879
880                    if (suppliersValid === null) {
881                        suppliersValid = suppliers;
882                    } else {
883                        suppliersValid = $.grep(suppliersValid, function (val) {
884                            return $.inArray(val, suppliers) !== -1;
885                        });
886                    }
887                }
888            });
889
890            $.each($t.find('option'), function () {
891                if ($(this).attr('value') !== '' &&
892                    suppliersValid !== null && suppliersValid.length > 0 &&
893                    $(suppliersValid).filter($(this).attr('data-suppliers').split(',')).length === 0
894                ) {
895                    $(this).remove();
896                    invalidOptions = true;
897                }
898            });
899
900            if (invalidOptions === true) {
901                var $o = $('<option value="">
901' + invalidOptionText + '</option>');
902                $o.data('option-invalid', true);
903                $t.append($o);
904            }
905
906            $t.trigger('chosen:updated');
907        });
908    }
909};
910
911
912TiogaTours.Quote.CarRental = {
913    init: function (target) {
914        TiogaTours.Quote.CarRental.initMapPick(target);
915        TiogaTours.Quote.CarRental.initModelPick(target);
916    },
917
918    initModelPick: function (target) {
919        $(target).find('.show-model-picker').click(function (e) {
920            e.preventDefault();
921            $('#quote-car-rental-model-modal').modal();
922
923            if (top !== self) {
924                var $dialog = $('#quote-car-rental-model-modal .modal-dialog'),
925                    $modalContainer = $('<div class="modal" style="z-index:2000; display:block; clear:both; position:relative;"></div>');
926                $($(e.target).parents('.row')[0]).after($modalContainer);
927                $modalContainer.append($dialog);
928                $('.modal-body', $dialog).css({ 'overflow-y': 'auto', 'max-height': 700 });
929
930                $dialog.css('zIndex', 2000);
931                var hide = function (e) {
932                    if (e.target.tagName === 'button') {
933                        e.preventDefault();
934                    }
935                    $('#quote-car-rental-model-modal').append($dialog);
936                    $modalContainer.remove();
937                };
938
939                $dialog.find('button[data-dismiss="modal"]').on('click', function () {
940                    $('#quote-car-rental-model-modal').modal('hide');
941                });
942                $dialog.on('click', 'button', function (e) {
943                    e.preventDefault();
944                });
945                $('#quote-car-rental-model-modal').on('hide.bs.modal', hide);
946            }
947
948            var inputEl = $($(e.target).prevAll('select')),
949                elList = $('#quote-car-rental-model-modal-dialog ul');
950
951            elList.empty();
952
953            if (!$('#quote-car-rental-model-modal-dialog').data('event-initialized')) {
954                $('#quote-car-rental-model-modal-dialog').data('event-initialized', true);
955
956                $('#quote-car-rental-model-modal-dialog').on('click', '[data-value]', function (e) {
957                    e.preventDefault();
958                    $('#quote-car-rental-model-modal').modal('hide');
959                    inputEl.val($(this).attr('data-value'));
960                    inputEl.change();
961                    inputEl.trigger('chosen:updated');
962                });
963            }
964
965            inputEl.find('option').each(function () {
966                $option = $(this);
967
968                var html = '<li><h3>' + $option.text() + '</h3>',
969                    $option = $(this);
970
971                if ($option.attr('value') === '') {
972                    return;
973                }
974
975                if ($option.attr('data-image') !== '') {
976                    html += '<a href="javascript:void null;" data-value="' + $option.attr('value') + '">';
977                    html += '<img src="' + $option.attr('data-image') + '" alt="' + $option.text() + '">';
978                    html += '</a>';
979                }
980
981                var capacities = [
982                    [
983                        'adults',
984                        'adult',
985                        'volwasse'
986                    ], [
987                        'children',
988                        'child',
989                        'kind'
990                    ], [
991                        'large-bags',
992                        'large-bag',
993                        'grote koffer'
994                    ], [
995                        'medium-bags',
996                        'medium-bag',
997                        'kleine koffer'
998                    ], [
999                        'small-bags',
1000                        'small-bag',
1001                        'tas'
1002                    ]
1003                ];
1004
1005                html += '<p class="car-icons">';
1006
1007                $.each(capacities, function () {
1008                    for (var i = 0; i < parseInt($option.attr('data-capacity-' + this[0])); i++) {
1009                        html += '<i class="' + this[1] + '" title="' + this[2] + '"></i>';
1010                    }
1011                    if (i > 0) {
1012                        html += '<br>';
1013                    }
1014                });
1015
1016                html += '</p>'
1017                    + '<button class="btn btn-primary" data-value="' + $option.attr('value') + '">Kies dit model</button>'
1018                    + '</li>';
1019                elList.append($(html));
1020            });
1021        });
1022    },
1023
1024    initMapPick: function (target) {
1025        $(target).find('.show-map-picker').click(function (e) {
1026            e.preventDefault();
1027            $('#quote-car-rental-location-modal').modal();
1028
1029            if (top !== self) {
1030                var $dialog = $('#quote-car-rental-location-modal .modal-dialog'),
1031                    $modalContainer = $('<div class="modal" style="z-index:2000; display:block; clear:both; position:relative;"></div>');
1032                $($(e.target).parents('.row')[0]).after($modalContainer);
1033                $modalContainer.append($dialog);
1034                $('.modal-body', $dialog).css({ 'overflow-y': 'auto', 'max-height': 700 });
1035
1036                $dialog.css('zIndex', 2000);
1037                var hide = function (e) {
1038                    if (e.target.tagName === 'button') {
1039                        e.preventDefault();
1040                    }
1041                    $('#quote-car-rental-location-modal').append($dialog);
1042                    $modalContainer.remove();
1043                };
1044
1045                $dialog.find('button[data-dismiss="modal"]').on('click', function () {
1046                    $('#quote-car-rental-location-modal').modal('hide');
1047                });
1048                $dialog.on('click', 'button', function (e) {
1049                    e.preventDefault();
1050                });
1051                $('#quote-car-rental-location-modal').on('hide.bs.modal', hide);
1052            }
1053
1054            if (!$('#quote-car-rental-location-modal-dialog .map').data('map-initialized')) {
1055                $('#quote-car-rental-location-modal-dialog .map').data('map-initialized', true);
1056
1057                TiogaTours.Quote.CarRental.locationMap = new google.maps.Map($('#quote-car-rental-location-modal-dialog .map')[0], {
1058                    center: { lat: 0, lng: 0 },
1059                    zoom: 8
1060                });
1061
1062                // Resize map after modal is shown
1063                $('#quote-car-rental-location-modal').on('shown.bs.modal', function () {
1064                    google.maps.event.trigger(TiogaTours.Quote.CarRental.locationMap, 'resize');
1065                });
1066            }
1067
1068            var inputEl = $($(e.target).prevAll('select'));
1069
1070            if (TiogaTours.Quote.CarRental.locationMarkers) {
1071                $.each(TiogaTours.Quote.CarRental.locationMarkers, function () {
1072                    this.setMap(null);
1073                });
1074            }
1075            TiogaTours.Quote.CarRental.locationMarkers = [];
1076
1077            var addMarkerClickEvent = function (marker, inputEl) {
1078                google.maps.event.addListener(marker, 'click', function () {
1079                    var contentEl = $('<div><strong>' + marker.getTitle() + '</strong><br><br>'
1080                        + '<a class="btn btn-primary">Kies deze locatie</a></div>');
1081                    var infowin = new google.maps.InfoWindow({
1082                        content: contentEl[0]
1083                    });
1084                    infowin.open(marker.getMap(), marker);
1085
1086                    contentEl.on('click', '.btn', function () {
1087                        inputEl.val(marker.getTitle());
1088                        $('#quote-car-rental-location-modal').modal('hide');
1089                        inputEl.change();
1090                        inputEl.trigger('chosen:updated');
1091                    })
1092                });
1093            };
1094
1095            var bounds = new google.maps.LatLngBounds();
1096
1097            inputEl.find('option').each(function () {
1098                var $option = $(this);
1099                if (!$option.attr('data-position')) {
1100                    return;
1101                }
1102
1103                var lat = $option.attr('data-position').split(',')[0],
1104                    lng = $option.attr('data-position').split(',')[1],
1105                    latLng = new google.maps.LatLng(lat, lng),
1106                    marker = new google.maps.Marker({
1107                        position: latLng,
1108                        map: TiogaTours.Quote.CarRental.locationMap,
1109                        title: $option.val()
1110                    });
1111
1112                addMarkerClickEvent(marker, inputEl);
1113
1114                TiogaTours.Quote.CarRental.locationMarkers.push(marker);
1115                bounds.extend(latLng);
1116            });
1117            setTimeout(function () {
1118                TiogaTours.Quote.CarRental.locationMap.fitBounds(bounds);
1119            }, 1000);
1120
1121        });
1122    }
1123};
1124
1125
1126TiogaTours.Quote.initSteps = function (e) {
1127    $('.quote-step').not(':first').css('display', 'none');
1128    var currentStep = 0;
1129    $(window).on('hashchange', function () {
1130        if (window.location.hash === '') {
1131            return;
1132        }
1133
1134        var nextStep = parseInt(window.location.hash.substr(1)),
1135            step = nextStep - currentStep,
1136            $form = $($('.quote-step').parents('form')[0]);
1137
1138        if (nextStep !== currentStep && (step < 0 || $form.validate() && $form.valid() && TiogaTours.Quote.validateHiddenRequiredFields($form))) {
1139
1140            $($('.quote-step')[nextStep]).slideDown();
1141            $('.quote-step .btn.active').removeClass('active'); // Disable active state of buttons (see script.js)
1142            $($('.quote-step')[currentStep]).slideUp();
1143            $(window).scrollTop($('h1').offset().top);
1144            currentStep = nextStep;
1145            if (TiogaTours.Quote.iFrame) {
1146                TiogaTours.Quote.iFrame.trigger();
1147                setTimeout(function () {
1148                    TiogaTours.Quote.iFrame.trigger();
1149                }, 400);
1150            }
1151        } else {
1152            window.location.hash = '#' + currentStep;
1153            if ($form.find('.has-error:visible').length > 0) {
1154                $(window).scrollTop($form.find('.has-error:visible').first().offset().top);
1155            }
1156
1157            if (TiogaTours.Quote.iFrame) {
1158                TiogaTours.Quote.iFrame.trigger();
1159                setTimeout(function () {
1160                    TiogaTours.Quote.iFrame.trigger();
1161                }, 400);
1162            }
1163        }
1164    });
1165};
1166
1167TiogaTours.Quote.validateHiddenRequiredFields = function ($form) {
1168    let valid = true;
1169    $form.find('.required-hidden[required]:enabled').each(function () {
1170        let $i = $(this);
1171        if ($i.val() !== '') {
1172            return;
1173        } else {
1174            valid = false;
1175            $($i.parents('.form-group')).addClass('has-error');
1176            $i.on('change.check-sf', function (evt) {
1177                var $t = $(evt.target);
1178                if ($t.val() !== '') {
1179                    $($t.parents('.form-group')[0]).removeClass('has-error');
1180                    $t.off('change.check-sf');
1181                }
1182            });
1183        }
1184    });
1185
1186    return valid;
1187}
1188
1189/*
1190$t.find('[required]:enabled:visible, .required-hidden[required]:enabled').each(function () {
1191let $i = $(this);
1192if ($i.val() !== '') {
1193    return;
1194} else {
1195    valid = false;
1196    $($i.parents('.form-group')).addClass('has-error');
1197    $i.on('change.check-sf', function (evt) {
1198        var $t = $(evt.target);
1199        if ($t.val() !== '') {
1200            $($t.parents('.form-group')[0]).removeClass('has-error');
1201            $t.off('change.check-sf');
1202        }
1203    });
1204}
1205});
1206
1207 */
1208TiogaTours.Quote.PostalCodeCheck = function (target) {
1209    var msgBox = $('#postal-code-check-message'),
1210        url = msgBox.attr('data-postal-code-check-url');
1211
1212    msgBox.hide();
1213
1214    new Geographic.PostalCodeHelper(
1215        '[name*="personalia[country]"]',
1216        '[name*="personalia[postalcode]"]',
1217        '[name*="personalia[housenr]"]',
1218        url,
1219        function (status, data) {
1220            var streetInput = $('[name*="personalia[street]"]', target),
1221                cityInput = $('[name*="personalia[city]"]', target);
1222
1223            this.defaultHandler(streetInput, cityInput, msgBox, status, data);
1224        }
1225    );
1226};
1227
1228
1229TiogaTours.Quote.MotorcycleRental = {
1230
1231    init: function (target) {
1232        TiogaTours.Quote.MotorcycleRental.initMapPick(target);
1233    },
1234
1235    initMapPick: function (target) {
1236        $(target).find('.show-map-picker').click(function (e) {
1237            e.preventDefault();
1238            $('#quote-motorcycle-rental-location-modal').modal();
1239
1240            if (top !== self) {
1241                var $dialog = $('#quote-motorcycle-rental-location-modal .modal-dialog'),
1242                    $modalContainer = $('<div class="modal" style="z-index:2000; display:block; clear:both; position:relative;"></div>');
1243                $($(e.target).parents('.row')[0]).after($modalContainer);
1244                $modalContainer.append($dialog);
1245                $('.modal-body', $dialog).css({ 'overflow-y': 'auto', 'max-height': 700 });
1246
1247                $dialog.css('zIndex', 2000);
1248                var hide = function (e) {
1249                    if (e.target.tagName === 'button') {
1250                        e.preventDefault();
1251                    }
1252                    $('#quote-motorcycle-rental-location-modal').append($dialog);
1253                    $modalContainer.remove();
1254                };
1255
1256                $dialog.find('button[data-dismiss="modal"]').on('click', function () {
1257                    $('#quote-motorcycle-rental-location-modal').modal('hide');
1258                });
1259                $dialog.on('click', 'button', function (e) {
1260                    e.preventDefault();
1261                });
1262                $('#quote-motorcycle-rental-location-modal').on('hide.bs.modal', hide);
1263            }
1264
1265            if (!$('#quote-motorcycle-rental-location-modal-dialog .map').data('map-initialized')) {
1266                $('#quote-motorcycle-rental-location-modal-dialog .map').data('map-initialized', true);
1267
1268                TiogaTours.Quote.MotorcycleRental.locationMap = new google.maps.Map($('#quote-motorcycle-rental-location-modal-dialog .map')[0], {
1269                    center: { lat: 0, lng: 0 },
1270                    zoom: 8
1271                });
1272
1273                // Resize map after modal is shown
1274                $('#quote-motorcycle-rental-location-modal').on('shown.bs.modal', function () {
1275                    google.maps.event.trigger(TiogaTours.Quote.MotorcycleRental.locationMap, 'resize');
1276                });
1277            }
1278
1279            var inputEl = $($(e.target).prevAll('select'));
1280
1281            if (TiogaTours.Quote.MotorcycleRental.locationMarkers) {
1282                $.each(TiogaTours.Quote.MotorcycleRental.locationMarkers, function () {
1283                    this.setMap(null);
1284                });
1285            }
1286            TiogaTours.Quote.MotorcycleRental.locationMarkers = [];
1287
1288            var addMarkerClickEvent = function (marker, inputEl) {
1289                google.maps.event.addListener(marker, 'click', function () {
1290                    var contentEl = $('<div><strong>' + marker.getTitle() + '</strong><br><br>'
1291                        + '<a class="btn btn-primary">Kies deze locatie</a></div>');
1292                    var infowin = new google.maps.InfoWindow({
1293                        content: contentEl[0]
1294                    });
1295                    infowin.open(marker.getMap(), marker);
1296
1297                    contentEl.on('click', '.btn', function () {
1298                        inputEl.val(marker.getTitle());
1299                        $('#quote-motorcycle-rental-location-modal').modal('hide');
1300                        inputEl.change();
1301                        inputEl.trigger('chosen:updated');
1302                    })
1303                });
1304            };
1305
1306            var bounds = new google.maps.LatLngBounds();
1307
1308            inputEl.find('option').each(function () {
1309                var $option = $(this);
1310                if (!$option.attr('data-position')) {
1311                    return;
1312                }
1313
1314                var lat = $option.attr('data-position').split(',')[0],
1315                    lng = $option.attr('data-position').split(',')[1],
1316                    latLng = new google.maps.LatLng(lat, lng),
1317                    marker = new google.maps.Marker({
1318                        position: latLng,
1319                        map: TiogaTours.Quote.MotorcycleRental.locationMap,
1320                        title: $option.val()
1321                    });
1322
1323                addMarkerClickEvent(marker, inputEl);
1324
1325                TiogaTours.Quote.MotorcycleRental.locationMarkers.push(marker);
1326                bounds.extend(latLng);
1327            });
1328            setTimeout(function () {
1329                TiogaTours.Quote.MotorcycleRental.locationMap.fitBounds(bounds);
1330            }, 1000);
1331
1332        });
1333    }
1334};

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.