├── .npmignore ├── .bowerrc ├── demos ├── assets │ ├── img │ │ └── sprite.png │ ├── js │ │ └── plugins.js │ └── less │ │ └── demo.less ├── index.html ├── adding-widgets-dynamically.html ├── dynamic-grid-width.html ├── grid-from-serialize.html ├── jquery.gridster.demo2.html ├── sticky-postion.html ├── resize.html ├── SwapDrop.html ├── expandable-widgets.html ├── using-drag-callbacks.html ├── using-resize-callbacks.html ├── custom-drag-handle.html ├── multiple-grids.html ├── serialize.html ├── resize-limits.html ├── chaosWidget.html └── responsive.html ├── lib ├── gridster.js-rails │ ├── version.rb │ └── engine.rb └── gridster.js-rails.rb ├── test ├── jquery-private.js ├── testsuite.js ├── amd-main.js ├── jquery.gridster.html ├── jquery.gridster-amd.html ├── lib │ └── test_utils.js └── jquery.gridster_test.js ├── .gitignore ├── .travis.yml ├── bower.json ├── gridster.js-rails.gemspec ├── LICENSE ├── package.json ├── README.md ├── dist ├── jquery.gridster.min.css └── jquery.gridster.css ├── src ├── utils.js ├── jquery.coords.js ├── jquery.gridster.less ├── jquery.gridster.extras.js ├── jquery.collision.js └── jquery.draggable.js ├── Gruntfile.js ├── .jshintrc ├── CONTRIBUTING.md └── CHANGELOG.md /.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !README.md 3 | !LICENSE 4 | !dist/**/* -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "libs", 3 | "json": "package.json" 4 | } -------------------------------------------------------------------------------- /demos/assets/img/sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emackey/gridster.js/master/demos/assets/img/sprite.png -------------------------------------------------------------------------------- /lib/gridster.js-rails/version.rb: -------------------------------------------------------------------------------- 1 | module Gridster 2 | module Rails 3 | VERSION = "0.6.10" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/gridster.js-rails.rb: -------------------------------------------------------------------------------- 1 | module Gridster 2 | module Rails 3 | require "gridster.js-rails/engine" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/jquery-private.js: -------------------------------------------------------------------------------- 1 | define(['jquery'], function (jq) { 2 | 'use strict'; 3 | return jq.noConflict( true ); 4 | }); 5 | -------------------------------------------------------------------------------- /lib/gridster.js-rails/engine.rb: -------------------------------------------------------------------------------- 1 | module Gridster 2 | module Rails 3 | class Engine < ::Rails::Engine 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | libs/ 3 | gh-pages/ 4 | demo/ 5 | .idea 6 | .DS_Store 7 | *.iml 8 | vendor 9 | *.gem 10 | *.css.map 11 | demos/assets/css/demo.css 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | install: 5 | - npm install 6 | - npm install -g bower grunt-cli 7 | before_script: 8 | - bower install 9 | script: 10 | - grunt build --verbose -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gridster", 3 | "homepage": "dsmorse.github.io/gridster.js/", 4 | "version": "0.6.10", 5 | "dependencies": { 6 | "jquery": "^2.1.3" 7 | }, 8 | "devDependencies": { 9 | "requirejs": "^2.1.17", 10 | "qunit": "~1.18.0" 11 | }, 12 | "main": [ 13 | "dist/jquery.gridster.js", 14 | "dist/jquery.gridster.css" 15 | ], 16 | "private": false, 17 | "ignore": [ 18 | ".bowerrc", 19 | ".jshintrc", 20 | ".gitignore", 21 | ".travis.yml", 22 | "CONTRIBUTING.md", 23 | "Gruntfile.js", 24 | "package.json", 25 | "test/", 26 | "gridster.js-rails.gemspec", 27 | "Gemfile", 28 | "Gemfile.lock", 29 | "lib" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /demos/assets/js/plugins.js: -------------------------------------------------------------------------------- 1 | // Avoid `console` errors in browsers that lack a console. 2 | (function () { 3 | var method; 4 | var noop = function () { 5 | }; 6 | var methods = [ 7 | 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 8 | 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 9 | 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 10 | 'timeStamp', 'trace', 'warn' 11 | ]; 12 | var length = methods.length; 13 | var console = (window.console = window.console || {}); 14 | 15 | while (length--) { 16 | method = methods[length]; 17 | 18 | // Only stub undefined methods. 19 | if (!console[method]) { 20 | console[method] = noop; 21 | } 22 | } 23 | }()); 24 | 25 | // Place any jQuery/helper plugins in here. 26 | -------------------------------------------------------------------------------- /test/testsuite.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | define([ 3 | 'QUnit', 4 | 'jquery', 5 | 'gridster' 6 | ], function(QUnit, $, gridster) { 7 | 8 | QUnit.module('Gridster AMD', { 9 | setup: function () { 10 | }, 11 | teardown: function () { 12 | } 13 | }); 14 | 15 | QUnit.test('window.$ should be undefined.', function() { 16 | equal(typeof window.$, 'undefined', 'window.$ should be undefined'); 17 | equal(typeof window.jQuery, 'undefined', 'window.jQuery should be undefined'); 18 | }); 19 | 20 | 21 | QUnit.test('gridster should be initialized.', function() { 22 | $('.wrapper ul').gridster(); 23 | equal($('.wrapper').hasClass('ready'), true, 'Gridster should initialized wrapper.'); 24 | equal($('.wrapper ul li').length, $('.gs-w').length, 'grid elements get a .gs-w class'); 25 | }); 26 | } 27 | ); 28 | -------------------------------------------------------------------------------- /gridster.js-rails.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | require File.expand_path('../lib/gridster.js-rails/version', __FILE__) 3 | 4 | Gem::Specification.new do |spec| 5 | spec.name = "gridster.js-rails" 6 | spec.version = Gridster::Rails::VERSION 7 | spec.authors = ["dsmorse"] 8 | spec.email = ['https://github.com/dsmorse'] 9 | 10 | spec.summary = %q{jQuery plugin for draggable grid layouts} 11 | spec.description = %q{Gridster is a jQuery plugin that makes building intuitive draggable layouts from elements spanning multiple columns. You can even dynamically add and remove elements from the grid.} 12 | spec.homepage = "https://github.com/dsmorse/gridster.js" 13 | spec.licenses = ['MIT'] 14 | 15 | spec.files = Dir["{demos,lib,vendor}/**/*"] + ["LICENSE", "bower.json", "package.json", "CHANGELOG.md", "README.md"] 16 | 17 | spec.require_paths = ["lib"] 18 | 19 | spec.add_development_dependency "bundler", "~> 1.9" 20 | spec.add_development_dependency "rake", "~> 10.0" 21 | end 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Ducksboard 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /demos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gridster Demos 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Samples

