Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Вызов функции вне html объекта (https://javascript.ru/forum/jquery/12141-vyzov-funkcii-vne-html-obekta.html)

arwprod 03.10.2010 00:59

Вызов функции вне html объекта
 
Всем ночи доброй.
Пишу функцию меню, нечто похожее на выпадающие меню во всех программах (например вашем браузере). Суть простая, тыкнули на пункт меню, открылся children. Тыкнули на область вне элемента, на который вызвали функцию, всё вернулось в исходное состояние.

Возможно объяснил неочень, но легко понять, если потыкать меню в браузере)))

Собственно как грамотно определить саму область вне элемента, пока непонятно, кто-нибудь занимался подобным?

arwprod 03.10.2010 01:04

Тоесть проще говоря нужно взять область элемента "body" и вырезать из неё элемент, пусть будет "div#menu". Пока работаем с "div#menu", работает плагин, когда кликаем вне "div#menu", плагин возвращается в исходное состояние, как буд-то страниу обновили...

Octane 03.10.2010 01:07

каждый раз при открытии меню делать:
$(document).one("click", close_menu)

arwprod 03.10.2010 01:16

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

Octane 03.10.2010 01:46

Что непонятного? Открыли меню, повесили обработчик для закрытия. Или меню многоуровневое? Тогда повесьте постоянный обработчик на документ и проверяйте event.target

Aetae 03.10.2010 01:49

Цитата:

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

На менюшке всплытие отменить и дело в шляпе.)

arwprod 03.10.2010 01:59

Aetae, спасибо )
Octane, и вам) Обрабатывать страницу при каждом действии пользователя, по-моему не очень, а вешать обработчик на одноуровневое меню - вполне.

Octane 03.10.2010 02:05

Если меню должно закрываться по клику на странице, то в любом случае будет обработчик события click на document или другом общем для всех элементов узле (html, body, …), не понятно к чему вы сказали:
Цитата:

Сообщение от arwprod
Обрабатывать страницу при каждом действии пользователя, по-моему не очень, а вешать обработчик на одноуровневое меню - вполне.

Видимо еще не поняли, что нужно сделать.

arwprod 03.10.2010 02:07

Aetae, а кросс-браузерного варианта для отмены всплытия от нижнего элемента к верхнему нету? =\

arwprod 03.10.2010 02:11

Цитата:

Сообщение от Octane (Сообщение 72846)
Если меню должно закрываться по клику на странице, то в любом случае будет обработчик события click на document или другом общем для всех элементов узле (html, body, …), не понятно к чему вы сказали:
Видимо еще не поняли, что нужно сделать.

дело в том, если мы открываем меню кликом, то оно у нас тут же закрывается, т.к. наше меню является частью document.

На самом деле нагородить можно всё что угодно, но пока что хотелось бы найти способ вырезать это самое меню из document и один раз вызвать функцию "close_menu", при клике на полученную область в document. И при этом чтобы плагин выключился и не работал, пока мы опять не ткнемся мышкой в меню...

Aetae 03.10.2010 02:23

Цитата:

Сообщение от arwprod (Сообщение 72847)
Aetae, а кросс-браузерного варианта для отмены всплытия от нижнего элемента к верхнему нету? =\

А для кого я линк в пост вставил?)

arwprod 03.10.2010 02:37

Aetae, либо ночь на дворе, либо: "Остановка всплытия" - кроссбраузерно, а остальное нет... Хотя в моем случае по-моему все равно откуда и куда двигаться... пора спать, завтра выложу результат =\

arwprod 03.10.2010 02:53

Octane,
Вы это имели ввиду?
if($(event.target.nodeName).parent('ul').hasClass('menu')){alert('Нажали на меню')}

вместо alerta делаем вызов по умолчанию, в противном случае, выключаем менюшку?

