{"id":13402803,"url":"https://github.com/somewebmedia/hc-offcanvas-nav","last_synced_at":"2025-05-15T10:11:50.733Z","repository":{"id":13972846,"uuid":"16673534","full_name":"somewebmedia/hc-offcanvas-nav","owner":"somewebmedia","description":"JavaScript library for creating toggled off-canvas multi-level navigations, allowing endless nesting of submenu elements, supporting swipe gestures, keyboard interactions and ARIA attributes.","archived":false,"fork":false,"pushed_at":"2022-03-25T17:31:00.000Z","size":3524,"stargazers_count":343,"open_issues_count":19,"forks_count":84,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-22T18:59:03.626Z","etag":null,"topics":["hamburger","hamburger-menu","jquery","jquery-plugin","menu","mobile","mobile-navigation","nav","navigation","offcanvas","offcanvas-menu","swipe-menu"],"latest_commit_sha":null,"homepage":"https://somewebmedia.github.io/hc-offcanvas-nav/","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/somewebmedia.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":"2014-02-09T19:25:07.000Z","updated_at":"2025-04-16T02:52:16.000Z","dependencies_parsed_at":"2022-08-25T06:10:56.459Z","dependency_job_id":null,"html_url":"https://github.com/somewebmedia/hc-offcanvas-nav","commit_stats":null,"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somewebmedia%2Fhc-offcanvas-nav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somewebmedia%2Fhc-offcanvas-nav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somewebmedia%2Fhc-offcanvas-nav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somewebmedia%2Fhc-offcanvas-nav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/somewebmedia","download_url":"https://codeload.github.com/somewebmedia/hc-offcanvas-nav/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319720,"owners_count":22051075,"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":["hamburger","hamburger-menu","jquery","jquery-plugin","menu","mobile","mobile-navigation","nav","navigation","offcanvas","offcanvas-menu","swipe-menu"],"created_at":"2024-07-30T19:01:21.038Z","updated_at":"2025-05-15T10:11:45.709Z","avatar_url":"https://github.com/somewebmedia.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"HC Off-canvas Nav\n===============\n\n[![Version](https://img.shields.io/npm/v/hc-offcanvas-nav.svg)](https://www.npmjs.com/package/hc-offcanvas-nav) [![Downloads](https://img.shields.io/npm/dt/hc-offcanvas-nav.svg)](https://www.npmjs.com/package/hc-offcanvas-nav)\n\nJavaScript library for creating off-canvas multi-level navigations, using ARIA. Dependency free, but also works as a jQuery plugin. [Demo](https://somewebmedia.github.io/hc-offcanvas-nav/)\n\n\u003cimg src=\"https://somewebmedia.github.io/hc-offcanvas-nav/hc-offcanvas-nav.png\" width=\"440\"\u003e\n\n\n\n### Features\n- Multi-level menu support\n- Endless nesting of navigation elements\n- Custom content inside menu items\n- Push/Slide DOM elements of choice\n- Touch swipe guestures\n- Different navigation positions\n- No dependencies\n- Flexible, simple markup\n- A number of exposed [Options](#options), [Methods](#methods) and [Events](#events)\n- 2 [Themes](#themes)\n- Cross-browser compatibility\n- Full ARIA keyboard support\n  - It relies on \u003ca href=\"https://www.w3.org/TR/wai-aria-practices/#dialog_modal\"\u003e\u003cabbr title=\"Accessible Rich Internet Application\"\u003eARIA\u003c/abbr\u003e Design pattern for Dialogs\u003c/a\u003e\n  - The tab key loops through all of the keyboard focusable items within the offcanvas navigation\n  - You can close it using \u003ckbd\u003eEsc\u003c/kbd\u003e\n\n\n\n## Quick start\n\n### Install\n\nThis package can be installed with:\n\n- [npm](https://www.npmjs.com/package/hc-offcanvas-nav): `npm install --save hc-offcanvas-nav`\n\nOr download the [latest release](https://github.com/somewebmedia/hc-offcanvas-nav/tags).\n\n\n\n### Including HC Off-canvas Nav\n\n#### Script and Css tag\n```html\n\u003clink rel=\"stylesheet\" href=\"/path/to/hc-offcanvas-nav.css\"\u003e\n\n\u003cscript src=\"/path/to/hc-offcanvas-nav.js\"\u003e\u003c/script\u003e\n```\n\n#### Webpack/Browserify\n\nIn the script, including HC Off-canvas Nav will usually look like this:\n\n```js\nconst hcOffcanvasNav = require('hc-offcanvas-nav');\n```\n\n#### Babel\n\n```js\nimport hcOffcanvasNav from 'hc-offcanvas-nav';\n```\n\n#### AMD (Asynchronous Module Definition)\n\nIf using AMD, the module will be automatically defined as `hcOffcanvasNav`.\n\n#### SCSS\n\n```scss\n@import 'hc-offcanvas-nav/src/scss/core';\n@import 'hc-offcanvas-nav/src/scss/toggle';\n@import 'hc-offcanvas-nav/src/scss/theme-default';\n```\n\n\n## Usage\n\nBe sure to call the Nav once your menu element is available in the DOM.\n\n#### Vanilla JS\n\n```js\ndocument.addEventListener('DOMContentLoaded', function() {\n\n  var Nav = new hcOffcanvasNav('#main-nav', {\n    disableAt: 1024,\n    customToggle: '.toggle',\n    navTitle: 'All Categories',\n    levelTitles: true,\n    levelTitleAsBack: true\n  });\n\n});\n```\n\n#### jQuery\n\n```js\njQuery(document).ready(function($) {\n\n  $('#main-nav').hcOffcanvasNav({\n    disableAt: 1024,\n    customToggle: $('.toggle'),\n    navTitle: 'All Categories',\n    levelTitles: true,\n    levelTitleAsBack: true\n  });\n\n});\n```\n\nFor HC Off-canvas Nav to work as a jQuery plugin, jQuery has to be a property of global `window` object, so be careful when using it in combination with Babel/Webpack/Browserify and jQuery.\n\n#### Example HTML menu structure\n\n```html\n\u003cnav id=\"main-nav\"\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"#\"\u003eHome\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#\"\u003eAbout\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#\"\u003eServices\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\n          \u003ca href=\"#\"\u003eHosting\u003c/a\u003e\n          \u003cul\u003e\n            \u003cli\u003e\u003ca href=\"#\"\u003ePrivate Server\u003c/a\u003e\u003c/li\u003e\n            \u003cli\u003e\u003ca href=\"#\"\u003eManaged Hosting\u003c/a\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#\"\u003eDomains\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#\"\u003eWebsites\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/nav\u003e\n```\n\n\n## Themes\n\nHC Off-canvas Nav currently has 2 themes, the default and Carbon. To use Carbon theme simply call the Carbon theme css instead of the default one:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"/path/to/hc-offcanvas-nav.carbon.css\"\u003e\n```\n\nOr if compiling the SCSS from the `src` dir, `@include` it from there:\n\n```scss\n@import 'hc-offcanvas-nav/src/scss/core';\n@import 'hc-offcanvas-nav/src/scss/toggle';\n@import 'hc-offcanvas-nav/src/scss/theme-carbon';\n```\n\n\n## Options\n\n| Property | Default | Type | Description |\n|----------|---------|------|-------------|\n| **width** | `280` | int / str | Width of the nav. Used for `left` and `right` positions. |\n| **height** | `'auto'` | int / str | Height of the nav. Used for `top` and `bottom` positions. |\n| **disableAt** | `false` | int / bool | Resolution above which to hide the offcanvas menu, and show the original. |\n| **pushContent** | `null` | str / Element obj | Content element (string selector or HTML Element object) that will be pushed when the navigation is open. |\n| **expanded** | `false`| bool | Initialize menu in expanded mode. It won't push content. |\n| **position** | `'left'` | str | Position on which the menu will open. Available options: `'left'`, `'right'`, `'top'` and `'bottom'`. |\n| **swipeGestures** | `true`| bool | Enable open/close swipe gestures like in native apps. Works only for `left` and `right` positions. |\n| **levelOpen** | `'overlap'` | str | Submenu levels open effect. Available options: `'overlap'`, `'expand'`, `'none'` or `false`. |\n| **levelSpacing** | `40` | int | If levels are overlaped, this is the spacing between them, if they are expanding or always open, this is the text indent of the submenus. |\n| **levelTitles** | `true` | bool | Show titles for submenus, which is the parent item name. Works only for overlaped levels. |\n| **navTitle** | `null` | str / Element obj | Main navigation (first level) title. Can also be HTML object like an image (logo). |\n| **navClass** | `''` | str | Custom navigation class. |\n| **disableBody** | `true` | bool | Disable body scroll when navigation is open. |\n| **closeOpenLevels** | `true` | bool | Should all open sub levels be closed when the nav closes. |\n| **closeActiveLevel** | `false` | bool | Should initially active sub level (see [`data-nav-active`](#data-attributes)) be cleared when the nav closes. |\n| **closeOnClick** | `true` | bool | Close the navigation when links are clicked. |\n| **closeOnEsc** | `true` | bool | Close the navigation on \u003ckbd\u003eEsc\u003c/kbd\u003e button. |\n| **customToggle** | `null` | str / Element obj | Custom navigation toggle element. |\n| **activeToggleClass** | `null` | str | Custom active toggle class. |\n| **insertClose** | `true` | bool / int | Insert navigation close button. You can also use an integer representing 0-based index that will be the position of the button in the list. Negative numbers are also supported. |\n| **insertBack** | `true` | bool / int | Insert back buttons to submenus. You can also use an integer representing 0-based index that will be the position of the button in the list. Negative numbers are also supported. Works only for overlaped levels. |\n| **labelClose** | `''` | str | Label for the close button. |\n| **labelBack** | `'Back'` | str | Label for the back buttons. |\n| **levelTitleAsBack** | `true` | bool | Use level titles as back labels. |\n| **rtl** | `false` | bool | Set the content direction to right-to-left. |\n| **bodyInsert** | `'prepend'` | str | Choose to prepend or append navigation to body. |\n| **keepClasses** | `true` | bool | Should original menus and their items classes be preserved or excluded. |\n| **removeOriginalNav** | `false` | bool | Remove original menu from the DOM. Don't use this if planning to update the nav! |\n| **ariaLabels** | `{...}` | obj | Labels for the ARIA attributes. If using HC Off-canvas Nav in different language than English, you should translate all the properties. See the next section. |\n\nARIA labels for the `aria-label` attributes on specific elements which will provide a text alternative to the elements that have no visible text on the screen.\n\n```js\nariaLabels: {\n  open:     'Open Menu',\n  close:    'Close Menu',\n  submenu:  'Submenu'\n}\n```\n\n\n## Methods\n\nThe HC Off-canvas Nav API offers a couple of methods to control the offcanvas and are publicly available to all active instances.\n\n#### Vanilla JS\n\n```js\nvar Nav = new hcOffcanvasNav();\n```\n\n#### jQuery\n\n```js\nvar $nav = $('#main-nav').hcOffcanvasNav();\nvar Nav = $nav.data('hcOffcanvasNav');\n```\n\n### .getSettings()\n\nReturns current settings.\n\n```js\nvar currentSettings = Nav.getSettings();\n```\n\n### .isOpen()\n\nChecks if the nav is open, and returns boolean.\n\n```js\nif (Nav.isOpen()) {\n  // do something\n}\n```\n\n### .update(options, updateDOM)\n\nUpdates just the specified settings with the new ones.\n\n```js\nNav.update({\n  disableAt: 1024,\n  navTitle: 'All pages'\n});\n```\n\nUpdates nav DOM. You don't have to pass empty settings object, the method is smart. Use this when original nav has been altered.\n\n```js\nNav.update(true);\n```\n\nUpdates both settings and nav DOM. Use this when original nav was changed and you also want to update some specific settings.\n\n```js\nNav.update({\n  disableAt: 1024,\n  navTitle: 'All pages'\n}, true);\n```\n\n### .open(level, index)\n\nOpens the nav if closed.\n\n```js\nNav.open();\n```\n\nOpen the nav and also a specific sub menu. Each level sub menu has its own index that is relative to that level, not the parent menu.\n\n```js\nNav.open(2, 1);\n```\nAbove code will open the nested menu in the example structure bellow:\n\n```html\n\u003cnav\u003e\n  \u003cul\u003e\u003c!-- Level: 0 --\u003e\n    \u003cli\u003e\u003c/li\u003e\n    \u003cli\u003e\n      \u003cul\u003e\u003c!-- Level: 1, Index 0 --\u003e\n        \u003cli\u003e\n          \u003cul\u003e\u003c!-- Level: 2, Index: 0 --\u003e\n            \u003cli\u003e\u003c/li\u003e\n            \u003cli\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n\n          \u003cul\u003e\u003c!-- Level: 2, Index: 1 --\u003e\n            \u003cli\u003e\u003c/li\u003e\n            \u003cli\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003c/li\u003e\n    \u003cli\u003e\n      \u003cul\u003e\u003c!-- Level: 1, Index 1 --\u003e\n        \u003cli\u003e\n          \u003cul\u003e\u003c!-- Level: 2, Index: 2 --\u003e\n            \u003cli\u003e\u003c/li\u003e\n            \u003cli\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/nav\u003e\n```\n\n### .close()\n\nCloses the nav if open.\n\n```js\nNav.close();\n```\n\n### .toggle()\n\nToggles (open/close) the nav.\n\n```js\nNav.toggle();\n```\n\n### .on(eventName, cb)\n\nAttach [Event](#events) listener to the nav.\n\n```js\nNav.on('close', function() {\n  // do something on close\n});\n```\n\n### .off(eventName, cb)\n\nRemove [Event](#events) listener from the nav.\n\n```js\n// remove specific function\nNav.off('close', onCloseFunction);\n\n// remove all event listeners\nNav.off('close');\n```\n\n## Events\n\n| Event | Description |\n|-------|-------------|\n| **open** | Triggers each time after nav is opened. |\n| **open.level** | Triggers each time after any level is opened. |\n| **close** | Triggers each time after nav is closed. |\n| **close.once** | Triggers only the first time after nav is closed, and than it detaches itself. |\n| **close.level** | Triggers each time after any level is closed. |\n| **toggle** | Triggers each time nav is triggered to be opened or closed. |\n\nAll events return Event object as first argument, and the plugin Settings object as second argument.\n\n- `open.level` and `close.level` return the newly opened level and index under the `Event.data` property.\n- `toggle` event returns the action under the `Event.data` property.\n\nOpen and close events are triggered after the nav animation is over, whie toggle event gets triggered imediatelly.\n\nExamples:\n\n```js\n// change nav open position after each close\nNav.on('close', function(e, settings) {\n  Nav.update({\n    position: settings.position === 'left' ? 'right' : 'left'\n  });\n});\n\n// will change nav open position only once\nNav.on('close.once', function(e, settings) {\n  Nav.update({\n    position: settings.position === 'left' ? 'right' : 'left'\n  });\n});\n\nNav.on('open.level', (e, settings) =\u003e {\n  localStorage.setItem('NavLevel', e.data.currentLevel);\n  localStorage.setItem('NavIndex', e.data.currentIndex);\n});\n\nNav.on('close.level', (e, settings) =\u003e {\n  localStorage.setItem('NavLevel', e.data.currentLevel);\n  localStorage.setItem('NavIndex', e.data.currentIndex);\n});\n\nNav.on('toggle', (e, settings) =\u003e {\n  if (e.data.action == 'open') {\n    // do something when `open` action is triggered\n  }\n});\n```\n\n\n## Data Attributes\n\n| Attr | Accepts | HTML Element | Description |\n|------|---------|--------------|-------------|\n| **data-nav-active** | | `\u003cul\u003e`, `\u003cli\u003e` | The next time nav opens it will open specified sub menu (or sub menu whose parent `\u003cli\u003e` element has the attribute). Works with [`expanded`](#options) option. |\n| **data-nav-highlight** | | `\u003cli\u003e` | Highlight list item. |\n| **data-nav-custom-content** | | `\u003cli\u003e` | Attached on the list items. Will clone item's content as is. |\n| **data-nav-close** | bool | `\u003ca\u003e` | Attached on the item links. Tells the nav if it needs to be closed on click or not. |\n\n```html\n\u003cnav id=\"main-nav\"\u003e\n  \u003cul\u003e\n    \u003cli data-nav-custom-content\u003e\n      \u003cdiv\u003eSome custom content\u003c/div\u003e\n    \u003c/li\u003e\n    \u003cli data-nav-highlight\u003e\u003ca href=\"#\"\u003eHome\u003c/a\u003e\u003c/li\u003e\n    \u003cli data-nav-active\u003e\n      \u003ca href=\"#\"\u003eAbout\u003c/a\u003e\n      \u003cul data-nav-active\u003e\u003c!-- or active attribute can be here --\u003e\n        \u003cli\u003e\u003ca href=\"#\"\u003eTeam\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#\"\u003eProject\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#\"\u003eServices\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca data-nav-close=\"false\" href=\"#\"\u003eAdd Page\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/nav\u003e\n```\n\n\n### WordPress data attributes integration\n\nIf you want to make your WordPress theme nav data ready, just place this code to your `functions.php` file and it should work out of the box. \u003cstrong\u003eDo not assign this custom Walker to your `wp_nav_menu` arguments!\u003c/strong\u003e And don't worry if you already use your own custom Walker, this code will take care of everything.\n\n```php\n/*\n * Adds menu data support for HC Off-canvas Nav\n */\n\n$hc_nav_menu_walker;\n\nclass HC_Walker_Nav_Menu extends Walker_Nav_Menu {\n\n  public function start_lvl(\u0026$output, $depth = 0, $args = array()) {\n    global $hc_nav_menu_walker;\n    $hc_nav_menu_walker-\u003estart_lvl($output, $depth, $args);\n  }\n\n  public function end_lvl(\u0026$output, $depth = 0, $args = array()) {\n    global $hc_nav_menu_walker;\n    $hc_nav_menu_walker-\u003eend_lvl($output, $depth, $args);\n  }\n\n  public function start_el(\u0026$output, $item, $depth = 0, $args = array(), $id = 0) {\n    global $hc_nav_menu_walker;\n\n    $item_output = '';\n\n    $hc_nav_menu_walker-\u003estart_el($item_output, $item, $depth, $args, $id);\n\n    if ($item-\u003ecurrent_item_parent) {\n      $item_output = preg_replace('/\u003cli/', '\u003cli data-nav-active', $item_output, 1);\n    }\n\n    if ($item-\u003ecurrent) {\n      $item_output = preg_replace('/\u003cli/', '\u003cli data-nav-highlight', $item_output, 1);\n    }\n\n    $output .= $item_output;\n  }\n\n  public function end_el(\u0026$output, $item, $depth = 0, $args = array(), $id = 0) {\n    global $hc_nav_menu_walker;\n    $hc_nav_menu_walker-\u003eend_el($output, $item, $depth, $args, $id);\n  }\n}\n\nadd_filter('wp_nav_menu_args', function($args) {\n  global $hc_nav_menu_walker;\n\n  if (!empty($args['walker'])) {\n    $hc_nav_menu_walker = $args['walker'];\n  }\n  else {\n    $hc_nav_menu_walker = new Walker_Nav_Menu();\n  }\n\n  $args['walker'] = new HC_Walker_Nav_Menu();\n\n  return $args;\n});\n```\n\n\n\n## Dev Building\n\nThis package comes with [Gulp](https://gulpjs.com/). The following tasks are available:\n\n  * `default` compiles the JS and SCSS into `/dist` and builds the demos into `/docs`.\n  * `demo` executes `default` task and opens the demo html page.\n  * `watch` watches source JS and SCSS files and builds them automatically whenever you save.\n\nYou can pass a `--dev` command if you don't want the compiled JS and Css to be minified.\n\n\n\n## License\n\nThe code and the documentation are released under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomewebmedia%2Fhc-offcanvas-nav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsomewebmedia%2Fhc-offcanvas-nav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomewebmedia%2Fhc-offcanvas-nav/lists"}