13 |
14 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gridster", 3 | "title": "gridster.js", 4 | "description": "a drag-and-drop multi-column jQuery grid plugin", 5 | "version": "0.6.10", 6 | "homepage": "https://dsmorse.github.io/gridster.js/", 7 | "author": { 8 | "name": "ducksboard" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/dsmorse/gridster.js.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/dsmorse/gridster.js/issues" 16 | }, 17 | "license": "MIT", 18 | "licenses": [ 19 | { 20 | "type": "MIT", 21 | "url": "https://github.com/dsmorse/gridster.js/blob/master/LICENSE" 22 | } 23 | ], 24 | "keywords": [], 25 | "devDependencies": { 26 | "bower": "~0.9.2", 27 | "grunt": "~0.4.5", 28 | "grunt-bump": "0.0.11", 29 | "grunt-contrib-clean": "^0.6.0", 30 | "grunt-contrib-concat": "^0.5.0", 31 | "grunt-contrib-copy": "^0.8.0", 32 | "grunt-contrib-cssmin": "~0.10.0", 33 | "grunt-contrib-jshint": "~0.10.0", 34 | "grunt-contrib-less": "^1.0.1", 35 | "grunt-contrib-qunit": "^0.7.0", 36 | "grunt-contrib-uglify": "~0.6.0", 37 | "grunt-contrib-watch": "~0.6.1", 38 | "grunt-contrib-yuidoc": "~0.7.0", 39 | "grunt-conventional-changelog": "~1.0.0", 40 | "grunt-gh-pages": "^0.10.0", 41 | "grunt-shell": "^1.1.2", 42 | "grunt-text-replace": "^0.4.0", 43 | "jshint-stylish": "^1.0.1" 44 | }, 45 | "scripts": { 46 | "test": "grunt test" 47 | }, 48 | "main": "dist/jquery.gridster.js", 49 | "directories": { 50 | "test": "test" 51 | }, 52 | "jspm": { 53 | "main": "jquery.gridster", 54 | "directories": { 55 | "lib": "dist" 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/amd-main.js: -------------------------------------------------------------------------------- 1 | //Based on https://github.com/jonnyreeves/qunit-require 2 | /* global require, QUnit*/ 3 | 'use strict'; 4 | require.config({ 5 | //set the baseUrl to the src dir so that gridster 6 | //AMD modules can be found. 7 | baseUrl: '../src/', 8 | paths: { 9 | 'QUnit': '../libs/qunit/qunit/qunit', 10 | 'jquery': '../libs/jquery/dist/jquery', 11 | 'gridster': 'jquery.gridster' 12 | }, 13 | map: { 14 | // '*' means all modules will get 'jquery-private' 15 | // for their 'jquery' dependency. 16 | '*': { 'jquery': '../test/jquery-private' }, 17 | 18 | // 'jquery-private' wants the real jQuery module 19 | // though. If this line was not here, there would 20 | // be an unresolvable cyclic dependency. 21 | '../test/jquery-private': { 'jquery': 'jquery' } 22 | }, 23 | shim: { 24 | 'QUnit': { 25 | exports: 'QUnit', 26 | init: function() { 27 | QUnit.config.autoload = false; 28 | QUnit.config.autostart = false; 29 | } 30 | } 31 | } 32 | }); 33 | /* 34 | Load all of our require'd files 35 | 36 | We have to load all of the gridster jquery.* modules so 37 | that they are defined for when gridster needs them. 38 | 39 | Lastly, load the testsuite which defines some tests. 40 | */ 41 | require([ 42 | 'QUnit', 43 | 'utils', 44 | 'jquery.coords', 45 | 'jquery.collision', 46 | 'jquery.draggable', 47 | '../test/testsuite' 48 | //Require'd files are passed as args, but we don't use them. 49 | ], function(QUnit/*, utils, coords, collision, draggable, testsuite*/) { 50 | QUnit.load(); 51 | QUnit.start(); 52 | } 53 | ); 54 | -------------------------------------------------------------------------------- /demos/adding-widgets-dynamically.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Add widgets dynamically » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Add widgets dynamically

15 | 16 |

Create a grid adding widgets from an Array (not from HTML) using add_widget method. Widget position (col, row) not specified.

17 | 18 |
19 | 20 |
21 | 22 | 23 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /test/jquery.gridster.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | gridster.js Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |

gridster.js Test Suite

28 | 29 |

30 | 31 |
32 |

