1(function ($) { 2 $.fn.itemsListArranger = function (option) { 3 4 var ItemsListArranger = function (element, options) { 5 this.settings = $.extend({}, ItemsListArranger.defaultOptions, options); 6 7 this.$container = $(element); 8 this.hideIncompleteRow = this.settings.hideIncompleteRow; 9 this.columnsCount = -1; 10 this.linkedList = { 11 $prev: this.settings.linkedList.prev ? $(this.settings.linkedList.prev) : null, 12 $next: this.settings.linkedList.next ? $(this.settings.linkedList.next) : null 13 }; 14 this._initEventHandlers(); 15 this._checkHideIncompleteRowMode(); 16 if (this.settings.arrangeOnInit) { 17 var columnsCount = this._updateColumnsCount(); 18 if (this.columnsCount !== columnsCount) { 19 this.columnsCount = columnsCount; 20 this.$container.trigger("columnsCountChanged", this.columnsCount); 21 } 22 } 23 }; 24 25 ItemsListArranger.namespace = "itemsListArranger"; 26 27 ItemsListArranger.defaultOptions = { 28 itemsSelector: "div.item", 29 singleBlockSelector: ".item-single-block", 30 doubleBlockSelector: ".item-double-block", 31 mustBeDoubleSelector: ".item-must-be-double", 32 doSingleBlock: $.noop, 33 doDoubleBlock: $.noop, 34 hideIncompleteRow: true, 35 arrangeOnInit: true, 36 // ÐоддеÑжка подгÑÑзки даннÑÑ Ð¿Ñи помоÑи AJAX'а 37 hookPageDataLoadedEvent: true, 38 pageDataLoadedEvent: "newPageDataLoaded", 39 moreButtonSelector: ".btn.loader", 40 // ÐбÑабоÑÑики ÑобÑÑий 41 beforeListArrange: null, 42 afterListArrange: null, 43 columnsCountChanged: null, 44 linkedList: { 45 prev: null, 46 next: null 47 }, 48 minimalRows: 1 49 }; 50 51 ItemsListArranger.prototype._updateColumnsCount = function () { 52 var containerWidth = this.$container.innerWidth(), 53 $block = $(this.settings.singleBlockSelector, this.$container).first(), 54 blockWidth = 0; 55 56 // ÐпÑеделÑем ÑиÑÐ¸Ð½Ñ Ð±Ð»Ð¾ÐºÐ° и колиÑеÑÑво колонок 57 if ($block.length > 0) { 58 blockWidth = $block.outerWidth(true); 59 } else { 60 $block = $(this.settings.doubleBlockSelector, this.$container).first(); 61 if ($block.length > 0) { 62 blockWidth = $block.outerWidth(true) / 2.0; 63 } 64 } 65 if (0 === blockWidth) return -1; 66 // ÐонÑÑанÑÑ 0.3 иÑполÑзÑем Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ пÑогнозиÑÑемого ÑезÑлÑÑаÑа 67 var columnsCount = Math.floor(containerWidth / blockWidth + 0.3); 68 return 0 !== columnsCount ? columnsCount : -1; 69 }; 70 71 ItemsListArranger.prototype._internalDoSingleBlock = function ($block) { 72 switch (typeof this.settings.doSingleBlock) { 73 case "function": 74 $.proxy(this.settings.doSingleBlock, this)($block); 75 break; 76 case "string": 77 // doSingleBlock - пеÑеÑÐµÐ½Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑемÑÑ ÐºÐ»Ð°ÑÑов 78 if (typeof this.settings.doDoubleBlock === "string") { 79 $block.removeClass(this.settings.doDoubleBlock); 80 } 81 $block.addClass(this.settings.doSingleBlock); 82 break; 83 } 84 }; 85 86 ItemsListArranger.prototype._internalDoDoubleBlock = function ($block) { 87 switch (typeof this.settings.doDoubleBlock) { 88 case "function": 89 $.proxy(this.settings.doDoubleBlock, this)($block); 90 break; 91 case "string": 92 // doDoubleBlock - пеÑеÑÐµÐ½Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑемÑÑ ÐºÐ»Ð°ÑÑов 93 if (typeof this.settings.doSingleBlock === "string") { 94 $block.removeClass(this.settings.doSingleBlock); 95 } 96 $block.addClass(this.settings.doDoubleBlock); 97 break; 98 } 99 }; 100 101 ItemsListArranger.prototype._checkHideIncompleteRowMode = function () { 102 /* 103 * ÐÑли оÑÑÑÑÑÑвÑÐµÑ ÐºÐ½Ð¾Ð¿ÐºÐ° "ÐÑе" и ÑобÑÑие загÑÑзки новÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð¾Ð±ÑабаÑÑваеÑÑÑ, 104 * Ñо оÑклÑÑаем "ÑкÑÑвание" незавеÑÑеннÑÑ ÑÑдов 105 */ 106 var settings = this.settings, 107 $loadMoreButton = $(settings.moreButtonSelector, this.$container), 108 overrideHideIncompleteRow = settings.hookPageDataLoadedEvent && $loadMoreButton.length === 0; 109 this.hideIncompleteRow = !overrideHideIncompleteRow ? this.settings.hideIncompleteRow : false;
110 }; 111 112 ItemsListArranger.prototype._arrangeItems = function () { 113 var self = this, 114 settings = this.settings, 115 columnsCount = this.columnsCount, 116 actualColumn = 0, 117 itemsInRow = 0, 118 realItemsInRow = 0, 119 extraItemsCount = 0, 120 rowsCount = 0, 121 $items = this.getItems(); 122 if (0 === $items.length && null !== this.linkedList.$next && 1 === this.linkedList.$next.length) { 123 this.$container.append($.map( 124 self.linkedList.$next.itemsListArranger("shiftItems", self.columnsCount * self.settings.minimalRows), 125 function (item) { 126 self._internalDoSingleBlock($(item)); 127 return $(item); 128 } 129 )); 130 $items = this.getItems(); 131 } 132 133 this.$container.trigger("beforeListArrange"); 134 var delta = Date.now(); 135 136 // ÐеÑебиÑаем вÑе ÑлеменÑÑ ÑпиÑка 137 $items.each(function (index, element) { 138 if (0 === itemsInRow) { 139 realItemsInRow = 0; 140 } 141 if (rowsCount >= settings.minimalRows) { 142 ++extraItemsCount; 143 } 144 var $item = $(this), 145 canBlockExpand = self._canBlockExpand(actualColumn, columnsCount); 146 if ($item.is(":hidden")) { 147 $item.show(); 148 } 149 if ($item.is(settings.doubleBlockSelector)) { 150 // Ðвойной блок 151 if (!canBlockExpand) { 152 self._internalDoSingleBlock($item); 153 } 154 } else { 155 // ÐдинаÑнÑй блок 156 if ($item.is(settings.mustBeDoubleSelector) && canBlockExpand) { 157 self._internalDoDoubleBlock($item); 158 } 159 } 160 var blockWidth = $item.is(settings.doubleBlockSelector) ? 2 : 1; 161 actualColumn = (actualColumn + blockWidth) % columnsCount; 162 // ÐолиÑеÑÑво ÑлеменÑов в ÑекÑÑей ÑÑÑоке 163 itemsInRow = 0 === actualColumn ? 0 : (itemsInRow + 1); 164 if (0 === itemsInRow) { 165 ++rowsCount; 166 } 167 ++realItemsInRow; 168 }); 169 // СкÑÑваем ÑÑдÑ, коÑоÑÑе Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð½Ñ Ð½Ðµ полноÑÑÑÑ 170 var isRowComplete = 0 === itemsInRow; 171 if (!isRowComplete) { 172 if (this.hideIncompleteRow) { 173 var $itemsToHide = $items.slice(-itemsInRow); 174 $itemsToHide.hide(); 175 // ÐÑли оÑÑÑÑÑÑвÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ñе ÑлеменÑÑ, Ñо оÑобÑажаем Ñо, ÑÑо еÑÑÑ 176 if ($items.filter(":visible").length === 0) { 177 $items.show(); 178 } 179 }/* else if (null !== this.linkedList.$next) { 180 //if (itemsInRow > columnsCount / 2) { 181 if (rowsCount < settings.minimalRows) { 182 this.$container.append( 183 $.map(this.linkedList.$next.itemsListArranger("shiftItems", columnsCount - itemsInRow), function (item) { 184 self._internalDoSingleBlock($(item)); 185 return $(item); 186 }) 187 ); 188 } else { 189 this.linkedList.$next.itemsListArranger("unshiftItems", $itemsToHide); 190 } 191 }*/ 192 } 193 if (null !== this.linkedList.$next) { 194 if (rowsCount !== settings.minimalRows || !isRowComplete) { 195 var itemsCount; 196 //itemsInRow = 0 !== itemsInRow ? itemsInRow : columnsCount; 197 if (rowsCount < settings.minimalRows) { 198 itemsCount = settings.minimalRows * columnsCount - $items.length; 199 this.$container.append($.map( 200 this.linkedList.$next.itemsListArranger("shiftItems", itemsCount), 201 function (item) { 202 self._internalDoSingleBlock($(item)); 203 return $(item); 204 } 205 )); 206 this._arrangeItems(); 207 } else { 208 itemsCount = extraItemsCount; 209 this.linkedList.$next.itemsListArranger("unshiftItems", $items.slice(-itemsCount)); 210 } 211 } 212 } 213 214 this.$container.trigger("afterListArrange"); 215 /* 216 console.log(this.$container.prop("id") + ": arrange in " + (Date.now() - delta) + " ms, " + 217 columnsCount + " columns "); 218 */ 219 }; 220 221 ItemsListArranger.prototype._canBlockExpand = function (blockColumn, columnsCount, exp
221andWidth) { 222 expandWidth = expandWidth || 2; 223 return (blockColumn + expandWidth - 1) < columnsCount; 224 }; 225 226 ItemsListArranger.prototype._initEventHandlers = function () { 227 var self = this, 228 settings = this.settings; 229 $(window).on("resize." + ItemsListArranger.namespace, function (event) { 230 if (null !== self.linkedList.$prev) { 231 return; 232 } 233 var columnsCount = self._updateColumnsCount(); 234 if (self.columnsCount !== columnsCount) { 235 self.columnsCount = columnsCount; 236 self.$container.trigger("columnsCountChanged", this.columnsCount); 237 } 238 }); 239 if (settings.hookPageDataLoadedEvent) { 240 var eventName = settings.pageDataLoadedEvent + '.' + ItemsListArranger.namespace; 241 this.$container.on(eventName, function (event, $newItems) { 242 self._checkHideIncompleteRowMode(); 243 self._arrangeItems(); 244 }); 245 } 246 if (null !== self.linkedList.$prev) { 247 self.linkedList.$prev.on("afterListArrange", function (event) { 248 var columnsCount = self._updateColumnsCount(); 249 if (self.columnsCount !== columnsCount) { 250 self.columnsCount = columnsCount; 251 self.$container.trigger("columnsCountChanged", this.columnsCount); 252 } 253 }); 254 } 255 this.$container 256 .on("beforeListArrange." + ItemsListArranger.namespace, function (event) { 257 if (typeof settings.beforeListArrange === "function") { 258 $.proxy(settings.beforeListArrange, self)(); 259 } 260 }) 261 .on("afterListArrange." + ItemsListArranger.namespace, function (event) { 262 if (typeof settings.afterListArrange === "function") { 263 $.proxy(settings.afterListArrange, self)(); 264 } 265 }) 266 .on("columnsCountChanged." + ItemsListArranger.namespace, function (event, newColumnCount) { 267 self._arrangeItems(); 268 if (typeof settings.columnsCountChanged === "function") { 269 $.proxy(settings.columnsCountChanged, self)(newColumnCount); 270 } 271 }); 272 }; 273 274 ItemsListArranger.prototype.getItems = function () { 275 return $(this.settings.itemsSelector, this.$container); 276 }; 277 278 ItemsListArranger.prototype.shiftItems = function (count) { 279 var self = this, 280 items = this.getItems().splice(0, count); 281 $.each(items, function (index, item) { 282 $(item).detach(); 283 }); 284 if (count > items.length && null !== this.linkedList.$next && 1 === this.linkedList.$next.length) { 285 items = items.concat(this.linkedList.$next.itemsListArranger("shiftItems", count - items.length)); 286 } 287 if (null !== this.linkedList.$next && 1 === this.linkedList.$next.length) { 288 this.$container.append($.map( 289 self.linkedList.$next.itemsListArranger("shiftItems", Math.min(count, self.columnsCount * self.settings.minimalRows)), 290 function (item) { 291 self._internalDoSingleBlock($(item)); 292 return $(item); 293 } 294 )); 295 } 296 297 return items; 298 }; 299 300 ItemsListArranger.prototype.unshiftItems = function (items) { 301 if (0 === items.length) { 302 return; 303 } 304 var self = this, 305 containerItems = this.getItems(); 306 if (null !== this.linkedList.$next) { 307 var itemsToInsert = items.length >= containerItems.length ? 308 items.splice(items.length - containerItems.length).concat(containerItems) : 309 containerItems.splice(-items.length); 310 $.each(itemsToInsert, function (index, item) { 311 $(item).detach(); 312 }); 313 this.linkedList.$next.itemsListArranger("unshiftItems", itemsToInsert); 314 } 315 this.$container.prepend($.map(items, function (item) { 316 self._internalDoSingleBlock($(item)); 317 return $(item); 318 })); 319 }; 320 321 ItemsListArranger.methods = { 322 update: ItemsListArranger.prototype._updateColumnsCount, 323 getItems: ItemsListArranger.prototype.getItems, 324 shiftItems: ItemsListArranger.prototype.shiftItems, 325 unshiftItems: ItemsListArranger.prototype.unshiftItems 326 }; 327 328 var scopeArguments = arguments; 329 if ("string" === typeof option && "function" === typeof ItemsListArranger.methods[option]) { 330 var data = this.data("cis." + ItemsListArranger.namespace); 331 if (data) { 332 return ItemsListArranger.methods[option].apply(data, Array.prototype.slice.call(scopeArguments, 1)); 333 } 334 } 335 return this.each(function (index, element) { 336 var $this = $(this); 337 var data = $this.data("cis." + ItemsListArranger.namespace); 338 var options = "object" === typeof option && option; 339 340 if (!data) { 341 $this.data("cis." + ItemsListArranger.namespace, (data = new ItemsListArranger(this, options))); 342 } 343 if ("string" === typeof option && "function" === typeof ItemsListArranger.methods[option]) { 344 ItemsListArranger.methods[option].apply(data, Array.prototype.slice.call(scopeArguments, 1)); 345 } 346 }); 347 348 }; 349})(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.