2014-11-10 03:18:33 +01:00
|
|
|
gridstack.js
|
|
|
|
============
|
|
|
|
|
2014-11-12 04:45:36 +01:00
|
|
|
gridstack.js is a jQuery plugin for widget layout. This is drag-and-drop multi-column grid. It allows you to build
|
2015-01-09 04:47:15 +01:00
|
|
|
draggable responsive bootstrap v3 friendly layouts. It also works great with [knockout.js](http://knockoutjs.com) and
|
|
|
|
touch devices.
|
2014-11-10 03:41:05 +01:00
|
|
|
|
2014-11-10 05:14:22 +01:00
|
|
|
Inspired by [gridster.js](http://gridster.net). Built with love.
|
2014-11-10 03:41:05 +01:00
|
|
|
|
|
|
|
Demo
|
|
|
|
====
|
|
|
|
|
2014-11-10 03:44:41 +01:00
|
|
|
Please visit http://troolee.github.io/gridstack.js/ for demo.
|
2014-11-10 03:41:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
Usage
|
|
|
|
=====
|
2014-11-10 05:14:22 +01:00
|
|
|
|
2014-11-12 06:21:21 +01:00
|
|
|
## Requirements
|
|
|
|
|
2015-01-09 04:56:07 +01:00
|
|
|
* [underscore.js](http://underscorejs.org) (>= 1.7.0)
|
2015-01-09 04:57:24 +01:00
|
|
|
* [jQuery](http://jquery.com) (>= 1.11.0)
|
2015-01-09 04:56:07 +01:00
|
|
|
* [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
|
2014-11-10 05:17:33 +01:00
|
|
|
|
2014-11-17 09:15:14 +01:00
|
|
|
## Basic usage
|
|
|
|
|
|
|
|
```html
|
2014-11-29 07:07:43 +01:00
|
|
|
<div class="grid-stack">
|
|
|
|
<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>
|
2014-11-17 09:15:14 +01:00
|
|
|
</div>
|
2014-11-29 07:07:43 +01:00
|
|
|
<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>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
$(function () {
|
|
|
|
var options = {
|
|
|
|
cell_height: 80,
|
|
|
|
vertical_margin: 10
|
|
|
|
};
|
|
|
|
$('.grid-stack').gridstack(options);
|
|
|
|
});
|
|
|
|
</script>
|
2014-11-17 09:15:14 +01:00
|
|
|
```
|
|
|
|
|
2014-11-17 09:04:18 +01:00
|
|
|
## Options
|
|
|
|
|
2015-01-09 04:41:07 +01:00
|
|
|
- `always_show_resize_handle` - if `true` the resizing handles are shown even the user is not hovering over the widget
|
|
|
|
(default: `false`)
|
2014-12-05 06:00:15 +01:00
|
|
|
- `animate` - turns animation on (default: `false`)
|
|
|
|
- `auto` - if `false` it tells to do not initialize existing items (default: `true`)
|
|
|
|
- `cell_height` - one cell height (default: `60`)
|
2014-12-05 06:11:51 +01:00
|
|
|
- `handle` - draggable handle selector (default: `'.grid-stack-item-content'`)
|
2014-11-29 06:57:24 +01:00
|
|
|
- `height` - maximum rows amount. Default is `0` which means no maximum rows
|
2014-12-05 06:00:15 +01:00
|
|
|
- `float` - enable floating widgets (default: `false`)
|
2014-12-05 06:11:51 +01:00
|
|
|
- `item_class` - widget class (default: `'grid-stack-item'`)
|
2014-12-05 06:00:15 +01:00
|
|
|
- `min_width` - minimal width. If window width is less grid will be shown in one-column mode (default: `768`)
|
2014-12-05 06:11:51 +01:00
|
|
|
- `placeholder_class` - class for placeholder (default: `'grid-stack-placeholder'`)
|
2014-12-05 06:00:15 +01:00
|
|
|
- `vertical_margin` - vertical gap size (default: `20`)
|
|
|
|
- `width` - amount of columns (default: `12`)
|
2014-11-17 09:04:18 +01:00
|
|
|
|
2014-11-17 09:15:14 +01:00
|
|
|
## Grid attributes
|
|
|
|
|
2014-12-05 06:00:15 +01:00
|
|
|
- `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.
|
2014-11-17 09:15:14 +01:00
|
|
|
|
2014-11-14 07:34:33 +01:00
|
|
|
## Item attributes
|
|
|
|
|
|
|
|
- `data-gs-x`, `data-gs-y` - element position
|
|
|
|
- `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
|
2014-11-21 02:27:52 +01:00
|
|
|
- `data-gs-no-move` - disable element moving
|
2014-11-17 09:04:18 +01:00
|
|
|
- `data-gs-auto-position` - tells to ignore `data-gs-x` and `data-gs-y` attributes and to place element to the first
|
|
|
|
available position
|
2014-12-06 05:31:53 +01:00
|
|
|
- `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
|
|
|
|
to completely lock the widget.
|
2014-11-17 09:58:57 +01:00
|
|
|
|
|
|
|
## Events
|
|
|
|
|
2014-11-26 08:10:47 +01:00
|
|
|
### onchange(items)
|
2014-11-17 09:58:57 +01:00
|
|
|
|
|
|
|
Occurs when widgets change their position/size
|
|
|
|
|
|
|
|
```javascript
|
2014-11-29 07:07:43 +01:00
|
|
|
var serialize_widget_map = function (items) {
|
|
|
|
console.log(items);
|
|
|
|
};
|
2014-11-17 10:05:25 +01:00
|
|
|
|
2014-11-29 07:07:43 +01:00
|
|
|
$('.grid-stack').on('change', function (e, items) {
|
|
|
|
serialize_widget_map(items);
|
|
|
|
});
|
2014-11-17 09:58:57 +01:00
|
|
|
```
|
|
|
|
|
2014-11-26 08:10:47 +01:00
|
|
|
### ondragstart(event, ui)
|
|
|
|
|
|
|
|
```javascript
|
2014-11-29 07:07:43 +01:00
|
|
|
$('.grid-stack').on('dragstart', function (event, ui) {
|
|
|
|
var grid = this;
|
|
|
|
var element = event.target;
|
|
|
|
});
|
2014-11-26 08:10:47 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
### ondragstop(event, ui)
|
|
|
|
|
|
|
|
```javascript
|
2014-11-29 07:07:43 +01:00
|
|
|
$('.grid-stack').on('dragstop', function (event, ui) {
|
|
|
|
var grid = this;
|
|
|
|
var element = event.target;
|
|
|
|
});
|
2014-11-26 08:10:47 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
### onresizestart(event, ui)
|
|
|
|
|
|
|
|
```javascript
|
2014-11-29 07:07:43 +01:00
|
|
|
$('.grid-stack').on('resizestart', function (event, ui) {
|
|
|
|
var grid = this;
|
|
|
|
var element = event.target;
|
|
|
|
});
|
2014-11-26 08:10:47 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
### onresizestop(event, ui)
|
|
|
|
|
|
|
|
```javascript
|
2014-11-29 07:07:43 +01:00
|
|
|
$('.grid-stack').on('resizestop', function (event, ui) {
|
|
|
|
var grid = this;
|
|
|
|
var element = event.target;
|
|
|
|
});
|
2014-11-26 08:10:47 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
2014-11-17 09:58:57 +01:00
|
|
|
## API
|
|
|
|
|
|
|
|
### add_widget(el, x, y, width, height, auto_position)
|
|
|
|
|
|
|
|
Creates new widget.
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
|
|
|
- `el` - widget to add
|
|
|
|
- `x`, `y`, `width`, `height` - widget position/dimensions (Optional)
|
|
|
|
- `auto_position` - if `true` then `x`, `y` parameters will be ignored and widget will be places on the first available
|
|
|
|
position
|
|
|
|
|
2014-12-06 03:37:50 +01:00
|
|
|
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.
|
|
|
|
|
2014-11-17 10:02:26 +01:00
|
|
|
```javascript
|
2014-11-17 10:02:57 +01:00
|
|
|
$('.grid-stack').gridstack();
|
2014-11-17 10:02:26 +01:00
|
|
|
|
2014-11-17 10:02:57 +01:00
|
|
|
var grid = $('.grid-stack').data('gridstack');
|
2014-11-17 10:02:26 +01:00
|
|
|
grid.add_widget(el, 0, 0, 3, 2, true);
|
|
|
|
```
|
|
|
|
|
2014-12-12 06:57:47 +01:00
|
|
|
### cell_height()
|
|
|
|
|
|
|
|
Gets current cell height.
|
|
|
|
|
|
|
|
### cell_height(val)
|
|
|
|
|
|
|
|
Update current cell height. This method rebuilds an internal CSS stylesheet. Note: You can expect performance issues if
|
|
|
|
call this method too often.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
grid.cell_height(grid.cell_width() * 1.2);
|
|
|
|
```
|
|
|
|
|
|
|
|
### cell_width()
|
|
|
|
|
|
|
|
Gets current cell width.
|
|
|
|
|
2014-12-06 05:31:53 +01:00
|
|
|
### locked(el, val)
|
|
|
|
|
|
|
|
Locks/unlocks widget.
|
|
|
|
|
|
|
|
- `el` - widget to modify.
|
|
|
|
- `val` - if `true` widget will be locked.
|
|
|
|
|
2014-11-17 09:58:57 +01:00
|
|
|
### remove_widget(el)
|
|
|
|
|
|
|
|
Removes widget from the grid.
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
2014-11-17 10:05:25 +01:00
|
|
|
- `el` - widget to remove
|
2014-11-14 07:34:33 +01:00
|
|
|
|
2014-11-24 02:04:11 +01:00
|
|
|
### remove_all()
|
|
|
|
|
|
|
|
Removes all widgets from the grid.
|
|
|
|
|
2014-11-22 03:45:26 +01:00
|
|
|
### resize(el, width, \[height\])
|
|
|
|
|
|
|
|
Changes widget size
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
|
|
|
- `el` - widget to resize
|
2014-11-22 04:02:04 +01:00
|
|
|
- `width`, `height` - new dimensions. If value is `null` or `undefined` it will be ignored.
|
2014-11-22 03:45:26 +01:00
|
|
|
|
|
|
|
### move(el, x, \[y\])
|
|
|
|
|
|
|
|
Changes widget position
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
|
|
|
- `el` - widget to move
|
2014-11-22 04:02:04 +01:00
|
|
|
- `x`, `y` - new position. If value is `null` or `undefined` it will be ignored.
|
2014-11-22 03:45:26 +01:00
|
|
|
|
2014-11-21 02:56:36 +01:00
|
|
|
### resizable(el, val)
|
|
|
|
|
|
|
|
Enables/Disables resizing.
|
|
|
|
|
|
|
|
- `el` - widget to modify
|
|
|
|
- `val` - if `true` widget will be resizable.
|
|
|
|
|
|
|
|
### movable(el, val)
|
|
|
|
|
|
|
|
Enables/Disables moving.
|
|
|
|
|
|
|
|
- `el` - widget to modify
|
2014-11-24 02:04:11 +01:00
|
|
|
- `val` - if `true` widget will be draggable.
|
2014-12-06 03:37:50 +01:00
|
|
|
|
|
|
|
### will_it_fit(x, y, width, height, auto_position)
|
|
|
|
|
|
|
|
Returns `true` if the `height` of the grid will be less the vertical constraint. Always returns `true` if grid doesn't
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
else {
|
2014-12-06 03:43:33 +01:00
|
|
|
alert('Not enough free space to place the widget');
|
2014-12-06 03:37:50 +01:00
|
|
|
}
|
|
|
|
```
|
2014-11-24 02:04:11 +01:00
|
|
|
|
2014-12-06 03:37:50 +01:00
|
|
|
|
2014-11-24 02:04:11 +01:00
|
|
|
## Utils
|
|
|
|
|
|
|
|
### GridStackUI.Utils.sort(nodes, \[dir\], \[width\])
|
|
|
|
|
|
|
|
Sorts array of nodes
|
|
|
|
|
|
|
|
- `nodes` - array to sort
|
|
|
|
- `dir` - `1` for asc, `-1` for desc
|
2014-11-24 06:03:02 +01:00
|
|
|
- `width` - width of the grid. If `undefined` the width will be calculated automatically.
|
2014-11-21 02:56:36 +01:00
|
|
|
|
2015-01-09 04:41:07 +01:00
|
|
|
## Touch devices support
|
|
|
|
|
2015-01-09 04:43:03 +01:00
|
|
|
Please use [jQuery UI Touch Punch](https://github.com/furf/jquery-ui-touch-punch) to make jQuery UI Draggable/Resizable
|
2015-01-09 04:41:07 +01:00
|
|
|
working on touch-based devices.
|
|
|
|
|
2015-01-09 04:47:15 +01:00
|
|
|
```html
|
|
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
|
|
|
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
|
|
|
<script src="jquery-ui.min.js"></script>
|
|
|
|
<script src="jquery.ui.touch-punch.min.js"></script>
|
|
|
|
|
|
|
|
<script src="gridstack.js"></script>
|
|
|
|
```
|
|
|
|
|
2015-01-09 04:41:07 +01:00
|
|
|
Also `always_show_resize_handle` option may be useful:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
$(function () {
|
|
|
|
var options = {
|
|
|
|
always_show_resize_handle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
|
|
|
};
|
|
|
|
$('.grid-stack').gridstack(options);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2014-11-12 04:24:48 +01:00
|
|
|
## Use with knockout.js
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
ko.components.register('dashboard-grid', {
|
|
|
|
viewModel: {
|
|
|
|
createViewModel: function (params, componentInfo) {
|
|
|
|
var ViewModel = function (params, componentInfo) {
|
|
|
|
var grid = null;
|
|
|
|
|
|
|
|
this.widgets = params.widgets;
|
|
|
|
|
|
|
|
this.afterAddWidget = function (items) {
|
|
|
|
_.each(items, function (item) {
|
|
|
|
item = $(item);
|
|
|
|
|
|
|
|
if (grid == null) {
|
|
|
|
grid = $(componentInfo.element).find('.grid-stack').gridstack({
|
|
|
|
auto: false
|
|
|
|
}).data('gridstack');
|
|
|
|
}
|
|
|
|
|
|
|
|
grid.add_widget(item);
|
2014-11-12 07:37:02 +01:00
|
|
|
ko.utils.domNodeDisposal.addDisposeCallback(item[0], function () {
|
|
|
|
grid.remove_widget(item);
|
|
|
|
});
|
2014-11-12 04:24:48 +01:00
|
|
|
}, this);
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
return new ViewModel(params, componentInfo);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
template: [
|
|
|
|
'<div class="grid-stack">',
|
|
|
|
' <!-- ko foreach: widgets, afterRender: afterAddWidget -->',
|
2014-11-12 04:45:36 +01:00
|
|
|
' <div class="grid-stack-item" data-bind="attr: {',
|
|
|
|
' \'data-gs-x\': x, \'data-gs-y\': y,',
|
|
|
|
' \'data-gs-width\': width, \'data-gs-height\': height}">',
|
|
|
|
' <span data-bind="text: $index"></span>',
|
|
|
|
' </div>',
|
2014-11-12 04:24:48 +01:00
|
|
|
' <!-- /ko -->',
|
|
|
|
'</div>'
|
|
|
|
].join('\n')
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
and HTML:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div data-bind="component: {name: 'dashboard-grid', params: $data}"></div>
|
|
|
|
```
|
|
|
|
|
2015-01-05 04:46:07 +01:00
|
|
|
## Change grid width
|
|
|
|
|
2015-01-05 05:35:33 +01:00
|
|
|
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.
|
2015-01-05 04:46:07 +01:00
|
|
|
|
2015-01-05 05:35:33 +01:00
|
|
|
For instance for 3-column grid you need to rewrite CSS to be:
|
2015-01-05 04:46:07 +01:00
|
|
|
|
|
|
|
```css
|
|
|
|
.grid-stack-item[data-gs-width="3"] { width: 100% }
|
|
|
|
.grid-stack-item[data-gs-width="2"] { width: 66.66666667% }
|
|
|
|
.grid-stack-item[data-gs-width="1"] { width: 33.33333333% }
|
|
|
|
|
|
|
|
.grid-stack-item[data-gs-x="2"] { left: 66.66666667% }
|
|
|
|
.grid-stack-item[data-gs-x="1"] { left: 33.33333333% }
|
|
|
|
```
|
|
|
|
|
|
|
|
For 4-column grid it should be:
|
|
|
|
|
|
|
|
```css
|
|
|
|
.grid-stack-item[data-gs-width="4"] { width: 100% }
|
|
|
|
.grid-stack-item[data-gs-width="3"] { width: 75% }
|
|
|
|
.grid-stack-item[data-gs-width="2"] { width: 50% }
|
|
|
|
.grid-stack-item[data-gs-width="1"] { width: 25% }
|
|
|
|
|
|
|
|
.grid-stack-item[data-gs-x="3"] { left: 75% }
|
|
|
|
.grid-stack-item[data-gs-x="2"] { left: 50% }
|
|
|
|
.grid-stack-item[data-gs-x="1"] { left: 25% }
|
|
|
|
```
|
|
|
|
|
2015-01-05 05:35:33 +01:00
|
|
|
and so on.
|
|
|
|
|
2014-11-12 04:24:48 +01:00
|
|
|
|
2014-11-19 03:41:21 +01:00
|
|
|
Changes
|
|
|
|
=======
|
|
|
|
|
2015-01-09 05:00:08 +01:00
|
|
|
#### v0.2.3 (development version)
|
2015-01-09 04:41:07 +01:00
|
|
|
|
|
|
|
- improved touch devices support
|
|
|
|
- add `always_show_resize_handle` option
|
|
|
|
|
2014-12-24 01:22:09 +01:00
|
|
|
#### v0.2.2 (2014-12-23)
|
2014-12-12 06:01:30 +01:00
|
|
|
|
2014-12-20 02:37:44 +01:00
|
|
|
- fix grid initialization
|
2014-12-12 06:57:47 +01:00
|
|
|
- add `cell_height`/`cell_width` API methods
|
2014-12-12 06:01:30 +01:00
|
|
|
- fix boolean attributes (issue #31)
|
|
|
|
|
2014-12-09 23:48:40 +01:00
|
|
|
#### v0.2.1 (2014-12-09)
|
2014-12-02 02:50:53 +01:00
|
|
|
|
2014-12-06 05:31:53 +01:00
|
|
|
- add widgets locking (issue #19)
|
2014-12-06 03:37:50 +01:00
|
|
|
- add `will_it_fit` API method
|
|
|
|
- fix auto-positioning (issue #20)
|
2014-12-05 06:00:15 +01:00
|
|
|
- add animation (thanks to @ishields)
|
2014-12-02 03:15:11 +01:00
|
|
|
- fix `y` coordinate calculation when dragging (issue #18)
|
2014-12-02 02:53:59 +01:00
|
|
|
- fix `remove_widget` (issue #16)
|
2014-12-06 04:20:22 +01:00
|
|
|
- minor fixes
|
2014-12-02 02:50:53 +01:00
|
|
|
|
|
|
|
|
2014-11-30 20:05:45 +01:00
|
|
|
#### v0.2.0 (2014-11-30)
|
2014-11-20 05:57:06 +01:00
|
|
|
|
2014-11-29 06:57:24 +01:00
|
|
|
- add `height` option
|
2014-11-26 07:45:49 +01:00
|
|
|
- auto-generate css rules (widgets `height` and `top`)
|
2014-11-24 02:05:57 +01:00
|
|
|
- add `GridStackUI.Utils.sort` utility function
|
|
|
|
- add `remove_all` API method
|
2014-11-22 03:45:26 +01:00
|
|
|
- add `resize` and `move` API methods
|
2014-11-21 02:56:36 +01:00
|
|
|
- add `resizable` and `movable` API methods
|
|
|
|
- add `data-gs-no-move` attribute
|
2014-11-20 05:57:06 +01:00
|
|
|
- add `float` option
|
|
|
|
- fix default css rule for inner content
|
2014-11-29 06:57:24 +01:00
|
|
|
- minor fixes
|
2014-11-20 05:57:06 +01:00
|
|
|
|
2014-11-19 03:41:21 +01:00
|
|
|
#### v0.1.0 (2014-11-18)
|
|
|
|
|
2014-11-19 03:45:48 +01:00
|
|
|
Very first version.
|
|
|
|
|
2014-11-19 03:41:21 +01:00
|
|
|
|
2014-11-10 05:17:33 +01:00
|
|
|
License
|
|
|
|
=======
|
|
|
|
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
|
|
|
Copyright (c) 2014 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
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
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.
|
|
|
|
|