{"id":23990443,"url":"https://github.com/manifestwebdesign/angular-gridster","last_synced_at":"2025-05-15T01:04:12.589Z","repository":{"id":12092930,"uuid":"14681221","full_name":"ManifestWebDesign/angular-gridster","owner":"ManifestWebDesign","description":"An implementation of gridster-like widgets for Angular JS","archived":false,"fork":false,"pushed_at":"2020-07-15T20:51:36.000Z","size":1044,"stargazers_count":961,"open_issues_count":217,"forks_count":392,"subscribers_count":70,"default_branch":"master","last_synced_at":"2025-04-03T03:29:38.855Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://manifestwebdesign.github.io/angular-gridster/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ManifestWebDesign.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-25T09:19:13.000Z","updated_at":"2025-03-15T01:17:35.000Z","dependencies_parsed_at":"2022-09-14T00:12:18.861Z","dependency_job_id":null,"html_url":"https://github.com/ManifestWebDesign/angular-gridster","commit_stats":null,"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2Fangular-gridster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2Fangular-gridster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2Fangular-gridster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2Fangular-gridster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ManifestWebDesign","download_url":"https://codeload.github.com/ManifestWebDesign/angular-gridster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248166853,"owners_count":21058481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-07T18:29:07.690Z","updated_at":"2025-04-10T06:15:17.629Z","avatar_url":"https://github.com/ManifestWebDesign.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"angular-gridster\n================\n[![Build Status](https://travis-ci.org/ManifestWebDesign/angular-gridster.svg)](https://travis-ci.org/ManifestWebDesign/angular-gridster)\n\nAn implementation of gridster-like widgets for Angular JS.  This is not a wrapper on the original gridster jQuery plugin (http://gridster.net/).  It is instead completely rewritten as Angular directives.  Rewriting allowed for some additional features and better use of Angular data binding.  Even more importantly, the original plugin had unpredictable behavior and crashed when wrapped with an Angular directive in my initial tests.\n\n## Demo\n\nSee \u003ca href=\"https://rawgit.com/ManifestWebDesign/angular-gridster/master/index.html\"\u003eLive Demo\u003c/a\u003e\n\n## Installation\n\n```bash\n  bower install angular-gridster\n```\n\nThen, import the following in your HTML alongside `jQuery` and `angular`:\n```html\n\t\u003clink rel=\"stylesheet\" href=\"bower_components/angular-gridster/dist/angular-gridster.min.css\"/\u003e\n\t\u003cscript src=\"bower_components/javascript-detect-element-resize/jquery.resize.js\"\u003e\u003c/script\u003e\n\t\u003cscript src=\"bower_components/angular-gridster/dist/angular-gridster.min.js\"\u003e\u003c/script\u003e\n```\n\n`jquery.resize` is a jQuery plugin needed to check for changes in the gridster size.\n\n## Usage\n\n\n```js\n\n// load the gridster module\nangular.module('myModule', ['gridster']);\n\n```\n\nDefault usage:\n```HTML\n\u003cdiv gridster\u003e\n\t\u003cul\u003e\n\t\t\u003cli gridster-item=\"item\" ng-repeat=\"item in standardItems\"\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\nWhich expects a scope setup like the following:\n``` JavaScript\n// IMPORTANT: Items should be placed in the grid in the order in which they should appear.\n// In most cases the sorting should be by row ASC, col ASC\n\n// these map directly to gridsterItem directive options\n$scope.standardItems = [\n  { sizeX: 2, sizeY: 1, row: 0, col: 0 },\n  { sizeX: 2, sizeY: 2, row: 0, col: 2 },\n  { sizeX: 1, sizeY: 1, row: 0, col: 4 },\n  { sizeX: 1, sizeY: 1, row: 0, col: 5 },\n  { sizeX: 2, sizeY: 1, row: 1, col: 0 },\n  { sizeX: 1, sizeY: 1, row: 1, col: 4 },\n  { sizeX: 1, sizeY: 2, row: 1, col: 5 },\n  { sizeX: 1, sizeY: 1, row: 2, col: 0 },\n  { sizeX: 2, sizeY: 1, row: 2, col: 1 },\n  { sizeX: 1, sizeY: 1, row: 2, col: 3 },\n  { sizeX: 1, sizeY: 1, row: 2, col: 4 }\n];\n```\nAlternatively, you can use the html attributes, similar to the original gridster plugin, but with two-way data binding:\n```HTML\n\u003cdiv gridster\u003e\n\t\u003cul\u003e\n\t\t\u003cli gridster-item row=\"item.position[0]\" col=\"item.position[1]\" size-x=\"item.size.x\" size-y=\"item.size.y\" ng-repeat=\"item in customItems\"\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\nor:\n```HTML\n\u003cdiv data-gridster\u003e\n\t\u003cul\u003e\n\t\t\u003cli data-gridster-item data-row=\"item.position[0]\" data-col=\"item.position[1]\" data-sizex=\"item.size.x\" data-sizey=\"item.size.y\" ng-repeat=\"item in customItems\"\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\nThis allows the items to provide their own structure for row, col, and size:\n```JavaScript\n$scope.customItems = [\n  { size: { x: 2, y: 1 }, position: [0, 0] },\n  { size: { x: 2, y: 2 }, position: [0, 2] },\n  { size: { x: 1, y: 1 }, position: [0, 4] },\n  { size: { x: 1, y: 1 }, position: [0, 5] },\n  { size: { x: 2, y: 1 }, position: [1, 0] },\n  { size: { x: 1, y: 1 }, position: [1, 4] },\n  { size: { x: 1, y: 2 }, position: [1, 5] },\n  { size: { x: 1, y: 1 }, position: [2, 0] },\n  { size: { x: 2, y: 1 }, position: [2, 1] },\n  { size: { x: 1, y: 1 }, position: [2, 3] },\n  { size: { x: 1, y: 1 }, position: [2, 4] }\n];\n```\nInstead of using attributes for row, col, and size, you can also just use a mapping object for the gridster-item directive:\n```HTML\n\u003cdiv gridster=\"gridsterOpts\"\u003e\n\t\u003cul\u003e\n\t\t\u003cli gridster-item=\"customItemMap\" ng-repeat=\"item in customItems\"\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\nThis expects a scope similar to the previous example, but with customItemMap also defined in the scope:\n```JavaScript\n// maps the item from customItems in the scope to the gridsterItem options\n$scope.customItemMap = {\n\tsizeX: 'item.size.x',\n\tsizeY: 'item.size.y',\n\trow: 'item.position[0]',\n\tcol: 'item.position[1]',\n\tminSizeY: 'item.minSizeY',\n\tmaxSizeY: 'item.maxSizeY'\n};\n```\nThe gridsterItem directive can be configured like this:\n```HTML\n\u003cdiv gridster=\"gridsterOpts\"\u003e\n\t\u003cul\u003e\n\t\t\u003cli gridster-item=\"item\" ng-repeat=\"item in standardItems\"\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\n\n## Configuration\n\n#### Via Scope\nSimply pass your desired options to the gridster directive\n\n```JavaScript\n$scope.gridsterOpts = {\n\tcolumns: 6, // the width of the grid, in columns\n\tpushing: true, // whether to push other items out of the way on move or resize\n\tfloating: true, // whether to automatically float items up so they stack (you can temporarily disable if you are adding unsorted items with ng-repeat)\n\tswapping: false, // whether or not to have items of the same size switch places instead of pushing down if they are the same size\n\twidth: 'auto', // can be an integer or 'auto'. 'auto' scales gridster to be the full width of its containing element\n\tcolWidth: 'auto', // can be an integer or 'auto'.  'auto' uses the pixel width of the element divided by 'columns'\n\trowHeight: 'match', // can be an integer or 'match'.  Match uses the colWidth, giving you square widgets.\n\tmargins: [10, 10], // the pixel distance between each widget\n\touterMargin: true, // whether margins apply to outer edges of the grid\n\tsparse: false, // \"true\" can increase performance of dragging and resizing for big grid (e.g. 20x50)\n\tisMobile: false, // stacks the grid items if true\n\tmobileBreakPoint: 600, // if the screen is not wider that this, remove the grid layout and stack the items\n\tmobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint\n\tminColumns: 1, // the minimum columns the grid must have\n\tminRows: 2, // the minimum height of the grid, in rows\n\tmaxRows: 100,\n\tdefaultSizeX: 2, // the default width of a gridster item, if not specifed\n\tdefaultSizeY: 1, // the default height of a gridster item, if not specified\n\tminSizeX: 1, // minimum column width of an item\n\tmaxSizeX: null, // maximum column width of an item\n\tminSizeY: 1, // minumum row height of an item\n\tmaxSizeY: null, // maximum row height of an item\n\tresizable: {\n\t   enabled: true,\n\t   handles: ['n', 'e', 's', 'w', 'ne', 'se', 'sw', 'nw'],\n\t   start: function(event, $element, widget) {}, // optional callback fired when resize is started,\n\t   resize: function(event, $element, widget) {}, // optional callback fired when item is resized,\n\t   stop: function(event, $element, widget) {} // optional callback fired when item is finished resizing\n\t},\n\tdraggable: {\n\t   enabled: true, // whether dragging items is supported\n\t   handle: '.my-class', // optional selector for drag handle\n\t   start: function(event, $element, widget) {}, // optional callback fired when drag is started,\n\t   drag: function(event, $element, widget) {}, // optional callback fired when item is moved,\n\t   stop: function(event, $element, widget) {} // optional callback fired when item is finished dragging\n\t}\n};\n```\n\n\n#### Via Constant\nYou can also override the default configuration site wide by modifying the ```gridsterConfig``` constant\n\n```js\nangular.module('yourApp').run(['gridsterConfig', function(gridsterConfig) {\n\tgridsterConfig.width = 1000;\n}]);\n```\n\n## Controller Access\n\nThe gridster and gridsterItem directive controller objects can be accessed within their scopes as 'gridster' and 'gridsterItem'.\n\nThese controllers are internal APIs that are subject to change.\n\n```html\n\u003cdiv gridster=\"gridsterOpts\"\u003e\n\t\u003cul\u003e\n\t\t\u003cli gridster-item=\"item\" ng-repeat=\"item in standardItems\"\u003e\n\t\t\t{{ gridsterItem.isMoving() }}\n\t\t\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/div\u003e\n```\n\n\n## Gridster Events\n\n#### gridster-mobile-changed\nWhen the gridster goes in or out of mobile mode, a 'gridster-mobile-changed' event is broadcast on rootScope:\n\n```js\nscope.$on('gridster-mobile-changed', function(gridster) {\n})\n```\n\n#### gridster-draggable-changed\nWhen the gridster draggable properties change, a 'gridster-draggable-changed' event is broadcast on rootScope:\n\n```js\nscope.$on('gridster-draggable-changed', function(gridster) {\n})\n```\n\n#### gridster-resizable-changed\nWhen the gridster resizable properties change, a 'gridster-resizable-changed' event is broadcast on rootScope:\n\n```js\nscope.$on('gridster-resizable-changed', function(gridster) {\n})\n```\n\n#### gridster-resized\nWhen the gridster element's size changes, a 'gridster-resized' event is broadcast on rootScope:\n\n```js\nscope.$on('gridster-resized', function(sizes, gridster) {\n\t// sizes[0] = width\n\t// sizes[1] = height\n\t// gridster.\n})\n```\n\n## Gridster Item Events\n\n#### gridster-item-transition-end\nGridster items have CSS transitions by default.  Gridster items listen for css transition-end across different browsers and broadcast the event 'gridster-item-transition-end'.  You can listen for it like this from within the gridster-item directive:\n\n```js\nscope.$on('gridster-item-transition-end', function(item) {\n\t// item.$element\n\t// item.gridster\n\t// item.row\n\t// item.col\n\t// item.sizeX\n\t// item.sizeY\n\t// item.minSizeX\n\t// item.minSizeY\n\t// item.maxSizeX\n\t// item.maxSizeY\n})\n```\n\n#### gridster-item-initialized\nAfter a gridster item's controller has finished with setup, it broadcasts an event 'gridster-item-initialized' on its own scope.  You can listen for it like this from within the gridster-item directive:\n\n```js\nscope.$on('gridster-item-initialized', function(item) {\n\t// item.$element\n\t// item.gridster\n\t// item.row\n\t// item.col\n\t// item.sizeX\n\t// item.sizeY\n\t// item.minSizeX\n\t// item.minSizeY\n\t// item.maxSizeX\n\t// item.maxSizeY\n})\n```\n\n#### gridster-item-resized\nAfter a gridster item's size changes (rows or columns), it broadcasts an event 'gridster-item-resized' on its own scope.  You can listen for it like this from within the gridster-item directive:\n\n```js\nscope.$on('gridster-item-resized', function(item) {\n\t// item.$element\n\t// item.gridster\n\t// item.row\n\t// item.col\n\t// item.sizeX\n\t// item.sizeY\n\t// item.minSizeX\n\t// item.minSizeY\n\t// item.maxSizeX\n\t// item.maxSizeY\n})\n```\n\n## Watching item changes of size and position\n\nThe typical Angular way would be to do a $scope.$watch on your item or items in the scope.  Example:\n\n```JavaScript\n// two objects, converted to gridster items in the view via ng-repeat\n$scope.items = [{},{}];\n\n$scope.$watch('items', function(items){\n   // one of the items changed\n}, true);\n```\n\nor\n\n```JavaScript\n$scope.$watch('items[0]', function(){\n   // item0 changed\n}, true);\n```\n\nor\n\n```JavaScript\n$scope.$watch('items[0].sizeX', function(){\n   // item0 sizeX changed\n}, true);\n```\n\nThe third argument, true, is to make the watch based on the value of the object, rather than just matching the reference to the object.\n\n\n## Note\nThis directive/plugin does not generate style tags, like the jQuery plugin.  It also uses standard camelCase for variables and object properties, while the original plugin used lower\\_case\\_with_underscores.  These options have not and may never be implemented:\n\n* widget_class - not necessary since directives already whatever classes and attributes you want to add\n* widget_margins - replaced by 'margins'\n* widget\\_base\\_dimensions - replaced by 'defaultSizeX' and 'defaultSizeY'\n* min_cols - currently, only 'columns' is used to defined the maximum width\n* max_cols - currently, only 'columns' is used to defined the maximum width\n* min_rows - replaced by 'minRows'\n* max_rows - replaced by 'maxRows'\n* max\\_size\\_x\n* max\\_size\\_y\n* extra_cols\n* extra_rows\n* autogenerate_stylesheet\n* avoid\\_overlapped\\_widgets\n* resize.axes\n* resize.handle_class - replaced by 'resize.handle', which doesn't need to be a class\n* resize.handle\\_append\\_to\n* resize.max_size\n* collision.on\\_overlap\\_start\n* collision.on_overlap\n* collision.on\\_overlap\\_stop\n\n## Contributing\n\n#### Install project dependencies\n```bash\n  npm install\n  bower install\n```\n\n#### Style Guide\nPlease respect the formatting specified in .editorconfig\n\n#### Grunt Tasks\n```grunt default``` Runs jshint \u0026 compiles project\n\n```grunt dev``` Opens demo page, starts karma test runner, runs unit tests on src \u0026 test folder changes\n\n```grunt e2e``` Watch src folder and run e2e tests on changes\n\n```grunt test``` Runs the unit \u0026 e2e tests\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanifestwebdesign%2Fangular-gridster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanifestwebdesign%2Fangular-gridster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanifestwebdesign%2Fangular-gridster/lists"}