monolithed 03.10.2010 11:47

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<style type="text/css">
body {background: #424A51;}
.block {position:absolute;top:20%;left: 40%;width: 200px;height: 50px;}
.block a {border: 1px solid #DDD;color: #FFF;display: block;text-align: center;text-decoration:none;width: 140px;height: 20px;}
.block img {border: 1px solid #DDD; width: 140px;height: 50px;}
</style>

<script type="text/javascript">
$(function(){
	$('.block').each(function(){
		$(this).find('img').hide();
		$(this).find('a').mouseover(function(){
			$(this).next('img').show();
		});
		$(document).click(function(e){
			(e.target.nodeName != $('.block img').get(0).tagName) && $(this).find('img').hide();
		});
	});
});
</script>

<div class="block">
	<a href="#" rel="">link</a>
	<img src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif" alt="" />
</div>

arwprod 03.10.2010 12:29

monolithed, не пойдет

$("body").click(function(event) {
	if($(event.target.nodeName).parents('ul').hasClass('menu') || event.target.className == 'menu'){
		//открываем меню, сделав еще1 клик
	} else {
		//закрываем меню
	}
});


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

//conf - options	
if(conf.event == 'click') {
	$("body").click(function(event) {
		if($(event.target.nodeName).parents('ul').hasClass('menu') || event.target.className == 'menu'){
			//открываем меню, без какого-либо event
		} else {
			//закрываем меню
		}
	}); 
} else {
	//юзаем обычный hover для работы с вложенностью
}

monolithed 03.10.2010 12:41

Цитата:

arwprod monolithed, не пойдет
Интересно узнать почему?

arwprod 03.10.2010 12:46

monolithed,
потому что, если
$(this).find('a').mouseover(function(){

заменить на
$(this).find('a').click(function(){

картинка не откроется вообще

Octane 03.10.2010 14:46

Цитата:

Сообщение от arwprod
$(event.target.nodeName)

Зачем nodeName?

Код простейший же:
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Menu</title>
<style>
body {
	font: 14px/24px sans-serif;
}
.nav {
	height: 24px;
	background: #ccc;
	zoom: 1; /* IE7 clear fix */
}
.nav:after {
	display: block;
	overflow: hidden;
	height: 0;
	clear: both;
	content: ".";
}
.menu {
	position: relative;
	float: left;
	margin-right: 10px;
}
.menu .list, .menu .list li {
	display: block;
	margin: 0;
	padding: 0;
	list-style: none;
}
.menu .list {
	display: none;
	position: absolute;
	top: 24px;
	left: 0;
	background: #ccf;
}
.menu .list li {
	white-space: nowrap;
}
</style>
<div class="nav">
	<div class="menu">
		<span class="toggler">Menu 1</span>
		<ul class="list">
			<li><a href="#">Menu 1 item 1</a></li>
			<li><a href="#">Menu 1 item 2</a></li>
			<li><a href="#">Menu 1 item 3</a></li>
			<li><a href="#">Menu 1 item 4</a></li>
			<li><a href="#">Menu 1 item 5</a></li>
		</ul>
	</div>
	<div class="menu">
		<span class="toggler">Menu 2</span>
		<ul class="list">
			<li><a href="#">Menu 2 item 1</a></li>
			<li><a href="#">Menu 2 item 2</a></li>
			<li><a href="#">Menu 2 item 3</a></li>
			<li><a href="#">Menu 2 item 4</a></li>
			<li><a href="#">Menu 2 item 5</a></li>
		</ul>
	</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
$(function () {
	$(".menu .toggler").click(function () {
		var $list = $(this).next(".list").stop();
		$list.slideDown(100, function () {
			$(document).one("click", function () {
				$list.slideUp(100);
			})
		});
	});
});
</script>

monolithed 03.10.2010 16:55

Цитата:

Сообщение от Octane
Зачем nodeName?

Для того чтобы можно перенести фокус на элемент, к примеру если он будет наполнен текстом и пр..

arwprod 04.10.2010 01:30

Octane, да вот если зохочется внести форму в какой-то пункт меню, то трындец)))
monolithed, именно для этого)

Octane 04.10.2010 03:01

Цитата:

Сообщение от arwprod
да вот если зохочется внести форму в какой-то пункт меню, то трындец)))

И что произойдет?

arwprod 04.10.2010 21:21

Цитата:

Сообщение от Octane (Сообщение 72945)
И что произойдет?

меню закроется, а так ничего)

Собственно говоря реализаций море, самого наработок много лежит. Но задача сейчас другая, определить элемент на который вызывается функция '<ul id="menu">'. Пока работаем с ним, открываются вкладки меню: ссылки, формы, текстовые блоки, картинки, грузится ajax в каком-нибудь другом блоке, в общем всё, что угодно.
Как-только кликнули куда-нибудь вне блока нашего меню, меню сбрасывается на первоначальный вид.

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

Octane 04.10.2010 22:45

Сразу все подробности поведения меню конечно трудно было описать… остается проверять event.target и его родителей.

arwprod 04.10.2010 23:44

Octane, прошу прощения, на счет "клика" внутри меню, моё упущение.

$('ul.menu').menu({/* config */});

$("body").click(function(event) {
	if(!$(event.target).parents('ul').hasClass('menu')){
		$('ul.menu').menu({/* config */}, 'destroy');
	}
});


Хотя, как мне кажется, это не лучший вараинт)

Octane 04.10.2010 23:58

Ну можно попробовать подкладывать под меню div {position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: url(empty.gif); } с прозрачным фоном и по клику на него скрывать меню, если так не хочется вешать обработчик на body или document.

arwprod 05.10.2010 00:14

Octane

$('div#cl').click(function(event) {
    $('ul.menu').menu({/* config */}, 'destroy');
});


'div#cl' положил после <body>. В таком варианте не работает, если мы тыкаем на определенный элемент в html документе, ну, что в принципе логично... Если ограничиваться кликами по пустой области в документе, то конечно вариант намного лучше, потому что каждый раз не делаем проверок.


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