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 pos = this.el.getBox(true);
404         
405         var minX = pos.x;
406         
407         var maxX = pos.right - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
408         
409         var standard = [
410             ['xs', 'xs', 'xs', 'wide'],
411             ['xs', 'xs', 'wide'],
412             ['xs', 'xs', 'sm'],
413             ['xs', 'xs', 'xs'],
414             ['xs', 'wide'],
415             ['xs', 'sm'],
416             ['xs', 'xs'],
417             ['xs'],
418             
419             ['sm', 'xs', 'xs'],
420             ['sm', 'xs'],
421             ['sm'],
422             
423             ['wide', 'xs', 'xs', 'xs'],
424             ['wide', 'xs', 'xs'],
425             ['wide', 'xs'],
426             ['wide']
427         ];
428         
429         var queue = [];
430         
431         var boxes = [];
432         
433         var box = [];
434         
435         Roo.each(items, function(item, k){
436             
437             switch (item.size) {
438                 case 'md' :
439                 case 'md-left' :
440                 case 'md-right' :
441                 case 'tall' :
442                     
443                     if(box.length){
444                         boxes.push(box);
445                         box = [];
446                     }
447                     
448                     boxes.push([item]);
449                     
450                     break;
451                     
452                 case 'xs' :
453                 case 'sm' :
454                 case 'wide' :
455                     
456                     box.push(item);
457                     
458                     break;
459                 default :
460                     break;
461                     
462             }
463             
464         }, this);
465         
466         if(box.length){
467             boxes.push(box);
468             box = [];
469         }
470         
471         
472         
473         
474         
475         
476         
477         var x = maxX;
478         
479         var queue = [];
480         
481         var box = [];
482         var size = 0;
483         var hit_end = false;
484         
485         Roo.each(items, function(item, k){
486             
487             item.el.setVisibilityMode(Roo.Element.DISPLAY);
488             item.el.show();
489             
490             if(hit_end){
491                 item.el.hide();
492                 return;
493             }
494             
495             if(size + item.y > 3){
496                 queue.push(box);
497                 box = [];
498                 size = 0;
499                 maxX = x;
500             }
501             
502             var width = Math.floor(this.unitWidth * item.x + (this.gutter * (item.x - 1)) + item.el.getPadding('lr'));
503             
504             x = Math.min(x, maxX - width - this.padWidth);
505             
506             if(x < minX){
507                 item.el.hide();
508                 hit_end = true;
509                 return;
510             }
511             
512             size = size + item.y;
513             
514             box.push(item);
515             
516             
517         }, this);
518         
519         if(box.length){
520             queue.push(box);
521         }
522         
523         this._processHorizontalLayoutQueue( queue, eItems, isInstant );
524     },
525     
526     /** Sets position of item in DOM
527     * @param {Element} item
528     * @param {Number} x - horizontal position
529     * @param {Number} y - vertical position
530     * @param {Boolean} isInstant - disables transitions
531     */
532     _processVerticalLayoutQueue : function( queue, isInstant )
533     {
534         var pos = this.el.getBox(true);
535         var x = pos.x;
536         var y = pos.y;
537         var maxY = [];
538         
539         for (var i = 0; i < this.cols; i++){
540             maxY[i] = pos.y;
541         }
542         
543         Roo.each(queue, function(box, k){
544             
545             var col = k % this.cols;
546             
547             Roo.each(box, function(b,kk){
548                 
549                 b.el.position('absolute');
550                 
551                 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
552                 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
553                 
554                 if(b.size == 'md-left' || b.size == 'md-right'){
555                     width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
556                     height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
557                 }
558                 
559                 b.el.setWidth(width);
560                 b.el.setHeight(height);
561                 
562             }, this);
563             
564             for (var i = 0; i < this.cols; i++){
565                 
566                 if(maxY[i] < maxY[col]){
567                     col = i;
568                     continue;
569                 }
570                 
571                 col = Math.min(col, i);
572                 
573             }
574             
575             x = pos.x + col * (this.colWidth + this.padWidth);
576             
577             y = maxY[col];
578             
579             var positions = [];
580             
581             switch (box.length){
582                 case 1 :
583                     positions = this.getVerticalOneBoxColPositions(x, y, box);
584                     break;
585                 case 2 :
586                     positions = this.getVerticalTwoBoxColPositions(x, y, box);
587                     break;
588                 case 3 :
589                     positions = this.getVerticalThreeBoxColPositions(x, y, box);
590                     break;
591                 case 4 :
592                     positions = this.getVerticalFourBoxColPositions(x, y, box);
593                     break;
594                 default :
595                     break;
596             }
597             
598             Roo.each(box, function(b,kk){
599                 
600                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
601                 
602                 var sz = b.el.getSize();
603                 
604                 maxY[col] = Math.max(maxY[col], positions[kk].y + sz.height + this.padWidth);
605                 
606             }, this);
607             
608         }, this);
609         
610         var mY = 0;
611         
612         for (var i = 0; i < this.cols; i++){
613             mY = Math.max(mY, maxY[i]);
614         }
615         
616         this.el.setHeight(mY - pos.y);
617         
618     },
619     
620 //    _processVerticalAlternativeLayoutQueue : function( items, isInstant )
621 //    {
622 //        var pos = this.el.getBox(true);
623 //        var x = pos.x;
624 //        var y = pos.y;
625 //        var maxX = pos.right;
626 //        
627 //        var maxHeight = 0;
628 //        
629 //        Roo.each(items, function(item, k){
630 //            
631 //            var c = k % 2;
632 //            
633 //            item.el.position('absolute');
634 //                
635 //            var width = Math.floor(this.colWidth + item.el.getPadding('lr'));
636 //
637 //            item.el.setWidth(width);
638 //
639 //            var height = Math.floor(this.colWidth * item.y / item.x + item.el.getPadding('tb'));
640 //
641 //            item.el.setHeight(height);
642 //            
643 //            if(c == 0){
644 //                item.el.setXY([x, y], isInstant ? false : true);
645 //            } else {
646 //                item.el.setXY([maxX - width, y], isInstant ? false : true);
647 //            }
648 //            
649 //            y = y + height + this.alternativePadWidth;
650 //            
651 //            maxHeight = maxHeight + height + this.alternativePadWidth;
652 //            
653 //        }, this);
654 //        
655 //        this.el.setHeight(maxHeight);
656 //        
657 //    },
658     
659     _processHorizontalLayoutQueue : function( queue, eItems, isInstant )
660     {
661         var pos = this.el.getBox(true);
662         
663         var minX = pos.x;
664         var minY = pos.y;
665         
666         var maxX = pos.right;
667         
668         this._processHorizontalEndItem(eItems, maxX, minX, minY, isInstant);
669         
670         var maxX = maxX - this.unitWidth * 3 - this.gutter * 2 - this.padWidth;
671         
672         Roo.each(queue, function(box, k){
673             
674             Roo.each(box, function(b, kk){
675                 
676                 b.el.position('absolute');
677                 
678                 var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
679                 var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
680                 
681                 if(b.size == 'md-left' || b.size == 'md-right'){
682                     width = Math.floor(this.unitWidth * (b.x - 1) + (this.gutter * (b.x - 2)) + b.el.getPadding('lr'));
683                     height = Math.floor(this.unitWidth * (b.y - 1) + (this.gutter * (b.y - 2)) + b.el.getPadding('tb'));
684                 }
685                 
686                 b.el.setWidth(width);
687                 b.el.setHeight(height);
688                 
689             }, this);
690             
691             if(!box.length){
692                 return;
693             }
694             
695             var positions = [];
696             
697             switch (box.length){
698                 case 1 :
699                     positions = this.getHorizontalOneBoxColPositions(maxX, minY, box);
700                     break;
701                 case 2 :
702                     positions = this.getHorizontalTwoBoxColPositions(maxX, minY, box);
703                     break;
704                 case 3 :
705                     positions = this.getHorizontalThreeBoxColPositions(maxX, minY, box);
706                     break;
707                 default :
708                     break;
709             }
710             
711             Roo.each(box, function(b,kk){
712                 
713                 b.el.setXY([positions[kk].x, positions[kk].y], isInstant ? false : true);
714                 
715                 maxX = Math.min(maxX, positions[kk].x - this.padWidth);
716                 
717             }, this);
718             
719         }, this);
720         
721     },
722     
723     _processHorizontalEndItem : function(eItems, maxX, minX, minY, isInstant)
724     {
725         Roo.each(eItems, function(b,k){
726             
727             b.size = (k == 0) ? 'sm' : 'xs';
728             b.x = (k == 0) ? 2 : 1;
729             b.y = (k == 0) ? 2 : 1;
730             
731             b.el.position('absolute');
732             
733             var width = Math.floor(this.unitWidth * b.x + (this.gutter * (b.x - 1)) + b.el.getPadding('lr'));
734                 
735             b.el.setWidth(width);
736             
737             var height = Math.floor(this.unitWidth * b.y + (this.gutter * (b.y - 1)) + b.el.getPadding('tb'));
738             
739             b.el.setHeight(height);
740             
741         }, this);
742
743         var positions = [];
744         
745         positions.push({
746             x : maxX - this.unitWidth * 2 - this.gutter,
747             y : minY
748         });
749         
750         positions.push({
751             x : maxX - this.unitWidth,
752             y : minY + (this.unitWidth + this.gutter) * 2
753         });
754         
755         positions.push({
756             x : maxX - this.unitWidth * 3 - this.gutter * 2,
757             y : minY
758         });
759         
760         Roo.each(eItems, function(b,k){
761             
762             b.el.setXY([positions[k].x, positions[k].y], isInstant ? false : true);
763
764         }, this);
765         
766     },
767     
768     getVerticalOneBoxColPositions : function(x, y, box)
769     {
770         var pos = [];
771         
772         var rand = Math.floor(Math.random() * ((4 - box[0].x)));
773         
774         if(box[0].size == 'md-left'){
775             rand = 0;
776         }
777         
778         if(box[0].size == 'md-right'){
779             rand = 1;
780         }
781         
782         pos.push({
783             x : x + (this.unitWidth + this.gutter) * rand,
784             y : y
785         });
786         
787         return pos;
788     },
789     
790     getVerticalTwoBoxColPositions : function(x, y, box)
791     {
792         var pos = [];
793         
794         if(box[0].size == 'xs'){
795             
796             pos.push({
797                 x : x,
798                 y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[1].y))
799             });
800
801             pos.push({
802                 x : x + (this.unitWidth + this.gutter) * (3 - box[1].x),
803                 y : y
804             });
805             
806             return pos;
807             
808         }
809         
810         pos.push({
811             x : x,
812             y : y
813         });
814
815         pos.push({
816             x : x + (this.unitWidth + this.gutter) * 2,
817             y : y + ((this.unitWidth + this.gutter) * Math.floor(Math.random() * box[0].y))
818         });
819         
820         return pos;
821         
822     },
823     
824     getVerticalThreeBoxColPositions : function(x, y, box)
825     {
826         var pos = [];
827         
828         if(box[0].size == 'xs' && box[1].size == 'xs' && box[2].size == 'xs'){
829             
830             pos.push({
831                 x : x,
832                 y : y
833             });
834
835             pos.push({
836                 x : x + (this.unitWidth + this.gutter) * 1,
837                 y : y
838             });
839             
840             pos.push({
841                 x : x + (this.unitWidth + this.gutter) * 2,
842                 y : y
843             });
844             
845             return pos;
846             
847         }
848         
849         if(box[0].size == 'xs' && box[1].size == 'xs'){
850             
851             pos.push({
852                 x : x,
853                 y : y
854             });
855
856             pos.push({
857                 x : x,
858                 y : y + ((this.unitWidth + this.gutter) * (box[2].y - 1))
859             });
860             
861             pos.push({
862                 x : x + (this.unitWidth + this.gutter) * 1,
863                 y : y
864             });
865             
866             return pos;
867             
868         }
869         
870         pos.push({
871             x : x,
872             y : y
873         });
874
875         pos.push({
876             x : x + (this.unitWidth + this.gutter) * 2,
877             y : y
878         });
879
880         pos.push({
881             x : x + (this.unitWidth + this.gutter) * 2,
882             y : y + (this.unitWidth + this.gutter) * (box[0].y - 1)
883         });
884             
885         return pos;
886         
887     },
888     
889     getVerticalFourBoxColPositions : function(x, y, box)
890     {
891         var pos = [];
892         
893         if(box[0].size == 'xs'){
894             
895             pos.push({
896                 x : x,
897                 y : y
898             });
899
900             pos.push({
901                 x : x,
902                 y : y + (this.unitWidth + this.gutter) * 1
903             });
904             
905             pos.push({
906                 x : x,
907                 y : y + (this.unitWidth + this.gutter) * 2
908             });
909             
910             pos.push({
911                 x : x + (this.unitWidth + this.gutter) * 1,
912                 y : y
913             });
914             
915             return pos;
916             
917         }
918         
919         pos.push({
920             x : x,
921             y : y
922         });
923
924         pos.push({
925             x : x + (this.unitWidth + this.gutter) * 2,
926             y : y
927         });
928
929         pos.push({
930             x : x + (this.unitWidth + this.gutter) * 2,
931             y : y + (this.unitWidth + this.gutter) * 1
932         });
933
934         pos.push({
935             x : x + (this.unitWidth + this.gutter) * 2,
936             y : y + (this.unitWidth + this.gutter) * 2
937         });
938
939         return pos;
940         
941     },
942     
943     getHorizontalOneBoxColPositions : function(maxX, minY, box)
944     {
945         var pos = [];
946         
947         if(box[0].size == 'md-left'){
948             pos.push({
949                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
950                 y : minY
951             });
952             
953             return pos;
954         }
955         
956         if(box[0].size == 'md-right'){
957             pos.push({
958                 x : maxX - this.unitWidth * (box[0].x - 1) - this.gutter * (box[0].x - 2),
959                 y : minY + (this.unitWidth + this.gutter) * 1
960             });
961             
962             return pos;
963         }
964         
965         var rand = Math.floor(Math.random() * (4 - box[0].y));
966         
967         pos.push({
968             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
969             y : minY + (this.unitWidth + this.gutter) * rand
970         });
971         
972         return pos;
973         
974     },
975     
976     getHorizontalTwoBoxColPositions : function(maxX, minY, box)
977     {
978         var pos = [];
979         
980         pos.push({
981             x : maxX - this.unitWidth * box[0].x - this.gutter * (box[0].x - 1),
982             y : minY
983         });
984
985         pos.push({
986             x : maxX - this.unitWidth * box[1].x - this.gutter * (box[1].x - 1),
987             y : minY + (this.unitWidth + this.gutter) * (3 - box[1].y)
988         });
989         
990         return pos;
991         
992     },
993     
994     getHorizontalThreeBoxColPositions : function(maxX, minY, box)
995     {
996         var pos = [];
997         
998         pos.push({
999             x : maxX - this.unitWidth,
1000             y : minY
1001         });
1002         
1003         pos.push({
1004             x : maxX - this.unitWidth,
1005             y : minY - this.unitWidth - this.gutter
1006         });
1007         
1008         pos.push({
1009             x : maxX - this.unitWidth,
1010             y : minY - (this.unitWidth + this.gutter) * 2
1011         });
1012         
1013         return pos;
1014         
1015     }
1016     
1017 });
1018
1019  
1020
1021