基于Bootstrap4的瀑布流插件mpmansory.js的bug修改

基于Bootstrap4的瀑布流插件mpmansory.js的bug修改

今天朋友给一个网上下的模板让帮着改改,我一看加载那一大堆的css和js就烦,正好这两天没事就学着用Bootstrap4给他改改,第一次用Bootstrap4,略微折腾了一下,感觉还是挺好用,怪不得那么多人喜欢用这个呢。网站文章列表用的图片加文字的瀑布流,结果用mpmansory.js这个插件上去之后老不行,发现这个插件最后一次更新是2016年,估计那时候Bootstrap4可能还没出来,肯定是不兼容,只好读代码修改了,修改后的代码如下。

(function ( $ ) {

	$.fn.mpmansory = function ( options ) {

		var settings = $.extend({
			childrenClass: "",
			breakpoints: {
					xl: 4,
					lg: 4,
					md: 6,
					sm: 12
			},
			distributeBy: {
				attr: "data-order",
				attrOrder: "asc",
				order: false,
				height: false
			},
			onload: function ( items ) {
				return true;
			}
			
		}, options);

		Array.min = function( array ){
		    return Math.min.apply( Math, array );
		};

		$.emptyArray = function ( array ) {
			for (var i = 0; i<array.length; i++) {
				array[i].remove();
			}

			return new Array();
		}

		$.fn.initialize = function ( columns, classStr ) {
			/*
			 * @params [string] {classStr} - the bootstrap column string
			 * @return [Array] - list of columns to create
			 * @description - creates the grid columns in wich the items will be distributed
			 */
			
			var cols = [];

			for (var i = 0; i<columns; i++) {
				
				var wrap = $("<div></div>");
				wrap.addClass(classStr);
				$(this).append(wrap);
				cols.push(wrap);
			
			}

			return cols;

		}

		$.fn.distributeItemsByHeight = function ( wrappers, items ) {
			/*
			 * @params [Array] {wrappers} - the array containing the columns elements
			 * @params [Array] {items} - the array containing items
			 * @description - distribute the items through the columns - to the columns with lowest height
			 */
			var counter = 0;

			for (var k = 0; k<items.length; k++) {

				var $heights = new Array();

				for (var i = 0; i<wrappers.length; i++ ) {

					//get the wrappers height
					
					$heights.push(wrappers[i].height());

				}

				//get the wrapper with the lowest height
				var min = Array.min($heights) == Number.POSITIVE_INFINITY || Array.min($heights) == Number.NEGATIVE_INFINITY ? 0 : Array.min($heights);
				wrappers[$heights.indexOf(min)].append(items[k]);
	
			}

		}

		$.fn.getCurrentColumnSize = function () {

			if ($(window).width() > 1200) {
				return "xl";
			} else if ($(window).width() > 992) {
				return "lg";
			} else if ($(window).width() > 768) {
				return "md";
			} else if ($(window).width() > 576) {
				return "sm";
			} else {
				return "";
			}

		}

		$.fn.distributeItemsByOrder = function ( wrappers, items ) {
			/*
			 * @params [Array] {wrappers} - the array containing the columns elements
			 * @params [Array] {items} - the array containing items
			 * @description - distribute the items through the columns - to the columns with lowest height
			 */
			var counter = 0;

			for (var k = 0; k<items.length; k++) {
				if (counter == wrappers.length) counter = 0; 
				wrappers[counter].append(items[k]);
				counter++;
			}

		}

		$.fn.orderItemsByAttr = function (items, order) {

			var attrs = new Array();
			for ( var k = 0; k<items.length; k++ ) {
				attrs.push($(items[k]).attr(order.attr));
			}

			if  (order.attrOrder == "asc") {
				attrs.sort(function (a, b) { return a-b });
			} else {
				attrs.sort(function (a, b) { return b-a });
			}

			var ordered_items = new Array();

			for ( var i = 0; i<attrs.length; i++) {
				var item = $.grep(items, function (e) {return $(e).attr(order.attr) == attrs[i]});
				ordered_items.push(item);
			}
			return ordered_items;
		}

		$.fn.distributeItemsByAttr = function ( wrappers, items, order) {

			var counter = 0;
			var counter2 = 0;

			for (var i = 0; i<items.length; i++) {
				console.log(wrappers);
				if (counter == wrappers.length) counter = 0;
				if ( items[i].length > 1) {
					if (counter2 == items[i].length) counter2 = 0; 
					wrappers[counter].append($(items[i][counter2]));
					counter2++;
				} else {
					wrappers[counter].append($(items[i]));	
				}
				counter++;
			}	
		}

		$.fn.apply = function ( settings, nrOfColumns, wrappers, items ) {

			var _this = $(this);
			
			var currentSize = _this.getCurrentColumnSize();

			var columns = nrOfColumns; //find number of columns

			//build the bootstrap class string
			var classStr = "col-xl-" + settings.breakpoints.xl + " col-lg-" + settings.breakpoints.lg + " col-md-"+settings.breakpoints.md + " col-sm-" + settings.breakpoints.sm + " " + settings.columnClasses;

			wrappers = $(this).initialize( columns, classStr ); //create columns"white

			if ( settings.distributeBy.order ) {
				_this.distributeItemsByOrder( wrappers, items); //apply mansory		
			} else if ( settings.distributeBy.height ) {
				_this.distributeItemsByHeight( wrappers, items); //apply mansory
			} else if ( settings.distributeBy.attr ) {
				_this.distributeItemsByAttr( wrappers, _this.orderItemsByAttr(items, settings.distributeBy), settings.distributeBy);
			}
			return { wrappers: wrappers, items: items };
		}



		return this.each(function () {

			var _this = $(this);

			var currentSize = _this.getCurrentColumnSize();

			var numberOfColumns = 12 / settings.breakpoints[currentSize];

			var items = _this.children( (settings.childrenClass != "" ? "."+settings.childrenClass : "div") );

			var wrappers = new Array();

			var returns = _this.apply( settings, numberOfColumns, wrappers, items );
			
			wrappers = returns.wrappers;

			$(window).on("resize", function ( e ) {

				if (_this.getCurrentColumnSize() != currentSize ) {
					numberOfColumns = 12 / settings.breakpoints[_this.getCurrentColumnSize()];
					wrappers = $.emptyArray(wrappers);
					returns = _this.apply( settings , numberOfColumns, wrappers, items);
					wrappers = returns.wrappers;
					currentSize = _this.getCurrentColumnSize();

				}

			});

			if (settings.hasOwnProperty("onload")) {

				//execute on load
				settings.onload( items );

			}

		});
	}

})(jQuery);

引用代码如下

<script>
jQuery(document).ready(function ( $ ) {
  $("#my-gallery-container").mpmansory(
    {
      childrenClass: "item", // default is a div
      columnClasses: "padding", //add classes to items
      breakpoints:{
        xl: 3,
		lg: 4,
		md: 6,
		sm: 12
      },
      distributeBy: { order: false, height: false, attr: "data-order", attrOrder: "asc" }, 
      onload: function (items) {
        //make somthing with items
      } 
    }
  );
});  
</script>

配置参数根据4略微修改了一下,其余的配置参数跟原来的一样。