PageSourceSearch

https://www.kimkimdir.net.tr/wp-content/themes/v1/js/freewall.js

js kimkimdir.net.tr collected 2026-10-02 14:00:17 UTC 46,414 bytes, 1,237 lines download raw bytes

1// created by Minh Nguyen;
2// version 1.04;
3
4(function($) {
5    
6    // for zeptojs;
7    $.isNumeric == null && ($.isNumeric = function(src) {
8        return src != null && src.constructor === Number;
9    });
10
11    $.isFunction == null && ($.isFunction = function(src) {
12        return src != null && src instanceof Function;
13    });
14
15    var $W = $(window);
16    var $D = $(document);
17    
18    var layoutManager = {
19        // default setting;
20        defaultConfig: {
21            animate: false,
22            cellW: 100, // function(container) {return 100;}
23            cellH: 100, // function(container) {return 100;}
24            delay: 0, // slowdown active block;
25            engine: 'giot', // 'giot' is a person name;
26            fixSize: null, // resize + adjust = fill gap;
27            //fixSize: 0, allow adjust size = no fill gap;
28            //fixSize: 1, no resize + no adjust = no fill gap;
29            gutterX: 15, // width spacing between blocks;
30            gutterY: 15, // height spacing between blocks;
31            selector: '> div',
32            draggable: false,
33            rightToLeft: false,
34            bottomToTop: false,
35            onStartSet: function() {},
36            onGapFound: function() {},
37            onComplete: function() {},
38            onResize: function() {},
39            onSetBlock: function() {}
40        },
41        plugin: {},
42        totalGrid: 1,
43        transition: false,
44        loadBlock: function(item, setting) {
45            var runtime = setting.runtime;
46            var $item = $(item);
47            var block = null;
48            var gutterX = runtime.gutterX;
49            var gutterY = runtime.gutterY;
50            var fixSize = parseInt($item.attr('data-fixSize'));
51            var blockId = runtime.lastId++ + '-' + this.totalGrid;
52            
53            //ignore dragging block;
54            if ($item.hasClass('fw-float')) return;
55            $item.attr({id: blockId, 'data-delay': item.index});
56
57            //remove animation for speed render;
58            if (setting.animate && this.transition) {
59                this.setTransition(item, "");
60            }
61            
62            // store original size;
63            $item.attr('data-height') == null && $item.attr('data-height', $item.height());
64            $item.attr('data-width') == null && $item.attr('data-width', $item.width());
65            var height = 1 * $item.attr('data-height');
66            var width = 1 * $item.attr('data-width');
67            var fixPos = $item.attr('data-position');
68
69            var cellH = runtime.cellH;
70            var cellW = runtime.cellW;
71            
72            var col = !width ? 0 : Math.round((width + gutterX) / cellW);
73            var row = !height ? 0 : Math.round((height + gutterY) / cellH);
74
75            isNaN(fixSize) && (fixSize = null);
76            // estimate size;
77            if (!fixSize && setting.cellH == 'auto') {
78                $item.width(cellW * col - gutterX);
79                item.style.height = "";
80                height = $item.height();
81                row = !height ? 0 : Math.round((height + gutterY) / cellH);
82            }
83
84            if (!fixSize && setting.cellW == 'auto') {
85                $item.height(cellH * row - gutterY);
86                item.style.width = "";
87                width = $item.width();
88                col = !width ? 0 : Math.round((width + gutterX) / cellW);
89            }
90            
91            // for none resize block;
92            if ((fixSize != null) && (col > runtime.limitCol || row > runtime.limitRow)) {
93                block = null;
94            } else {
95                // get smallest width and smallest height of block;
96                // using for image runtime;
97                row && row < runtime.minHoB && (runtime.minHoB = row);
98                col && col < runtime.minWoB && (runtime.minWoB = col);
99
100                // get biggest width and biggest height of block;
101                row > runtime.maxHoB && (runtime.maxHoB = row);
102                col > runtime.maxWoB && (runtime.maxWoB = col);
103
104                width == 0 && (col = 0);
105                height == 0 && (row = 0);
106
107                block = {
108                    id: blockId,
109                    width: col,
110                    height: row,
111                    fixSize: fixSize
112                };
113
114                // for fix position;
115                if (fixPos) {
116                    fixPos = fixPos.split("-");
117                    block.y = 1 * fixPos[0];
118                    block.x = 1 * fixPos[1];
119                    block.width = fixSize != null ? col : Math.min(col, runtime.limitCol - block.x);
120                    block.height = fixSize != null ? row : Math.min(row, runtime.limitRow - block.y);
121                    var holeId = block.y + "-" + block.x + "-" + block.width + "-" + block.height;
122                    runtime.holes[holeId] = {
123                        id: block.id,
124                        top: block.y,
125                        left: block.x,
126                        width: block.width,
127                        height: block.height
128                    };
129                    this.setBlock(block, setting);
130                }
131            }
132
133            // for css animation;
134            if ($item.attr("data-state") == null) {
135                $item.attr("data-state", "init");
136            } else {
137                $item.attr("data-state", "move");
138            }
139            return fixPos ? null : block;
140        },
141        setBlock: function(block, setting) {
142            var runtime = setting.runtime;
143            var gutterX = runtime.gutterX;
144            var gutterY = runtime.gutterY;
145            var height = block.height;
146            var width = block.width;
147            var cellH = runtime.cellH;
148            var cellW = runtime.cellW;
149            var x = block.x;
150            var y = block.y;
151
152            if (setting.rightToLeft) {
153                x = runtime.limitCol - x - width;
154            }
155            if (setting.bottomToTop) {
156                y = runtime.limitRow - y - height;
157            }
158
159            var realBlock = {
160                fixSize: block.fixSize,
161                top: y * cellH,
162                left: x  * cellW,
163                width: cellW * width - gutterX,
164                height: cellH * height - gutterY
165            };
166            
167            realBlock.top = 1 * realBlock.top.toFixed(2);
168            realBlock.left = 1 * realBlock.left.toFixed(2);
169            realBlock.width = 1 * realBlock.width.toFixed(2);
170            realBlock.height = 1 * realBlock.height.toFixed(2);
171
172            //runtime.length += 1;
173            block.id && (runtime.blocks[block.id] = realBlock);
174
175            // for append feature;
176            return realBlock;
177        },
178        showBlock: function(item, setting) {
179            var runtime = setting.runtime;
180            var method = setting.animate && !this.transition ? 'animate' : 'css';
181            var block = runtime.blocks[item.id];
182            var $item = $(item);
183            var self = this;
184            var start = $item.attr("data-state") != "move";
185            var trans = start ? "width 0.5s, height 0.5s" : "top 0.5s, left 0.5s, width 0.5s, height 0.5s, opacity 0.5s";
186            
187            item.delay && clearTimeout(item.delay);
188            //ignore dragging block;
189            if ($item.hasClass('fw-float')) return;
190            
191            // kill the old transition;
192            self.setTransition(item, "");
193            item.style.position = "absolute";
194            setting.onStartSet.call(item, block, setting);
195            
196            function action() {
197                // start to arrange;
198                start && $item.attr("data-state", "start");
199                // add animation by using css3 transition;
200                if (setting.animate && self.transition) {
201                    self.setTransition(item, trans);
202                }
203
204                // for hidden block;
205                if (!block) {
206                    //var position = $item.position(); <= make speed so slow;
207                    var height = parseInt(item.style.height) || 0;
208                    var width = parseInt(item.style.width) || 0;
209                    var left = parseInt(item.style.left) || 0;
210                    var top = parseInt(item.style.top) || 0;
211                    $item[method]({
212                        left: left + width / 2,
213                        top: top + height / 2,
214                        width: 0,
215                        height: 0,
216                        opacity: 0
217                    });
218                } else {
219                    if (block.fixSize) {
220                        block.height = 1 * $item.attr("data-height");
221                        block.width = 1 * $item.attr("data-width");
222                    }
223
224                    $item["css"]({
225                        opacity: 1,
226                        width: block.width,
227                        height: block.height
228                    });
229
230                    // for animating by javascript;
231                    $item[method]({
232                        top: block.top,
233                        left: block.left
234                    });
235
236                    if ($item.attr('data-nested') != null) {
237                        self.nestedGrid(item, setting);
238                    }
239                }
240
241                runtime.length -= 1;
242
243                setting.onSetBlock.call(item, block, setting);
244
245                runtime.length == 0 && setting.onComplete.call(item, block, setting);
246            }
247
248            setting.delay > 0 ? (item.delay = setTimeout(action, setting.delay * $item.attr("data-delay"))) : action(); 
249        },
250        nestedGrid: function(item, setting) {
251            var innerWall, $item = $(item), runtime = setting.runtime;
252            var gutterX = $item.attr("data-gutterX") || setting.gutterX;
253            var gutterY = $item.attr("data-gutterY") || setting.gutterY;
254            var method = $item.attr("data-method") || "fitZone";
255            var nested = $item.attr('data-nested') || "> div";
256            var cellH = $item.attr("data-cellH") || setting.cellH;
257            var cellW = $item.attr("data-cellW") || setting.cellW;
258            var block = runtime.blocks[item.id];
259            
260            if (block) {
261                innerWall = new freewall($item);
262                innerWall.reset({
263                    cellH: cellH,
264                    cellW: cellW,
265                    gutterX: 1 * gutterX,
266                    gutterY: 1 * gutterY,
267                    selector: nested
268                });
269
270                switch (method) {
271                    case "fitHeight":
272                        innerWall[method](block.height);
273                        break;
274                    case "fitWidth":
275                        innerWall[method](block.width);
276                        break;
277                    case "fitZone":
278                        innerWall[method](block.width, block.height);
279                        break;
280                }
281            }
282        },
283        adjustBlock: function(block, setting) {
284            var runtime = setting.runtime;
285            var gutterX = runtime.gutterX;
286            var gutterY = runtime.gutterY;
287            var $item = $("#" + block.id);
288            var cellH = runtime.cellH;
289            var cellW = runtime.cellW;
290
291            if (setting.cellH = 'auto') {
292                $item.width(block.width * cellW - gutterX);
293                $item.get(0).style = "";
294                block.height = Math.round(($item.height() + gutterY) / cellH);
295            }
296        },
297        adjustUnit: function(width, height, setting) {
298            var gutterX = setting.gutterX;
299            var gutterY = setting.gutterY;
300            var runtime = setting.runtime;
301            var cellW = setting.cellW;
302            var cellH = setting.cellH;
303
304            $.isFunction(cellW) && (cellW = cellW(width));
305            cellW = 1 * cellW;
306            !$.isNumeric(cellW) && (cellW = 1);
307            
308            $.isFunction(cellH) && (cellH = cellH(height));
309            cellH = 1 * cellH;
310            !$.isNumeric(cellH) && (cellH = 1);
311
312            if ($.isNumeric(width)) {
313                // adjust cell width via container;
314                cellW < 1 && (cellW = cellW * width);
315
316                // estimate total columns;
317                var limitCol = Math.max(1, Math.floor(width / cellW));
318
319                // adjust unit size for fit width;
320                if (!$.isNumeric(gutterX)) {
321                    gutterX = (width - limitCol * cellW) / Math.max(1, (limitCol - 1));
322                    gutterX = Math.max(0, gutterX);
323                }
324
325                limitCol = Math.floor((width + gutterX) / cellW);
326                runtime.cellW = (width + gutterX) / Math.max(limitCol, 1);
327                runtime.cellS = runtime.cellW / cellW;
328                runtime.gutterX = gutterX;
329                runtime.limitCol = limitCol;
330            } 
331
332            if ($.isNumeric(height)) {
333                // adjust cell height via container;
334                cellH < 1 && (cellH = cellH * height);
335
336                // estimate total rows;
337                var limitRow = Math.max(1, Math.floor(height / cellH));
338
339                // adjust size unit for fit height;
340                if (!$.isNumeric(gutterY)) {
341                    gutterY = (height - limitRow * cellH) / Math.max(1, (limitRow - 1));
342                    gutterY = Math.max(0, gutterY);
343                }
344
345                limitRow = Math.floor((height + gutterY) / cellH);
346                runtime.cellH = (height + gutterY) / Math.max(limitRow, 1);
347                runtime.cellS = runtime.cellH / cellH;
348                runtime.gutterY = gutterY;
349                runtime.limitRow = limitRow;
350            } 
351
352            if (!$.isNumeric(width)) {
353                // adjust cell width via cell height;
354                cellW < 1 && (cellW = runtime.cellH);
355                runtime.cellW = cellW != 1 ? cellW * runtime.cellS : 1;
356                runtime.gutterX = gutterX;
357                runtime.limitCol = 666666;
358            }
359
360            if (!$.isNumeric(height)) {
361                // adjust cell height via cell width;
362                cellH < 1 && (cellH = runtime.cellW);
363                runtime.cellH = cellH != 1 ? cellH * runtime.cellS : 1;
364                runtime.gutterY = gutterY;
365                runtime.limitRow = 666666;
366            }
367        },
368        resetGrid: function(runtime) {
369            runtime.blocks = {};
370            runtime.length = 0;
371            runtime.cellH = 0;
372            runtime.cellW = 0;
373            runtime.lastId = 1;
374            runtime.matrix = {};
375            runtime.totalCol = 0;
376            runtime.totalRow = 0;
377        },
378        setDragable: function(item, option) {
379            var isTouch = false;
380            var config = {
381                startX: 0, //start clientX;
382                startY: 0, 
383                top: 0,
384                left: 0,
385                proxy: null,
386                onDrop: function() {},
387                onDrag: function() {},
388                onStart: function() {}
389            };
390            
391            $(item).each(function() {
392                var setting = $.extend({}, config, option);
393                var ele = setting.proxy || this;
394                var $E = $(ele);
395                
396                var posStyle = $E.css("position");
397                posStyle != "absolute" && $E.css("position", "relative");
398                
399
400                function mouseDown(evt) {
401                    evt.stopPropagation();
402                    evt = evt.originalEvent;
403
404                    if (evt.touches) {
405                        isTouch = true;
406                        evt = evt.changedTouches[0];
407                    }
408
409                    if (evt.button != 2 && evt.which != 3) {
410                        setting.onStart.call(ele, evt);
411                        
412                        setting.startX = evt.clientX;
413                        setting.startY = evt.clientY;
414                        setting.top = parseInt($E.css("top")) || 0;
415                        setting.left = parseInt($E.css("left")) || 0;
416                        
417                        $D.bind("mouseup touchend", mouseUp);
418                        $D.bind("mousemove touchmove", mouseMove); 
419                    }
420
421                    return false;
422                };
423                
424                        
425                function mouseMove(evt) {
426                    evt = evt.originalEvent;
427                    isTouch && (evt = evt.changedTouches[0]);
428                    
429                    $E.css({
430                        top: setting.top - (setting.startY - evt.clientY),
431                        left: setting.left - (setting.startX - evt.clientX)
432                    });
433                    
434                    setting.onDrag.call(ele, evt);
435                };
436                
437                function mouseUp(evt) {
438                    evt = evt.originalEvent;
439                    isTouch && (evt = evt.changedTouches[0]);
440        
441                    setting.onDrop.call(ele, evt);
442
443                    $D.unbind("mouseup touchend", mouseUp);
444                    $D.unbind("mousemove touchmove", mouseMove);
445                };
446
447                // ignore drag drop on text field;
448                $(this).find("iframe, form, input, textarea, .ignore-drag")
449                .each(function() {
450                    $(this).on("touchstart mousedown", function(evt) {
451                        evt.stopPropagation();
452                    });
453                });
454                
455                $D.unbind("mouseup touchend", mouseUp);
456                $D.unbind("mousemove touchmove", mouseMove);
457                $E.unbind("mousedown touchstart").bind("mousedown touchstart", mouseDown);
458
459            });
460        },
461        setTransition: function(item, trans) {
462            var style = item.style;
463            var $item = $(item);
464                
465            // remove animation;
466            if (!this.transition && $item.stop) {
467                $item.stop();
468            } else if (style.webkitTransition != null) {
469                style.webkitTransition = trans;
470            } else if (style.MozTransition != null) {
471                style.MozTransition = trans;
472            } else if (style.msTransition != null) {
473                style.msTransition = trans;
474            } else if (style.OTransition != null) {
475                style.OTransition = trans;
476            } else {
477                style.transition = trans;
478            }
479        },
480        getFreeArea: function(t, l, runtime) {
481            var maxY = Math.min(t + runtime.maxHoB, runtime.limitRow);
482            var maxX = Math.min(l + runtime.maxWoB, runtime.limitCol);
483            var minX = maxX;
484            var minY = maxY;
485            var matrix = runtime.matrix;
486            
487            // find limit zone by horizon;
488            for (var y = t; y < minY; ++y) {
489                for (var x = l; x < maxX; ++x) {
490                    if (matrix[y + '-' + x]) {
491                        (l < x && x < minX) && (minX = x);
492                    }
493                }
494            }
495            
496            // find limit zone by vertical;
497            for (var y = t; y < maxY; ++y) {
498                for (var x = l; x < minX; ++x) {
499                    if (matrix[y + '-' + x]) {
500                        (t < y && y < minY) && (minY = y);
501                    }
502                }
503            }
504
505            return {
506                top: t,
507                left: l,
508                width: minX - l,
509                height: minY - t
510            };
511
512        },
513        setWallSize: function(runtime, container) {
514            var totalRow = runtime.totalRow;
515            var totalCol = runtime.totalCol;
516            var gutterY = runtime.gutterY;
517            var gutterX = runtime.gutterX;
518            var cellH = runtime.cellH;
519            var cellW = runtime.cellW;
520            var totalWidth = Math.max(0, cellW * totalCol - gutterX);
521            var totalHeight = Math.max(0, cellH * totalRow - gutterY);
522            
523            container.attr({
524                'data-total-col': totalCol,
525                'data-total-row': totalRow,
526                'data-wall-width': Math.ceil(totalWidth),
527                'data-wall-height': Math.ceil(totalHeight)
528            });
529
530            if (runtime.limitCol < runtime.limitRow) {
531                // do not set height with nesting grid;
532                !container.attr("data-height") && container.height(Math.ceil(totalHeight));
533            }
534        }
535    };
536
537    
538
539    var engine = {
540        // Giot just a person name;
541        giot: function(items, setting) {
542            var runtime = setting.runtime,
543                row = runtime.limitRow,
544                col = runtime.limitCol,
545                x = 0,
546                y = 0,
547                maxX = runtime.totalCol,
548                maxY = runtime.totalRow,
549                wall = {},
550                holes = runtime.holes,
551                block = null,
552                matrix = runtime.matrix,
553                bigLoop = Math.max(col, row),
554                freeArea = null,
555                misBlock = null,
556                fitWidth = col < row ? 1 : 0,
557                lastBlock = null,
558                smallLoop = Math.min(col, row);
559
560            // fill area with top, left, width, height;
561            function fillMatrix(id, t, l, w, h) {
562                for (var y = t; y < t + h;) {
563                    for (var x = l; x < l + w;) {
564                        matrix[y + '-' + x] = id;
565                        ++x > maxX && (maxX = x);
566                    }
567                    ++y > maxY && (maxY = y);
568                }
569            }
570            
571            // set a hole on the wall;
572            for (var i in holes) {
573                if (holes.hasOwnProperty(i)) {
574                    fillMatrix(holes[i]["id"] || true, holes[i]['top'], holes[i]['left'], holes[i]['width'], holes[i]['height']);
575                }
576            }
577            
578
579            for (var b = 0; b < bigLoop; ++b) {
580                if (!items.length) break;
581                fitWidth ? (y = b) : (x = b);
582                lastBlock = null;
583
584                for (var s = 0; s < smallLoop; ++s) {
585                    if (!items.length) break;
586                    fitWidth ? (x = s) : (y = s);
587                    if (runtime.matrix[y + '-' + x]) continue;
588                    freeArea = layoutManager.getFreeArea(y, x, runtime);
589                    block = null;
590                    for (var i = 0; i < items.length; ++i) {
591                        if (items[i].height > freeArea.height) continue;
592                        if (items[i].width > freeArea.width) continue;
593                        block = items.splice(i, 1)[0];
594                        break;
595                    }
596
597                    // trying resize the other block to fit gap;
598                    if (block == null && setting.fixSize == null) {
599                        // resize near block to fill gap;
600                        if (lastBlock && !fitWidth && runtime.minHoB > freeArea.height) {
601                            lastBlock.height += freeArea.height;
602                            fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
603                            layoutManager.setBlock(lastBlock, setting);
604                            continue;
605                        } else if (lastBlock && fitWidth && runtime.minWoB > freeArea.width) {
606                            lastBlock.width += freeArea.width;
607                            fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
608                            layoutManager.setBlock(lastBlock, setting);
609                            continue;
610                        } else {
611                            // get other block fill to gap;
612                            for (var i = 0; i < items.length; ++i) {
613                                if (items[i]['fixSize'] != null) continue;
614                                block = items.splice(i, 1)[0];
615                                if (fitWidth) {
616                                    block.width = freeArea.width;
617                                    if (setting.cellH == 'auto') {
618                                        layoutManager.adjustBlock(block, setting);
619                                    }
620                                    // for fitZone;
621                                    block.height = Math.min(block.height, freeArea.height);
622                                } else {
623                                    block.height = freeArea.height;
624                                    // for fitZone;
625                                    block.width = Math.min(block.width, freeArea.width);
626                                }
627                                break;
628                            }
629                        }
630                    }
631                    
632                    if (block != null) {
633                        wall[block.id] = {
634                            id: block.id,
635                            x: x,
636                            y: y,
637                            width: block.width,
638                            height: block.height,
639                            fixSize: block.fixSize
640                        };
641                        
642                        // keep success block for next round;
643                        lastBlock = wall[block.id];
644
645                        fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
646                        layoutManager.setBlock(lastBlock, setting);
647                    } else {
648                        // get expect area;
649                        var misBlock = {
650                            x: x,
651                            y: y,
652                            fixSize: 0
653                        };
654                        if (fitWidth) {
655                            misBlock.width = freeArea.width;
656                            misBlock.height = 0;
657                            var lastX = x - 1;
658                            var lastY = y;
659                            
660                            while (matrix[lastY + '-' + lastX]) {
661                                matrix[lastY + '-' + x] = true;
662                                misBlock.height += 1;
663                                lastY += 1;
664                            }
665                        } else {
666                            misBlock.height = freeArea.height;
667                            misBlock.width = 0;
668                            var lastY = y - 1;
669                            var lastX = x;
670                            
671                            while (matrix[lastY + '-' + lastX]) {
672                                matrix[y + '-' + lastX] = true;
673                                misBlock.width += 1;
674                                lastX += 1;
675                            }
676                        }
677                        setting.onGapFound(layoutManager.setBlock(misBlock, setting), setting);
678                    }
679                }
680
681            }
682
683            runtime.matrix = matrix;
684            runtime.totalRow = maxY;
685            runtime.totalCol = maxX;
686        }
687    };
688
689
690
691    window.freewall = function(selector) {
692        
693        var container = $(selector);
694        if (container.css('position') == 'static') {
695            container.css('position', 'relative');
696        }
697        var MAX = Number.MAX_VALUE;
698        var klass = this;
699        // increase the instance index;
700        layoutManager.totalGrid += 1;
701
702        var setting = $.extend({}, layoutManager.defaultConfig);
703        var runtime = {
704            blocks: {}, // store all items;
705            events: {}, // store custome events;
706            matrix: {},
707            holes: {}, // forbidden zone;
708            
709            cellW: 0,
710            cellH: 0, // unit adjust;
711            cellS: 1, // unit scale;
712            
713            filter: '', // filter selector;
714            
715            lastId: 0,
716            length: 0,
717
718            maxWoB: 0, // max width of block;
719            maxHoB: 0,
720            minWoB: MAX, 
721            minHoB: MAX, // min height of block;
722
723            running: 0, // flag to check layout arranging;
724
725            gutterX: 15, 
726            gutterY: 15,
727
728            totalCol: 0,
729            totalRow: 0,
730
731            limitCol: 666666, // maximum column; 
732            limitRow: 666666,
733            
734            currentMethod: null,
735            currentArguments: []
736        };
737        setting.runtime = runtime;
738        
739        // check browser support transition;
740        var bodyStyle = document.body.style;
741        if (!layoutManager.transition) {
742            (bodyStyle.webkitTransition != null ||
743            bodyStyle.MozTransition != null ||
744            bodyStyle.msTransition != null ||
745            bodyStyle.OTransition != null ||
746            bodyStyle.transition != null) &&
747            (layoutManager.transition = true);
748        }
749        
750
751        function setDragable(item) {
752            
753            var gutterX = runtime.gutterX;
754            var gutterY = runtime.gutterY;
755            var cellH = runtime.cellH;
756            var cellW = runtime.cellW;
757            var $item = $(item);
758
759            layoutManager.setDragable(item, {
760                onStart: function(event) {
761                    if (setting.animate && layoutManager.transition) {
762                        layoutManager.setTransition(this, "");
763                    }
764                    $item.css('z-index', 9999).addClass('fw-float');
765                },
766                onDrag: function(evt, tracker) {
767                    var position = $item.position();
768                    var top = Math.round(position.top / cellH);
769                    var left = Math.round(position.left / cellW);
770                    var width = Math.round($item.width() / cellW);
771                    var height = Math.round($item.height() / cellH);
772                    top = Math.min(Math.max(0, top), runtime.limitRow - height);
773                    left = Math.min(Math.max(0, left), runtime.limitCol - width);
774                    klass.setHoles({top: top, left: left, width: width, height: height});
775                    klass.refresh();
776                },
777                onDrop: function() {
778                    var position = $item.position();
779                    var top = Math.round(position.top / cellH);
780                    var left = Math.round(position.left / cellW);
781                    var width = Math.round($item.width() / cellW);
782                    var height = Math.round($item.height() / cellH);
783                    top = Math.min(Math.max(0, top), runtime.limitRow - height);
784                    left = Math.min(Math.max(0, left), runtime.limitCol - width);
785
786                    $item.removeClass('fw-float');
787                    $item.css({
788                        zIndex: "auto",
789                        top: top * cellH,
790                        left: left * cellW
791                    });
792                    
793                    //check old drag element;
794                    var x, y, key, oldDropId;
795                    for (y = 0; y < height; ++y) {
796                        for (x = 0; x < width; ++x) {
797                            key = (y + top) + "-" + (x + left);
798                            oldDropId = runtime.matrix[key];
799                            if (oldDropId && oldDropId != true) {
800                                $("#" + oldDropId).removeAttr("data-position");
801                            }
802                        }
803                    }
804                    
805                    runtime.holes = {};
806                    
807                    $item.attr({
808                        "data-width": $item.width(),
809                        "data-height": $item.height(),
810                        "data-position": top + "-" + left
811                    });
812
813                    klass.refresh();
814                }
815            });
816        }
817        
818
819        $.extend(klass, {
820            
821            addCustomEvent: function(name, func) {
822                var events = runtime.events;
823                name = name.toLowerCase();
824                !events[name] && (events[name] = []);
825                func.eid = events[name].length;
826                events[name].push(func);
827                return this;
828            },
829
830            appendBlock: function(items) {
831                var allBlock = $(items).appendTo(container);
832                var block = null;
833                var activeBlock = [];
834                
835                allBlock.each(function(index, item) {
836                    item.index = ++index;
837                    if (block = layoutManager.loadBlock(item, setting)) {
838                        activeBlock.push(block);
839                        klass.fireEvent('onBlockLoad', item, setting);
840                    }
841                });
842
843                engine[setting.engine](activeBlock, setting);
844                
845                layoutManager.setWallSize(runtime, container);
846                
847                runtime.length = allBlock.length;
848
849                allBlock.each(function(index, item) {
850                    setting.draggable && setDragable(item);
851                    layoutManager.showBlock(item, setting);
852                    klass.fireEvent('onBlockShow', item, setting);
853                });
854            },
855            /*
856            add one or more blank area (hole) on layout;
857            example:
858                
859                wall.appendHoles({
860                    top: 10,
861                    left: 36,
862                    width: 2,
863                    height: 6
864                });
865
866                wall.appendHoles([
867                    {
868                        top: 16,
869                        left: 16,
870                        width: 8,
871                        height: 2
872                    },
873                    {
874                        top: 10,
875                        left: 36,
876                        width: 2,
877                        height: 6
878                    }
879                ]);
880
881            */
882            appendHoles: function(holes) {
883                var newHoles = [].concat(holes), h = {}, i;
884                for (i = 0; i < newHoles.length; ++i) {
885                    h = newHoles[i];
886                    runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height] = h;
887                }
888                return this;
889            },
890
891            container: container,
892
893            fillHoles: function(holes) {
894                if (arguments.length == 0) {
895                    runtime.holes = {};
896                } else {
897                    var newHoles = [].concat(holes), h = {}, i;
898                    for (i = 0; i < newHoles.length; ++i) {
899                        h = newHoles[i];
900                        runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height] = null;
901                    }
902                }
903                return this;
904            },
905
906            filter: function(filter) {
907                runtime.filter = filter;
908                runtime.currentMethod && this.refresh();
909                return this;
910            },
911
912            fireEvent: function(name, object, setting) {
913                var events = runtime.events;
914                name = name.toLowerCase();
915                if (events[name] && events[name].length) {
916                    for (var i = 0; i < events[name].length; ++i) {
917                        events[name][i].call(object, setting);
918                    }
919                }
920                return this;
921            },
922
923            fitHeight: function(height) {
924                var allBlock = container.find(setting.selector).removeAttr('id'),
925                    block = null,
926                    activeBlock = [];
927
928                height = height ? height : container.height() || $W.height();
929                
930                runtime.currentMethod = arguments.callee;
931                runtime.currentArguments = arguments;
932                
933                layoutManager.resetGrid(runtime);
934                layoutManager.adjustUnit('auto', height, setting);
935                
936                if (runtime.filter) {
937                    allBlock.data('active', 0);
938                    allBlock.filter(runtime.filter).data('active', 1);
939                } else {
940                    allBlock.data('active', 1);
941                }
942
943                klass.fireEvent('onGridReady', container, setting);
944
945                allBlock.each(function(index, item) {
946                    var $item = $(item);
947                    item.index = ++index;
948                    if (block = layoutManager.loadBlock(item, setting)) {
949                        $item.data("active") && activeBlock.push(block);
950                        klass.fireEvent('onBlockLoad', item, setting);
951                    }
952                });
953                
954                klass.fireEvent('onGridLoad', container, setting);
955
956                engine[setting.engine](activeBlock, setting);
957                
958                layoutManager.setWallSize(runtime, container);
959
960                klass.fireEvent('onGridArrange', container, setting);
961
962                runtime.length = allBlock.length;
963
964                allBlock.each(function(index, item) {
965                    setting.draggable && setDragable(item);
966                    layoutManager.showBlock(item, setting);
967                    klass.fireEvent('onBlockShow', item, setting);
968                });
969
970                klass.fireEvent('onGridShow', container, setting);
971            },
972
973            fitWidth: function(width) {
974                var allBlock = container.find(setting.selector).removeAttr('id'),
975                    block = null,
976                    activeBlock = [];
977
978                width = width ? width : container.width() || $W.width();
979
980                runtime.currentMethod = arguments.callee;
981                runtime.currentArguments = arguments;
982                
983                layoutManager.resetGrid(runtime);
984                layoutManager.adjustUnit(width, 'auto', setting);
985                
986                if (runtime.filter) {
987                    allBlock.data('active', 0);
988                    allBlock.filter(runtime.filter).data('active', 1);
989                } else {
990                    allBlock.data('active', 1);
991                }
992                
993                klass.fireEvent('onGridReady', container, setting);
994
995                allBlock.each(function(index, item) {
996                    var $item = $(item);
997                    item.index = ++index;
998                    if (block = layoutManager.loadBlock(item, setting)) {
999                        $item.data("active") && activeBlock.push(block);
1000                        klass.fireEvent('onBlockLoad', item, setting);
1001                    }
1002                });
1003                
1004                klass.fireEvent('onGridLoad', container, setting);
1005                
1006                engine[setting.engine](activeBlock, setting);
1007
1008                layoutManager.setWallSize(runtime, container);
1009                
1010                klass.fireEvent('onGridArrange', container, setting);
1011
1012                runtime.length = allBlock.length;
1013
1014                allBlock.each(function(index, item) {
1015                    setting.draggable && setDragable(item);
1016                    layoutManager.showBlock(item, setting);
1017                    klass.fireEvent('onBlockShow', item, setting);
1018                });
1019
1020                klass.fireEvent('onGridShow', container, setting);
1021            },
1022
1023            fitZone: function(width, height) {
1024                var allBlock = container.find(setting.selector).removeAttr('id'),
1025                    block = null,
1026                    activeBlock = [];
1027
1028                height = height ? height : container.height() || $W.height();
1029                width = width ? width : container.width() || $W.width();
1030                
1031                runtime.currentMethod = arguments.callee;
1032                runtime.currentArguments = arguments;
1033                
1034                layoutManager.resetGrid(runtime);
1035                layoutManager.adjustUnit(width, height, setting);
1036
1037                if (runtime.filter) {
1038                    allBlock.data('active', 0);
1039                    allBlock.filter(runtime.filter).data('active', 1);
1040                } else {
1041                    allBlock.data('active', 1);
1042                }
1043                
1044                klass.fireEvent('onGridReady', container, setting);
1045
1046                allBlock.each(function(index, item) {
1047                    var $item = $(item);
1048                    item.index = ++index;
1049                    if (block = layoutManager.loadBlock(item, setting)) {
1050                        $item.data("active") && activeBlock.push(block);
1051                        klass.fireEvent('onBlockLoad', item, setting);
1052                    }
1053                });
1054
1055                klass.fireEvent('onGridLoad', container, setting);
1056
1057                engine[setting.engine](activeBlock, setting);
1058                
1059                layoutManager.setWallSize(runtime, container);
1060                
1061                klass.fireEvent('onGridArrange', container, setting);
1062
1063                runtime.length = allBlock.length;
1064               
1065                allBlock.each(function(index, item) {
1066                    setting.draggable && setDragable(item);
1067                    layoutManager.showBlock(item, setting);
1068                    klass.fireEvent('onBlockShow', item, setting);
1069                });
1070
1071                klass.fireEvent('onGridShow', container, setting);
1072            },
1073
1074            /*
1075            set block with special position, the top and left are multiple of unit width/height;
1076            example:
1077
1078                wall.fixSize({
1079                    top: 0,
1080                    left: 0,
1081                    block: $('.free')
1082                });
1083            */
1084            fixPos: function(option) {
1085                $(option.block).attr({'data-position': option.top + "-" + option.left});
1086                return this;
1087            },
1088
1089            /*
1090            set block with special size, the width and height are multiple of unit width/height;
1091            example:
1092
1093                wall.fixSize({
1094                    height: 5,
1095                    width: 2,
1096                    block: $('.free')
1097                });
1098            */
1099            fixSize: function(option) {
1100                option.width != null && $(option.block).attr({'data-width': option.width});
1101                option.height != null && $(option.block).attr({'data-height': option.height});
1102                return this;
1103            },
1104
1105            prepend: function(items) {
1106                container.prepend(items);
1107                runtime.currentMethod && this.refresh();
1108                return this;
1109            },
1110
1111            refresh: function() {
1112                var params = arguments.length ? arguments : runtime.currentArguments;
1113                runtime.currentMethod == null && (runtime.currentMethod = this.fitWidth);
1114                runtime.currentMethod.apply(this, Array.prototype.slice.call(params, 0));
1115                return this;
1116            },
1117
1118            /*
1119            custom layout setting;
1120            example:
1121
1122                wall.reset({
1123                    selector: '.brick',
1124                    animate: true,
1125                    cellW: 160,
1126                    cellH: 160,
1127                    delay: 50,
1128                    onResize: function() {
1129                        wall.fitWidth();
1130                    }
1131                });
1132            */
1133            reset: function(option) {
1134                $.extend(setting, option);
1135                return this;
1136            },
1137            
1138            /*
1139            create one or more blank area (hole) on layout;
1140            example:
1141                
1142                wall.setHoles({
1143                    top: 2,
1144                    left: 2,
1145                    width: 2,
1146                    height: 2
1147                });
1148            */
1149            
1150            setHoles: function(holes) {
1151                var newHoles = [].concat(holes), h = {}, i;
1152                runtime.holes = {};
1153                for (i = 0; i < newHoles.length; ++i) {
1154                    h = newHoles[i];
1155                    runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height] = h;
1156                }
1157                return this;
1158            },
1159
1160            unFilter: function() {
1161                delete runtime.filter;
1162                this.refresh();
1163                return this;
1164            }
1165        });
1166        
1167        container.attr('data-min-width', Math.floor($W.width() / 80) * 80);
1168        // execute plugins;
1169        for (var i in layoutManager.plugin) {
1170            if (layoutManager.plugin.hasOwnProperty(i)) {
1171                layoutManager.plugin[i].call(klass, setting, container);
1172            }
1173        }
1174
1175        // setup resize event;
1176        $W.resize(function() {
1177            if (runtime.running) return;
1178            runtime.running = 1;
1179            setTimeout(function() {
1180                runtime.running = 0;
1181                setting.onResize.call(klass, container);
1182            }, 122);
1183            container.attr('data-min-width', Math.floor($W.width() / 80) * 80);
1184        });
1185    };
1186
1187
1188    /*
1189    support create new plugin;
1190    example:
1191        
1192        freewall.createPlugin({
1193            centering: function(setting, container) {
1194                console.log(this);
1195                console.log(setting);
1196            }
1197        }).addConfig({
1198            offsetLeft: 0
1199        });
1200    */
1201    freewall.createPlugin = function(pluginData) {
1202        // register new plugin;
1203        $.extend(layoutManager.plugin, pluginData);
1204        return {
1205            addConfig: function(newConfig) {
1206                // add default setting;
1207                $.extend(layoutManager.defaultConfig, newConfig);    
1208            }
1209        }
1210    };
1211
1212    /*
1213    support create new arrange algorithm;
1214    example:
1215
1216        freewall.createEngine({
1217            slice: function(items, setting) {
1218                // slice engine;
1219            }
1220        });
1221    */
1222    freewall.createEngine = function(engineData) {
1223        // create new engine;
1224        $.extend(engine, engineData);
1225    };
1226
1227    /*
1228    support access helper function;
1229    example:
1230
1231        freewall.getMethod('setBlock')(block, setting);
1232    */
1233    freewall.getMethod = function(method) {
1234        return layoutManager[method];
1235    };
1236 
1237})(window.Zepto || window.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.