Update dist. (+14 squashed commits)

Squashed commits:
[50607a9] build dist
[ff0c00b] Allow negative numbers to be passed to parseHeight function test case fix
[3ecc1ca] Allow negative numbers to be passed to parseHeight function test case
[d20f670] Allow negative numbers to be passed to parseHeight function fix
[0816163] Allow negative numbers to be passed to parseHeight function
[aa18c63] rebuild dist
[601b5d5] setGridWidth api documentation udpdate
[c309856] Add a parameter to setGridWidth method to allow not to propagate resizing to widgets.
[ea442d1] drag between grids
[50ce614] jqueryui + requirejs note
[3d8a8e1] drag between grids demo
[446dade] drag from sidebar/between grids
[e31d50e] check if element setup before detach
[67274f8] trash zone is accepting only widgets
This commit is contained in:
Pavel Reznikov 2016-02-27 18:46:41 -08:00 committed by d
parent 0b944927ab
commit 0273bb66d8
8 changed files with 385 additions and 76 deletions

View file

@ -37,6 +37,7 @@ Join gridstack.js on Slack: https://gridstackjs.troolee.com
- [Load grid from array](#load-grid-from-array)
- [Override resizable/draggable options](#override-resizabledraggable-options)
- [IE8 support](#ie8-support)
- [Use with require.js](#use-with-requirejs)
- [Nested grids](#nested-grids)
- [Resizing active grid](#resizing-active-grid)
- [Using AniJS](#using-anijs)
@ -428,6 +429,12 @@ for i in range(N):
There are at least two more issues with gridstack in IE8 with jQueryUI resizable (it seems it doesn't work) and
droppable. If you have any suggestions about support of IE8 you are welcome here: https://github.com/troolee/gridstack.js/issues/76
## Use with require.js
If you're using require.js and a single file jQueryUI please check out this
[Stackoverflow question](http://stackoverflow.com/questions/35582945/redundant-dependencies-with-requirejs) to get it
working properly.
## Nested grids
@ -472,11 +479,12 @@ Changes
- fix `setStatic` method
- add `setAnimation` method to API
- add `setGridWidth` method ([#227](https://github.com/troolee/gridstack.js/issues/227))
- add `removable`/`removeTimeout`
- add `removable`/`removeTimeout` *(experimental)*
- add `detachGrid` parameter to `destroy` method ([#216](https://github.com/troolee/gridstack.js/issues/216)) (thanks @jhpedemonte)
- add `useOffset` parameter to `getCellFromPixel` method ([#237](https://github.com/troolee/gridstack.js/issues/237))
- add `minWidth`, `maxWidth`, `minHeight`, `maxHeight`, `id` parameters to `addWidget` ([#188](https://github.com/troolee/gridstack.js/issues/188))
- add `added` and `removed` events for when a widget is added or removed, respectively. ([#54](https://github.com/troolee/gridstack.js/issues/54))
- add `acceptWidgets` parameter. Widgets can now be draggable between grids or from outside *(experimental)*
#### v0.2.4 (2016-02-15)

View file

@ -48,13 +48,45 @@
margin-bottom: 20px;
background: rgba(255, 0, 0, 0.1) center center url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDQzOC41MjkgNDM4LjUyOSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDM4LjUyOSA0MzguNTI5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPGc+CgkJPHBhdGggZD0iTTQxNy42ODksNzUuNjU0Yy0xLjcxMS0xLjcwOS0zLjkwMS0yLjU2OC02LjU2My0yLjU2OGgtODguMjI0TDMwMi45MTcsMjUuNDFjLTIuODU0LTcuMDQ0LTcuOTk0LTEzLjA0LTE1LjQxMy0xNy45ODkgICAgQzI4MC4wNzgsMi40NzMsMjcyLjU1NiwwLDI2NC45NDUsMGgtOTEuMzYzYy03LjYxMSwwLTE1LjEzMSwyLjQ3My0yMi41NTQsNy40MjFjLTcuNDI0LDQuOTQ5LTEyLjU2MywxMC45NDQtMTUuNDE5LDE3Ljk4OSAgICBsLTE5Ljk4NSw0Ny42NzZoLTg4LjIyYy0yLjY2NywwLTQuODUzLDAuODU5LTYuNTY3LDIuNTY4Yy0xLjcwOSwxLjcxMy0yLjU2OCwzLjkwMy0yLjU2OCw2LjU2N3YxOC4yNzQgICAgYzAsMi42NjQsMC44NTUsNC44NTQsMi41NjgsNi41NjRjMS43MTQsMS43MTIsMy45MDQsMi41NjgsNi41NjcsMi41NjhoMjcuNDA2djI3MS44YzAsMTUuODAzLDQuNDczLDI5LjI2NiwxMy40MTgsNDAuMzk4ICAgIGM4Ljk0NywxMS4xMzksMTkuNzAxLDE2LjcwMywzMi4yNjQsMTYuNzAzaDIzNy41NDJjMTIuNTY2LDAsMjMuMzE5LTUuNzU2LDMyLjI2NS0xNy4yNjhjOC45NDUtMTEuNTIsMTMuNDE1LTI1LjE3NCwxMy40MTUtNDAuOTcxICAgIFYxMDkuNjI3aDI3LjQxMWMyLjY2MiwwLDQuODUzLTAuODU2LDYuNTYzLTIuNTY4YzEuNzA4LTEuNzA5LDIuNTctMy45LDIuNTctNi41NjRWODIuMjIxICAgIEM0MjAuMjYsNzkuNTU3LDQxOS4zOTcsNzcuMzY3LDQxNy42ODksNzUuNjU0eiBNMTY5LjMwMSwzOS42NzhjMS4zMzEtMS43MTIsMi45NS0yLjc2Miw0Ljg1My0zLjE0aDkwLjUwNCAgICBjMS45MDMsMC4zODEsMy41MjUsMS40Myw0Ljg1NCwzLjE0bDEzLjcwOSwzMy40MDRIMTU1LjMxMUwxNjkuMzAxLDM5LjY3OHogTTM0Ny4xNzMsMzgwLjI5MWMwLDQuMTg2LTAuNjY0LDguMDQyLTEuOTk5LDExLjU2MSAgICBjLTEuMzM0LDMuNTE4LTIuNzE3LDYuMDg4LTQuMTQxLDcuNzA2Yy0xLjQzMSwxLjYyMi0yLjQyMywyLjQyNy0yLjk5OCwyLjQyN0gxMDAuNDkzYy0wLjU3MSwwLTEuNTY1LTAuODA1LTIuOTk2LTIuNDI3ICAgIGMtMS40MjktMS42MTgtMi44MS00LjE4OC00LjE0My03LjcwNmMtMS4zMzEtMy41MTktMS45OTctNy4zNzktMS45OTctMTEuNTYxVjEwOS42MjdoMjU1LjgxNVYzODAuMjkxeiIgZmlsbD0iI2ZmOWNhZSIvPgoJCTxwYXRoIGQ9Ik0xMzcuMDQsMzQ3LjE3MmgxOC4yNzFjMi42NjcsMCw0Ljg1OC0wLjg1NSw2LjU2Ny0yLjU2N2MxLjcwOS0xLjcxOCwyLjU2OC0zLjkwMSwyLjU2OC02LjU3VjE3My41ODEgICAgYzAtMi42NjMtMC44NTktNC44NTMtMi41NjgtNi41NjdjLTEuNzE0LTEuNzA5LTMuODk5LTIuNTY1LTYuNTY3LTIuNTY1SDEzNy4wNGMtMi42NjcsMC00Ljg1NCwwLjg1NS02LjU2NywyLjU2NSAgICBjLTEuNzExLDEuNzE0LTIuNTY4LDMuOTA0LTIuNTY4LDYuNTY3djE2NC40NTRjMCwyLjY2OSwwLjg1NCw0Ljg1MywyLjU2OCw2LjU3QzEzMi4xODYsMzQ2LjMxNiwxMzQuMzczLDM0Ny4xNzIsMTM3LjA0LDM0Ny4xNzJ6IiBmaWxsPSIjZmY5Y2FlIi8+CgkJPHBhdGggZD0iTTIxMC4xMjksMzQ3LjE3MmgxOC4yNzFjMi42NjYsMCw0Ljg1Ni0wLjg1NSw2LjU2NC0yLjU2N2MxLjcxOC0xLjcxOCwyLjU2OS0zLjkwMSwyLjU2OS02LjU3VjE3My41ODEgICAgYzAtMi42NjMtMC44NTItNC44NTMtMi41NjktNi41NjdjLTEuNzA4LTEuNzA5LTMuODk4LTIuNTY1LTYuNTY0LTIuNTY1aC0xOC4yNzFjLTIuNjY0LDAtNC44NTQsMC44NTUtNi41NjcsMi41NjUgICAgYy0xLjcxNCwxLjcxNC0yLjU2OCwzLjkwNC0yLjU2OCw2LjU2N3YxNjQuNDU0YzAsMi42NjksMC44NTQsNC44NTMsMi41NjgsNi41N0MyMDUuMjc0LDM0Ni4zMTYsMjA3LjQ2NSwzNDcuMTcyLDIxMC4xMjksMzQ3LjE3MnogICAgIiBmaWxsPSIjZmY5Y2FlIi8+CgkJPHBhdGggZD0iTTI4My4yMiwzNDcuMTcyaDE4LjI2OGMyLjY2OSwwLDQuODU5LTAuODU1LDYuNTctMi41NjdjMS43MTEtMS43MTgsMi41NjItMy45MDEsMi41NjItNi41N1YxNzMuNTgxICAgIGMwLTIuNjYzLTAuODUyLTQuODUzLTIuNTYyLTYuNTY3Yy0xLjcxMS0xLjcwOS0zLjkwMS0yLjU2NS02LjU3LTIuNTY1SDI4My4yMmMtMi42NywwLTQuODUzLDAuODU1LTYuNTcxLDIuNTY1ICAgIGMtMS43MTEsMS43MTQtMi41NjYsMy45MDQtMi41NjYsNi41Njd2MTY0LjQ1NGMwLDIuNjY5LDAuODU1LDQuODUzLDIuNTY2LDYuNTdDMjc4LjM2NywzNDYuMzE2LDI4MC41NSwzNDcuMTcyLDI4My4yMiwzNDcuMTcyeiIgZmlsbD0iI2ZmOWNhZSIvPgoJPC9nPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo=) no-repeat;
}
.sidebar {
background: rgba(0, 255, 0, 0.1);
height: 150px;
padding: 25px 0;
text-align: center;
}
.sidebar .grid-stack-item {
width: 200px;
height: 100px;
border: 2px dashed green;
text-align: center;
line-height: 100px;
z-index: 10;
background: rgba(0, 255, 0, 0.1);
cursor: default;
display: inline-block;
}
.sidebar .grid-stack-item .grid-stack-item-content {
background: none;
}
</style>
</head>
<body>
<div class="container-fluid">
<h1>Two grids demo</h1>
<div class="trash">
<div class="row">
<div class="col-md-3">
<div class="sidebar">
<div class="grid-stack-item"><div class="grid-stack-item-content">Drag me</div></div>
</div>
</div>
<div class="col-md-9">
<div class="trash">
</div>
</div>
</div>
<div class="row">
@ -74,12 +106,15 @@
$(function () {
var options = {
width: 6,
float: true,
float: false,
removable: '.trash',
removeTimeout: 100
removeTimeout: 100,
acceptWidgets: '.grid-stack-item'
};
$('#grid1').gridstack(options);
$('#grid2').gridstack(options);
$('#grid2').gridstack(_.defaults({
float: true
}, options));
var items = [
{x: 0, y: 0, width: 2, height: 2},
@ -97,6 +132,13 @@
node.x, node.y, node.width, node.height);
}, this);
});
$('.sidebar .grid-stack-item').draggable({
revert: 'invalid',
handle: '.grid-stack-item-content',
scroll: false,
appendTo: 'body'
});
});
</script>
</body>

188
dist/gridstack.js vendored
View file

@ -99,7 +99,7 @@
var height = val;
var heightUnit = 'px';
if (height && _.isString(height)) {
var match = height.match(/^([0-9]*\.[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/);
var match = height.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/);
if (!match) {
throw new Error('Invalid height');
}
@ -477,10 +477,6 @@
opts.placeholderText = opts.placeholder_text;
obsoleteOpts('placeholder_text', 'placeholderText');
}
if (typeof opts.item_class !== 'undefined') {
opts.itemClass = opts.item_class;
obsoleteOpts('item_class', 'itemClass');
}
if (typeof opts.cell_height !== 'undefined') {
opts.cellHeight = opts.cell_height;
obsoleteOpts('cell_height', 'cellHeight');
@ -576,7 +572,9 @@
var maxHeight = 0;
_.each(nodes, function(n) {
if (n._id === null) {
n.el.remove();
if (n.el) {
n.el.remove();
}
} else {
n.el
.attr('data-gs-x', n.x)
@ -671,7 +669,9 @@
if (typeof self.opts.removable === 'string') {
var trashZone = $(self.opts.removable);
if (!trashZone.data('droppable')) {
trashZone.droppable({});
trashZone.droppable({
accept: '.' + self.opts.itemClass
});
}
trashZone
.on('dropover', function(event, ui) {
@ -691,6 +691,114 @@
self._clearRemovingTimeout(el);
});
}
if (self.opts.acceptWidgets) {
var draggingElement = null;
var onDrag = function(event, ui) {
var el = draggingElement;
var node = el.data('_gridstack_node');
var pos = self.getCellFromPixel(ui.offset, true);
var x = Math.max(0, pos.x);
var y = Math.max(0, pos.y);
if (!node._added) {
node._added = true;
node.el = el;
node.x = x;
node.y = y;
self.grid.cleanNodes();
self.grid.beginUpdate(node);
self.grid.addNode(node);
self.container.append(self.placeholder);
self.placeholder
.attr('data-gs-x', node.x)
.attr('data-gs-y', node.y)
.attr('data-gs-width', node.width)
.attr('data-gs-height', node.height)
.show();
node.el = self.placeholder;
node._beforeDragX = node.x;
node._beforeDragY = node.y;
self._updateContainerHeight();
} else {
if (!self.grid.canMoveNode(node, x, y)) {
return;
}
self.grid.moveNode(node, x, y);
self._updateContainerHeight();
}
};
$(self.container).droppable({
accept: function(el) {
el = $(el);
var node = el.data('_gridstack_node');
if (node && node._grid === self) {
return false;
}
return el.is(self.opts.acceptWidgets === true ? '.grid-stack-item' : self.opts.acceptWidgets);
},
over: function(event, ui) {
var offset = self.container.offset();
var el = $(ui.draggable);
var cellWidth = self.cellWidth();
var cellHeight = self.cellHeight();
var origNode = el.data('_gridstack_node');
var width = origNode ? origNode.width : (Math.ceil(el.outerWidth() / cellWidth));
var height = origNode ? origNode.height : (Math.ceil(el.outerHeight() / cellHeight));
draggingElement = el;
var node = self.grid._prepareNode({width: width, height: height, _added: false, _temporary: true});
el.data('_gridstack_node', node);
el.data('_gridstack_node_orig', origNode);
el.on('drag', onDrag);
},
out: function(event, ui) {
var el = $(ui.draggable);
el.unbind('drag', onDrag);
var node = el.data('_gridstack_node');
node.el = null;
self.grid.removeNode(node);
self.placeholder.detach();
self._updateContainerHeight();
el.data('_gridstack_node', el.data('_gridstack_node_orig'));
},
drop: function(event, ui) {
self.placeholder.detach();
var node = $(ui.draggable).data('_gridstack_node');
node._grid = self;
var el = $(ui.draggable).clone(false);
el.data('_gridstack_node', node);
$(ui.draggable).remove();
node.el = el;
self.placeholder.hide();
el
.attr('data-gs-x', node.x)
.attr('data-gs-y', node.y)
.attr('data-gs-width', node.width)
.attr('data-gs-height', node.height)
.addClass(self.opts.itemClass)
.removeAttr('style')
.enableSelection()
.removeData('draggable')
.removeClass('ui-draggable ui-draggable-dragging ui-draggable-disabled')
.unbind('drag', onDrag);
self.container.append(el);
self._prepareElementByNode(el, node);
self._updateContainerHeight();
self._triggerChangeEvent();
self.grid.endUpdate();
}
});
}
};
GridStack.prototype._triggerChangeEvent = function(forceTrigger) {
@ -840,7 +948,6 @@
};
GridStack.prototype._clearRemovingTimeout = function(el) {
var self = this;
var node = $(el).data('_gridstack_node');
if (!node._removeTimeout) {
@ -852,30 +959,8 @@
node._isAboutToRemove = false;
};
GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
triggerAddEvent = typeof triggerAddEvent != 'undefined' ? triggerAddEvent : false;
GridStack.prototype._prepareElementByNode = function(el, node) {
var self = this;
el = $(el);
el.addClass(this.opts.itemClass);
var node = self.grid.addNode({
x: el.attr('data-gs-x'),
y: el.attr('data-gs-y'),
width: el.attr('data-gs-width'),
height: el.attr('data-gs-height'),
maxWidth: el.attr('data-gs-max-width'),
minWidth: el.attr('data-gs-min-width'),
maxHeight: el.attr('data-gs-max-height'),
minHeight: el.attr('data-gs-min-height'),
autoPosition: Utils.toBool(el.attr('data-gs-auto-position')),
noResize: Utils.toBool(el.attr('data-gs-no-resize')),
noMove: Utils.toBool(el.attr('data-gs-no-move')),
locked: Utils.toBool(el.attr('data-gs-locked')),
el: el,
id: el.attr('data-gs-id'),
_grid: self
}, triggerAddEvent);
el.data('_gridstack_node', node);
var cellWidth;
var cellHeight;
@ -962,9 +1047,13 @@
};
var onEndMoving = function(event, ui) {
var o = $(this);
if (!o.data('_gridstack_node')) {
return;
}
var forceNotify = false;
self.placeholder.detach();
var o = $(this);
node.el = o;
self.placeholder.hide();
@ -1031,6 +1120,34 @@
el.attr('data-gs-locked', node.locked ? 'yes' : null);
};
GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
triggerAddEvent = typeof triggerAddEvent != 'undefined' ? triggerAddEvent : false;
var self = this;
el = $(el);
el.addClass(this.opts.itemClass);
var node = self.grid.addNode({
x: el.attr('data-gs-x'),
y: el.attr('data-gs-y'),
width: el.attr('data-gs-width'),
height: el.attr('data-gs-height'),
maxWidth: el.attr('data-gs-max-width'),
minWidth: el.attr('data-gs-min-width'),
maxHeight: el.attr('data-gs-max-height'),
minHeight: el.attr('data-gs-min-height'),
autoPosition: Utils.toBool(el.attr('data-gs-auto-position')),
noResize: Utils.toBool(el.attr('data-gs-no-resize')),
noMove: Utils.toBool(el.attr('data-gs-no-move')),
locked: Utils.toBool(el.attr('data-gs-locked')),
el: el,
id: el.attr('data-gs-id'),
_grid: self
}, triggerAddEvent);
el.data('_gridstack_node', node);
this._prepareElementByNode(el, node);
};
GridStack.prototype.setAnimation = function(enable) {
if (enable) {
this.container.addClass('grid-stack-animate');
@ -1417,10 +1534,13 @@
this.grid.commit();
};
GridStack.prototype.setGridWidth = function(gridWidth) {
GridStack.prototype.setGridWidth = function(gridWidth,doNotPropagate) {
this.container.removeClass('grid-stack-' + this.opts.width);
this._updateNodeWidths(this.opts.width, gridWidth);
if (doNotPropagate !== true) {
this._updateNodeWidths(this.opts.width, gridWidth);
}
this.opts.width = gridWidth;
this.grid.width = gridWidth;
this.container.addClass('grid-stack-' + gridWidth);
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -45,7 +45,7 @@ gridstack.js API
- [resize(el, width, height)](#resizeel-width-height)
- [resizable(el, val)](#resizableel-val)
- [setAnimation(doAnimate)](#setanimationdoanimate)
- [setGridWidth(gridWidth)](#setgridwidthgridwidth)
- [setGridWidth(gridWidth, doNotPropagate)](#setgridwidthgridwidth-donotpropagate)
- [setStatic(staticValue)](#setstaticstaticvalue)
- [update(el, x, y, width, height)](#updateel-x-y-width-height)
- [willItFit(x, y, width, height, autoPosition)](#willitfitx-y-width-height-autoposition)
@ -56,6 +56,8 @@ gridstack.js API
## Options
- `acceptWidgets` - if `true` of jquery selector the grid will accept widgets dragged from other grids or from
outside (default: `false`) See [example](http://troolee.github.io/gridstack.js/demo/two.html)
- `alwaysShowResizeHandle` - if `true` the resizing handles are shown even if the user is not hovering over the widget
(default: `false`)
- `animate` - turns animation on (default: `false`)
@ -413,11 +415,12 @@ Toggle the grid animation state. Toggles the `grid-stack-animate` class.
- `doAnimate` - if `true` the grid will animate.
### setGridWidth(gridWidth)
### setGridWidth(gridWidth, doNotPropagate)
(Experimental) Modify number of columns in the grid. Will attempt to update existing widgets to conform to new number of columns. Requires `gridstack-extra.css` or `gridstack-extra.min.css`.
- `gridWidth` - Integer between 1 and 12.
- `doNotPropagate` - if true existing widgets will not be updated.
### setStatic(staticValue)

View file

@ -91,7 +91,19 @@ describe('gridstack utils', function() {
expect(utils.parseHeight('12.3vw')).toEqual(jasmine.objectContaining({height: 12.3, unit: 'vw'}));
expect(utils.parseHeight('12.5')).toEqual(jasmine.objectContaining({height: 12.5, unit: 'px'}));
expect(function() { utils.parseHeight('12.5 df'); }).toThrowError('Invalid height');
});
it('should parse negative height value', function() {
expect(utils.parseHeight(-12)).toEqual(jasmine.objectContaining({height: -12, unit: 'px'}));
expect(utils.parseHeight('-12px')).toEqual(jasmine.objectContaining({height: -12, unit: 'px'}));
expect(utils.parseHeight('-12.3px')).toEqual(jasmine.objectContaining({height: -12.3, unit: 'px'}));
expect(utils.parseHeight('-12.3em')).toEqual(jasmine.objectContaining({height: -12.3, unit: 'em'}));
expect(utils.parseHeight('-12.3rem')).toEqual(jasmine.objectContaining({height: -12.3, unit: 'rem'}));
expect(utils.parseHeight('-12.3vh')).toEqual(jasmine.objectContaining({height: -12.3, unit: 'vh'}));
expect(utils.parseHeight('-12.3vw')).toEqual(jasmine.objectContaining({height: -12.3, unit: 'vw'}));
expect(utils.parseHeight('-12.5')).toEqual(jasmine.objectContaining({height: -12.5, unit: 'px'}));
expect(function() { utils.parseHeight('-12.5 df'); }).toThrowError('Invalid height');
});
});
});

View file

@ -99,7 +99,7 @@
var height = val;
var heightUnit = 'px';
if (height && _.isString(height)) {
var match = height.match(/^([0-9]*\.[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/);
var match = height.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/);
if (!match) {
throw new Error('Invalid height');
}
@ -572,7 +572,9 @@
var maxHeight = 0;
_.each(nodes, function(n) {
if (n._id === null) {
n.el.remove();
if (n.el) {
n.el.remove();
}
} else {
n.el
.attr('data-gs-x', n.x)
@ -667,7 +669,9 @@
if (typeof self.opts.removable === 'string') {
var trashZone = $(self.opts.removable);
if (!trashZone.data('droppable')) {
trashZone.droppable({});
trashZone.droppable({
accept: '.' + self.opts.itemClass
});
}
trashZone
.on('dropover', function(event, ui) {
@ -687,6 +691,114 @@
self._clearRemovingTimeout(el);
});
}
if (self.opts.acceptWidgets) {
var draggingElement = null;
var onDrag = function(event, ui) {
var el = draggingElement;
var node = el.data('_gridstack_node');
var pos = self.getCellFromPixel(ui.offset, true);
var x = Math.max(0, pos.x);
var y = Math.max(0, pos.y);
if (!node._added) {
node._added = true;
node.el = el;
node.x = x;
node.y = y;
self.grid.cleanNodes();
self.grid.beginUpdate(node);
self.grid.addNode(node);
self.container.append(self.placeholder);
self.placeholder
.attr('data-gs-x', node.x)
.attr('data-gs-y', node.y)
.attr('data-gs-width', node.width)
.attr('data-gs-height', node.height)
.show();
node.el = self.placeholder;
node._beforeDragX = node.x;
node._beforeDragY = node.y;
self._updateContainerHeight();
} else {
if (!self.grid.canMoveNode(node, x, y)) {
return;
}
self.grid.moveNode(node, x, y);
self._updateContainerHeight();
}
};
$(self.container).droppable({
accept: function(el) {
el = $(el);
var node = el.data('_gridstack_node');
if (node && node._grid === self) {
return false;
}
return el.is(self.opts.acceptWidgets === true ? '.grid-stack-item' : self.opts.acceptWidgets);
},
over: function(event, ui) {
var offset = self.container.offset();
var el = $(ui.draggable);
var cellWidth = self.cellWidth();
var cellHeight = self.cellHeight();
var origNode = el.data('_gridstack_node');
var width = origNode ? origNode.width : (Math.ceil(el.outerWidth() / cellWidth));
var height = origNode ? origNode.height : (Math.ceil(el.outerHeight() / cellHeight));
draggingElement = el;
var node = self.grid._prepareNode({width: width, height: height, _added: false, _temporary: true});
el.data('_gridstack_node', node);
el.data('_gridstack_node_orig', origNode);
el.on('drag', onDrag);
},
out: function(event, ui) {
var el = $(ui.draggable);
el.unbind('drag', onDrag);
var node = el.data('_gridstack_node');
node.el = null;
self.grid.removeNode(node);
self.placeholder.detach();
self._updateContainerHeight();
el.data('_gridstack_node', el.data('_gridstack_node_orig'));
},
drop: function(event, ui) {
self.placeholder.detach();
var node = $(ui.draggable).data('_gridstack_node');
node._grid = self;
var el = $(ui.draggable).clone(false);
el.data('_gridstack_node', node);
$(ui.draggable).remove();
node.el = el;
self.placeholder.hide();
el
.attr('data-gs-x', node.x)
.attr('data-gs-y', node.y)
.attr('data-gs-width', node.width)
.attr('data-gs-height', node.height)
.addClass(self.opts.itemClass)
.removeAttr('style')
.enableSelection()
.removeData('draggable')
.removeClass('ui-draggable ui-draggable-dragging ui-draggable-disabled')
.unbind('drag', onDrag);
self.container.append(el);
self._prepareElementByNode(el, node);
self._updateContainerHeight();
self._triggerChangeEvent();
self.grid.endUpdate();
}
});
}
};
GridStack.prototype._triggerChangeEvent = function(forceTrigger) {
@ -836,7 +948,6 @@
};
GridStack.prototype._clearRemovingTimeout = function(el) {
var self = this;
var node = $(el).data('_gridstack_node');
if (!node._removeTimeout) {
@ -848,30 +959,8 @@
node._isAboutToRemove = false;
};
GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
triggerAddEvent = typeof triggerAddEvent != 'undefined' ? triggerAddEvent : false;
GridStack.prototype._prepareElementByNode = function(el, node) {
var self = this;
el = $(el);
el.addClass(this.opts.itemClass);
var node = self.grid.addNode({
x: el.attr('data-gs-x'),
y: el.attr('data-gs-y'),
width: el.attr('data-gs-width'),
height: el.attr('data-gs-height'),
maxWidth: el.attr('data-gs-max-width'),
minWidth: el.attr('data-gs-min-width'),
maxHeight: el.attr('data-gs-max-height'),
minHeight: el.attr('data-gs-min-height'),
autoPosition: Utils.toBool(el.attr('data-gs-auto-position')),
noResize: Utils.toBool(el.attr('data-gs-no-resize')),
noMove: Utils.toBool(el.attr('data-gs-no-move')),
locked: Utils.toBool(el.attr('data-gs-locked')),
el: el,
id: el.attr('data-gs-id'),
_grid: self
}, triggerAddEvent);
el.data('_gridstack_node', node);
var cellWidth;
var cellHeight;
@ -958,9 +1047,13 @@
};
var onEndMoving = function(event, ui) {
var o = $(this);
if (!o.data('_gridstack_node')) {
return;
}
var forceNotify = false;
self.placeholder.detach();
var o = $(this);
node.el = o;
self.placeholder.hide();
@ -1027,6 +1120,34 @@
el.attr('data-gs-locked', node.locked ? 'yes' : null);
};
GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
triggerAddEvent = typeof triggerAddEvent != 'undefined' ? triggerAddEvent : false;
var self = this;
el = $(el);
el.addClass(this.opts.itemClass);
var node = self.grid.addNode({
x: el.attr('data-gs-x'),
y: el.attr('data-gs-y'),
width: el.attr('data-gs-width'),
height: el.attr('data-gs-height'),
maxWidth: el.attr('data-gs-max-width'),
minWidth: el.attr('data-gs-min-width'),
maxHeight: el.attr('data-gs-max-height'),
minHeight: el.attr('data-gs-min-height'),
autoPosition: Utils.toBool(el.attr('data-gs-auto-position')),
noResize: Utils.toBool(el.attr('data-gs-no-resize')),
noMove: Utils.toBool(el.attr('data-gs-no-move')),
locked: Utils.toBool(el.attr('data-gs-locked')),
el: el,
id: el.attr('data-gs-id'),
_grid: self
}, triggerAddEvent);
el.data('_gridstack_node', node);
this._prepareElementByNode(el, node);
};
GridStack.prototype.setAnimation = function(enable) {
if (enable) {
this.container.addClass('grid-stack-animate');
@ -1413,10 +1534,13 @@
this.grid.commit();
};
GridStack.prototype.setGridWidth = function(gridWidth) {
GridStack.prototype.setGridWidth = function(gridWidth,doNotPropagate) {
this.container.removeClass('grid-stack-' + this.opts.width);
this._updateNodeWidths(this.opts.width, gridWidth);
if (doNotPropagate !== true) {
this._updateNodeWidths(this.opts.width, gridWidth);
}
this.opts.width = gridWidth;
this.grid.width = gridWidth;
this.container.addClass('grid-stack-' + gridWidth);
};