Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   onmouseout и линк (https://javascript.ru/forum/misc/30504-onmouseout-i-link.html)

codingfighter 06.08.2012 19:25

onmouseout и линк
 
Всем привет. Столкнулся с довольно странной проблемой. Стоит родительский div в котором прописаны события onmouseover и onmouseout. Все работает, но когда наводишь курсор на ссылку внутри этого div'a чего-то срабатывает событие onmouseout хотя ведь курсор все еще в родительском div'e. Как посоветуете решить проблему?

devote 06.08.2012 19:30

используйте события onmouseenter, onmouseleave
<div id="la" style="width: 100px; height: 100px; background: #f00;">
    <a href="">test</a>
</div>
<script>
    document.getElementById('la').onmouseenter = function() {
        this.style.backgroundColor = '#0f0';
    }
    document.getElementById('la').onmouseleave = function() {
        this.style.backgroundColor = '#f00';
    }
</script>

codingfighter 06.08.2012 19:32

Читал уже про это http://www.xiper.net/manuals/html/ev...ouseenter.html

Цитата:

Событие onmouseenter работает только в IE. Для кроссбраузерного решения используется событие onmouseover.
так что тут замкнутый круг.

читаю про такие жонглирования http://javascript.ru/tutorial/events...rigger:-target

devote 06.08.2012 19:37

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

devote 06.08.2012 19:40

а вообще странно что оно не поддерживается другими браузерами кроме ИЕ и Оперы, хотя насчет ФФ ничего не скажу... нет возможности проветить.. Но в хроме точно не пашет.. Хотя в спецификации такие события есть http://www.w3.org/TR/DOM-Level-3-Eve...ype-mouseenter

codingfighter 06.08.2012 19:49

нда уж, что называется осложнили жизнь

devote 06.08.2012 19:52

Цитата:

Сообщение от codingfighter
нда уж, что называется осложнили жизнь

честно говоря я не ожидал того что в хроме не будет работать то что описано в документах. Вроде как хром хвалят за то что любит всякие экспериментальные штуки добавлять и то что в черновиках.. Уж не думал что банальное событие в хроме не будет работать.

devote 06.08.2012 19:55

ну а выход лишь один, для браузеров имеющих событие юзай его, а для других пиши костыль. Начало кода примерно такое:
// elem - это элемент на который хочешь повесить событие
if ( "onmouseenter" in elem ) {
    // тут код для тех кто его понимает
} else {
    // тут для тех кто не понимает пишешь костыль.
}

codingfighter 06.08.2012 20:01

нет, лучше уже просто словить откуда событие пришло. вот пример кода (со страницы на которую я давал линк)

// Обработчик для mouseover
function mouseoverHandler(event) {
	event = event || window.event
	var relatedTarget = event.relatedTarget || event.fromElement
	// для mouseover
	// relatedTarget - элемент, с которого пришел курсор мыши
}

// Обработчик для mouseout
function mouseoutHandler(event) {
	event = event || window.event
	var relTarg = event.relatedTarget || event.toElement
	// для mouseout
	// relatedTarget - элемент, на который перешел курсор мыши
}


кстати подправить там надо, relTarg во второй функции (комментарий)

devote 06.08.2012 20:38

ну дык это и называется костыль
<div id="la" style="width: 100px; height: 100px; background: #f00;">
    <a href="">test</a>
</div>
<script>
    function onMouseEnter( elem, callback ) {
        if ( "onmouseenter" in elem ) {
            if ( elem.addEventListener ) {
                 elem.addEventListener( "mouseenter", callback, false );
            } else {
                 elem.attachEvent( "onmouseenter", callback );
            }
        } else if ( elem.addEventListener ) {
            elem.addEventListener( 'mouseover', function( event ) {

                var relTarg = event.relatedTarget;

                while( relTarg && relTarg !== elem && ( relTarg = relTarg.parentNode ) ) {}

                if ( relTarg !== elem ) {
                    callback && callback.call( this, event );
                }
            }, false );
        }
    }

    function onMouseLeave( elem, callback ) {
        if ( "onmouseleave" in elem ) {
            if ( elem.addEventListener ) {
                 elem.addEventListener( "mouseleave", callback, false );
            } else {
                 elem.attachEvent( "onmouseleave", callback );
            }
        } else if ( elem.addEventListener ) {
            elem.addEventListener( 'mouseout', function( event ) {

                var relTarg = event.relatedTarget;

                while( relTarg && relTarg !== elem && ( relTarg = relTarg.parentNode ) ) {}

                if ( relTarg !== elem ) {
                    callback && callback.call( this, event );
                }
            }, false );
        }
    }

    var elem = document.getElementById('la');
    onMouseEnter( elem, function() {
        document.body.appendChild(document.createTextNode('over|'));
    });
    onMouseLeave( elem, function() {
        document.body.appendChild(document.createTextNode('out|'));
    });
</script>

devote 06.08.2012 20:49

чуть подправил код.

codingfighter 06.08.2012 21:13

хм... пытаюсь разобраться в костыле. можно поподробнее прокомментировать?

devote 06.08.2012 21:16

Цитата:

Сообщение от codingfighter
костыль какой-то слишком неповоротливый.

что значит не поворотливый?

Цитата:

Сообщение от codingfighter
что если вот мы получили элемент на который перешел курсор, как проверить находится ли он в списке дочерних элементов

именно это я и проверяю в костыле, с помощью конструкции while(){}

Цитата:

Сообщение от codingfighter
элемента с определенным айди?

всмысле? не совсем понял причем тут айди?

codingfighter 06.08.2012 21:17

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

devote 06.08.2012 21:19

Цитата:

Сообщение от codingfighter
так, я просто запарился уже пол дня париться над этой фигней. смотри, у меня элементы создаются динамически (ну на которые надо ставить эти события).

ну дык и ставь, в чем проблема?

codingfighter 06.08.2012 21:24

Заработало!!! Спасибо тебе, добрый человек!)

