josdejong / jsoneditor

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

Feature request - events handling with more informations #39

Open Arkhee opened 11 years ago

Arkhee commented 11 years ago

Hi, I want to use jsoneditor in a large project, but to do so I need to interact more deeply with the editor. To do so I need to handle events like : click, double click, right click, etc. I patched the latest editor release but I'm unsure how to submit my modifications si here is a proposition : Line 2753 add :

case 'contextmenu':
if(this.editor.options.contextmenu) this.editor.options.contextmenu(event,target,dom,node);
break;

Line 2735 add :

             case 'dblclick':
                if(this.editor.options.dblclick) this.editor.options.dblclick(event,target,dom,node);
                break;
            case 'click':
                if(this.editor.options.click) this.editor.options.click(event,target,dom,node);
                break;

Line 2711 add :

           case 'contextmenu':
                if(this.editor.options.contextmenu) this.editor.options.contextmenu(event,target,dom,node);
                break;

Line 2693 add :

            case 'dblclick':
                if(this.editor.options.dblclick) this.editor.options.dblclick(event,target,dom,node);
                break;

Line 2662 add :

    // Modif YB
    if(type == 'click' && this.editor.options.click) this.editor.options.click(event,target,dom,node);

Line 524 add :

    // Modif YB oncontextmenu
    this.frame.oncontextmenu = function (event) {
        onEvent(event);
        jsoneditor.util.preventDefault(event);
        return false;
    };  
    // Modif YB ajout du dblclick
    this.frame.ondblclick = function (event) {
        onEvent(event);

        // prevent default submit action when JSONEditor is located inside a form
        jsoneditor.util.preventDefault(event);
    };

This allows me basically to fully handle events, including interacting with the clicked elements etc.

josdejong commented 11 years ago

Interesting idea. This will give you as developer indeed more flexibility to interact with the editor. I'm still thinking about how to shape this in a compact but flexible way. JSONEditor uses one delegated onEvent handler. So maybe it is enough to be able to define one generic event callback handler like:

var options = {
    // ...
    event: function (event, node) {...}   // onEvent callback handler
};

Where the event parameter is the original HTML Event, and the node param is the Node on which the event took place. From the event you can read the type (click, dblclick, etc), the target, and a lot more. And from the node you can retrieve the complete dom structure, the value, etc.

Arkhee commented 11 years ago

You're right about the generic event callback, it would be basically the same. However there are a few small differences that should be considered :

As for the parameters, I would recommend keeping the "target" param at least : because when clicking on a node it allows you to know if the field or the value was clicked, which is critical if you want to change either the field or the value from outside. So the parameters would be : event, target, node Not sure the dom param is usefull.

Another point regarding the API : I tried to add subelements in an object or array. I did as follow, inside a "double click event" :

        node._onInsertAfter('test', 'toto', 'string');
        if(node.type=="object" || node.type=="array")
        {
            var createdNode=node._nextNode();
            var nodePrev=node.childs[0];
            node.moveBefore(createdNode, nodePrev);
        }

I'm not sure it's the best solution, but I noticed I need to call "private" methods ( underscore prefixed). I believe such things as : add node after, add node inside, remove, move, update field, update value, should be done with a simple api call. Actually I think the only missing method would be : add node inside, right ?

Regarding new methods, I think it would be interesting to have to new easy to use functions :

What do you think of these ? Do they already exist ? (I must confess I did not check on those 2)

josdejong commented 11 years ago

Thanks for your thoughts.

I think we should reckon two types of developers who may use the editor:

The first group is happy to set some options and a callback on change of the data, maybe override the style of the editor and that's it.

For the second group (you are amongst them I suppose), the editor as it is comes close to what they need, but misses some essential things for their specific use case. They want to integrate the editor tightly in a large web application. They want to manipulate the internals of the editor: Nodes, HTML Events, HTML DOM, etc. This requires knowledge about how the editor internally works, else you can easily mess up the DOM, node tree, history, etc.

The first group does not want to know about these internals, whilst the second group does want easy access to it. Trying to create one API for both groups would definetely fail: the first group will drown in a complex, extensive API, and the second group will never have enough options for all their specific needs.

I think the API should aim for the first group of developers, and should be clean, compact, and straightforward. For the second group, the internal structure of the editor should be as easy as possible to adjust and extend, and I'm sure we can improve on that a lot. It should be easy to extend the JSONEditor prototype with your own MySuperJSONEditor prototype, override and extend some methods and event handlers and tune it as you wish.

Arkhee commented 11 years ago

