Как я могу написать эту строку меню в jQuery, чтобы вкладки оставались в состоянии наведения?

У меня есть простая строка меню, здесь. Моя проблема заключается в том, что когда вы наводите курсор на вкладки, а подменю скользит вниз, а затем вы наводите курсор на меню слайдов, вкладка выходит из состояния наведения.

Вот мой jQuery:

$('.js-tab').hover(function(){
    $(this).css('background-color', 'black').css('color', 'white').children('.js-icon').css('background-position', '0px -65px');
},function(){
    $(this).css('background-color', 'white').css('color', 'black').children('.js-icon').css('background-position', '0 0');
});

$('nav').hover(function(){
    $('.js-subitems').slideDown(150);
},function(){
    $('.js-subitems').slideUp(200);
});

.js-tab(s) — это все вкладки. При наведении их CSS меняется, чтобы инвертировать цвет и выбирать инвертированную часть спрайта. 'nav' - это все меню. Его размер определяется элементами внутри него, у него нет определенного стиля, вместо этого я выбираю вкладки для подменю, чтобы подменю оставалось открытым, когда вы наводите на него курсор.

Вот мой CSS:

.js-subitems {
    background: rgba(0,0,0,.8);
    width: 539px;
    height: 170px;
    margin: 0 0 0 313px;
    border: 1px solid rgba(255,255,255,.5);
    border-top: 0px solid transparent;
    border-right: 1px solid rgba(0,0,0,.8);
    position: absolute;
    display: none;
    z-index: 7;
    padding: 15px;
    padding-top: 185px;
    color: white;
}

.js-icon{
    background-color:transparent;
    background-position:top left;
    background-repeat:no-repeat;
    position:absolute
}

.js-menu{
    float:left;
    width:570px;
    height: 340px;
    position:relative;
    margin-left:313px;
    border-left: 1px solid #CCC;
    z-index:10
}

.js-menu li{
    float:left;
    border-right:1px solid #CCC
}

.js-tab{
    background:#fff;
    display:block;
    overflow:hidden;
    position:relative;
    text-align:center;
    width:94px;
    height:170px;
    text-decoration:none;
    z-index:8
}

.js-tab h2{
    font-size:13px;
    font-weight:500;
    left:0;
    position:absolute;
    top:120px;
    width:97px;
    text-decoration:none
}

ПРИМЕЧАНИЕ. Хотя цвет фона можно изменить без использования javascript, я пытаюсь сохранить все это в одном месте. Я уменьшу это позже, компрессия сейчас не важна.

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


person alt    schedule 10.11.2011    source источник


Ответы (2)


Я думаю, что привязка события hover только к li должна работать:

$('#js-menu li).hover(function(){
    $(this).find('.js-tab').css('background-color', 'black').css('color', 'white').children('.js-icon').css('background-position', '0px -65px');
    $(this).find('.js-subitems').slideDown(150);
},function(){
    $(this).find('.js-tab').css('background-color', 'white').css('color', 'black').children('.js-icon').css('background-position', '0 0');
    $(this).find('.js-subitems').slideUp(200);
});

Это вызовет оба изменения, которые вам нужны. Однако я бы также поместил каждый список подэлементов в li, например:

<li data-hovercolor="#fff">
    <a href="/" class="js-tab">
    <h2 data-type="mText" class="js-item">Home</h2>
    <span data-type="icon" class="js-icon js-icon-home"></span>
    </a>
    <div class="js-subitems">
        Testing the text.
    </div>
</li>

Таким образом, поскольку подэлементы являются частью родительского li, родительский li сохранит эффект наведения при наведении мыши на подэлементы.

EDIT: После некоторого обсуждения потребовалось новое решение. Я почти уверен, что это должно работать для того, что вам нужно: http://jsfiddle.net/jackrugile/SkhqF/< /а>

Он изменяет продолжительность в зависимости от того, наводится курсор на ul или нет, и применяет небольшой setTimeout для обработки анимации при выходе из ul. Благодаря ответу @GregL за вдохновение.

