{"id":19863867,"url":"https://github.com/sandialabs/chordly","last_synced_at":"2025-12-12T04:06:53.881Z","repository":{"id":51160590,"uuid":"11642695","full_name":"sandialabs/Chordly","owner":"sandialabs","description":"Chordly is a javascript library that may be used to detect and act upon key sequences entered by a user.","archived":false,"fork":false,"pushed_at":"2025-01-26T22:32:08.000Z","size":168,"stargazers_count":18,"open_issues_count":5,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-06T22:42:39.888Z","etag":null,"topics":["chord","chordly","event","events","hacktoberfest","hot-keys","hotkeys","javascript","keyboard","keyboard-events","keyboard-listeners","keyboard-navigation","keyboard-shortcuts","keydown","keypress","keyup","konami","mousehate","scr-2414","snl-other"],"latest_commit_sha":null,"homepage":"","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/sandialabs.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":"SECURITY.md","support":null}},"created_at":"2013-07-24T18:57:59.000Z","updated_at":"2025-02-19T21:05:52.000Z","dependencies_parsed_at":"2022-08-31T02:11:37.400Z","dependency_job_id":null,"html_url":"https://github.com/sandialabs/Chordly","commit_stats":null,"previous_names":["rheone/jquery.chord"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2FChordly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2FChordly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2FChordly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2FChordly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandialabs","download_url":"https://codeload.github.com/sandialabs/Chordly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251992548,"owners_count":21677018,"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":["chord","chordly","event","events","hacktoberfest","hot-keys","hotkeys","javascript","keyboard","keyboard-events","keyboard-listeners","keyboard-navigation","keyboard-shortcuts","keydown","keypress","keyup","konami","mousehate","scr-2414","snl-other"],"created_at":"2024-11-12T15:16:21.265Z","updated_at":"2025-12-12T04:06:48.590Z","avatar_url":"https://github.com/sandialabs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\nchordly is a plug-in library that lets you detect and act upon user keyboard input. This is accomplished by wiring Chordly up to listen for key sequences, known as chords, entered by a user.\n\nChordly was inspired by John Resig's [jQuery.hotkeys](https://github.com/jeresig/jquery.hotkeys). Though we are big fans of jQuery.hotkeys (and John) the plugin lacks functionality we have included in Chordly.\n\nA proud supporter of #mousehate\n\n## Features\n\n- Trigger events on single, or multiple key presses. Includes Shift, Alt, and Control options\n- Cross browser compatibility\n- Custom 'chordlyMatch' event that may be listened for by user code\n- Optionally ignore input on form elements\n- Storage of user readable buffer of key presses\n- Pause and Re-Start key capturing and event firing\n- Optional automatic timeout of key buffering\n- Optional Greedy matching\n- Multiple instances allowed on a single page\n- ...\n\n## Usage\n\nChordly may be attached to any DOM node in order to listen for sequences of keyboard activity within that node and its descendants. In its simplest form Chordly can be enabled like this:\n\n```js\ndocument.querySelector(expression).pushToChordly(\"bindLiteralSequence\", \"hello\", function() {\n  console.log(\"world\");\n});\n```\n\n### Advanced Usage\n\n_Also, be sure to check out the **Code Snippet** section below that contains useful examples and hints_\n\nWhile the above is great for simple keyboard input it is Chordly's more advance uses where it begins to sing. Chordly offers a variety of configuration options and makes it easy to handle a number of key sequences with a single configuration. A more advanced form of the above would look likes this:\n\n```js\ndocument.querySelector(expression).pushToChordly({\n  sequenceMap: [\n    {\n      sequence: window.chordly.literalStringToSequence(\"hello\"),\n      matched: function() {\n        console.log(\"world\");\n      }\n    }\n  ]\n});\n```\n\nWhich admittedly looks unnecessarily more complicated until you realize it allows you to do things like this:\n\n```js\ndocument.querySelector(expression).pushToChordly(\"bind\", [\n  {\n    sequence: window.chordly.literalStringToSequence(\"mouse\"),\n    matched: function() {\n      console.log(\"squeak!\");\n    }\n  },\n  {\n    sequence: [\n      window.chordly.literalStringToSequence(\"cow\"),\n      window.chordly.literalStringToSequence(\"bull\")\n    ],\n    matched: function() {\n      console.log(\"moo!\");\n    }\n  }\n]);\n```\n\n### Options\n\nIn the above examples we are making use of Chordly's `options` object which may contain the following, otherwise defaults are used:\n\n- **captureShift** `(bool)` default: `[false]`\n  Treat shift as a key press.\n\n- **captureAlt** `(bool)` default: `[false]`\n  Treat alt as a key press.\n\n- **captureCtrl** `(bool)` default: `[false]`\n  Treat ctrl as a key press.\n\n- **ignoreFormElements** `(bool)` default: `[true]`\n  Ignore key presses within form elements\n\n- **keyEvent** `(string)` default: `[keyup]`\n  the key event that triggers listening. other options are keydown (or any event that stores the key code _not ASCII char code_ within the 'which' property of the event)\n\n- **maxBufferLength** `(int)` default: `[5]`\n  the length of the key buffer. Note that the buffer will be auto expanded in order to maintain at minimum the length of the longest sequence to be detected. Modifying this allows for a greater depth of key press history to be kept if desired\n\n- **clearBufferOnMatch** `(bool)` default: `[true]`\n  determines if the key buffer should be cleared on a match\n\n- **paused** `(bool)` default: `[false]`\n  determines if chordly on the element should start paused (not collecting key)\n\n- **bufferTimeoutMs** `(int)` default: `[0]`\n  timeout length for key buffer clearing in ms (value of \u003c1 means no timeout)\n\n- **greedyTimeoutMs** `(int)` default: `[0]`\n  timeout length since last recording of a key press before executing a match event. This is reset by next key press. (value of \u003c1 means no greedy matching)\n\n- **sequenceMap** `(object array)` default: `[empty array]`\n  an array of objects defining sequence mapping. Defaults to an empty array. Mapping object may have the following attributes\n\n- **sequence** - a sequence, array of sequences, or array of sequence parts\n  to create a sequence from a string use\n  `window.chordly.literalStringToSequence(str)`\n  or to create a part use\n  `window.chordly.makeSequencePart(keyCode, shift, alt, ctrl)`\n\n- **matched** - optional function that will be called on sequence completion\n\n- **lookup** - optional lookup code that will be passed to the custom `chordlyMatch` event on sequence completion\n\n### Methods\n\n- **clearSequenceBuffer**\n  clear the sequence buffer, effectively resetting the memory of previously pressed keys\n  `document.querySelector(expression).pushToChordly('clearSequenceBuffer')`\n\n- **destroy**\n  destroy the chordly instance unbinding events and removing data from element\n  `document.querySelector(expression).pushToChordly('destroy')`\n\n- **pause**\n  pause the chordly instance\n  `document.querySelector(expression).pushToChordly('pause')`\n\n- **resume**\n  resume the chordly instance\n  `document.querySelector(expression).pushToChordly('resume')`\n\n- **togglePause**\n  pause/resume chordly instance if was unpaused/paused\n  `document.querySelector(expression).pushToChordly('togglePause')`\n\n- **bind(args)**\n  bind new sequence(s)\n  args[0] array of sequence/lookup/matched objects to add to the sequenceMap\n\n```js\ndocument.querySelector(expression).pushToChordly('bind', {\n    sequence: window.chordly.literalStringToSequence('mouse'),\n    matched: function () {\n        console.log('squeak!')\n    }\n});\n```\n\n- **unbind(args)**\n  unbind each occurrence of a sequence\n  args[0] the sequence to unbind\n  `document.querySelector(expression).pushToChordly('unbind', window.chordly.literalStringToSequence('mouse'));`\n\n- **actOnBuffer**\n  act on data in buffer as if a listen event has occurred\n  `document.querySelector(expression).pushToChordly('actOnBuffer')`\n\n- **pushSequence(args)**\n  push a sequence onto the buffer. Not that this will not cause a listen to be fired. You must call actOnBuffer if a reaction is desired. To push and act on buffer call pushSequenceAndAct\n  args[0] sequence to push (array of sequence parts)\n  `document.querySelector(expression).pushToChordly('pushSequence', window.chordly.literalStringToSequence('dog'))`\n\n- **pushSequenceAndActOnBuffer(args)**\n  push a sequence onto the buffer and act upon it\n  args[0] sequence to push (array of sequence parts)\n  `document.querySelector(expression).pushToChordly('pushSequenceAndAct', window.chordly.literalStringToSequence('dog'))`\n\n### Events\n\nChordly also makes available a custom 'chordlyMatch' event. This event object will contain the following NEW properties:\n\n- **originalEvent** - the original triggering event event\n- **lookup** - the lookup as defined in the sequence map\n- **sequence** - the sequence that triggered the event\n- **sequenceString** - the triggering sequence as a string\n\nBelow is an example of a handler of the chordlyMatch event.\n\n```js\ndocument.querySelector(expression).addEventListener(\"chordlyMatch\", function(e) {\n  console.log(\"chordlyMatch event:\");\n  console.log(\"\\t event:\", e);\n  console.log(\"\\t lookup:\", e.lookup);\n  console.log(\"\\t sequence:\", e.sequence);\n  console.log(\"\\t sequenceString:\", e.sequenceString);\n  console.log(\"\\t originalEvent:\", e.originalEvent);\n});\n```\n\n### Code Snippets\n\nThe Sky is the limit with Chordly, or at the very least the keyboard. The following are some code examples of how chordly may be used to make interacting with your website better.\n\n#### Konami Code\n\nThis example fires of an method, in this case an alert stating \"Konami Code!\", when the Konami Code is entered.\n```js\n$(document).ready(function () {\n  document.querySelector('body').pushToChordly('bindSequence', 'UpArrow UpArrow DownArrow DownArrow LeftArrow RightArrow LeftArrow RightArrow B A Enter', function () { alert(\"Konami Code!\"); });\n});\n```\n\n#### Page Redirection\n\nThis example shows how chordly definition may be chained to have key presses of G then H, G then F, and G then A redirect the browser to home.html, faq.html, and about.html respectively\n\n```js\n$(document).ready(function () {\n  const body = document.querySelector('body');\n  body.pushToChordly('bindSequence', 'G H', function() { window.location = 'home.html'; });\n  body.pushToChordly('bindSequence', 'G F', function() { window.location = 'faq.html'; });\n  body.pushToChordly('bindSequence', 'G A', function() { window.location = 'about.html'; });\n});\n```\n\n#### Greedy Sequence Matching\n\nThis example shows how Chordly may be set up so that it will attempt to match on the longest possible key entry before defaulting to a smaller defined one. In this case entering 'cows' will not trigger the 'cow' event, yet both may still be fired.\n\n```js\n$(document).ready(function() {\n  var $document = document.querySelector(expression);\n  $document.pushToChordly({\n    bufferTimeoutMs: 400, // buffer auto-clears after 400 ms\n    greedyTimeoutMs: 225 // wait 225 ms for more keys before declaring a match\n  });\n  $document.pushToChordly(\"bindSequence\", \"C O W\", function() {\n    alert(\"one cow: Moo!\");\n  });\n  $document.pushToChordly(\"bindSequence\", \"C O W S\", function() {\n    alert(\"two cows: Moo! Moo!\");\n  });\n});\n```\n\n#### On Screen 'J/K' Style Navigation\n\nThis is an example snippet of how chordly can be used to accomplish J/K style navigation on a web page. J and K buttons may be used to optionally navigate tags marked with the 'data-selectable' attribute. Once selected a pressing the Enter key activates the link associated with the current item.\n\n_see [chordly example of J/K navigation Gist](docs/jknavigation.md)_\n\n## Copyright\n\n\u003e Copyright 2018 National Technology \u0026 Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software.\n\n## License\n\n\u003e Licensed under the Apache License, Version 2.0 (the \"License\");\n\u003e you may not use this file except in compliance with the License.\n\u003e You may obtain a copy of the License at\n\u003e\n\u003e       http://www.apache.org/licenses/LICENSE-2.0\n\u003e\n\u003e Unless required by applicable law or agreed to in writing, software\n\u003e distributed under the License is distributed on an \"AS IS\" BASIS,\n\u003e WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\u003e See the License for the specific language governing permissions and\n\u003e limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandialabs%2Fchordly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandialabs%2Fchordly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandialabs%2Fchordly/lists"}