1// version 1.4.0 2// http://welcome.totheinter.net/columnizer-jquery-plugin/ 3// created by: Adam Wulf [email protected] 4 5(function($){ 6 7 $.fn.columnize = function(options) { 8 9 10 var defaults = { 11 // default width of columnx 12 width: 400, 13 // optional # of columns instead of width 14 columns : false, 15 // true to build columns once regardless of window resize 16 // false to rebuild when content box changes bounds 17 buildOnce : false, 18 // an object with options if the text should overflow 19 // it's container if it can't fit within a specified height 20 overflow : false, 21 // this function is called after content is columnized 22 doneFunc : function(){}, 23 // if the content should be columnized into a 24 // container node other than it's own node 25 target : false, 26 // re-columnizing when images reload might make things 27 // run slow. so flip this to true if it's causing delays 28 ignoreImageLoading : true, 29 // should columns float left or right 30 float : "left", 31 // ensure the last column is never the tallest column 32 lastNeverTallest : false 33 }; 34 var options = $.extend(defaults, options); 35 36 return this.each(function() { 37 var $inBox = options.target ? $(options.target) : $(this); 38 var maxHeight = $(this).height(); 39 var $cache = $('<div></div>'); // this is where we'll put the real content 40 var lastWidth = 0; 41 var columnizing = false; 42 $cache.append($(this).children().clone(true)); 43 44 // images loading after dom load 45 // can screw up the column heights, 46 // so recolumnize after images load 47 if(!options.ignoreImageLoading && !options.target){ 48 if(!$inBox.data("imageLoaded")){ 49 $inBox.data("imageLoaded", true); 50 if($(this).find("img").length > 0){ 51 // only bother if there are 52 // actually images... 53 var func = function($inBox,$cache){ return function(){ 54 if(!$inBox.data("firstImageLoaded")){ 55 $inBox.data("firstImageLoaded", "true"); 56 $inBox.empty().append($cache.children().clone(true)); 57 $inBox.columnize(options); 58 } 59 }}($(this), $cache); 60 $(this).find("img").one("load", func); 61 $(this).find("img").one("abort", func); 62 return; 63 } 64 } 65 } 66 67 $inBox.empty(); 68 69 columnizeIt(); 70 71 if(!options.buildOnce){ 72 $(window).resize(function() { 73 if(!options.buildOnce && $.browser.msie){ 74 if($inBox.data("timeout")){ 75 clearTimeout($inBox.data("timeout")); 76 } 77 $inBox.data("timeout", setTimeout(columnizeIt, 200)); 78 }else if(!options.buildOnce){ 79 columnizeIt(); 80 }else{ 81 // don't rebuild 82 } 83 }); 84 } 85 86 /** 87 * return a node that has a height 88 * less than or equal to height 89 * 90 * @param putInHere, a dom element 91 * @$pullOutHere, a jQuery element 92 */ 93 function columnize($putInHere, $pullOutHere, $parentColumn, height){ 94 while($parentColumn.height() < height && 95 $pullOutHere[0].childNodes.length){ 96 $putInHere.append($pullOutHere[0].childNodes[0]); 97 } 98 if($putInHere[0].childNodes.length == 0) return; 99 100 // now we're too tall, undo the last one 101 var kids = $putInHere[0].childNodes; 102 var lastKid = kids[kids.length-1]; 103 $putInHere[0].removeChild(lastKid); 104 var $item = $(lastKid); 105 106 107 if($item[0].nodeType == 3){ 108 // it's a text node, split it up 109 var oText = $item[0].nodeValue; 110 var counter2 = options.width / 18; 111 if(options.accuracy) 112 counter2 = options.accuracy; 113 var columnText; 114 var latestTextNode = null; 115 while($parentColumn.height() < height && oText.length){ 116 if (oText.indexOf(' ', counter2) != '-1') { 117 columnText = oText.substring(0, oText.indexOf(' ', counter2)); 118 } else { 119 columnText = oText; 120 } 121 latestTextNode = document.createTextNode(columnText); 122 $putInHere.append(latestTextNode); 123 124 if(oText.length > counter2){ 125 oText = oText.substring(oText.indexOf(' ', counter2)); 126 }else{ 127 oText = ""; 128 } 129 } 130 if($parentColumn.height() >= height && latestTextNode != null){ 131 // too tall :( 132 $putInHere[0].removeChild(latestTextNode); 133 oText = latestTextNode.nodeValue + oText; 134 } 135 if(oText.length){ 136 $item[0].nodeValue = oText; 137 }else{ 138 return false; // we ate the whole text node, move on to the next node 139 } 140 } 141 142 if($pullOutHere.children().length){
143 $pullOutHere.prepend($item); 144 }else{ 145 $pullOutHere.append($item); 146 } 147 148 return $item[0].nodeType == 3; 149 } 150 151 function split($putInHere, $pullOutHere, $parentColumn, height){ 152 if($pullOutHere.children().length){ 153 $cloneMe = $pullOutHere.children(":first"); 154 $clone = $cloneMe.clone(true); 155 if($clone.attr("nodeType") == 1 && !$clone.hasClass("dontend")){ 156 $putInHere.append($clone); 157 if($clone.is("img") && $parentColumn.height() < height + 20){ 158 $cloneMe.remove(); 159 }else if(!$cloneMe.hasClass("dontsplit") && $parentColumn.height() < height + 20){ 160 $cloneMe.remove(); 161 }else if($clone.is("img") || $cloneMe.hasClass("dontsplit")){ 162 $clone.remove(); 163 }else{ 164 $clone.empty(); 165 if(!columnize($clone, $cloneMe, $parentColumn, height)){ 166 if($cloneMe.children().length){ 167 split($clone, $cloneMe, $parentColumn, height); 168 } 169 } 170 if($clone.get(0).childNodes.length == 0){ 171 // it was split, but nothing is in it :( 172 $clone.remove(); 173 } 174 } 175 } 176 } 177 } 178 179 180 function singleColumnizeIt() { 181 if ($inBox.data("columnized") && $inBox.children().length == 1) { 182 return; 183 } 184 $inBox.data("columnized", true); 185 $inBox.data("columnizing", true); 186 187 $inBox.empty(); 188 $inBox.append($("<div class='first last column' style='width:98%; padding: 3px; float: " + options.float + ";'></div>")); //" 189 $col = $inBox.children().eq($inBox.children().length-1); 190 $destroyable = $cache.clone(true); 191 if(options.overflow){ 192 targetHeight = options.overflow.height; 193 columnize($col, $destroyable, $col, targetHeight); 194 // make sure that the last item in the column isn't a "dontend" 195 if(!$destroyable.children().find(":first-child").hasClass("dontend")){ 196 split($col, $destroyable, $col, targetHeight); 197 } 198 199 while(checkDontEndColumn($col.children(":last").length && $col.children(":last").get(0))){ 200 var $lastKid = $col.children(":last"); 201 $lastKid.remove(); 202 $destroyable.prepend($lastKid); 203 } 204 205 var html = ""; 206 var div = document.createElement('DIV'); 207 while($destroyable[0].childNodes.length > 0){ 208 var kid = $destroyable[0].childNodes[0]; 209 for(var i=0;i<kid.attributes.length;i++){ 210 if(kid.attributes[i].nodeName.indexOf("jQuery") == 0){ 211 kid.removeAttribute(kid.attributes[i].nodeName); 212 } 213 } 214 div.innerHTML = ""; 215 div.appendChild($destroyable[0].childNodes[0]); 216 html += div.innerHTML; 217 } 218 var overflow = $(options.overflow.id)[0]; 219 overflow.innerHTML = html; 220 221 }else{ 222 $col.append($destroyable); 223 } 224 $inBox.data("columnizing", false); 225 226 if(options.overflow){ 227 options.overflow.doneFunc(); 228 } 229 230 } 231 232 function checkDontEndColumn(dom){ 233 if(dom.nodeType != 1) return false; 234 if($(dom).hasClass("dontend")) return true; 235 if(dom.childNodes.length == 0) return false; 236 return checkDontEndColumn(dom.childNodes[dom.childNodes.length-1]); 237 } 238 239 function columnizeIt() { 240 if(lastWidth == $inBox.width()) return; 241 lastWidth = $inBox.width(); 242 243 var numCols = Math.round($inBox.width() / options.width); 244 if(options.columns) numCols = options.columns; 245// if ($inBox.data("columnized") && numCols == $inBox.children().length) { 246// return; 247// } 248 if(numCols <= 1){ 249 return singleColumnizeIt(); 250 } 251 if($inBox.data("columnizing")) return; 252 $inBox.data("columnized", true); 253 $inBox.data("columnizing", true); 254 255 $inBox.empty(); 256 $inBox.append($("<div style='width:" + (Math.round(100 / numCols) - 2)+ "%; padding: 3px; float: " + options.float + ";'></div>")); //" 257 $col = $inBox.children(":last"); 258 $col.append($cache.clone()); 259 maxHeight = $col.height(); 260 $inBox.empty(); 261 262 var targetHeight = maxHeight / numCols; 263 var firstTime = true; 264 var maxLoops = 3; 265 var scrollHorizontally = false; 266 if(options.overflow){ 267 maxLoops = 1; 268 targetHeight = options.overflow.height; 269 }else if(options.height && options.width){ 270 maxLoops = 1; 271 targetHeight = options.height; 272 scrollHorizontally = true; 273 } 274 275 for(var loopCount=0;loopCount<maxLoops;loopCount++){ 276 $inBox.empty(); 277 var $destroyable; 278 try{ 279 $destroyable = $cache.clone(true); 280 }catch(e){ 281 // jquery in ie6 can't clone with true 282 $destroyable = $cache.clone(); 283 } 284 $destroyable.css("visibility", "hidden"); 285 // create the columns 286 for (var i = 0; i < numCols; i++) { 287 /* create column */
288 var className = (i == 0) ? "first column" : "column"; 289 var className = (i == numCols - 1) ? ("last " + className) : className; 290 $inBox.append($("<div class='" + className + "' style='width:" + (Math.round(100 / numCols) - 2)+ "%; float: " + options.float + ";'></div>")); //" 291 } 292 293 // fill all but the last column (unless overflowing) 294 var i = 0; 295 while(i < numCols - (options.overflow ? 0 : 1) || scrollHorizontally && $destroyable.children().length){ 296 if($inBox.children().length <= i){ 297 // we ran out of columns, make another 298 $inBox.append($("<div class='" + className + "' style='width:" + (Math.round(100 / numCols) - 2)+ "%; float: " + options.float + ";'></div>")); //" 299 } 300 var $col = $inBox.children().eq(i); 301 columnize($col, $destroyable, $col, targetHeight); 302 // make sure that the last item in the column isn't a "dontend" 303 if(!$destroyable.children().find(":first-child").hasClass("dontend")){ 304 split($col, $destroyable, $col, targetHeight); 305 }else{ 306// alert("not splitting a dontend"); 307 } 308 309 while(checkDontEndColumn($col.children(":last").length && $col.children(":last").get(0))){ 310 var $lastKid = $col.children(":last"); 311 $lastKid.remove(); 312 $destroyable.prepend($lastKid); 313 } 314 i++; 315 } 316 if(options.overflow && !scrollHorizontally){ 317 var IE6 = false /*@cc_on || @_jscript_version < 5.7 @*/; 318 var IE7 = (document.all) && (navigator.appVersion.indexOf("MSIE 7.") != -1); 319 if(IE6 || IE7){ 320 var html = ""; 321 var div = document.createElement('DIV'); 322 while($destroyable[0].childNodes.length > 0){ 323 var kid = $destroyable[0].childNodes[0]; 324 for(var i=0;i<kid.attributes.length;i++){ 325 if(kid.attributes[i].nodeName.indexOf("jQuery") == 0){ 326 kid.removeAttribute(kid.attributes[i].nodeName); 327 } 328 } 329 div.innerHTML = ""; 330 div.appendChild($destroyable[0].childNodes[0]); 331 html += div.innerHTML; 332 } 333 var overflow = $(options.overflow.id)[0]; 334 overflow.innerHTML = html; 335 }else{ 336 $(options.overflow.id).empty().append($destroyable.children().clone(true)); 337 } 338 }else if(!scrollHorizontally){ 339 // the last column in the series 340 $col = $inBox.children().eq($inBox.children().length-1); 341 while($destroyable.children().length) $col.append($destroyable.children(":first")); 342 var afterH = $col.height(); 343 var diff = afterH - targetHeight; 344 var totalH = 0; 345 var min = 10000000; 346 var max = 0; 347 var lastIsMax = false; 348 $inBox.children().each(function($inBox){ return function($item){ 349 var h = $inBox.children().eq($item).height(); 350 lastIsMax = false; 351 totalH += h; 352 if(h > max) { 353 max = h; 354 lastIsMax = true; 355 } 356 if(h < min) min = h; 357 }}($inBox)); 358 359 var avgH = totalH / numCols; 360 if(options.lastNeverTallest && lastIsMax){ 361 // the last column is the tallest 362 // so allow columns to be taller 363 // and retry 364 targetHeight = targetHeight + 30; 365 if(loopCount == maxLoops-1) maxLoops++; 366 }else if(max - min > 30){ 367 // too much variation, try again 368 targetHeight = avgH + 30; 369 }else if(Math.abs(avgH-targetHeight) > 20){ 370 // too much variation, try again 371 targetHeight = avgH; 372 }else { 373 // solid, we're done 374 loopCount = maxLoops; 375 } 376 }else{ 377 // it's scrolling horizontally, fix the width/classes of the columns 378 $inBox.children().each(function(i){ 379 $col = $inBox.children().eq(i); 380 $col.width(options.width + "px"); 381 if(i==0){ 382 $col.addClass("first"); 383 }else if(i==$inBox.children().length-1){ 384 $col.addClass("last"); 385 }else{ 386 $col.removeClass("first"); 387 $col.removeClass("last"); 388 } 389 }); 390 $inBox.width($inBox.children().length * options.width + "px"); 391 } 392 $inBox.append($("<br style='clear:both;'>")); 393 } 394 $inBox.find('.column').find(':first.removeiffirst').remove(); 395 $inBox.find('.column').find(':last.removeiflast').remove();
396 $inBox.data("columnizing", false); 397 398 if(options.overflow){ 399 options.overflow.doneFunc(); 400 } 401 options.doneFunc(); 402 } 403 }); 404 }; 405})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.