codingfighter 06.08.2012 21:29

А то я сам уже ну просто запарился. Учитывая то что я уже весьма устал зря ты такой костыль крупный реализовал, надо было просто основы расписать ну и далее я уже сам бы все сделал :)

В общем вот основа.

событие onmouseover

function go_get(event) {
	event = event || window.event;
	var relatedTarget = event.relatedTarget || event.fromElement;
	
	var elem = document.getElementById("where_is_parent");
	
	while( relatedTarget && relatedTarget !== elem && ( relatedTarget = relatedTarget.parentNode ) ) {}

	if ( relatedTarget === elem ) {
		return;
    }

//...


событие onmouseout

function go_away(event) {
	event = event || window.event;
	var relTarg = event.relatedTarget || event.toElement;
	
	var elem = document.getElementById("where_is_parent");
	
	while( relTarg && relTarg !== elem && ( relTarg = relTarg.parentNode ) ) {}
	 
	if ( relTarg === elem ) {
		return;
	} 

//...


Все остальное - мишура :)

devote 06.08.2012 21:36

Цитата:

Сообщение от codingfighter
Все остальное - мишура

тебе виднее, я лишь реализовал кроссбраузерное решение для использования события onmouseenter и onmouseleave, а уж как вы его переиначите собственно решать вам.. Ведь ты не один явно задаешься таким вопросом, может потом кто будет искать решение, и оно уже написано. Так что хуже от этого никому.

codingfighter 06.08.2012 21:41

Ну вот зачем тут примешивать onmouseenter и onmouseleave ?? Они не нужны, и без них хорошо, и кода меньше. Тем более еще и динамически назначать события лично мне неудобно, когда можно применить такой простой и четкий подход, сразу при инсерте html кода можно вписать функции для событий onmouseover и onmouseout. Тем более, опять же, работает кроссбраузерно.

devote 06.08.2012 21:47

Цитата:

Сообщение от codingfighter
Ну вот зачем тут примешивать onmouseenter и onmouseleave ??

а все очень просто, если элемент будет иметь огромное количство потомков, вариант с поиском родителя будет занимать какое то время, тем самым такой вариант приводит к замедлению работы скрипта. Конечно если вы не заботитесь об оптимизации и скорости. То понятно дело что достаточно повесить событие лишь на одно общее.. Но я например не приемлю лишнюю нагрузку и всегда стараюсь писать более оптимизировано. Особенно если браузер это позволяет.

devote 06.08.2012 21:50

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

bes 06.08.2012 22:03

Я бы предложил использовать делегирование и вешать обработчики на родителя (лучше прямо на body)

devote 06.08.2012 22:06

Цитата:

Сообщение от bes
Я бы предложил использовать делегирование и вешать обработчики на родителя (лучше прямо на body)

в данной проблеме делегирование не поможет

bes 06.08.2012 22:37

Цитата:

Сообщение от devote
в данной проблеме делегирование не поможет

Да, есть проблемы при быстрых уходах, хотя идея привлекательна (может быть чего-нибудь и можно сделать)

<style>
	.show {
		background: lightgreen;
		margin: 40px;
	}
	.div {
		background: lightgrey;
		padding: 2px;
	}
</style>
<div class="show">show</div>
<div class="div">
	<a href="#">link1</a><br>
	<a href="#">link2</a><br>
	<a href="#">link3</a><br>
</div>


<script>
window.onload = function () {
	document.body.onmouseout = function (e) {
		e = e || event; 
		var rt = e.relatedTarget || e.toElement;
		var target = e.target || e.srcElement;
		if (target.className == 'div' && rt.parentNode.className != 'div') {
			target.style.display = 'none';
		}
	}
	document.onmouseover = function (e)  {
		e = e || event;
		var target = e.target || e.srcElement;
		if (target.className == 'show') {
			target.parentNode.children[1].style.display = 'block';
		}
	}
}
</script>

Deff 06.08.2012 22:46

Цитата:

Сообщение от codingfighter
Столкнулся с довольно странной проблемой. Стоит родительский div в котором прописаны события onmouseover и onmouseout. Все работает, но когда наводишь курсор на ссылку внутри этого div'a чего-то срабатывает событие onmouseout



Чот не наблюдаю эффекта - скорее всего внедрена ссылка вне данного div

<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Cообщения</title>

</head>
<body align=center>

<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>

<style type="text/css">
#LinkInserTium {
  text-align:center;
  margin:0 auto;
  height:100px;
  width:100px;
  border:1px red solid;
}
#LinkInserTium:hover {
  background-color:#0000CC;
}

