Roo/bootstrap/LayoutMasonry.js
[roojs1] / Roo / bootstrap / LayoutMasonry.js
1 /**
2  *
3  * This is based on 
4  * http://masonry.desandro.com
5  *
6  * The idea is to render all the bricks based on vertical width...
7  *
8  * The original code extends 'outlayer' - we might need to use that....
9  * 
10  */
11
12
13 /**
14  * @class Roo.bootstrap.LayoutMasonry
15  * @extends Roo.bootstrap.Component
16  * Bootstrap Layout Masonry class
17  * 
18  * @constructor
19  * Create a new Element
20  * @param {Object} config The config object
21  */
22
23 Roo.bootstrap.LayoutMasonry = function(config){
24     Roo.bootstrap.LayoutMasonry.superclass.constructor.call(this, config);
25     
26     this.bricks = [];
27     
28 };
29
30 Roo.extend(Roo.bootstrap.LayoutMasonry, Roo.bootstrap.Component,  {
31     
32     /**
33      * @cfg {Boolean} isLayoutInstant = no animation?
34      */   
35     isLayoutInstant : false, // needed?
36    
37     /**
38      * @cfg {Number} boxWidth  width of the columns
39      */   
40     boxWidth : 450,
41     
42     /**
43      * @cfg {Number} padWidth padding below box..
44      */   
45     padWidth : 10, 
46     
47     /**
48      * @cfg {Number} gutter gutter width..
49      */   
50     gutter : 10, 
51     
52     /**
53      * @cfg {Boolean} isAutoInitial defalut true
54      */   
55     isAutoInitial : true, 
56     
57     containerWidth: 0,
58     
59     /**
60      * @cfg {Boolean} isHorizontal defalut false
61      */   
62     isHorizontal : false, 
63
64     currentSize : null,
65     
66     tag: 'div',
67     
68     cls: '',
69     
70     bricks: null, //CompositeElement
71     
72     cols : 1,
73     
74     _isLayoutInited : false,
75     
76 //    isAlternative : false, // only use for vertical layout...
77     
78     /**
79      * @cfg {Number} alternativePadWidth padding below box..
80      */   
81     alternativePadWidth : 50, 
82     
83     getAutoCreate : function(){
84         
85         var cfg = {
86             tag: this.tag,
87             cls: 'blog-masonary-wrapper ' + this.cls,
88             cn : {
89                 cls : 'mas-boxes masonary'
90             }
91         };
92         
93         return cfg;
94     },
95     
96     getChildContainer: function( )
97     {
98         if (this.boxesEl) {
99             return this.boxesEl;
100         }
101         
102         this.boxesEl = this.el.select('.mas-boxes').first();
103         
104         return this.boxesEl;
105     },
106     
107     
108     initEvents : function()
109     {
110         var _this = this;
111         
112         if(this.isAutoInitial){
113             Roo.log('hook children rendered');
114             this.on('childrenrendered', function() {
115                 Roo.log('children rendered');
116                 _this.initial();
117             } ,this);
118         }
119     },
120     
121     initial : function()
122     {
123         this.currentSize = this.el.getBox(true);
124         
125         Roo.EventManager.onWindowResize(this.resize, this); 
126
127         if(!this.isAutoInitial){
128             this.layout();
129             return;
130         }
131         
132         this.layout();
133         
134         return;
135         //this.layout.defer(500,this);
136         
137     },
138     
139     resize : function()
140     {
141         Roo.log('resize');
142         
143         var cs = this.el.getBox(true);
144         
145         if (this.currentSize.width == cs.width && this.currentSize.x == cs.x ) {
146             Roo.log("no change in with or X");
147             return;
148         }
149         
150         this.currentSize = cs;
151         
152         this.layout();
153         
154     },
155     
156     layout : function()
157     {   
158         this._resetLayout();
159         
160         var isInstant = this.isLayoutInstant !== undefined ? this.isLayoutInstant : !this._isLayoutInited;
161         
162         this.layoutItems( isInstant );
163       
164         this._isLayoutInited = true;
165         
166     },
167     
168     _resetLayout : function()
169     {
170         if(this.isHorizontal){
171             this.horizontalMeasureColumns();
172             return;
173         }
174         
175         this.verticalMeasureColumns();
176         
177     },
178     
179     verticalMeasureColumns : function()
180     {
181         this.getContainerWidth();
182         
183 //        if(Roo.lib.Dom.getViewWidth() < 768 && this.isAlternative){
184 //            this.colWidth = Math.floor(this.containerWidth * 0.8);
185 //            return;
186 //        }
187         
188         var boxWidth = this.boxWidth + this.padWidth;
189         
190         if(this.containerWidth < this.boxWidth){
191             boxWidth = this.containerWidth
192         }
193         
194         var containerWidth = this.containerWidth;
195         
196         var cols = Math.floor(containerWidth / boxWidth);
197         
198         this.cols = Math.max( cols, 1 );
199         
200         var totalBoxWidth = this.cols * boxWidth - this.padWidth;
201         
202         var avail = Math.floor((containerWidth - totalBoxWidth) / this.cols);
203         
204         this.colWidth = boxWidth + avail - this.padWidth;
205         
206         this.unitWidth = Math.floor((this.colWidth - (this.gutter * 2)) / 3);
207     },
208     
209     horizontalMeasureColumns : function()
210     {
211         this.getContainerWidth();
212         
213         var boxWidth = this.boxWidth;
214         
215         if(this.containerWidth < boxWidth){
216             boxWidth = this.containerWidth;
217         }
218         
219         this.unitWidth = Math.floor((boxWidth - (this.gutter * 2)) / 3);
220         
221         this.el.setHeight(boxWidth);
222         
223     },
224     
225     getContainerWidth : function()
226     {
227         this.containerWidth = this.el.getBox(true).width;  //maybe use getComputedWidth
228     },
229     
230     layoutItems : function( isInstant )
231     {
232         var items = Roo.apply([], this.bricks);
233         
234         if(this.isHorizontal){
235             this._horizontalLayoutItems( items , isInstant );
236             return;
237         }
238         
239 //        if(Roo.lib.Dom.getViewWidth() < 768 && this.isAlternative){
240 //            this._verticalAlternativeLayoutItems( items , isInstant );
241 //            return;
242 //        }
243         
244         this._verticalLayoutItems( items , isInstant );
245         
246     },
247     
248     _verticalLayoutItems : function ( items , isInstant)
249     {
250         if ( !items || !items.length ) {
251             return;
252         }
253         
254         var standard = [
255             ['xs', 'xs', 'xs', 'tall'],
256             ['xs', 'xs', 'tall'],
257             ['xs', 'xs', 'sm'],
258             ['xs', 'xs', 'xs'],
259             ['xs', 'tall'],
260             ['xs', 'sm'],
261             ['xs', 'xs'],
262             ['xs'],
263             
264             ['sm', 'xs', 'xs'],
265             ['sm', 'xs'],
266             ['sm'],
267             
268             ['tall', 'xs', 'xs', 'xs'],
269             ['tall', 'xs', 'xs'],
270             ['tall', 'xs'],
271             ['tall']
272         ];
273         
274         var queue = [];
275         
276         var boxes = [];
277         
278         var box = [];
279         
280         Roo.each(items, function(item, k){
281             
282             switch (item.size) {
283                 case 'md' :
284                 case 'md-left' :
285                 case 'md-right' :
286                 case 'wide' :
287                     
288                     if(box.length){
289                         boxes.push(box);
290                         box = [];
291                     }
292                     
293                     boxes.push([item]);
294                     
295                     break;
296                     
297                 case 'xs' :
298                 case 'sm' :
299                 case 'tall' :
300                     
301                     box.push(item);
302                     
303                     break;
304                 default :
305                     break;
306                     
307             }
308             
309         }, this);
310         
311         if(box.length){
312             boxes.push(box);
313             box = [];
314         }
315         
316         var filterPattern = function(box, length)
317         {
318             if(!box.length){
319                 return;
320             }
321             
322             var match = false;
323             
324             var pattern = box.slice(0, length);
325             
326             var format = [];
327             
328             Roo.each(pattern, function(i){
329                 format.push(i.size);
330             }, this);
331             
332             Roo.each(standard, function(s){
333                 
334                 if(String(s) != String(format)){
335                     return;
336                 }
337                 
338                 match = true;
339                 return false;
340                 
341             }, this);
342             
343             if(!match && length == 1){
344                 return;
345             }
346             
347             if(!match){
348                 filterPattern(box, length - 1);
349                 return;
350             }
351                 
352             queue.push(pattern);
353
354             box = box.slice(length, box.length);
355
356             filterPattern(box, 4);
357
358             return;
359             
360         }
361         
362         Roo.each(boxes, function(box, k){
363             
364             if(!box.length){
365                 return;
366             }
367             
368             if(box.length == 1){
369                 queue.push(box);
370                 return;
371             }
372             
373             filterPattern(box, 4);
374             
375         }, this);
376         
377         this._processVerticalLayoutQueue( queue, isInstant );
378         
379     },
380     
381 //    _verticalAlternativeLayoutItems : function( items , isInstant )
382 //    {
383 //        if ( !items || !items.length ) {
384 //            return;
385 //        }
386 //
387 //        this._processVerticalAlternativeLayoutQueue( items, isInstant );
388 //        
389 //    },
390     
391     _horizontalLayoutItems : function ( items , isInstant)
392     {
393         if ( !items || !items.length || items.length < 3) {
394             return;
395         }
396         
397         items.reverse();
398         
399         var eItems = items.slice(0, 3);
400         
401         items = items.slice(3, items.length);
402         
403         var standard = [
404             ['xs', 'xs', 'xs', 'wide'],
405             ['xs', 'xs', 'wide'],
406             ['xs', 'xs', 'sm'],
407             ['xs', 'xs', 'xs'],
408             ['xs', 'wide'],
409             ['xs', 'sm'],
410             ['xs', 'xs'],
411             ['xs'],
412             
413             ['sm', 'xs', 'xs'],
414             ['sm', 'xs'],
415             ['sm'],
416             
417             ['wide', 'xs', 'xs', 'xs'],
418             ['wide', 'xs', 'xs'],
419             ['wide', 'xs'],
420             ['wide']
421         ];
422         
423         var queue = [];
424         
425         var boxes = [];
426         
427         var box = [];
428         
429         Roo.each(items, function(item, k){
430             
431             switch (item.size) {
432                 case 'md' :
433                 case 'md-left' :
434                 case 'md-right' :
435                 case 'tall' :
436                     
437                     if(box.length){
438                         boxes.push(box);
439                         box = [];
440                     }
441                     
442                     boxes.push([item]);
443                     
444                     break;
445                     
446                 case 'xs' :
447                 case 'sm' :
448                 case 'wide' :
449                     
450                     box.push(item);
451                     
452                     break;
453                 default :
454                     break;
455                     
456             }
457             
458         }, this);
459         
460         if(box.length){
461             boxes.push(box);
462             box = [];
463         }
464         
465         var filterPattern = function(box, length)
466         {
467             if(!box.length){
468                 return;
469             }
470             
471             var match = false;
472             
473             var pattern = box.slice(0, length);
474             
475             var format = [];
476             
477             Roo.each(pattern, function(i){
478                 format.push(i.size);
479             }, this);
480             
481             Roo.each(standard, function(s){
482                 
483                 if(String(s) != String(format)){
484                     return;
485                 }
486                 
487                 match = true;
488                 return false;
489                 
490             }, this);
491             
492             if(!match && length == 1){
493                 return;
494             }
495             
496             if(!match){
497                 filterPattern(box, length - 1);
498                 return;
499             }
500                 
501             queue.push(pattern);
502
503             box = box.slice(length, box.length);
504
505             filterPattern(box, 4);
506
507             return;
508             
509         }
510         
511         Roo.each(boxes, function(box, k){
512             
513             if(!box.length){
514                 return;
515             }
516             
517             if(box.length == 1){
518                 queue.push(box);
519                 return;
520             }
521             
522             filterPattern(box, 4);
523             
524         }, this);
525         
526         
527         var prune = [];
528         
529         var pos = this.el.getBox(true);
530         
531         var minX = pos.x;
532         
533         var maxX = pos.right - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
534         
535         var hit_end = false;
536         
537         Roo.each(queue, function(box){
538             
539             if(hit_end){
540                 return;
541             }
542             
543             var mx = 0;
544             
545             Roo.each(box, function(b){
546                 
547                 b.el.setVisibilityMode(Roo.Element.DISPLAY);
548                 b.el.show();
549
550                 mx = Math.max(mx, b.x);
551                 
552             }, this);
553             
554             maxX = maxX - this.unitWidth * mx - this.gutter * (mx - 1) - this.padWidth;
555             
556             
557         }, this);
558         
559         
560         
561         
562         var x = maxX;
563         
564         var queue = [];
565         
566         var box = [];
567         var size = 0;
568         var hit_end = false;
569         
570         Roo.each(items, function(item, k){
571             
572             item.el.setVisibilityMode(Roo.Element.DISPLAY);
573             item.el.show();
574             
575             if(hit_end){
576                 item.el.hide();
577                 return;
578             }
579             
580             if(size + item.y > 3){
581                 queue.push(box);
582                 box = [];
583                 size = 0;
584                 maxX = x;
585             }
586             
587             var width = Math.floor(this.unitWidth * item.x + (this.gutter * (item.x - 1)) + item.el.getPadding('lr'));
588             
589             x = Math.min(x, maxX - width - this.padWidth);
590             
591             if(x < minX){
592                 item.el.hide();
593                 hit_end = true;
594                 return;
595             }
596             
597             size = size + item.y;
598             
599             box.push(item);
600             
601             
602         }, this);
603         
604         if(box.length){
605             queue.push(box);
606         }
607         
608         this._processHorizontalLayoutQueue( queue, eItems, isInstant );
609     },
610     
611     /** Sets position of item in DOM
612     * @param {Element} item
613     * @param {Number} x - horizontal position
614     * @param {Number} y - vertical position
615     * @param {Boolean} isInstant - disables transitions
616     */
617     _processVerticalLayoutQueue : function( queue, isInstant )
618     {
619         var pos = this.el.getBox(true);
620         var x = pos.x;
621         var y = pos.y;
622         var maxY = [];
623         
624         for (var i = 0; i < this.cols; i++){
625             maxY[i] = pos.y;
626         }
627         
628         Roo.each(queue, function(box, k){
629             
630             var col = k % this.cols;
631             
632             Roo.each(box, function(b,kk){
633                 
634                 b.el.position('absolute');
635                 
636                 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
637                 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
638                 
639                 if(b.size == 'md-left' || b.size == 'md-right'){
640                     width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
641                     height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
642                 }
643                 
644                 b.el.setWidth(width);
645                 b.el.setHeight(height);
646                 
647             }, this);
648             
649             for (var i = 0; i < this.cols; i++){
650                 
651                 if(maxY[i] < maxY[col]){
652                     col = i;
653                     continue;
654                 }
655                 
656                 col = Math.min(col, i);
657                 
658             }
659             
660             x = pos.x + col * (this.colWidth + this.padWidth);
661             
662             y = maxY[col];
663             
664             var positions = [];
665             
666             switch (box.length){
667                 case 1 :
668                     positions = this.getVerticalOneBoxColPositions(x, y, box);
669                     break;
670                 case 2 :
671                     positions = this.getVerticalTwoBoxColPositions(x, y, box);
672                     break;
673                 case 3 :
674                     positions = this.getVerticalThreeBoxColPositions(x, y, box);
675                     break;
676                 case 4 :
677                     positions = this.getVerticalFourBoxColPositions(x, y, box);
678                     break;
679                 default :
680                     break;
681             }
682             
683             Roo.each(box, function(b,kk){
684                 
685                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
686                 
687                 var sz = b.el.getSize();
688                 
689                 maxY[col] = Math.max(maxY[col], positions[kk].y + sz.height + this.padWidth);
690                 
691             }, this);
692             
693         }, this);
694         
695         var mY = 0;
696         
697         for (var i = 0; i < this.cols; i++){
698             mY = Math.max(mY, maxY[i]);
699         }
700         
701         this.el.setHeight(mY - pos.y);
702         
703     },
704     
705 //    _processVerticalAlternativeLayoutQueue : function( items, isInstant )
706 //    {
707 //        var pos = this.el.getBox(true);
708 //        var x = pos.x;
709 //        var y = pos.y;
710 //        var maxX = pos.right;
711 //        
712 //        var maxHeight = 0;
713 //        
714 //        Roo.each(items, function(item, k){
715 //            
716 //            var c = k % 2;
717 //            
718 //            item.el.position('absolute');
719 //                
720 //            var width = Math.floor(this.colWidth + item.el.getPadding('lr'));
721 //
722 //            item.el.setWidth(width);
723 //
724 //            var height = Math.floor(this.colWidth * item.y / item.x + item.el.getPadding('tb'));
725 //
726 //            item.el.setHeight(height);
727 //            
728 //            if(c == 0){
729 //                item.el.setXY([x, y], isInstant ? false : true);
730 //            } else {
731 //                item.el.setXY([maxX - width, y], isInstant ? false : true);
732 //            }
733 //            
734 //            y = y + height + this.alternativePadWidth;
735 //            
736 //            maxHeight = maxHeight + height + this.alternativePadWidth;
737 //            
738 //        }, this);
739 //        
740 //        this.el.setHeight(maxHeight);
741 //        
742 //    },
743     
744     _processHorizontalLayoutQueue : function( queue, eItems, isInstant )
745     {
746         var pos = this.el.getBox(true);
747         
748         var minX = pos.x;
749         var minY = pos.y;
750         
751         var maxX = pos.right;
752         
753         this._processHorizontalEndItem(eItems, maxX, minX, minY, isInstant);
754         
755         var maxX = maxX - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
756         
757         Roo.each(queue, function(box, k){
758             
759             Roo.each(box, function(b, kk){
760                 
761                 b.el.position('absolute');
762                 
763                 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
764                 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
765                 
766                 if(b.size == 'md-left' || b.size == 'md-right'){
767                     width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
768                     height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
769                 }
770                 
771                 b.el.setWidth(width);
772                 b.el.setHeight(height);
773                 
774             }, this);
775             
776             if(!box.length){
777                 return;
778             }
779             
780             var positions = [];
781             
782             switch (box.length){
783                 case 1 :
784                     positions = this.getHorizontalOneBoxColPositions(maxX, minY, box);
785                     break;
786                 case 2 :
787                     positions = this.getHorizontalTwoBoxColPositions(maxX, minY, box);
788                     break;
789                 case 3 :
790                     positions = this.getHorizontalThreeBoxColPositions(maxX, minY, box);
791                     break;
792                 default :
793                     break;
794             }
795             
796             Roo.each(box, function(b,kk){
797                 
798                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
799                 
800                 maxX = Math.min(maxX, positions[kk].x - this.padWidth);
801                 
802             }, this);
803             
804         }, this);
805         
806     },
807     
808     _processHorizontalEndItem : function(eItems, maxX, minX, minY, isInstant)
809     {
810         Roo.each(eItems, function(b,k){
811             
812             b.size = (k == 0) ? 'sm' : 'xs';
813             b.x = (k == 0) ? 2 : 1;
814             b.y = (k == 0) ? 2 : 1;
815             
816             b.el.position('absolute');
817             
818             var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
819                 
820             b.el.setWidth(width);
821             
822             var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
823             
824             b.el.setHeight(height);
825             
826         }, this);
827
828         var positions = [];
829         
830         positions.push({
831             x : maxX - this.unitWidth * 2 - this.gutter,
832             y : minY
833         });
834         
835         positions.push({
836             x : maxX - this.unitWidth,
837             y : minY + (this.unitWidth + this.gutter) * 2
838         });
839         
840         positions.push({
841             x : maxX - this.unitWidth * 3 - this.gutter * 2,
842             y : minY
843         });
844         
845         Roo.each(eItems, function(b,k){
846             
847             b.el.setXY([positions[k].x, positions[k].y], isInstant ? false : true);
848
849         }, this);
850         
851     },
852     
853     getVerticalOneBoxColPositions : function(x, y, box)
854     {
855         var pos = [];
856         
857         var rand = Math.floor(Math.random() * ((4 - box[0].x)));
858         
859         if(box[0].size == 'md-left'){
860             rand = 0;
861         }
862         
863         if(box[0].size == 'md-right'){
864             rand = 1;
865         }
866         
867         pos.push({
868             x : x + (this.unitWidth + this.gutter) * rand,
869             y : y
870         });
871         
872         return pos;
873     },
874     
875     getVerticalTwoBoxColPositions : function(x, y, box)
876     {
877         var pos = [];
878         
879         if(box[0].size == 'xs'){
880             
881             pos.push({
882                 x : x,
883                 y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[1].y))
884             });
885
886             pos.push({
887                 x : x + (this.unitWidth + this.gutter) * (3 - box[1].x),
888                 y : y
889             });
890             
891             return pos;
892             
893         }
894         
895         pos.push({
896             x : x,
897             y : y
898         });
899
900         pos.push({
901             x : x + (this.unitWidth + this.gutter) * 2,
902             y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[0].y))
903         });
904         
905         return pos;
906         
907     },
908     
909     getVerticalThreeBoxColPositions : function(x, y, box)
910     {
911         var pos = [];
912         
913         if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
914             
915             pos.push({
916                 x : x,
917                 y : y
918             });
919
920             pos.push({
921                 x : x + (this.unitWidth + this.gutter) * 1,
922                 y : y
923             });
924             
925             pos.push({
926                 x : x + (this.unitWidth + this.gutter) * 2,
927                 y : y
928             });
929             
930             return pos;
931             
932         }
933         
934         if(box[0].size == 'xs' && box[1].size == 'xs'){
935             
936             pos.push({
937                 x : x,
938                 y : y
939             });
940
941             pos.push({
942                 x : x,
943                 y : y + ((this.unitWidth + this.gutter) * (box[2].y - 1))
944             });
945             
946             pos.push({
947                 x : x + (this.unitWidth + this.gutter) * 1,
948                 y : y
949             });
950             
951             return pos;
952             
953         }
954         
955         pos.push({
956             x : x,
957             y : y
958         });
959
960         pos.push({
961             x : x + (this.unitWidth + this.gutter) * 2,
962             y : y
963         });
964
965         pos.push({
966             x : x + (this.unitWidth + this.gutter) * 2,
967             y : y + (this.unitWidth + this.gutter) * (box[0].y - 1)
968         });
969             
970         return pos;
971         
972     },
973     
974     getVerticalFourBoxColPositions : function(x, y, box)
975     {
976         var pos = [];
977         
978         if(box[0].size == 'xs'){
979             
980             pos.push({
981                 x : x,
982                 y : y
983             });
984
985             pos.push({
986                 x : x,
987                 y : y + (this.unitWidth + this.gutter) * 1
988             });
989             
990             pos.push({
991                 x : x,
992                 y : y + (this.unitWidth + this.gutter) * 2
993             });
994             
995             pos.push({
996                 x : x + (this.unitWidth + this.gutter) * 1,
997                 y : y
998             });
999             
1000             return pos;
1001             
1002         }
1003         
1004         pos.push({
1005             x : x,
1006             y : y
1007         });
1008
1009         pos.push({
1010             x : x + (this.unitWidth + this.gutter) * 2,
1011             y : y
1012         });
1013
1014         pos.push({
1015             x : x + (this.unitWidth + this.gutter) * 2,
1016             y : y + (this.unitWidth + this.gutter) * 1
1017         });
1018
1019         pos.push({
1020             x : x + (this.unitWidth + this.gutter) * 2,
1021             y : y + (this.unitWidth + this.gutter) * 2
1022         });
1023
1024         return pos;
1025         
1026     },
1027     
1028     getHorizontalOneBoxColPositions : function(maxX, minY, box)
1029     {
1030         var pos = [];
1031         
1032         if(box[0].size == 'md-left'){
1033             pos.push({
1034                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1035                 y : minY
1036             });
1037             
1038             return pos;
1039         }
1040         
1041         if(box[0].size == 'md-right'){
1042             pos.push({
1043                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1044                 y : minY + (this.unitWidth + this.gutter) * 1
1045             });
1046             
1047             return pos;
1048         }
1049         
1050         var rand = Math.floor(Math.random() * (4 - box[0].y));
1051         
1052         pos.push({
1053             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1054             y : minY + (this.unitWidth + this.gutter) * rand
1055         });
1056         
1057         return pos;
1058         
1059     },
1060     
1061     getHorizontalTwoBoxColPositions : function(maxX, minY, box)
1062     {
1063         var pos = [];
1064         
1065         pos.push({
1066             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1067             y : minY
1068         });
1069
1070         pos.push({
1071             x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1072             y : minY + (this.unitWidth + this.gutter) * (3 - box[1].y)
1073         });
1074         
1075         return pos;
1076         
1077     },
1078     
1079     getHorizontalThreeBoxColPositions : function(maxX, minY, box)
1080     {
1081         var pos = [];
1082         
1083         pos.push({
1084             x : maxX - this.unitWidth,
1085             y : minY
1086         });
1087         
1088         pos.push({
1089             x : maxX - this.unitWidth,
1090             y : minY - this.unitWidth - this.gutter
1091         });
1092         
1093         pos.push({
1094             x : maxX - this.unitWidth,
1095             y : minY - (this.unitWidth + this.gutter) * 2
1096         });
1097         
1098         return pos;
1099         
1100     }
1101     
1102 });
1103
1104  
1105
1106