33 |
    34 |
    35 | 36 |
    37 | 41 |
    42 |
    43 |
    44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /demos/assets/less/demo.less: -------------------------------------------------------------------------------- 1 | /*! gridster.js - v0.6.10 - 2015-05-31 2 | * https://dsmorse.github.io/gridster.js/ 3 | * Copyright (c) 2015 ducksboard; Licensed MIT */ 4 | 5 | @bg-color: #26941f; 6 | 7 | body { 8 | background: @bg-color; 9 | font-size: 16px; 10 | font-family: 'Helvetica Neue', Arial, sans-serif; 11 | color: #ffffff; 12 | margin: 0; 13 | } 14 | h1, h2, h3, p { 15 | margin: 10px; 16 | } 17 | table { 18 | border-collapse: collapse; 19 | border-spacing: 0; 20 | } 21 | .demo { 22 | margin: 3em 0; 23 | padding: 7.5em 0 5.5em; 24 | background: @bg-color; 25 | } 26 | .demo:hover { 27 | .gridster { 28 | margin: 0 auto; 29 | opacity: .8; 30 | -webkit-transition: opacity .6s; 31 | -moz-transition: opacity .6s; 32 | -o-transition: opacity .6s; 33 | -ms-transition: opacity .6s; 34 | transition: opacity .6s; 35 | } 36 | } 37 | .content { 38 | color: white; 39 | } 40 | .gridster { 41 | .gs-w { 42 | background: #61A9CF; 43 | cursor: pointer; 44 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); 45 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); 46 | } 47 | .player { 48 | -webkit-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); 49 | box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); 50 | background: #BBB; 51 | } 52 | .gs-w.try { 53 | background-image: url(../img/sprite.png); 54 | background-repeat: no-repeat; 55 | background-position: 37px -169px; 56 | } 57 | .preview-holder { 58 | border: none !important; 59 | border-radius: 0 !important; 60 | background: red !important; 61 | } 62 | ul { 63 | background-color: #EFEFEF; 64 | } 65 | li { 66 | font-size: 1em; 67 | font-weight: bold; 68 | text-align: center; 69 | line-height: 100%; 70 | } 71 | } 72 | ul { 73 | list-style-type: none; 74 | } 75 | li { 76 | list-style: none; 77 | font-weight: bold; 78 | } 79 | .gridster-box { 80 | position: relative; 81 | width: 100%; 82 | height: 100%; 83 | } 84 | .controls { 85 | margin-bottom: 20px; 86 | } 87 | -------------------------------------------------------------------------------- /demos/dynamic-grid-width.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Dynamic grid width » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

    Dynamic grid width

    14 | 15 |

    Drag or resize some widgets to the right side. Use max_cols option to set a maximum number of columns for the grid.

    16 | 17 |
    18 | 30 |
    31 | 32 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /demos/grid-from-serialize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Grid from serialize » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

    Build grid from serialized positions

    14 | 15 |

    Build a entire new grid from previously stored positions obtained with serialize method.

    16 | 17 |
    18 | 19 |
    20 | 21 |
    22 | 24 |
    25 | 26 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /demos/jquery.gridster.demo2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 24 |
    25 | 26 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /test/jquery.gridster-amd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | gridster.js AMD Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

    gridster.js AMD Test Suite

    16 |

    17 |
    18 |

    19 |
      20 |
      21 | 22 |
      23 | 49 |
      50 |
      51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /demos/sticky-postion.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » sticky position widgets » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

      Sticky position widgets

      14 | 15 |

      Widgets can be moved to an exact postion on the grid and the grid will not attempt to collapse it down to a smaller size. Also widgets will not move out of the way automatically, but will move only on mouse up

      16 | 17 | 18 |
      19 |
      33 | 34 | 35 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /demos/resize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Resize » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

      Resize

      14 | 15 |

      Grab the right or bottom border and drag to the desired width or height.

      16 | 17 |
      18 | 19 |
      20 | 21 |
      22 | 34 |
      35 | 36 | 41 | 42 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /demos/SwapDrop.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gridster Grid Swapping Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 31 |
      32 |

      Grid with larger widgets swapping spots with smaller ones

      33 |

      This demo represents using the branch in swap mode. This works best with shift_larger_widgets_down set to "false". However, smaller widgets do 34 | not displace larger ones.

      35 |
      36 |
      37 | 54 |
      55 | 56 | 57 | -------------------------------------------------------------------------------- /demos/expandable-widgets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Expandable widgets » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

      Expandable widgets

      14 | 15 |

      Expand widgets when hover on them using resize_widget method.

      16 | 17 | 18 |
      19 | 33 |
      34 | 35 | 40 | 41 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/dsmorse/gridster.js.svg)](http://travis-ci.org/dsmorse/gridster.js) 2 | [![GitHub version](https://badge.fury.io/gh/dsmorse%2Fgridster.js.svg)](http://dsmorse.github.io/gridster.js/) 3 | [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) 4 | [![Gem Version](https://badge.fury.io/rb/gridster.js-rails.svg)](https://rubygems.org/gems/gridster.js-rails) 5 | [![Bower version](https://badge.fury.io/bo/gridster-js.svg)](http://bower.io/search/?q=gridster-js) 6 | 7 | Gridster.js 8 | =========== 9 | 10 | Gridster is a jQuery plugin that makes building intuitive draggable 11 | layouts from elements spanning multiple columns. You can even 12 | dynamically add and remove elements from the grid. 13 | 14 | More at [http://gridster.net/](http://gridster.net/). 15 | 16 | ### Live Preview at: [http://dsmorse.github.io/gridster.js/](http://dsmorse.github.io/gridster.js/) 17 | 18 | [Releases](https://github.com/dsmorse/gridster.js/releases) 19 | 20 | [CHANGELOG](https://github.com/dsmorse/gridster.js/blob/master/CHANGELOG.md) 21 | 22 | Gridster was created by Ducksboard but they have basiclly abondoned the project 23 | and even those who had write permissions to the repo are not merging pull requests. 24 | 25 | ## Forks 26 | 27 | As of result of the inactivity over the last year in the [Ducksboard](https://github.com/ducksboard/gridster.js) repository, [@dsmorse](https://github.com/dsmorse/gridster.js) has created a fork 28 | for current support. He will GLADLY accept pull requests, and will be working to merge existing 29 | Pull Requests from Ducksboard repo. 30 | 31 | ## Ruby on Rails integration 32 | 33 | This artifact is published to [rubygems.org](https://rubygems.org/gems/gridster.js-rails) to be consumed by ruby on rails applications. 34 | 35 | Include gridster.js-rails in Gemfile; 36 | 37 | ``` ruby 38 | gem 'gridster.js-rails' 39 | ``` 40 | 41 | and run bundle install. 42 | 43 | ### Configuration 44 | 45 | Add this line to app/assets/stylesheets/application.css 46 | 47 | ``` css 48 | *= require jquery.gridster 49 | ``` 50 | 51 | Add this line to app/assets/javascripts/application.js 52 | 53 | ``` javascript 54 | //= require jquery.gridster 55 | ``` 56 | 57 | ## Contributing to this project 58 | 59 | Anyone and everyone is welcome to contribute. Please take a moment to review the guidelines for contributing. 60 | 61 | * [Bug reports](CONTRIBUTING.md#bugs) 62 | * [Feature requests](CONTRIBUTING.md#features) 63 | * [Pull requests](CONTRIBUTING.md#pull-requests) 64 | 65 | 66 | ## License 67 | 68 | Distributed under the MIT license. 69 | 70 | ## Whodunit 71 | 72 | Gridster is built by [Ducksboard](http://ducksboard.com/) with the help of all 73 | these [wonderful people](https://github.com/ducksboard/gridster.js/graphs/contributors). 74 | -------------------------------------------------------------------------------- /dist/jquery.gridster.min.css: -------------------------------------------------------------------------------- 1 | /*! gridster.js - v0.6.10 - 2015-08-05 - * https://dsmorse.github.io/gridster.js/ - Copyright (c) 2015 ducksboard; Licensed MIT */ 2 | .gridster{position:relative}.gridster>*{-webkit-transition:height .4s,width .4s;-moz-transition:height .4s,width .4s;-o-transition:height .4s,width .4s;-ms-transition:height .4s,width .4s;transition:height .4s,width .4s}.gridster .gs-w{z-index:2;position:absolute}.gridster .preview-holder{z-index:1;position:absolute;background-color:#fff;border-color:#fff;opacity:.3}.gridster .player-revert{z-index:10!important;-webkit-transition:left .3s,top .3s!important;-moz-transition:left .3s,top .3s!important;-o-transition:left .3s,top .3s!important;transition:left .3s,top .3s!important}.gridster.collapsed{height:auto!important}.gridster.collapsed .gs-w{position:static!important}.ready .gs-w:not(.preview-holder),.ready .resize-preview-holder{-webkit-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-moz-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-o-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;transition:opacity .3s,left .3s,top .3s,width .3s,height .3s}.gridster .dragging,.gridster .resizing{z-index:10!important;-webkit-transition:all 0s!important;-moz-transition:all 0s!important;-o-transition:all 0s!important;transition:all 0s!important}.gs-resize-handle{position:absolute;z-index:1}.gs-resize-handle-both{width:20px;height:20px;bottom:-8px;right:-8px;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=);background-position:top left;background-repeat:no-repeat;cursor:se-resize;z-index:20}.gs-resize-handle-x{top:0;bottom:13px;right:-5px;width:10px;cursor:e-resize}.gs-resize-handle-y{left:0;right:13px;bottom:-5px;height:10px;cursor:s-resize}.gs-w:hover .gs-resize-handle,.resizing .gs-resize-handle{opacity:1}.gs-resize-handle,.gs-w.dragging .gs-resize-handle{opacity:0}.gs-resize-disabled .gs-resize-handle,[data-max-sizex="1"] .gs-resize-handle-x,[data-max-sizey="1"] .gs-resize-handle-y,[data-max-sizey="1"][data-max-sizex="1"] .gs-resize-handle{display:none!important} -------------------------------------------------------------------------------- /demos/using-drag-callbacks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Using drag callbacks » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 19 | 20 | 21 | 22 | 23 |

      Drag callbacks

      24 | 25 |

      Drag some widgets and see the log below.

      26 | 27 |
      28 | 40 |
      41 | 42 |

      Log

      43 | 44 |
      45 | 46 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | (function (window, undefined) { 2 | 'use strict'; 3 | /* Delay, debounce and throttle functions taken from underscore.js 4 | * 5 | * Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and 6 | * Investigative Reporters & Editors 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | window.delay = function (func, wait) { 31 | var args = Array.prototype.slice.call(arguments, 2); 32 | return setTimeout(function () { 33 | return func.apply(null, args); 34 | }, wait); 35 | }; 36 | 37 | window.debounce = function (func, wait, immediate) { 38 | var timeout; 39 | return function () { 40 | var context = this, args = arguments; 41 | var later = function () { 42 | timeout = null; 43 | if (!immediate) { 44 | func.apply(context, args); 45 | } 46 | }; 47 | if (immediate && !timeout) { 48 | func.apply(context, args); 49 | } 50 | clearTimeout(timeout); 51 | timeout = setTimeout(later, wait); 52 | }; 53 | }; 54 | 55 | window.throttle = function (func, wait) { 56 | var context, args, timeout, throttling, more, result; 57 | var whenDone = debounce( 58 | function () { 59 | more = throttling = false; 60 | }, wait); 61 | return function () { 62 | context = this; 63 | args = arguments; 64 | var later = function () { 65 | timeout = null; 66 | if (more) { 67 | func.apply(context, args); 68 | } 69 | whenDone(); 70 | }; 71 | if (!timeout) { 72 | timeout = setTimeout(later, wait); 73 | } 74 | if (throttling) { 75 | more = true; 76 | } else { 77 | result = func.apply(context, args); 78 | } 79 | whenDone(); 80 | throttling = true; 81 | return result; 82 | }; 83 | }; 84 | 85 | })(window); 86 | -------------------------------------------------------------------------------- /demos/using-resize-callbacks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Using resize callbacks » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 19 | 20 | 21 | 22 | 23 |

      Resize callbacks

      24 | 25 |

      Resize some widgets and see the log below.

      26 | 27 | 28 |
      29 | 41 |
      42 | 43 |

      Log

      44 | 45 |
      46 | 47 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /demos/custom-drag-handle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Custom drag handle » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

      Custom drag handle

      15 | 16 |

      Restricts dragging from starting unless the mousedown occurs on the specified element(s).

      17 | 18 | 19 |
      20 | 64 |
      65 | 66 | 79 | 80 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /demos/multiple-grids.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Multiple gridster intances » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

      Multiple gridster instances with different configurations

      14 | 15 |

      When using multiple gridster instances on the same page you can scope the CSS code generated by gridster using namespace config 16 | option.

      17 | 18 |

      Demo 1

      19 | 20 |
      21 | 32 |
      33 | 34 | 35 |

      Demo 2

      36 | 37 |
      38 | 49 |
      50 | 51 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /demos/serialize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Serialize » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 28 | 29 | 30 | 31 | 32 |

      Serialize positions

      33 | 34 |

      Use serialize method to get widget positions. It returns a Array of objects that can be used as a JSON object.

      35 | 36 |
      37 | 38 |
      39 | 40 | 41 | 42 |
      43 | 67 |
      68 | 69 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /demos/resize-limits.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Resize » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

      Resize with limits

      14 | 15 |

      Use resize.max_size and resize.min_size config options or data-max-sizex, data-max-sizey, 16 | data-min-sizex and data-min-sizey HTML attributes to limit widget dimensions when resizing.

      17 | 18 |

      If a global max_size is specified through the config option, can be overwrited in specified widgets with HTML data-attributes or using set_widget_max_size 19 | method. This page has a global max limit of 4x4

      20 | 21 | 22 |
      23 | 54 |
      55 | 56 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /demos/chaosWidget.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo » Resize » gridster.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

      Resize

      15 | 16 |

      As hommage to Netflix's Chaos Monkey, this demo page is for testing. It attempts to insert a widget at a random location to ensure the overlap deconfliction locic works.

      17 | 18 |
      19 | 20 | 21 |
      22 | 23 |
      24 | 36 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
      50 | 51 | 52 | 59 | 60 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /demos/responsive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gridster Responsive Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 27 | 28 | 29 |
      30 |

      Responsive Layout

      31 |

      This demo represents using the branch in responsive mode. This makes the grid as wide as the screen and responds to changes in browser 32 | width.

      33 |
      34 |
      35 | 92 |
      93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/jquery.coords.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.coords 3 | * https://github.com/ducksboard/gridster.js 4 | * 5 | * Copyright (c) 2012 ducksboard 6 | * Licensed under the MIT licenses. 7 | */ 8 | 9 | ;(function(root, factory) { 10 | 'use strict'; 11 | if(typeof exports === 'object') { 12 | module.exports = factory(require('jquery')); 13 | } 14 | else if (typeof define === 'function' && define.amd) { 15 | define('gridster-coords', ['jquery'], factory); 16 | } else { 17 | root.GridsterCoords = factory(root.$ || root.jQuery); 18 | } 19 | 20 | }(this, function($) { 21 | 'use strict'; 22 | /** 23 | * Creates objects with coordinates (x1, y1, x2, y2, cx, cy, width, height) 24 | * to simulate DOM elements on the screen. 25 | * Coords is used by Gridster to create a faux grid with any DOM element can 26 | * collide. 27 | * 28 | * @class Coords 29 | * @param {HTMLElement|Object} obj The jQuery HTMLElement or a object with: left, 30 | * top, width and height properties. 31 | * @return {Object} Coords instance. 32 | * @constructor 33 | */ 34 | function Coords(obj) { 35 | if (obj[0] && $.isPlainObject(obj[0])) { 36 | this.data = obj[0]; 37 | }else { 38 | this.el = obj; 39 | } 40 | 41 | this.isCoords = true; 42 | this.coords = {}; 43 | this.init(); 44 | return this; 45 | } 46 | 47 | 48 | var fn = Coords.prototype; 49 | 50 | 51 | fn.init = function(){ 52 | this.set(); 53 | this.original_coords = this.get(); 54 | }; 55 | 56 | 57 | fn.set = function(update, not_update_offsets) { 58 | var el = this.el; 59 | 60 | if (el && !update) { 61 | this.data = el.offset(); 62 | this.data.width = el[0].scrollWidth; 63 | this.data.height = el[0].scrollHeight; 64 | } 65 | 66 | if (el && update && !not_update_offsets) { 67 | var offset = el.offset(); 68 | this.data.top = offset.top; 69 | this.data.left = offset.left; 70 | } 71 | 72 | var d = this.data; 73 | 74 | if ( d.left === undefined ) { 75 | d.left = d.x1; 76 | } 77 | 78 | if ( d.top === undefined ) { 79 | d.top = d.y1; 80 | } 81 | 82 | this.coords.x1 = d.left; 83 | this.coords.y1 = d.top; 84 | this.coords.x2 = d.left + d.width; 85 | this.coords.y2 = d.top + d.height; 86 | this.coords.cx = d.left + (d.width / 2); 87 | this.coords.cy = d.top + (d.height / 2); 88 | this.coords.width = d.width; 89 | this.coords.height = d.height; 90 | this.coords.el = el || false ; 91 | 92 | return this; 93 | }; 94 | 95 | 96 | fn.update = function(data){ 97 | if (!data && !this.el) { 98 | return this; 99 | } 100 | 101 | if (data) { 102 | var new_data = $.extend({}, this.data, data); 103 | this.data = new_data; 104 | return this.set(true, true); 105 | } 106 | 107 | this.set(true); 108 | return this; 109 | }; 110 | 111 | 112 | fn.get = function(){ 113 | return this.coords; 114 | }; 115 | 116 | fn.destroy = function() { 117 | this.el.removeData('coords'); 118 | delete this.el; 119 | }; 120 | 121 | //jQuery adapter 122 | $.fn.coords = function() { 123 | if (this.data('coords') ) { 124 | return this.data('coords'); 125 | } 126 | 127 | var ins = new Coords(this); 128 | this.data('coords', ins); 129 | return ins; 130 | }; 131 | 132 | return Coords; 133 | 134 | })); 135 | -------------------------------------------------------------------------------- /src/jquery.gridster.less: -------------------------------------------------------------------------------- 1 | /*! gridster.js - v0.6.10 - 2015-05-31 2 | * https://dsmorse.github.io/gridster.js/ 3 | * Copyright (c) 2015 ducksboard; Licensed MIT */ 4 | 5 | .gridster { 6 | position:relative; 7 | & > * { 8 | -webkit-transition: height .4s, width .4s; 9 | -moz-transition: height .4s, width .4s; 10 | -o-transition: height .4s, width .4s; 11 | -ms-transition: height .4s, width .4s; 12 | transition: height .4s, width .4s; 13 | } 14 | .gs-w { 15 | z-index: 2; 16 | position: absolute; 17 | } 18 | .preview-holder { 19 | z-index: 1; 20 | position: absolute; 21 | background-color: #fff; 22 | border-color: #fff; 23 | opacity: 0.3; 24 | } 25 | .player-revert { 26 | z-index: 10!important; 27 | -webkit-transition: left .3s, top .3s!important; 28 | -moz-transition: left .3s, top .3s!important; 29 | -o-transition: left .3s, top .3s!important; 30 | transition: left .3s, top .3s!important; 31 | } 32 | } 33 | .gridster.collapsed { 34 | height: auto !important; 35 | .gs-w { 36 | position: static !important; 37 | } 38 | } 39 | .ready { 40 | .gs-w:not(.preview-holder) { 41 | -webkit-transition: opacity .3s, left .3s, top .3s; 42 | -moz-transition: opacity .3s, left .3s, top .3s; 43 | -o-transition: opacity .3s, left .3s, top .3s; 44 | transition: opacity .3s, left .3s, top .3s; 45 | } 46 | } 47 | .ready .gs-w:not(.preview-holder),.ready .resize-preview-holder { 48 | -webkit-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 49 | -moz-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 50 | -o-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 51 | transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 52 | } 53 | .gridster .dragging,.gridster .resizing { 54 | z-index: 10!important; 55 | -webkit-transition: all 0s !important; 56 | -moz-transition: all 0s !important; 57 | -o-transition: all 0s !important; 58 | transition: all 0s !important; 59 | } 60 | .gs-resize-handle { 61 | position: absolute; 62 | z-index: 1; 63 | } 64 | .gs-resize-handle-both { 65 | width: 20px; 66 | height: 20px; 67 | bottom: -8px; 68 | right: -8px; 69 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4='); 70 | background-position: top left; 71 | background-repeat: no-repeat; 72 | cursor: se-resize; 73 | z-index: 20; 74 | } 75 | .gs-resize-handle-x { 76 | top: 0; 77 | bottom: 13px; 78 | right: -5px; 79 | width: 10px; 80 | cursor: e-resize; 81 | } 82 | .gs-resize-handle-y { 83 | left: 0; 84 | right: 13px; 85 | bottom: -5px; 86 | height: 10px; 87 | cursor: s-resize; 88 | } 89 | .gs-w:hover .gs-resize-handle,.resizing .gs-resize-handle { 90 | opacity: 1; 91 | } 92 | .gs-resize-handle,.gs-w.dragging .gs-resize-handle { 93 | opacity: 0; 94 | } 95 | .gs-resize-disabled { 96 | .gs-resize-handle { 97 | display: none!important; 98 | } 99 | } 100 | [data-max-sizex="1"] .gs-resize-handle-x,[data-max-sizey="1"] .gs-resize-handle-y,[data-max-sizey="1"][data-max-sizex="1"] .gs-resize-handle { 101 | display: none !important; 102 | } 103 | 104 | /* Uncomment this if you set helper : "clone" in draggable options */ 105 | /*.gridster .player { 106 | opacity:0; 107 | } 108 | */ -------------------------------------------------------------------------------- /dist/jquery.gridster.css: -------------------------------------------------------------------------------- 1 | /*! gridster.js - v0.6.10 - 2015-05-31 2 | * https://dsmorse.github.io/gridster.js/ 3 | * Copyright (c) 2015 ducksboard; Licensed MIT */ 4 | .gridster { 5 | position: relative; 6 | } 7 | .gridster > * { 8 | -webkit-transition: height .4s, width .4s; 9 | -moz-transition: height .4s, width .4s; 10 | -o-transition: height .4s, width .4s; 11 | -ms-transition: height .4s, width .4s; 12 | transition: height .4s, width .4s; 13 | } 14 | .gridster .gs-w { 15 | z-index: 2; 16 | position: absolute; 17 | } 18 | .gridster .preview-holder { 19 | z-index: 1; 20 | position: absolute; 21 | background-color: #fff; 22 | border-color: #fff; 23 | opacity: 0.3; 24 | } 25 | .gridster .player-revert { 26 | z-index: 10!important; 27 | -webkit-transition: left .3s, top .3s!important; 28 | -moz-transition: left .3s, top .3s!important; 29 | -o-transition: left .3s, top .3s!important; 30 | transition: left .3s, top .3s!important; 31 | } 32 | .gridster.collapsed { 33 | height: auto !important; 34 | } 35 | .gridster.collapsed .gs-w { 36 | position: static !important; 37 | } 38 | .ready .gs-w:not(.preview-holder) { 39 | -webkit-transition: opacity .3s, left .3s, top .3s; 40 | -moz-transition: opacity .3s, left .3s, top .3s; 41 | -o-transition: opacity .3s, left .3s, top .3s; 42 | transition: opacity .3s, left .3s, top .3s; 43 | } 44 | .ready .gs-w:not(.preview-holder), 45 | .ready .resize-preview-holder { 46 | -webkit-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 47 | -moz-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 48 | -o-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 49 | transition: opacity .3s, left .3s, top .3s, width .3s, height .3s; 50 | } 51 | .gridster .dragging, 52 | .gridster .resizing { 53 | z-index: 10!important; 54 | -webkit-transition: all 0s !important; 55 | -moz-transition: all 0s !important; 56 | -o-transition: all 0s !important; 57 | transition: all 0s !important; 58 | } 59 | .gs-resize-handle { 60 | position: absolute; 61 | z-index: 1; 62 | } 63 | .gs-resize-handle-both { 64 | width: 20px; 65 | height: 20px; 66 | bottom: -8px; 67 | right: -8px; 68 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4='); 69 | background-position: top left; 70 | background-repeat: no-repeat; 71 | cursor: se-resize; 72 | z-index: 20; 73 | } 74 | .gs-resize-handle-x { 75 | top: 0; 76 | bottom: 13px; 77 | right: -5px; 78 | width: 10px; 79 | cursor: e-resize; 80 | } 81 | .gs-resize-handle-y { 82 | left: 0; 83 | right: 13px; 84 | bottom: -5px; 85 | height: 10px; 86 | cursor: s-resize; 87 | } 88 | .gs-w:hover .gs-resize-handle, 89 | .resizing .gs-resize-handle { 90 | opacity: 1; 91 | } 92 | .gs-resize-handle, 93 | .gs-w.dragging .gs-resize-handle { 94 | opacity: 0; 95 | } 96 | .gs-resize-disabled .gs-resize-handle { 97 | display: none!important; 98 | } 99 | [data-max-sizex="1"] .gs-resize-handle-x, 100 | [data-max-sizey="1"] .gs-resize-handle-y, 101 | [data-max-sizey="1"][data-max-sizex="1"] .gs-resize-handle { 102 | display: none !important; 103 | } 104 | /* Uncomment this if you set helper : "clone" in draggable options */ 105 | /*.gridster .player { 106 | opacity:0; 107 | } 108 | */ 109 | /*# sourceMappingURL=dist/jquery.gridster.css.map */ -------------------------------------------------------------------------------- /src/jquery.gridster.extras.js: -------------------------------------------------------------------------------- 1 | ;(function(root, factory) { 2 | 'use strict'; 3 | if(typeof exports === 'object') { 4 | module.exports = factory(require('jquery'), require('./jquery.gridster.js')); 5 | } 6 | else if (typeof define === 'function' && define.amd) { 7 | define(['jquery', 'gridster'], factory); 8 | } else { 9 | root.Gridster = factory(root.$ || root.jQuery, root.Gridster); 10 | } 11 | 12 | }(this, function($, Gridster) { 13 | 'use strict'; 14 | var fn = Gridster.prototype; 15 | 16 | fn.widgets_in_col = function(col) { 17 | if (!this.gridmap[col]) { 18 | return false; 19 | } 20 | 21 | for (var i = this.gridmap[col].length - 1; i >= 0; i--) { 22 | if (this.is_widget(col, i) !== false) { 23 | return true; 24 | } 25 | } 26 | 27 | return false; 28 | }; 29 | 30 | fn.widgets_in_row = function(row) { 31 | for (var i = this.gridmap.length; i >= 1; i--) { 32 | if (this.is_widget(i, row) !== false) { 33 | return true; 34 | } 35 | } 36 | 37 | return false; 38 | }; 39 | 40 | fn.get_bottom_most_occupied_cell = function() { 41 | var row = 0; 42 | var col = 0; 43 | this.for_each_cell(function($el, c, r) { 44 | if ($el && r > row) { 45 | row = r; 46 | col = c; 47 | } 48 | }); 49 | 50 | return {col: col, row: row}; 51 | }; 52 | 53 | 54 | fn.get_right_most_occupied_cell = function() { 55 | var row = 0; 56 | var col = 0; 57 | this.for_each_cell(function($el, c, r) { 58 | if ($el) { 59 | row = r; 60 | col = c; 61 | return false; 62 | } 63 | }); 64 | 65 | return {col: col, row: row}; 66 | }; 67 | 68 | 69 | fn.for_each_cell = function(callback, gridmap) { 70 | gridmap || (gridmap = this.gridmap); 71 | var cols = gridmap.length; 72 | var rows = gridmap[1].length; 73 | 74 | cols_iter: 75 | for (var c = cols - 1; c >= 1; c--) { 76 | for (var r = rows - 1; r >= 1; r--) { 77 | var $el = gridmap[c] && gridmap[c][r]; 78 | if (callback) { 79 | if (callback.call(this, $el, c, r) === false) { 80 | break cols_iter; 81 | } else { continue; } 82 | } 83 | } 84 | } 85 | }; 86 | 87 | 88 | fn.next_position_in_range = function(size_x, size_y) { 89 | size_x || (size_x = 1); 90 | size_y || (size_y = 1); 91 | var ga = this.gridmap; 92 | var cols_l = ga.length; 93 | var valid_pos = []; 94 | var rows_l; 95 | 96 | for (var c = 1; c < cols_l; c++) { 97 | rows_l = this.options.max_rows || ga[c].length; 98 | for (var r = 1; r <= rows_l; r++) { 99 | var can_move_to = this.can_move_to({ 100 | size_x: size_x, 101 | size_y: size_y 102 | }, c, r); 103 | 104 | if (can_move_to) { 105 | valid_pos.push({ 106 | col: c, 107 | row: r, 108 | size_y: size_y, 109 | size_x: size_x 110 | }); 111 | } 112 | } 113 | } 114 | 115 | if (valid_pos.length >= 1) { 116 | return Gridster.sort_by_col_asc(valid_pos)[0]; 117 | } 118 | 119 | return false; 120 | }; 121 | 122 | 123 | fn.closest_to_right = function(col, row) { 124 | if (!this.gridmap[col]) { return false; } 125 | var cols_l = this.gridmap.length - 1; 126 | 127 | for (var c = col; c <= cols_l; c++) { 128 | if (this.gridmap[c][row]) { 129 | return { col: c, row: row }; 130 | } 131 | } 132 | 133 | return false; 134 | }; 135 | 136 | 137 | fn.closest_to_left = function(col, row) { 138 | if (!this.gridmap[col]) { return false; } 139 | 140 | for (var c = col; c >= 1; c--) { 141 | if (this.gridmap[c][row]) { 142 | return { col: c, row: row }; 143 | } 144 | } 145 | 146 | return false; 147 | }; 148 | 149 | return Gridster; 150 | 151 | })); 152 | -------------------------------------------------------------------------------- /test/lib/test_utils.js: -------------------------------------------------------------------------------- 1 | /* global u, SPEED*/ 2 | 3 | 'use strict'; 4 | 5 | window.serialization = { 6 | 'default': function() { 7 | return [ 8 | {name: 'A', col: 1, row: 1, size_x: 1, size_y: 2}, 9 | {name: 'B', col: 2, row: 1, size_x: 3, size_y: 2}, 10 | {name: 'C', col: 5, row: 1, size_x: 3, size_y: 2}, 11 | {name: 'D', col: 8, row: 1, size_x: 2, size_y: 1}, 12 | {name: 'E', col: 1, row: 3, size_x: 4, size_y: 1}, 13 | {name: 'F', col: 10, row: 1, size_x: 1, size_y: 2}, 14 | {name: 'G', col: 8, row: 2, size_x: 2, size_y: 1}, 15 | {name: 'H', col: 5, row: 3, size_x: 3, size_y: 2}, 16 | {name: 'I', col: 8, row: 3, size_x: 1, size_y: 1}, 17 | {name: 'J', col: 9, row: 3, size_x: 2, size_y: 2}, 18 | {name: 'K', col: 1, row: 4, size_x: 1, size_y: 3} 19 | ]; 20 | } 21 | }; 22 | 23 | 24 | window.u = { 25 | pick: function(data, prop) { 26 | return data.map(function(elm) { 27 | return elm[prop]; 28 | }); 29 | }, 30 | 31 | getRandomColor: function() { 32 | var letters = '0123456789ABCDEF'.split(''); 33 | var color = '#'; 34 | for (var i = 0; i < 6; i++) { 35 | color += letters[Math.round(Math.random() * 10)]; 36 | } 37 | return color; 38 | }, 39 | 40 | createGridster: function(config, serialize, fromDom) { 41 | var defaults = { 42 | widget_margins: [5, 5], 43 | widget_base_dimensions: [100, 55], 44 | min_cols: 10, 45 | max_cols: 10 46 | }; 47 | 48 | serialize || (serialize = window.serialization.default()); 49 | 50 | var widgets = []; 51 | $.each(serialize, function(i, w) { 52 | widgets.push(['
    1. ' + w.name + '
    2. ', w.size_x, w.size_y, w.col, w.row]); 53 | }); 54 | 55 | this.$fixture = $('#fixture'); 56 | this.$fixture.html('
      '); 57 | this.$el = $('.gridster > ul'); 58 | 59 | if (fromDom) { 60 | var html = []; 61 | $.each(serialize, function(i, w) { 62 | html.push('
    3. ' + w.name + '
    4. '); 63 | }); 64 | this.$el.html(html.join('\n')); 65 | } 66 | 67 | this.gridster = this.$el.gridster( 68 | $.extend({}, defaults, config)).data('gridster'); 69 | 70 | if (!fromDom) { 71 | $.each(widgets, function(i, widget) { 72 | this.gridster.add_widget.apply(this.gridster, widget); 73 | }.bind(this)); 74 | } 75 | 76 | this.drag_from_to = u._dragFromTo; 77 | 78 | return this.gridster; 79 | }, 80 | 81 | createEvent: function(type, offset) { 82 | var event = document.createEvent('MouseEvents'); 83 | event.initMouseEvent(type, true, true, window, 0, 0, 0, 84 | offset.left, offset.top, false, false, false, false, 0, null); 85 | 86 | return event; 87 | }, 88 | 89 | dispatchEvent: function(elem, type, event) { 90 | if (elem.dispatchEvent) { 91 | elem.dispatchEvent(event); 92 | } else if (elem.fireEvent) { 93 | elem.fireEvent('on' + type, event); 94 | } 95 | }, 96 | 97 | _dragFromTo: function(fromCoords, toCoords) { 98 | var d = $.Deferred(); 99 | var gridster = this.gridster; 100 | var $el; 101 | 102 | function getMousePos(coords) { 103 | var size = gridster.options.widget_base_dimensions; 104 | var margin = gridster.options.widget_margins; 105 | 106 | var left = ((coords[0] - 1) * size[0]) + (margin[0] * ((coords[0] * 2) - 1)); 107 | var top = ((coords[1] - 1) * size[1]) + (margin[1] * ((coords[1] * 2) - 1)); 108 | 109 | var parentOffset = gridster.$wrapper.offset(); 110 | 111 | return { 112 | left: parentOffset.left + left + 20, 113 | top: parentOffset.top + top + 20 114 | }; 115 | } 116 | 117 | function addPoint(offset) { 118 | $('').css({ 119 | left: offset.left + 'px', 120 | top: offset.top + 'px', 121 | width: '2px', 122 | height: '2px', 123 | background: 'red', 124 | display: 'inline-block', 125 | position: 'absolute', 126 | zIndex: '9999' 127 | }).appendTo('body'); 128 | } 129 | 130 | var from_offset; 131 | 132 | if (fromCoords instanceof $) { 133 | $el = fromCoords; 134 | var offset = $el.offset(); 135 | from_offset = { 136 | left: offset.left + ($el.width() / 2), 137 | top: offset.top + ($el.height() / 2) 138 | }; 139 | } else { 140 | $el = this.gridster.gridmap[fromCoords[0]][fromCoords[1]]; 141 | from_offset = getMousePos(fromCoords); 142 | } 143 | 144 | if (! $el) { 145 | return; 146 | } 147 | 148 | var to_offset = getMousePos(toCoords); 149 | var el = $el.get(0); 150 | 151 | addPoint(from_offset); 152 | addPoint(to_offset); 153 | 154 | // Simulating drag start 155 | var type = 'mousedown'; 156 | var event = u.createEvent(type, from_offset); 157 | u.dispatchEvent(el, type, event); 158 | 159 | // Simulating drop 160 | type = 'mousemove'; 161 | u.dispatchEvent(el, type, u.createEvent(type, { 162 | top: from_offset.top + 2, 163 | left: from_offset.left + 2 164 | })); 165 | 166 | this.gridster.$el.on('gridster:dragstop gridster:resizestop', function() { 167 | setTimeout(function() { 168 | d.resolveWith(this); 169 | }.bind(this), SPEED); 170 | }.bind(this)); 171 | 172 | var diff_x = to_offset.left - from_offset.left; 173 | var diff_y = to_offset.top - from_offset.top; 174 | var steps = 10; 175 | var step_x = diff_x / steps; 176 | var step_y = diff_y / steps; 177 | 178 | var tmp_offset = { 179 | left: from_offset.left, 180 | top: from_offset.top 181 | }; 182 | 183 | for (var i = 0; i < steps; i++) { 184 | tmp_offset.left += step_x; 185 | tmp_offset.top += step_y; 186 | addPoint(tmp_offset); 187 | u.dispatchEvent(el, type, u.createEvent(type, tmp_offset)); 188 | } 189 | 190 | u.dispatchEvent(el, type, u.createEvent(type, to_offset)); 191 | addPoint(to_offset); 192 | 193 | // Simulating drag end 194 | type = 'mouseup'; 195 | var dragEndEvent = u.createEvent(type, to_offset); 196 | u.dispatchEvent(el, type, dragEndEvent); 197 | 198 | return d.promise(); 199 | } 200 | }; 201 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | 4 | 'use strict'; 5 | // Project configuration. 6 | grunt.initConfig({ 7 | pkg: grunt.file.readJSON('package.json'), 8 | meta: { 9 | banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + 10 | '<%= grunt.template.today("yyyy-mm-dd") %>\n' + 11 | '<%= pkg.homepage ? "* " + pkg.homepage : "" %>\n' + 12 | '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 13 | ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n\n', 14 | 15 | minibanner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + 16 | '<%= grunt.template.today("yyyy-mm-dd") %> - ' + 17 | '<%= pkg.homepage ? "* " + pkg.homepage + " - " : "" %>' + 18 | 'Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 19 | ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */ ' 20 | }, 21 | concat: { 22 | options: { 23 | stripBanners: true, 24 | banner: '<%= meta.banner %>' 25 | }, 26 | dist_js: { 27 | src: ['src/jquery.coords.js', 'src/jquery.collision.js', 'src/utils.js', 'src/jquery.draggable.js', 'src/jquery.<%= pkg.name %>.js'], 28 | dest: 'dist/jquery.<%= pkg.name %>.js' 29 | }, 30 | 31 | dist_extras_js: { 32 | src: ['src/jquery.coords.js', 'src/jquery.collision.js', 'src/utils.js', 'src/jquery.draggable.js', 'src/jquery.<%= pkg.name %>.js', 'src/jquery.<%= pkg.name %>.extras.js'], 33 | dest: 'dist/jquery.<%= pkg.name %>.with-extras.js' 34 | } 35 | }, 36 | uglify: { 37 | options: { 38 | banner: '<%= meta.minibanner %>' 39 | }, 40 | dist: { 41 | files: { 42 | 'dist/jquery.<%= pkg.name %>.min.js': ['<%= concat.dist_js.dest %>'] 43 | } 44 | }, 45 | 46 | dist_extras: { 47 | files: { 48 | 'dist/jquery.<%= pkg.name %>.with-extras.min.js': ['<%= concat.dist_extras_js.dest %>'] 49 | } 50 | } 51 | }, 52 | cssmin: { 53 | compress: { 54 | options: { 55 | keepSpecialComments: 0, 56 | banner: '<%= meta.minibanner %>' 57 | }, 58 | files: { 59 | 'dist/jquery.<%= pkg.name %>.min.css': ['dist/jquery.<%= pkg.name %>.css'] 60 | } 61 | } 62 | }, 63 | jshint: { 64 | options: { 65 | verbose: true, 66 | reporter: require('jshint-stylish'), 67 | jshintrc: '.jshintrc' 68 | }, 69 | files: ['GruntFile.js', 'src/**/*.js','sample/**/*.js', 'test/**/*.js'] 70 | }, 71 | yuidoc: { 72 | compile: { 73 | 'name': 'gridster.js', 74 | 'description': 'gridster.js, a drag-and-drop multi-column jQuery grid plugin', 75 | 'version': 'v<%= pkg.version %>', 76 | 'url': 'http://gridster.net/', 77 | 'logo': 'https://ducksboard.com/static/images/svg/logo-ducksboard-black-small.svg', 78 | options: { 79 | paths: 'src/', 80 | outdir: 'gh-pages/docs/' 81 | } 82 | } 83 | }, 84 | replace: { 85 | 'rails-version': { 86 | src: ['lib/gridster.js-rails/version.rb'], 87 | dest: 'lib/gridster.js-rails/version.rb', 88 | replacements: [{ 89 | from: /(\S*)(VERSION = ).*/g, 90 | to: '$1$2"<%= pkg.version %>"' 91 | }] 92 | } 93 | }, 94 | copy: { 95 | dist: { 96 | files: [{ 97 | expand: true, 98 | dest: 'gh-pages/', 99 | src: ['dist/*', 'demos/**'] 100 | },{ 101 | expand: true, 102 | dest: 'dist', 103 | src: ['src/jquery.gridster.less'] 104 | }] 105 | }, 106 | rails: { 107 | files: [{ 108 | expand: true, 109 | flatten: true, 110 | dest: 'vendor/assets/javascripts/', 111 | src: ['dist/*.js'] 112 | }, { 113 | expand: true, 114 | flatten: true, 115 | dest: 'vendor/assets/stylesheets/', 116 | src: ['dist/*.css'] 117 | }] 118 | } 119 | }, 120 | shell: { 121 | 'build-rails-gem': { 122 | command: 'gem build gridster.js-rails.gemspec' 123 | }, 124 | 'publish-rails-gem': { 125 | command: 'gem push gridster.js-rails-<%= pkg.version %>.gem' 126 | } 127 | }, 128 | 'gh-pages': { 129 | target: { 130 | options: { 131 | message: 'update docs for changes from v<%= pkg.version %> ', 132 | base: 'gh-pages', 133 | add: true, 134 | push: true 135 | }, 136 | src: '**' 137 | } 138 | }, 139 | bump: { 140 | options: { 141 | files: ['package.json', 'bower.json'], 142 | updateConfigs: ['pkg'], 143 | commit: true, 144 | commitMessage: 'Release v%VERSION%', 145 | commitFiles: ['package.json', 'bower.json', 'CHANGELOG.md', 'dist/'], // '-a' for all files 146 | createTag: true, 147 | tagName: 'v%VERSION%', 148 | tagMessage: 'Version %VERSION%', 149 | push: false, 150 | pushTo: 'origin', 151 | gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe' 152 | } 153 | }, 154 | clean: { 155 | dist: [ 156 | 'gridster.js-rails*.gem', 157 | '.grunt', 158 | 'gh-pages', 159 | 'dist', 160 | 'vendor' 161 | ] 162 | }, 163 | changelog: { 164 | options: { 165 | dest: 'CHANGELOG.md' 166 | } 167 | }, 168 | watch: { 169 | files: ['libs/*.js', 'src/*.js', 'src/*.less', 'Gruntfile.js'], 170 | tasks: ['concat', 'uglify', 'less', 'cssmin'] 171 | }, 172 | qunit: { 173 | files: [ 174 | 'test/jquery.gridster.html' 175 | ] 176 | }, 177 | less: { 178 | default: { 179 | options: { 180 | sourceMap: true, 181 | sourceMapFilename: 'dist/jquery.gridster.css.map' 182 | }, 183 | files: { 184 | 'dist/jquery.gridster.css': 'src/jquery.gridster.less' 185 | } 186 | }, 187 | demo: { 188 | options: { 189 | sourceMap: true, 190 | sourceMapFilename: 'demos/assets/css/demo.css.map' 191 | }, 192 | files: { 193 | 'demos/assets/css/demo.css': 'demos/assets/less/demo.less' 194 | } 195 | } 196 | } 197 | }); 198 | 199 | grunt.loadNpmTasks('grunt-contrib-clean'); 200 | grunt.loadNpmTasks('grunt-contrib-copy'); 201 | grunt.loadNpmTasks('grunt-contrib-watch'); 202 | grunt.loadNpmTasks('grunt-contrib-jshint'); 203 | grunt.loadNpmTasks('grunt-contrib-concat'); 204 | grunt.loadNpmTasks('grunt-contrib-less'); 205 | grunt.loadNpmTasks('grunt-contrib-uglify'); 206 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 207 | grunt.loadNpmTasks('grunt-contrib-qunit'); 208 | grunt.loadNpmTasks('grunt-contrib-yuidoc'); 209 | grunt.loadNpmTasks('grunt-bump'); 210 | grunt.loadNpmTasks('grunt-conventional-changelog'); 211 | grunt.loadNpmTasks('grunt-gh-pages'); 212 | grunt.loadNpmTasks('grunt-text-replace'); 213 | grunt.loadNpmTasks('grunt-shell'); 214 | 215 | // Default task. 216 | grunt.registerTask('default', ['jshint', 'concat', 'less', 'uglify', 'cssmin', 'replace:rails-version', 'copy:rails']); 217 | grunt.registerTask('build', ['default', 'qunit', 'shell:build-rails-gem']); 218 | grunt.registerTask('test', ['jshint','qunit']); 219 | grunt.registerTask('docs', ['clean', 'build', 'yuidoc', 'copy:dist', 'gh-pages']); 220 | 221 | //builds and releases the gem files 222 | grunt.registerTask('rails:publish', ['clean', 'build', 'shell:publish-rails-gem']); 223 | 224 | //use one of the four release tasks to build the artifacts for the release (it will push the docs pages only) 225 | grunt.registerTask('release:patch', ['build', 'bump-only:patch', 'build', 'docs', 'changelog']); 226 | grunt.registerTask('release:minor', ['build', 'bump-only:minor', 'build', 'docs', 'changelog']); 227 | grunt.registerTask('release:major', ['build', 'bump-only:major', 'build', 'docs', 'changelog']); 228 | grunt.registerTask('release:git', ['build', 'bump-only:git', 'build', 'docs', 'changelog']); 229 | 230 | //use this task to publish the release artifacts 231 | grunt.registerTask('release:commit', ['bump-commit', 'shell:publish-rails-gem']); 232 | 233 | }; 234 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // http://www.jshint.com/docs/ 3 | // Based on node-jshint@2.x.x 4 | 5 | // ENFORCING OPTIONS 6 | // These options tell JSHint to be more strict towards your code. Use them if 7 | // you want to allow only a safe subset of JavaScript—very useful when your 8 | // codebase is shared with a big number of developers with different skill 9 | // levels. 10 | 11 | "bitwise": true, //prohibits the use of bitwise operators such as ^ (XOR), | (OR) and others 12 | "camelcase": false, //force all variable names to use either camelCase style or UPPER_CASE with underscores 13 | "curly": true, //requires you to always put curly braces around blocks in loops and conditionals 14 | "eqeqeq": true, //prohibits the use of == and != in favor of === and !== 15 | "es3": false, //tells JSHint that your code needs to adhere to ECMAScript 3 specification 16 | "forin": false, //requires all `for in` loops to filter object's items with `hasOwnProperty()` 17 | "immed": true, //prohibits the use of immediate function invocations without wrapping them in parentheses 18 | "indent": 2, //enforces specific tab width 19 | "latedef": true, //prohibits the use of a variable before it was defined 20 | "newcap": true, //requires you to capitalize names of constructor functions 21 | "noarg": true, //prohibits the use of `arguments.caller` and `arguments.callee` 22 | "noempty": true, //warns when you have an empty block in your code 23 | "nonew": true, //prohibits the use of constructor functions for side-effects 24 | "plusplus": false, //prohibits the use of unary increment and decrement operators 25 | "quotmark": true, //enforces the consistency of quotation marks used throughout your code 26 | "undef": true, //prohibits the use of explicitly undeclared variables 27 | "unused": "vars", //warns when you define and never use your variables 28 | "strict": true, //requires all functions to run in ECMAScript 5's strict mode 29 | "trailing": true, //makes it an error to leave a trailing whitespace in your code 30 | "maxparams": false, //set the max number of formal parameters allowed per function 31 | "maxdepth": 6, //control how nested do you want your blocks to be 32 | "maxstatements": false, //set the max number of statements allowed per function 33 | "maxcomplexity": false, //control cyclomatic complexity throughout your code 34 | 35 | // RELAXING OPTIONS 36 | // These options allow you to suppress certain types of warnings. Use them 37 | // only if you are absolutely positive that you know what you are doing. 38 | 39 | "asi": false, //suppresses warnings about missing semicolons 40 | "boss": false, //suppresses warnings about the use of assignments in cases where comparisons are expected 41 | "debug": false, //suppresses warnings about the debugger statements in your code 42 | "eqnull": false, //suppresses warnings about == null comparisons 43 | "esnext": false, //your code uses ES.next specific features such as const 44 | "evil": false, //suppresses warnings about the use of eval 45 | "expr": true, //suppresses warnings about the use of expressions where normally you would expect to see assignments or function calls 46 | "funcscope": false, //suppresses warnings about declaring variables inside of control structures while accessing them later from the outside 47 | "globalstrict": false, //suppresses warnings about the use of global strict mode 48 | "iterator": false, //suppresses warnings about the `__iterator__` property 49 | "lastsemic": false, //suppresses warnings about missing semicolons, but only when the semicolon is omitted for the last statement in a one-line block 50 | "laxbreak": false, //suppresses most of the warnings about possibly unsafe line breakings in your code 51 | "laxcomma": false, //suppresses warnings about comma-first coding style 52 | "loopfunc": false, //suppresses warnings about functions inside of loops 53 | "moz": false, //tells JSHint that your code uses Mozilla JavaScript extensions 54 | "multistr": false, //suppresses warnings about multi-line strings 55 | "proto": false, //suppresses warnings about the `__proto__` property 56 | "scripturl": false, //suppresses warnings about the use of script-targeted URLs—such as `javascript:...` 57 | "smarttabs": false, //suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only 58 | "shadow": false, //suppresses warnings about variable shadowing 59 | "sub": false, //suppresses warnings about using `[]` notation when it can be expressed in dot notation 60 | "supernew": false, //suppresses warnings about "weird" constructions like `new function () { ... }` and `new Object;` 61 | "validthis": false, //suppresses warnings about possible strict violations when the code is running in strict mode and you use `this` in a non-constructor function 62 | 63 | // ENVIRONMENTS 64 | // These options pre-define global variables that are exposed by popular 65 | // JavaScript libraries and runtime environments—such as browser or node.js. 66 | // Essentially they are shortcuts for explicit declarations like 67 | // /*global $:false, jQuery:false */ 68 | 69 | "browser": true, //defines globals exposed by modern browsers 70 | "couch": false, //defines globals exposed by CouchDB 71 | "devel": true, //defines globals that are usually used for logging poor-man's debugging: `console`, `alert`, etc. 72 | "dojo": false, //defines globals exposed by the Dojo Toolkit 73 | "jquery": true, //defines globals exposed by the jQuery JavaScript library 74 | "mootools": false, //defines globals exposed by the MooTools JavaScript framework 75 | "node": true, //defines globals available when your code is running inside of the Node runtime environment 76 | "nonstandard": false, //defines non-standard but widely adopted globals such as `escape` and `unescape` 77 | "phantom": false, //defines globals available when your core is running inside of the PhantomJS runtime environment 78 | "qunit": true, //defines globals available when your core is running inside of the Qqunit runtime environment 79 | "prototypejs": false, //defines globals exposed by the Prototype JavaScript framework 80 | "rhino": false, //defines globals available when your code is running inside of the Rhino runtime environment 81 | "worker": true, //defines globals available when your code is running inside of a Web Worker 82 | "wsh": false, //defines globals available when your code is running as a script for the Windows Script Host 83 | "yui": false, //defines globals exposed by the YUI JavaScript framework 84 | 85 | "globals": { 86 | "define": false, 87 | "throttle": false, 88 | "delay": false, 89 | "debounce": false, 90 | "jQuery": true, 91 | "require": false, 92 | "Gridster": false 93 | }, 94 | 95 | // LEGACY 96 | // These options are legacy from JSLint. Aside from bug fixes they will not 97 | // be improved in any way and might be removed at any point. 98 | 99 | "nomen": false, //disallows the use of dangling `_` in variables 100 | "onevar": false, //allows only one `var` statement per function 101 | "passfail": false, //makes JSHint stop on the first error or warning 102 | "white": false //make JSHint check your source code against Douglas Crockford's JavaScript coding style 103 | } 104 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this project 2 | 3 | Please take a moment to review this document in order to make the contribution 4 | process easy and effective for everyone involved. 5 | 6 | Following these guidelines helps to communicate that you respect the time of 7 | the developers managing and developing this open source project. In return, 8 | they should reciprocate that respect in addressing your issue or assessing 9 | patches and features. 10 | 11 | 12 | ## Using the issue tracker 13 | 14 | The issue tracker is the preferred channel for [bug reports](#bugs), 15 | [features requests](#features) and [submitting pull 16 | requests](#pull-requests), but please respect the following restrictions: 17 | 18 | * Please **do not** use the issue tracker for personal support requests (use 19 | [Stack Overflow](http://stackoverflow.com)). 20 | 21 | * Please **do not** derail or troll issues. Keep the discussion on topic and 22 | respect the opinions of others. 23 | 24 | 25 | 26 | ## Bug reports 27 | 28 | A bug is a _demonstrable problem_ that is caused by the code in the repository. 29 | Good bug reports are extremely helpful - thank you! 30 | 31 | Guidelines for bug reports: 32 | 33 | 1. **Use the GitHub issue search** — check if the issue has already been 34 | reported. 35 | 36 | 2. **Check if the issue has been fixed** — try to reproduce it using the 37 | latest `master` or development branch in the repository. 38 | 39 | 3. **Isolate the problem** — ideally create a [reduced test 40 | case](http://css-tricks.com/6263-reduced-test-cases/) and a live example (you can use something like [jsfiddle](http://jsfiddle.net/) or [jsbin](http://jsbin.com/)) . 41 | 42 | A good bug report shouldn't leave others needing to chase you up for more 43 | information. Please try to be as detailed as possible in your report. What is 44 | your environment? What steps will reproduce the issue? What browser(s) and OS 45 | experience the problem? What would you expect to be the outcome? All these 46 | details will help people to fix any potential bugs. 47 | 48 | Example: 49 | 50 | > Short and descriptive example bug report title 51 | > 52 | > A summary of the issue and the browser/OS environment in which it occurs. If 53 | > suitable, include the steps required to reproduce the bug. 54 | > 55 | > 1. This is the first step 56 | > 2. This is the second step 57 | > 3. Further steps, etc. 58 | > 59 | > `` - a link to the reduced test case 60 | > 61 | > Any other information you want to share that is relevant to the issue being 62 | > reported. This might include the lines of code that you have identified as 63 | > causing the bug, and potential solutions (and your opinions on their 64 | > merits). 65 | 66 | 67 | 68 | ## Feature requests 69 | 70 | Feature requests are welcome. But take a moment to find out whether your idea 71 | fits with the scope and aims of the project. It's up to *you* to make a strong 72 | case to convince the project's developers of the merits of this feature. Please 73 | provide as much detail and context as possible. 74 | 75 | **Please, use the GitHub issue search** to check if the feature has already been requested. 76 | 77 | 78 | 79 | ## Pull requests 80 | 81 | Good pull requests - patches, improvements, new features - are a fantastic 82 | help. They should remain focused in scope and avoid containing unrelated 83 | commits. 84 | 85 | **Please ask first** before embarking on any significant pull request (e.g. 86 | implementing features, refactoring code, porting to a different language), 87 | otherwise you risk spending a lot of time working on something that the 88 | project's developers might not want to merge into the project. 89 | 90 | Code must follow, mostly, these [coding conventions](http://javascript.crockford.com/code.html) . 91 | 92 | Adhering to the following this process is the best way to get your work 93 | included in the project: 94 | 95 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, 96 | and configure the remotes: 97 | 98 | ```bash 99 | # Clone your fork of the repo into the current directory 100 | git clone https://github.com//gridster.js 101 | # Navigate to the newly cloned directory 102 | cd gridster.js 103 | # Assign the original repo to a remote called "upstream" 104 | git remote add upstream https://github.com/ducksboard/gridster.js 105 | ``` 106 | 107 | 2. If you cloned a while ago, get the latest changes from upstream: 108 | 109 | ```bash 110 | git checkout master 111 | git pull upstream master 112 | ``` 113 | 114 | 3. Create a new topic branch (off the main project development branch) to 115 | contain your feature, change, or fix: 116 | 117 | ```bash 118 | git checkout -b 119 | ``` 120 | 121 | 4. Commit your changes in logical chunks. Please adhere to these [git commit 122 | message guidelines](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y) 123 | or your code is unlikely be merged into the main project. Use Git's 124 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 125 | feature to tidy up your commits before making them public. 126 | 127 | 5. Merge or rebase the upstream development branch into your topic branch: 128 | 129 | ```bash 130 | git pull --rebase upstream master 131 | ``` 132 | 133 | 6. Push your topic branch up to your fork: 134 | 135 | ```bash 136 | git push origin 137 | ``` 138 | 139 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) 140 | with a clear title and description. 141 | 142 | **IMPORTANT**: By submitting a patch, you agree to allow the project owner to 143 | license your work under the same license as that used by the project. 144 | 145 | 146 | #commit Message Guidelines 147 | We use [automatic changelog creation](https://github.com/ajoslin/conventional-changelog), so it best if your commit messages follow the following conventions: 148 | 149 | ### Commit Message Format 150 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special 151 | format that includes a **type**, a **scope** and a **subject**: 152 | 153 | ``` 154 | (): 155 | 156 | 157 | 158 |