person jackrugile    schedule 10.11.2011
comment
хм... теперь ничего не появляется. Я разбираю это. Но то, что вы говорите, имеет смысл. - person alt; 10.11.2011
comment
Да, вам придется настроить свой css, чтобы .js-подэлементы отображались правильно. Дайте мне знать, если вам нужна помощь с этим. - person jackrugile; 10.11.2011
comment
О, я понял... каждое подменю находится ВНУТРИ элемента li. Это работает! ОДНАКО: у меня не может быть анимации, показывающей, что есть несколько разделов подменю. Он должен вести себя так же, как и раньше. Теперь посмотрите на сайт со своими изменениями: bridgecitymedical.com. Как я могу предотвратить эту скользящую анимацию при переходе от вкладки к вкладке в вашей версии, но оставить ее, когда вы выходите из всего меню? Спасибо приятель! - person alt; 10.11.2011
comment
Я думаю, что теперь понимаю, что вы имеете в виду, каждый пункт меню будет иметь другой список под ним, но все они будут выглядеть так, как будто они хранятся в одном и том же ящике. И вы хотите, чтобы это анимировалось только вверх и вниз, когда вы входите или выходите из всей навигации в целом, а не при переходе от элемента к элементу, правильно ли это звучит? - person jackrugile; 10.11.2011
comment
Ага. Вот так. Ваши изменения были УДИВИТЕЛЬНЫМИ и решили мою проблему. Но создали еще один. Как я могу предотвратить эту анимацию от табуляции к табуляции, чтобы она выглядела так, как это было до вашего редактирования, но функционировала так же, как сейчас. ;) - person alt; 10.11.2011
comment
@JacksonGariety Я бы подумал о добавлении класса «зависание» или «активный» в первом обратном вызове в .hover() к <li> и удалении его во втором обратном вызове. Затем перед строкой .slideUp() проверьте, есть ли <li> с этим классом. Если да, то не скатывайтесь... Это направит вас на верный путь? - person GregL; 10.11.2011
comment
Хорошо, я думаю, что самый простой способ сделать это — переместить один div из списка, как вы делали раньше, и это будет действовать как фон вашего подэлемента, который скользит вверх и вниз. Привяжите событие hover к #js-menu, чтобы инициировать скольжение вверх и вниз по фоновому div. Это предотвратит многократное срабатывание. Затем сохраните фактическое содержимое подэлементов там, где они сейчас (в li), и удалите большой фон, оставив их только как текстовые элементы. Затем вы можете выбрать постепенное их появление и исчезновение вместо слайда или что угодно. Дайте мне знать, если это имеет смысл, я мог бы сделать демо. - person jackrugile; 10.11.2011
comment
Да. Но как проверить есть ли списки и не сползать вниз - person alt; 10.11.2011
comment
Да, я не особенно хочу идти по этому пути, потому что то, как я собираюсь представить содержимое этих div, должно фактически быть вложено внутри элемента sub-items. Я подумал, можно ли как-нибудь создать такую ​​переменную: var $speed = 200, а затем изменить эту скорость в зависимости от того, с какой вкладки мы идем. Так что, если мы перейдем от отсутствия вкладок к одной вкладке, это $speed = 200, если мы перейдем от вкладки к вкладке, $speed = 0, поэтому мы не получим эту анимацию. Если это возможно, я бы предпочел это. Как это можно сделать? кстати, спасибо за помощь - person alt; 10.11.2011

Вот моя полностью непроверенная настройка javascript @jackrugile. Если ничего другого, это может дать вам некоторые идеи. Порядок операторов может нуждаться в исправлении.

EDIT: Новый подход: вместо этого установите активное состояние для содержащего <nav> элемента. Код обновлен.

РЕДАКТИРОВАНИЕ 2. Новый подход: проверьте, есть ли еще одно развернутое подменю, и если да, пропустите анимацию. Удалена идея класса <nav>, я не думаю, что это позволит какие-либо анимации.

