Простая горизонтальная навигация по Javascript с прототипом - PullRequest
0 голосов
/ 02 марта 2010

Я пытаюсь реализовать простое горизонтальное меню навигации, которое просто показывает один 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 и затем показать тот, на который нажимали, но, может быть, есть лучший способ?

1 Ответ

1 голос
/ 02 марта 2010

Некоторые ноты FW (T) W:

  1. С Prototype и подобными библиотеками вы не хотите подключать обработчики событий, назначая функции элементу onclick и аналогичным свойствам; у этого стиля есть несколько недостатков (не менее важно то, что для элемента в событии может быть только один обработчик). Вместо этого используйте функцию observe прототипа:

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

    Это также позволяет Prototype обходить некоторые ошибки IE, связанные с потерей памяти.

  2. Вы можете посмотреть на событие прототипа 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 вы можете искать 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) или когда есть много вещей, которые нужно посмотреть, обращайтесь к делегированию событий - гораздо проще справиться с изменением наборов элементов, использующих делегирование событий и просто наблюдающих за родителем. При работе со стабильной структурой всего из нескольких вещей (как в вашем примере) может быть проще просто наблюдать за элементами по отдельности.

  4. Оказавшись внутри вашего обработчика, вы можете использовать Element#down, чтобы найти дочерние элементы (таким образом, из li вы можете использовать li.down('div'), чтобы найти div), или Element#next, чтобы перейти к следующему элементу-брату (например, перейдя по ссылке на div). В любом случае, если у вас есть ссылка на div, вы можете использовать Element#show и Element#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 ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...