JQuery, если тогда еще с помощью плагина парсера URL квест на элегантность займет 2 - PullRequest
2 голосов
/ 26 апреля 2009

Это мой второй вопрос по этой теме, оригинальный вопрос можно найти здесь: JQuery, если в таком случае используется плагин парсера URL, должно быть более элегантное решение!

Если вы сидите с комфортом, я начну!

Я создал веб-страницу, которая содержит список вопросов. Каждый вопрос имеет ответ, содержащийся в Div после него. HTML выглядит так:

<div class="questions_main_box">
   <h2>common questions:</h2>
   <ul>
      <li>
         <h3 id="question1">question number 1</h3>
     <div id="answer1"> answer number 1</div>
      </li>
      <li>
         <h3 id="question2">question number 2</h3>
     <div id="answer2"> answer number 2</div>
      </li>
      etc etc...
   </ul>
</div>

Я написал некоторый код, используя jQuery для настройки поведения этого списка. Идея состоит в том, что все ответы Div скрыты с помощью jQuery, а затем раскрываются одним из двух способов:

Либо пользователь щелкает соответствующий заголовок h3

или

Пользователь нажимает на ссылку на один из вопросов с другой страницы.

Если пользователь переходит с другой страницы, должен отображаться вопрос, по которому он щелкнул, а все остальные скрыты.

Я сделал эту работу, но мой код довольно неэффективен. В моем предыдущем объяснении этой проблемы мне был предоставлен ответ, но полученные ответы имели нежелательный побочный эффект: они не позволяли меню отображать ответы, если в URL-адресе не была якорная ссылка. Так, например:

http://mydomain.com/questions.html не будет работать

но

http://mydomain.com/questions.html#question1 будет работать!

Мне нужно, чтобы оба работали! Как я уже сказал, моя версия работает в обоих направлениях, но довольно неуклюжа, и я уверен, что должен быть лучший способ выразить ее. Вот код, который может быть более эффективным:

