{"id":18406161,"url":"https://github.com/nodebb/pulling","last_synced_at":"2025-10-28T10:04:16.011Z","repository":{"id":65420827,"uuid":"110311002","full_name":"NodeBB/pulling","owner":"NodeBB","description":"Flexible slideout menu for mobile webapps","archived":false,"fork":false,"pushed_at":"2021-03-24T05:19:39.000Z","size":18,"stargazers_count":7,"open_issues_count":1,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-14T06:47:35.702Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NodeBB.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-11T02:17:50.000Z","updated_at":"2022-05-11T12:36:44.000Z","dependencies_parsed_at":"2023-01-22T19:45:15.528Z","dependency_job_id":null,"html_url":"https://github.com/NodeBB/pulling","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NodeBB%2Fpulling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NodeBB%2Fpulling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NodeBB%2Fpulling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NodeBB%2Fpulling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NodeBB","download_url":"https://codeload.github.com/NodeBB/pulling/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247620372,"owners_count":20968198,"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-11-06T03:07:11.631Z","updated_at":"2025-10-28T10:04:10.977Z","avatar_url":"https://github.com/NodeBB.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pulling\n\nFlexible slideout menu for mobile webapps\n\n```js\nconst panel = document.querySelector('#panel');\nconst toggle = document.querySelectorAll('#toggle');\nconst menu = document.querySelector('#menu');\n\nconst pullin = Pulling.create({\n  menu,\n  panel,\n});\n\ntoggle.addEventListener('click', () =\u003e pullin.toggle());\n```\n\n## Installation\n\nPulling is available on npm. \n\n - `npm install pulling`\n - `yarn add pulling`\n\n## Features\n\n- Flicking gesture support\n- Supports multiple slideout menus\n- Standalone, dependency-free\n- Simple markup\n- Native scrolling\n- Easy customization\n- CSS transforms \u0026 transitions\n- Two different display modes\n- Just 10 Kb!\n\n## Usage\n\nYou just need a panel for your main content and a menu element:\n\n```html\n\u003cnav id=\"menu\"\u003e\n  \u003cheader\u003e\n    \u003ch2\u003eMenu\u003c/h2\u003e\n  \u003c/header\u003e\n\u003c/nav\u003e\n\n\u003cmain id=\"panel\"\u003e\n  \u003cheader\u003e\n    \u003ch2\u003ePanel\u003c/h2\u003e\n  \u003c/header\u003e\n\u003c/main\u003e\n```\n\nStyling is simple, too. The library handles most things for you, so just add a background on your panel and menu, and add a `min-height` on the panel if you're using the reveal mode.\n\nThen include Pulling and set up the menu.\n\n```js\nconst panel = document.querySelector('#panel');\nconst menu = document.querySelector('#menu');\n\nconst pullin = Pulling.create({\n  menu,\n  panel,\n});\n```\n\nSee [test.html](test.html) for a full example.\n\n### Browser Support\n\n- Chrome (IOS, Android, desktop)\n- Firefox (Android, desktop)\n- Safari (IOS, Android, desktop)\n- Opera (desktop)\n- IE 10+ (desktop and mobile)\n\n# API\n\n## `Pulling.create(options)`\nCreates a new `Pulling` instance\n\n### `options`\n\n+ **menu** - `Element`\n\n  DOM element of menu\n\n+ **panel** - `Element`\n\n  DOM element of panel\n\n+ **side** - `\"left\" | \"right\"` (default: `left`)\n\n  side menu should display on\n\n+ **mode** - `\"drawer\" | \"reveal\"` (default: `drawer`)\n\n  whether the menu slide over the panel (`drawer`)\nor the panel should slide to reveal the menu (`reveal`)\n\n+ **margin** - `number` (default: `25`)\n\n  the number of pixels from the edge of the viewport \nin which a touch event will be accepted\n\n+ **timing** - `number` (default: `200`)\n\n  milliseconds of the transition animation for opening and closing,\nin the case where it isn't pulled out manually\n\n+ **timingFunction** - `string` (default: `ease`)\n\n  CSS3 transition timing function\n\n+ **width** - `number` (default: `256`)\n\n  width of menu in pixels\n\n+ **sensitivity** - `number` (default: `0.25`)\n\n  the speed needed to activate a flick\n\n+ **slope** - `number` (default: `0.5`)\n\n  maximum ratio of vertical touch movement to horizontal touch\nmovement that should be accepted\n\n+ **touch** - `boolean` (default: `true`)\n\n  Enable touch functionality\n\n+ **ignoreScrollables** - `boolean` (default: `true`)\n\n  Ignore horizontally scrollable elements\n\n## Instance Methods\n\nAll methods are chainable\n\n### `#open()`\n\nOpens the menu. Emits `beforeopen` and `opened` events.\n\n### `#close()`\n\nCloses the menu. Emits `beforeclose` and `closed` events.\n\n### `#toggle(condition?: boolean)`\n\nToggles the state of the menu (closed -\u003e open, open -\u003e closed). \n\n  + If `condition === true`, it opens the menu\n  + If `condition === false`, it closes the menu\n\n### `#on(eventName: string, handler: Function)`\n\nAdd an event handler for the event\n\n### `#off(eventName: string, handler?: Function)`\n\nRemove an event handler for the event, or remove all handlers for the event\n\n### `#ignore(selector: string)`\n\nIgnore touch events from a specific selector\n\n### `#unignore(selector: string)`\n\nRemove selector from ignore list. Will not override ignored selectors.\n\n### `#disable()`\n\nDisable all functionality of the menu\n\n### `#enable()`\n\nEnable the menu's functionality\n\n### `#disableTouch()`\n\nDisable touch event functionality for this menu\n\n### `#enableTouch()`\n\nEnable touch event functionality for this menu\n\n## Events\n\n+ `beforeclose`  \n  Emitted before close begins, including when dragging closed with touch\n+ `closed`  \n  Emitted after close completes\n+ `beforeopen`  \n  Emitted before open begins, including when dragging open with touch\n+ `opened`  \n  Emitted after open completes\n+ `touchstart`  \n  Emitted when a touch movement begins\n+ `touchmove`  \n  Emitted on every movement due to touch\n+ `touchend`  \n  Emitted when a touch movement ends\n\nYou can use these to support multiple menus by disabling one when the other opens:\n```js\npullinLeft.on('beforeopen', () =\u003e pullinRight.disableTouch());\npullinLeft.on('closed', () =\u003e pullinRight.enableTouch());\npullinRight.on('beforeopen', () =\u003e pullinLeft.disableTouch());\npullinRight.on('closed', () =\u003e pullinLeft.enableTouch());\n```\n\n## State\n\n+ **`.state.closed`** - `boolean`\n+ **`.state.closing`** - `boolean`\n+ **`.state.open`** - `boolean`\n+ **`.state.opening`** - `boolean`\n\n## FAQ\n\n### How do I prevent it from opening when scrolling through a carousel?\n\nYou can either use `.ignore(selector)` to add the specific element selector to the ignore list, or you can do `.ignore('[data-pullin-ignore]')` to add that selector the the list and then just add the `data-pullin-ignore` attribute to every element you want ignored.\n\n### How do I add a toggle button?\n\n```js\n// vanilla js\ndocument.querySelector('.toggle-menu').addEventListener('click', () =\u003e pullin.toggle());\n\n// jQuery\n$('.toggle-menu').on('click', () =\u003e pullin.toggle());\n```\n\n## How do I use two menus, one on each side?\n\nYou'll want to use events to keep one menu disabled while the other is open.\n\n```js\npullinLeft.on('beforeopen', () =\u003e {\n  pullinRight.close().disableTouch();\n});\npullinLeft.on('closed', () =\u003e pullinRight.enableTouch());\npullinRight.on('beforeopen', () =\u003e {\n  pullinLeft.close().disableTouch();\n});\npullinRight.on('closed', () =\u003e pullinLeft.enableTouch());\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodebb%2Fpulling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnodebb%2Fpulling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodebb%2Fpulling/lists"}