Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   drag & drop, mouseup (https://javascript.ru/forum/events/29438-drag-drop-mouseup.html)

cyber 27.06.2012 22:58

drag & drop, mouseup
 
пишу фреймворк который перемещает элементы в определенный блок,
так вот задумался а как лучше определять вошел элемент в нужную область или нет , есть 2 варианта :
1. использовать document.elementFromPoint(clientX, clientY)

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

devote 28.06.2012 00:23

Цитата:

Сообщение от cyber
1. использовать document.elementFromPoint(clientX, clientY)

А кто мешает это юзать? вроде насколько мне помнится это и в ИЕ отлично работает, даже IE7 если не ошибавюсь.
<!doctype html>
<html>
	<head>
	</head>
	<body>

<div id="dragged" style=" top: 10px; width: 50px; height: 50px; background-color: #0f0; position: absolute;"></div>
<div id="target" style="position: absolute; border: 10px solid #f00; left: 50%; top: 40%; width: 100px; height: 100px; background-color: #f00;"></div>

<script type="text/javascript">

var oX, oY, elmousedowned = null;

document.getElementById('dragged').onmousedown = function( e ) {

	e = e || window.event;

    elmousedowned = e.target || event.srcElement;

    oX = e.offsetX || e.layerX;
    oY = e.offsetY || e.layerY;

    elmousedowned.style.zIndex = 100;
}
document.onmousemove = function( e ) {
    if ( elmousedowned ) {

		e = e || window.event;

		if ( e.pageX == null && e.clientX != null ) {
			var html = document.documentElement;
			var body = document.body;
			e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
			e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
		}

        elmousedowned.style.left = ( e.pageX - oX ) + "px";
        elmousedowned.style.top = ( e.pageY - oY ) + "px";

        // временно уберем перетаскиваемый элемент, что бы увидеть что под курсором
        elmousedowned.style.display = 'none';

        var el = document.elementFromPoint( e.pageX, e.pageY );

        if ( el && el === document.getElementById('target') ) {
            el.style.borderColor = "#00f";
        } else {
            document.getElementById('target').style.borderColor = "#f00";
        }

        elmousedowned.style.display = 'block';
    }
}
document.onmouseup = function() {
	if ( elmousedowned ) {
	    elmousedowned.style.zIndex = "";
	    elmousedowned = null;
	}
}
</script>

	</body>
</html>

cyber 28.06.2012 00:40

Цитата:

Сообщение от devote (Сообщение 184703)
А кто мешает это юзать? вроде насколько мне помнится это и в ИЕ отлично работает, даже IE7 если не ошибавюсь.
<!doctype html>
<html>
	<head>
	</head>
	<body>

<div id="dragged" style=" top: 10px; width: 50px; height: 50px; background-color: #0f0; position: absolute;"></div>
<div id="target" style="position: absolute; border: 10px solid #f00; left: 50%; top: 40%; width: 100px; height: 100px; background-color: #f00;"></div>

<script type="text/javascript">

var oX, oY, elmousedowned = null;

document.getElementById('dragged').onmousedown = function( e ) {

	e = e || window.event;

    elmousedowned = e.target || event.srcElement;

    oX = e.offsetX || e.layerX;
    oY = e.offsetY || e.layerY;

    elmousedowned.style.zIndex = 100;
}
document.onmousemove = function( e ) {
    if ( elmousedowned ) {

		e = e || window.event;

		if ( e.pageX == null && e.clientX != null ) {
			var html = document.documentElement;
			var body = document.body;
			e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
			e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
		}

        elmousedowned.style.left = ( e.pageX - oX ) + "px";
        elmousedowned.style.top = ( e.pageY - oY ) + "px";

        // временно уберем перетаскиваемый элемент, что бы увидеть что под курсором
        elmousedowned.style.display = 'none';

        var el = document.elementFromPoint( e.pageX, e.pageY );

        if ( el && el === document.getElementById('target') ) {
            el.style.borderColor = "#00f";
        } else {
            document.getElementById('target').style.borderColor = "#f00";
        }

        elmousedowned.style.display = 'block';
    }
}
document.onmouseup = function() {
	if ( elmousedowned ) {
	    elmousedowned.style.zIndex = "";
	    elmousedowned = null;
	}
}
</script>

	</body>
</html>

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

cyber 28.06.2012 00:47

а не сильно ли напряжно для браузера каждый раз менять при смещение на пик сель менять display

cyber 28.06.2012 01:16

вот что у меня получилось
http://cyberua.16mb.com/drag&drop/
но проблема в том что когда элементов больше чем блок они выходят за его границы , как можно опередить когда нужно увеличивать его высоту или ширину?

cyber 28.06.2012 01:22

все проблему решил=)