$('#js-menu li').hover(function(){
    $(this).find('.js-tab').css('background-color', 'black').css('color', 'white').children('.js-icon').css('background-position', '0px -65px');
    var duration = 150;
    if ($('.js-subitems:visible').length) // if another tab active then show it immediately
        duration = 0;
    $(this).find('.js-subitems').slideDown(duration);
},function(){
    $(this).find('.js-tab').css('background-color', 'white').css('color', 'black').children('.js-icon').css('background-position', '0 0');
    var duration = 200;
    if ($('.js-subitems:visible').length) // if another tab active then hide it immediately
        duration = 0;
    $(this).find('.js-subitems').slideUp(duration);
});
person GregL    schedule 10.11.2011
comment
Кстати, я совершенно не пытаюсь украсть славу @jackrugile. Примите его ответ, если это было главное, что сработало, я просто хотел высказать идею, за которую можно проголосовать, если она будет полезна. - person GregL; 10.11.2011
comment
Спасибо за чувак без репутации! Я проверю это сейчас. - person alt; 10.11.2011
comment
Кроме того, прочитайте мой последний комментарий к сообщению @jackrugile, он объясняет, чего я пытаюсь достичь сейчас. - person alt; 10.11.2011
comment
Да, видишь ли, с твоим я столкнулся с той же проблемой, что и с домкратом. - person alt; 10.11.2011
comment
Да, я вижу, к чему ты клонишь, извини. - person alt; 10.11.2011
comment
ОТЛИЧНО. Все еще не работает, теперь я озадачен, почему, это ДОЛЖНО работать! :D Вы на что-то. - person alt; 10.11.2011
comment
Проблема заключается в проверке того, активен ли он. - person alt; 10.11.2011
comment
Да, я чувствую, что в теории это должно работать. Однако удаление активного класса происходит прямо перед проверкой в ​​if ($('#js-menu li.active').length), поэтому он никогда не удовлетворит этому оператору if. Я бы решил эту проблему, установив продолжительность var перед привязкой и добавив активный класс в ul при наведении. Продолжительность будет равна 0, если вы находитесь на ул, и 200, когда вы находитесь вне ул. - person jackrugile; 10.11.2011
comment
@JacksonGariety @jackrugile Новый подход - вместо этого установите класс active для содержащего <nav> (ответ обновлен). Это работает лучше? - person GregL; 10.11.2011
comment
ПРОГРЕСС: Это работает. Как бы. Когда вы наводите курсор ВНЕ всего, продолжительность по-прежнему равна 0. Дерьмо. Дай подумать. - person alt; 10.11.2011
comment
@JacksonGariety Я слишком поздно понял, что моя логика предотвратит появление анимации. Обновленный ответ снова с другим новым подходом. - person GregL; 10.11.2011
comment
Вы использовали «видимый». Разве это не должно быть «блокировать», поскольку jQuery использует display:none not visible:hidden ? Или я ошибаюсь. Несмотря ни на что, это не работает. - person alt; 10.11.2011
comment
Это просто возвращает продолжительность = 200 при переходе от вкладки к вкладке. Единственное время, когда НЕТ анимации, — это наведение курсора за пределы строки меню. РЖУ НЕ МОГУ - person alt; 10.11.2011
comment
Я попытался добавить что-то вроде этого: $nav.mouseleave(function(){ $(this).removeClass('active'); var duration = 200; }); Поэтому, когда вы покидали всю строку меню, она сбрасывала продолжительность и класс. - person alt; 10.11.2011
comment
Только что обновил свой ответ демонстрацией jsFiddle, дайте мне знать, если это сработает. Основываясь на некоторой логике @GregL. - person jackrugile; 10.11.2011
comment
@jackrugile Ваш способ довольно глючный, по крайней мере, с моей настройкой. bridgecitymedical.com При быстром переходе подменю останавливается. И есть небольшое дрожание между каждой вкладкой. - person alt; 10.11.2011
comment
Дрожание было от «10», которое у вас было там, должно было быть 0. - person alt; 10.11.2011
comment
Спасибо, приятель, я переместил несколько вещей, и это ИДЕАЛЬНО. - person alt; 10.11.2011
comment
@jackrugile Это самое близкое, что есть у каждого из нас. В нем есть небольшие недостатки (например, быстрое перемещение мыши от элемента и обратно), но для большинства целей я был бы доволен этим. - person GregL; 10.11.2011
comment
@JacksonGariety Я так понимаю, тебе наплевать на IE6? В IE6 это выглядит ужасно из-за отсутствия поддержки прозрачного PNG. - person GregL; 10.11.2011
comment
Да, мне пришлось добавить .stop(false,true), потому что по какой-то причине при скольжении в jQuery все так легко застревает. Но для предотвращения очереди анимации требовался хотя бы какой-то .stop(). У меня никогда не возникало проблем с отображением/скрытием или исчезновением. Рада, что вы хотя бы стали ближе! Идти спать ;) - person jackrugile; 10.11.2011
comment
@GregL Да, мне еще нужно проверить IE6 на наличие ошибок. (кошмар) Но я гораздо лучше разбираюсь в CSS, чем в javascript, И я избавляюсь от этих png и вместо этого получаю jpg. PNG были для старой строки меню, от которой я избавился. - person alt; 10.11.2011