Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   контекстное меню (https://javascript.ru/forum/misc/51323-kontekstnoe-menyu.html)

skrudjmakdak 02.11.2014 18:31

контекстное меню
 
решил сделать типа самописного комбобокса и столкнулся с проблемкой:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>Example</title>  
		<style>
.list {
	position: absolute;
	background-color: white;
	margin: 5px 0px 5px 0px;
	border: 1px solid black;
	z-index: 5000;
	width: 200px;
}

.list div:hover {
	background-color: yellow;
	cursor: pointer;
}
		</style>
    </head>
	<body>
		<input type="text" value="234" onfocus="f(this);">
		<div class="list" onclick="s(this, event)" style="display: none;">
			<div>111111</div>
			<div>222222</div>
			<div>333333</div>
		</div>
	<script>
	var menu = document.querySelector('.list'),
		input = document.querySelector('input');
	
	contextMenuList = [];
	function f (ths) {
		menu.style.display = 'block';
		contextMenuList.push(menu, input);
	}
	
	function s (ths, event) {
		var v = event.target.innerHTML;
		input.value = v;
		if (v == '222222')
			return;
		ths.style.display = 'none';
		contextMenuList.length = 0;
	}
	
	window.document.onclick = function (e) {
		var ln = contextMenuList.length,
			el = e.target;
	
		if (ln == 0 ) {
			return;
		}
		
		do {
			for (var i = 0; i < ln; ++i) {
				if (el === contextMenuList[i]) {
					return;
				}
			}
		} while (el = el.parentNode);
		
		contextMenuList[0].style.display = 'none';
		contextMenuList.length = 0;
	}
	</script>
    </body>
</html>


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

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

ruslan_mart 02.11.2014 18:45

skrudjmakdak,
так у тебя при открытии меню фокус остаётся на поле, просто сделай, чтобы меню скрывалось по событию blur у поля.

Safort 02.11.2014 18:53

skrudjmakdak,
а в чём, собственно, проблема? Всё же работает) Или нужен совет по улучшению кода?
Можно, например, в функции s выбирать что закрывать, а что нет, основываясь на классе/спец. атрибуте, а не содержимом.
Т.е. будет как-то так:
<div class="list" onclick="s(this, event)" style="display: none;">
  <div>111111</div>
  <div class="do-nothing">222222</div>
  <div>333333</div>
</div>

function s (ths, event) {
        var v = event.target.innerHTML;
        input.value = v;
        if (event.target.classList.contains('do-nothing'))
            return;
        ths.style.display = 'none';
        contextMenuList.length = 0;
    }



Цитата:

window.document.onclick
Не надо так) Можно короче
window.onclick



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

Safort 02.11.2014 18:54

Ruslan_xDD,
Цитата:

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

skrudjmakdak 02.11.2014 19:04

подсказки просто улет. ну видно же, что так работать не будет:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>Example</title>  
		<style>
.list {
	position: absolute;
	background-color: white;
	margin: 5px 0px 5px 0px;
	border: 1px solid black;
	width: 200px;
	height: 150px;
}
		</style>
    </head>
	<body>
		<input type="text" value="234" onfocus="ff()" onblur="f();">
		<div class="list" onclick="s()"></div>
	<script>
	var menu = document.querySelector('.list'),
		input = document.querySelector('input');
	
	input.focus();
	
	function ff () {
		menu.style.display = 'block';
	}
	
	function f () {
		menu.style.display = 'none';
	}
	
	function s () {
		console.log('кликнули');
	}
	</script>
    </body>
</html>


контекстное меню закроется быстрей чем сработает клик. и браузер клика не увидит

рони 02.11.2014 19:06

skrudjmakdak,
на туже тему не так давно ...
http://javascript.ru/forum/dom-windo...tml#post338455

skrudjmakdak 02.11.2014 19:14

Safort, мне надо закрыть контекстное меню если dom элемент по которому кликнули не является дочерним элементом контекстного меню или самим элементом. т.е. есть div из примера:
<div class="list"

внутри этого дива может быть еще куча dom элементов. так вот если мы кликнули по какому то диву и этот див находится внутри контейнера контекстного меню, то закрываем по "особому условию" прописывается в методе function s(), (я там от балды накатал, для примера). а если клик произошел не внутри этого контейнера то закрыть это контекстное меню надо полюбэ

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

skrudjmakdak 02.11.2014 19:16

рони,
опять таки идет перебор родителей, как и у меня))

skrudjmakdak 02.11.2014 19:24

я думал может метод есть какой или конструкция. можно же проверить объект на принадлежность какому либо классу. может есть возможность проверки является ли компонент дочерним по отношению к кому либо.. или еще какая нибудь конструкция

function Car(model) {
  this.model = model
}
function Honda(model) {
  this.model = model
  this.isHonda = true
}
Honda.prototype = new Car()

honda = new Honda("Accord")

honda instanceof Honda // true
honda instanceof Car // **true**
honda instanceof Object // true

honda instanceof Date // false

рони 02.11.2014 19:34

skrudjmakdak,
вариант проставить класс всем элементам клик на которые надо отменить и при клике проверять этот класс.
в этом случае цикл всего один, а не при каждом клике.


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