josdejong / jsoneditor

A web-based tool to view, edit, format, and validate JSON
http://jsoneditoronline.org
Apache License 2.0
11.62k stars 2.04k forks source link

Add ability to customize key shortcuts #148

Open alechenninger opened 9 years ago

alechenninger commented 9 years ago

I'm not really a huge fan of the keyboard shortcuts. The most obvious to me -- create a new node after current and move to it -- is one of the most awkward to use ("ctrl+shift+insert").

I can see that allowing this to be customized might not be that difficult to do, I can open a pull request if we can agree on a basic strategy before I attempt it.

What jumps out to me is to have a keybinds parameter as an option, which is a map of shortcut names to key codes. Instead of hard coding the keycodes, the different modes would look up the shortcut from this.options.keybinds[THE_KEYBIND_NAME] and the different elements (Node, Searchbox, etc) would look it up from this.editor.options.keybinds[THE_KEYBIND_NAME]. Then document all of the keybind names. A default keybinds object would exist, and any passed in keybinds would simply overwrite the default setting where a property was present.

What do you think?

alechenninger commented 9 years ago

Expanding on this a bit more (has to support modifier keys, and can be a little more object oriented):

Something like:

function Keybind(config) {
  this.key = config.key;
  this.ctrl = config.ctrl || false;
  this.shift = config.shift || false;
  this.alt = config.alt || false;
};

// Method name could be less verbose... tried to pick consistent terminology with 
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
Keybind.prototype.isRepresentedBy(keyEvent) {
  var key = keyEvent.which || event.keyCode;
  return this.key === key &&
      this.ctrl === keyEvent.ctrlKey &&
      this.shift === keyEvent.shiftKey &&
      this.alt === keyEvent.altKey;
}

// Usage...
var options = {
  keybinds: {
    duplicateNode: new Keybind({key: 68, ctrl: true})
  }
};

new JSONEditor(document.getElementById("editor"), options);

// Node.js
Node.prototype.onKeyDown = function(event) {
  var keybinds = this.editor.options.keybinds;
  // snip
  } else if (editable && keybinds.duplicateNode.isRepresentedBy(event)) {
    this._onDuplicate();
    handled = true;
  } // etc.
}
josdejong commented 9 years ago

Thanks, good idea. Maybe we also need to change the default quick keys... What would be your choice?

alechenninger commented 9 years ago

Cool, I'll work on a PR.

My default choice for insert? Hrm. Probably like ctrl-enter or something like that but I'd have to play around. At the very least, I would recommend swapping the append and insert keys: so adding a node after the current and moving to it would be ctrl-insert, and adding a node before the current and moving to it would be ctrl-shift-insert. My guess is most folks will move top -> down sequentially when building the json, as you would in a code editor, so inserting sequentially should be less keys to press IMHO.

sbliven commented 4 years ago

I keep wanting to use shift-enter to insert a node below. This is consistent with jupyter notebooks, for instance. Another option would be to make enter the default so that tree mode behaves a bit like text mode. To insert a newline character in a string one would have to use shift-enter. This is consistent with chat programs (e.g. slack).

This is currently my most desired feature of jsoneditor. I'll see if I can manage to implement it myself since the issue has been open quite a while.

josdejong commented 4 years ago

Thanks @sbliven , would be nice if you can look into making quickkeys customizable.