I have packery with jQuery Draggable all setup and working correctly on my development environment.
At the moment I am saving my ordered (packery) html to the database. Before everything is inserted to the DB I change the order of the dom elements to match the packery order. Everything works nicely
when re-loading the page with the saved html all the divs appear in their position as per the save.
The problem I am having is when I set up packery again with my loaded HTML using ($grid is the parent div)
var $grid = $('.grid');
$grid.packery({
columnWidth: '.grid-sizer',
itemSelector: '.grid-item',
stamp: ".stamp",
gutter:0,
percentPosition: true
});
Packery does its thing a "packs" everything again. which is exactly what it is supposed to do. Thing is i want to keep my old layout that may of had empty space in it.
My question is...
Is it possible to init packery without triggering the layout function? I have tried adding initLayout: false
to the options. but it doesn't let me drag elements & layoutInstant: false
doesn't seem to do anything.
Screens of saved html (after dragging everything how i want it) and then after re-loading and then $grid.packery()
https://i.sstatic.net/fS2Vp.png
https://i.sstatic.net/pAnkW.png
Alright i managed to sort this out myself. mainly from this answer on the metafizzy git metafizzy isse tracker
Added code before the initial packery set up
Packery.prototype.getShiftPositions = function( attrName ) {
attrName = attrName || 'id';
var _this = this;
console.log(_this.packer.width);
return this.items.map( function( item ) {
return {
attr: item.element.getAttribute( attrName ),
x: item.element.offsetLeft,
y: item.element.offsetTop
}
});
};
Packery.prototype.initShiftLayout = function( positions, attr ) {
if ( !positions ) {
// if no initial positions, run packery layout
this.layout();
return;
}
// parse string to JSON
if ( typeof positions == 'string' ) {
try {
positions = JSON.parse( positions );
} catch( error ) {
console.error( 'JSON parse error: ' + error );
this.layout();
return;
}
}
attr = attr || 'id'; // default to id attribute
console.log(this.items);
this._resetLayout();
// set item order and horizontal position from saved positions
this.items = positions.map( function( itemPosition ) {
var selector = '[' + attr + '="' + itemPosition.attr + '"]';
var itemElem = this.element.querySelector( selector );
var item = this.getItem( itemElem );
if (item) {
item.rect.x = itemPosition.x;
item.rect.y = itemPosition.y;
return item;
}
}, this );
// filter out any items that no longer exist
this.items = this.items.filter(function(item) {
return item !== undefined;
});
// add new items
var newitems = [];
var p = this;
$(this.$element[0]).find(this.options.itemSelector).each(function(i, e) {
if (!p.getItem(e)) {
newitems.push(e);
}
});
this.addItems(newitems);
this.shiftLayout();
};
When setting packery up. set initLayout:false
e.g.
$grid.packery({
columnWidth: parseInt($columnWidth),
itemSelector: '.grid-item',
stamp: ".stamp",
gutter:0,
percentPosition: true,
initLayout: false,
});
Then setting everything up (data-item-index) is a unique value added to each div that can be moved around. you could use 'id'
var initPositions = $grid.packery( 'getShiftPositions', 'data-item-index');
$grid.packery( 'initShiftLayout', initPositions, 'data-item-index');