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         this.unitHeight = this.boxHeight > 0 ? this.boxHeight  : this.unitWidth;
208     },
209     
210     horizontalMeasureColumns : function()
211     {
212         this.getContainerWidth();
213         
214         var boxWidth = this.boxWidth;
215         
216         if(this.containerWidth < boxWidth){
217             boxWidth = this.containerWidth;
218         }
219         
220         this.unitWidth = Math.floor((boxWidth - (this.gutter * 2)) / 3);
221         
222         this.el.setHeight(boxWidth);
223         
224     },
225     
226     getContainerWidth : function()
227     {
228         this.containerWidth = this.el.getBox(true).width;  //maybe use getComputedWidth
229     },
230     
231     layoutItems : function( isInstant )
232     {
233         var items = Roo.apply([], this.bricks);
234         
235         if(this.isHorizontal){
236             this._horizontalLayoutItems( items , isInstant );
237             return;
238         }
239         
240 //        if(Roo.lib.Dom.getViewWidth() < 768 && this.isAlternative){
241 //            this._verticalAlternativeLayoutItems( items , isInstant );
242 //            return;
243 //        }
244         
245         this._verticalLayoutItems( items , isInstant );
246         
247     },
248     
249     _verticalLayoutItems : function ( items , isInstant)
250     {
251         if ( !items || !items.length ) {
252             return;
253         }
254         
255         var standard = [
256             ['xs', 'xs', 'xs', 'tall'],
257             ['xs', 'xs', 'tall'],
258             ['xs', 'xs', 'sm'],
259             ['xs', 'xs', 'xs'],
260             ['xs', 'tall'],
261             ['xs', 'sm'],
262             ['xs', 'xs'],
263             ['xs'],
264             
265             ['sm', 'xs', 'xs'],
266             ['sm', 'xs'],
267             ['sm'],
268             
269             ['tall', 'xs', 'xs', 'xs'],
270             ['tall', 'xs', 'xs'],
271             ['tall', 'xs'],
272             ['tall'],
273             
274             
275             
276         ];
277         
278         var queue = [];
279         
280         var boxes = [];
281         
282         var box = [];
283         
284         Roo.each(items, function(item, k){
285             
286             switch (item.size) {
287                 // these layouts take up a full box,
288                 case 'md' :
289                 case 'md-left' :
290                 case 'md-right' :
291                 case 'wide' :
292                     
293                     if(box.length){
294                         boxes.push(box);
295                         box = [];
296                     }
297                     
298                     boxes.push([item]);
299                     
300                     break;
301                     
302                 case 'xs' :
303                 case 'sm' :
304                 case 'tall' :
305                     
306                     box.push(item);
307                     
308                     break;
309                 default :
310                     break;
311                     
312             }
313             
314         }, this);
315         
316         if(box.length){
317             boxes.push(box);
318             box = [];
319         }
320         
321         var filterPattern = function(box, length)
322         {
323             if(!box.length){
324                 return;
325             }
326             
327             var match = false;
328             
329             var pattern = box.slice(0, length);
330             
331             var format = [];
332             
333             Roo.each(pattern, function(i){
334                 format.push(i.size);
335             }, this);
336             
337             Roo.each(standard, function(s){
338                 
339                 if(String(s) != String(format)){
340                     return;
341                 }
342                 
343                 match = true;
344                 return false;
345                 
346             }, this);
347             
348             if(!match && length == 1){
349                 return;
350             }
351             
352             if(!match){
353                 filterPattern(box, length - 1);
354                 return;
355             }
356                 
357             queue.push(pattern);
358
359             box = box.slice(length, box.length);
360
361             filterPattern(box, 4);
362
363             return;
364             
365         }
366         
367         Roo.each(boxes, function(box, k){
368             
369             if(!box.length){
370                 return;
371             }
372             
373             if(box.length == 1){
374                 queue.push(box);
375                 return;
376             }
377             
378             filterPattern(box, 4);
379             
380         }, this);
381         
382         this._processVerticalLayoutQueue( queue, isInstant );
383         
384     },
385     
386 //    _verticalAlternativeLayoutItems : function( items , isInstant )
387 //    {
388 //        if ( !items || !items.length ) {
389 //            return;
390 //        }
391 //
392 //        this._processVerticalAlternativeLayoutQueue( items, isInstant );
393 //        
394 //    },
395     
396     _horizontalLayoutItems : function ( items , isInstant)
397     {
398         if ( !items || !items.length || items.length < 3) {
399             return;
400         }
401         
402         items.reverse();
403         
404         var eItems = items.slice(0, 3);
405         
406         items = items.slice(3, items.length);
407         
408         var standard = [
409             ['xs', 'xs', 'xs', 'wide'],
410             ['xs', 'xs', 'wide'],
411             ['xs', 'xs', 'sm'],
412             ['xs', 'xs', 'xs'],
413             ['xs', 'wide'],
414             ['xs', 'sm'],
415             ['xs', 'xs'],
416             ['xs'],
417             
418             ['sm', 'xs', 'xs'],
419             ['sm', 'xs'],
420             ['sm'],
421             
422             ['wide', 'xs', 'xs', 'xs'],
423             ['wide', 'xs', 'xs'],
424             ['wide', 'xs'],
425             ['wide'],
426             
427             ['wide-thin']
428         ];
429         
430         var queue = [];
431         
432         var boxes = [];
433         
434         var box = [];
435         
436         Roo.each(items, function(item, k){
437             
438             switch (item.size) {
439                 case 'md' :
440                 case 'md-left' :
441                 case 'md-right' :
442                 case 'tall' :
443                     
444                     if(box.length){
445                         boxes.push(box);
446                         box = [];
447                     }
448                     
449                     boxes.push([item]);
450                     
451                     break;
452                     
453                 case 'xs' :
454                 case 'sm' :
455                 case 'wide' :
456                 case 'wide-thin' :
457                     
458                     box.push(item);
459                     
460                     break;
461                 default :
462                     break;
463                     
464             }
465             
466         }, this);
467         
468         if(box.length){
469             boxes.push(box);
470             box = [];
471         }
472         
473         var filterPattern = function(box, length)
474         {
475             if(!box.length){
476                 return;
477             }
478             
479             var match = false;
480             
481             var pattern = box.slice(0, length);
482             
483             var format = [];
484             
485             Roo.each(pattern, function(i){
486                 format.push(i.size);
487             }, this);
488             
489             Roo.each(standard, function(s){
490                 
491                 if(String(s) != String(format)){
492                     return;
493                 }
494                 
495                 match = true;
496                 return false;
497                 
498             }, this);
499             
500             if(!match && length == 1){
501                 return;
502             }
503             
504             if(!match){
505                 filterPattern(box, length - 1);
506                 return;
507             }
508                 
509             queue.push(pattern);
510
511             box = box.slice(length, box.length);
512
513             filterPattern(box, 4);
514
515             return;
516             
517         }
518         
519         Roo.each(boxes, function(box, k){
520             
521             if(!box.length){
522                 return;
523             }
524             
525             if(box.length == 1){
526                 queue.push(box);
527                 return;
528             }
529             
530             filterPattern(box, 4);
531             
532         }, this);
533         
534         
535         var prune = [];
536         
537         var pos = this.el.getBox(true);
538         
539         var minX = pos.x;
540         
541         var maxX = pos.right - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
542         
543         var hit_end = false;
544         
545         Roo.each(queue, function(box){
546             
547             if(hit_end){
548                 
549                 Roo.each(box, function(b){
550                 
551                     b.el.setVisibilityMode(Roo.Element.DISPLAY);
552                     b.el.hide();
553
554                 }, this);
555
556                 return;
557             }
558             
559             var mx = 0;
560             
561             Roo.each(box, function(b){
562                 
563                 b.el.setVisibilityMode(Roo.Element.DISPLAY);
564                 b.el.show();
565
566                 mx = Math.max(mx, b.x);
567                 
568             }, this);
569             
570             maxX = maxX - this.unitWidth * mx - this.gutter * (mx - 1) - this.padWidth;
571             
572             if(maxX < minX){
573                 
574                 Roo.each(box, function(b){
575                 
576                     b.el.setVisibilityMode(Roo.Element.DISPLAY);
577                     b.el.hide();
578                     
579                 }, this);
580                 
581                 hit_end = true;
582                 
583                 return;
584             }
585             
586             prune.push(box);
587             
588         }, this);
589         
590         this._processHorizontalLayoutQueue( prune, eItems, isInstant );
591     },
592     
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
598     */
599     _processVerticalLayoutQueue : function( queue, isInstant )
600     {
601         var pos = this.el.getBox(true);
602         var x = pos.x;
603         var y = pos.y;
604         var maxY = [];
605         
606         for (var i = 0; i < this.cols; i++){
607             maxY[i] = pos.y;
608         }
609         
610         Roo.each(queue, function(box, k){
611             
612             var col = k % this.cols;
613             
614             Roo.each(box, function(b,kk){
615                 
616                 b.el.position('absolute');
617                 
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'));
620                 
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'));
624                 }
625                 
626                 b.el.setWidth(width);
627                 b.el.setHeight(height);
628                 
629             }, this);
630             
631             for (var i = 0; i < this.cols; i++){
632                 
633                 if(maxY[i] < maxY[col]){
634                     col = i;
635                     continue;
636                 }
637                 
638                 col = Math.min(col, i);
639                 
640             }
641             
642             x = pos.x + col * (this.colWidth + this.padWidth);
643             
644             y = maxY[col];
645             
646             var positions = [];
647             
648             switch (box.length){
649                 case 1 :
650                     positions = this.getVerticalOneBoxColPositions(x, y, box);
651                     break;
652                 case 2 :
653                     positions = this.getVerticalTwoBoxColPositions(x, y, box);
654                     break;
655                 case 3 :
656                     positions = this.getVerticalThreeBoxColPositions(x, y, box);
657                     break;
658                 case 4 :
659                     positions = this.getVerticalFourBoxColPositions(x, y, box);
660                     break;
661                 default :
662                     break;
663             }
664             
665             Roo.each(box, function(b,kk){
666                 
667                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
668                 
669                 var sz = b.el.getSize();
670                 
671                 maxY[col] = Math.max(maxY[col], positions[kk].y + sz.height + this.padWidth);
672                 
673             }, this);
674             
675         }, this);
676         
677         var mY = 0;
678         
679         for (var i = 0; i < this.cols; i++){
680             mY = Math.max(mY, maxY[i]);
681         }
682         
683         this.el.setHeight(mY - pos.y);
684         
685     },
686     
687 //    _processVerticalAlternativeLayoutQueue : function( items, isInstant )
688 //    {
689 //        var pos = this.el.getBox(true);
690 //        var x = pos.x;
691 //        var y = pos.y;
692 //        var maxX = pos.right;
693 //        
694 //        var maxHeight = 0;
695 //        
696 //        Roo.each(items, function(item, k){
697 //            
698 //            var c = k % 2;
699 //            
700 //            item.el.position('absolute');
701 //                
702 //            var width = Math.floor(this.colWidth + item.el.getPadding('lr'));
703 //
704 //            item.el.setWidth(width);
705 //
706 //            var height = Math.floor(this.colWidth * item.y / item.x + item.el.getPadding('tb'));
707 //
708 //            item.el.setHeight(height);
709 //            
710 //            if(c == 0){
711 //                item.el.setXY([x, y], isInstant ? false : true);
712 //            } else {
713 //                item.el.setXY([maxX - width, y], isInstant ? false : true);
714 //            }
715 //            
716 //            y = y + height + this.alternativePadWidth;
717 //            
718 //            maxHeight = maxHeight + height + this.alternativePadWidth;
719 //            
720 //        }, this);
721 //        
722 //        this.el.setHeight(maxHeight);
723 //        
724 //    },
725     
726     _processHorizontalLayoutQueue : function( queue, eItems, isInstant )
727     {
728         var pos = this.el.getBox(true);
729         
730         var minX = pos.x;
731         var minY = pos.y;
732         
733         var maxX = pos.right;
734         
735         this._processHorizontalEndItem(eItems, maxX, minX, minY, isInstant);
736         
737         var maxX = maxX - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
738         
739         Roo.each(queue, function(box, k){
740             
741             Roo.each(box, function(b, kk){
742                 
743                 b.el.position('absolute');
744                 
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'));
747                 
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'));
751                 }
752                 
753                 b.el.setWidth(width);
754                 b.el.setHeight(height);
755                 
756             }, this);
757             
758             if(!box.length){
759                 return;
760             }
761             
762             var positions = [];
763             
764             switch (box.length){
765                 case 1 :
766                     positions = this.getHorizontalOneBoxColPositions(maxX, minY, box);
767                     break;
768                 case 2 :
769                     positions = this.getHorizontalTwoBoxColPositions(maxX, minY, box);
770                     break;
771                 case 3 :
772                     positions = this.getHorizontalThreeBoxColPositions(maxX, minY, box);
773                     break;
774                 case 4 :
775                     positions = this.getHorizontalFourBoxColPositions(maxX, minY, box);
776                     break;
777                 default :
778                     break;
779             }
780             
781             Roo.each(box, function(b,kk){
782                 
783                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
784                 
785                 maxX = Math.min(maxX, positions[kk].x - this.padWidth);
786                 
787             }, this);
788             
789         }, this);
790         
791     },
792     
793     _processHorizontalEndItem : function(eItems, maxX, minX, minY, isInstant)
794     {
795         Roo.each(eItems, function(b,k){
796             
797             b.size = (k == 0) ? 'sm' : 'xs';
798             b.x = (k == 0) ? 2 : 1;
799             b.y = (k == 0) ? 2 : 1;
800             
801             b.el.position('absolute');
802             
803             var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
804                 
805             b.el.setWidth(width);
806             
807             var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
808             
809             b.el.setHeight(height);
810             
811         }, this);
812
813         var positions = [];
814         
815         positions.push({
816             x : maxX - this.unitWidth * 2 - this.gutter,
817             y : minY
818         });
819         
820         positions.push({
821             x : maxX - this.unitWidth,
822             y : minY + (this.unitWidth + this.gutter) * 2
823         });
824         
825         positions.push({
826             x : maxX - this.unitWidth * 3 - this.gutter * 2,
827             y : minY
828         });
829         
830         Roo.each(eItems, function(b,k){
831             
832             b.el.setXY([positions[k].x, positions[k].y], isInstant ? false : true);
833
834         }, this);
835         
836     },
837     
838     getVerticalOneBoxColPositions : function(x, y, box)
839     {
840         var pos = [];
841         
842         var rand = Math.floor(Math.random() * ((4 - box[0].x)));
843         
844         if(box[0].size == 'md-left'){
845             rand = 0;
846         }
847         
848         if(box[0].size == 'md-right'){
849             rand = 1;
850         }
851         
852         pos.push({
853             x : x + (this.unitWidth + this.gutter) * rand,
854             y : y
855         });
856         
857         return pos;
858     },
859     
860     getVerticalTwoBoxColPositions : function(x, y, box)
861     {
862         var pos = [];
863         
864         if(box[0].size == 'xs'){
865             
866             pos.push({
867                 x : x,
868                 y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[1].y))
869             });
870
871             pos.push({
872                 x : x + (this.unitWidth + this.gutter) * (3 - box[1].x),
873                 y : y
874             });
875             
876             return pos;
877             
878         }
879         
880         pos.push({
881             x : x,
882             y : y
883         });
884
885         pos.push({
886             x : x + (this.unitWidth + this.gutter) * 2,
887             y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[0].y))
888         });
889         
890         return pos;
891         
892     },
893     
894     getVerticalThreeBoxColPositions : function(x, y, box)
895     {
896         var pos = [];
897         
898         if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
899             
900             pos.push({
901                 x : x,
902                 y : y
903             });
904
905             pos.push({
906                 x : x + (this.unitWidth + this.gutter) * 1,
907                 y : y
908             });
909             
910             pos.push({
911                 x : x + (this.unitWidth + this.gutter) * 2,
912                 y : y
913             });
914             
915             return pos;
916             
917         }
918         
919         if(box[0].size == 'xs' && box[1].size == 'xs'){
920             
921             pos.push({
922                 x : x,
923                 y : y
924             });
925
926             pos.push({
927                 x : x,
928                 y : y + ((this.unitWidth + this.gutter) * (box[2].y - 1))
929             });
930             
931             pos.push({
932                 x : x + (this.unitWidth + this.gutter) * 1,
933                 y : y
934             });
935             
936             return pos;
937             
938         }
939         
940         pos.push({
941             x : x,
942             y : y
943         });
944
945         pos.push({
946             x : x + (this.unitWidth + this.gutter) * 2,
947             y : y
948         });
949
950         pos.push({
951             x : x + (this.unitWidth + this.gutter) * 2,
952             y : y + (this.unitWidth + this.gutter) * (box[0].y - 1)
953         });
954             
955         return pos;
956         
957     },
958     
959     getVerticalFourBoxColPositions : function(x, y, box)
960     {
961         var pos = [];
962         
963         if(box[0].size == 'xs'){
964             
965             pos.push({
966                 x : x,
967                 y : y
968             });
969
970             pos.push({
971                 x : x,
972                 y : y + (this.unitWidth + this.gutter) * 1
973             });
974             
975             pos.push({
976                 x : x,
977                 y : y + (this.unitWidth + this.gutter) * 2
978             });
979             
980             pos.push({
981                 x : x + (this.unitWidth + this.gutter) * 1,
982                 y : y
983             });
984             
985             return pos;
986             
987         }
988         
989         pos.push({
990             x : x,
991             y : y
992         });
993
994         pos.push({
995             x : x + (this.unitWidth + this.gutter) * 2,
996             y : y
997         });
998
999         pos.push({
1000             x : x + (this.unitWidth + this.gutter) * 2,
1001             y : y + (this.unitWidth + this.gutter) * 1
1002         });
1003
1004         pos.push({
1005             x : x + (this.unitWidth + this.gutter) * 2,
1006             y : y + (this.unitWidth + this.gutter) * 2
1007         });
1008
1009         return pos;
1010         
1011     },
1012     
1013     getHorizontalOneBoxColPositions : function(maxX, minY, box)
1014     {
1015         var pos = [];
1016         
1017         if(box[0].size == 'md-left'){
1018             pos.push({
1019                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1020                 y : minY
1021             });
1022             
1023             return pos;
1024         }
1025         
1026         if(box[0].size == 'md-right'){
1027             pos.push({
1028                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
1029                 y : minY + (this.unitWidth + this.gutter) * 1
1030             });
1031             
1032             return pos;
1033         }
1034         
1035         var rand = Math.floor(Math.random() * (4 - box[0].y));
1036         
1037         pos.push({
1038             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1039             y : minY + (this.unitWidth + this.gutter) * rand
1040         });
1041         
1042         return pos;
1043         
1044     },
1045     
1046     getHorizontalTwoBoxColPositions : function(maxX, minY, box)
1047     {
1048         var pos = [];
1049         
1050         if(box[0].size == 'xs'){
1051             
1052             pos.push({
1053                 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1054                 y : minY
1055             });
1056
1057             pos.push({
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)
1060             });
1061             
1062             return pos;
1063             
1064         }
1065         
1066         pos.push({
1067             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1068             y : minY
1069         });
1070
1071         pos.push({
1072             x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1073             y : minY + (this.unitWidth + this.gutter) * 2
1074         });
1075         
1076         return pos;
1077         
1078     },
1079     
1080     getHorizontalThreeBoxColPositions : function(maxX, minY, box)
1081     {
1082         var pos = [];
1083         
1084         if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
1085             
1086             pos.push({
1087                 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1088                 y : minY
1089             });
1090
1091             pos.push({
1092                 x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1093                 y : minY + (this.unitWidth + this.gutter) * 1
1094             });
1095             
1096             pos.push({
1097                 x : maxX - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1098                 y : minY + (this.unitWidth + this.gutter) * 2
1099             });
1100             
1101             return pos;
1102             
1103         }
1104         
1105         if(box[0].size == 'xs' && box[1].size == 'xs'){
1106             
1107             pos.push({
1108                 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1109                 y : minY
1110             });
1111
1112             pos.push({
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),
1114                 y : minY
1115             });
1116             
1117             pos.push({
1118                 x : maxX - this.unitWidth * box[2].x - this.gutter * (box[2].x - 1),
1119                 y : minY + (this.unitWidth + this.gutter) * 1
1120             });
1121             
1122             return pos;
1123             
1124         }
1125         
1126         pos.push({
1127             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1128             y : minY
1129         });
1130
1131         pos.push({
1132             x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1133             y : minY + (this.unitWidth + this.gutter) * 2
1134         });
1135
1136         pos.push({
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
1139         });
1140             
1141         return pos;
1142         
1143     },
1144     
1145     getHorizontalFourBoxColPositions : function(maxX, minY, box)
1146     {
1147         var pos = [];
1148         
1149         if(box[0].size == 'xs'){
1150             
1151             pos.push({
1152                 x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1153                 y : minY
1154             });
1155
1156             pos.push({
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),
1158                 y : minY
1159             });
1160             
1161             pos.push({
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),
1163                 y : minY
1164             });
1165             
1166             pos.push({
1167                 x : maxX - this.unitWidth * box[3].x - this.gutter * (box[3].x - 1),
1168                 y : minY + (this.unitWidth + this.gutter) * 1
1169             });
1170             
1171             return pos;
1172             
1173         }
1174         
1175         pos.push({
1176             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
1177             y : minY
1178         });
1179         
1180         pos.push({
1181             x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
1182             y : minY + (this.unitWidth + this.gutter) * 2
1183         });
1184         
1185         pos.push({
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
1188         });
1189         
1190         pos.push({
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
1193         });
1194
1195         return pos;
1196         
1197     }
1198     
1199 });
1200
1201  
1202
1203