Your IP : 3.135.182.54
// created by Minh Nguyen;
// version 1.05;
(function($) {
// for zeptojs;
$.isNumeric == null && ($.isNumeric = function(src) {
return src != null && src.constructor === Number;
});
$.isFunction == null && ($.isFunction = function(src) {
return src != null && src instanceof Function;
});
var $W = $(window);
var $D = $(document);
var layoutManager = {
// default setting;
defaultConfig: {
animate: false,
cellW: 100, // function(container) {return 100;}
cellH: 100, // function(container) {return 100;}
delay: 0, // slowdown active block;
engine: 'giot', // 'giot' is a person name;
fixSize: null, // resize + adjust = fill gap;
//fixSize: 0, resize but keep ratio = no fill gap;
//fixSize: 1, no resize + no adjust = no fill gap;
gutterX: 15, // width spacing between blocks;
gutterY: 15, // height spacing between blocks;
keepOrder: false,
selector: '> div',
draggable: false,
cacheSize: true, // caches the original size of block;
rightToLeft: false,
bottomToTop: false,
onGapFound: function() {},
onComplete: function() {},
onResize: function() {},
onBlockDrag: function() {},
onBlockMove: function() {},
onBlockDrop: function() {},
onBlockReady: function() {},
onBlockFinish: function() {},
onBlockActive: function() {},
onBlockResize: function() {}
},
plugin: {},
totalGrid: 1,
transition: false,
loadBlock: function(item, setting) {
var runtime = setting.runtime;
var gutterX = runtime.gutterX;
var gutterY = runtime.gutterY;
var cellH = runtime.cellH;
var cellW = runtime.cellW;
var block = null;
var $item = $(item);
var active = $item.data("active");
var fixPos = $item.attr('data-position');
var fixSize = parseInt($item.attr('data-fixSize'));
var blockId = runtime.lastId++ + '-' + runtime.totalGrid;
//ignore dragging block;
if ($item.hasClass('fw-float')) return null;
$item.attr({id: blockId, 'data-delay': item.index});
//remove animation for speed render;
if (setting.animate && this.transition) {
this.setTransition(item, "");
}
isNaN(fixSize) && (fixSize = null);
(fixSize == null) && (fixSize = setting.fixSize);
var makeRound = (!fixSize) ? "round" : "ceil";
// store original size;
$item.attr('data-height') == null && $item.attr('data-height', $item.height());
$item.attr('data-width') == null && $item.attr('data-width', $item.width());
var height = 1 * $item.attr('data-height');
var width = 1 * $item.attr('data-width');
if (!setting.cacheSize) {
item.style.width = "";
width = $item.width();
item.style.height = "";
height = $item.height();
}
var col = !width ? 0 : Math[makeRound]((width + gutterX) / cellW);
var row = !height ? 0 : Math[makeRound]((height + gutterY) / cellH);
// estimate size;
if (!fixSize && setting.cellH == 'auto') {
$item.width(cellW * col - gutterX);
item.style.height = "";
height = $item.height();
row = !height ? 0 : Math.round((height + gutterY) / cellH);
}
if (!fixSize && setting.cellW == 'auto') {
$item.height(cellH * row - gutterY);
item.style.width = "";
width = $item.width();
col = !width ? 0 : Math.round((width + gutterX) / cellW);
}
// for none resize block;
if ((fixSize != null) && (col > runtime.limitCol || row > runtime.limitRow)) {
block = null;
} else {
// get smallest width and smallest height of block;
// using for image runtime;
row && row < runtime.minHoB && (runtime.minHoB = row);
col && col < runtime.minWoB && (runtime.minWoB = col);
// get biggest width and biggest height of block;
row > runtime.maxHoB && (runtime.maxHoB = row);
col > runtime.maxWoB && (runtime.maxWoB = col);
width == 0 && (col = 0);
height == 0 && (row = 0);
block = {
resize: false,
id: blockId,
width: col,
height: row,
fixSize: fixSize
};
// for fix position;
if (fixPos) {
fixPos = fixPos.split("-");
block.y = 1 * fixPos[0];
block.x = 1 * fixPos[1];
block.width = fixSize != null ? col : Math.min(col, runtime.limitCol - block.x);
block.height = fixSize != null ? row : Math.min(row, runtime.limitRow - block.y);
var holeId = block.y + "-" + block.x + "-" + block.width + "-" + block.height;
if (active) {
runtime.holes[holeId] = {
id: block.id,
top: block.y,
left: block.x,
width: block.width,
height: block.height
};
this.setBlock(block, setting);
} else {
delete runtime.holes[holeId];
}
}
}
// for css animation;
if ($item.attr("data-state") == null) {
$item.attr("data-state", "init");
} else {
$item.attr("data-state", "move");
}
setting.onBlockReady.call(item, block, setting);
return (fixPos && active) ? null : block;
},
setBlock: function(block, setting) {
var runtime = setting.runtime;
var gutterX = runtime.gutterX;
var gutterY = runtime.gutterY;
var height = block.height;
var width = block.width;
var cellH = runtime.cellH;
var cellW = runtime.cellW;
var x = block.x;
var y = block.y;
if (setting.rightToLeft) {
x = runtime.limitCol - x - width;
}
if (setting.bottomToTop) {
y = runtime.limitRow - y - height;
}
var realBlock = {
fixSize: block.fixSize,
resize: block.resize,
top: y * cellH,
left: x * cellW,
width: cellW * width - gutterX,
height: cellH * height - gutterY
};
realBlock.top = 1 * realBlock.top.toFixed(2);
realBlock.left = 1 * realBlock.left.toFixed(2);
realBlock.width = 1 * realBlock.width.toFixed(2);
realBlock.height = 1 * realBlock.height.toFixed(2);
//runtime.length += 1;
block.id && (runtime.blocks[block.id] = realBlock);
// for append feature;
return realBlock;
},
showBlock: function(item, setting) {
var runtime = setting.runtime;
var method = setting.animate && !this.transition ? 'animate' : 'css';
var block = runtime.blocks[item.id];
var $item = $(item);
var self = this;
var start = $item.attr("data-state") != "move";
var trans = start ? "width 0.5s, height 0.5s" : "top 0.5s, left 0.5s, width 0.5s, height 0.5s, opacity 0.5s";
item.delay && clearTimeout(item.delay);
//ignore dragging block;
if ($item.hasClass('fw-float')) return;
// kill the old transition;
self.setTransition(item, "");
item.style.position = "absolute";
setting.onBlockActive.call(item, block, setting);
function action() {
// start to arrange;
start && $item.attr("data-state", "start");
// add animation by using css3 transition;
if (setting.animate && self.transition) {
self.setTransition(item, trans);
}
// for hidden block;
if (!block) {
//var position = $item.position(); <= make speed so slow;
var height = parseInt(item.style.height) || 0;
var width = parseInt(item.style.width) || 0;
var left = parseInt(item.style.left) || 0;
var top = parseInt(item.style.top) || 0;
$item[method]({
left: left + width / 2,
top: top + height / 2,
width: 0,
height: 0,
opacity: 0
});
} else {
if (block.fixSize) {
block.height = 1 * $item.attr("data-height");
block.width = 1 * $item.attr("data-width");
}
$item["css"]({
opacity: 1,
width: block.width,
height: block.height
});
// for animating by javascript;
$item[method]({
top: block.top,
left: block.left
});
if ($item.attr('data-nested') != null) {
self.nestedGrid(item, setting);
}
}
runtime.length -= 1;
setting.onBlockFinish.call(item, block, setting);
runtime.length == 0 && setting.onComplete.call(item, block, setting);
}
block && block.resize && setting.onBlockResize.call(item, block, setting);
setting.delay > 0 ? (item.delay = setTimeout(action, setting.delay * $item.attr("data-delay"))) : action();
},
nestedGrid: function(item, setting) {
var innerWall, $item = $(item), runtime = setting.runtime;
var gutterX = $item.attr("data-gutterX") || setting.gutterX;
var gutterY = $item.attr("data-gutterY") || setting.gutterY;
var method = $item.attr("data-method") || "fitZone";
var nested = $item.attr('data-nested') || "> div";
var cellH = $item.attr("data-cellH") || setting.cellH;
var cellW = $item.attr("data-cellW") || setting.cellW;
var block = runtime.blocks[item.id];
if (block) {
innerWall = new Freewall($item);
innerWall.reset({
cellH: cellH,
cellW: cellW,
gutterX: 1 * gutterX,
gutterY: 1 * gutterY,
selector: nested,
cacheSize: false
});
switch (method) {
case "fitHeight":
innerWall[method](block.height);
break;
case "fitWidth":
innerWall[method](block.width);
break;
case "fitZone":
innerWall[method](block.width, block.height);
break;
}
}
},
adjustBlock: function(block, setting) {
var runtime = setting.runtime;
var gutterX = runtime.gutterX;
var gutterY = runtime.gutterY;
var $item = $("#" + block.id);
var cellH = runtime.cellH;
var cellW = runtime.cellW;
if (setting.cellH == 'auto') {
$item.width(block.width * cellW - gutterX);
$item[0].style.height = "";
block.height = Math.round(($item.height() + gutterY) / cellH);
}
},
adjustUnit: function(width, height, setting) {
var gutterX = setting.gutterX;
var gutterY = setting.gutterY;
var runtime = setting.runtime;
var cellW = setting.cellW;
var cellH = setting.cellH;
$.isFunction(cellW) && (cellW = cellW(width));
cellW = 1 * cellW;
!$.isNumeric(cellW) && (cellW = 1);
$.isFunction(cellH) && (cellH = cellH(height));
cellH = 1 * cellH;
!$.isNumeric(cellH) && (cellH = 1);
if ($.isNumeric(width)) {
// adjust cell width via container;
cellW < 1 && (cellW = cellW * width);
// estimate total columns;
var limitCol = Math.max(1, Math.floor(width / cellW));
// adjust unit size for fit width;
if (!$.isNumeric(gutterX)) {
gutterX = (width - limitCol * cellW) / Math.max(1, (limitCol - 1));
gutterX = Math.max(0, gutterX);
}
limitCol = Math.floor((width + gutterX) / cellW);
runtime.cellW = (width + gutterX) / Math.max(limitCol, 1);
runtime.cellS = runtime.cellW / cellW;
runtime.gutterX = gutterX;
runtime.limitCol = limitCol;
}
if ($.isNumeric(height)) {
// adjust cell height via container;
cellH < 1 && (cellH = cellH * height);
// estimate total rows;
var limitRow = Math.max(1, Math.floor(height / cellH));
// adjust size unit for fit height;
if (!$.isNumeric(gutterY)) {
gutterY = (height - limitRow * cellH) / Math.max(1, (limitRow - 1));
gutterY = Math.max(0, gutterY);
}
limitRow = Math.floor((height + gutterY) / cellH);
runtime.cellH = (height + gutterY) / Math.max(limitRow, 1);
runtime.cellS = runtime.cellH / cellH;
runtime.gutterY = gutterY;
runtime.limitRow = limitRow;
}
if (!$.isNumeric(width)) {
// adjust cell width via cell height;
cellW < 1 && (cellW = runtime.cellH);
runtime.cellW = cellW != 1 ? cellW * runtime.cellS : 1;
runtime.gutterX = gutterX;
runtime.limitCol = 666666;
}
if (!$.isNumeric(height)) {
// adjust cell height via cell width;
cellH < 1 && (cellH = runtime.cellW);
runtime.cellH = cellH != 1 ? cellH * runtime.cellS : 1;
runtime.gutterY = gutterY;
runtime.limitRow = 666666;
}
runtime.keepOrder = setting.keepOrder;
},
resetGrid: function(runtime) {
runtime.blocks = {};
runtime.length = 0;
runtime.cellH = 0;
runtime.cellW = 0;
runtime.lastId = 1;
runtime.matrix = {};
runtime.totalCol = 0;
runtime.totalRow = 0;
},
setDraggable: function(item, option) {
var isTouch = false;
var config = {
startX: 0, //start clientX;
startY: 0,
top: 0,
left: 0,
handle: null,
onDrop: function() {},
onDrag: function() {},
onStart: function() {}
};
$(item).each(function() {
var setting = $.extend({}, config, option);
var handle = setting.handle || this;
var ele = this;
var $E = $(ele);
var $H = $(handle);
var posStyle = $E.css("position");
posStyle != "absolute" && $E.css("position", "relative");
function mouseDown(evt) {
evt.stopPropagation();
evt = evt.originalEvent;
if (evt.touches) {
isTouch = true;
evt = evt.changedTouches[0];
}
if (evt.button != 2 && evt.which != 3) {
setting.onStart.call(ele, evt);
setting.startX = evt.clientX;
setting.startY = evt.clientY;
setting.top = parseInt($E.css("top")) || 0;
setting.left = parseInt($E.css("left")) || 0;
$D.bind("mouseup touchend", mouseUp);
$D.bind("mousemove touchmove", mouseMove);
}
return false;
};
function mouseMove(evt) {
evt = evt.originalEvent;
isTouch && (evt = evt.changedTouches[0]);
$E.css({
top: setting.top - (setting.startY - evt.clientY),
left: setting.left - (setting.startX - evt.clientX)
});
setting.onDrag.call(ele, evt);
};
function mouseUp(evt) {
evt = evt.originalEvent;
isTouch && (evt = evt.changedTouches[0]);
setting.onDrop.call(ele, evt);
$D.unbind("mouseup touchend", mouseUp);
$D.unbind("mousemove touchmove", mouseMove);
};
// ignore drag drop on text field;
$E.find("iframe, form, input, textarea, .ignore-drag")
.each(function() {
$(this).on("touchstart mousedown", function(evt) {
evt.stopPropagation();
});
});
$D.unbind("mouseup touchend", mouseUp);
$D.unbind("mousemove touchmove", mouseMove);
$H.unbind("mousedown touchstart").bind("mousedown touchstart", mouseDown);
});
},
setTransition: function(item, trans) {
var style = item.style;
var $item = $(item);
// remove animation;
if (!this.transition && $item.stop) {
$item.stop();
} else if (style.webkitTransition != null) {
style.webkitTransition = trans;
} else if (style.MozTransition != null) {
style.MozTransition = trans;
} else if (style.msTransition != null) {
style.msTransition = trans;
} else if (style.OTransition != null) {
style.OTransition = trans;
} else {
style.transition = trans;
}
},
getFreeArea: function(t, l, runtime) {
var maxY = Math.min(t + runtime.maxHoB, runtime.limitRow);
var maxX = Math.min(l + runtime.maxWoB, runtime.limitCol);
var minX = maxX;
var minY = maxY;
var matrix = runtime.matrix;
// find limit zone by horizon;
for (var y = t; y < minY; ++y) {
for (var x = l; x < maxX; ++x) {
if (matrix[y + '-' + x]) {
(l < x && x < minX) && (minX = x);
}
}
}
// find limit zone by vertical;
for (var y = t; y < maxY; ++y) {
for (var x = l; x < minX; ++x) {
if (matrix[y + '-' + x]) {
(t < y && y < minY) && (minY = y);
}
}
}
return {
top: t,
left: l,
width: minX - l,
height: minY - t
};
},
setWallSize: function(runtime, container) {
var totalRow = runtime.totalRow;
var totalCol = runtime.totalCol;
var gutterY = runtime.gutterY;
var gutterX = runtime.gutterX;
var cellH = runtime.cellH;
var cellW = runtime.cellW;
var totalWidth = Math.max(0, cellW * totalCol - gutterX);
var totalHeight = Math.max(0, cellH * totalRow - gutterY);
container.attr({
'data-total-col': totalCol,
'data-total-row': totalRow,
'data-wall-width': Math.ceil(totalWidth),
'data-wall-height': Math.ceil(totalHeight)
});
if (runtime.limitCol < runtime.limitRow) {
// do not set height with nesting grid;
!container.attr("data-height") && container.height(Math.ceil(totalHeight));
}
}
};
var engine = {
// Giot just a person name;
giot: function(items, setting) {
var runtime = setting.runtime,
row = runtime.limitRow,
col = runtime.limitCol,
x = 0,
y = 0,
maxX = runtime.totalCol,
maxY = runtime.totalRow,
wall = {},
holes = runtime.holes,
block = null,
matrix = runtime.matrix,
bigLoop = Math.max(col, row),
freeArea = null,
misBlock = null,
fitWidth = col < row ? 1 : 0,
lastBlock = null,
smallLoop = Math.min(col, row);
// fill area with top, left, width, height;
function fillMatrix(id, t, l, w, h) {
for (var y = t; y < t + h;) {
for (var x = l; x < l + w;) {
matrix[y + '-' + x] = id;
++x > maxX && (maxX = x);
}
++y > maxY && (maxY = y);
}
}
// set holes on the wall;
for (var i in holes) {
if (holes.hasOwnProperty(i)) {
fillMatrix(holes[i]["id"] || true, holes[i]['top'], holes[i]['left'], holes[i]['width'], holes[i]['height']);
}
}
for (var b = 0; b < bigLoop; ++b) {
if (!items.length) break;
fitWidth ? (y = b) : (x = b);
lastBlock = null;
for (var s = 0; s < smallLoop; ++s) {
if (!items.length) break;
block = null;
fitWidth ? (x = s) : (y = s);
if (runtime.matrix[y + '-' + x]) continue;
freeArea = layoutManager.getFreeArea(y, x, runtime);
// trying resize last block to fit free area;
if (setting.fixSize == null) {
// resize near block to fill gap;
if (lastBlock && !fitWidth && runtime.minHoB > freeArea.height) {
lastBlock.height += freeArea.height;
lastBlock.resize = true;
fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
layoutManager.setBlock(lastBlock, setting);
continue;
} else if (lastBlock && fitWidth && runtime.minWoB > freeArea.width) {
lastBlock.width += freeArea.width;
lastBlock.resize = true;
fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
layoutManager.setBlock(lastBlock, setting);
continue;
}
}
// get the next block to keep order;
if (runtime.keepOrder) {
block = items.shift();
block.resize = true;
} else {
// find a suitable block to fit gap;
for (var i = 0; i < items.length; ++i) {
if (items[i].height > freeArea.height) continue;
if (items[i].width > freeArea.width) continue;
block = items.splice(i, 1)[0];
break;
}
// trying resize the other block to fit gap;
if (block == null && setting.fixSize == null) {
// get other block fill to gap;
for (var i = 0; i < items.length; ++i) {
if (items[i]['fixSize'] != null) continue;
block = items.splice(i, 1)[0];
block.resize = true;
break;
}
}
}
if (block != null) {
// resize block with free area;
if (block.resize) {
if (fitWidth) {
block.width = freeArea.width;
if (setting.cellH == 'auto') {
layoutManager.adjustBlock(block, setting);
}
// for fitZone;
block.height = Math.min(block.height, freeArea.height);
} else {
block.height = freeArea.height;
// for fitZone;
block.width = Math.min(block.width, freeArea.width);
}
}
wall[block.id] = {
id: block.id,
x: x,
y: y,
width: block.width,
height: block.height,
resize: block.resize,
fixSize: block.fixSize
};
// keep success block for next round;
lastBlock = wall[block.id];
fillMatrix(lastBlock.id, lastBlock.y, lastBlock.x, lastBlock.width, lastBlock.height);
layoutManager.setBlock(lastBlock, setting);
} else {
// get expect area;
var misBlock = {
x: x,
y: y,
fixSize: 0
};
if (fitWidth) {
misBlock.width = freeArea.width;
misBlock.height = 0;
var lastX = x - 1;
var lastY = y;
while (matrix[lastY + '-' + lastX]) {
matrix[lastY + '-' + x] = true;
misBlock.height += 1;
lastY += 1;
}
} else {
misBlock.height = freeArea.height;
misBlock.width = 0;
var lastY = y - 1;
var lastX = x;
while (matrix[lastY + '-' + lastX]) {
matrix[y + '-' + lastX] = true;
misBlock.width += 1;
lastX += 1;
}
}
setting.onGapFound(layoutManager.setBlock(misBlock, setting), setting);
}
}
}
runtime.matrix = matrix;
runtime.totalRow = maxY;
runtime.totalCol = maxX;
}
};
function Freewall(selector) {
var container = $(selector);
if (container.css('position') == 'static') {
container.css('position', 'relative');
}
var MAX = Number.MAX_VALUE;
var klass = this;
// increase the instance index;
layoutManager.totalGrid += 1;
var setting = $.extend({}, layoutManager.defaultConfig);
var runtime = {
arguments: null,
blocks: {}, // store all items;
events: {}, // store custome events;
matrix: {},
holes: {}, // forbidden zone;
cellW: 0,
cellH: 0, // unit adjust;
cellS: 1, // unit scale;
filter: '', // filter selector;
lastId: 0,
length: 0,
maxWoB: 0, // max width of block;
maxHoB: 0,
minWoB: MAX,
minHoB: MAX, // min height of block;
running: 0, // flag to check layout arranging;
gutterX: 15,
gutterY: 15,
totalCol: 0,
totalRow: 0,
limitCol: 666666, // maximum column;
limitRow: 666666,
sortFunc: null,
keepOrder: false
};
setting.runtime = runtime;
runtime.totalGrid = layoutManager.totalGrid;
// check browser support transition;
var bodyStyle = document.body.style;
if (!layoutManager.transition) {
(bodyStyle.webkitTransition != null ||
bodyStyle.MozTransition != null ||
bodyStyle.msTransition != null ||
bodyStyle.OTransition != null ||
bodyStyle.transition != null) &&
(layoutManager.transition = true);
}
function setDraggable(item) {
var gutterX = runtime.gutterX;
var gutterY = runtime.gutterY;
var cellH = runtime.cellH;
var cellW = runtime.cellW;
var $item = $(item);
var handle = $item.find($item.attr("data-handle"));
layoutManager.setDraggable(item, {
handle: handle[0],
onStart: function(event) {
if (setting.animate && layoutManager.transition) {
layoutManager.setTransition(this, "");
}
$item.css('z-index', 9999).addClass('fw-float');
setting.onBlockDrag.call(item, event);
},
onDrag: function(event, tracker) {
var position = $item.position();
var top = Math.round(position.top / cellH);
var left = Math.round(position.left / cellW);
var width = Math.round($item.width() / cellW);
var height = Math.round($item.height() / cellH);
top = Math.min(Math.max(0, top), runtime.limitRow - height);
left = Math.min(Math.max(0, left), runtime.limitCol - width);
klass.setHoles({top: top, left: left, width: width, height: height});
klass.refresh();
setting.onBlockMove.call(item, event);
},
onDrop: function(event) {
var position = $item.position();
var top = Math.round(position.top / cellH);
var left = Math.round(position.left / cellW);
var width = Math.round($item.width() / cellW);
var height = Math.round($item.height() / cellH);
top = Math.min(Math.max(0, top), runtime.limitRow - height);
left = Math.min(Math.max(0, left), runtime.limitCol - width);
$item.removeClass('fw-float');
$item.css({
zIndex: "auto",
top: top * cellH,
left: left * cellW
});
//check old drag element;
var x, y, key, oldDropId;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
key = (y + top) + "-" + (x + left);
oldDropId = runtime.matrix[key];
if (oldDropId && oldDropId != true) {
$("#" + oldDropId).removeAttr("data-position");
}
}
}
runtime.holes = {};
$item.attr({
"data-width": $item.width(),
"data-height": $item.height(),
"data-position": top + "-" + left
});
klass.refresh();
setting.onBlockDrop.call(item, event);
}
});
}
$.extend(klass, {
addCustomEvent: function(name, func) {
var events = runtime.events;
name = name.toLowerCase();
!events[name] && (events[name] = []);
func.eid = events[name].length;
events[name].push(func);
return this;
},
appendBlock: function(items) {
var allBlock = $(items).appendTo(container);
var block = null;
var activeBlock = [];
if (runtime.arguments) {
if ($.isFunction(runtime.sortFunc)) {
allBlock.sort(runtime.sortFunc);
}
allBlock.each(function(index, item) {
item.index = ++index;
block = layoutManager.loadBlock(item, setting);
block && activeBlock.push(block);
});
engine[setting.engine](activeBlock, setting);
layoutManager.setWallSize(runtime, container);
runtime.length = allBlock.length;
allBlock.each(function(index, item) {
layoutManager.showBlock(item, setting);
if (setting.draggable || item.getAttribute('data-draggable')) {
setDraggable(item);
}
});
}
},
/*
add one or more blank area (hole) on layout;
example:
wall.appendHoles({
top: 10,
left: 36,
width: 2,
height: 6
});
wall.appendHoles([
{
top: 16,
left: 16,
width: 8,
height: 2
},
{
top: 10,
left: 36,
width: 2,
height: 6
}
]);
*/
appendHoles: function(holes) {
var newHoles = [].concat(holes), h = {}, i;
for (i = 0; i < newHoles.length; ++i) {
h = newHoles[i];
runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height] = h;
}
return this;
},
container: container,
destroy: function() {
var allBlock = container.find(setting.selector).removeAttr('id'),
block = null,
activeBlock = [];
allBlock.each(function(index, item) {
$item = $(item);
var width = 1 * $item.attr('data-width') || "";
var height = 1 * $item.attr('data-height') || "";
$item.width(width).height(height).css({
position: 'static'
});
});
},
fillHoles: function(holes) {
if (arguments.length == 0) {
runtime.holes = {};
} else {
var newHoles = [].concat(holes), h = {}, i;
for (i = 0; i < newHoles.length; ++i) {
h = newHoles[i];
delete runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height];
}
}
return this;
},
filter: function(filter) {
runtime.filter = filter;
if (runtime.arguments) {
this.refresh();
}
return this;
},
fireEvent: function(name, object, setting) {
var events = runtime.events;
name = name.toLowerCase();
if (events[name] && events[name].length) {
for (var i = 0; i < events[name].length; ++i) {
events[name][i].call(this, object, setting);
}
}
return this;
},
fitHeight: function(height) {
var height = height ? height : container.height() || $W.height();
this.fitZone('auto', height);
runtime.arguments = arguments;
},
fitWidth: function(width) {
var width = width ? width : container.width() || $W.width();
this.fitZone(width, 'auto');
runtime.arguments = arguments;
},
fitZone: function(width, height) {
var allBlock = container.find(setting.selector).removeAttr('id'),
block = null,
activeBlock = [];
height = height ? height : container.height() || $W.height();
width = width ? width : container.width() || $W.width();
runtime.arguments = arguments;
layoutManager.resetGrid(runtime);
layoutManager.adjustUnit(width, height, setting);
if (runtime.filter) {
allBlock.data('active', 0);
allBlock.filter(runtime.filter).data('active', 1);
} else {
allBlock.data('active', 1);
}
if ($.isFunction(runtime.sortFunc)) {
allBlock.sort(runtime.sortFunc);
}
allBlock.each(function(index, item) {
var $item = $(item);
item.index = ++index;
block = layoutManager.loadBlock(item, setting);
block && $item.data("active") && activeBlock.push(block);
});
klass.fireEvent('onGridReady', container, setting);
engine[setting.engine](activeBlock, setting);
layoutManager.setWallSize(runtime, container);
klass.fireEvent('onGridArrange', container, setting);
runtime.length = allBlock.length;
allBlock.each(function(index, item) {
layoutManager.showBlock(item, setting);
if (setting.draggable || item.getAttribute('data-draggable')) {
setDraggable(item);
}
});
},
/*
set block with special position, the top and left are multiple of unit width/height;
example:
wall.fixPos({
top: 0,
left: 0,
block: $('.free')
});
*/
fixPos: function(option) {
$(option.block).attr({'data-position': option.top + "-" + option.left});
return this;
},
/*
set block with special size, the width and height are multiple of unit width/height;
example:
wall.fixSize({
height: 5,
width: 2,
block: $('.free')
});
*/
fixSize: function(option) {
option.height != null && $(option.block).attr({'data-height': option.height});
option.width != null && $(option.block).attr({'data-width': option.width});
return this;
},
prepend: function(items) {
container.prepend(items);
if (runtime.arguments) {
this.refresh();
}
return this;
},
refresh: function() {
var params = arguments.length ? arguments : runtime.arguments;
var oldArg = runtime.arguments;
var method = oldArg ? oldArg.callee : this.fitWidth;
method.apply(this, Array.prototype.slice.call(params, 0));
return this;
},
/*
custom layout setting;
example:
wall.reset({
selector: '.brick',
animate: true,
cellW: 160,
cellH: 160,
delay: 50,
onResize: function() {
wall.fitWidth();
}
});
*/
reset: function(option) {
$.extend(setting, option);
return this;
},
/*
create one or more blank area (hole) on layout;
example:
wall.setHoles({
top: 2,
left: 2,
width: 2,
height: 2
});
*/
setHoles: function(holes) {
var newHoles = [].concat(holes), h = {}, i;
runtime.holes = {};
for (i = 0; i < newHoles.length; ++i) {
h = newHoles[i];
runtime.holes[h.top + "-" + h.left + "-" + h.width + "-" + h.height] = h;
}
return this;
},
/*
sort items by using array sort function;
example:
wall.sortBy(function(itemA, itemB) {
return $(itemA).width() - $(itemB).width();
});
*/
sortBy: function(func) {
runtime.sortFunc = func;
if (runtime.arguments) {
this.refresh();
}
return this;
},
unFilter: function() {
delete runtime.filter;
this.refresh();
return this;
}
});
container.attr('data-min-width', Math.floor($W.width() / 80) * 80);
// execute plugins;
for (var i in layoutManager.plugin) {
if (layoutManager.plugin.hasOwnProperty(i)) {
layoutManager.plugin[i].call(klass, setting, container);
}
}
// setup resize event;
$W.resize(function() {
if (runtime.running) return;
runtime.running = 1;
setTimeout(function() {
runtime.running = 0;
setting.onResize.call(klass, container);
}, 122);
container.attr('data-min-width', Math.floor($W.width() / 80) * 80);
});
};
/*
add default setting;
example:
Freewall.addConfig({
offsetLeft: 0
});
*/
Freewall.addConfig = function(newConfig) {
// add default setting;
$.extend(layoutManager.defaultConfig, newConfig);
};
/*
support create new arrange algorithm;
example:
Freewall.createEngine({
slice: function(items, setting) {
// slice engine;
}
});
*/
Freewall.createEngine = function(engineData) {
// create new engine;
$.extend(engine, engineData);
};
/*
support create new plugin;
example:
Freewall.createPlugin({
centering: function(setting, container) {
console.log(this);
console.log(setting);
}
})l
*/
Freewall.createPlugin = function(pluginData) {
// register new plugin;
$.extend(layoutManager.plugin, pluginData);
};
/*
support access helper function;
example:
Freewall.getMethod('setBlock')(block, setting);
*/
Freewall.getMethod = function(method) {
// get helper method;
return layoutManager[method];
};
window.Freewall = window.freewall = Freewall;
})(window.Zepto || window.jQuery);