Merge commit 'a33f046fa6b05ad2e42f4b3eaf2d0921504f2b4b'
This commit is contained in:
commit
3f374257f2
2
.jscsrc
2
.jscsrc
|
@ -15,5 +15,5 @@
|
|||
"requireTrailingComma": false,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireCapitalizedComments": false,
|
||||
"excludeFiles": ["dist/*.js", "demo/*"]
|
||||
"excludeFiles": ["dist/*.js", "demo/*", "spec/*"]
|
||||
}
|
||||
|
|
13
README.md
13
README.md
|
@ -3,6 +3,8 @@ gridstack.js
|
|||
|
||||
[![Build Status](https://travis-ci.org/troolee/gridstack.js.svg?branch=master)](https://travis-ci.org/troolee/gridstack.js)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/troolee/gridstack.js/badge.svg?branch=master)](https://coveralls.io/github/troolee/gridstack.js?branch=master)
|
||||
[![Dependency Status](https://david-dm.org/troolee/gridstack.js.svg)](https://david-dm.org/troolee/gridstack.js)
|
||||
[![devDependency Status](https://david-dm.org/troolee/gridstack.js/dev-status.svg)](https://david-dm.org/troolee/gridstack.js#info=devDependencies)
|
||||
|
||||
gridstack.js is a jQuery plugin for widget layout. This is drag-and-drop multi-column grid. It allows you to build
|
||||
draggable responsive bootstrap v3 friendly layouts. It also works great with [knockout.js](http://knockoutjs.com), [angular.js](https://angularjs.org) and touch devices.
|
||||
|
@ -37,6 +39,7 @@ Join gridstack.js on Slack: https://gridstackjs.troolee.com
|
|||
- [IE8 support](#ie8-support)
|
||||
- [Nested grids](#nested-grids)
|
||||
- [Resizing active grid](#resizing-active-grid)
|
||||
- [The Team](#the-team)
|
||||
- [Changes](#changes)
|
||||
- [v0.2.5-dev (Development version)](#v025-dev-development-version)
|
||||
- [v0.2.4 (2016-02-15)](#v024-2016-02-15)
|
||||
|
@ -85,6 +88,8 @@ $ bower install gridstack
|
|||
|
||||
* Using npm:
|
||||
|
||||
[![NPM version](https://img.shields.io/npm/v/gridstack.svg)](https://www.npmjs.com/package/gridstack)
|
||||
|
||||
```bash
|
||||
$ npm install gridstack
|
||||
```
|
||||
|
@ -436,6 +441,14 @@ Resizing on-the-fly is possible, though experimental. This may be used to make g
|
|||
See example: [Responsive grid demo](http://troolee.github.io/gridstack.js/demo/responsive.html)
|
||||
|
||||
|
||||
The Team
|
||||
========
|
||||
|
||||
gridstack.js is currently maintained by [Pavel Reznikov](https://github.com/troolee), [Dylan Weiss](https://github.com/radiolips)
|
||||
and [Kevin Dietrich](https://github.com/kdietrich). And we appreciate [all contributors](https://github.com/troolee/gridstack.js/graphs/contributors)
|
||||
for help.
|
||||
|
||||
|
||||
Changes
|
||||
=======
|
||||
|
||||
|
|
12
dist/gridstack.js
vendored
12
dist/gridstack.js
vendored
|
@ -87,11 +87,6 @@
|
|||
return n != this.node && Utils.isIntercepted(n, this.nn);
|
||||
},
|
||||
|
||||
_didCollideFloat: function(bn) {
|
||||
return this.n != bn &&
|
||||
Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn);
|
||||
},
|
||||
|
||||
_didCollide: function(bn) {
|
||||
return Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn);
|
||||
},
|
||||
|
@ -108,7 +103,7 @@
|
|||
if (!match) {
|
||||
throw new Error('Invalid height');
|
||||
}
|
||||
heightUnit = match[2];
|
||||
heightUnit = match[2] || 'px';
|
||||
height = parseFloat(match[1]);
|
||||
}
|
||||
return {height: height, unit: heightUnit};
|
||||
|
@ -182,7 +177,7 @@
|
|||
var collisionNode = _.find(this.nodes, _.bind(function(n) {
|
||||
return Utils.isIntercepted(n, nn);
|
||||
}, this));
|
||||
return collisionNode === null;
|
||||
return collisionNode === null || typeof collisionNode === 'undefined';
|
||||
};
|
||||
|
||||
GridStackEngine.prototype._sortNodes = function(dir) {
|
||||
|
@ -282,7 +277,7 @@
|
|||
if (this._updateCounter) {
|
||||
return;
|
||||
}
|
||||
var deletedNodes = Array.prototype.slice.call(arguments, 1).concat(this.getDirtyNodes());
|
||||
var deletedNodes = Array.prototype.slice.call(arguments, 0);
|
||||
deletedNodes = deletedNodes.concat(this.getDirtyNodes());
|
||||
this.onchange(deletedNodes);
|
||||
};
|
||||
|
@ -1450,6 +1445,7 @@
|
|||
scope.GridStackUI = GridStack;
|
||||
|
||||
scope.GridStackUI.Utils = Utils;
|
||||
scope.GridStackUI.Engine = GridStackEngine;
|
||||
|
||||
$.fn.gridstack = function(opts) {
|
||||
return this.each(function() {
|
||||
|
|
6
dist/gridstack.min.js
vendored
6
dist/gridstack.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/gridstack.min.map
vendored
2
dist/gridstack.min.map
vendored
File diff suppressed because one or more lines are too long
|
@ -24,13 +24,18 @@
|
|||
"url": "https://github.com/troolee/gridstack.js/issues"
|
||||
},
|
||||
"homepage": "http://troolee.github.io/gridstack.js/",
|
||||
"dependencies": {
|
||||
"jquery": "^2.2.1",
|
||||
"jquery-ui": "^1.10.5",
|
||||
"lodash": "^4.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.11.6",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-contrib-copy": "^0.8.2",
|
||||
"grunt-contrib-cssmin": "^0.14.0",
|
||||
"grunt-contrib-jshint": "^1.0.0",
|
||||
"grunt-contrib-uglify": "^0.10.1",
|
||||
"grunt-contrib-uglify": "^0.11.1",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-doctoc": "^0.1.1",
|
||||
"grunt-jscs": "^2.7.0",
|
||||
|
|
160
spec/gridstack-engine-spec.js
Normal file
160
spec/gridstack-engine-spec.js
Normal file
|
@ -0,0 +1,160 @@
|
|||
describe('gridstack engine', function() {
|
||||
'use strict';
|
||||
|
||||
var e;
|
||||
var w;
|
||||
|
||||
beforeEach(function() {
|
||||
w = window;
|
||||
e = w.GridStackUI.Engine;
|
||||
});
|
||||
|
||||
describe('test constructor', function() {
|
||||
var engine;
|
||||
|
||||
beforeAll(function() {
|
||||
engine = new GridStackUI.Engine(12);
|
||||
})
|
||||
|
||||
it('should be setup properly', function() {
|
||||
expect(engine.width).toEqual(12);
|
||||
expect(engine.float).toEqual(false);
|
||||
expect(engine.height).toEqual(0);
|
||||
expect(engine.nodes).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test _prepareNode', function() {
|
||||
var engine;
|
||||
|
||||
beforeAll(function() {
|
||||
engine = new GridStackUI.Engine(12);
|
||||
})
|
||||
|
||||
it('should prepare a node', function() {
|
||||
expect(engine._prepareNode({}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({x: 10}, false)).toEqual(jasmine.objectContaining({x: 10, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({x: -10}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({y: 10}, false)).toEqual(jasmine.objectContaining({x: 0, y: 10, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({y: -10}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({width: 3}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 3, height: 1}));
|
||||
expect(engine._prepareNode({width: 100}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 12, height: 1}));
|
||||
expect(engine._prepareNode({width: 0}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({width: -190}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({height: 3}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 3}));
|
||||
expect(engine._prepareNode({height: 0}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({height: -10}, false)).toEqual(jasmine.objectContaining({x: 0, y: 0, width: 1, height: 1}));
|
||||
expect(engine._prepareNode({x: 4, width: 10}, false)).toEqual(jasmine.objectContaining({x: 2, y: 0, width: 10, height: 1}));
|
||||
expect(engine._prepareNode({x: 4, width: 10}, true)).toEqual(jasmine.objectContaining({x: 4, y: 0, width: 8, height: 1}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('test isAreaEmpty', function() {
|
||||
var engine;
|
||||
|
||||
beforeAll(function() {
|
||||
engine = new GridStackUI.Engine(12, null, true);
|
||||
engine.nodes = [
|
||||
engine._prepareNode({x: 3, y: 2, width: 3, height: 2})
|
||||
];
|
||||
})
|
||||
|
||||
it('should be true', function() {
|
||||
expect(engine.isAreaEmpty(0, 0, 3, 2)).toEqual(true);
|
||||
expect(engine.isAreaEmpty(3, 4, 3, 2)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be false', function() {
|
||||
expect(engine.isAreaEmpty(1, 1, 3, 2)).toEqual(false);
|
||||
expect(engine.isAreaEmpty(2, 3, 3, 2)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test cleanNodes/getDirtyNodes', function() {
|
||||
var engine;
|
||||
|
||||
beforeAll(function() {
|
||||
engine = new GridStackUI.Engine(12, null, true);
|
||||
engine.nodes = [
|
||||
engine._prepareNode({x: 0, y: 0, width: 1, height: 1, idx: 1, _dirty: true}),
|
||||
engine._prepareNode({x: 3, y: 2, width: 3, height: 2, idx: 2, _dirty: true}),
|
||||
engine._prepareNode({x: 3, y: 7, width: 3, height: 2, idx: 3})
|
||||
];
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
engine._updateCounter = 0;
|
||||
});
|
||||
|
||||
it('should return all dirty nodes', function() {
|
||||
var nodes = engine.getDirtyNodes();
|
||||
|
||||
expect(nodes.length).toEqual(2);
|
||||
expect(nodes[0].idx).toEqual(1);
|
||||
expect(nodes[1].idx).toEqual(2);
|
||||
});
|
||||
|
||||
it('should\'n clean nodes if _updateCounter > 0', function() {
|
||||
engine._updateCounter = 1;
|
||||
engine.cleanNodes();
|
||||
|
||||
expect(engine.getDirtyNodes().length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should clean all dirty nodes', function() {
|
||||
engine.cleanNodes();
|
||||
|
||||
expect(engine.getDirtyNodes().length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test _notify', function() {
|
||||
var engine;
|
||||
var spy;
|
||||
|
||||
beforeEach(function() {
|
||||
spy = {
|
||||
callback: function () {}
|
||||
}
|
||||
spyOn(spy, 'callback');
|
||||
|
||||
engine = new GridStackUI.Engine(12, spy.callback, true);
|
||||
|
||||
engine.nodes = [
|
||||
engine._prepareNode({x: 0, y: 0, width: 1, height: 1, idx: 1, _dirty: true}),
|
||||
engine._prepareNode({x: 3, y: 2, width: 3, height: 2, idx: 2, _dirty: true}),
|
||||
engine._prepareNode({x: 3, y: 7, width: 3, height: 2, idx: 3})
|
||||
];
|
||||
});
|
||||
|
||||
it('should\'n be called if _updateCounter > 0', function() {
|
||||
engine._updateCounter = 1;
|
||||
engine._notify();
|
||||
|
||||
expect(spy.callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should by called with dirty nodes', function() {
|
||||
engine._notify();
|
||||
|
||||
expect(spy.callback).toHaveBeenCalledWith([
|
||||
engine.nodes[0],
|
||||
engine.nodes[1]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should by called with extra passed dirty nodes', function() {
|
||||
var n1 = {idx: -1},
|
||||
n2 = {idx: -2};
|
||||
|
||||
engine._notify(n1, n2);
|
||||
|
||||
expect(spy.callback).toHaveBeenCalledWith([
|
||||
n1,
|
||||
n2,
|
||||
engine.nodes[0],
|
||||
engine.nodes[1]
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -39,5 +39,59 @@ describe('gridstack utils', function() {
|
|||
|
||||
});
|
||||
|
||||
describe('test isIntercepted', function() {
|
||||
var src = {x: 3, y: 2, width: 3, height: 2};
|
||||
|
||||
});
|
||||
it('should intercept.', function() {
|
||||
expect(utils.isIntercepted(src, {x: 0, y: 0, width: 4, height: 3})).toEqual(true);
|
||||
expect(utils.isIntercepted(src, {x: 0, y: 0, width: 40, height: 30})).toEqual(true);
|
||||
expect(utils.isIntercepted(src, {x: 3, y: 2, width: 3, height: 2})).toEqual(true);
|
||||
expect(utils.isIntercepted(src, {x: 5, y: 3, width: 3, height: 2})).toEqual(true);
|
||||
});
|
||||
|
||||
it('shouldn\'t intercept.', function() {
|
||||
expect(utils.isIntercepted(src, {x: 0, y: 0, width: 3, height: 2})).toEqual(false);
|
||||
expect(utils.isIntercepted(src, {x: 0, y: 0, width: 13, height: 2})).toEqual(false);
|
||||
expect(utils.isIntercepted(src, {x: 1, y: 4, width: 13, height: 2})).toEqual(false);
|
||||
expect(utils.isIntercepted(src, {x: 0, y: 3, width: 3, height: 2})).toEqual(false);
|
||||
expect(utils.isIntercepted(src, {x: 6, y: 3, width: 3, height: 2})).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test createStylesheet/removeStylesheet', function() {
|
||||
|
||||
it('should create/remove style DOM', function() {
|
||||
var _id = 'test-123';
|
||||
|
||||
utils.createStylesheet(_id);
|
||||
|
||||
var style = $('STYLE[data-gs-style-id=' + _id + ']');
|
||||
|
||||
expect(style.size()).toEqual(1);
|
||||
expect(style.prop('tagName')).toEqual('STYLE');
|
||||
|
||||
utils.removeStylesheet(_id)
|
||||
|
||||
style = $('STYLE[data-gs-style-id=' + _id + ']');
|
||||
|
||||
expect(style.size()).toEqual(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('test parseHeight', function() {
|
||||
|
||||
it('should parse 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');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -87,11 +87,6 @@
|
|||
return n != this.node && Utils.isIntercepted(n, this.nn);
|
||||
},
|
||||
|
||||
_didCollideFloat: function(bn) {
|
||||
return this.n != bn &&
|
||||
Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn);
|
||||
},
|
||||
|
||||
_didCollide: function(bn) {
|
||||
return Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn);
|
||||
},
|
||||
|
@ -108,7 +103,7 @@
|
|||
if (!match) {
|
||||
throw new Error('Invalid height');
|
||||
}
|
||||
heightUnit = match[2];
|
||||
heightUnit = match[2] || 'px';
|
||||
height = parseFloat(match[1]);
|
||||
}
|
||||
return {height: height, unit: heightUnit};
|
||||
|
@ -182,7 +177,7 @@
|
|||
var collisionNode = _.find(this.nodes, _.bind(function(n) {
|
||||
return Utils.isIntercepted(n, nn);
|
||||
}, this));
|
||||
return collisionNode === null;
|
||||
return collisionNode === null || typeof collisionNode === 'undefined';
|
||||
};
|
||||
|
||||
GridStackEngine.prototype._sortNodes = function(dir) {
|
||||
|
@ -282,7 +277,7 @@
|
|||
if (this._updateCounter) {
|
||||
return;
|
||||
}
|
||||
var deletedNodes = Array.prototype.slice.call(arguments, 1).concat(this.getDirtyNodes());
|
||||
var deletedNodes = Array.prototype.slice.call(arguments, 0);
|
||||
deletedNodes = deletedNodes.concat(this.getDirtyNodes());
|
||||
this.onchange(deletedNodes);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue