2

我正在使用ExtJS 4框架,也在Raphael.js我的主应用程序面板中使用。

首先,我试图阻止显示常规上下文菜单,我发现了非常简单的解决方案。

raphael_element.node.oncontextmenu = function()
{
    return false;
} 

这很好用,但在返回 false 之前,我想添加一些代码来显示我自己的自定义菜单。
有谁知道这是怎么做到的吗?

我在 html 中有一些东西,正在考虑在菜单中使用:

<ul id="rect_menu" class="contextMenu">
    <li><a href="call_to_js_function">Set aaa</a></li>
    <li><a href="call_to_js_function">Set xxx</a></li>
    <li><a href="call_to_js_function">Set ccc</a></li>
</ul>

如您所见,我有css class(代码不在这里,它无关紧要)用于样式并id=rect_menu在用户右键单击ie Raphael 矩形对象时显示。

任何人都可以展示一种方式,也许是不涉及 jquery 的小型演示?纳克斯

4

2 回答 2

3

您可以使用 Ext 在浮动组件中显示您的自定义 HTML:

var menu = Ext.create('Ext.Component', {
    floating: true
    ,html: ['<ul id="rect_menu" class="contextMenu">',
        '<li><a href="call_to_js_function">Set aaa</a></li>',
        '<li><a href="call_to_js_function">Set xxx</a></li>',
        '<li><a href="call_to_js_function">Set ccc</a></li>',
        '</ul>'].join('')
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

但是,显示菜单并不是棘手的部分。隐藏菜单的逻辑,无论是当用户点击它之外,还是按下 ESC 键时,都涉及更多。这就是为什么我会使用常规Menu让 Ext 为我们完成繁重的工作。

var menu = Ext.create('Ext.menu.Menu', {
    items: [{
        text: 'Set aaa'
        ,handler: function() {
            // logic for aaa
        }
    }, {
        text: 'Set bbb'
        ,handler: function() {
            // logic for bbb
        }
    }]
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

现在,如果您对使用所有菜单系统、Ext 菜单项等不感兴趣,并且您真的想呈现自己的 HTML,您仍然可以利用 Ext 菜单从其隐藏机制中受益:

var menu = Ext.create('Ext.menu.Menu', {
    // This will prevent the icon gutter from showing, and your component from
    // being left padded
    plain: true
    ,items: [{
        xtype: 'component'
        ,html: ['<ul id="rect_menu" class="contextMenu">',
            '<li><a href="call_to_js_function">Set aaa</a></li>',
            '<li><a href="call_to_js_function">Set xxx</a></li>',
            '<li><a href="call_to_js_function">Set ccc</a></li>',
            '</ul>'].join('')
    }]
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

这是使用最后一个示例的小提琴。它不使用 Raphael,但从你得到一个不具有任何重要性的 DOM 元素的那一刻起。

使用实际 Raphael 元素编辑示例

我用实际的拉斐尔元素更新了我的小提琴。它确实按预期工作。

很酷的是元素的点击事件完全尊重矢量路径边界,这意味着您可以精确地决定菜单将在哪里弹出或不弹出。不那么酷的是,例如,著名的tiger,这将意味着 240 个事件处理程序......在性能方面有点糟糕......你总是可以将处理程序添加到 SVG 元素而不是单个形状元素,但是当然,菜单将绑定到整个绘图矩形而不是单个部分。

// --- Creating a ball (see http://raphaeljs.com/ball.html)
Raphael.fn.ball = function (x, y, r, hue) {
    hue = hue || 0;
    return this.set(
        this.ellipse(x, y + r - r / 5, r, r / 2).attr({fill: "rhsb(" + hue + ", 1, .25)-hsb(" + hue + ", 1, .25)", stroke: "none", opacity: 0}),
        this.ellipse(x, y, r, r).attr({fill: "r(.5,.9)hsb(" + hue + ", 1, .75)-hsb(" + hue + ", .5, .25)", stroke: "none"}),
        this.ellipse(x, y, r - r / 5, r - r / 20).attr({stroke: "none", fill: "r(.5,.1)#ccc-#ccc", opacity: 0})
    );
};

var R = Raphael("holder"), x = 310, y = 180, r = 150;
var ball = R.ball(x, y, r, Math.random());

// --- Creatin a custom menu
var menu = Ext.create('Ext.menu.Menu', {
    plain: true
    ,cls: 'myContextMenu'
    ,items: [{
        xtype: 'component'
        ,html: ['<ul id="rect_menu" class="contextMenu">',
            '<li><a href="call_to_js_function">Set aaa</a></li>',
            '<li><a href="call_to_js_function">Set xxx</a></li>',
            '<li><a href="call_to_js_function">Set ccc</a></li>',
            '</ul>'].join('')
    }]
});

// --- Adding menu handler to all ball's elements

var contextMenuHandler = function(e) {
    menu.showAt(e.getXY());
    e.preventDefault();
};

Ext.each(ball, function(raphaelElement) {
    Ext.fly(raphaelElement.node).on({
        contextmenu: contextMenuHandler
    });
});
于 2013-08-05T07:44:41.997 回答
0

这也很好用,并且在 MIT 许可下

https://swisnl.github.io/jQuery-contextMenu//

JsFiddle(从上面的链接复制的示例)

$(function() {
    $.contextMenu({
        selector: '.context-menu-one', 
        callback: function(key, options) {
            var m = "clicked: " + key;
            window.console && console.log(m) || alert(m); 
        },
        items: {
            "edit": {name: "Edit", icon: "edit"},
            "cut": {name: "Cut", icon: "cut"},
           copy: {name: "Copy", icon: "copy"},
            "paste": {name: "Paste", icon: "paste"},
            "delete": {name: "Delete", icon: "delete"},
            "sep1": "---------",
            "quit": {name: "Quit", icon: function(){
                return 'context-menu-icon context-menu-icon-quit';
            }}
        }
    });

    $('.context-menu-one').on('click', function(e){
        console.log('clicked', this);
    })    
});
于 2019-03-22T10:04:35.183 回答