简单的水平Javascript导航与原型

时间:2010-03-02 04:43:49

标签: javascript ruby-on-rails css menu prototypejs

我正在尝试实现一个简单的水平导航菜单,只显示每个链接的一个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,但也许有更好的方法?

1 个答案:

答案 0 :(得分:1)

一些注释FW(T)W:

  1. 使用Prototype和类似的库,您不希望通过将函数分配给元素的onclick和类似属性来挂钩事件处理程序;该样式有几个缺点(尤其是在元素上只有一个事件处理程序)。相反,使用Prototype的observe函数:

    someElement.observe('click', functionRefHere);
    // or
    Element.observe(someElementOrID, 'click', functionRefHere);
    

    这也让Prototype可以解决一些IE内存丢失错误。

  2. 您可能会看到Prototype的dom:loaded事件,它比window.onload更早发生(在您加载所有图像和其他外部资源之前不会发生这种情况,这可能是页面显示后的第二个或第二个):

    document.observe('dom:loaded', initFunctionRefHere);
    
  3. 您可以使用事件委派,只需查看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,您可能会找到lievent.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元素)或者有很多事情需要关注时,请查看事件委派 - 它更容易处理使用事件委派更改元素集并只观看父节点。处理只有少数事情的稳定结构时(如您的示例所示),单独观察元素可能更简单。

  4. 进入处理程序后,您可以使用Element#down查找子元素(因此,li可能会使用li.down('div')来查找div)或{{ 3}}到达下一个兄弟元素(例如,从链接到div)。无论哪种方式,一旦您引用了div,就可以使用Element#nextElement#show(或Element#hide)。

  5. 我建议使用命名函数而不是匿名函数(请参阅上面的示例)。命名函数可以帮助您的工具(调试器,显示错误的浏览器等)帮助您。请务必不要声明命名函数将其用作表达式(例如,不要立即将其分配给某些内容):

    // 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)。