ctrl.init = function()

in kahuna/public/js/components/gu-lazy-preview/gu-lazy-preview.js [20:99]


    ctrl.init = function({items$, totalItems$, preloadedItems$, currentIndex$}) {
        const itemsCount$ = items$.map(items => items.length).distinctUntilChanged();
        const totalItemsCount$ = totalItems$.map(totalItems => {
            return totalItems.length;
        }).distinctUntilChanged();

        const buttonCommands$ = Rx.Observable.create(observer => {
            ctrl.prevItem     = () => observer.onNext('prevItem');
            ctrl.nextItem     = () => observer.onNext('nextItem');

            // Make sure we start at the beginning
            observer.onNext('previewStart');
        });


        const itemsOffset$ = buttonCommands$.combineLatest(
            itemsCount$,
            (command, itemsCount) => {
                return {command, itemsCount};
            }).withLatestFrom(
                currentIndex$,
                ({command}, currentIndex) => {
                    return {
                        prevItem:     -1,
                        nextItem:     +1,
                        previewStart: currentIndex * -1
                    }[command] || 0;
                }
            );




        const updatedIndex$ = itemsOffset$.withLatestFrom(
            currentIndex$, itemsCount$, totalItemsCount$,
            (itemsOffset, currentIndex, itemsCount, totalItemsCount) => {
                const updatedIndex = currentIndex + itemsOffset;
                // Update the index if it's in the range of items
                if (updatedIndex >= 0 && updatedIndex < totalItemsCount) {
                    return updatedIndex;
                } else {
                    return currentIndex;
                }
        });

        const item$ = updatedIndex$.withLatestFrom(
            totalItemsCount$, items$,
            (updatedIndex, totalItemsCount, items) => {
                currentIndex$.onNext(updatedIndex);
                return items[updatedIndex];
        });

        const currentPage$ = currentIndex$.withLatestFrom(
            preloadedItems$,
            (currentIndex, preloadedItems) => {
                return Math.floor(currentIndex / preloadedItems);
        });

        const rangeToLoad$ = currentPage$.withLatestFrom(
            preloadedItems$,
            (currentPage, preloadedItems) => {
                const start = currentPage * preloadedItems;
                const end = ((currentPage + 1) * preloadedItems) - 1;
            return {start, end};
        }).
            // Debounce range loading, which also helps discard
            // erroneous large ranges while combining
            // loadedRangeStart$ and loadedRangeEnd$ changes (one after the other)
            debounce(10).
            // Ignore if either end isn't set (whole range already loaded)
            filter(({start, end}) => start !== -1 && end !== -1).
            // Ignore if $start after $end (incomplete combine$ state)
            filter(({start, end}) => start <= end).
            distinctUntilChanged(({start, end}) => `${start}-${end}`);

        return {
            item$,
            rangeToLoad$
        };
    };