我有几个这样的菜单:
// Contextual Menu
// triggers
<div id="contextMenuTrigger0">0</div>
<div id="contextMenuTrigger1">1</div>
// menu
<div dojoType="dijit.Menu"
targetNodeIds="contextMenuTrigger0, contextMenuTrigger1"
leftClicktoOpen="true" style="display:none">
<div dojoType="dijit.MenuItem" class="first">Item One</div>
<div dojoType="dijit.MenuItem">Item Two</div>
<div dojoType="dijit.MenuItem">Item Three</div>
<div dojoType="dijit.MenuItem">Item Four is really, really long item.</div>
</div>
和此:
// Tools Menu
// trigger
<div id="toolsButton">Tools</div>
// menu
<div dojoType="dijit.Menu" class="toolsMenu"
targetNodeIds="toolsButton"
leftClicktoOpen="true" style="display:none">
<div dojoType="dijit.MenuItem" class="first">Item One</div>
<div dojoType="dijit.MenuItem">Item Two</div>
<div dojoType="dijit.MenuItem">Item Three</div>
<div dojoType="dijit.MenuItem">Item Four</div>
</div>
现在,当菜单打开时,它会显示在鼠标下方。我希望它出现在相对于触发器*的特定位置。我找到了启动和onOpen事件,并尝试编写一个函数来设置菜单的domNode的样式,但它们似乎没有生效。
另外,在没有多个节点的情境中,我没有找到找出哪个节点是触发器的方法。
* FWIW,我希望它们的位置使菜单的左上角与上下文触发器的右上角对齐,并与工具菜单的左下角对齐。
答案 0 :(得分:4)
我发现以下css覆盖效果很好,如果你只是想要自动定位的相对差异:
.dijitMenuPopup {
margin-left: -25px !important;
margin-top: 15px !important;
}
答案 1 :(得分:3)
事实证明,dojo.popup.open(我猜是菜单继承自)有一个参数(orient),您可以使用该参数来定位相对于节点的菜单。我最终定义了一个知道如何利用它的自定义触发器类。 (我还为其他具有不同方向的菜单类型创建了子类,但为了清楚起见,我会将它们留下来。)
UPDATE :根据this page,我不推荐在templateString中使用的变量替换方法。相反,你应该创建一个attributeMap,我在下面做了。
http://docs.dojocampus.org/quickstart/writingWidgets
// Define a basic MenuTrigger
dojo.declare("my.MenuTrigger", [dijit._Widget, dijit._Templated], {
// summary:
// A button that shows a popup.
// Supply label and popup as parameter when instantiating this widget.
label: null,
orient: {'BL': 'TL', 'BR': 'TR'}, // see http://api.dojotoolkit.org/jsdoc/1.3.2/dijit.popup.__OpenArgs (orient)
templateString: "<a href='#' class='button enabled' dojoAttachEvent='onclick: openPopup' onClick='return false;' ><span dojoAttachPoint='labelNode'></span></a>",
disabled: false,
attributeMap: {
label: {
node: "labelNode",
type: "innerHTML"
}
},
openPopup: function(){
if (this.disabled) return;
var self = this;
dijit.popup.open({
popup: this.popup,
parent: this,
around: this.domNode,
orient: this.orient,
onCancel: function(){
console.log(self.id + ": cancel of child");
},
onExecute: function(){
console.log(self.id + ": execute of child");
dijit.popup.close(self.popup);
self.open = false;
}
});
this.open = true;
},
closePopup: function(){
if(this.open){
console.log(this.id + ": close popup due to blur");
dijit.popup.close(this.popup);
this.open = false;
}
},
toggleDisabled: function() {
this.disabled = !this.disabled
dojo.toggleClass(this.domNode, 'buttonDisabled');
dojo.toggleClass(this.domNode, 'enabled');
dojo.attr(this.domNode, 'disabled', this.disabled);
},
_onBlur: function(){
// summary:
// This is called from focus manager and when we get the signal we
// need to close the drop down
// (note: I don't fully understand where this comes from
// I couldn't find docs. Got the code from this example:
// http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/_base/test_popup.html
this.closePopup();
}
});
// create some menus & triggers and put them on the page
dojo.addOnLoad(function(){
// MENU
cMenu = new dijit.Menu();
cMenu.addChild(new dijit.MenuItem({ label: "First Item" }));
cMenu.addChild(new dijit.MenuItem({ label: "Second Item" }));
cMenu.addChild(new dijit.MenuItem({ label: "Third Item" }));
cMenu.addChild(new dijit.MenuItem({ label: "Fourth Item is truly a really, really, really long item" }));
// TRIGGER
cTrigger = new my.MenuTrigger({
id: "cTrigger",
popup: cMenu
}).placeAt(dojo.body());
cTrigger = new my.MenuTrigger({
id: "cTrigger2",
popup: cMenu
}).placeAt(dojo.byId('contextTriggerContainer2'));
});
答案 2 :(得分:0)
正如我从dijit.Menu
源代码中看到的那样,您不需要支持您想要的功能
我能想到的是声明一个继承自dijit.Menu
并覆盖bindDomNode
方法的新小部件。它将_openMyself
处理程序绑定到onClick事件,如下所示:
dojo.connect(cn, (this.leftClickToOpen)?"onclick":"oncontextmenu", this, "_openMyself")
_openMyself
处理程序从作为参数出现的事件对象中获取coords
因此,我们的想法是使用所需的坐标传递一个伪造的事件对象。
dojo.connect(cn, (this.leftClickToOpen)?"onclick":"oncontextmenu", this, function(){
var e = { target: desiredTarget, pageX: desiredX, pageY: desiredY };
this._openMyself(e);
});