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
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); |