2010-02-03 28 views
2

我有一对夫妇的菜单是这样的:如何定位dijit.menu相对于其触发器?

// 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的风格,但它们似乎没有生效。

另外,我没有看到找出哪个节点是触发器的情况下,有多个的方式。

我看到this & this,但没有能够进一步与他们进一步。

* FWIW,我希望它们的位置使菜单的左上角与上下文触发器的右上角对齐,并与工具菜单的左下角对齐。

回答

3

事实证明,dojo.popup.open(我猜菜单从继承)有一个参数(东方),你可以使用相对于一个节点的菜单定位。我最终定义了一个定制触发器类,它知道如何利用它。 (我还创建了子类有不同的取向其他菜单类型,但我会离开那些出了清晰的缘故。)

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')); 
}); 
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); 
}); 
4

我发现下面的CSS覆盖工作得很好,如果你只是想在自动定位的相对差异:

.dijitMenuPopup { 
    margin-left: -25px !important; 
    margin-top: 15px !important; 
} 
相关问题