You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

146 lines
5.4 KiB

/**
* jquery waterfall
* @author richard chen
* @update 2014-10-07
* @version 1.0
* @parameters
* itemClass: the brick element class
* spacingWidth: the brick element horizontal spacing
* spacingHeight: the brick element vertical spacing
* minColCount: min columns
* resizeable: trigger positionAll() when browser window is resized
* itemAlign: the alignment of the brick element ( e.q. [center|left] )
* isFadeIn: fadeIn effect on loading
* ajaxCallback: callback when ajax loaded, two parameters ( success, end )
*/
(function($) {
var $window = $(window),
pluginName = 'waterfall',
defaults = {
itemClass: "waterfall-item", // the brick element class
spacingWidth: 10, // the brick element horizontal spacing
spacingHeight: 10, // the brick element vertical spacing
minColCount: 2, // min columns
resizeable: false, // trigger positionAll() when browser window is resized
itemAlign: "center", // the alignment of the brick element ( e.q. [center|left] )
isFadeIn: true, // fadeIn effect on loading
ajaxCallback: null // callback when ajax loaded, two parameters ( success, end )
};
function Waterfall(element, options) {
this.$element = $(element);
this.options = $.extend(true, {}, defaults, options);
this.ajaxLoading = false; // is ajax loading
this.colHeightArray = []; // height of each columns
this._init();
}
Waterfall.prototype = {
constructor: Waterfall,
_init: function () {
var $this = this;
$window.on("load", function() {
$this._positionAll();
});
if(this.options.resizeable) {
$window.on("resize", function() {
$this._positionAll();
});
}
this._doScroll();
},
_getColumnCount: function () {
var parentWidth = this.$element.width(),
$item = $(this.options.itemClass),
itemWidth = $item.eq(0).outerWidth(),
iCol = Math.floor(parentWidth / (itemWidth + this.options.spacingWidth)),
realWidth = 0,
leftOffset = 0;
iCol = iCol > this.options.minColCount ? iCol : this.options.minColCount;
realWidth = iCol * itemWidth;
if(parentWidth > realWidth) {
leftOffset = Math.floor((parentWidth - realWidth - iCol * this.options.spacingWidth) / 2);
}
this.itemWidth = itemWidth;
this.cols = iCol;
this.leftOffset = this.options.itemAlign == "center" ? leftOffset : 0;
},
_positionAll: function () {
var $this = this,
$item = $(this.options.itemClass),
minHeight,
minIndex;
this._getColumnCount();
this.colHeightArray = [];
$item.each(function(index) {
$(this).css("position", "absolute");
if(index < $this.cols) {
$(this).css("top", 0);
$(this).css("left", $this.leftOffset + index * $this.itemWidth + index * $this.options.spacingWidth);
$this.colHeightArray.push($(this).outerHeight());
} else {
minHeight = Math.min.apply(null, $this.colHeightArray);
minIndex = $.inArray(minHeight, $this.colHeightArray);
$(this).css("top", minHeight + $this.options.spacingHeight);
$(this).css("left", $item.eq(minIndex).offset().left);
$this.colHeightArray[minIndex] += $(this).outerHeight() + $this.options.spacingHeight;
}
if($this.options.isFadeIn) {
$(this).animate({"opacity": 1}, 300);
}
});
this.$element.css("height", Math.max.apply(null, $this.colHeightArray));
},
_doScroll: function () {
var $this = this,
scrollTimer;
$window.on("scroll", function() {
if(scrollTimer) {
clearTimeout(scrollTimer);
}
scrollTimer = setTimeout(function() {
var $last = $($this.options.itemClass).last(),
scrollTop = $window.scrollTop() + $window.height();
if(!$this.ajaxLoading && scrollTop > $last.offset().top + $last.outerHeight() / 2) {
$this.ajaxLoading = true;
$this.options.ajaxCallback && $this.options.ajaxCallback(
// reposition all the brick element after successful load ajax data
function() {
$this._positionAll();
},
function() {
$this.ajaxLoading = false;
}
);
}
}, 100);
});
}
}
$.fn[pluginName] = function (options) {
this.each(function() {
if(!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Waterfall(this, options));
}
});
return this;
}
})(jQuery);