реализация jquery, похожая на firebug

#jquery

#jquery

Вопрос:

Я хочу реализовать выделение, подобное firebug, при наведении курсора на элемент

 $("*").mouseover(function()
{
    $(this).css({border:'1px solid blue'});
})
.mouseleave(function() 
{
    $(this).css({border: ''});
});
  

но это не меняет css при наведении курсора на внутренний элемент, стиль внешнего элемента по-прежнему изменяется вместо возврата к исходному css из-за mouseleave()

Ответ №1:

Не делайте таких тяжелых вещей на * . Используйте .delegate вместо этого.

 $('body').delegate('*', 'mouseover mouseout', function (e) {
    if (this === e.target) {
        $(e.target).css('border', (e.type === 'mouseover' ? '1px solid blue' : ''));
    }
});
  

Я не тестировал это, но моя точка зрения заключается в использовании .delegate .

Редактировать Добавленное предложение от Crowder (спасибо!)

Комментарии:

1. Мне нравится, как вы сгустили вещи, и я согласен с delegate (добавлял delegate решение к моему ответу, как вы опубликовали), но обратите внимание, что вышеупомянутое будет повторно вызываться css неоднократно для одного и того же элемента ( e.target ). Если у вас есть (скажем) ul с li strong , если пользователь наведет курсор на strong элемент, ваш код вызовет css этот strong элемент три раза (один раз для strong , снова для li и снова для ul ). В данном случае это в значительной степени безвредно, но требует много ненужной работы. @ianace, ты захочешь добавить this === e.target проверку.

2. Да, я только что jsbined и проверил, вы правы. Забавно, я все еще не могу представить, почему он это делает. придется поискать повнимательнее 🙂 спасибо, кстати jsbin.com/eveno4/8/edit

3. @Shrikant: Не беспокойтесь. 🙂 Он делает это, потому что delegate он фантастический и на самом деле выполняет пузырящиеся вызовы, а mouseover и mouseout являются пузырящимися событиями (так что mouseover на дочернем элементе также видно на родительском элементе).

4. @Crowder, верно, но для родительских элементов это событие с пузырьками, верно? не событие, которое возникло на них, поэтому delegate не следует его поднимать …. о, подождите! мы используем * селектор, который соответствует им всем, и событие запускается! черт! спасибо 🙂

Ответ №2:

Как и у Noufal, моей первой мыслью было «лучше сделать это с помощью :hover псевдокласса CSS» (если только вам не нужно поддерживать IE6, который не поддерживает :hover ничего, кроме ссылок), но я не могу сразу придумать, как бы вы справились с тем, чтобы у элементов-предков также не было границы. И наличие границы для всех предков выглядит для меня довольно уродливо:http://jsbin.com/eveno4/2

Что касается решения на JavaScript: вы были близки к этому, но обычно вы использовали mouseover и mouseout , или использовали mouseenter и mouseleave , но не mouseover и mouseleave (обычно нет; есть места, где вы бы это сделали).

В этом случае я бы, вероятно, использовал mouseover и mouseout , но действовал бы только на события, фактически инициируемые рассматриваемым элементом (не пузырьковые):

 $("*").mouseover(function(event)
{
  if (this === event.target) {
    $(this).css({border:'1px solid blue'});
  }
})
.mouseout(function(event) 
{
  if (this === event.target) {
    $(this).css({border:''});
  }
});
  

Живая копия

Обратите внимание на использование event.target , чтобы убедиться, что мы не обрабатываем событие с пузырьками.

Или, вместо того, чтобы подключать обработчик к каждому элементу на странице, подключите обработчики только к body элементу и воспользуйтесь тем фактом, что они всплывают, используя delegate :

 $(document.body).delegate("*", "mouseover", function(event)
{
  if (this === event.target) {
    $(this).css({border:'1px solid blue'});
  }
})
.delegate("*", "mouseout", function(event) 
{
  if (this === event.target) {
    $(this).css({border:''});
  }
});
  

Живой пример

(Или вы могли бы использовать live , это в значительной степени сводится к тому же.)

Комментарии:

1. Насколько я знаю, if условия в delegate примере бесполезны, поскольку this всегда равно event.target .

2. @Shrikant: Нет, они действительно служат определенной цели. Посмотрите на это без них: jsbin.com/eveno4/5

3. @Crowder Виноват, я имел это в виду, когда говорил это jsbin.com/eveno4/6/edit (заимствовано из моего ответа)

Ответ №3:

Разве вы не можете сделать что-то вроде

 *:hover {
     border: 1px solid blue;
} 
  

в ваших правилах CSS вместо того, чтобы полагаться на Javascript?

Обновить. Я только что попробовал это, и, похоже, это работает достаточно хорошо.

Комментарии:

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

2. Ну, родительский элемент тоже будет выделен, но вы могли бы найти более узкий селектор и использовать его. Кроме того, это не так отвлекает, как кажется.

3. Как бы вы это сделали? (Надежно кроссбраузерный, конечно.) Нацеливаться на любой элемент, но только по одному за раз? На мой взгляд, это выглядит ужасно, поскольку у родителей также есть граница: jsbin.com/eveno4/2

4. Вы правы. Способа нет (я все равно не могу придумать ни одного). На мой взгляд, это не так плохо, но и не идеально. Я пытался получить что-то лучшее, используя вместо этого непрозрачность и цвета фона, но не смог.