cyber 28.06.2012 01:29

не все таки от чужих идей не откажусь=)
если ставить height auto то не очень красиво=)

devote 28.06.2012 07:20

Цитата:

Сообщение от cyber
а не сильно ли напряжно для браузера каждый раз менять при смещение на пик сель менять display

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

Цитата:

Сообщение от cyber
вот что у меня получилось

у меня не работает:
[17.02.1972 15:33:22] JavaScript - http://cyberua.16mb.com/drag&drop/
Event thread: mousedown
Uncaught exception: DOMException: NO_MODIFICATION_ALLOWED_ERR
Error thrown at line 61, column 5 in <anonymous function: down>(e) in http://cyberua.16mb.com/drag&drop/drag_manager/drag.js:
    e.target = e.target || e.srcElement;
called from line 20, column 6 in <anonymous function: onmousedown>(e) in http://cyberua.16mb.com/drag&drop/drag_manager/drag.js:
    if(!action.down(e))

cyber 28.06.2012 11:16

Цитата:

Сообщение от devote (Сообщение 184724)
браузер не успевает запустить периресовку. Поэтому напряга не должно быть.


у меня не работает:
[17.02.1972 15:33:22] JavaScript - [url]http://cyberua.16mb.com/drag&drop/[/url]
Event thread: mousedown
Uncaught exception: DOMException: NO_MODIFICATION_ALLOWED_ERR
Error thrown at line 61, column 5 in <anonymous function: down>(e) in [url]http://cyberua.16mb.com/drag&drop/drag_manager/drag.js:[/url]
    e.target = e.target || e.srcElement;
called from line 20, column 6 in <anonymous function: onmousedown>(e) in [url]http://cyberua.16mb.com/drag&drop/drag_manager/drag.js:[/url]
    if(!action.down(e))

а что за браузер?
я у себя даже в ие7 проверял, там ток opacity не работает

cyber 28.06.2012 11:29

попробуйте еще раз http://cyberua.16mb.com/drag&drop/ пере залил все файлы

devote 28.06.2012 14:39

Цитата:

Сообщение от cyber
попробуйте еще раз http://cyberua.16mb.com/drag&drop/ пере залил все файлы

таже ситуация.. ясно же написано, в ошибке, что свойство e.target нельзя менять
e.target = e.target || e.srcElement;
сделай иначе:
var target = e.target || e.srcElement;

cyber 28.06.2012 14:44

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

devote 28.06.2012 14:48

Цитата:

Сообщение от cyber
понял, но блин не пойму почему у меня на 3х компах даже в самых древних браузерах работает

потому что в старых ИЕ нет такого свойства, а другие браузеры не знаю почему не орут при модификации данного свойства. Хотя в спецификации четко и ясно написано что свойство target - readonly.

У меня браузер Opera 11.64

cyber 28.06.2012 14:50

все поправил target и перевалил http://cyberua.16mb.com/drag&drop/ .
а проблему с высотой решил так
width_height:function( drop_elem){
		
		var width_drop, height_drop, height, width, height_drag, width_drag;
		
		 if(action.auto){
			  drop_elem.style.height = "auto"; 
			   action.auto = "stop";
		  }
		  width_drop = drop_elem.offsetWidth;
		   height_drop = drop_elem.offsetHeight;
		     
			 width_drag = drag.obj.offsetWidth + parseInt(getComputed(drag.obj).marginLeft);
			  width_drag +=  parseInt(getComputed(drag.obj).marginRight);
			   
			   height_drag = drag.obj.offsetHeight  + parseInt(getComputed(drag.obj).marginTop);
			   
			     height_drag +=  parseInt(getComputed(drag.obj).marginBottom);
				
				width = width_drop - width_drag * action.count;
			      height = height_drop - height_drag ;
				  
				  if(width <  width_drag && height < height_drag) action.auto = true;
				  
		  
		 }

devote 28.06.2012 14:57

cyber,
теперь с этим:
e.which = e.which || e.button;
таже трабла

devote 28.06.2012 14:58

cyber,
не пытайся перезаписывать о объекта Event свойства, по спецификации они все readonly

cyber 28.06.2012 15:10

хм...
просто интересно что у вас за браузер?=)

devote 28.06.2012 15:15

