javascript - 带有原型(prototype)的简单水平 Javascript 导航

标签 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,然后显示被点击的那个,但也许有更好的方法?

最佳答案

一些笔记 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. 您可以使用事件委托(delegate)并只观察您的 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.
    }
    

    您是单独观察每个元素还是使用事件委托(delegate)取决于您在做什么(和个人偏好)。每当任何事情可能改变(例如,添加和删除导航 li 元素)或有很多事情需要注意时,请查看事件委托(delegate)——这要容易得多使用事件委托(delegate)并仅观察父元素来处理不断变化的元素集会更简单。在处理只有少数事物的稳定结构时(如您的示例),单独观察元素可能更简单。

  4. 进入处理程序后,您可以使用 Element#down找到子元素(所以从 li,你可以使用 li.dow​​n('div') 来找到 div),或者 Element#next到达下一个兄弟元素(例如,从链接到 div)。无论哪种方式,一旦你有对 div 的引用,你就可以使用 Element#showElement#hide (或 Element#toggle )。

  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) {
        // ...
    }
    

    ...因为虽然您应该能够根据规范做到这一点,但实际上各种浏览器中的各种错误使其无法可靠地工作(article)。

关于javascript - 带有原型(prototype)的简单水平 Javascript 导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2360953/

相关文章:

javascript - 如何在 javascript 中使用 C# 代码

javascript - 动态地将 CSS 样式应用于特定元素

javascript - 如何动态更改JQM可折叠的主题

javascript - div inside table td 在右上角?

javascript - 密码管理器如何知道我已成功登录?

JavaScript 2.0 规范

ruby-on-rails - 在 Rails ajax 调用中将 DOM 编译为 angularjs

mysql - 有没有办法在 MySQL/Rails 中为单个查找强制区分大小写?

ruby-on-rails - 未设置安全 session cookie

html - 如何在CSS中为几何图形添加边框?