Как начать событие mouseover при перетаскивании
Когда я перетаскиваю элемент поверх другого div
, на котором у меня есть событие mouseover, событие не запускается. Однако, это работает, если я навис над ним, не перетаскивая.
Есть ли способ обнаруживать события наведения элемента, если я перетаскиваю его поверх него?
Ответы
Ответ 1
Вот пример использования решения X-Y.
Рабочий пример на jsfiddle
Пример может быть улучшен, но является хорошей отправной точкой.
Просто отслеживает местоположение мыши и проверяет, находится ли он внутри каких-либо ограничивающих прямоугольников объектов сбрасываемых объектов. Следовательно, если событие mouseup срабатывает на любом из них, объект перетаскивается.
Вы также можете использовать координаты объекта, который вы перетаскиваете, для обнаружения, если он находится в раскрывающемся окне, но для этого требуется немного больше кода для поиска углов ограничивающих коробок и с помощью мыши.
В коде используется jQuery, но нет jQueryUI.
Я тестировал в Chrome, Firefox и Opera, но не в IE:)
Я также добавляю код сюда, если jsfiddle недоступен.
HTML
<p>Drag orange boxes to grey ones</p>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="draggable"></div>
<div class="draggable"></div>
<div class="draggable"></div>
CSS
.droppable {
width:50px;
height:50px;
float: left;
background-color: #DDD;
margin: 5px;
}
.draggable {
width:40px;
height:40px;
float: right;
background-color: #FC0;
margin: 5px;
cursor: pointer;
}
.dropped {
background-color: #FC0;
}
.somethingover {
background-color: #FCD;
}
JS
var dragged, mousex, mousey, coordinates = [];
var continueDragging = function(e) {
// Change the location of the draggable object
dragged.css({
"left": e.pageX - (dragged.width() / 2),
"top": e.pageY - (dragged.height() / 2)
});
// Check if we hit any boxes
for (var i in coordinates) {
if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
// Yes, the mouse is on a droppable area
// Lets change the background color
coordinates[i].dom.addClass("somethingover");
}
} else {
// Nope, we did not hit any objects yet
coordinates[i].dom.removeClass("somethingover");
}
}
// Keep the last positions of the mouse coord.s
mousex = e.pageX;
mousey = e.pageY;
}
var endDragging = function(e) {
// Remove document event listeners
$(document).unbind("mousemove", continueDragging);
$(document).unbind("mouseup", endDragging);
// Check if we hit any boxes
for (var i in coordinates) {
if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
// Yes, the mouse is on a droppable area
droptarget = coordinates[i].dom;
droptarget.removeClass("somethingover").addClass("dropped");
dragged.hide("fast", function() {
$(this).remove();
});
}
}
}
// Reset variables
mousex = 0;
mousey = 0;
dragged = null;
coordinates = [];
}
var startDragging = function(e) {
// Find coordinates of the droppable bounding boxes
$(".droppable").each(function() {
var lefttop = $(this).offset();
// and save them in a container for later access
coordinates.push({
dom: $(this),
left: lefttop.left,
top: lefttop.top,
right: lefttop.left + $(this).width(),
bottom: lefttop.top + $(this).height()
});
});
// When the mouse down event is received
if (e.type == "mousedown") {
dragged = $(this);
// Change the position of the draggable
dragged.css({
"left": e.pageX - (dragged.width() / 2),
"top": e.pageY - (dragged.height() / 2),
"position": "absolute"
});
// Bind the events for dragging and stopping
$(document).bind("mousemove", continueDragging);
$(document).bind("mouseup", endDragging);
}
}
// Start the dragging
$(".draggable").bind("mousedown", startDragging);
Ответ 2
Во всех представленных ответах я не вижу самого простого и очевидного (возможно, что-то не хватает в вопросе ОП). Но, если кто-то наткнется на это позже и нуждается в быстром и простом решении в чистом JS..
Вы делаете это, изменяя элемент className ondragover и меняя исходный класс ondragleave
my_element.ondragover = function(ev) {
ev.preventDefault();
this.className = 'myElem_dragover';
}
my_element.ondragleave = function(ev) {
ev.preventDefault();
this.className = 'myElem_orig';
}
CSS
.myElem_orig { //this is your initial class for element
top: 30px;
left: 20px;
.....
background-color: blue;
}
.myElem_orig:hover { //this is hover state, just changing bg color
background-color: red;
}
.myElem_dragover { //new class, needs all attributes from original class
top: 30px;
left: 20px;
........
background-color: red; //behaves the same like hover does
}
Редактирование:
забыл упомянуть, вам нужно вернуть оригинальный класс ondrop, иначе div останется в классе dragover
Ответ 3
Есть два основных способа сделать это:
- отслеживать
mousemove
и реагировать на координаты x/y
- имеет прозрачную цель с более высоким
z-index
, чем контейнер перетаскивания
Первый вариант действительно не использует событие mouseover вообще, но даст вам тот же чистый результат.
Имейте в виду, что некоторые браузеры (т.е.) не будут запускать mouseover
на прозрачных элементах, поэтому вы должны подделать его, установив фоновое изображение, которое является прозрачным или установит случайное изображение в качестве фона и позиционирует его вне элемента, например это:
element {
background: url(/path/to/img) no-repeat -10000px 0;
}
Ответ 4
jQuery-ui имеет droppable plugin для этого.
Плагин, используемый с перетаскиваемым элементом, вызывает события dropover
, которые могут быть связаны с любым действием, которое вам требуется.
См. ответ Mottie на этот вопрос (включая демонстрацию)
Ответ 5
Модифицируя код, отправленный emrahgunduz, в частности цикл for, вы также можете управлять вложенной областью droppable.
var dragged, mousex, mousey, coordinates = [];
var continueDragging = function(e) {
// Change the location of the draggable object
dragged.css({
"left": e.pageX - (dragged.width() / 2),
"top": e.pageY - (dragged.height() / 2)
});
// Check if we hit any boxes
for (var i = coordinates.length - 1; i >= 0; i--) {
if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
// Yes, the mouse is on a droppable area
// Lets change the background color
$('.droppable').removeClass("somethingover");
coordinates[i].dom.addClass("somethingover");
break;
}
} else {
// Nope, we did not hit any objects yet
coordinates[i].dom.removeClass("somethingover");
}
}
// Keep the last positions of the mouse coord.s
mousex = e.pageX;
mousey = e.pageY;
};
var endDragging = function(e) {
// Remove document event listeners
$(document).unbind("mousemove", continueDragging);
$(document).unbind("mouseup", endDragging);
// Check if we hit any boxes
for (var i = coordinates.length - 1; i >= 0; i--) {
if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
// Yes, the mouse is on a droppable area
droptarget = coordinates[i].dom;
droptarget.removeClass("somethingover").addClass("dropped");
dragged.hide("fast", function() {
$(this).remove();
});
}
}
}
// Reset variables
mousex = 0;
mousey = 0;
dragged = null;
coordinates = [];
};
var startDragging = function(e) {
// Find coordinates of the droppable bounding boxes
$(".droppable").each(function() {
var lefttop = $(this).offset();
// and save them in a container for later access
coordinates.push({
dom: $(this),
left: lefttop.left,
top: lefttop.top,
right: lefttop.left + $(this).width(),
bottom: lefttop.top + $(this).height()
});
};
// When the mouse down event is received
if (e.type == "mousedown") {
dragged = $(this);
// Change the position of the draggable
dragged.css({
"left": e.pageX - (dragged.width() / 2),
"top": e.pageY - (dragged.height() / 2),
"position": "absolute"
});
// Bind the events for dragging and stopping
$(document).bind("mousemove", continueDragging);
$(document).bind("mouseup", endDragging);
}
// Start the dragging
$(".draggable").bind("mousedown", startDragging);
Ответ 6
Нашел небольшую ошибку в примере jsfiddle.
Когда вы покидаете область падения вертикально, область выделения по-прежнему имеет класс "somethinghover".
http://jsfiddle.net/MAazv
Замените это
if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
// Yes, the mouse is on a droppable area
// Lets change the background color
coordinates[i].dom.addClass("somethingover");
}
} else {
// Nope, we did not hit any objects yet
coordinates[i].dom.removeClass("somethingover");
}