PDA

View Full Version : 右クリック不可能なメニュー



Kazuhiro Kotsutsumi
24 Mar 2009, 12:43 PM
コンテキストメニューやツールバーのメニューで、Ext.menu.Menukクラスを使う機会があると思います。

このExt.menu.Menuクラスは、内部的に右クリックのイベントを制御していません。
そのため、contextmenuなどのイベントも起きません。

従って、コンテキストメニューの上で、さらに右クリックするとブラウザのコンテキストメニューが表示されてしまいます。なにげに右クリックをダブルクリックしてしまう人もいるようで、マウスの調子とか。

それを修正するパッチを作りました。
取り急ぎ、2.2.1用です。
ちなみに、Right Click Cancel Menuの略です。
パッチを当てたあとのメニューオブジェクトはcontextmenuイベントを発行するようになっています。
何か処理をしたいときは、リスナーを設定してください。


RCCMenu.js


/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

// {{{ Ext.ux.override.RCCMenu

/**
* Ext.ux.override.RCCMenu
*
* 右クリックキャンセルメニュー
*
* @author Kazuhiro Kotsutsumi <kotsutsumi@xenophy.com>
*/
if( Ext.version === '2.2.1' ) {

Ext.override( Ext.menu.Menu, {

// private
render : function(){

if(this.el){
return;
}
var el = this.el = this.createEl();

if(!this.keyNav){
this.keyNav = new Ext.menu.MenuNav(this);
}
if(this.plain){
el.addClass("x-menu-plain");
}
if(this.cls){
el.addClass(this.cls);
}
// generic focus element
this.focusEl = el.createChild({
tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
});
var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
ul.on("click", this.onClick, this);
ul.on("mouseover", this.onMouseOver, this);
ul.on("mouseout", this.onMouseOut, this);

// 右クリックキャンセル処理
ul.on("contextmenu", function( e, t ) {

if( this.fireEvent("contextmenu", this, e, t) ) {
e.stopEvent();
}

}, this);

this.items.each(function(item){
var li = document.createElement("li");
li.className = "x-menu-list-item";
ul.dom.appendChild(li);
item.render(li, this);
}, this);
this.ul = ul;
this.autoWidth();
}

// }}}

});

}

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/

yuki
24 Mar 2009, 11:43 PM
ちなみに、this.ulのイベントハンドラーって解除処理が必要じゃないですか?:D

Kazuhiro Kotsutsumi
29 Mar 2009, 2:41 AM
ちなみに、this.ulのイベントハンドラーって解除処理が必要じゃないですか?:D

思いますが、サボってます。
monにしてしまうのがいいのかな?

Kazuhiro Kotsutsumi
12 Apr 2009, 9:24 AM
renderからonRenderに変わったのと、monになっていたのであわせました。


/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

// {{{ Ext.ux.override.RCCMenu

/**
* Ext.ux.override.RCCMenu
*
* 右クリックキャンセルメニュー
*
* @author Kazuhiro Kotsutsumi <kotsutsumi@xenophy.com>
*/
if( Ext.version === '2.2.1' ) {

Ext.override( Ext.menu.Menu, {

// private
render : function(){

if(this.el){
return;
}
var el = this.el = this.createEl();

if(!this.keyNav){
this.keyNav = new Ext.menu.MenuNav(this);
}
if(this.plain){
el.addClass("x-menu-plain");
}
if(this.cls){
el.addClass(this.cls);
}
// generic focus element
this.focusEl = el.createChild({
tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
});
var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
ul.on("click", this.onClick, this);
ul.on("mouseover", this.onMouseOver, this);
ul.on("mouseout", this.onMouseOut, this);

// 右クリックキャンセル処理
ul.on("contextmenu", function( e, t ) {

if( this.fireEvent("contextmenu", this, e, t) ) {
e.stopEvent();
}

}, this);

this.items.each(function(item){
var li = document.createElement("li");
li.className = "x-menu-list-item";
ul.dom.appendChild(li);
item.render(li, this);
}, this);
this.ul = ul;
this.autoWidth();
}

// }}}

});

} else if( Ext.version === '3.0' ) {

Ext.override( Ext.menu.Menu, {

// private
onRender : function(ct, position){
if(!ct){
ct = Ext.getBody();
}

var dh = {
id: this.getId(),
cls: 'x-menu ' + ((this.floating) ? 'x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
style: this.style,
cn: [
{tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
{tag: 'ul', cls: 'x-menu-list'}
]
};
if(this.floating){
this.el = new Ext.Layer({
shadow: this.shadow,
dh: dh,
constrain: false,
parentEl: ct,
zindex:15000
});
}else{
this.el = ct.createChild(dh);
}
Ext.menu.Menu.superclass.onRender.call(this, ct, position);

if(!this.keyNav){
this.keyNav = new Ext.menu.MenuNav(this);
}
// generic focus element
this.focusEl = this.el.child('a.x-menu-focus');
this.ul = this.el.child('ul.x-menu-list');
this.mon(this.ul, 'click', this.onClick, this);
this.mon(this.ul, 'mouseover', this.onMouseOver, this);
this.mon(this.ul, 'mouseout', this.onMouseOut, this);

// 右クリックキャンセル処理
this.mon(this.ul, 'contextmenu', function( e, t ) {

if( this.fireEvent("contextmenu", this, e, t) ) {
e.stopEvent();
}

}, this);

if(this.enableScrolling){
this.mon(this.el, 'click', this.onScroll, this, {delegate: '.x-menu-scroller'});
this.mon(this.el, 'mouseover', this.deactivateActive, this, {delegate: '.x-menu-scroller'});
}
},
});

}

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/