Merge commit 'acc2acbec1a2839656bd1a04a30ab8b219dc1df5'

This commit is contained in:
Dylan Weiss 2016-02-13 17:12:38 -05:00
commit 96b84ed45b
18 changed files with 2426 additions and 433 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules

61
Gruntfile.js Executable file
View file

@ -0,0 +1,61 @@
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-doctoc');
grunt.initConfig({
sass: {
options: {
outputStyle: 'expanded'
},
dist: {
files: {
'dist/gridstack.css': 'src/gridstack.scss',
'dist/gridstack-extra.css': 'src/gridstack-extra.scss'
}
}
},
cssmin: {
dist: {
files: {
'dist/gridstack.min.css': ['dist/gridstack.css'],
'dist/gridstack-extra.min.css': ['dist/gridstack-extra.css']
}
}
},
copy: {
dist: {
files: {
'dist/gridstack.js': ['src/gridstack.js']
}
}
},
uglify: {
options: {
sourceMap: true,
sourceMapName: 'dist/gridstack.min.map'
},
dist: {
files: {
'dist/gridstack.min.js': ['src/gridstack.js']
}
}
},
doctoc: {
options: {
removeAd: false
},
readme: {
target: "./README.md"
}
}
});
grunt.registerTask('default', ['sass', 'cssmin', 'copy', 'uglify', 'doctoc']);
};

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Pavel Reznikov
Copyright (c) 2014-2016 Pavel Reznikov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

229
README.md
View file

