随笔-124  评论-194  文章-0  trackbacks-0

dojo提供了不错的树控件,但上下文菜单比较简单,不能动态改变:比如我想根据不同节点显示不同的上下文菜单就比较困难,根据多种实验和查阅下面提供一种实现方式。在此过程中也学到不少东西。先把解决方案说一下,再把发现过程说一下:

DOJO提供了AOP的方式来“注入”代码,我们就把修改menu的代码注入到TreeContextMenuV3里就可以了:
在open事件前注入我们的代码:

dojo.event.connect("before", dojo.widget.byId("contextMenu1"), "open"this"onContextMenuOpen");

注意before是表示在menu打开之前调用,其它关键字还可以是after,around。强,赞一个!

在onContextMenuOpen函数中,做改变菜单的事情:

    this.onContextMenuOpen = function (evt) {
        dojo.log.info (
"before context open");
        dojo.log.info (evt);
        
var m = dojo.widget.byId("contextMenu1");
        dojo.log.info (m);
        m.removeChild (dojo.widget.byId(
"treeContextMenuEdit"));
        m.removeChild (dojo.widget.byId(
"treeContextMenuDown"));
        m.removeChild (dojo.widget.byId(
"treeContextMenuCreate"));
        m.removeChild (dojo.widget.byId(
"treeContextMenuCreate2"));

        
if (null == this.context_menu["MenuItem2"]) {
            
var id = dojo.widget.createWidget("MenuItem2"{caption: "Page Info"});
            dojo.log.info (id);
            
this.context_menu["MenuItem2"= id;
            m.addChild(id);
        }

        
        
//m.destroyChildren ();
        dojo.log.info (m);
        
//w.destory ();
        
    }
;


在这里可以根据节点来增删菜单项了,context_menu成员是用来记录加入过的菜单项,以免重复加入。
另外,removeChild没有destory掉菜单项,应该可以重复使用。所以,我设想的实现是,在程序开头将所有可能的菜单项动态创建好,存在一个MAP中,然后,在这里来动态加删它们。


下面是寻找解决方法的过程:

刚开始时,我想是改变整个树的菜单,确实也找到了可以编程改变它的方法:

var ctxMenu = dojo.widget.byId("contextMenu");
var tree = dojo.widget.byId("phyTree");
dojo.log.info (ctxMenu);

ctxMenu.listenTree(tree);
ctxMenu.bindDomNode(tree.domNode); 

关键是一句:bindDomNode。
这样虽然可以动态“加载”菜单了,可是没有“时机”来加载新菜单,无法达到根据节点变化来做改变。


随后,我又想到重载,去创造这个“时机”:

dojo.require ("dojo.widget.TreeContextMenuV3");

dojo.provide(
"mywidgets.MyTreeContextMenu");

dojo.widget.defineWidget(
    
// widget name and class
    "mywidgets.MyTreeContextMenu",
    
    
// superclass
    [dojo.widget.TreeContextMenuV3],

    
function() {
        dojo.log.info (
"my context menu create1");
    }
,    
    
    
// properties and methods
    {
        open: 
function() {
            
var result = dojo.widget.PopupMenu2.prototype.open.apply(this, arguments);
    
            dojo.log.info (
"my context menu create");
            
for(var i=0; i< this.children.length; i++{
                
/* notify children */
                
if (this.children[i].menuOpen) {
                    
this.children[i].menuOpen(this.getTreeNode());
                }

            }

            
return result;
        }

    }

);


这也是我第一次重载DOJO,发现其实很简单,关键要注意它的namespace:
dojo.require()语句的寻找方法是:
dojo.xxx => dojo/src/xxx.js

dojo.xxx.yyy => dojo/src/xxx/yyy.js

dojo.xxx.yyy.zzz => dojo/src/xxx/yyy/zzz.js

如果遇到不是dojo开头时,它的寻找方法是:
example.xxx => dojo/../example/xxx.js

example.xxx.yyy => dojo/../example/xxx/yyy.js

example.xxx.yyy.zzz => dojo/../example/xxx/yyy/zzz.js

所以要把自己的代码放到跟dojo同级就可以了。
这个办法我没往下试,因为重载的是contextmenu,在它里面把它“整个自己”换成别的menu,我觉得是不可行的。而看半天代码也没找着在哪重载右键点击这个事件。不过启发我可以更换子item来解决。
于是有了开头的解决方案。

posted on 2007-07-01 11:15 我爱佳娃 阅读(2588) 评论(3)  编辑  收藏 所属分类: AJAX

评论:
# re: 在dojo的TreeV3中实现动态的上下文菜单TreeContextMenuV3[未登录] 2007-08-30 09:00 | 小强
想问下你有没有考虑 后台如何来取得修改后的树。即如何来取得整个树的所有节点以及其之间的关系  回复  更多评论
  
# re: 在dojo的TreeV3中实现动态的上下文菜单TreeContextMenuV3 2007-09-10 10:58 | 我爱佳娃
DOJO太慢,最近在研究其它库。
不如试下YUI-EXT这个库,谁用谁知道。  回复  更多评论
  
# re: 在dojo的TreeV3中实现动态的上下文菜单TreeContextMenuV3 2007-12-21 11:24 | wudili
兄弟,多谢,我想了3天了.
甚至想过重写,还是你牛!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: