4 * http://masonry.desandro.com
6 * The idea is to render all the bricks based on vertical width...
8 * The original code extends 'outlayer' - we might need to use that....
14 * @class Roo.bootstrap.LayoutMasonry
15 * @extends Roo.bootstrap.Component
16 * Bootstrap Layout Masonry class
19 * Create a new Element
20 * @param {Object} config The config object
23 Roo.bootstrap.LayoutMasonry = function(config){
24 Roo.bootstrap.LayoutMasonry.superclass.constructor.call(this, config);
30 Roo.extend(Roo.bootstrap.LayoutMasonry, Roo.bootstrap.Component, {
33 * @cfg {Boolean} isLayoutInstant = no animation?
35 isLayoutInstant : false, // needed?
38 * @cfg {Number} boxWidth width of the columns
43 * @cfg {Number} padWidth padding below box..
48 * @cfg {Number} gutter gutter width..
53 * @cfg {Boolean} isAutoInitial defalut true
60 * @cfg {Boolean} isHorizontal defalut false
70 bricks: null, //CompositeElement
74 _isLayoutInited : false,
76 // isAlternative : false, // only use for vertical layout...
79 * @cfg {Number} alternativePadWidth padding below box..
81 alternativePadWidth : 50,
83 getAutoCreate : function(){
87 cls: 'blog-masonary-wrapper ' + this.cls,
89 cls : 'mas-boxes masonary'
96 getChildContainer: function( )
102 this.boxesEl = this.el.select('.mas-boxes').first();
108 initEvents : function()
112 if(this.isAutoInitial){
113 Roo.log('hook children rendered');
114 this.on('childrenrendered', function() {
115 Roo.log('children rendered');
123 this.currentSize = this.el.getBox(true);
125 Roo.EventManager.onWindowResize(this.resize, this);
127 if(!this.isAutoInitial){
135 //this.layout.defer(500,this);
143 var cs = this.el.getBox(true);
145 if (this.currentSize.width == cs.width && this.currentSize.x == cs.x ) {
146 Roo.log("no change in with or X");
150 this.currentSize = cs;
160 var isInstant = this.isLayoutInstant !== undefined ? this.isLayoutInstant : !this._isLayoutInited;
162 this.layoutItems( isInstant );
164 this._isLayoutInited = true;
168 _resetLayout : function()
170 if(this.isHorizontal){
171 this.horizontalMeasureColumns();
175 this.verticalMeasureColumns();
179 verticalMeasureColumns : function()
181 this.getContainerWidth();
183 // if(Roo.lib.Dom.getViewWidth() < 768 && this.isAlternative){
184 // this.colWidth = Math.floor(this.containerWidth * 0.8);
188 var boxWidth = this.boxWidth + this.padWidth;
190 if(this.containerWidth < this.boxWidth){
191 boxWidth = this.containerWidth
194 var containerWidth = this.containerWidth;
196 var cols = Math.floor(containerWidth / boxWidth);
198 this.cols = Math.max( cols, 1 );
200 var totalBoxWidth = this.cols * boxWidth - this.padWidth;
202 var avail = Math.floor((containerWidth - totalBoxWidth) / this.cols);
204 this.colWidth = boxWidth + avail - this.padWidth;
206 this.unitWidth = Math.floor((this.colWidth - (this.gutter * 2)) / 3);
207 this.unitHeight = this.boxHeight > 0 ? this.boxHeight : this.unitWidth;
210 horizontalMeasureColumns : function()
212 this.getContainerWidth();
214 var boxWidth = this.boxWidth;
216 if(this.containerWidth < boxWidth){
217 boxWidth = this.containerWidth;
220 this.unitWidth = Math.floor((boxWidth - (this.gutter * 2)) / 3);
222 this.el.setHeight(boxWidth);
226 getContainerWidth : function()
228 this.containerWidth = this.el.getBox(true).width; //maybe use getComputedWidth
231 layoutItems : function( isInstant )
233 var items = Roo.apply([], this.bricks);
235 if(this.isHorizontal){
236 this._horizontalLayoutItems( items , isInstant );
240 // if(Roo.lib.Dom.getViewWidth() < 768 && this.isAlternative){
241 // this._verticalAlternativeLayoutItems( items , isInstant );
245 this._verticalLayoutItems( items , isInstant );
249 _verticalLayoutItems : function ( items , isInstant)
251 if ( !items || !items.length ) {
256 ['xs', 'xs', 'xs', 'tall'],
257 ['xs', 'xs', 'tall'],
269 ['tall', 'xs', 'xs', 'xs'],
270 ['tall', 'xs', 'xs'],
284 Roo.each(items, function(item, k){
287 // these layouts take up a full box,
321 var filterPattern = function(box, length)
329 var pattern = box.slice(0, length);
333 Roo.each(pattern, function(i){
337 Roo.each(standard, function(s){
339 if(String(s) != String(format)){
348 if(!match && length == 1){
353 filterPattern(box, length - 1);
359 box = box.slice(length, box.length);
361 filterPattern(box, 4);
367 Roo.each(boxes, function(box, k){
378 filterPattern(box, 4);
382 this._processVerticalLayoutQueue( queue, isInstant );
386 // _verticalAlternativeLayoutItems : function( items , isInstant )
388 // if ( !items || !items.length ) {
392 // this._processVerticalAlternativeLayoutQueue( items, isInstant );
396 _horizontalLayoutItems : function ( items , isInstant)
398 if ( !items || !items.length || items.length < 3) {
404 var eItems = items.slice(0, 3);
406 items = items.slice(3, items.length);
409 ['xs', 'xs', 'xs', 'wide'],
410 ['xs', 'xs', 'wide'],
422 ['wide', 'xs', 'xs', 'xs'],
423 ['wide', 'xs', 'xs'],
436 Roo.each(items, function(item, k){
473 var filterPattern = function(box, length)
481 var pattern = box.slice(0, length);
485 Roo.each(pattern, function(i){
489 Roo.each(standard, function(s){
491 if(String(s) != String(format)){
500 if(!match && length == 1){
505 filterPattern(box, length - 1);
511 box = box.slice(length, box.length);
513 filterPattern(box, 4);
519 Roo.each(boxes, function(box, k){
530 filterPattern(box, 4);
537 var pos = this.el.getBox(true);
541 var maxX = pos.right - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
545 Roo.each(queue, function(box){
549 Roo.each(box, function(b){
551 b.el.setVisibilityMode(Roo.Element.DISPLAY);
561 Roo.each(box, function(b){
563 b.el.setVisibilityMode(Roo.Element.DISPLAY);
566 mx = Math.max(mx, b.x);
570 maxX = maxX - this.unitWidth * mx - this.gutter * (mx - 1) - this.padWidth;
574 Roo.each(box, function(b){
576 b.el.setVisibilityMode(Roo.Element.DISPLAY);
590 this._processHorizontalLayoutQueue( prune, eItems, isInstant );
593 /** Sets position of item in DOM
594 * @param {Element} item
595 * @param {Number} x - horizontal position
596 * @param {Number} y - vertical position
597 * @param {Boolean} isInstant - disables transitions
599 _processVerticalLayoutQueue : function( queue, isInstant )
601 var pos = this.el.getBox(true);
606 for (var i = 0; i < this.cols; i++){
610 Roo.each(queue, function(box, k){
612 var col = k % this.cols;
614 Roo.each(box, function(b,kk){
616 b.el.position('absolute');
618 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
619 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
621 if(b.size == 'md-left' || b.size == 'md-right'){
622 width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
623 height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
626 b.el.setWidth(width);
627 b.el.setHeight(height);
631 for (var i = 0; i < this.cols; i++){
633 if(maxY[i] < maxY[col]){
638 col = Math.min(col, i);
642 x = pos.x + col * (this.colWidth + this.padWidth);
650 positions = this.getVerticalOneBoxColPositions(x, y, box);
653 positions = this.getVerticalTwoBoxColPositions(x, y, box);
656 positions = this.getVerticalThreeBoxColPositions(x, y, box);
659 positions = this.getVerticalFourBoxColPositions(x, y, box);
665 Roo.each(box, function(b,kk){
667 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
669 var sz = b.el.getSize();
671 maxY[col] = Math.max(maxY[col], positions[kk].y + sz.height + this.padWidth);
679 for (var i = 0; i < this.cols; i++){
680 mY = Math.max(mY, maxY[i]);
683 this.el.setHeight(mY - pos.y);
687 // _processVerticalAlternativeLayoutQueue : function( items, isInstant )
689 // var pos = this.el.getBox(true);
692 // var maxX = pos.right;
694 // var maxHeight = 0;
696 // Roo.each(items, function(item, k){
700 // item.el.position('absolute');
702 // var width = Math.floor(this.colWidth + item.el.getPadding('lr'));
704 // item.el.setWidth(width);
706 // var height = Math.floor(this.colWidth * item.y / item.x + item.el.getPadding('tb'));
708 // item.el.setHeight(height);
711 // item.el.setXY([x, y], isInstant ? false : true);
713 // item.el.setXY([maxX - width, y], isInstant ? false : true);
716 // y = y + height + this.alternativePadWidth;
718 // maxHeight = maxHeight + height + this.alternativePadWidth;
722 // this.el.setHeight(maxHeight);
726 _processHorizontalLayoutQueue : function( queue, eItems, isInstant )
728 var pos = this.el.getBox(true);
733 var maxX = pos.right;
735 this._processHorizontalEndItem(eItems, maxX, minX, minY, isInstant);
737 var maxX = maxX - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
739 Roo.each(queue, function(box, k){
741 Roo.each(box, function(b, kk){
743 b.el.position('absolute');
745 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
746 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
748 if(b.size == 'md-left' || b.size == 'md-right'){
749 width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
750 height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
753 b.el.setWidth(width);
754 b.el.setHeight(height);
766 positions = this.getHorizontalOneBoxColPositions(maxX, minY, box);
769 positions = this.getHorizontalTwoBoxColPositions(maxX, minY, box);
772 positions = this.getHorizontalThreeBoxColPositions(maxX, minY, box);
775 positions = this.getHorizontalFourBoxColPositions(maxX, minY, box);
781 Roo.each(box, function(b,kk){
783 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
785 maxX = Math.min(maxX, positions[kk].x - this.padWidth);
793 _processHorizontalEndItem : function(eItems, maxX, minX, minY, isInstant)
795 Roo.each(eItems, function(b,k){
797 b.size = (k == 0) ? 'sm' : 'xs';
798 b.x = (k == 0) ? 2 : 1;
799 b.y = (k == 0) ? 2 : 1;
801 b.el.position('absolute');
803 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
805 b.el.setWidth(width);
807 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
809 b.el.setHeight(height);
816 x : maxX - this.unitWidth * 2 - this.gutter,
821 x : maxX - this.unitWidth,
822 y : minY + (this.unitWidth + this.gutter) * 2
826 x : maxX - this.unitWidth * 3 - this.gutter * 2,
830 Roo.each(eItems, function(b,k){
832 b.el.setXY([positions[k].x, positions[k].y], isInstant ? false : true);
838 getVerticalOneBoxColPositions : function(x, y, box)
842 var rand = Math.floor(Math.random() * ((4 - box[0].x)));
844 if(box[0].size == 'md-left'){
848 if(box[0].size == 'md-right'){
853 x : x + (this.unitWidth + this.gutter) * rand,
860 getVerticalTwoBoxColPositions : function(x, y, box)
864 if(box[0].size == 'xs'){
868 y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[1].y))
872 x : x + (this.unitWidth + this.gutter) * (3 - box[1].x),
886 x : x + (this.unitWidth + this.gutter) * 2,
887 y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[0].y))
894 getVerticalThreeBoxColPositions : function(x, y, box)
898 if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
906 x : x + (this.unitWidth + this.gutter) * 1,
911 x : x + (this.unitWidth + this.gutter) * 2,
919 if(box[0].size == 'xs' && box[1].size == 'xs'){
928 y : y + ((this.unitWidth + this.gutter) * (box[2].y - 1))
932 x : x + (this.unitWidth + this.gutter) * 1,
946 x : x + (this.unitWidth + this.gutter) * 2,
951 x : x + (this.unitWidth + this.gutter) * 2,
952 y : y + (this.unitWidth + this.gutter) * (box[0].y - 1)
959 getVerticalFourBoxColPositions : function(x, y, box)
963 if(box[0].size == 'xs'){
972 y : y + (this.unitWidth + this.gutter) * 1
977 y : y + (this.unitWidth + this.gutter) * 2
981 x : x + (this.unitWidth + this.gutter) * 1,
995 x : x + (this.unitWidth + this.gutter) * 2,
1000 x : x + (this.unitWidth + this.gutter) * 2,
1001 y : y + (this.unitWidth + this.gutter) * 1
1005 x : x + (this.unitWidth + this.gutter) * 2,
1006 y : y + (this.unitWidth + this.gutter) * 2
1013 getHorizontalOneBoxColPositions : function(maxX, minY, box)
1017 if(box[0].size == 'md-left'){
1019 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1026 if(box[0].size == 'md-right'){
1028 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1029 y : minY + (this.unitWidth + this.gutter) * 1
1035 var rand = Math.floor(Math.random() * (4 - box[0].y));
1038 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1039 y : minY + (this.unitWidth + this.gutter) * rand
1046 getHorizontalTwoBoxColPositions : function(maxX, minY, box)
1050 if(box[0].size == 'xs'){
1053 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1058 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1059 y : minY + (this.unitWidth + this.gutter) * (3 - box[1].y)
1067 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1072 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1073 y : minY + (this.unitWidth + this.gutter) * 2
1080 getHorizontalThreeBoxColPositions : function(maxX, minY, box)
1084 if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
1087 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1092 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1093 y : minY + (this.unitWidth + this.gutter) * 1
1097 x : maxX - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1098 y : minY + (this.unitWidth + this.gutter) * 2
1105 if(box[0].size == 'xs' && box[1].size == 'xs'){
1108 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1113 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1) - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1118 x : maxX - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1119 y : minY + (this.unitWidth + this.gutter) * 1
1127 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1132 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1133 y : minY + (this.unitWidth + this.gutter) * 2
1137 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1) - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1138 y : minY + (this.unitWidth + this.gutter) * 2
1145 getHorizontalFourBoxColPositions : function(maxX, minY, box)
1149 if(box[0].size == 'xs'){
1152 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1157 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1) - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1162 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1) - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1) - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1167 x : maxX - this.unitWidth * box[3].x - this.gutter * (box[3].x - 1),
1168 y : minY + (this.unitWidth + this.gutter) * 1
1176 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1181 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1182 y : minY + (this.unitWidth + this.gutter) * 2
1186 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1) - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1187 y : minY + (this.unitWidth + this.gutter) * 2
1191 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1) - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1) - this.unitWidth * box[3].x - this.gutter * (box[3].x - 1),
1192 y : minY + (this.unitWidth + this.gutter) * 2