if 
($.url.attr('anchor') == 'question1'){
        $('#answer2, #answer3, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
        $.scrollTo('#question1');
}
else if
($.url.attr('anchor') == 'question2'){
        $('#answer1, #answer3, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
        $.scrollTo('#question2');
}
else if
($.url.attr('anchor') == 'question3'){
        $('#answer1, #answer2, #answer4, #answer5, #answer6, #answer7, #answer8').hide();
        $.scrollTo('#question3');
}
else if
($.url.attr('anchor') == 'question4'){
        $('#answer1, #answer2, #answer3, #answer5, #answer6, #answer7, #answer8').hide();
        $.scrollTo('#question4');
}
else if
($.url.attr('anchor') == 'question5'){
        $('#answer1, #answer2, #answer3, #answer4, #answer6, #answer7, #answer8').hide();
        $.scrollTo('#question5');
}
else if
($.url.attr('anchor') == 'question6'){
        $('#answer1, #answer2, #answer3, #answer4, #answer5, #answer7, #answer8').hide();
        $.scrollTo('#question6');
}
else if
($.url.attr('anchor') == 'question7'){
        $('#answer1, #answer2, #answer3, #answer4, #answer5, #answer6, #answer8').hide();
        $.scrollTo('#question7');
}
else if
($.url.attr('anchor') == 'question8'){
        $('#answer1, #answer2, #answer3, #answer4, #answer5, #answer6, #answer7').hide();
        $.scrollTo('#question8');
}
else if
($.url.attr('anchor') != 'question1, question2, question3, question4, question5, question6, question7, question8'){
        $('.questions_main_box ul li div').hide();
};

Работает нормально, но довольно неуклюже, в текущем воплощении это также означает, что если я хочу добавить больше вопросов и ответов, я должен добавить их явно в список (ы) идентификаторов. Было бы гораздо лучше не делать этого!

Просто чтобы у вас была вся картинка, вот остаток кода:

$('.questions_main_box h3').addClass('js_main_box');
    $('.questions_main_box h3').hover(
        function(){
            $(this).addClass('js_main_box_highlight');
        },
        function(){
            $(this).removeClass('js_main_box_highlight');
        }
    );

    $('.questions_main_box h3').click(
            function(){
                if ($(this).next().is(':visible')){
                    $(this).next().hide('fast');
                    }
                else if ($(this).next().is(':hidden')){
                    $(this).next().show('fast');
                    }
            }
    );

Так что все это работает как есть, и я на самом деле просто ищу способы сделать его более эффективным.

Я обнаружил одну проблему с тем, что я делаю, хотя, и я не могу понять, почему это происходит, и как бы я решил это исправить:

Проблема только в Firefox (я тестировал 3.0.9 и 3.1b3)

Когда я нажимаю на одну из якорных ссылок для перехода к соответствующему вопросу и ответу, Firefox переходит на нужную страницу, и правильный ответ будет виден, но страница не будет вертикально прокручиваться до нужного места, где тег привязки начинается. Это означает, что довольно часто вопрос, на который щелкнул пользователь, не отображается на экране, когда он впервые попадает на страницу вопросов и ответов! Это происходит только в Firefox. Сафари и Опера идут в нужное место. Я уверен, что это должно быть как-то связано со скрытыми элементами Div, например, когда JavaScript отключен и список отображается нормально, теги привязки работают нормально в Firefox. Я нахожу это действительно странным, и я понятия не имею, как это можно исправить или это просто ошибка без обходного пути. Любая информация по любому из моих вопросов будет с благодарностью получена.

Спасибо, что нашли время взглянуть на это!

Ян.

PS

Я использую плагин JQuery URL Parser, найденный здесь: http://projects.allmarkedup.com/jquery_url_parser/

Ответы [ 6 ]

3 голосов
/ 26 апреля 2009

Я бы рекомендовал использовать селектор CSS для сокрытия ваших ответов. Для этого вам необходимо добавить в ответ атрибут класса.

<div class="questions_main_box">
   <h2>common questions:</h2>
   <ul>
      <li>
         <h3 id="question1">question number 1</h3>
     <div id="answer1" class="answer">answer number 1</div>
      </li>
      <li>
         <h3 id="question2">question number 2</h3>
     <div id="answer2" class="answer">answer number 2</div>
      </li>
      etc etc...
   </ul>
</div>

Тогда с помощью jquery вы можете скрыть все ответы, используя

$('.answer').hide();

Итак, вместе с вашим другим вопросом JQuery, если затем используется плагин для парсера URL, должно быть более элегантное решение! это будет:

var match = jQuery.url.attr('anchor').match(/^question([0-9]+)$/);
if (match && match.length > 0) {
    $('.answer').hide();
    $('#answer' + match[1] ).show();
} 

Или в одной строке, как эта.

 $('.answer').hide().is('#answer' + match[1]).show();
1 голос
/ 27 апреля 2009

Вы должны добавить класс, было бы намного чище, чтобы скрыть их всех с помощью css. Но используя ваш существующий HTML ...

$("div.questions_main_box div").hide();

В отсутствии якоря, похоже, что вы хотели, чтобы первый вопрос был показан так ...

var question = jQuery.url.attr('anchor') | "question1";
var match = question.match(/^question([0-9]+)$/);
if (match && match.length > 0) {
    $('#answer' + match[1] ).show().scrollTo();
}

Я не уверен, что .scrollTO в вашем коде, но я предполагаю, что это плагин, и $ .scrollTo (селектор) должен быть таким же, как $ (селектор) .scrollTo ()

Поскольку вы используете якоря, вы должны использовать встроенный в браузер механизм прокрутки с якорями и забыть о прокрутке jQuery. Добавьте соответствующий тег привязки к каждому вопросу, например:

<li>
    <a name="question1" />
1 голос
/ 26 апреля 2009

Мое предложение состоит в том, чтобы не использовать jQuery для первоначального скрытия ответов, так как динамическое выполнение этого действия может запутать браузер в отношении длины страницы.

Вместо этого я бы использовал класс и CSS, чтобы скрыть их, например,

<li>
  <h3 id="question1">Foo?</h3>
  <div id="answer1" class="answer">Bar!</div>
</li>

и добавьте .answers { display: none; } к стилю страницы, чтобы браузер знал, что они не появятся при первом отображении страницы. Затем добавление $('#answer1').show() покажет соответствующий.

Конечно, это работает, только если у ваших пользователей включен Javascript, что может быть допустимым предположением. Если это не так, то вам нужно динамически добавить этот CSS вверху страницы, прежде чем страница полностью отобразится. Это делается путем добавления <script> к верхней части тела, добавляющего стиль:

<body>
  <script type="text/javascript">
    var style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = '.answers { display: none; }';
    document.getElementsByTagName('head')[0].appendChild(style);
  </script>
  ...

Это гарантирует, что люди без Javascript увидят все ответы.

В моих тестах такое поведение гарантирует, что страница будет правильно прокручена до нужного вопроса, по крайней мере, в FF3.

1 голос
/ 26 апреля 2009

Чтобы исправить проблему с Firefox, вы можете попробовать использовать jQuery для прокрутки к своему якору после того, как показало его. Полагаю, это немного хакерски, но должно работать.

Плагин «Интерфейс» для jQuery включает метод scrollTo. Link

Пример использования. jQuery Плавная прокрутка до якорных ссылок

Чтобы решить проблему элегантности, вот одна идея:

var targetDiv = $('#'+($.url.attr('anchor'))).next().attr('id');
$("div[id!='"+targetDiv+"'][id^='answer']").hide();
$("div[id='"+targetDiv+"']").show();
$.scrollTo('#'+($.url.attr('anchor')));
0 голосов
/ 01 мая 2009

ОК, так что я собираюсь ответить на свой вопрос! Это решение исправляет ошибку прокрутки в Firefox с помощью scrollTo, и код становится намного более элегантным и масштабируемым. Это все еще не идеально, но мне удалось сжать цикл if до этого:

if 
  ($.url.segment(1) == 'questions.html'||'terms.html') {
    $('.questions_main_box ul li div').hide();
    $('#'+($.url.attr('anchor'))).next().show();
    $.scrollTo('#'+($.url.attr('anchor')));
};

Плюсы:

  • Код гораздо более элегантный / сжатый / СУХОЙ
  • URL-привязки теперь будут работать независимо от того, как они называются
  • Не зависит от соответствующего вопроса и идентификатора ответа
  • Масштабируется до любого количества записей

Минусы:

  • Все div скрыты до того, как разбор URL используется для выявления совпадений. Это немного менее эффективно, чем найти способ проверить и скрыть только необходимые элементы.

Вот и все! Надеюсь, это поможет кому-то с похожей загадкой, бродящей в его мозгу! Если кто-нибудь может придумать, как улучшить этот код, чтобы убрать окончательный довод, тогда мне было бы очень интересно увидеть ваше решение.

Наконец, спасибо Стивену Ричардсу за решение проблемы с ошибками в Firefox, предложив использовать scrollTo. Безболезненное и простое решение, я благодарю вас! https://stackoverflow.com/users/96089/steven-richards

0 голосов
/ 27 апреля 2009
$('.questions_main_box h3').addClass('js_main_box');

$('.questions_main_box h3').bind('mousenter mouseleave',function(){
    $(this).toggleClass('js_main_box_highlight');
});

$('.questions_main_box h3').click(function(){
    var answer = $(this).parent().find("div");
    if (answer.is(':visible')) {
      answer.hide('fast');
      return;
    }
    answer.show('fast');
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...