#LinkInserTium a {
  padding:0 4px;
  background-color:#F7F7F7;
  border:1px red solid;
}

#hover {
  display:none;

}
</style>

<div id=LinkInserTium><br />
        <a href="/sdfsdf/">ПриветБ</a>

</div>
<span id=hover>Мышь в DIV</span><span id=out>Мышь ушла с Блока</span>

<script type="text/javascript">
$("#LinkInserTium").mouseover(function(){
       $("#hover").show();$("#out").hide();
    }).mouseout(function(){
       $("#hover").hide();$("#out").show();
    });
</script>

</body>
</html>

devote 06.08.2012 23:04

Deff,
на таком примере и не заметишь, потому как браузер просто не успевает внести изменения в ДОМ, как снова нужно вернуть обратное, это заметно на таком примере:
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Cообщения</title>
 
</head>
<body align=center>
 
<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
 
<style type="text/css">
#LinkInserTium {
  text-align:center;
  margin:0 auto;
  height:100px;
  width:100px;
  border:1px red solid;
}
#LinkInserTium:hover {
  background-color:#0000CC;
}
 
#LinkInserTium a {
  padding:0 4px;
  background-color:#F7F7F7;
  border:1px red solid;
}
 
#hover {
  display:none;
 
}
</style>
 
<div id=LinkInserTium><br />
        <a href="/sdfsdf/">ПриветБ</a>
 
</div>
<span id=hover>Мышь в DIV</span><span id=out>Мышь ушла с Блока</span>
 
<script type="text/javascript">
$("#LinkInserTium").mouseover(function(){
       document.body.appendChild(document.createTextNode('over|'));
    }).mouseout(function(){
       document.body.appendChild(document.createTextNode('out|'));
    });
</script>
 
</body>
</html>
вот тут при наведении на ссылку сработает out а потом снова over, вот именно в этом промежутке твое решение и не заметно, так как при out просто не успевает отрисоваться, как снова нужно опять отрисовывать over

Deff 06.08.2012 23:31

devote,
А поставь фон по hover(как у меня) и попробуй выводить и цвет фона ( если сss цвета не меняецо - мож его отслеживать на переходах ?

Deff 06.08.2012 23:40

<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Cообщения</title>
 
</head>
<body align=center>
 
<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
 
<style type="text/css">
#LinkInserTium {
  text-align:center;
  margin:0 auto;
  height:100px;
  width:100px;
  border:1px red solid;
}
#LinkInserTium:hover {
  background-color:#0000CC;
}
 
#LinkInserTium a {
  padding:0 4px;
  background-color:#F7F7F7;
  border:1px red solid;
}
 
#hover {
  display:none;
 
}
</style>
 
<div id=LinkInserTium><br />
        <a href="/sdfsdf/">ПриветБ</a>
 
</div>
<span id=hover>Мышь в DIV</span><span id=out>Мышь ушла с Блока</span>
 
<script type="text/javascript">
$("#LinkInserTium").mouseover(function(){
       var a=$(this).css("background-color")
       document.body.appendChild(document.createTextNode(a+'over|'));
    }).mouseout(function(){
       var a=$(this).css("background-color")
       document.body.appendChild(document.createTextNode(a+'out|'));
    });
