/*! // Infinite Scroll jQuery plugin // copyright Paul Irish, licensed GPL & MIT // version 1.5.110408 // home and docs: http://www.infinite-scroll.com */ (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) { 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 } if ($.isFunction(opts.pathParse)) { return [path] } else { 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 filterNav() { opts.isFiltered = true; return binder.trigger("error.infscr." + opts.infid, [302]) } function hiddenHeight(element) { var height = 0; $(element).children().each(function () { height = height + $(this).outerHeight(false) }); return height } function generateInstanceID(element) { var number = $(element).length + $(element).html().length + $(element).attr("class").length + $(element).attr("id").length; opts.infid = number } function isNearBottom() { if (opts.container.nodeName == "HTML") { var pixelsFromWindowBottomToBottom = 0 + $(document).height() - ($(opts.container).scrollTop() || $(opts.container.ownerDocument.body).scrollTop()) - $(window).height() } else { var pixelsFromWindowBottomToBottom = 0 + hiddenHeight(opts.container) - $(opts.container).scrollTop() - $(opts.container).height() } debug("math:", pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom) } function showDoneMsg() { props.loadingMsg.find("img").hide().parent().find("div").html(opts.donetext).animate({ opacity: 1 }, 2000, function () { $(this).parent().fadeOut("normal") }); opts.errorCallback() } function infscrSetup() { if (opts.isDuringAjax || opts.isInvalidPage || opts.isDone || opts.isFiltered || opts.isPaused) { return } if (!isNearBottom(opts, props)) { return } $(document).trigger("retrieve.infscr." + opts.infid) } function kickOffAjax() { opts.isDuringAjax = true; props.loadingMsg.appendTo(opts.loadMsgSelector).show(opts.loadingMsgRevealSpeed, function () { $(opts.navSelector).hide(); opts.currPage++; debug("heading into ajax", path); box = $(opts.contentSelector).is("table") ? $("") : $("
"); frag = document.createDocumentFragment(); if ($.isFunction(opts.pathParse)) { desturl = opts.pathParse(path.join("2"), opts.currPage) } else { desturl = path.join(opts.currPage) } box.load(desturl + " " + opts.itemSelector, null, loadCallback) }) } function loadCallback() { if (opts.isDone) { showDoneMsg(); return false } else { var children = box.children(); if (children.length == 0 || children.hasClass("error404")) { return infscrError([404]) } while (box[0].firstChild) { frag.appendChild(box[0].firstChild) } $(opts.contentSelector)[0].appendChild(frag); props.loadingMsg.fadeOut("normal"); if (opts.animate) { var scrollTo = $(window).scrollTop() + $("#infscr-loading").height() + opts.extraScrollPx + "px"; $("html,body").animate({ scrollTop: scrollTo }, 800, function () { opts.isDuringAjax = false }) } callback.call($(opts.contentSelector)[0], children.get()); if (!opts.animate) { opts.isDuringAjax = false } } } function initPause(pauseValue) { pauseValue = (pauseValue && (pauseValue == "pause" || pauseValue == "resume")) ? pauseValue : "toggle"; switch (pauseValue) { case "pause": opts.isPaused = true; break; case "resume": opts.isPaused = false; break; case "toggle": opts.isPaused = !opts.isPaused; break } debug("Paused: " + opts.isPaused); return false } function infscrError(xhr) { if (!opts.isDone && xhr == 404) { debug("Page not found. Self-destructing..."); showDoneMsg(); opts.isDone = true; opts.currPage = 1; binder.unbind("smartscroll.infscr." + opts.infid); $(document).unbind("retrieve.infscr." + opts.infid) } if (opts.isFiltered && xhr == 302) { debug("Filtered. Going to next instance..."); opts.isDone = true; opts.currPage = 1; opts.isPaused = false; binder.unbind("smartscroll.infscr." + opts.infid, infscrSetup).unbind("pause.infscr." + opts.infid).unbind("filter.infscr." + opts.infid).unbind("error.infscr." + opts.infid); $(document).unbind("retrieve.infscr." + opts.infid, kickOffAjax) } } var event = $.event, scrollTimeout; event.special.smartscroll = { setup: function () { $(this).bind("scroll", event.special.smartscroll.handler) }, teardown: function () { $(this).unbind("scroll", event.special.smartscroll.handler) }, handler: function (event, execAsap) { var context = this, args = arguments; event.type = "smartscroll"; if (scrollTimeout) { clearTimeout(scrollTimeout) } scrollTimeout = setTimeout(function () { jQuery.event.handle.apply(context, args) }, execAsap === "execAsap" ? 0 : 100) } }; $.fn.smartscroll = function (fn) { return fn ? this.bind("smartscroll", fn) : this.trigger("smartscroll", ["execAsap"]) }; $.browser.ie6 = $.browser.msie && $.browser.version < 7; var opts = $.extend({}, $.infinitescroll.defaults, options), props = $.infinitescroll, box, frag, desturl, thisPause, errorStatus; callback = callback || function () { }; if (!areSelectorsValid(opts)) { return false } opts.container = opts.container || document.documentElement; opts.contentSelector = opts.contentSelector || this; if (opts.infid == 0) { generateInstanceID(opts.contentSelector) } opts.loadMsgSelector = opts.loadMsgSelector || opts.contentSelector; var relurl = /(.*?\/\/).*?(\/.*)/, path = $(opts.nextSelector).attr("href"); if (!path) { debug("Navigation selector not found"); return } path = determinePath(path); props.loadingMsg = $('
Loading...
' + opts.loadingText + "
"); (new Image()).src = opts.loadingImg; if (opts.container.nodeName == "HTML") { debug("Window Scroll"); var innerContainerHeight = $(document).height(); var binder = $(window) } else { debug("Local Scroll"); var innerContainerHeight = hiddenHeight(opts.container); var binder = $(opts.container) } opts.pixelsFromNavToBottom = innerContainerHeight + (opts.container == document.documentElement ? 0 : $(opts.container).offset().top) - $(opts.navSelector).offset().top; binder.bind("smartscroll.infscr." + opts.infid, function () { infscrSetup() }, 600, false).bind("filter.infscr." + opts.infid, filterNav).bind("error.infscr." + opts.infid, function (event, errorStatus) { infscrError(errorStatus) }).bind("pause.infscr." + opts.infid, function (event, thisPause) { initPause(thisPause) }).trigger("smartscroll.infscr." + opts.infid); $(document).bind("retrieve.infscr." + opts.infid, kickOffAjax); return this }; $.infinitescroll = { defaults: { debug: false, preload: false, nextSelector: "div.navigation a:first", loadingImg: "http://www.infinite-scroll.com/loading.gif", loadingText: "Loading the next set of posts...", donetext: "Congratulations, you've reached the end of the internet.", navSelector: "div.navigation", contentSelector: null, loadMsgSelector: null, loadingMsgRevealSpeed: "fast", extraScrollPx: 150, itemSelector: "div.post", animate: false, pathParse: undefined, bufferPx: 40, orientation: "height", errorCallback: function () { }, currPage: 1, infid: 0, isDuringAjax: false, isInvalidPage: false, isFiltered: false, isDone: false, isPaused: false, container: undefined, pixelsFromNavToBottom: undefined }, loadingImg: undefined, loadingMsg: undefined, currDOMChunk: null} })(jQuery);