Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   dragleave работает как mouseout, а не mouseleave? (https://javascript.ru/forum/events/41449-dragleave-rabotaet-kak-mouseout-ne-mouseleave.html)

danik.js 14.09.2013 18:18

dragleave работает как mouseout, а не mouseleave?
 
Нужно отловить момент когда указатель покидает область элемента.
element.ondragleave для этого не совсем подходит, так как срабатывает еще и при переходах к дочерним элементам (в общем, как mouseout действует).
Как быть?

danik.js 15.09.2013 13:35

Вроде бы нашел хороший способ:
var toElement = document.elementFromPoint(event.pageX, event.pageY);
if (!toElement || !myelement.contains(toElement)) {
    // конкретный dragleave
}

Правда в Opera это не всегда работает, пока что думаю как обойти проблему.

Второй вариант - завести counter и по dragenter прибавлять +1, по dragleave уменьшать -1. Если counter == 0, значит конкретный dragleave.
Опять же в Opera dragenter не происходит если перетаскиваемый_элемент = текущая_цель. В этом случае нужно делать инкремент по первому dragover. Еще в Firefox в моем экземпляре почему то первый dragenter происходит дважды.

cyber 16.09.2013 12:19

danik.js, а что не так в опере?
пробывал в 12 все работает, пробывал на примере из этой статьи (лень было свой делать) http://www.html5rocks.com/ru/tutorials/dnd/basics/

danik.js 16.09.2013 12:53

Там очень простой случай.
В опере некорректные координаты когда мышь выходит за границы окна. Поэтому если элемент-цель находится у границы окна, то document.elementFromPoint вернет этот крайний элемент вместо null, и скрипт так и не узнает что мышь уже ушла с элемента. Кроме того, в такой ситуации в опере даже само событие dragleave не всегда происходит (хз почему и отчего это зависит).

Вобще, Drag'N'Drop только на первый взгляд хорошо работает в браузерах. Если капнуть глубже, то вскрывается целая куча косяков в разных браузерах. Да и сама спецификация не до конца продумана (в последнем варианте вроде ввели событие dragexit).
Багов тьма в хроме. Лучше всех себя показал Firefox, хотя и там есть косячки. Что в хроме что в IE беда с dropEffect'ом.

cyber 16.09.2013 16:16

danik.js,
так почему тогда не написать просто на js , без хтмл 5 ?

danik.js 16.09.2013 16:43

Оно ща так и сделано. Смотри http://ace.c9.io/build/kitchen-sink.html
Проблема в том оно работает только впределах документа (то есть даже из айфрейма не выбраться) + курсор непривычный.

Яростный Меч 16.09.2013 16:55

Цитата:

Сообщение от danik.js
Багов тьма в хроме.

помню, dragleave для документа вызывался постоянно не по делу, пришлось делать костыли с таймаутом для убирания "территории сброса файла", чтобы не мерцал.

cyber 17.09.2013 09:32

danik.js, а dragenter работает нормально?

cyber 17.09.2013 10:02

danik.js, накидал по быстрому, в браузерах кроме хрома не пробывал
<!DOCTYPE HTML>
<html>
  <head><style>
    
    .column {
height: 150px;
width: 150px;
float: left;
border: 2px solid #666;
background-color: #ccc;
margin-right: 5px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: inset 0 0 3px #000;
-moz-box-shadow: inset 0 0 3px #000;
-ms-box-shadow: inset 0 0 3px #000;
-o-box-shadow: inset 0 0 3px #000;
box-shadow: inset 0 0 3px #000;
text-align: center;
cursor: move;
margin-bottom: 30px;
}
    
.column.over {
border: 2px dashed #000;
}    
    
    </style></head>
  <body>
<div class="column" id='a' draggable="true" style="opacity: 1;"><header>А</header></div>
<div class="column" id='b' draggable="true" style="opacity: 1;"><header>B</header></div>
    <script>

var b = document.getElementById('b'),
        a = document.getElementById('a');

 function dragleave (callback) {

  b.addEventListener('dragenter', function () {
   
    var self = this;
    
   
    this.className = 'column over';
    
    a.addEventListener('drag', function onDrag(e) {
      
       console.log(document.elementFromPoint(e.clientX, e.clientY));
      
      
      
      if(document.elementFromPoint(e.clientX, e.clientY) != self) {
       
        
        a.removeEventListener('drag', onDrag);
        
        callback();
      
      }
    
      
      
    });
    
  });
        
    }

      
      
      dragleave(function () {
       
        
        console.log('leave');
       
      });  
    </script>

  </body>
</html>

danik.js 17.09.2013 10:24

Ну вариант elementFromPoint я ведь сам предложил во втором посте. С ним только проблема в Опере, я уже говорил (+ contains() нету в старых браузерах).

cyber 17.09.2013 13:44

danik.js, а ну так если проблема только в fromPoint, то вот document.elementFromPoint – a jQuery solution

danik.js 17.09.2013 14:10

НЕЕЕТ!!! Проблема в том что в опере координаты неправильные при выходе за границы окна. Они не уходят в минус при движении мыши вверх/влево и не становятся больше ширины/высоты окна при движении впрапво/вниз.

cyber 17.09.2013 14:29

danik.js, в какой версии оперы ковыряешь ? (вечером посижу , попробую что то придумать )

danik.js 17.09.2013 14:53

12.14

devote 17.09.2013 15:30

danik.js,
не совсем я понял твоей проблемы в опере. Можешь пример привести?
ну что-то типо:
<!DOCTYPE html>
<html>
	<head>
	<script>
		document.onmousemove = function(e) {
			document.body.children[0].innerHTML = e.pageX + 'x' + e.pageY;
		}
	</script>
	</head>
	<body>
		Вдави мышь в пол(документ) и веди курсор проч(за пределы)
		<div></div>
	</body>
</html>

danik.js 17.09.2013 17:10

В общем способ с elementFromPoint не подходит. Он не учитывает возможность отмены операции drag'n'drop (через Esc например). При отмене произойдет событие dragleave, но мышь останется над дроп-зоной.
К тому же в webkit/blink тоже проблемы с координатами (хотя вроде скрипт работал корректно, не пойму чета).
Остаются вариант со счетчиком и вариант с накрыванием элемента оверлеем, защищающим от множественного срабатывания событий.

cyber 17.09.2013 17:12

Цитата:

Сообщение от danik.js
В общем способ с elementFromPoint не подходит. Он не учитывает возможность отмены операции drag'n'drop (через Esc например).

danik.js, а событие dragend ?

danik.js 17.09.2013 17:17

А dragend не всегда есть. Притащить могут ведь и извне.


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