</script>

</body>
</html>


Цвет не меняется при данных пертурбациях - так шо он флаг - если цвет тот жа что и при hover - из .mouseout - return false;

Deff 06.08.2012 23:54

devote,
:) A а вообщем Ти прав .mouseleave/.mouseenter на JQ - работает и в ИЕ

<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Cообщения</title>
 
</head>
<body align=center>
 
<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
 
<style type="text/css">
#LinkInserTium {
  text-align:center;
  margin:0 auto;
  height:100px;
  width:100px;
  border:1px red solid;
}
#LinkInserTium:hover {
  background-color:#0000CC;
}
 
#LinkInserTium a {
  padding:0 4px;
  background-color:#F7F7F7;
  border:1px red solid;
}
 
#hover {
  display:none;
 
}
</style>
 
<div id=LinkInserTium><br />
        <a href="/sdfsdf/">ПриветБ</a>
 
</div>
<span id=hover>Мышь в DIV</span><span id=out>Мышь ушла с Блока</span>
 
<script type="text/javascript">
$("#LinkInserTium").mouseenter(function(){
       var a=$(this).css("background-color")
       document.body.appendChild(document.createTextNode(a+'over|'));
    }).mouseleave(function(){
       var a=$(this).css("background-color")
       document.body.appendChild(document.createTextNode(a+'out|'));
    });
</script>

</body>
</html>

devote 07.08.2012 00:59

Deff,
ну теперь понял разницу в событиях? mouseover, mouseout работают совсем не так как mouseenter, mouseleave... И дело совсем не в ощутимости изменения цвета иль еще чего.. а втом что при сожании на mouseenter обработчика, я знаю что оно будет вызвано лишь раз для элемента, и не произайдет делегирования, то есть оно не будет срабатывать если я мышь держу в его приделах даже на дочерних элементах... что не скажешь о событии mouseover, которое будет срабатывать даже если я не уходил с элемента за его пределы, а всего лишь перешел на дочерний элемент, это и есть делегирование.. когда событие родителя срабатывает по цепи захвата/всплытия

Deff 07.08.2012 01:07

devote,
Да мну вобщем её не забывал - другое дело - что показалась, что задача ошибки внедрения объекта вне div...
А далее по накатанной -коли текущий метод и событие в руках - "как исправить" - потом - понято - чо дух противоречия и накатанности - тут ни к чему - (* хотя походу - mouseenter, mouseleave в JQ сгенерили по флагу из mouseover, mouseout - иначе в ИЕ б -7 не работало

devote 07.08.2012 01:14

Цитата:

Сообщение от Deff
иначе в ИЕ б -7 не работало

в ИЕ6-7 всегда были эти события, этих событий нет в хроме и возможно в ФФ. А в ИЕ и Опере они всегда существовали.

Deff 07.08.2012 01:17

devote, потестил в JQ
Работает везде

devote 07.08.2012 01:19

Цитата:

Сообщение от Deff
Работает везде

ну вот для Хрома и ФФ видимо джуквери эмулирует это событие, так же как я это делаю в посте который на первой странице. Некий костыль.

Deff 07.08.2012 01:22

devote,
Ну через css цвет тож можно эмуляцию сделать (она чуть попроще наверно - там жа любой параметр - можно вснуть по hover

devote 07.08.2012 01:25

не спорю, hover это и есть события mouseenter/mouseleave, одно странно почему на уровне JS не реализовал Хром и ФФ этих событий, вот это загадка..

oneguy 07.08.2012 01:27

Цитата:

Сообщение от devote
не спорю, hover это и есть события mouseenter/mouseleave, одно странно почему на уровне JS не реализовал Хром и ФФ этих событий, вот это загадка..

Вообще-то в ФФ эти события работают, я проверял.

devote 07.08.2012 01:29

Цитата:

Сообщение от oneguy
Вообще-то в ФФ эти события работают, я проверял.

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

codingfighter 07.08.2012 20:54

Цитата:

Конечно если вы не заботитесь об оптимизации и скорости
А откуда такие выводы? Элементов у меня там немного, скорость меня устраивает.

Что, так значит работают эти события? О_о
jquery подключена. но тестить сейчас уже неохото, так это она события эти эмулирует или нет?

devote 07.08.2012 22:24

Цитата:

Сообщение от codingfighter
так это она события эти эмулирует или нет?

для себя да


Часовой пояс GMT +3, время: 19:57.