Charles Goodwin
Charles Goodwin

Reputation: 6652

How to add a custom context menu to a textarea in Vexi?

I want to add a custom entry to the context menu in a Vexi application.

I tried adding a contextActions function but it throws an error:

<textarea>
    thisbox.contextmenu.contextActions = function() {
        return [{
            text: "Foo",
            action: function(v) { cascade = v; vexi.log.info("foo"); },
            enabled: enabled
        }]);
    }
</textarea>

How do I do this?

Upvotes: 4

Views: 375

Answers (1)

Charles Goodwin
Charles Goodwin

Reputation: 6652

To extend the existing textarea context menu implementation in a re-usable way, create a template that preapplies vexi.widget.textarea and put a read trap on the contextActions property. We can use cascade to invoke a read from that property - i.e. call the existing implementation - which returns an array. We simply add to that array:

<vexi xmlns="vexi.widget">
    <textarea>
        // overlays the trap specified in the inherited
        // org.vexi.lib.text.contextmenu by textarea
        thisbox.contextActions ++= function() {
            var actions = cascade;
            actions.push(
            new .menuitem({
                text: "Foo",
                action: function(v) { cascade = v; vexi.log.info("foo"); },
                enabled: enabled
            }));
            return actions;
        }
    </textarea>
</vexi>

Background

The key to extending an existing textarea is understanding both Traps and how the <textarea> widget inherits via preapplied templates (and the templates they preapply, etc). You can go through the widget hierarchy, starting at src/vexi/widget/textarea.t then looking up the relevant preapplies. You will eventually see that org.vexi.lib.widget.textarea preapplies org.vexi.lib.text.contextmenu and there we can see the default context menu implementation with copy/cut/paste etc.

Upvotes: 3

Related Questions