{"id":13500738,"url":"https://github.com/hootsuite/grid","last_synced_at":"2025-09-27T07:32:07.177Z","repository":{"id":11792502,"uuid":"14335772","full_name":"hootsuite/grid","owner":"hootsuite","description":"Drag and drop library for two-dimensional, resizable and responsive lists","archived":true,"fork":false,"pushed_at":"2022-02-03T13:38:45.000Z","size":325,"stargazers_count":3574,"open_issues_count":46,"forks_count":281,"subscribers_count":255,"default_branch":"master","last_synced_at":"2024-05-22T15:09:58.184Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://hootsuite.github.io/grid/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hootsuite.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-12T15:16:40.000Z","updated_at":"2024-05-06T08:53:26.000Z","dependencies_parsed_at":"2022-07-12T19:50:30.190Z","dependency_job_id":null,"html_url":"https://github.com/hootsuite/grid","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hootsuite%2Fgrid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hootsuite%2Fgrid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hootsuite%2Fgrid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hootsuite%2Fgrid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hootsuite","download_url":"https://codeload.github.com/hootsuite/grid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234410320,"owners_count":18828176,"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":"2024-07-31T22:01:12.289Z","updated_at":"2025-09-27T07:31:58.056Z","avatar_url":"https://github.com/hootsuite.png","language":"JavaScript","readme":"# DEPRECATED \nThis project is no longer maintained, please consider using [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) instead.\n\nGridList [![Build Status](https://travis-ci.org/hootsuite/grid.svg?branch=master)](https://travis-ci.org/hootsuite/grid)\n====\nDrag and drop library for a two-dimensional resizable and responsive list of\nitems\n\n**Demo: http://hootsuite.github.io/grid/**\n\nThe GridList library is split into two roles:\n\n1. An agnostic [**GridList class**](#gridlist-class) that manages the\ntwo-dimensional positions from a list of items within a virtual matrix.\n2. A [**jQuery plugin**](#fngridlist) built on top of the GridList class\nthat translates the generic items positions into responsive DOM elements with\ndrag and drop capabilities.\n\n## GridList class\n\nJump to:\n\n- [**API**](#api)\n- [**Primitives**](#primitives)\n\n### API\n\n#### new GridList(items, options)\n\n```js\nvar myGrid = new GridList(items, {\n  direction: 'horizontal',\n  lanes: 3\n});\n```\n\nThe first constructor parameter is an array of [items](#primitives) to populate\nthe grid with.\n\n Supported options:\n\n - **direction** - Can be `'horizontal'` or `'vertical'`. Defaults to\n   `'horizontal'`. This sets how the grid can expand e.g. for 'horizontal' the\n   grid will stretch towards the right to accommodate all the items. For\n   'vertical', it will stretch towards the bottom.\n - **lanes** - Number of fixed rows or columns, depending on the\n   direction.\n\n#### generateGrid()\n\n```js\nmyGrid.generateGrid();\n```\n\nBuild the grid structure from scratch, using the positions of the given\nitems. If items lack positional attributes (x and y), they will be misplaced,\npossibly overlapping. If you want to build a grid around a list of items that\nonly have their size attributes defined (w and h), and rely on the library to\nposition them two-dimensionally, use [_resizeGrid._](#resizegridrows)\n\n#### resizeGrid(lanes)\n\n```js\nmyGrid.resizeGrid(4);\n```\n\n(Re)generate positions for the items inside a grid instance for a given number\nof rows/columns. This method has two major use-cases:\n\n1. Items are being represented two-dimensionally for the first time.\n2. Items already have 2d positions but need to be represented on a different\ngrid size, maintaining as much as possible of their previous order.\n\nPositions inside the grid are generated left-to-right, top-to-bottom. So when\nlooking for a new position inside the grid the topmost row from the leftmost\ncolumn is chosen.\n\n#### moveItemToPosition(item, position)\n\n```js\n// Move item from [0, 0] to [1, 1]\nvar carefreeItem = myGrid.grid[0][0];\nmyGrid.moveItemToPosition(carefreeItem, [1, 1]);\n```\n\nHere are things that happen when moving an item inside the grid:\n\n1. The item's previous position is cleared inside the [2d grid](#gridlistgrid),\n2. The position inside the [item object](#item) is updated,\n3. The item's new position is marked inside the 2d grid and\n4. Collisions are handled if the moved item overlaps with other item(s) from\nthe grid.\n\nCollisions can be solved in two ways. First, an attempt to resolve them\n_locally_ is made, meaning that the moved item tries to swap position with\nthe overlapped item(s). This is the preferred _fair trade._ If this doesn't\nwork out and after swapping we still have collisions inside the grid, the\nentire grid will be [regenerated](#resizegridrows), starting with the moved\nitem fixed in its new position. In the latter case, all the items around and\nto the right of the moved item might have their position slightly altered.\n\n#### resizeItem(item, size)\n\n```js\n// Resize item from position [0, 0] to span over 3 columns\nvar growthItem = myGrid.grid[0, 0];\n\nmyGrid.resizeItem(growthItem, {w: 3});\nconsole.log(growthItem.w); // will output \"3\"\n\nmyGrid.resizing(growthItem, {h: 2});\nconsole.log(growthItem.h); // will output \"2\"\n```\n\nResizing an item is very similar to moving its position, in the sense that\n[grid](#gridlistgrid) cells will be repopulated and collisions will be handled\nafterwards. See [moveItemToPosition.](#moveitemtopositionitem-position)\n\n\n### Primitives\n\n#### Item\n\nThe item is the building block of GridList, and is a plain JavaScript object.\nThe primary function of the GridList is to position such items\ntwo-dimentionally. Which brings us to the composition of an item: **w** and\n**h** for size, **x** and **y** for position. E.g.\n\n```js\n{w: 3, h: 1, x: 0, y: 1}\n```\n\nNote that x and y (**column** and **row**) are abstract coords inside the grid,\nthey are integer values starting from 0. Naturally, w and h (**width** and\n**height**) also take up space in the same coordinate system, which reveals the\nsmallest unit of a grid: the **cell.** You could say, for example, that the\nfeatured item above takes up three grid cells.\n\n#### gridList.items\n\nA GridList instance works around an array of items. The items array is the\nfirst parameter of the class constructor and is always visible under the\n`.items` property. Here's a list of items for a grid with three 1x1 items on a\ncolumn with three rows:\n\n```js\n[{w: 1, h: 1, x: 0, y: 0},\n {w: 1, h: 1, x: 0, y: 1},\n {w: 1, h: 1, x: 0, y: 2}]\n```\n\n#### gridList.grid\n\nSeeing how JavaScript doesn't support multidimensional arrays, the 2d grid\ninside GridList is represented by an array for columns, with each array entry\ncontaining another array with cells for each row. __The cell is simply a pointer\nto an item that occupies it, or a *null* reference if no item is sitting on\nthat cell's position.__ Note that more cells can point to the same item\nreference, because items occupy `w * h` cells. Here's a grid\npseudo-representation:\n\n| col1 | col2 | col3 | col4 |\n| :--: | :--: | :--: | :--: |\n| 1    | 2    |      |      |\n| 1    | 3    | 4    | 4    |\n| 1    |      | 4    | 4    |\n\nHaving the grid in a two-dimensional data structure, we can fetch item\nreferences directly by targeting any of the cells they cover inside the grid.\nE.g.\n\n```js\nmyGrid.grid[1][0] // reference to item #2\nmyGrid.grid[1][1] // reference to item #3\nmyGrid.grid[2][1] // reference to item #4\nmyGrid.grid[3][2] // still reference to item #4\n```\n\nPS. This grid would be generated by these items:\n\n```js\n[{w: 1, h: 3, x: 0, y: 0},\n {w: 1, h: 1, x: 1, y: 0},\n {w: 1, h: 1, x: 1, y: 1},\n {w: 2, h: 2, x: 2, y: 1}]\n```\n\n## $.fn.gridList\n\n```js\n$('.my-list').gridList({\n  direction: 'horizontal',\n  lanes: 3\n});\n```\n\nThe jQuery plugin has two main functions:\n\n- Render the GridList on top of a list of **DOM elements.** The list items are\nexpected to have `data-w` and `data-h` attributes, and optionally `data-x` and\n`data-y` (if their positions have been previously generated and persisted)\n- **Drag and drop** capabilities\n\nThe function takes an optional argument with options that will be passed to the\ndraggables when constructing them.\n\n```js\n$('.my-list').gridList({lanes: 3}, {handle: '.title'});\n```\n\nSee [jQuery UI Draggable API](https://api.jqueryui.com/draggable/) for details on all\nthe available options.\n\nThe rendered list is **responsive** to its parent container, meaning that the\nwidth and height of the items are calculated based on the container height\ndivided by the number of grid rows.\n\n## FAQ: Why not [gridster](https://github.com/ducksboard/gridster.js)?\n\n- Their README reads Ducksboard is no longer active in their development. There\n  are a few notable forks but it's hard to assert their\n  [reliability.](https://github.com/dustmoo/gridster.js/issues)\n- gridster works vertically while our solution works both vertically and\n  horizontally.\n- Our lib contains over 5 times fewer code.\n- gridster collisions are [very\n  basic](https://github.com/ducksboard/gridster.js/issues/54), we pushed towards\n  better UX and found alternative ways for dealing with collisions.\n- We wanted out-of-the-box responsiveness, and the entire grid system was build\n  fluid, relative to any parent container.\n- We needed the grid logic to be a DOM-less lib outside the jQuery plugin. This\n  allows us to compute grid positions on the server-side and run kick-ass fast\n  tests with Node.\n- Another more particular thing we needed was widgets that had height=0, which\n  means they stretch on however many rows a grid has. We show timelines like\n  this. It also works for width=0.\n\n*Please check [demo page](http://hootsuite.github.io/grid/) or code directly for\ninvestigating these assumptions.*\n","funding_links":[],"categories":["JavaScript","Misc","others","Misc [🔝](#readme)","Grid","Uncategorized","大杂烩"],"sub_categories":["Other","React Components","Uncategorized","其它"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhootsuite%2Fgrid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhootsuite%2Fgrid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhootsuite%2Fgrid/lists"}