菜单除了要它能显示,还要它能执行动作才是最关键的地方。popup是个子窗口,虽然他没有opener。我们有两种办法来在popup中执行脚本,一是把script代码写到其document中,让它运行,比如:
这样在弹出的popup中就可以点击"click me"出来一个alert msg box。
另一种方法是使用attachEvent的办法,这样popup可以执行其opener窗口中的脚本,比如:
在opener窗口中的scirpt方法:
在第二个方法里有个undocumented的特性,使用attachEvent方法attach的事件响应函数在被触发时,第一个参数默认就是其window上的event属性。为什么说是其窗口上呢?因为popup确实是个具有自己的window对象的元素(虽然我们前面说它比较怪异)。这个特性被极好的使用在了菜单条目被点击时的响应处理上,在后面的Menu.Show()和Menu.ShowEx()里都回用到。
我们在使用(2)中的最后说过,由于在popup的doucment对象上使用appendChild有UI效果上的问题,所以我们不得不使用innerHTML赋值方式来生成菜单的显示UI HTML代码。这样的代码和我们的JavaScript写的菜单类之间就没有了任何的联系,为了把这个联系重新建立起来,我们使用了一个全局的类似Hashtable的类__MenuCache__来存储菜单逻辑和UI HTML之间的一对一联系,这个方法不是我创造的,它是Erik Arvidsson实现的DHTML Menu 4里面的方法,我借用了一下,觉得这个方法还是挺好的。
var
win
=
window;
var doc = win.document;
var popup = win.createPopup();
var popwin = popup.document.parentWindow;
var popdoc = popwin.document;
popdoc.write(' < script > function showAlert(){alert( " a " );} < ' + ' / script > < div onclick = " showAlert() " > click me </ div > ');
popup.show( 0 , 0 , 100 , 100 );
var doc = win.document;
var popup = win.createPopup();
var popwin = popup.document.parentWindow;
var popdoc = popwin.document;
popdoc.write(' < script > function showAlert(){alert( " a " );} < ' + ' / script > < div onclick = " showAlert() " > click me </ div > ');
popup.show( 0 , 0 , 100 , 100 );
另一种方法是使用attachEvent的办法,这样popup可以执行其opener窗口中的脚本,比如:
popdoc.write('
<
div
>
click me
</
div
>
');
var div = popdoc.getElementsByTagName('DIV')[ 0 ];
div.attachEvent('onclick', Alert3);
popup.show( 0 , 0 , 100 , 100 );
var div = popdoc.getElementsByTagName('DIV')[ 0 ];
div.attachEvent('onclick', Alert3);
popup.show( 0 , 0 , 100 , 100 );
function
Alert3() { alert(
3
); }
我们在使用(2)中的最后说过,由于在popup的doucment对象上使用appendChild有UI效果上的问题,所以我们不得不使用innerHTML赋值方式来生成菜单的显示UI HTML代码。这样的代码和我们的JavaScript写的菜单类之间就没有了任何的联系,为了把这个联系重新建立起来,我们使用了一个全局的类似Hashtable的类__MenuCache__来存储菜单逻辑和UI HTML之间的一对一联系,这个方法不是我创造的,它是Erik Arvidsson实现的DHTML Menu 4里面的方法,我借用了一下,觉得这个方法还是挺好的。
var
__MenuCache__
=
{
m_Count : 0 ,
m_IdPrefix : " __MenuObject__ " ,
m_ActiveItem : null ,
NewId : function ()
{
return this .m_IdPrefix + this .m_Count ++ ;
},
Remove : function (mi)
{
delete this [mi.m_Id];
}
};
{
m_Count : 0 ,
m_IdPrefix : " __MenuObject__ " ,
m_ActiveItem : null ,
NewId : function ()
{
return this .m_IdPrefix + this .m_Count ++ ;
},
Remove : function (mi)
{
delete this [mi.m_Id];
}
};
虽然我看了Eric的Menu4的代码,我只能说这个__MenuCache__是里面的亮点,而其他的部分写的真是有些乱,毕竟他那个Menu类前前后后历时两年,其间修复了n多bug。当然我这个Menu的实现自然有些站在巨人肩膀上的味道了。
再说点题外话,Eric的javascript水平是毋庸置疑的,既有webfx.eae.net上丰富的DHTML组件类,还有更震耳发聩的Bindows™。但是更让我觉得难能可贵的是他在webfx上那些详细的教程,我看了他的教程后,一个晚上就做一个Menu的prototype,后来修修补补到现在一个周已经完全实现了DHTML Menu 4菜单部分的全部功能(MenuBotton那部分我没有做,因我目前暂时用不上)。本来我可以简单的把代码一发就完事,可能还更受大家欢迎。但我觉得我在这里详细的介绍这个PopMenu的实现过程和其间遇到的一些问题,会让踏实学习的人收获到更多的东西,同时也督促我自己更加踏实的学习工作。如果能引起讨论氛围,指出我使用的方法中的错误和不足并给予建议,那更是一件让我开心的事。
to be continued ...