Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify InfiniteScroll to work horizontally

I see a few posts on this topic here but couldnt quite find one that actually solves the issue im trying to handle.

On my site i have pages of blog posts. i have setup infiniteScroll (https://github.com/paulirish/infinite-scroll) and it is working properly to load in the next page of content triggered by the scrolling action. i have set my div to scroll horizontally but i cannot figure out how to modify the infiniteScroll script (and the local.js script) to be triggered by a horizontal scroll rather than a vertical scroll.

here is the progress: https://adrtimesv6.squarespace.com/library/ (you have to type in the visitor access captcha to view while im building).

Any help would be greatly appreciated!! i have been tinkering and hunting through the interwebs for days now trying to get this to work....

My html structure is like so:

<div class="listWrapper">
    <div id="scroller">
        <article class="item"></article>
        <article class="item"></article>
        ... and so on
    </div>
</div>

My script looks like this:

$('#scroller').infinitescroll({
    behavior: 'local',
    binder: $('#scroller'),
    nextSelector: ".pagination .nextPage",
    navSelector: ".pagination",
    itemSelector: ".item",
    animate: false,
    extraScrollPx: 0,
    bufferPx: 235,
    pixelsFromNavToRight: undefined,
});

And i have modified the infiniteScroll js file to change all height references to width, top to left, and bottom to right:

;
(function ($) {
    $.fn.infinitescroll = function (options, callback) {
        function debug() {
            if (opts.debug) {
                window.console && console.log.call(console, arguments)
            }
        }

        function areSelectorsValid(opts) {
            for (var key in opts) {
                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
                    debug('Your ' + key + ' found no elements.');
                    return false;
                }
                return true;
            }
        }

        function determinePath(path) {
            path.match(relurl) ? path.match(relurl)[2] : path;
            if (path.match(/^(.*?)\b2\b(.*?$)/)) {
                path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
            } else
            if (path.match(/^(.*?)2(.*?$)/)) {
                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
                    return path;
                }
                debug('Trying backup next selector parse technique. Treacherous waters here, matey.');
                path = path.match(/^(.*?)2(.*?$)/).slice(1);
            } else {
                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
                    return path;
                }
                debug('Sorry, we couldn\'t parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.');
                props.isInvalidPage = true;
            }
            return path;
        }

        function getDocumentWidth() {
            return opts.localMode ? ($(props.container)[0].scrollWidth && $(props.container)[0].scrollWidth) : $(document).width()
        }

        function isNearRight() {
            var pixelsFromWindowRightToRight = 0 +
                getDocumentWidth() - (opts.localMode ? $(props.container).scrollLeft() : ($(props.container).scrollLeft() || $(props.container.ownerDocument.body).scrollLeft())) - $(opts.localMode ? props.container : window).width();
            debug('math:', pixelsFromWindowRightToRight, props.pixelsFromNavToRight);
            return (pixelsFromWindowRightToRight - opts.bufferPx < props.pixelsFromNavToRight);
        }

        function showDoneMsg() {
            props.loadingMsg.find('img').hide().parent().find('div').html(opts.donetext).animate({
                opacity: 1
            }, 2000).fadeOut('normal');
            opts.errorCallback();
        }

        function infscrSetup() {
            if (props.isDuringAjax || props.isInvalidPage || props.isDone) return;
            if (!isNearRight(opts, props)) return;
            $(document).trigger('retrieve.infscr');
        }

        function kickOffAjax() {
            props.isDuringAjax = true;
            props.loadingMsg.appendTo(opts.contentSelector).show();
            $(opts.navSelector).hide();
            props.currPage++;
            debug('heading into ajax', path);
            box = $(opts.contentSelector).is('table') ? $('<tbody/>') : $('<div/>');
            frag = document.createDocumentFragment();
            box.load(path.join(props.currPage) + ' ' + opts.itemSelector, null, loadCallback);
        }

        function loadCallback() {
            if (props.isDone) {
                showDoneMsg();
                return false;
            } else {
                var children = box.children().get();
                if (children.length == 0) {
                    return $.event.trigger("ajaxError", [{
                        status: 404
                    }]);
                }
                while (box[0].firstChild) {
                    frag.appendChild(box[0].firstChild);
                }
                $(opts.contentSelector)[0].appendChild(frag);
                props.loadingMsg.fadeOut('normal');
                if (opts.animate) {
                    var scrollTo = $(".listWrapper").scrollLeft() + $('#infscr-loading').width() + opts.extraScrollPx + 'px';
                    $(".listWrapper").animate({
                        scrollLeft: scrollTo
                    }, 800, function () {
                        props.isDuringAjax = false;
                    });
                }
                callback.call($(opts.contentSelector)[0], children);
                if (!opts.animate) props.isDuringAjax = false;
            }
        }
        $.browser.ie6 = $.browser.msie && $.browser.version < 7;
        var opts = $.extend({}, $.infinitescroll.defaults, options),
            props = $.infinitescroll,
            box, frag;
        callback = callback || function () {};
        if (!areSelectorsValid(opts)) {
            return false;
        }
        props.container = opts.localMode ? this : document.documentElement;
        opts.contentSelector = opts.contentSelector || this;
        var relurl = /(.*?\/\/).*?(\/.*)/,
            path = $(opts.nextSelector).attr('href');
        if (!path) {
            debug('Navigation selector not found');
            return;
        }
        path = determinePath(path);
        if (opts.localMode) $(props.container)[0].scrollLeft = 0;
        props.pixelsFromNavToRight = getDocumentWidth() +
            (props.container == document.documentElement ? 0 : $(props.container).offset().left) -
            $(opts.navSelector).offset().left;
        props.loadingMsg = $('<div id="infscr-loading" style="text-align: center;"><img alt="Loading" src="' +
            opts.loadingImg + '" /><div>' + opts.loadingText + '</div></div>');
        (new Image()).src = opts.loadingImg;
        $(document).ajaxError(function (e, xhr, opt) {
            debug('Page not found. Self-destructing...');
            if (xhr.status == 404) {
                showDoneMsg();
                props.isDone = true;
                $(opts.localMode ? this : window).unbind('scroll.infscr');
            }
        });
        $(opts.localMode ? this : window).bind('scroll.infscr', infscrSetup).trigger('scroll.infscr');
        $(document).bind('retrieve.infscr', kickOffAjax);
        return this;
    }
    $.infinitescroll = {
        defaults: {
            debug: false,
            preload: false,
            nextSelector: "div.navigation a:first",
            loadingImg: "http://www.infinite-scroll.com/loading.gif",
            loadingText: "<em>Loading</em>",
            donetext: "<em>Congratulations, you've reached the end.</em>",
            navSelector: "div.navigation",
            contentSelector: null,
            extraScrollPx: 150,
            itemSelector: "div.post",
            animate: false,
            localMode: false,
            bufferPx: 40,
            errorCallback: function () {}
        },
        loadingImg: undefined,
        loadingMsg: undefined,
        container: undefined,
        currPage: 1,
        currDOMChunk: null,
        isDuringAjax: false,
        isInvalidPage: false,
        isDone: false
    };
})(jQuery);

I also switched out all the top, left, right, bottom references in the local.js file:

// Calculate internal width (used for local horizontal scroll)
function infsrc_local_hiddenWidth(element) {
   var width = 0;
   jQuery(element).children().each(function() {
     width = width + jQuery(this).outerWidth(false);
   });
   return width;
}

jQuery.extend(jQuery.infinitescroll.prototype,{
   _nearright_local: function infscr_nearright_local() {
       var opts = this.options, instance = this,
           pixelsFromWindowRightToRight = infsrc_local_hiddenWidth(opts.binder)
               - jQuery(opts.binder).scrollLeft() - jQuery(opts.binder).width();

       if (opts.local_pixelsFromNavToRight == undefined){
           opts.local_pixelsFromNavToRight = infsrc_local_hiddenWidth(opts.binder) +
         jQuery(opts.binder).offset().left - jQuery(opts.navSelector).offset().left;
       }
       instance._debug('local math:', pixelsFromWindowRightToRight,
opts.local_pixelsFromNavToRight);

       return (pixelsFromWindowRightToRight - opts.bufferPx < opts.local_pixelsFromNavToRight);
   }
});

UPDATE ** It seems as though it is almost all working correctly, there are a couple little glitches left: -- the content is loaded and the element the content is loaded into is scrolling horizontally, however the load seems to still be triggered by the vertical scroll and not the horizontal scroll like i need it. -- it seems like the local.js file is not being triggered. if i remove the script then nothing changes. this might be the heart of my problem?

like image 719
VUELA Avatar asked Jul 16 '13 22:07

VUELA


1 Answers

Is this what you're looking for?

var scrollp = Math.ceil( $('body').width() / 20 );
$('body').mousewheel(function(event, delta) {
    if (delta < 0) {
        $('body').scrollTo('+='+scrollp, 50, {easing:'easeInOutSine', queue:false, axis:'x'});
    } else {
        $('body').scrollTo('-='+scrollp , 50, {easing:'easeInOutSine', queue:false, axis:'x'} );
        event.preventDefault();
    }
});

http://jsfiddle.net/jonnysooter/RHKyP/18/

EDIT

If this sort of "jump back to the start" isn't what you want, then just modify the code a bit to start loading your content in this callback if the scroll hits the full width. When your content loads, the div width will increase and with it the scroll.

This question might shed some light on another approach. horizontal infinite scroll

like image 64
Jonny Sooter Avatar answered Sep 24 '22 22:09

Jonny Sooter