PageSourceSearch

https://flohkids.de/assets/cache/floh_services_booking_mod.js?_dt=1790305770

js flohkids.de collected 2026-09-25 03:09:46 UTC 32,200 bytes, 925 lines download raw bytes

1/**
2 * Copyright CRP Solutions GmbH
3 * You are not allowed to copy or reproduce this code.
4 * However, you are allowed to get inspired.
5 * 
6 * EK
7 */
8
9let order = {
10    store_id: 1
11};
12
13// count obj length
14Object.keys = function (obj) {
15    let keys = [], key;
16    for (key in obj) {
17        if (obj.hasOwnProperty(key))
18            keys.push(key);
19    }
20    return keys;
21};
22
23jQuery.datetimepicker.setLocale('de');
24
25// prevent mouse scroll data change
26
27$('.datetime_picker').off('scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove',
28function (ev) {
29    ev.preventDefault();
30    ev.stopPropagation();
31    return false;
32});
33
34$('td.xdsoft_date.xdsoft_date').off('scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove', 
35function (ev) {
36    ev.preventDefault();
37    ev.stopPropagation();
38    return false;
39});
40
41// pre select booking duration
42window.addEventListener('load', function(event) {
43    
44    let preset_location = null;
45    
46    let match_location = window.location.hash.match(/standort=([^,\s]+)/);
47    
48    // if location is not set, set to default for server
49    if (match_location && match_location[1])  {
50        preset_location = match_location[1];
51    }
52    
53    select_item('li[data-location="' + preset_location + '"]');
54    
55});
56
57let cancelPanning = false;
58
59/*
60 * Select start date
61 * @param {type} dp
62 * @param {type} date
63 * @returns {undefined}
64 * 
65 */
66function select_start_date(dp, date) {
67
68    let d = date.val().split('.');
69    
70    removeLoader();
71    
72    draw.clear();
73    
74    renderLoader($('#position-block'));
75
76    // select order start date
77    order.start = d[2] + '-' + d[1] + '-' + d[0];
78
79    ajaxcall(
80            {
81                booking_start: order.start, 
82                booking_duration: order.duration
83            },
84            '/booking/calculate_booking',
85            $(this),
86        function ($this, response) {
87            if (response && response.order) {
88                console.log(response.order);
89                order = response.order;
90                
91                // special discount detected!
92                if (response.message) {
93                    
94                    let config = {
95                        title: response.message.title,
96                        html: response.message.message,
97                        showCloseButton: true,
98                        confirmButtonText: 'Super!'
99                    };
100                    if (response.message.image) {
101                        config.imageUrl = response.message.image;
102                    }
103                    
104                    swal(config).then(() => {
105                        set_start_date(order.start, order.end);
106                    });    
107                } else {
108                    set_start_date(order.start, order.end);
109                }
110            } else if (response.error) {
111                // we send detailed messages here but do not display
112                BOOKING_FAIL_WAIT_TOO_LONG();
113            }
114        },
115        function ($this, err) {
116            BOOKING_FAIL_WAIT_TOO_LONG();
117        }
118    );
119}
120
121/**
122 * @returns {undefined}
123 */
124function set_start_date() {
125
126    dataLayer.push({event: 'checkout_select_day'});
127    
128    // remove order and payment block
129    $('#order-block').fadeOut();
130    $('#payment-block').fadeOut();
131    
132    cancelPanning = false;
133    if (cancelPanning)
134        return;
135
136    // display pre calculated dates
137    $('.order-start').text(formatDate(order.start));
138    
139    // correct time depending on day of week
140    let d = new Date(order.end);   
141    let end_date = '';
142    if (d.getDay() === 6) {
143        end_date = formatDate(order.end) + ' bis 15 Uhr<br>';
144    } else {
145        end_date = formatDate(order.end) + ' bis 17 Uhr<br>';
146    }
147    $('.order-end').html(end_date);
148
149    // correct time depending on day of week
150    d = new Date(order.prepare);    
151    let prepare_date = '';
152    if (d.getDay() === 6) {
153        prepare_date = formatDate(order.prepare) + ' zwischen 15-16 Uhr<br>';
154    } else {
155        prepare_date = formatDate(order.prepare) + ' zwischen 17-18 Uhr<br>';
156    }
157    $('.order-start-day-before').html(
158          prepare_date + '<i>oder ' + formatDate(order.start) + ' zwischen 9-10 Uhr</i>'
159    );    
160    
161    // some action - show change
162    if (order.action_booking.duration) {
163        $('.order-duration').html('<s>' + order.action_booking.duration + ' Tage</s> ' + order.duration + ' Tage 🎉');
164    } else {
165        $('.order-duration').text(order.duration + ' Tage');
166    }
167
168    $('.rentperiod-detail').show();
169
170    let show_id = '#position-block';
171    let message = 'Wo soll dein Stand stehen?';
172
173    $('.flag-booking-start').removeClass('badge-light').addClass('badge-success');
174
175    // unset shelf badge because now none is selected
176    $('.flag-booking-position').removeClass('badge-success').addClass('badge-light');
177
178    // enable refuse 14 days booking withdrawal
179    if (order.days_to_start && order.days_to_start <= 14) {
180        $('.enable-withdrawal').show();
181    } else {
182        $('.enable-withdrawal').hide();
183    }
184    
185    console.log(order.days_to_start);
186
187    message && toast(message);
188
189    $(show_id).fadeIn();
190    scrollToTarget(show_id);
191
192    load_shelfs(order.store_id, order.start, order.duration);
193}
194
195function set_location(location) {
196    
197    dataLayer.push({event: 'checkout_location'});
198
199    // maybe duration was already selected
200    let duration = window.location.hash.match(/dauer=([^,\s]+)/);
201    
202    if (duration && duration[1]) {
203        duration = duration[1];
204    }
205
206    let location_data = locations[location];
207    
208    if (location && location_data) {
209        let retval = changeLocation(
210            location_data.domain + '/buchen#' + (duration ? 'dauer=' + duration : '') +
211            (location_data ? ',standort=' + location_data.key : ''),
212            location
213        );
214        
215        // we change location. stop everything else.
216        if (retval === true) {
217            return false;
218        }
219        
220        location_description = location_data.street + ', ' + location_data.zip + ' ' + location_data.city;
221        renderLoader($('#location-block'));        
222        
223        order.location = location;
224    }
225
226    removeLoader();
227    
228    console.log('Set location ' + location_description);
229    $('.order-location').text(location_description);
230        
231    // reset shelf selected before
232    ekselect.shelf = null;
233    order.shelf_type = null;
234    ekselect.duration = null;
235    order.duration = null;
236    
237    if (duration)  {
238        // delay selection
239        setTimeout(() => {select_item('li[data-rent="' + duration + '"]');}, 500);
240    } 
241}
242
243/**
244 * Set Rent duration
245 * @param {type} duration
246 * @returns {undefined}
247 */
248function set_rent(duration) {
249
250    dataLayer.push({event: 'add_to_cart'});
251    dataLayer.push({event: 'checkout_duration'});
252    
253    order.duration = duration;
254
255    removeLoader();
256    
257    $('.order-duration').text(duration + ' Tage');
258    
259    // reset shelf selected before
260    order.shelf_type = null;
261    reset_item('shelf');
262}
263
264/**
265 * Set the type of shelf needed. Collects information about the availability.
266 * @param {type} shelf_type
267 * @returns {undefined}
268 */
269function set_shelf_type(shelf_type) {
270
271    dataLayer.push({event: 'checkout_shelf_type'});
272
273    renderLoader($('#date-block'));
274    order.shelf_type = shelf_type;
275
276    // hide preselected day
277    $('.rentperiod-detail').hide();
278    $('#position-block').hide();
279    // reset shelf display
280    draw.clear();
281    // select delivery date
282    if ($('.datetime_picker')[0]) {
283        $('.datetime_picker').datetimepicker('destroy');
284    }    
285
286    ajaxcall({order: order}, '/booking/calculate_shelf_availability', $(this),
287            function ($this, response) {
288                if (response && response !== false) {
289                    console.log(response);
290                    
291                    removeLoader();
292
293                    // cycle through the days until free booking available
294                    let cycle_day = new Date();
295                    cycle_day.setDate(cycle_day.getDate() + 1);
296                    cycle_day.setHours(01, 00, 00);
297                    
298                    let secureCounter = 0;
299                    while(
300                        secureCounter < 150 && 
301                        response.content.days_not_available.includes(formatDateMYSQL(cycle_day).toString())
302                    ){
303                        cycle_day.setDate(cycle_day.getDate() + 1);
304                        secureCounter++;
305                    }
306                    
307                    // most recent booking day found
308                    let d = cycle_day;
309                    
310                    let currentDay = (d.getDate());
311                    let currentMonth = (d.getMonth() + 1);
312                    let currentYear = (d.getFullYear());
313                    
314                    d.setDate(d.getDate() + 150);
315                    let maxDate = d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate(); // getMonth GFYS! :D
316                    
317                    $('.datetime_picker').datetimepicker({
318                        inline: true,
319                        startDate: currentYear + '/' + currentMonth + '/' + currentDay,
320                        minDate: '+1970/01/02', // new: start just the next day
321                                                // TODO: set day depending from current time (same day possible, if
322                                                // booking before 2 pm)?
323                        maxDate: maxDate, // selection restricted // yeah, try to disable this in console to cheat :P
324                        dayOfWeekStart: 1,
325                        disabledWeekDays: [0],
326                        timepicker: false,
327                        timepickerScrollbar: false,
328                        disabledDates: response.content.days_not_available, // disable booked days
329                        formatDate:'Y-m-d',
330                        scrollInput: false,
331                        scrollTime: false,
332                        scrollMonth: false,
333                        format: 'd.m.Y',
334                        onChangeDateTime: select_start_date,
335                        onGenerate:function( ct ){
336                            $('.datetime_picker').
337                                on('scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove',
338                            function (ev) {
339                                ev.preventDefault();
340                                ev.stopPropagation();
341                                return false;
342                            });
343
344                            $('td.xdsoft_date.xdsoft_date').
345                                on('scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove',
346                            function (ev) {
347                                ev.preventDefault();
348                                ev.stopPropagation();
349                                return false;
350                            });
351                            
352                            ajaxcall(
353                                    {
354                                        month: ct.getMonth() + 1, 
355                                        year: ct.getFullYear(), 
356                                        duration: order.duration
357                                    }, 
358                                    '/booking/actions/getActionsDates', $(this),
359                                function($this, actions) {
360                                    if (!actions) {
361                                        return;
362                                    }
363                                    actions.forEach(function(action) {
364                                        action.days.forEach(function(d){
365                                            let actionDay = new Date(d);
366                                            $('td[data-date="' + actionDay.getDate() + '"]' +
367                                                    '[data-month="' + (actionDay.getMonth()) + '"]' +
368                                                    '[data-year="' + actionDay.getFullYear() + '"]')
369                                                    .attr('title', action.calendar_title);
370                                            $('td[data-date="' + actionDay.getDate() + '"]' +
371                                                    '[data-month="' + (actionDay.getMonth()) + '"]' +
372                                                    '[data-year="' + actionDay.getFullYear() + '"]')
373                                                    .append('<div style="position:relative">' +
374                                                    '<div style="position: absolute;top: -34px;font-size: 30px;">' +
375                                                    action.calendar_icon + '️</div></div>');
376                                        });
377                                    });
378                                },
379                                function() {
380                                    Swal.fire('Ein Fehler ist aufgetreten', 'Bitte die Buchung neu starten.', 'error');
381                                }
382                            )                           
383                        }
384                    });
385                    
386                  
387                } else if (response === false) {
388                    Swal.fire(
389                        'Keine Regale mehr frei für den laufenden Monat.', 
390                        'Bitte den nächsten Monat probieren.',
391                        'error'
392                    );
393                } else if (response.error) {
394                    // we send detailed messages here but do not display
395                    BOOKING_FAIL_WAIT_TOO_LONG();
396                }
397            },
398            function ($this, err) {
399                BOOKING_FAIL_WAIT_TOO_LONG();
400            }
401    );
402}
403
404/**
405 * Set Shelf Location
406 * @param {event} e
407 * @returns {undefined}
408 */
409function select_shelf(e) {
410
411    dataLayer.push({event: 'checkout_shelf_location'});
412
413    dataLayer.push({event: 'begin_checkout'});
414
415    let shelf_obj = e.currentTarget.childNodes[0];
416    console.log(shelf_obj);
417
418    // init shelf
419    if (!ekselect['shelf_id']) {
420        ekselect['shelf_id'] = null;
421    }
422
423    // check if shelf not selected
424    if (!SVG(shelf_obj).data('selected')) {
425        // highlight selected shelf
426        SVG(shelf_obj).data('selected', true);
427        SVG(shelf_obj).fill('#3af');
428
429        if (ekselect['shelf_id']) {
430            // remove highlight on old selected shelf
431            SVG(ekselect['shelf_id']).data('selected', false);
432            SVG(ekselect['shelf_id']).fill('lightgreen');
433        }
434
435        // save selected shelf
436        ekselect['shelf_id'] = shelf_obj;
437    } else {
438
439        // remove highlight on unselected shelf
440        SVG(shelf_obj).data('selected', false);
441        SVG(shelf_obj).fill('lightgreen');
442
443        ekselect['shelf_id'] = null;
444    }
445
446    // unset shelf badge if no shelf remains selected
447    if (ekselect['shelf_id'] === null) {
448        $('.flag-booking-position').removeClass('badge-success').addClass('badge-light');
449
450        // remove order and payment block
451        $('#order-block').fadeOut();
452        $('#payment-block').fadeOut();
453    } else {
454        // set badge on success
455        $('.flag-booking-position').removeClass('badge-light').addClass('badge-success');
456
457        // show order block
458        $('#order-block').fadeIn();
459
460        scrollToTarget('#order-block');
461    }
462
463    if (ekselect['shelf_id']) {
464        order.shelf_id = SVG(ekselect['shelf_id']).data('shelf_id');
465        $('.order-shelf').text(SVG(ekselect['shelf_id']).data('shelf_label'));
466
467        let message = 'Du hast dir Stand ' + SVG(ekselect['shelf_id']).data('shelf_label') + ' ausgesucht.';
468        message && toast(message);
469
470    } else {
471        order.shelf_id = null;
472    }
473
474    ajaxcall(null, '/booking/calculate_booking', $(this),
475            function ($this, response) {
476                if (response && response.order) {
477                    $('.order-shelf-type').text(response.order.shelf_type_description);
478                    
479                    // some action - show price change
480                    if (response.order.action_booking.rent_price) {
481                        $('.order-rent-price').html(
482                                '<s>' + 
483                                response.order.action_booking.rent_price.toLocaleStr
483ing(
484                                    'de-DE', 
485                                    { 
486                                        style: 'currency', 
487                                        currency: 'EUR'
488                                    }
489                                ) + 
490                                '</s> ' +
491                                response.order.booking_price.toLocaleString(
492                                    'de-DE', 
493                                    {
494                                        style: 'currency', 
495                                        currency: 'EUR' 
496                                    }
497                                ) +
498                                ' 🎉');
499                    } else {
500                        $('.order-rent-price').text(
501                                response.order.booking_price.toLocaleString(
502                                    'de-DE', 
503                                    { 
504                                        style: 'currency', 
505                                        currency: 'EUR' 
506                                    }
507                                ) +
508                                '');
509                    }
510                    
511                    // affiliate coupon
512                    let coupon = getCookie('affiliate_coupon');
513                    if (coupon && coupon !== 'undefined') {
514                        $('#coupon_code').val(coupon);
515
516                        validate_coupon(false);
517                    }                    
518                } else if (response.error) {
519                    BOOKING_FAIL_WAIT_TOO_LONG();
520                }
521            },
522            function ($this, err) {
523                BOOKING_FAIL_WAIT_TOO_LONG();
524            }
525    );
526}
527
528/**
529 * Loads and Renders Shelfs for Location and Rent Beginn + Duration
530 * @param {type} store_id
531 * @returns {undefined}
532 */
533function load_shelfs(store_id = null) {
534    
535    ajaxcall({store_id: store_id}, '/booking/get_location_shelfs', $(this),
536            function ($this, response) {
537                if (response) {
538
539                    shelfs = response.content.shelfs;
540                    shelf_groups = response.content.groups;
541                    shelf_type = response.content.types;
542                    shelf_booked = response.content.booked;
543                    
544                    if (!shelf_map_set) {
545                        for(let group in shelf_groups) {
546                            
547                            let group_shelfs = [];
548                            
549                            // collect shelfs in group
550                            for(let shelf in shelfs) {
551                                if (shelfs[shelf].group_id === shelf_groups[group].id) {
552                                    group_shelfs.push(shelfs[shelf]);
553                                }
554                            }
555                            
556                            shelf_map.push({
557                                type: 'group',
558                                x: shelf_groups[group].x,
559                                y: shelf_groups[group].y,
560                                rotation: shelf_groups[group].rotation,
561                                shelfs: group_shelfs
562                            });                            
563                        }
564                        // set only once
565                        shelf_map_set = true;                        
566                    }
567                    
568                    render_shelfs();
569                    
570                    removeLoader();
571
572                    // render movement for mobile
573                    if (window.innerWidth <= 767) {
574                        setTimeout(() => {
575                            $('#shelfmap svg').addClass('shelfs-left-right');
576                        }, 1000);
577
578                        setTimeout(() => {
579                            $('#shelfmap svg').removeClass('shelfs-left-right');
580                        }, 3000);                    
581                    }
582                    
583                } else if (response.error) {
584                    BOOKING_FAIL_WAIT_TOO_LONG();
585                }
586            },
587            function ($this, err) {
588                BOOKING_FAIL_WAIT_TOO_LONG();
589            }
590    );
591}
592
593let shelfs = [];
594let shelf_type = {};
595let shelf_map_set = false;
596let shelf_groups = [];
597let shelf_map = [];
598let shelf_booked = [];
599let draw = SVG().addTo('#shelfmap').size('900', '900');
600
601function get_shelf_type(id) {
602    for(let type in shelf_type) {
603        if (shelf_type[type].id === parseInt(id)) {
604            //console.log(['MATCH SHELF TYPE', type, shelf_type[type]]);
605            return shelf_type[type];
606        }
607    }
608}
609
610function render_shelfs() {
611    draw.clear();
612    draw.addClass('canvas');
613    draw.attr('viewBox', '0 0 900 900');
614
615    for (let i in shelf_map) {
616        // clone data otherwise calculated dimensions will persist in object and get added
617        let group = JSON.parse(JSON.stringify(shelf_map[i]));
618
619        if (group.type === 'group') {
620            render_group(draw, group);
621        }
622    }
623}
624
625function render_group(draw = null, group = []) {
626
627    group.w = 0;
628    group.h = 0;
629
630    // calculate width/height for group
631    for (let i in group.shelfs) {
632        let shelf = group.shelfs[i];
633        let type = get_shelf_type(shelf.type_id);
634
635        let shelf_x = group.x + ((shelf.x - 1) * type.width);
636        let shelf_y = group.y + ((shelf.y - 1) * type.depth);
637
638        if ((shelf_x + type.width) > group.w) {
639            group.w = shelf_x + type.width;
640        }
641
642        if ((shelf_y + type.depth) > group.h) {
643            group.h = shelf_y + type.depth;
644        }
645    }
646
647    // render shelfs
648    for (let i in group.shelfs) {
649
650        let shelf = group.shelfs[i];
651        
652        // do not render removed shelves
653        if (shelf.type_id === 99) {
654            continue;
655        }
656        
657        // because: label can be a number, and as such, json_encode stores this value as number.
658        // but SVG renderer does some text methods with this value, which would break. so we transform it here to string
659        shelf.label += '';
660        
661        let type = get_shelf_type(shelf.type_id);
662        // mark as booked if:
663        // * in list of booked
664        // * not the type of shelf needed
665        shelf.booked = (shelf_booked[shelf.shelf_id] || shelf.type_id !== order.shelf_type) ? true : false;
666
667        shelf.x = group.x + ((shelf.x - 1) * 30);
668        shelf.y = group.y + ((shelf.y - 1) * 30);
669
670        //console.log(shelf);
671
672        let g = draw.group();
673
674        let s = draw.rect(type.width, type.depth).move(shelf.x, shelf.y)
675                .fill((type.inactive === 'false' && shelf.booked) ? '#ff8080' : type.fill);
676        s.addClass('shelf');
677        s.attr('id', 'shelf_' + shelf.shelf_id);
678        s.data('shelf_id', shelf.shelf_id);
679        s.data('shelf_label', shelf.label);
680        g.add(s);
681
682        let text = draw.text(shelf.label).move(shelf.x + (type.width / 2), shelf.y + (type.depth / 2) - 7)
683                .fill(type.color ? type.color : ((shelf.booked) ? '#fff' : '#000'));
684        text.font({family: 'Helvetica', size: 14, anchor: 'middle'});
685        text.addClass('shelf-text');
686
687        g.add(text);
688
689        g.add(draw.line(0, 0, type.width, 0)
690                .move(shelf.x, shelf.y)
691                .stroke({color: type.border ? type.border : '#000', width: 1}));
692        g.add(draw.line(0, 0, type.width, 0)
693                .move(shelf.x, shelf.y + type.depth)
694                .stroke({color: type.border ? type.border : '#000', width: 1}));
695        g.add(draw.line(0, 0, 0, type.depth)
696                .move(shelf.x, shelf.y)
697                .stroke({color: type.border ? type.border : '#000', width: 1}));
698        g.add(draw.line(0, 0, 0, type.depth)
699                .move(shelf.x + type.width, shelf.y)
700                .stroke({color: type.border ? type.border : '#000', width: 1}));
701
702        g.rotate(shelf.rotation, shelf.x, shelf.y); // rotate element
703        g.rotate(group.rotation, group.x, group.y); // rotate group
704
705        if (shelf.booked || (type.inactive && type.inactive === 'true')) {
706
707        } else {
708            s.addClass('shelf-active');
709            text.addClass('shelf-text-active');
710
711            g.on('mouseover', function (e) {
712                if (!SVG(e.currentTarget.childNodes[0]).data('selected')) {
713                    SVG(e.currentTarget.childNodes[0]).fill('#3af');
714                }
715                //SVG(e.currentTarget.childNodes[0]).transform({scale: 3});
716            });
717
718            g.on('mouseout', function (e) {
719                //console.log(this);
720                if (!SVG(e.currentTarget.childNodes[0]).data('selected')) {
721                    SVG(e.currentTarget.childNodes[0]).fill(type.fill);
722                }
723            });
724
725            g.on('click', select_shelf);
726        }
727    }
728}
729
730$('.action_check_coupon').off('click').on('click', function () {
731    validate_coupon();
732});
733
734function validate_coupon(verbose = true) {
735    let coupon = $('#coupon_code').val();
736    
737    if (coupon === '') {
738        return;
739    }
740    
741    if (verbose)
742    swal({
743        title: "Gutschein wird eingelöst...",
744        showConfirmButton: false,
745        type: 'info'
746    });
747    
748    ajaxcall({coupon: coupon}, '/booking/validate_coupon', $(this),
749        function ($this, response) {
750            if (response && response.error === false) {
751                
752                let config = {
753                    title: response.message.title || "Gutschein eingelöst!",
754                    html: response.message.message,
755                    showCloseButton: true,
756                    confirmButtonText: 'Ok',
757                    type: response.message.type || 'error'
758                };
759
760                if (verbose)
761                swal(config).then(() => {
762                    if (response.message.jsaction) {
763                        eval(response.message.jsaction);
764                    }
765                });                 
766
767                if (response && response.order) {
768                    
769                    $('.order-shelf-type').text(response.order.shelf_type_description);
770    
771                    // some action - show price change
772                    if (response.order.action_booking && response.order.action_booking.rent_price) {
773                        $('.order-rent-price').html(
774                                '<s>' + 
775                                response.order.action_booking.rent_price.toLocaleString(
776                                    'de-DE', 
777                                        { 
778                                            style: 'currency',
779                                            currency: 'EUR'
780                                        }
781                                ) +
782                                '</s> ' +
783                                response.order.booking_price.toLocaleString(
784                                    'de-DE', 
785                                        {
786                                            style: 'currency',
787                                            currency: 'EUR'
788                                        }
789                                ) +
790                                ' 🎉');
791                    } else {
792                        $('.order-rent-price').text(
793                                response.order.booking_price.toLocaleString(
794                                    'de-DE', 
795                                        { 
796                                            style: 'currency',
797                                            currency: 'EUR'
798                                        }
799                                ) +
800                                '');
801                    }
802                    
803                    if (response.coupon && response.coupon.bypass_payment) {
804                        $('.order-rent-price').text('Über Gutschein bezahlt.');
805                    }
806                } else if (response.error) {
807                    if (verbose) BOOKING_FAIL_WAIT_TOO_LONG();
808                }
809         
810            } else if(response.message) {
811                let config = {
812                    title: response.message.title,
813                    html: response.message.message,
814                    showCloseButton: true,
815                    confirmButtonText: 'Ok',
816                    type: 'error'
817                };
818
819                if (verbose)
820                swal(config).then(() => {
821                    if (response.message.jsaction) {
822                        eval(response.message.jsaction);
823                    }
824                });                       
825            } else if(response.error) {
826                // formular wrong
827                console.log({'FORM ERROR':response.error});
828                $('input').each(function () {
829                    let id = $(this).attr('id');                        
830                    if (response.error[id]) {
831                        $('#' + id).addClass('is-invalid');
832                        $('.' + id + '-message').html(response.error[id]);
833                    } else {
834                        $('#' + id).removeClass('is-invalid');
835                        $('.' + id + '-message').html();
836                    }
837                });
838
839                if (verbose)
840                swal({
841                    title: "Der Gutschein ist unbekannt oder kann nicht verwendet werden.",
842                    showConfirmButton: true,
843                    type: 'error'
844                });
845            }
846        },
847        function ($this, err) {
848            if (verbose) BOOKING_FAIL_WAIT_TOO_LONG();
849        }    
850    );
851};
852
853// we use this function to initiate payment inline
854activate_pay_button();
855
856function insertPayPalPayment() {
857    let jsinsert = document.getElementById('jsinsert');
858    jsinsert.children[0] && jsinsert.removeChild(jsinsert.children[0]);
859    
860    let button = document.getElementById('paypal-button-container');
861    if (button) {
862        button.innerHTML = null;
863        button.innerHTML = '';
864    }
865    
866    ajaxcall({}, '/booking/paypalpayment/render_paypal', $(this),
867            function ($this, response) {
868                let script = document.createElement('script');
869                script.text = response;
870                document.getElementById('jsinsert').appendChild(script);
871            },
872            function ($this, err) {
873                BOOKING_FAIL_WAIT_TOO_LONG();
874            }
875    );
876}
877
878function renderLoader(element) {
879    let div = element.prepend('<div class="loaderdiv"><div class="loader"></div></div>');
880    console.log(['Show loader for: ' + element.attr('id'), div]);    
881}
882
883function removeLoader() {
884    $('div.loader').remove();
885}
886
887function formatDateMYSQL(date) {
888    var d = new Date(date),
889        month = '' + (d.getMonth() + 1),
890        day = '' + d.getDate(),
891        year = d.getFullYear();
892
893    if (month.length < 2) 
894        month = '0' + month;
895    if (day.length < 2) 
896        day = '0' + day;
897
898    return [year, month, day].join('-');
899}
900function doPayPalCheckout() {
901    
902    console.log('Payment call');
903    
904    const formData = new FormData();
905    formData.append('ci_csrf_token', csrf_token_value);
906    
907    fetch('/booking/paypalpayment/pay', {
908        method: 'POST',
909        body: formData,
910    })
911    .then(function (response) {
912        return response.json();
913    })
914    .then(function (session) {
915        console.log(session.links);
916        for(let link in session.links) {
917            if (session.links[link].rel === 'approve') {
918                location.href = session.links[link].href;
919                return true;
920            }
921        }
922    });
923};
924
925

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.