I agree with you about the two groups, but actually I think I'm still in the first one : I surely don't wan't to touch the editor's internal, since any modification could be lost with the next update. As a member of the group one I would need a simple but durable API, that allows a simple access to basic tasks. If you look at it as model-controler, I believe the API should allow roughly the same basic interactions the user has with the mouse and keyboard, without modification of the library itself, and I think the current state of the lib is very close to that state. When you say the lib shoud be "should be clean, compact, and straightforward" what does that involve exactly ?

For me, there are two axes :

Anything else should probably developped outside of the lib IMHO : like for example context menu to change a field label or value, automatically adding subitems to an object etc.

josdejong commented 11 years ago

Nice discussion. I think we are on the same page, though our idea on what should be "standard" functionality differs a little. I try to beware of feature creep, that is why I want to keep the API simple and concise.

For you, manipulating HTML events and the node tree should be standard functionality, but for me this falls under the "advanced" usage, as (right now) these kind of manipulations require you to have knowledge of the internal workings of the Editor - you can mess up stuff when not doing this correctly.

So far I only focused on exposing a simple API for using the Editor as is, with just a few configuration options. I didn't focus on an API allowing you to manipulate nodes, the node tree, the actions menu, etc. This "advanced" API is almost there though, with private methods like _onInsertAfter. It wouldn't be too hard to make these methods more robust and complete, document them, and open up this "advanced" API.

Maybe we end up with three levels of API:

Arkhee commented 11 years ago

I completely agree with the three levels you describe, but now, as everyone has limited time ressources, you probably have to make a choice : what to develop first. I don't know your roadmap, but I think a good thing would be to implement the event handler very first, since after this working the current "private" methods would be fine for an advanced developper. Making this move first would limit the need to patch the lib, and thus allow developers to follow the updates on a more regular basis, which is the aim I think. Also I would recommend to keep backward compatibility on these private methods for some time in the futur. As you saw on my first post, I did a "quick-and-dirty" patch that took me 6 small modifications to have a basic and satisfying (IMO) event handler. it's not very elaborate but still usable I think.

josdejong commented 11 years ago

Indeed, working out this API will make the editor much more versatile in usage.

So far the focus has been on the end user: making a nicely working editor. With the recent release of version 2, these editing features start to mature. Currently I'm replacing the plain text editor with Ace (see beta), replacing the build script with jake, and merging/reorganizing the code. After that I hope to address the API, documentation, and examples. And another important wish is to improve the performance of the editor with large files.

Asc2011 commented 7 years ago

Hi Jos, great to see how Jsoneditor matured over time 👍 thx for all the work you've done. I believe that the editor will be used as a UI-component alongside others. At least thats my case. I have a category/subcategory-tree, made with D3js and two json-editors in the UI. The user selects a category and by pressing TAB he jumps right into the editor. If we have a schema for the category-data, then the second editor displays that schema. As more UI-components are likely to come, i decided to decouple all myJS-libs using a pub/sub-lib called postalJS. The one thing that would help me is a event-emitter on the js-editor - can an be a callback as already proposed here. At the moment i wrap the editor in a simple-class the consumes the triggered events 'error', 'changed', 'modeChanged', etc. by intercepting the called handlers. I did this using plain JS - since i now learned Proxies arrived at JS i'd use these. Now i can trigger focus, mode-changes, set and retrieve the editors contents and trigger schema-validation. I can't define a keyboard-shortcut to regain focus yet. If the editor would emit a event when the user pressed a predefined key. So i/(one of the other listening components) could respond to this. A event-emitter would be a nice thing to have. So i guess that makes me a member of group-2 ? Whats the status on eventing with jsoneditor ? greets Andreas

josdejong commented 7 years ago

Thanks for your input @Asc2011 . I've recently started rewriting JSONEditor from scratch (see this branch), with an architecture allowing customization via hooks. The onChange event will pass a JSON patch object and the editor will get new methods like patch to update the current JSON. There will be hooks to customize the ContextMenu and main menu, and more. It's far from finished but the progress is steady.

LucianViana commented 6 years ago

I am using the jsoneditor with sceditor editor and I could not use the code and no error occurred but did not display the message, was it just an idea in speech or is there such an option? var options = { // ... event: function (event, node) {...} // onEvent callback handler }; I did so: var editor = new JSONEditor(document.getElementById('editor_holder'),{ schema: { type: "object", title: "Texto:", properties: { texto: { type: "string", format: "html", options: { wysiwyg: true, event: function (event, node) {alert("teste event = " + event);} } } } }, disable_array_add: true, disable_array_delete: true, disable_array_delete_all_rows: true, disable_array_delete_last_row: true, disable_array_reorder: true, disable_collapse: true, disable_edit_json: true, disable_properties: true }); thank you

josdejong commented 6 years ago

This event handling API is indeed not yet implemented.

trsh commented 6 years ago

Need this also badly