@ -1,15 +1,19 @@
gridstack.js
============
gridstack.js is a jQuery plugin for widget layout. This is drag-and-drop multi-column grid. It allows you to build
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) and
touch devices.
Inspired by [gridster.js](http://gridster.net). Built with love.
Join gridstack.js on Slack: https://gridstackjs.troolee.com
[![Slack Status](https://gridstackjs.troolee.com/badge.svg)](https://gridstackjs.troolee.com)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
- [Demo](#demo)
- [Usage](#usage)
@ -24,38 +28,50 @@ Inspired by [gridster.js](http://gridster.net). Built with love.
- [ondragstop(event, ui)](#ondragstopevent-ui)
- [onresizestart(event, ui)](#onresizestartevent-ui)
- [onresizestop(event, ui)](#onresizestopevent-ui)
- [disable(event)](#disableevent)
- [enable(event)](#enableevent)
- [API](#api)
- [add_widget(el, x, y, width, height, auto_position)](#add_widgetel-x-y-width-height-auto_position)
- [make_widget(el)](#make_widgetel)
- [batch_update()](#batch_update)
- [cell_height()](#cell_height)
- [cell_height(val)](#cell_heightval)
- [cell_width()](#cell_width)
- [commit()](#commit)
- [destroy()](#destroy)
- [disable()](#disable)
- [enable()](#enable)
- [get_cell_from_pixel(position)](#get_cell_from_pixelposition)
- [is_area_empty(x, y, width, height)](#is_area_emptyx-y-width-height)
- [locked(el, val)](#lockedel-val)
- [min_width(el, val)](#min_widthel-val)
- [min_height(el, val)](#min_heightel-val)
- [movable(el, val)](#movableel-val)
- [move(el, x, y)](#moveel-x-y)
- [remove_widget(el, detach_node)](#remove_widgetel-detach_node)
- [remove_all()](#remove_all)
- [resize(el, width, height)](#resizeel-width-height)
- [move(el, x, y)](#moveel-x-y)
- [resizable(el, val)](#resizableel-val)
- [movable(el, val)](#movableel-val)
- [set_static(static_value)](#set_staticstatic_value)
- [update(el, x, y, width, height)](#updateel-x-y-width-height)
- [will_it_fit(x, y, width, height, auto_position)](#will_it_fitx-y-width-height-auto_position)
- [Utils](#utils)
- [GridStackUI.Utils.sort(nodes, dir, width)](#gridstackuiutilssortnodes-dir-width)
- [GridStackUI.Utils.sort(nodes[, dir[, width]])](#gridstackuiutilssortnodes-dir-width)
- [Touch devices support](#touch-devices-support)
- [Use with knockout.js](#use-with-knockoutjs)
- [Use with angular.js](#use-with-angularjs)
- [Rails integration](#rails-integration)
- [Change grid width](#change-grid-width)
- [Extra CSS](#extra-css)
- [Different grid widths](#different-grid-widths)
- [Save grid to array](#save-grid-to-array)
- [Load grid from array](#load-grid-from-array)
- [Override resizable/draggable options](#override-resizabledraggable-options)
- [IE8 support](#ie8-support)
- [Nested grids](#nested-grids)
- [Changes](#changes)
- [v0.2.3 (development version)](#v023-development-version)
- [v0.2.4 (development version)](#v024-development-version)
- [v0.2.3 (2015-06-23)](#v023-2015-06-23)
- [v0.2.2 (2014-12-23)](#v022-2014-12-23)
- [v0.2.1 (2014-12-09)](#v021-2014-12-09)
- [v0.2.0 (2014-11-30)](#v020-2014-11-30)
@ -77,7 +93,7 @@ Usage
## Requirements
* [lodash.js](https://lodash.com) (>= 3.5.0)
* [jQuery](http://jquery.com) (>= 1.11.0)
* [jQuery](http://jquery.com) (>= 1.11.0)
* [jQuery UI](http://jqueryui.com) (>= 1.11.0). Minimum required components: Core, Widget, Mouse, Draggable, Resizable
* (Optional) [knockout.js](http://knockoutjs.com) (>= 3.2.0)
* (Optional) [jquery-ui-touch-punch](https://github.com/furf/jquery-ui-touch-punch) for touch-based devices support
@ -88,13 +104,13 @@ Note: You can still use [underscore.js](http://underscorejs.org) (>= 1.7.0) inst
```html
<div class="grid-stack">
<div class="grid-stack-item"
data-gs-x="0" data-gs-y="0"
<div class="grid-stack-item"
data-gs-x="0" data-gs-y="0"
data-gs-width="4" data-gs-height="2">
<div class="grid-stack-item-content"></div>
</div>
<div class="grid-stack-item"
data-gs-x="4" data-gs-y="0"
<div class="grid-stack-item"
data-gs-x="4" data-gs-y="0"
data-gs-width="4" data-gs-height="4">
<div class="grid-stack-item-content"></div>
</div>
@ -113,25 +129,28 @@ $(function () {
## Options
- `always_show_resize_handle` - if `true` the resizing handles are shown even the user is not hovering over the widget
(default: `false`)
- `always_show_resize_handle` - 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`)
- `auto` - if `false` it tells to do not initialize existing items (default: `true`)
- `auto` - if `false` gridstack will not initialize existing items (default: `true`)
- `cell_height` - one cell height (default: `60`)
- `draggable` - allows to override jQuery UI draggable options. (default: `{handle: '.grid-stack-item-content', scroll: true, appendTo: 'body'}`)
- `draggable` - allows to override jQuery UI draggable options. (default: `{handle: '.grid-stack-item-content', scroll: true, appendTo: 'body'}`)
- `handle` - draggable handle selector (default: `'.grid-stack-item-content'`)
- `handle_class` - draggable handle class (e.g. `'grid-stack-item-content'`). If set `handle` is ignored (default: `null`)
- `height` - maximum rows amount. Default is `0` which means no maximum rows
- `float` - enable floating widgets (default: `false`) See [example](http://troolee.github.io/gridstack.js/demo/float.html)
- `item_class` - widget class (default: `'grid-stack-item'`)
- `min_width` - minimal width. If window width is less grid will be shown in one-column mode (default: `768`)
- `min_width` - minimal width. If window width is less, grid will be shown in one-column mode. You need also update your css file (`@media (max-width: 768px) {...}`) with corresponding value (default: `768`)
- `placeholder_class` - class for placeholder (default: `'grid-stack-placeholder'`)
- `placeholder_text` - placeholder default content (default: `''`)
- `resizable` - allows to override jQuery UI resizable options. (default: `{autoHide: true, handles: 'se'}`)
- `static_grid` - makes grid static (default `false`). If true widgets are not movable/resizable. You don't even need jQueryUI draggable/resizable. A CSS class `grid-stack-static` is also added to the container.
- `vertical_margin` - vertical gap size (default: `20`)
- `width` - amount of columns (default: `12`)
## Grid attributes
- `data-gs-animate` - turns animation on
- `data-gs-animate` - turns animation on
- `data-gs-width` - amount of columns
- `data-gs-height` - maximum rows amount. Default is `0` which means no maximum rows.
@ -141,18 +160,18 @@ $(function () {
- `data-gs-width`, `data-gs-height` - element size
- `data-gs-max-width`, `data-gs-min-width`, `data-gs-max-height`, `data-gs-min-height` - element constraints
- `data-gs-no-resize` - disable element resizing
- `data-gs-no-move` - disable element moving
- `data-gs-auto-position` - tells to ignore `data-gs-x` and `data-gs-y` attributes and to place element to the first
- `data-gs-no-move` - disable element moving
- `data-gs-auto-position` - tells to ignore `data-gs-x` and `data-gs-y` attributes and to place element to the first
available position
- `data-gs-locked` - the widget will be locked. It means another widgets couldn't move it during dragging or resizing.
The widget is still can be dragged or resized. You need to add `data-gs-no-resize` and `data-gs-no-move` attributes
- `data-gs-locked` - the widget will be locked. It means another widget wouldn't be able to move it during dragging or resizing.
The widget can still be dragged or resized. You need to add `data-gs-no-resize` and `data-gs-no-move` attributes
to completely lock the widget.
## Events
### onchange(items)
Occurs when widgets change their position/size
Occurs when adding/removing widgets or existing widgets change their position/size
```javascript
var serialize_widget_map = function (items) {
@ -200,6 +219,21 @@ $('.grid-stack').on('resizestop', function (event, ui) {
});
```
### disable(event)
```javascipt
$('.grid-stack').on('disable', function(event) {
var grid = event.target;
});
```
### enable(event)
```javascipt
$('.grid-stack').on('enable', function(event) {
var grid = event.target;
});
```
## API
@ -214,8 +248,8 @@ Parameters:
- `auto_position` - if `true` then `x`, `y` parameters will be ignored and widget will be places on the first available
position
Widget will be always placed even if result height will be more then grid height. You need to use `will_it_fit` method
before call `add_widget` for additional check.
Widget will be always placed even if result height is more than actual grid height. You need to use `will_it_fit` method
before calling `add_widget` for additional check.
```javascript
$('.grid-stack').gridstack();
@ -224,9 +258,26 @@ var grid = $('.grid-stack').data('gridstack');
grid.add_widget(el, 0, 0, 3, 2, true);
```
### make_widget(el)
If you add elements to your gridstack container by hand, you have to tell gridstack afterwards to make them widgets. If you want gridstack to add the elements for you, use `add_widget` instead.
Makes the given element a widget and returns it.
Parameters:
- `el` - element to convert to a widget
```javascript
$('.grid-stack').gridstack();
$('.grid-stack').append('<div id="gsi-1" data-gs-x="0" data-gs-y="0" data-gs-width="3" data-gs-height="2" data-gs-auto-position="1"></div>')
var grid = $('.grid-stack').data('gridstack');
grid.make_widget('gsi-1');
```
### batch_update()
Initailizes batch updates. You will see no changes until `commit` method is called.
Initailizes batch updates. You will see no changes until `commit` method is called.
### cell_height()
@ -249,6 +300,10 @@ Gets current cell width.
Finishes batch updates. Updates DOM nodes. You must call it after `batch_update`.
### destroy()
Destroys a grid instance.
### disable()
Disables widgets moving/resizing. This is a shortcut for:
@ -286,7 +341,37 @@ Checks if specified area is empty.
Locks/unlocks widget.
- `el` - widget to modify.
- `val` - if `true` widget will be locked.
- `val` - if `true` widget will be locked.
### min_width(el, val)
Set the minWidth for a widget.
- `el` - widget to modify.
- `val` - A numeric value of the number of columns
### min_height(el, val)
Set the minHeight for a widget.
- `el` - widget to modify.
- `val` - A numeric value of the number of rows
### movable(el, val)
Enables/Disables moving.
- `el` - widget to modify
- `val` - if `true` widget will be draggable.
### move(el, x, y)
Changes widget position
Parameters:
- `el` - widget to move
- `x`, `y` - new position. If value is `null` or `undefined` it will be ignored.
### remove_widget(el, detach_node)
@ -310,28 +395,18 @@ Parameters:
- `el` - widget to resize
- `width`, `height` - new dimensions. If value is `null` or `undefined` it will be ignored.
### move(el, x, y)
Changes widget position
Parameters:
- `el` - widget to move
- `x`, `y` - new position. If value is `null` or `undefined` it will be ignored.
### resizable(el, val)
Enables/Disables resizing.
- `el` - widget to modify
- `val` - if `true` widget will be resizable.
- `val` - if `true` widget will be resizable.
### movable(el, val)
### set_static(static_value)
Enables/Disables moving.
Toggle the grid static state. Also toggle the `grid-stack-static` class.
- `el` - widget to modify
- `val` - if `true` widget will be draggable.
- `static_value` - if `true` the grid become static.
### update(el, x, y, width, height)
@ -350,17 +425,17 @@ have `height` constraint.
```javascript
if (grid.will_it_fit(new_node.x, new_node.y, new_node.width, new_node.height, true)) {
grid.add_widget(new_node.x, new_node.y, new_node.width, new_node.height, true);
grid.add_widget(new_node.el, new_node.x, new_node.y, new_node.width, new_node.height, true);
}
else {
alert('Not enough free space to place the widget');
}
```
## Utils
### GridStackUI.Utils.sort(nodes, dir, width)
### GridStackUI.Utils.sort(nodes[, dir[, width]])
Sorts array of nodes
@ -466,16 +541,26 @@ template:
' ....',
' </div>', // <-- NO SPACE **AFTER** </div>
'</div> ' // <-- NO SPACE **BEFORE** </div>
].join('') // <-- JOIN WITH **EMPTY** STRING
].join('') // <-- JOIN WITH **EMPTY** STRING
```
Otherwise `addDisposeCallback` won't work.
## Use with angular.js
Please check [gridstack-angular](https://github.com/kdietrich/gridstack-angular)
## Rails integration
For rails users, integration of gridstack.js and its dependencies can be done through [gridstack-js-rails](https://github.com/randoum/gridstack-js-rails)
## Change grid width
To change grid width (columns count), to addition to `width` option, CSS rules
for `.grid-stack-item[data-gs-width="X"]` and `.grid-stack-item[data-gs-x="X"]` have to be changed accordingly.
To change grid width (columns count), to addition to `width` option, CSS rules
for `.grid-stack-item[data-gs-width="X"]` and `.grid-stack-item[data-gs-x="X"]` have to be changed accordingly.
For instance for 3-column grid you need to rewrite CSS to be:
@ -519,10 +604,29 @@ Here is a SASS code snipped which can make life easier (Thanks to @ascendantofra
}
```
Or you can include `gridstack-extra.css`. See below for more details.
## Extra CSS
There are few extra CSS batteries in `gridstack-extra.css` (`gridstack-extra.min.css`).
### Different grid widths
You can use other than 12 grid width:
```html
<div class="grid-stack grid-stack-N">...</div>
```
```javascript
$('.grid-stack').gridstack({width: N});
```
See example: [2 grids demo](http://troolee.github.io/gridstack.js/demo/two.html)
## Save grid to array
Because gridstack doesn't track any kind of user-defined widget id there is no reason to make serialization to be part
of gridstack API. To serialize grid you can simply do something like this (let's say you store widget id inside `data-custom-id`
of gridstack API. To serialize grid you can simply do something like this (let's say you store widget id inside `data-custom-id`
attribute):
```javascript
@ -542,7 +646,7 @@ alert(JSON.stringify(res));
See example: [Serialization demo](http://troolee.github.io/gridstack.js/demo/serialization.html)
You can also use `onchange` event if you need to save only changed widgets right away they have been changed.
You can also use `onchange` event if you need to save only changed widgets right away they have been changed.
## Load grid from array
@ -564,7 +668,7 @@ var grid = $('.grid-stack').data('gridstack');
grid.remove_all();
_.each(serialization, function (node) {
grid.add_widget($('<div><div class="grid-stack-item-content" /><div/>'),
grid.add_widget($('<div><div class="grid-stack-item-content" /></div>'),
node.x, node.y, node.width, node.height);
});
```
@ -630,22 +734,32 @@ for i in range(N):
print '.grid-stack > .grid-stack-item[data-gs-y="%(index)s"] { top: %(height)spx }' % {'index': i , 'height': h}
```
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
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
## Nested grids
Gridstack may be nested. All nested grids have an additional class `grid-stack-nested` which is assigned automatically
during initialization.
Gridstack may be nested. All nested grids have an additional class `grid-stack-nested` which is assigned automatically
during initialization.
See example: [Nested grid demo](http://troolee.github.io/gridstack.js/demo/nested.html)
Changes
=======
#### v0.2.3 (development version)
#### v0.2.4 (development version)
- fix closure compiler/linter warnings
- add `static_grid` option.
- add `min_width`/`min_height` methods (Thanks to @cvillemure)
- add `destroy` method (Thanks to @zspitzer)
- add `placeholder_text` option (Thanks to @slauyama)
- lodash v 4.x support (Thanks to Andy Robbins)
#### v0.2.3 (2015-06-23)
- gridstack-extra.css
- add support of lodash.js
- add `is_area_empty` method
- nested grids
@ -683,7 +797,7 @@ Changes
- auto-generate css rules (widgets `height` and `top`)
- add `GridStackUI.Utils.sort` utility function
- add `remove_all` API method
- add `resize` and `move` API methods
- add `resize` and `move` API methods
- add `resizable` and `movable` API methods
- add `data-gs-no-move` attribute
- add `float` option
@ -700,7 +814,7 @@ License
The MIT License (MIT)
Copyright (c) 2014-2015 Pavel Reznikov
Copyright (c) 2014-2016 Pavel Reznikov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -719,4 +833,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,6 +1,6 @@
{
"name": "gridstack",
"version": "0.2.2",
"version": "0.2.3",
"homepage": "https://github.com/troolee/gridstack.js",
"authors": [
"Pavel Reznikov <pashka.reznikov@gmail.com>"

View file

@ -56,6 +56,7 @@
<script type="text/javascript">
$(function () {
var options = {
static_grid: true
};
$('.grid-stack').gridstack(options);

85
demo/two.html Normal file
View file

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Two grids demo</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="../dist/gridstack.css"/>
<link rel="stylesheet" href="../dist/gridstack-extra.css"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
<script src="../dist/gridstack.js"></script>
<style type="text/css">
#grid1 {
background: lightgoldenrodyellow;
}
#grid2 {
background: lightcyan;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #18bc9c;
}
</style>
</head>
<body>
<div class="container-fluid">
<h1>Two grids demo</h1>
<div class="row">
<div class="col-md-6">
<div class="grid-stack grid-stack-6" id="grid1">
</div>
</div>
<div class="col-md-6">
<div class="grid-stack grid-stack-6" id="grid2">
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
var options = {
width: 6,
float: true
};
$('#grid1').gridstack(options);
$('#grid2').gridstack(options);
var items = [
{x: 0, y: 0, width: 2, height: 2},
{x: 3, y: 1, width: 1, height: 2},
{x: 4, y: 1, width: 1, height: 1},
{x: 2, y: 3, width: 3, height: 1},
{x: 2, y: 5, width: 1, height: 1}
];
$('.grid-stack').each(function () {
var grid = $(this).data('gridstack');
_.each(items, function (node) {
grid.add_widget($('<div><div class="grid-stack-item-content" /><div/>'),
node.x, node.y, node.width, node.height);
}, this);
});
});
</script>
</body>
</html>

1295
dist/gridstack-extra.css vendored Normal file

File diff suppressed because it is too large Load diff

1
dist/gridstack-extra.min.css vendored Normal file

File diff suppressed because one or more lines are too long

148
dist/gridstack.css vendored
View file

@ -5,6 +5,7 @@
.grid-stack {
position: relative;
}
.grid-stack .grid-stack-placeholder > .placeholder-content {
border: 1px dashed lightgray;
margin: 0;
@ -15,12 +16,15 @@
bottom: 0;
width: auto;
z-index: 0 !important;
text-align: center;
}
.grid-stack > .grid-stack-item {
min-width: 8.33333333%;
min-width: 8.3333333333%;
position: absolute;
padding: 0;
}
.grid-stack > .grid-stack-item > .grid-stack-item-content {
margin: 0;
position: absolute;
@ -33,6 +37,7 @@
overflow-x: hidden;
overflow-y: auto;
}
.grid-stack > .grid-stack-item > .ui-resizable-handle {
position: absolute;
font-size: 0.1px;
@ -40,18 +45,23 @@
-ms-touch-action: none;
touch-action: none;
}
.grid-stack > .grid-stack-item.ui-resizable-disabled > .ui-resizable-handle, .grid-stack > .grid-stack-item.ui-resizable-autohide > .ui-resizable-handle {
.grid-stack > .grid-stack-item.ui-resizable-disabled > .ui-resizable-handle,
.grid-stack > .grid-stack-item.ui-resizable-autohide > .ui-resizable-handle {
display: none;
}
.grid-stack > .grid-stack-item.ui-draggable-dragging, .grid-stack > .grid-stack-item.ui-resizable-resizing {
z-index: 100;
}
.grid-stack > .grid-stack-item.ui-draggable-dragging > .grid-stack-item-content,
.grid-stack > .grid-stack-item.ui-draggable-dragging > .grid-stack-item-content, .grid-stack > .grid-stack-item.ui-resizable-resizing > .grid-stack-item-content,
.grid-stack > .grid-stack-item.ui-resizable-resizing > .grid-stack-item-content {
box-shadow: 1px 4px 6px rgba(0, 0, 0, 0.2);
opacity: 0.8;
}
.grid-stack > .grid-stack-item > .ui-resizable-se,
.grid-stack > .grid-stack-item > .ui-resizable-sw {
text-align: right;
@ -64,19 +74,21 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.grid-stack > .grid-stack-item > .ui-resizable-se::before,
.grid-stack > .grid-stack-item > .ui-resizable-sw::before {
content: "\f065";
}
.grid-stack > .grid-stack-item > .ui-resizable-se {
display: inline-block;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-o-transform: rotate(90deg);
transform: rotate(90deg);
}
.grid-stack > .grid-stack-item > .ui-resizable-nw {
cursor: nw-resize;
width: 20px;
@ -84,6 +96,7 @@
left: 10px;
top: 0;
}
.grid-stack > .grid-stack-item > .ui-resizable-n {
cursor: n-resize;
height: 10px;
@ -91,6 +104,7 @@
left: 25px;
right: 25px;
}
.grid-stack > .grid-stack-item > .ui-resizable-ne {
cursor: ne-resize;
width: 20px;
@ -98,6 +112,7 @@
right: 10px;
top: 0;
}
.grid-stack > .grid-stack-item > .ui-resizable-e {
cursor: e-resize;
width: 10px;
@ -105,6 +120,7 @@
top: 15px;
bottom: 15px;
}
.grid-stack > .grid-stack-item > .ui-resizable-se {
cursor: se-resize;
width: 20px;
@ -112,6 +128,7 @@
right: 10px;
bottom: 0;
}
.grid-stack > .grid-stack-item > .ui-resizable-s {
cursor: s-resize;
height: 10px;
@ -119,6 +136,7 @@
bottom: 0;
right: 25px;
}
.grid-stack > .grid-stack-item > .ui-resizable-sw {
cursor: sw-resize;
width: 20px;
@ -126,6 +144,7 @@
left: 10px;
bottom: 0;
}
.grid-stack > .grid-stack-item > .ui-resizable-w {
cursor: w-resize;
width: 10px;
@ -133,158 +152,211 @@
top: 15px;
bottom: 15px;
}
.grid-stack > .grid-stack-item[data-gs-width='1'] {
width: 8.33333333%;
width: 8.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-x='1'] {
left: 8.33333333%;
left: 8.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='1'] {
min-width: 8.33333333%;
min-width: 8.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='1'] {
max-width: 8.33333333%;
max-width: 8.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-width='2'] {
width: 16.66666667%;
width: 16.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-x='2'] {
left: 16.66666667%;
left: 16.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='2'] {
min-width: 16.66666667%;
min-width: 16.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='2'] {
max-width: 16.66666667%;
max-width: 16.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-width='3'] {
width: 25%;
}
.grid-stack > .grid-stack-item[data-gs-x='3'] {
left: 25%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='3'] {
min-width: 25%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='3'] {
max-width: 25%;
}
.grid-stack > .grid-stack-item[data-gs-width='4'] {
width: 33.33333333%;
width: 33.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-x='4'] {
left: 33.33333333%;
left: 33.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='4'] {
min-width: 33.33333333%;
min-width: 33.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='4'] {
max-width: 33.33333333%;
max-width: 33.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-width='5'] {
width: 41.66666667%;
width: 41.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-x='5'] {
left: 41.66666667%;
left: 41.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='5'] {
min-width: 41.66666667%;
min-width: 41.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='5'] {
max-width: 41.66666667%;
max-width: 41.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-width='6'] {
width: 50%;
}
.grid-stack > .grid-stack-item[data-gs-x='6'] {
left: 50%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='6'] {
min-width: 50%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='6'] {
max-width: 50%;
}
.grid-stack > .grid-stack-item[data-gs-width='7'] {
width: 58.33333333%;
width: 58.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-x='7'] {
left: 58.33333333%;
left: 58.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='7'] {
min-width: 58.33333333%;
min-width: 58.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='7'] {
max-width: 58.33333333%;
max-width: 58.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-width='8'] {
width: 66.66666667%;
width: 66.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-x='8'] {
left: 66.66666667%;
left: 66.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='8'] {
min-width: 66.66666667%;
min-width: 66.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='8'] {
max-width: 66.66666667%;
max-width: 66.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-width='9'] {
width: 75%;
}
.grid-stack > .grid-stack-item[data-gs-x='9'] {
left: 75%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='9'] {
min-width: 75%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='9'] {
max-width: 75%;
}
.grid-stack > .grid-stack-item[data-gs-width='10'] {
width: 83.33333333%;
width: 83.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-x='10'] {
left: 83.33333333%;
left: 83.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='10'] {
min-width: 83.33333333%;
min-width: 83.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='10'] {
max-width: 83.33333333%;
max-width: 83.3333333333%;
}
.grid-stack > .grid-stack-item[data-gs-width='11'] {
width: 91.66666667%;
width: 91.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-x='11'] {
left: 91.66666667%;
left: 91.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='11'] {
min-width: 91.66666667%;
min-width: 91.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='11'] {
max-width: 91.66666667%;
max-width: 91.6666666667%;
}
.grid-stack > .grid-stack-item[data-gs-width='12'] {
width: 100%;
}
.grid-stack > .grid-stack-item[data-gs-x='12'] {
left: 100%;
}
.grid-stack > .grid-stack-item[data-gs-min-width='12'] {
min-width: 100%;
}
.grid-stack > .grid-stack-item[data-gs-max-width='12'] {
max-width: 100%;
}
.grid-stack.grid-stack-animate, .grid-stack.grid-stack-animate .grid-stack-item {
.grid-stack.grid-stack-animate,
.grid-stack.grid-stack-animate .grid-stack-item {
-webkit-transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
-moz-transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
-ms-transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
-o-transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
}
.grid-stack.grid-stack-animate .grid-stack-item.ui-draggable-dragging, .grid-stack.grid-stack-animate .grid-stack-item.ui-resizable-resizing, .grid-stack.grid-stack-animate .grid-stack-item.grid-stack-placeholder {
.grid-stack.grid-stack-animate .grid-stack-item.ui-draggable-dragging,
.grid-stack.grid-stack-animate .grid-stack-item.ui-resizable-resizing,
.grid-stack.grid-stack-animate .grid-stack-item.grid-stack-placeholder {
-webkit-transition: left 0s, top 0s, height 0s, width 0s;
-moz-transition: left 0s, top 0s, height 0s, width 0s;
-ms-transition: left 0s, top 0s, height 0s, width 0s;
@ -296,7 +368,6 @@
/*
.grid-stack > .grid-stack-item > .ui-resizable-sw {
display: inline-block;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
@include vendor(transform, rotate(180deg));
}
*/
@ -311,7 +382,6 @@
.grid-stack-item .ui-resizable-handle {
display: none;
}
.grid-stack {
height: auto !important;
}

472
dist/gridstack.js vendored Normal file → Executable file
View file

@ -1,54 +1,62 @@
// gridstack.js 0.2.3-dev
// gridstack.js 0.2.4-dev
// http://troolee.github.io/gridstack.js/
// (c) 2014-2015 Pavel Reznikov
// (c) 2014-2016 Pavel Reznikov
// gridstack.js may be freely distributed under the MIT license.
(function (factory) {
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery', 'lodash'], factory);
define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable',
'jquery-ui/resizable'], factory);
}
else if (typeof exports !== 'undefined') {
try { jQuery = require('jquery'); } catch(e) {}
try { _ = require('lodash'); } catch(e) {}
factory(jQuery, _);
}
else {
factory(jQuery, _);
}
})(function ($, _) {
})(function($, _) {
var scope = window;
var Utils = {
is_intercepted: function (a, b) {
is_intercepted: function(a, b) {
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
},
sort: function (nodes, dir, width) {
width = width || _.chain(nodes).map(function (node) { return node.x + node.width; }).max().value();
sort: function(nodes, dir, width) {
width = width || _.chain(nodes).map(function(node) { return node.x + node.width; }).max().value();
dir = dir != -1 ? 1 : -1;
return _.sortBy(nodes, function (n) { return dir * (n.x + n.y * width); });
return _.sortBy(nodes, function(n) { return dir * (n.x + n.y * width); });
},
create_stylesheet: function (id) {
var style = document.createElement("style");
style.setAttribute("type", "text/css");
style.setAttribute("data-gs-id", id);
create_stylesheet: function(id) {
var style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.setAttribute('data-gs-id', id);
if (style.styleSheet) {
style.styleSheet.cssText = "";
style.styleSheet.cssText = '';
}
else {
style.appendChild(document.createTextNode(""));
style.appendChild(document.createTextNode(''));
}
document.getElementsByTagName('head')[0].appendChild(style);
return style.sheet;
},
insert_css_rule: function (sheet, selector, rules, index) {
if(typeof sheet.insertRule === 'function') {
sheet.insertRule(selector + "{" + rules + "}", index);
remove_stylesheet: function(id) {
$("STYLE[data-gs-id=" + id +"]").remove();
},
insert_css_rule: function(sheet, selector, rules, index) {
if (typeof sheet.insertRule === 'function') {
sheet.insertRule(selector + '{' + rules + '}', index);
}
else if(typeof sheet.addRule === 'function') {
else if (typeof sheet.addRule === 'function') {
sheet.addRule(selector, rules, index);
}
},
toBool: function (v) {
toBool: function(v) {
if (typeof v == 'boolean')
return v;
if (typeof v == 'string') {
@ -61,24 +69,24 @@
var id_seq = 0;
var GridStackEngine = function (width, onchange, float, height, items) {
var GridStackEngine = function(width, onchange, float_mode, height, items) {
this.width = width;
this.float = float || false;
this['float'] = float_mode || false;
this.height = height || 0;
this.nodes = items || [];
this.onchange = onchange || function () {};
this.onchange = onchange || function() {};
this._update_counter = 0;
this._float = this.float;
this._float = this['float'];
};
GridStackEngine.prototype.batch_update = function () {
GridStackEngine.prototype.batch_update = function() {
this._update_counter = 1;
this.float = true;
};
GridStackEngine.prototype.commit = function () {
GridStackEngine.prototype.commit = function() {
this._update_counter = 0;
if (this._update_counter == 0) {
this.float = this._float;
@ -87,18 +95,18 @@
}
};
GridStackEngine.prototype._fix_collisions = function (node) {
GridStackEngine.prototype._fix_collisions = function(node) {
this._sort_nodes(-1);
var nn = node, has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
var nn = node, has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked }));
if (!this.float && !has_locked) {
nn = {x: 0, y: node.y, width: this.width, height: node.height};
}
while (true) {
var collision_node = _.find(this.nodes, function (n) {
var collision_node = _.find(this.nodes, _.bind(function(n) {
return n != node && Utils.is_intercepted(n, nn);
}, this);
}, this));
if (typeof collision_node == 'undefined') {
return;
}
@ -107,31 +115,32 @@
}
};
GridStackEngine.prototype.is_area_empty = function (x, y, width, height) {
GridStackEngine.prototype.is_area_empty = function(x, y, width, height) {
var nn = {x: x || 0, y: y || 0, width: width || 1, height: height || 1};
var collision_node = _.find(this.nodes, function (n) {
var collision_node = _.find(this.nodes, _.bind(function(n) {
return Utils.is_intercepted(n, nn);
}, this);
}, this));
return collision_node == null;
};
GridStackEngine.prototype._sort_nodes = function (dir) {
GridStackEngine.prototype._sort_nodes = function(dir) {
this.nodes = Utils.sort(this.nodes, dir, this.width);
};
GridStackEngine.prototype._pack_nodes = function () {
GridStackEngine.prototype._pack_nodes = function() {
this._sort_nodes();
if (this.float) {
_.each(this.nodes, function (n, i) {
_.each(this.nodes, _.bind(function(n, i) {
if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y)
return;
var new_y = n.y;
while (new_y >= n._orig_y) {
var collision_node = _.chain(this.nodes)
.find(function (bn) {
return n != bn && Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
.find(function(bn) {
return n != bn &&
Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
})
.value();
@ -141,10 +150,10 @@
}
--new_y;
}
}, this);
}, this));
}
else {
_.each(this.nodes, function (n, i) {
_.each(this.nodes, _.bind(function(n, i) {
if (n.locked)
return;
while (n.y > 0) {
@ -154,7 +163,7 @@
if (i > 0) {
var collision_node = _.chain(this.nodes)
.take(i)
.find(function (bn) {
.find(function(bn) {
return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
})
.value();
@ -167,11 +176,11 @@
n._dirty = n.y != new_y;
n.y = new_y;
}
}, this);
}, this));
}
};
GridStackEngine.prototype._prepare_node = function (node, resizing) {
GridStackEngine.prototype._prepare_node = function(node, resizing) {
node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 });
node.x = parseInt('' + node.x);
@ -213,7 +222,7 @@
return node;
};
GridStackEngine.prototype._notify = function () {
GridStackEngine.prototype._notify = function() {
if (this._update_counter) {
return;
}
@ -222,12 +231,12 @@
this.onchange(deleted_nodes);
};
GridStackEngine.prototype.clean_nodes = function () {
_.each(this.nodes, function (n) {n._dirty = false });
GridStackEngine.prototype.clean_nodes = function() {
_.each(this.nodes, function(n) {n._dirty = false });
};
GridStackEngine.prototype.get_dirty_nodes = function () {
return _.filter(this.nodes, function (n) { return n._dirty; });
GridStackEngine.prototype.get_dirty_nodes = function() {
return _.filter(this.nodes, function(n) { return n._dirty; });
};
GridStackEngine.prototype.add_node = function(node) {
@ -244,12 +253,12 @@
if (node.auto_position) {
this._sort_nodes();
for (var i = 0; ; ++i) {
for (var i = 0;; ++i) {
var x = i % this.width, y = Math.floor(i / this.width);
if (x + node.width > this.width) {
continue;
}
if (!_.find(this.nodes, function (n) {
if (!_.find(this.nodes, function(n) {
return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n);
})) {
node.x = x;
@ -267,15 +276,15 @@
return node;
};
GridStackEngine.prototype.remove_node = function (node) {
GridStackEngine.prototype.remove_node = function(node) {
node._id = null;
this.nodes = _.without(this.nodes, node);
this._pack_nodes();
this._notify(node);
};
GridStackEngine.prototype.can_move_node = function (node, x, y, width, height) {
var has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
GridStackEngine.prototype.can_move_node = function(node, x, y, width, height) {
var has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked }));
if (!this.height && !has_locked)
return true;
@ -286,21 +295,29 @@
null,
this.float,
0,
_.map(this.nodes, function (n) { if (n == node) { cloned_node = $.extend({}, n); return cloned_node; } return $.extend({}, n) }));
_.map(this.nodes, function(n) {
if (n == node) {
cloned_node = $.extend({}, n);
return cloned_node;
}
return $.extend({}, n);
}));
clone.move_node(cloned_node, x, y, width, height);
var res = true;
if (has_locked)
res &= !Boolean(_.find(clone.nodes, function (n) { return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty); }));
res &= !Boolean(_.find(clone.nodes, function(n) {
return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty);
}));
if (this.height)
res &= clone.get_grid_height() <= this.height;
return res;
};
GridStackEngine.prototype.can_be_placed_with_respect_to_height = function (node) {
GridStackEngine.prototype.can_be_placed_with_respect_to_height = function(node) {
if (!this.height)
return true;
@ -309,12 +326,12 @@
null,
this.float,
0,
_.map(this.nodes, function (n) { return $.extend({}, n) }));
_.map(this.nodes, function(n) { return $.extend({}, n) }));
clone.add_node(node);
return clone.get_grid_height() <= this.height;
};
GridStackEngine.prototype.move_node = function (node, x, y, width, height, no_pack) {
GridStackEngine.prototype.move_node = function(node, x, y, width, height, no_pack) {
if (typeof x != 'number') x = node.x;
if (typeof y != 'number') y = node.y;
if (typeof width != 'number') width = node.width;
@ -347,30 +364,32 @@
return node;
};
GridStackEngine.prototype.get_grid_height = function () {
return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0);
GridStackEngine.prototype.get_grid_height = function() {
return _.reduce(this.nodes, function(memo, n) { return Math.max(memo, n.y + n.height); }, 0);
};
GridStackEngine.prototype.begin_update = function (node) {
_.each(this.nodes, function (n) {
GridStackEngine.prototype.begin_update = function(node) {
_.each(this.nodes, function(n) {
n._orig_y = n.y;
});
node._updating = true;
};
GridStackEngine.prototype.end_update = function () {
_.each(this.nodes, function (n) {
GridStackEngine.prototype.end_update = function() {
_.each(this.nodes, function(n) {
n._orig_y = n.y;
});
var n = _.find(this.nodes, function (n) { return n._updating; });
var n = _.find(this.nodes, function(n) { return n._updating; });
if (n) {
n._updating = false;
}
};
var GridStack = function (el, opts) {
var GridStack = function(el, opts) {
var self = this, one_column_mode;
opts = opts || {};
this.container = $(el);
opts.item_class = opts.item_class || 'grid-stack-item';
@ -381,13 +400,16 @@
height: parseInt(this.container.attr('data-gs-height')) || 0,
item_class: 'grid-stack-item',
placeholder_class: 'grid-stack-placeholder',
placeholder_text: '',
handle: '.grid-stack-item-content',
handle_class: null,
cell_height: 60,
vertical_margin: 20,
auto: true,
min_width: 768,
float: false,
_class: 'grid-stack-' + (Math.random() * 10000).toFixed(0),
static_grid: false,
_class: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0),
animate: Boolean(this.container.attr('data-gs-animate')) || false,
always_show_resize_handle: opts.always_show_resize_handle || false,
resizable: _.defaults(opts.resizable || {}, {
@ -395,7 +417,7 @@
handles: 'se'
}),
draggable: _.defaults(opts.draggable || {}, {
handle: '.grid-stack-item-content',
handle: (opts.handle_class ? '.' + opts.handle_class : (opts.handle ? opts.handle : '')) || '.grid-stack-item-content',
scroll: false,
appendTo: 'body'
})
@ -403,15 +425,18 @@
this.opts.is_nested = is_nested;
this.container.addClass(this.opts._class);
this._set_static_class();
if (is_nested) {
this.container.addClass('grid-stack-nested');
}
this._init_styles();
this.grid = new GridStackEngine(this.opts.width, function (nodes) {
this.grid = new GridStackEngine(this.opts.width, function(nodes) {
var max_height = 0;
_.each(nodes, function (n) {
_.each(nodes, function(n) {
if (n._id == null) {
n.el.remove();
}
@ -430,25 +455,29 @@
if (this.opts.auto) {
var elements = [];
var _this = this;
this.container.children('.' + this.opts.item_class).each(function (index, el) {
this.container.children('.' + this.opts.item_class + ':not(.' + this.opts.placeholder_class + ')').each(function(index, el) {
el = $(el);
elements.push({
el: el,
i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width // Use opts.width as weight for Y
i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width
});
});
_.chain(elements).sortBy(function (x) { return x.i; }).each(function (i) {
_.chain(elements).sortBy(function(x) { return x.i; }).each(function(i) {
self._prepare_element(i.el);
}).value();
}
this.set_animation(this.opts.animate);
this.placeholder = $('<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '"><div class="placeholder-content" /></div>').hide();
this.container.append(this.placeholder);
this.container.height((this.grid.get_grid_height()) * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
this.placeholder = $(
'<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '">' +
'<div class="placeholder-content">' + this.opts.placeholder_text + '</div></div>').hide();
var on_resize_handler = function () {
this.container.height(
this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) -
this.opts.vertical_margin);
this.on_resize_handler = function() {
if (self._is_one_column_mode()) {
if (one_column_mode)
return;
@ -456,9 +485,12 @@
one_column_mode = true;
self.grid._sort_nodes();
_.each(self.grid.nodes, function (node) {
_.each(self.grid.nodes, function(node) {
self.container.append(node.el);
if (self.opts.static_grid) {
return;
}
if (!node.no_move) {
node.el.draggable('disable');
}
@ -473,7 +505,11 @@
one_column_mode = false;
_.each(self.grid.nodes, function (node) {
if (self.opts.static_grid) {
return;
}
_.each(self.grid.nodes, function(node) {
if (!node.no_move) {
node.el.draggable('enable');
}
@ -484,11 +520,26 @@
}
};
$(window).resize(on_resize_handler);
on_resize_handler();
$(window).resize(this.on_resize_handler);
this.on_resize_handler();
};
GridStack.prototype._init_styles = function () {
GridStack.prototype._trigger_change_event = function(forceTrigger) {
var elements = this.grid.get_dirty_nodes();
var hasChanges = false;
var eventParams = [];
if (elements && elements.length) {
eventParams.push(elements);
hasChanges = true;
}
if (hasChanges || forceTrigger === true) {
this.container.trigger('change', eventParams);
}
};
GridStack.prototype._init_styles = function() {
if (this._styles_id) {
$('[data-gs-id="' + this._styles_id + '"]').remove();
}
@ -498,7 +549,7 @@
this._styles._max = 0;
};
GridStack.prototype._update_styles = function (max_height) {
GridStack.prototype._update_styles = function(max_height) {
if (this._styles == null) {
return;
}
@ -542,18 +593,21 @@
}
};
GridStack.prototype._update_container_height = function () {
GridStack.prototype._update_container_height = function() {
if (this.grid._update_counter) {
return;
}
this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
this.container.height(
this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) -
this.opts.vertical_margin);
};
GridStack.prototype._is_one_column_mode = function () {
return $(window).width() <= this.opts.min_width;
GridStack.prototype._is_one_column_mode = function() {
return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <=
this.opts.min_width;
};
GridStack.prototype._prepare_element = function (el) {
GridStack.prototype._prepare_element = function(el) {
var self = this;
el = $(el);
@ -576,13 +630,34 @@
});
el.data('_gridstack_node', node);
if (self.opts.static_grid) {
return;
}
var cell_width, cell_height;
var on_start_moving = function (event, ui) {
var drag_or_resize = function(event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height / 2) / cell_height),
width, height;
if (event.type != "drag") {
width = Math.round(ui.size.width / cell_width);
height = Math.round(ui.size.height / cell_height);
}
if (!self.grid.can_move_node(node, x, y, width, height)) {
return;
}
self.grid.move_node(node, x, y, width, height);
self._update_container_height();
};
var on_start_moving = function(event, ui) {
self.container.append(self.placeholder);
var o = $(this);
self.grid.clean_nodes();
self.grid.begin_update(node);
cell_width = Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
cell_width = o.outerWidth() / o.attr('data-gs-width');
cell_height = self.opts.cell_height + self.opts.vertical_margin;
self.placeholder
.attr('data-gs-x', o.attr('data-gs-x'))
@ -592,11 +667,16 @@
.show();
node.el = self.placeholder;
el.resizable('option', 'minWidth', cell_width * (node.min_width || 1));
el.resizable('option', 'minWidth', Math.round(cell_width * (node.min_width || 1)));
el.resizable('option', 'minHeight', self.opts.cell_height * (node.min_height || 1));
if (event.type == 'resizestart') {
o.find('.grid-stack-item').trigger('resizestart');
}
};
var on_end_moving = function (event, ui) {
var on_end_moving = function(event, ui) {
self.placeholder.detach();
var o = $(this);
node.el = o;
self.placeholder.hide();
@ -607,39 +687,30 @@
.attr('data-gs-height', node.height)
.removeAttr('style');
self._update_container_height();
self.container.trigger('change', [self.grid.get_dirty_nodes()]);
self._trigger_change_event();
self.grid.end_update();
var nested_grids = o.find('.grid-stack');
if (nested_grids.length && event.type == 'resizestop') {
nested_grids.each(function(index, el) {
$(el).data('gridstack').on_resize_handler();
});
o.find('.grid-stack-item').trigger('resizestop');
}
};
el.draggable(_.extend(this.opts.draggable, {
start: on_start_moving,
stop: on_end_moving,
drag: function (event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height/2) / cell_height);
if (!self.grid.can_move_node(node, x, y, node.width, node.height)) {
return;
}
self.grid.move_node(node, x, y);
self._update_container_height();
},
containment: this.opts.is_nested ? this.container.parent() : null
})).resizable(_.extend(this.opts.resizable, {
start: on_start_moving,
stop: on_end_moving,
resize: function (event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height/2) / cell_height),
width = Math.round(ui.size.width / cell_width),
height = Math.round(ui.size.height / cell_height);
if (!self.grid.can_move_node(node, x, y, width, height)) {
return;
}
self.grid.move_node(node, x, y, width, height);
self._update_container_height();
}
}));
el
.draggable(_.extend(this.opts.draggable, {
containment: this.opts.is_nested ? this.container.parent() : null
}))
.on('dragstart', on_start_moving)
.on('dragstop', on_end_moving)
.on('drag', drag_or_resize)
.resizable(_.extend(this.opts.resizable, {}))
.on('resizestart', on_start_moving)
.on('resizestop', on_end_moving)
.on('resize', drag_or_resize);
if (node.no_move || this._is_one_column_mode()) {
el.draggable('disable');
@ -652,7 +723,7 @@
el.attr('data-gs-locked', node.locked ? 'yes' : null);
};
GridStack.prototype.set_animation = function (enable) {
GridStack.prototype.set_animation = function(enable) {
if (enable) {
this.container.addClass('grid-stack-animate');
}
@ -661,7 +732,7 @@
}
};
GridStack.prototype.add_widget = function (el, x, y, width, height, auto_position) {
GridStack.prototype.add_widget = function(el, x, y, width, height, auto_position) {
el = $(el);
if (typeof x != 'undefined') el.attr('data-gs-x', x);
if (typeof y != 'undefined') el.attr('data-gs-y', y);
@ -671,16 +742,26 @@
this.container.append(el);
this._prepare_element(el);
this._update_container_height();
this._trigger_change_event(true);
return el;
};
GridStack.prototype.will_it_fit = function (x, y, width, height, auto_position) {
GridStack.prototype.make_widget = function(el) {
el = $(el);
this._prepare_element(el);
this._update_container_height();
this._trigger_change_event(true);
return el;
};
GridStack.prototype.will_it_fit = function(x, y, width, height, auto_position) {
var node = {x: x, y: y, width: width, height: height, auto_position: auto_position};
return this.grid.can_be_placed_with_respect_to_height(node);
};
GridStack.prototype.remove_widget = function (el, detach_node) {
GridStack.prototype.remove_widget = function(el, detach_node) {
detach_node = typeof detach_node === 'undefined' ? true : detach_node;
el = $(el);
var node = el.data('_gridstack_node');
@ -689,19 +770,30 @@
this._update_container_height();
if (detach_node)
el.remove();
this._trigger_change_event(true);
};
GridStack.prototype.remove_all = function (detach_node) {
_.each(this.grid.nodes, function (node) {
GridStack.prototype.remove_all = function(detach_node) {
_.each(this.grid.nodes, _.bind(function(node) {
this.remove_widget(node.el, detach_node);
}, this);
}, this));
this.grid.nodes = [];
this._update_container_height();
};
GridStack.prototype.resizable = function (el, val) {
GridStack.prototype.destroy = function() {
$(window).off("resize", this.on_resize_handler);
this.disable();
this.container.remove();
Utils.remove_stylesheet(this._styles_id);
if (this.grid)
this.grid = null;
};
GridStack.prototype.resizable = function(el, val) {
var self = this;
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -709,7 +801,7 @@
}
node.no_resize = !(val || false);
if (node.no_resize) {
if (node.no_resize || self._is_one_column_mode()) {
el.resizable('disable');
}
else {
@ -719,9 +811,10 @@
return this;
};
GridStack.prototype.movable = function (el, val) {
GridStack.prototype.movable = function(el, val) {
var self = this;
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -729,29 +822,33 @@
}
node.no_move = !(val || false);
if (node.no_move) {
if (node.no_move || self._is_one_column_mode()) {
el.draggable('disable');
el.removeClass('ui-draggable-handle');
}
else {
el.draggable('enable');
el.addClass('ui-draggable-handle');
}
});
return this;
};
GridStack.prototype.disable = function () {
GridStack.prototype.disable = function() {
this.movable(this.container.children('.' + this.opts.item_class), false);
this.resizable(this.container.children('.' + this.opts.item_class), false);
this.container.trigger('disable');
};
GridStack.prototype.enable = function () {
GridStack.prototype.enable = function() {
this.movable(this.container.children('.' + this.opts.item_class), true);
this.resizable(this.container.children('.' + this.opts.item_class), true);
this.container.trigger('enable');
};
GridStack.prototype.locked = function (el, val) {
GridStack.prototype.locked = function(el, val) {
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -764,7 +861,41 @@
return this;
};
GridStack.prototype._update_element = function (el, callback) {
GridStack.prototype.min_height = function (el, val) {
el = $(el);
el.each(function (index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
return;
}
if(!isNaN(val)){
node.min_height = (val || false);
el.attr('data-gs-min-height', val);
}
});
return this;
};
GridStack.prototype.min_width = function (el, val) {
el = $(el);
el.each(function (index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
return;
}
if(!isNaN(val)){
node.min_width = (val || false);
el.attr('data-gs-min-width', val);
}
});
return this;
};
GridStack.prototype._update_element = function(el, callback) {
el = $(el).first();
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -779,13 +910,13 @@
callback.call(this, el, node);
self._update_container_height();
self.container.trigger('change', [self.grid.get_dirty_nodes()]);
self._trigger_change_event();
self.grid.end_update();
};
GridStack.prototype.resize = function (el, width, height) {
this._update_element(el, function (el, node) {
GridStack.prototype.resize = function(el, width, height) {
this._update_element(el, function(el, node) {
width = (width != null && typeof width != 'undefined') ? width : node.width;
height = (height != null && typeof height != 'undefined') ? height : node.height;
@ -793,8 +924,8 @@
});
};
GridStack.prototype.move = function (el, x, y) {
this._update_element(el, function (el, node) {
GridStack.prototype.move = function(el, x, y) {
this._update_element(el, function(el, node) {
x = (x != null && typeof x != 'undefined') ? x : node.x;
y = (y != null && typeof y != 'undefined') ? y : node.y;
@ -802,8 +933,8 @@
});
};
GridStack.prototype.update = function (el, x, y, width, height) {
this._update_element(el, function (el, node) {
GridStack.prototype.update = function(el, x, y, width, height) {
this._update_element(el, function(el, node) {
x = (x != null && typeof x != 'undefined') ? x : node.x;
y = (y != null && typeof y != 'undefined') ? y : node.y;
width = (width != null && typeof width != 'undefined') ? width : node.width;
@ -813,7 +944,7 @@
});
};
GridStack.prototype.cell_height = function (val) {
GridStack.prototype.cell_height = function(val) {
if (typeof val == 'undefined') {
return this.opts.cell_height;
}
@ -824,7 +955,7 @@
this._update_styles();
};
GridStack.prototype.cell_width = function () {
GridStack.prototype.cell_width = function() {
var o = this.container.children('.' + this.opts.item_class).first();
return Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
};
@ -840,27 +971,54 @@
return {x: Math.floor(relativeLeft / column_width), y: Math.floor(relativeTop / row_height)};
};
GridStack.prototype.batch_update = function () {
GridStack.prototype.batch_update = function() {
this.grid.batch_update();
};
GridStack.prototype.commit = function () {
GridStack.prototype.commit = function() {
this.grid.commit();
this._update_container_height()
this._update_container_height();
};
GridStack.prototype.is_area_empty = function (x, y, width, height) {
GridStack.prototype.is_area_empty = function(x, y, width, height) {
return this.grid.is_area_empty(x, y, width, height);
};
GridStack.prototype.set_static = function(static_value) {
this.opts.static_grid = (static_value === true);
this._set_static_class();
};
GridStack.prototype._set_static_class = function() {
var static_class_name = 'grid-stack-static';
if (this.opts.static_grid === true) {
this.container.addClass(static_class_name);
} else {
this.container.removeClass(static_class_name);
}
};
scope.GridStackUI = GridStack;
scope.GridStackUI.Utils = Utils;
$.fn.gridstack = function (opts) {
return this.each(function () {
if (!$(this).data('gridstack')) {
$(this).data('gridstack', new GridStack(this, opts));
function event_stop_propagate(event) {
event.stopPropagation();
}
$.fn.gridstack = function(opts) {
return this.each(function() {
var o = $(this);
if (!o.data('gridstack')) {
o
.data('gridstack', new GridStack(this, opts))
.on('dragstart', event_stop_propagate)
.on('dragstop', event_stop_propagate)
.on('drag', event_stop_propagate)
.on('resizestart', event_stop_propagate)
.on('resizestop', event_stop_propagate)
.on('resize', event_stop_propagate)
.on('change', event_stop_propagate);
}
});
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

30
package.json Executable file
View file

@ -0,0 +1,30 @@
{
"name": "gridstack",
"version": "0.2.3",
"description": "gridstack.js is a jQuery plugin for widget layout",
"main": "dist/gridstack.js",
"repository": {
"type": "git",
"url": "git+https://github.com/troolee/gridstack.js.git"
},
"keywords": [
"gridstack",
"grid",
"gridster",
"layout",
"jquery"
],
"author": "Pavel Reznikov <pashka.reznikov@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/troolee/gridstack.js/issues"
},
"homepage": "http://troolee.github.io/gridstack.js/",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-copy": "^0.8.2",
"grunt-contrib-cssmin": "^0.14.0",
"grunt-contrib-uglify": "^0.10.1",
"grunt-sass": "^1.1.0"
}
}

21
src/gridstack-extra.scss Normal file
View file

@ -0,0 +1,21 @@
$gridstack-columns: 12 !default;
@mixin grid-stack-items($gridstack-columns) {
.grid-stack.grid-stack-#{$gridstack-columns} {
> .grid-stack-item {
min-width: 100% / $gridstack-columns;
@for $i from 1 through $gridstack-columns {
&[data-gs-width='#{$i}'] { width: (100% / $gridstack-columns) * $i; }
&[data-gs-x='#{$i}'] { left: (100% / $gridstack-columns) * $i; }
&[data-gs-min-width='#{$i}'] { min-width: (100% / $gridstack-columns) * $i; }
&[data-gs-max-width='#{$i}'] { max-width: (100% / $gridstack-columns) * $i; }
}
}
}
}
@for $j from 1 through $gridstack-columns {
@include grid-stack-items($j)
}

View file

@ -1,54 +1,62 @@
// gridstack.js 0.2.3-dev
// gridstack.js 0.2.4-dev
// http://troolee.github.io/gridstack.js/
// (c) 2014-2015 Pavel Reznikov
// (c) 2014-2016 Pavel Reznikov
// gridstack.js may be freely distributed under the MIT license.
(function (factory) {
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable', 'jquery-ui/resizable'], factory);
define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable',
'jquery-ui/resizable'], factory);
}
else if (typeof exports !== 'undefined') {
try { jQuery = require('jquery'); } catch(e) {}
try { _ = require('lodash'); } catch(e) {}
factory(jQuery, _);
}
else {
factory(jQuery, _);
}
})(function ($, _) {
})(function($, _) {
var scope = window;
var Utils = {
is_intercepted: function (a, b) {
is_intercepted: function(a, b) {
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
},
sort: function (nodes, dir, width) {
width = width || _.chain(nodes).map(function (node) { return node.x + node.width; }).max().value();
sort: function(nodes, dir, width) {
width = width || _.chain(nodes).map(function(node) { return node.x + node.width; }).max().value();
dir = dir != -1 ? 1 : -1;
return _.sortBy(nodes, function (n) { return dir * (n.x + n.y * width); });
return _.sortBy(nodes, function(n) { return dir * (n.x + n.y * width); });
},
create_stylesheet: function (id) {
var style = document.createElement("style");
style.setAttribute("type", "text/css");
style.setAttribute("data-gs-id", id);
create_stylesheet: function(id) {
var style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.setAttribute('data-gs-id', id);
if (style.styleSheet) {
style.styleSheet.cssText = "";
style.styleSheet.cssText = '';
}
else {
style.appendChild(document.createTextNode(""));
style.appendChild(document.createTextNode(''));
}
document.getElementsByTagName('head')[0].appendChild(style);
return style.sheet;
},
insert_css_rule: function (sheet, selector, rules, index) {
if(typeof sheet.insertRule === 'function') {
sheet.insertRule(selector + "{" + rules + "}", index);
remove_stylesheet: function(id) {
$("STYLE[data-gs-id=" + id +"]").remove();
},
insert_css_rule: function(sheet, selector, rules, index) {
if (typeof sheet.insertRule === 'function') {
sheet.insertRule(selector + '{' + rules + '}', index);
}
else if(typeof sheet.addRule === 'function') {
else if (typeof sheet.addRule === 'function') {
sheet.addRule(selector, rules, index);
}
},
toBool: function (v) {
toBool: function(v) {
if (typeof v == 'boolean')
return v;
if (typeof v == 'string') {
@ -61,24 +69,24 @@
var id_seq = 0;
var GridStackEngine = function (width, onchange, float, height, items) {
var GridStackEngine = function(width, onchange, float_mode, height, items) {
this.width = width;
this.float = float || false;
this['float'] = float_mode || false;
this.height = height || 0;
this.nodes = items || [];
this.onchange = onchange || function () {};
this.onchange = onchange || function() {};
this._update_counter = 0;
this._float = this.float;
this._float = this['float'];
};
GridStackEngine.prototype.batch_update = function () {
GridStackEngine.prototype.batch_update = function() {
this._update_counter = 1;
this.float = true;
};
GridStackEngine.prototype.commit = function () {
GridStackEngine.prototype.commit = function() {
this._update_counter = 0;
if (this._update_counter == 0) {
this.float = this._float;
@ -87,18 +95,18 @@
}
};
GridStackEngine.prototype._fix_collisions = function (node) {
GridStackEngine.prototype._fix_collisions = function(node) {
this._sort_nodes(-1);
var nn = node, has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
var nn = node, has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked }));
if (!this.float && !has_locked) {
nn = {x: 0, y: node.y, width: this.width, height: node.height};
}
while (true) {
var collision_node = _.find(this.nodes, function (n) {
var collision_node = _.find(this.nodes, _.bind(function(n) {
return n != node && Utils.is_intercepted(n, nn);
}, this);
}, this));
if (typeof collision_node == 'undefined') {
return;
}
@ -107,31 +115,32 @@
}
};
GridStackEngine.prototype.is_area_empty = function (x, y, width, height) {
GridStackEngine.prototype.is_area_empty = function(x, y, width, height) {
var nn = {x: x || 0, y: y || 0, width: width || 1, height: height || 1};
var collision_node = _.find(this.nodes, function (n) {
var collision_node = _.find(this.nodes, _.bind(function(n) {
return Utils.is_intercepted(n, nn);
}, this);
}, this));
return collision_node == null;
};
GridStackEngine.prototype._sort_nodes = function (dir) {
GridStackEngine.prototype._sort_nodes = function(dir) {
this.nodes = Utils.sort(this.nodes, dir, this.width);
};
GridStackEngine.prototype._pack_nodes = function () {
GridStackEngine.prototype._pack_nodes = function() {
this._sort_nodes();
if (this.float) {
_.each(this.nodes, function (n, i) {
_.each(this.nodes, _.bind(function(n, i) {
if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y)
return;
var new_y = n.y;
while (new_y >= n._orig_y) {
var collision_node = _.chain(this.nodes)
.find(function (bn) {
return n != bn && Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
.find(function(bn) {
return n != bn &&
Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
})
.value();
@ -141,10 +150,10 @@
}
--new_y;
}
}, this);
}, this));
}
else {
_.each(this.nodes, function (n, i) {
_.each(this.nodes, _.bind(function(n, i) {
if (n.locked)
return;
while (n.y > 0) {
@ -154,7 +163,7 @@
if (i > 0) {
var collision_node = _.chain(this.nodes)
.take(i)
.find(function (bn) {
.find(function(bn) {
return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
})
.value();
@ -167,11 +176,11 @@
n._dirty = n.y != new_y;
n.y = new_y;
}
}, this);
}, this));
}
};
GridStackEngine.prototype._prepare_node = function (node, resizing) {
GridStackEngine.prototype._prepare_node = function(node, resizing) {
node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 });
node.x = parseInt('' + node.x);
@ -213,7 +222,7 @@
return node;
};
GridStackEngine.prototype._notify = function () {
GridStackEngine.prototype._notify = function() {
if (this._update_counter) {
return;
}
@ -222,12 +231,12 @@
this.onchange(deleted_nodes);
};
GridStackEngine.prototype.clean_nodes = function () {
_.each(this.nodes, function (n) {n._dirty = false });
GridStackEngine.prototype.clean_nodes = function() {
_.each(this.nodes, function(n) {n._dirty = false });
};
GridStackEngine.prototype.get_dirty_nodes = function () {
return _.filter(this.nodes, function (n) { return n._dirty; });
GridStackEngine.prototype.get_dirty_nodes = function() {
return _.filter(this.nodes, function(n) { return n._dirty; });
};
GridStackEngine.prototype.add_node = function(node) {
@ -244,12 +253,12 @@
if (node.auto_position) {
this._sort_nodes();
for (var i = 0; ; ++i) {
for (var i = 0;; ++i) {
var x = i % this.width, y = Math.floor(i / this.width);
if (x + node.width > this.width) {
continue;
}
if (!_.find(this.nodes, function (n) {
if (!_.find(this.nodes, function(n) {
return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n);
})) {
node.x = x;
@ -267,15 +276,15 @@
return node;
};
GridStackEngine.prototype.remove_node = function (node) {
GridStackEngine.prototype.remove_node = function(node) {
node._id = null;
this.nodes = _.without(this.nodes, node);
this._pack_nodes();
this._notify(node);
};
GridStackEngine.prototype.can_move_node = function (node, x, y, width, height) {
var has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
GridStackEngine.prototype.can_move_node = function(node, x, y, width, height) {
var has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked }));
if (!this.height && !has_locked)
return true;
@ -286,21 +295,29 @@
null,
this.float,
0,
_.map(this.nodes, function (n) { if (n == node) { cloned_node = $.extend({}, n); return cloned_node; } return $.extend({}, n) }));
_.map(this.nodes, function(n) {
if (n == node) {
cloned_node = $.extend({}, n);
return cloned_node;
}
return $.extend({}, n);
}));
clone.move_node(cloned_node, x, y, width, height);
var res = true;
if (has_locked)
res &= !Boolean(_.find(clone.nodes, function (n) { return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty); }));
res &= !Boolean(_.find(clone.nodes, function(n) {
return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty);
}));
if (this.height)
res &= clone.get_grid_height() <= this.height;
return res;
};
GridStackEngine.prototype.can_be_placed_with_respect_to_height = function (node) {
GridStackEngine.prototype.can_be_placed_with_respect_to_height = function(node) {
if (!this.height)
return true;
@ -309,12 +326,12 @@
null,
this.float,
0,
_.map(this.nodes, function (n) { return $.extend({}, n) }));
_.map(this.nodes, function(n) { return $.extend({}, n) }));
clone.add_node(node);
return clone.get_grid_height() <= this.height;
};
GridStackEngine.prototype.move_node = function (node, x, y, width, height, no_pack) {
GridStackEngine.prototype.move_node = function(node, x, y, width, height, no_pack) {
if (typeof x != 'number') x = node.x;
if (typeof y != 'number') y = node.y;
if (typeof width != 'number') width = node.width;
@ -347,30 +364,32 @@
return node;
};
GridStackEngine.prototype.get_grid_height = function () {
return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0);
GridStackEngine.prototype.get_grid_height = function() {
return _.reduce(this.nodes, function(memo, n) { return Math.max(memo, n.y + n.height); }, 0);
};
GridStackEngine.prototype.begin_update = function (node) {
_.each(this.nodes, function (n) {
GridStackEngine.prototype.begin_update = function(node) {
_.each(this.nodes, function(n) {
n._orig_y = n.y;
});
node._updating = true;
};
GridStackEngine.prototype.end_update = function () {
_.each(this.nodes, function (n) {
GridStackEngine.prototype.end_update = function() {
_.each(this.nodes, function(n) {
n._orig_y = n.y;
});
var n = _.find(this.nodes, function (n) { return n._updating; });
var n = _.find(this.nodes, function(n) { return n._updating; });
if (n) {
n._updating = false;
}
};
var GridStack = function (el, opts) {
var GridStack = function(el, opts) {
var self = this, one_column_mode;
opts = opts || {};
this.container = $(el);
opts.item_class = opts.item_class || 'grid-stack-item';
@ -381,13 +400,16 @@
height: parseInt(this.container.attr('data-gs-height')) || 0,
item_class: 'grid-stack-item',
placeholder_class: 'grid-stack-placeholder',
placeholder_text: '',
handle: '.grid-stack-item-content',
handle_class: null,
cell_height: 60,
vertical_margin: 20,
auto: true,
min_width: 768,
float: false,
_class: 'grid-stack-' + (Math.random() * 10000).toFixed(0),
static_grid: false,
_class: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0),
animate: Boolean(this.container.attr('data-gs-animate')) || false,
always_show_resize_handle: opts.always_show_resize_handle || false,
resizable: _.defaults(opts.resizable || {}, {
@ -395,7 +417,7 @@
handles: 'se'
}),
draggable: _.defaults(opts.draggable || {}, {
handle: '.grid-stack-item-content',
handle: (opts.handle_class ? '.' + opts.handle_class : (opts.handle ? opts.handle : '')) || '.grid-stack-item-content',
scroll: false,
appendTo: 'body'
})
@ -403,15 +425,18 @@
this.opts.is_nested = is_nested;
this.container.addClass(this.opts._class);
this._set_static_class();
if (is_nested) {
this.container.addClass('grid-stack-nested');
}
this._init_styles();
this.grid = new GridStackEngine(this.opts.width, function (nodes) {
this.grid = new GridStackEngine(this.opts.width, function(nodes) {
var max_height = 0;
_.each(nodes, function (n) {
_.each(nodes, function(n) {
if (n._id == null) {
n.el.remove();
}
@ -430,25 +455,29 @@
if (this.opts.auto) {
var elements = [];
var _this = this;
this.container.children('.' + this.opts.item_class).each(function (index, el) {
this.container.children('.' + this.opts.item_class + ':not(.' + this.opts.placeholder_class + ')').each(function(index, el) {
el = $(el);
elements.push({
el: el,
i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width // Use opts.width as weight for Y
i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width
});
});
_.chain(elements).sortBy(function (x) { return x.i; }).each(function (i) {
_.chain(elements).sortBy(function(x) { return x.i; }).each(function(i) {
self._prepare_element(i.el);
}).value();
}
this.set_animation(this.opts.animate);
this.placeholder = $('<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '"><div class="placeholder-content" /></div>').hide();
this.container.append(this.placeholder);
this.container.height((this.grid.get_grid_height()) * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
this.placeholder = $(
'<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '">' +
'<div class="placeholder-content">' + this.opts.placeholder_text + '</div></div>').hide();
var on_resize_handler = function () {
this.container.height(
this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) -
this.opts.vertical_margin);
this.on_resize_handler = function() {
if (self._is_one_column_mode()) {
if (one_column_mode)
return;
@ -456,9 +485,12 @@
one_column_mode = true;
self.grid._sort_nodes();
_.each(self.grid.nodes, function (node) {
_.each(self.grid.nodes, function(node) {
self.container.append(node.el);
if (self.opts.static_grid) {
return;
}
if (!node.no_move) {
node.el.draggable('disable');
}
@ -473,7 +505,11 @@
one_column_mode = false;
_.each(self.grid.nodes, function (node) {
if (self.opts.static_grid) {
return;
}
_.each(self.grid.nodes, function(node) {
if (!node.no_move) {
node.el.draggable('enable');
}
@ -484,11 +520,26 @@
}
};
$(window).resize(on_resize_handler);
on_resize_handler();
$(window).resize(this.on_resize_handler);
this.on_resize_handler();
};
GridStack.prototype._init_styles = function () {
GridStack.prototype._trigger_change_event = function(forceTrigger) {
var elements = this.grid.get_dirty_nodes();
var hasChanges = false;
var eventParams = [];
if (elements && elements.length) {
eventParams.push(elements);
hasChanges = true;
}
if (hasChanges || forceTrigger === true) {
this.container.trigger('change', eventParams);
}
};
GridStack.prototype._init_styles = function() {
if (this._styles_id) {
$('[data-gs-id="' + this._styles_id + '"]').remove();
}
@ -498,7 +549,7 @@
this._styles._max = 0;
};
GridStack.prototype._update_styles = function (max_height) {
GridStack.prototype._update_styles = function(max_height) {
if (this._styles == null) {
return;
}
@ -542,18 +593,21 @@
}
};
GridStack.prototype._update_container_height = function () {
GridStack.prototype._update_container_height = function() {
if (this.grid._update_counter) {
return;
}
this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
this.container.height(
this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) -
this.opts.vertical_margin);
};
GridStack.prototype._is_one_column_mode = function () {
return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <= this.opts.min_width;
GridStack.prototype._is_one_column_mode = function() {
return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <=
this.opts.min_width;
};
GridStack.prototype._prepare_element = function (el) {
GridStack.prototype._prepare_element = function(el) {
var self = this;
el = $(el);
@ -576,13 +630,34 @@
});
el.data('_gridstack_node', node);
if (self.opts.static_grid) {
return;
}
var cell_width, cell_height;
var on_start_moving = function (event, ui) {
var drag_or_resize = function(event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height / 2) / cell_height),
width, height;
if (event.type != "drag") {
width = Math.round(ui.size.width / cell_width);
height = Math.round(ui.size.height / cell_height);
}
if (!self.grid.can_move_node(node, x, y, width, height)) {
return;
}
self.grid.move_node(node, x, y, width, height);
self._update_container_height();
};
var on_start_moving = function(event, ui) {
self.container.append(self.placeholder);
var o = $(this);
self.grid.clean_nodes();
self.grid.begin_update(node);
cell_width = Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
cell_width = o.outerWidth() / o.attr('data-gs-width');
cell_height = self.opts.cell_height + self.opts.vertical_margin;
self.placeholder
.attr('data-gs-x', o.attr('data-gs-x'))
@ -592,11 +667,16 @@
.show();
node.el = self.placeholder;
el.resizable('option', 'minWidth', cell_width * (node.min_width || 1));
el.resizable('option', 'minWidth', Math.round(cell_width * (node.min_width || 1)));
el.resizable('option', 'minHeight', self.opts.cell_height * (node.min_height || 1));
if (event.type == 'resizestart') {
o.find('.grid-stack-item').trigger('resizestart');
}
};
var on_end_moving = function (event, ui) {
var on_end_moving = function(event, ui) {
self.placeholder.detach();
var o = $(this);
node.el = o;
self.placeholder.hide();
@ -607,39 +687,30 @@
.attr('data-gs-height', node.height)
.removeAttr('style');
self._update_container_height();
self.container.trigger('change', [self.grid.get_dirty_nodes()]);
self._trigger_change_event();
self.grid.end_update();
var nested_grids = o.find('.grid-stack');
if (nested_grids.length && event.type == 'resizestop') {
nested_grids.each(function(index, el) {
$(el).data('gridstack').on_resize_handler();
});
o.find('.grid-stack-item').trigger('resizestop');
}
};
el.draggable(_.extend(this.opts.draggable, {
start: on_start_moving,
stop: on_end_moving,
drag: function (event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height/2) / cell_height);
if (!self.grid.can_move_node(node, x, y, node.width, node.height)) {
return;
}
self.grid.move_node(node, x, y);
self._update_container_height();
},
containment: this.opts.is_nested ? this.container.parent() : null
})).resizable(_.extend(this.opts.resizable, {
start: on_start_moving,
stop: on_end_moving,
resize: function (event, ui) {
var x = Math.round(ui.position.left / cell_width),
y = Math.floor((ui.position.top + cell_height/2) / cell_height),
width = Math.round(ui.size.width / cell_width),
height = Math.round(ui.size.height / cell_height);
if (!self.grid.can_move_node(node, x, y, width, height)) {
return;
}
self.grid.move_node(node, x, y, width, height);
self._update_container_height();
}
}));
el
.draggable(_.extend(this.opts.draggable, {
containment: this.opts.is_nested ? this.container.parent() : null
}))
.on('dragstart', on_start_moving)
.on('dragstop', on_end_moving)
.on('drag', drag_or_resize)
.resizable(_.extend(this.opts.resizable, {}))
.on('resizestart', on_start_moving)
.on('resizestop', on_end_moving)
.on('resize', drag_or_resize);
if (node.no_move || this._is_one_column_mode()) {
el.draggable('disable');
@ -652,7 +723,7 @@
el.attr('data-gs-locked', node.locked ? 'yes' : null);
};
GridStack.prototype.set_animation = function (enable) {
GridStack.prototype.set_animation = function(enable) {
if (enable) {
this.container.addClass('grid-stack-animate');
}
@ -661,7 +732,7 @@
}
};
GridStack.prototype.add_widget = function (el, x, y, width, height, auto_position) {
GridStack.prototype.add_widget = function(el, x, y, width, height, auto_position) {
el = $(el);
if (typeof x != 'undefined') el.attr('data-gs-x', x);
if (typeof y != 'undefined') el.attr('data-gs-y', y);
@ -671,16 +742,26 @@
this.container.append(el);
this._prepare_element(el);
this._update_container_height();
this._trigger_change_event(true);
return el;
};
GridStack.prototype.will_it_fit = function (x, y, width, height, auto_position) {
GridStack.prototype.make_widget = function(el) {
el = $(el);
this._prepare_element(el);
this._update_container_height();
this._trigger_change_event(true);
return el;
};
GridStack.prototype.will_it_fit = function(x, y, width, height, auto_position) {
var node = {x: x, y: y, width: width, height: height, auto_position: auto_position};
return this.grid.can_be_placed_with_respect_to_height(node);
};
GridStack.prototype.remove_widget = function (el, detach_node) {
GridStack.prototype.remove_widget = function(el, detach_node) {
detach_node = typeof detach_node === 'undefined' ? true : detach_node;
el = $(el);
var node = el.data('_gridstack_node');
@ -689,19 +770,30 @@
this._update_container_height();
if (detach_node)
el.remove();
this._trigger_change_event(true);
};
GridStack.prototype.remove_all = function (detach_node) {
_.each(this.grid.nodes, function (node) {
GridStack.prototype.remove_all = function(detach_node) {
_.each(this.grid.nodes, _.bind(function(node) {
this.remove_widget(node.el, detach_node);
}, this);
}, this));
this.grid.nodes = [];
this._update_container_height();
};
GridStack.prototype.resizable = function (el, val) {
GridStack.prototype.destroy = function() {
$(window).off("resize", this.on_resize_handler);
this.disable();
this.container.remove();
Utils.remove_stylesheet(this._styles_id);
if (this.grid)
this.grid = null;
};
GridStack.prototype.resizable = function(el, val) {
var self = this;
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -709,7 +801,7 @@
}
node.no_resize = !(val || false);
if (node.no_resize) {
if (node.no_resize || self._is_one_column_mode()) {
el.resizable('disable');
}
else {
@ -719,9 +811,10 @@
return this;
};
GridStack.prototype.movable = function (el, val) {
GridStack.prototype.movable = function(el, val) {
var self = this;
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -729,29 +822,33 @@
}
node.no_move = !(val || false);
if (node.no_move) {
if (node.no_move || self._is_one_column_mode()) {
el.draggable('disable');
el.removeClass('ui-draggable-handle');
}
else {
el.draggable('enable');
el.addClass('ui-draggable-handle');
}
});
return this;
};
GridStack.prototype.disable = function () {
GridStack.prototype.disable = function() {
this.movable(this.container.children('.' + this.opts.item_class), false);
this.resizable(this.container.children('.' + this.opts.item_class), false);
this.container.trigger('disable');
};
GridStack.prototype.enable = function () {
GridStack.prototype.enable = function() {
this.movable(this.container.children('.' + this.opts.item_class), true);
this.resizable(this.container.children('.' + this.opts.item_class), true);
this.container.trigger('enable');
};
GridStack.prototype.locked = function (el, val) {
GridStack.prototype.locked = function(el, val) {
el = $(el);
el.each(function (index, el) {
el.each(function(index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -764,7 +861,41 @@
return this;
};
GridStack.prototype._update_element = function (el, callback) {
GridStack.prototype.min_height = function (el, val) {
el = $(el);
el.each(function (index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
return;
}
if(!isNaN(val)){
node.min_height = (val || false);
el.attr('data-gs-min-height', val);
}
});
return this;
};
GridStack.prototype.min_width = function (el, val) {
el = $(el);
el.each(function (index, el) {
el = $(el);
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
return;
}
if(!isNaN(val)){
node.min_width = (val || false);
el.attr('data-gs-min-width', val);
}
});
return this;
};
GridStack.prototype._update_element = function(el, callback) {
el = $(el).first();
var node = el.data('_gridstack_node');
if (typeof node == 'undefined' || node == null) {
@ -779,13 +910,13 @@
callback.call(this, el, node);
self._update_container_height();
self.container.trigger('change', [self.grid.get_dirty_nodes()]);
self._trigger_change_event();
self.grid.end_update();
};
GridStack.prototype.resize = function (el, width, height) {
this._update_element(el, function (el, node) {
GridStack.prototype.resize = function(el, width, height) {
this._update_element(el, function(el, node) {
width = (width != null && typeof width != 'undefined') ? width : node.width;
height = (height != null && typeof height != 'undefined') ? height : node.height;
@ -793,8 +924,8 @@
});
};
GridStack.prototype.move = function (el, x, y) {
this._update_element(el, function (el, node) {
GridStack.prototype.move = function(el, x, y) {
this._update_element(el, function(el, node) {
x = (x != null && typeof x != 'undefined') ? x : node.x;
y = (y != null && typeof y != 'undefined') ? y : node.y;
@ -802,8 +933,8 @@
});
};
GridStack.prototype.update = function (el, x, y, width, height) {
this._update_element(el, function (el, node) {
GridStack.prototype.update = function(el, x, y, width, height) {
this._update_element(el, function(el, node) {
x = (x != null && typeof x != 'undefined') ? x : node.x;
y = (y != null && typeof y != 'undefined') ? y : node.y;
width = (width != null && typeof width != 'undefined') ? width : node.width;
@ -813,7 +944,7 @@
});
};
GridStack.prototype.cell_height = function (val) {
GridStack.prototype.cell_height = function(val) {
if (typeof val == 'undefined') {
return this.opts.cell_height;
}
@ -824,7 +955,7 @@
this._update_styles();
};
GridStack.prototype.cell_width = function () {
GridStack.prototype.cell_width = function() {
var o = this.container.children('.' + this.opts.item_class).first();
return Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
};
@ -840,27 +971,54 @@
return {x: Math.floor(relativeLeft / column_width), y: Math.floor(relativeTop / row_height)};
};
GridStack.prototype.batch_update = function () {
GridStack.prototype.batch_update = function() {
this.grid.batch_update();
};
GridStack.prototype.commit = function () {
GridStack.prototype.commit = function() {
this.grid.commit();
this._update_container_height()
this._update_container_height();
};
GridStack.prototype.is_area_empty = function (x, y, width, height) {
GridStack.prototype.is_area_empty = function(x, y, width, height) {
return this.grid.is_area_empty(x, y, width, height);
};
GridStack.prototype.set_static = function(static_value) {
this.opts.static_grid = (static_value === true);
this._set_static_class();
};
GridStack.prototype._set_static_class = function() {
var static_class_name = 'grid-stack-static';
if (this.opts.static_grid === true) {
this.container.addClass(static_class_name);
} else {
this.container.removeClass(static_class_name);
}
};
scope.GridStackUI = GridStack;
scope.GridStackUI.Utils = Utils;
$.fn.gridstack = function (opts) {
return this.each(function () {
if (!$(this).data('gridstack')) {
$(this).data('gridstack', new GridStack(this, opts));
function event_stop_propagate(event) {
event.stopPropagation();
}
$.fn.gridstack = function(opts) {
return this.each(function() {
var o = $(this);
if (!o.data('gridstack')) {
o
.data('gridstack', new GridStack(this, opts))
.on('dragstart', event_stop_propagate)
.on('dragstop', event_stop_propagate)
.on('drag', event_stop_propagate)
.on('resizestart', event_stop_propagate)
.on('resizestop', event_stop_propagate)
.on('resize', event_stop_propagate)
.on('change', event_stop_propagate);
}
});
};

View file

@ -1,7 +1,7 @@
$gridstack-columns: 12;
$horizontal_padding: 20px;
$vertical_padding: 20px;
$animation_speed: .3s;
$gridstack-columns: 12 !default;
$horizontal_padding: 20px !default;
$vertical_padding: 20px !default;
$animation_speed: .3s !default;
@mixin vendor($property, $value...){
-webkit-#{$property}:$value;
@ -26,6 +26,7 @@ $animation_speed: .3s;
bottom: 0;
width: auto;
z-index: 0 !important;
text-align: center;
}
> .grid-stack-item {
@ -53,21 +54,21 @@ $animation_speed: .3s;
-ms-touch-action: none;
touch-action: none;
}
&.ui-resizable-disabled > .ui-resizable-handle,
&.ui-resizable-autohide > .ui-resizable-handle { display: none; }
&.ui-draggable-dragging,
&.ui-resizable-resizing {
z-index: 100;
> .grid-stack-item-content,
> .grid-stack-item-content {
box-shadow: 1px 4px 6px rgba(0, 0, 0, 0.2);
opacity: 0.8;
}
}
> .ui-resizable-se,
> .ui-resizable-sw {
text-align: right;
@ -81,16 +82,15 @@ $animation_speed: .3s;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&::before { content: "\f065"; }
}
> .ui-resizable-se {
display: inline-block;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
@include vendor(transform, rotate(90deg));
}
> .ui-resizable-nw { cursor: nw-resize; width: 20px; height: 20px; left: 10px; top: 0; }
> .ui-resizable-n { cursor: n-resize; height: 10px; top: 0; left: 25px; right: 25px; }
> .ui-resizable-ne { cursor: ne-resize; width: 20px; height: 20px; right: 10px; top: 0; }
@ -99,7 +99,7 @@ $animation_speed: .3s;
> .ui-resizable-s { cursor: s-resize; height: 10px; left: 25px; bottom: 0; right: 25px; }
> .ui-resizable-sw { cursor: sw-resize; width: 20px; height: 20px; left: 10px; bottom: 0; }
> .ui-resizable-w { cursor: w-resize; width: 10px; left: $horizontal_padding / 2; top: 15px; bottom: 15px; }
@for $i from 1 through $gridstack-columns {
&[data-gs-width='#{$i}'] { width: (100% / $gridstack-columns) * $i; }
&[data-gs-x='#{$i}'] { left: (100% / $gridstack-columns) * $i; }
@ -107,8 +107,8 @@ $animation_speed: .3s;
&[data-gs-max-width='#{$i}'] { max-width: (100% / $gridstack-columns) * $i; }
}
}
&.grid-stack-animate,
&.grid-stack-animate,
&.grid-stack-animate .grid-stack-item {
@include vendor(transition, left $animation_speed, top $animation_speed, height $animation_speed, width $animation_speed);
}
@ -124,7 +124,6 @@ $animation_speed: .3s;
/*
.grid-stack > .grid-stack-item > .ui-resizable-sw {
display: inline-block;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
@include vendor(transform, rotate(180deg));
}
*/
@ -136,7 +135,7 @@ $animation_speed: .3s;
left: 0 !important;
top: auto !important;
margin-bottom: $vertical_padding;
.ui-resizable-handle { display: none; }
}