Changed rendering of fragment lists.
[wolnelektury.git] / media / js / jquery.autocolumn.js
1 // version 1.1.0
2 // http://welcome.totheinter.net/columnizer-jquery-plugin/
3 // created by: Adam Wulf adam.wulf@gmail.com
4
5 (function($){
6  $.fn.columnize = function(options) {
7
8
9         var defaults = {
10                 width: 400,
11                 columns : false,
12                 buildOnce : false
13         };
14         var options = $.extend(defaults, options);
15
16     return this.each(function() {
17             var $inBox = $(this);
18                 var maxHeight = $inBox.height();
19                 var $cache = $('<div></div>'); // this is where we'll put the real content
20                 var lastWidth = 0;
21                 var columnizing = false;
22                 $cache.append($inBox.children().clone());
23                 
24                 columnizeIt();
25                 
26                 $(window).resize(function() {
27                         if(!options.buildOnce && $.browser.msie){
28                                 if($inBox.data("timeout")){
29                                         clearTimeout($inBox.data("timeout"));
30                                 }
31                                 $inBox.data("timeout", setTimeout(columnizeIt, 200));
32                         }else if(!options.buildOnce){
33                                 columnizeIt();
34                         }else{
35                                 // don't rebuild
36                         }
37                 });
38                 
39                 /**
40                  * return a node that has a height
41                  * less than or equal to height
42                  *
43                  * @param putInHere, a dom element
44                  * @$pullOutHere, a jQuery element
45                  */
46                 function columnize($putInHere, $pullOutHere, $parentColumn, height){
47                         while($parentColumn.height() < height &&
48                                   $pullOutHere[0].childNodes.length){
49                                 $putInHere.append($pullOutHere[0].childNodes[0]);
50                         }
51                         if($putInHere[0].childNodes.length == 0) return;
52                         
53                         // now we're too tall, undo the last one
54                         var kids = $putInHere[0].childNodes;
55                         var lastKid = kids[kids.length-1];
56                         $putInHere[0].removeChild(lastKid);
57                         var $item = $(lastKid);
58                         if($item[0].nodeType == 3){
59                                 // it's a text node, split it up
60                                 var oText = $item[0].nodeValue;
61                                 var counter2 = options.width / 8;
62                                 var columnText;
63                                 while($parentColumn.height() < height && oText.length){
64                                         if (oText.indexOf(' ', counter2) != '-1') {
65                                                 columnText = oText.substring(0, oText.indexOf(' ', counter2));
66                                         } else {
67                                                 columnText = oText;
68                                         }
69                                         $putInHere.append(document.createTextNode(columnText));
70                                         if(oText.length > counter2){
71                                                 oText = oText.substring(oText.indexOf(' ', counter2));
72                                         }else{
73                                                 oText = "";
74                                         }
75                                 }
76                                 if(oText.length){
77                                         $item[0].nodeValue = oText;
78                                 }else{
79                                         return;
80                                 }
81                         }
82                         
83                         if($pullOutHere.children().length){
84                                 $pullOutHere.prepend($item);
85                         }else{
86                                 $pullOutHere.append($item);
87                         }
88                 }
89                 
90                 function split($putInHere, $pullOutHere, $parentColumn, height){
91                         if($pullOutHere.children().length){
92                                 $cloneMe = $pullOutHere.children(":first");
93                                 $clone = $cloneMe.clone();
94                                 if($clone.attr("nodeType") == 1){ 
95                                         $putInHere.append($clone);
96                                         if($clone.is("img") && $parentColumn.height() < height + 20){
97                                                 $cloneMe.remove();
98                                         }else if(!$cloneMe.hasClass("dontsplit") && $parentColumn.height() < height + 20){
99                                                 $cloneMe.remove();
100                                         }else if($clone.is("img") || $cloneMe.hasClass("dontsplit")){
101                                                 $clone.remove();
102                                         }else{
103                                                 $clone.empty();
104                                                 columnize($clone, $cloneMe, $parentColumn, height);
105                                                 if($cloneMe.children().length){
106                                                         split($clone, $cloneMe, $parentColumn, height);
107                                                 }
108                                         }
109                                 }
110                         }
111                 }
112                 
113                 
114                 function singleColumnizeIt() {
115                         if ($inBox.data("columnized") && $inBox.children().length == 1) {
116                                 return;
117                         }
118                         $inBox.data("columnized", true);
119                         $inBox.data("columnizing", true);
120                         
121                         $inBox.empty();
122                         $inBox.append($("<div class='first last column'></div>")); //"
123                         $col = $inBox.children().eq($inBox.children().length-1);
124                         $col.append($cache.clone());
125                         
126                         $inBox.data("columnizing", false);
127                 }
128                 
129                 
130                 function columnizeIt() {
131                         if(lastWidth == $inBox.width()) return;
132                         lastWidth = $inBox.width();
133                         
134                         var numCols = Math.round($inBox.width() / options.width);
135                         if(options.columns) numCols = options.columns;
136 //                      if ($inBox.data("columnized") && numCols == $inBox.children().length) {
137 //                              return;
138 //                      }
139                         if(numCols <= 1){
140                                 return singleColumnizeIt();
141                         }
142                         if($inBox.data("columnizing")) return;
143                         $inBox.data("columnized", true);
144                         $inBox.data("columnizing", true);
145                         
146                         $inBox.empty();
147                         $inBox.append($("<div style='width:" + (Math.round(100 / numCols) - 2)+ "%; padding: 3px; float: left;'></div>")); //"
148                         $col = $inBox.children(":last");
149                         $col.append($cache.clone());
150                         maxHeight = $col.height();
151                         $inBox.empty();
152                         
153                         var targetHeight = maxHeight / numCols;
154                         var firstTime = true;
155                         var maxLoops = 3;
156                         for(var loopCount=0;loopCount<maxLoops;loopCount++){
157                                 $inBox.empty();
158                                 var $destroyable = $cache.clone();
159                                 $destroyable.css("visibility", "hidden");
160                                 // create the columns
161                                 for (var i = 0; i < numCols; i++) {
162                                         /* create column */
163                                         var className = (i == 0) ? "first column" : "column";
164                                         var className = (i == numCols - 1) ? ("last " + className) : className;
165                                         $inBox.append($("<div class='" + className + "' style='width:" + (Math.round(100 / numCols) - 2)+ "%; float: left;'></div>")); //"
166                                 }
167                                 
168                                 // fill all but the last column
169                                 for (var i = 0; i < numCols-1; i++) {
170                                         var $col = $inBox.children().eq(i);
171                                         columnize($col, $destroyable, $col, targetHeight);
172                                         split($col, $destroyable, $col, targetHeight);
173                                 }
174                                 // the last column in the series
175                                 $col = $inBox.children().eq($inBox.children().length-1);
176                                 while($destroyable.children().length) $col.append($destroyable.children(":first"));
177                                 var afterH = $col.height();
178                                 var diff = afterH - targetHeight;
179                                 var totalH = 0;
180                                 var min = 10000000;
181                                 var max = 0;
182                                 $inBox.children().each(function($inBox){ return function($item){
183                                         var h = $inBox.children().eq($item).height();
184                                         totalH += h;
185                                         if(h > max) max = h;
186                                         if(h < min) min = h;
187                                 }}($inBox));
188                                 var avgH = totalH / numCols;
189                                 if(max - min > 30){
190                                         targetHeight = avgH + 30;
191                                 }else if(Math.abs(avgH-targetHeight) > 20){
192                                         targetHeight = avgH;
193                                 }else{
194                                         loopCount = maxLoops;
195                                 }
196                                 $inBox.append($("<br style='clear:both;'>"));
197                         }
198                         $inBox.data("columnizing", false);
199                 }
200     });
201  };
202 })(jQuery);