我正在尝试实现一个简单的水平导航菜单,只显示每个链接的一个div。它有点像下拉菜单,但不是鼠标悬停触发下拉列表,onclick事件将触发显示div。我想确保在采取进一步行动之前采取正确的方法,任何帮助表示赞赏。这就是我到目前为止所做的:
<ul id="settings_nav">
<li>
<a>Theme</a>
<div id="settings_block"><%= render :partial => 'email_password' %></div>
</li>
<li>
<a href="index.htm">Lists</a>
<div id="settings_block"><%= render :partial => 'lists' %></div>
</li>
</ul>
window.onload = function(){
settingsMenuInit('settings_nav')
}
function settingsMenuInit(settings_nav){
$(settings_nav).childElements().each(
function(node){
node.onclick= function(){ this.next.show() };
})
}
类似的东西,但我不确定如何获取当前显示的div并隐藏它。我可以迭代所有的childElements并隐藏每个div然后显示一个被点击的div,但也许有更好的方法?
答案 0 :(得分:1)
一些注释FW(T)W:
使用Prototype和类似的库,您不希望通过将函数分配给元素的onclick
和类似属性来挂钩事件处理程序;该样式有几个缺点(尤其是在元素上只有一个事件处理程序)。相反,使用Prototype的observe
函数:
someElement.observe('click', functionRefHere);
// or
Element.observe(someElementOrID, 'click', functionRefHere);
这也让Prototype可以解决一些IE内存丢失错误。
您可能会看到Prototype的dom:loaded
事件,它比window.onload
更早发生(在您加载所有图像和其他外部资源之前不会发生这种情况,这可能是页面显示后的第二个或第二个):
document.observe('dom:loaded', initFunctionRefHere);
您可以使用事件委派,只需查看settings_nav元素,而不是单独查看每个子节点。
$(settings_nav).observe('click', handleNavClick);
function handleNavClick(event) {
var elm = event.findElement("some CSS selector here");
if (elm) {
event.stop();
// Handle it
}
}
如您所见,Event#findElement
接受CSS选择器。它从单击的实际元素开始,并尝试将其与选择器匹配;如果它匹配,则返回元素,否则它将转到父元素以查看它是否匹配;因此,使用您的HTML,您可能会找到li
(event.findElement('li')
)或链接(event.findElement('a')
)。
但是如果你想单独观看每一个,他们可以共享一个功能(就像你在例子中一样):
$(settings_nav).childElements().invoke('observe', 'click', handleNavClick);
function handleNavClick(event) {
// Prototype makes `this` reference the element being observed, so
// `this` will be the `li` element in this example.
}
您是单独观看每个元素还是使用事件委托取决于您正在做什么(以及个人偏好)。每当有任何事情可能更改(例如添加和删除导航li
元素)或者有很多事情需要关注时,请查看事件委派 - 它更容易处理使用事件委派更改元素集并只观看父节点。处理只有少数事情的稳定结构时(如您的示例所示),单独观察元素可能更简单。
进入处理程序后,您可以使用Element#down
查找子元素(因此,li
可能会使用li.down('div')
来查找div)或{{ 3}}到达下一个兄弟元素(例如,从链接到div)。无论哪种方式,一旦您引用了div,就可以使用Element#next
和Element#show
(或Element#hide
)。
我建议使用命名函数而不是匿名函数(请参阅上面的示例)。命名函数可以帮助您的工具(调试器,显示错误的浏览器等)帮助您。请务必不要声明命名函数和将其用作表达式(例如,不要立即将其分配给某些内容):
// Don't do this because of browser implementation bugs:
someElement.observe('click', function elementClickHandler(event) {
// ...
});
// Do this instead:
someElement.observe('click', elementClickHandler);
function elementClickHandler(event) {
// ...
}
...因为虽然你应该能够根据规范做到这一点,但实际上各种浏览器中的各种错误使它无法可靠地工作(Element#toggle
)。