cyber,
яж написал выше, Opera 11.64

cyber 28.06.2012 15:22

не увидел=)
и опять опера видет себя хуже ИЕ , щас поправлю=)

devote 28.06.2012 15:24

Цитата:

Сообщение от cyber
и опять опера видет себя хуже ИЕ

вот тут ты не прав, Опера ведет себя так как описано в спецификациях.. не нужно считать что Баг ИЕ это круто, а правильность Оперы это БАГ

devote 28.06.2012 15:26

Цитата:

Сообщение от cyber
кстати у меня почему то этот код не работает в ие

он и не будет рабоать:
return getComputedStyle(obj, null) || drag.obj.currentStyle;
вот тут и ошибка getComputedStyle в ИЕ вызовет останов выполнения скриптов

devote 28.06.2012 15:28

писать нужно так:
function getComputed (obj){
    if ( obj.ownerDocument && obj.ownerDocument.defaultView ) {
        return obj.ownerDocument.defaultView.getComputedStyle( obj, null );
    } else if ( obj.currentStyle ) {
        return obj.currentStyle;
    }
    return null;
}

cyber 28.06.2012 15:31

а что значит
obj.ownerDocument.defaultView

devote 28.06.2012 15:32

Цитата:

Сообщение от cyber
а что значит
obj.ownerDocument.defaultView

Это текущий документ отображения.. По сути обычный объект window но в другом исполнении.

cyber 28.06.2012 15:33

Цитата:

Сообщение от devote (Сообщение 184897)
Это текущий документ отображения.. По сути обычный объект window но в другом исполнении.

а зачем он в проверке не совсем понял..

cyber 28.06.2012 15:34

а если так
try{ 
	 
	    return getComputedStyle(obj, null)
	   
	   } catch(e){ 
	      
		  return obj.currentStyle;
		   }

devote 28.06.2012 15:37

Цитата:

Сообщение от cyber
а зачем он в проверке не совсем понял..

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

Сообщение от cyber
а если так

А вы что пытаетесь экономить на весе коде?

cyber 28.06.2012 15:41

Цитата:

Сообщение от devote (Сообщение 184901)
потому что эту придумано не так давно.. то есть не во всех браузерах есть, поэтому его нужно проверять.

А вы что пытаетесь экономить на весе коде?

нет, просто спросил как вариант =)
хм , а почитать есть что то про эту проверку на русском

devote 28.06.2012 15:42

Цитата:

Сообщение от cyber
хм , а почитать есть что то про эту проверку на русском

Ну я обычно спецификации читаю, а они никогда не бывают на русском

cyber 28.06.2012 15:43

теперь вроде все поправил=)
http://cyberua.16mb.com/drag&drop/

cyber 28.06.2012 15:48

Цитата:

Сообщение от devote (Сообщение 184914)
Ну я обычно спецификации читаю, а они никогда не бывают на русском

а где можно почитать?

devote 28.06.2012 15:59

Цитата:

Сообщение от cyber
а где можно почитать?

w3.org

cyber 28.06.2012 16:05

кстати работает у вас ?=)

devote 28.06.2012 16:08

Цитата:

Сообщение от cyber
кстати работает у вас?=)

нет конечно, вы же ничего не исправили:
e.which = e.which || e.button;

cyber 28.06.2012 16:11

Цитата:

Сообщение от devote (Сообщение 184929)
нет конечно, вы же ничего не исправили:
e.which = e.which || e.button;

я только хотел написать=)
кстати firefox 3.6 в отличие от 13 я так понял больше отвечает спецификации..
потому что в 3.6 не работает а в 13 работает

cyber 28.06.2012 16:13

все в firefox 3.6 работает значит в опере должно
http://cyberua.16mb.com/drag&drop/
:dance:

devote 28.06.2012 16:14

Цитата:

Сообщение от cyber
значит в опере должно

да работает

cyber 28.06.2012 16:19

Цитата:

Сообщение от devote (Сообщение 184937)
да работает

спасибо за помощь=)

cyber 30.06.2012 22:59

возник еще один вопрос, не хочу создавать новую тему поэтому напишу тут, мне нужно найти все элементы с атрибутом draggable, но перебирать

var all_tag = getElementsByTagName('*');
....
while(i--){

all_tag[i].getAttribute("draggable")

}

не очень хочется...
если какие то другие варианты?
и если нет то как оптимизировать ее?

devote 30.06.2012 23:12

document.querySelectorAll('[draggable]');
в ИЕ7 работать не будет


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