PageSourceSearch

https://www.cruiseonline.com/nl-nl/assets/js/favorite.js?v=1791385018

js cruiseonline.com collected 2026-10-07 14:57:37 UTC 19,231 bytes, 582 lines download raw bytes

1var isBusiness = false;
2try {
3    if (document.currentScript && document.currentScript.src) {
4        const urlParams = new URL(document.currentScript.src).searchParams;
5        isBusiness = urlParams.get('business') === 'true';
6    }
7} catch (e) {}
8
9if (!isBusiness && (window.location.pathname.includes('/dev/') || window.location.pathname.includes('/business/') || window.location.pathname.includes('/admin/'))) {
10    isBusiness = true;
11}
12
13var endpoint = (isBusiness ? '/dev/api/business/favorite.php' : '/api/favorite.php');
14var isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
15var favoriteProducts = [];
16let added = false;
17timeout = false;
18timeout2 = false;
19$(document).ready(function ($) {
20    var webPath = $('#webpath').val() || '';
21    endpoint = webPath + (isBusiness ? '/dev/api/business/favorite.php' : '/api/favorite.php');
22
23    $('body').on('keyup', '#favoriteSearch', function() {
24        var value = $(this).val().toLowerCase();
25
26        $('#favoritePopup form .col-12').each(function() {
27            var col = $(this);
28            if (col.find('input[value="new"]').length > 0 ||
29                col.find('button[type="submit"]').length > 0 ||
30                col.find('#favoriteSearch').length > 0) {
31                return;
32            }
33
34            var text = col.text().toLowerCase();
35            var isMatch = text.indexOf(value) > -1;
36
37            col.toggle(isMatch);
38
39            col.next('hr').toggle(isMatch);
40        });
41    });
42
43
44    $('body').on('click', '.favorite', function (e) {
45        e.preventDefault();
46
47        var thisBtn = $(this);
48        var productId = thisBtn.data('product');
49        var start = thisBtn.data('date');
50
51        if(isBusiness) {
52            var listHashContainer = thisBtn.closest('div[data-listhash]');
53            var isRemovingFromList = thisBtn.hasClass('active') && listHashContainer.length > 0;
54            console.log(isRemovingFromList);
55            if (isRemovingFromList) {
56                var list = listHashContainer.data('listhash');
57
58                thisBtn.toggleClass('active', false);
59
60                syncFavorites('delete', productId, start, thisBtn, list);
61            } else {
62
63                loadFavoriteList(null, null, productId, start);
64            }
65
66        } else {
67            var isRemoving = thisBtn.hasClass('active');
68            var performAction = isRemoving ? 'delete' : 'add';
69
70            $(this).toggleClass('active', !isRemoving);
71
72            if (!isRemoving) {
73                loadFavoriteList(null, null, productId, start);
74
75                let modal = $("#favoriteListPopup");
76                modal.data("product", productId);
77                modal.data("start", start);
78                modal.data("btn", thisBtn);
79                modal.modal("show");
80                return;
81            }
82
83            syncFavorites(performAction, productId, start, thisBtn, null);
84        }
85
86        return false;
87    });
88
89    $(document).on("hide.bs.modal", "#favoriteListPopup", function () {
90        let modal = $("#favoriteListPopup");
91        console.log($(".favoriteSavedPopup").is(":visible"));
92
93        if (!added) {
94            $(".favorite[data-product='" + modal.data("product") + "'][data-date='" + modal.data("start") + "']").removeClass("active");
95            let notSavedPopup = $(".favoriteNotSavedPopup")
96            notSavedPopup.slideToggle();
97            if (timeout) {
98                clearTimeout(timeout);
99                notSavedPopup.slideToggle();
100            }
101            timeout = setTimeout(function () {
102                if (notSavedPopup.is(":visible")) {
103                    notSavedPopup.slideToggle()
104                }
105                timeout = false;
106            }, 5000)
107        }
108    })
109
110    $(document).on("click", "#favoriteLoginButton", function () {
111        added=true;
112        let modal = $("#loginModal");
113        modal.data('favorite_product', $(this).parents('.modal').data('product'));
114        modal.data('start', $(this).parents('.modal').data('start'));
115        modal.data('btn', $(this).parents('.modal').data('btn'));
116        modal.modal("show");
117        $("#favoriteListPopup").modal("hide");
118    })
119
120    $(document).on("click", "#favoriteRegisterButton", function () {
121        added=true;
122        let modal = $("#registerModal");
123        modal.data('favorite_product', $(this).parents('.modal').data('product'));
124        modal.data('start', $(this).parents('.modal').data('start'));
125        modal.data('btn', $(this).parents('.modal').data('btn'));
126        modal.modal("show");
127        $("#favoriteListPopup").modal("hide");
128    })
129
130    $(document).on("click", ".favoriteAddList", function (e) {
131        added = true;
132        let modal = $("#favoriteListPopup");
133        let productId = modal.data("product")
134        let start = modal.data("start");
135        let btn = modal.data("btn")
136        let list = $(this).data("listid");
137        modal.modal("hide")
138
139        syncFavorites("add", productId, start, btn, list);
140    })
141
142    $(document).on("click", "#newListButton", function (e) {
143        $("#newListContent").show();
144        $("#listContent").hide();
145    });
146
147    moveElements();
148    $(window).resize(function () {
149        moveElements();
150    });
151
152    setFavoriteProducts();
153
154    $('.swipe-front').each(function() {
155        var card = $(this);
156        var startX, currentX;
157        var threshold = 100; // Distance to swipe before it snaps open
158        var isDragging = false;
159
160        card.on('touchstart', function(e) {
161            // jQuery wrapper for touch event
162            var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
163            startX = touch.clientX;
164            card.css('transition', 'none'); // Remove transition for instant follow
165            isDragging = true;
166        });
167
168        card.on('touchmove', function(e) {
169            if (!isDragging) return;
170
171            var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
172            currentX = touch.clientX;
173            var diff = currentX - startX;
174
175            // Only allow swiping left (negative values)
176            if (diff < 0) {
177                // If swiping horizontally, stop page scroll (optional but recommended)
178                if (Math.abs(diff) > 10 && e.cancelable) {
179                    // e.preventDefault();
180                }
181                card.css('transform', 'translateX(' + diff + 'px)');
182            }
183        });
184
185        card.on('touchend', function(e) {
186            if (!isDragging) return;
187            isDragging = false;
188
189            var diff = currentX - startX;
190            card.css('transition', 'transform 0.3s ease-out'); // Smooth snap
191
192            // If swiped left more than threshold, snap open to -120px
193            if (diff < -threshold) {
194                card.css('transform', 'translateX(-120px)');
195            } else {
196                card.css('transform', 'translateX(0)');
197            }
198        });
199    });
200
201    $('body').on('click', '.delete-action', function() {
202        var btn = $(this);
203        var container = btn.closest('.swipe-container');
204        var listId = container.data('id');
205        var listCount = parseInt(container.data('listcount')) || 0;
206        if(listCount > 0) {
207            Lobibox.notify('error', {
208                pauseDelayOnHover: true,
209                size: 'mini',
210                rounded: true,
211                delayIndicator: true,
212                delay: isMobile ? 4500 : 3500,
213                icon: 'material-icons favorite-icon',
214                continueDelayOnInactiveTab: false,
215                position: isMobile ? 'bottom center custom-lobi' : 'top right',
216                msg: trans("delete_favorites_first")
217            });
218            container.find('.swipe-front').css('transform', 'translateX(0)');
219            return;
220        }
221
222        deleteList(listId, container);
223    });
224});
225
226function deleteList(listId, container) {
227    if (!confirm(trans("sure_to_delete_list"))) {
228        container.find('.swipe-front').css('transform', 'translateX(0)');
229        return;
230    }
231
232    $.ajax({
233        url: endpoint,
234        method: 'POST',
235        dataType: 'json',
236        data: {
237            action: 'deleteList',
238            list_id: listId
239        },
240        success: function (response) {
241            if (response.success) {
242                container.css('transition', 'all 0.5s ease').css('opacity', '0');
243
244                setTimeout(function() {
245                    container.slideUp(300, function() {
246                        $(this).remove();
247                    });
248                }, 500);
249
250
251                    Lobibox.notify('success', {
252                        size: 'mini',
253                        rounded: true,
254                        icon: 'material-icons check',
255                        msg: trans("list_deleted_successfully")
256                    });
257
258            } else {
259                alert(trans("something_went_wrong_try_again"));
260                container.find('.swipe-front').css('transform', 'translateX(0)');
261            }
262        },
263        error: function (xhr, status, error) {
264            console.error("Delete failed:", error);
265            Lobibox.notify('error', {
266                size: 'mini',
267                rounded: true,
268                icon: 'material-icons check',
269                msg: trans("something_wrong")
270            });
271            container.find('.swipe-front').css('transform', 'translateX(0)');
272        }
273    });
274}
275
276function saveFavoriteList() {
277    let name = $("#nameInput").val();
278    let modal = $("#favoriteListPopup");
279    let productId = modal.data("product")
280    let start = modal.data("start");
281    let btn = modal.data("btn")
282    $.ajax({
283        url: endpoint,
284        method: 'POST',
285        dataType: 'json',
286        data: {
287            action: 'createList',
288            name: name,
289        },
290        success: function (response) {
291            if (response.success) {
292                added = true;
293                syncFavorites("add", productId, start, btn, response.listId);
294                modal.modal("hide");
295                $("#newListContent").hide();
296                $("#listContent").show();
297            } else {
298                Lobibox.notify('error', {
299                    size: 'mini',
300                    rounded: true,
301                    icon: 'material-icons check',
302                    msg: response.message
303                });
304            }
305            let saveButton =  $("#saveFavoriteListButton")
306            saveButton.html(saveButton.data("text"))
307        },
308        error: function (xhr, status, error) {
309            Lobibox.notify('error', {
310                size: 'mini',
311                rounded: true,
312                icon: 'material-icons check',
313                msg: trans("something_wrong")
314            });
315        }
316    });
317}
318
319function updateHeaderCount(count) {
320    var favoriteBlock = $('#favoriteProductContent');
321    var countSpan = favoriteBlock.find('a span:not(.material-icons):not(.logout)');
322    if (countSpan.length === 0) {
323        countSpan = favoriteBlock.find('a div.li span');
324    }
325    var linkContainer = favoriteBlock.find('a');
326    var breakBar = $('.break-bar');
327    var toggler = $('.navbar-toggler');
328
329    countSpan.html(count);
330
331    if (count > 0) {
332        linkContainer.show();
333        favoriteBlock.find('a .li').show();
334        breakBar.css('display', 'inline-block');
335        toggler.addClass('favoriteEnabled');
336    } else {
337        linkContainer.hide();
338        breakBar.hide();
339        toggler.removeClass('favoriteEnabled');
340    }
341}
342
343
344function addFavoriteAfterLogin() {
345    let modal = $("#loginmodal:visible, #registerModal:visible");
346    if (modal.data("favorite_product")) {
347        syncFavorites("add", modal.data("favorite_product"), modal.data("start"), modal.data("btn"))
348    }
349}
350
351function syncFavorites(performAction, productId = 0, start = false, btn = false, list = null) {
352    $.ajax({
353        url: endpoint,
354        method: 'POST',
355        dataType: 'json',
356        data: {
357            action: 'syncFavorite',
358            perform: performAction,
359            product_id: productId,
360            start: start,
361            list: list
362        },
363        success: function (response) {
364            var newCount = response.favoriteCount || 0;
365
366            updateHeaderCount(newCount);
367
368            var date = new Date();
369            date.setTime(date.getTime()+(1500*60*1000));
370            var expires = "; expires="+date.toGMTString();
371
372            document.cookie = "favoriteProduct=" + newCount + expires +";  path=/";
373            if (window.flutter_inappwebview !== undefined) {
374                console.log('favoritesUpdated');
375                window.flutter_inappwebview.callHandler('favoritesUpdated');
376            }
377
378
379            if (performAction == "delete" && $("[data-listhash]").length > 0) {
380                window.location.reload();
381            }
382
383            if (performAction === 'add' && btn) {
384                added = false;
385                var message = trans("save_in_link", {
386                    "LINK": '<a href="' + response.list_url + '"><u>' + response.list + '</u></a>'
387                })
388                let savedPopup = $(".favoriteSavedPopup")
389                let savedTextElement = savedPopup.find(".savedText");
390                let img = $(".favoriteSavedPopup").find("img");
391                savedTextElement.html(message);
392                savedPopup.slideToggle()
393                img.attr("src", response.image);
394
395                if (timeout2) {
396                    clearTimeout(timeout2);
397                    savedPopup.slideToggle()
398                }
399                timeout2 = setTimeout(function () {
400                    if (savedPopup.is(":visible")) {
401                        savedPopup.slideToggle()
402                    }
403                    timeout2 = false;
404                }, 10000)
405
406            } else if(performAction === 'sync') {
407
408                favoriteProducts = response.favoriteProducts;
409
410                $('body .favorite').each(function() {
411                    var productId = $(this).data('product') + '-' + $(this).data('date');
412                    if(favoriteProducts.includes(productId)) {
413                        $(this).addClass('active');
414                    } else {
415                        $(this).removeClass('active');
416                    }
417                })
418            }
419        },
420        error: function (xhr, status, error) {
421            console.log("Favorite sync failed:", error);
422            console.log("Status Code:", xhr.status);
423            console.log("Server Response:", xhr.responseText);
424            if(productId > 0) {
425                $(".favorite[data-product='" + productId + "']").toggleClass('active', performAction === 'delete');
426            }
427        }
428    });
429}
430
431function moveElements() {
432    var domWidth = $(window).width();
433    var favoriteBlock = $('#favoriteProductContent');
434    if (domWidth > 1199) {
435        $('.favoriteProductContentDesktop').html(favoriteBlock.outerHTML);
436        $('.favoriteProductContentMobile').html('');
437    } else {
438        $('.favoriteProductContentDesktop').html('');
439        $('.favoriteProductContentMobile').html(favoriteBlock.outerHTML);
440    }
441}
442
443function setFavoriteProducts() {
444    syncFavorites('sync');
445}
446
447function loadFavoriteList(favorite_id, list_id, product_id = null, start = null) {
448
449    $('#favoritePopup .modal-body').html('<div class="w-100 text-center py-5"><span style="font-size:36px;" class="mi-spin material-icons">progress_activity</span></div>')
450    if (isBusiness) {
451        $('#favoritePopup').modal("show");
452    }
453
454
455    $.ajax({
456        url: endpoint,
457        method: 'POST',
458        dataType: 'json',
459        data: {
460            action: 'loadFavoriteList',
461            favorite_id: favorite_id,
462            list_id: list_id,
463            product_id: product_id,
464            start: start
465        },
466        success: function (response) {
467            if(response.success) {
468                if (isBusiness) {
469                    $('#favoritePopup .modal-body').html(response.html)
470                } else {
471                    $('#favoriteListPopup #favoriteLists').html(response.html)
472                }
473
474            } else {
475                $('#favoritePopup .modal-body').html(`<p class="p-3 text-center">${trans("something_wrong_not_logged_in")}</p>`);
476            }
477        }
478    })
479}
480
481function submitFavoriteForm(e, form) {
482    e.preventDefault();
483
484    var selectedLists = [];
485
486    $(form).find('input[name="favorite_list[]"]:checked').each(function() {
487        selectedLists.push($(this).val());
488    });
489
490    if(selectedLists.length === 0) {
491        var radioVal = $(form).find('input[name="favorite_list"]:checked').val();
492        if(radioVal) {
493            selectedLists.push(radioVal);
494        }
495    }
496
497    $.ajax({
498        url: endpoint,
499        method: 'POST',
500        dataType: 'json',
501        data: {
502            action: 'saveFavorite',
503            favorite_id: $(form).find('input[name=favorite_id]').val(),
504            product_id: $(form).find('input[name=product_id]').val(),
505            start: $(form).find('input[name=start]').val(),
506            favorite_list: selectedLists,
507            new_name: $(form).find('input[name=new_name]').val(),
508        },
509        success: function (response) {
510
511            Lobibox.notify(response.success ? 'success' : 'error', {
512                pauseDelayOnHover: true,
513                size: 'mini',
514                rounded: true,
515                delayIndicator: true,
516                delay: 3500,
517                icon: 'material-icons favorite-icon',
518                continueDelayOnInactiveTab: false,
519                position: 'top right',
520                msg: response.message
521            });
522
523            $('#favoritePopup').modal("hide");
524
525            if(response.success) {
526                syncFavorites('sync');
527            }
528        }
529    })
530}
531
532function saveFavoriteNamePopup() {
533    const modal = $("#favoriteNamePopup");
534    const name = modal.find("input[type='text']").val();
535    const listId = modal.find("[name=list_id]").val();
536    modal.modal("hide");
537
538    $.ajax({
539        url: endpoint,
540        method: 'POST',
541        dataType: 'json',
542        data: {
543            action: 'changeName',
544            list_id: listId,
545            name,
546        },
547        success: function (response) {
548            if (response.success) {
549                window.location.reload();
550            }
551        },
552        error: function (xhr, status, error) {
553            console.error("Delete failed:", error);
554        }
555    });
556}
557
558function deleteFavoriteList() {
559    const modal = $("#favoriteDeletePopup");
560    const listId = modal.find("[name=list_id]").val();
561    modal.modal("hide");
562    $.ajax({
563        url: endpoint,
564        method: 'POST',
565        dataType: 'json',
566        data: {
567            action: 'deleteList',
568            list_id: listId
569        },
570        success: function (response) {
571            if (response.success) {
572                window.location.reload();
573            } else {
574                console.log("DELETE DID NOT WORKKK")
575            }
576
577        },
578        error: function (xhr, status, error) {
579            console.error("Delete failed:", error);
580        }
581    });
582}

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.