При запуске Firefox при запуске
Я пытаюсь отслеживать dragenter/leave для всего экрана, который до сих пор отлично работает в Chrome/Safari, благодаря плану draguover из qaru.site/info/33623/... как в:
$.fn.draghover = function(options) {
return this.each(function() {
var collection = $(),
self = $(this);
self.on('dragenter', function(e) {
if (collection.size() === 0) {
self.trigger('draghoverstart');
}
collection = collection.add(e.target);
});
self.on('dragleave drop', function(e) {
// timeout is needed because Firefox 3.6 fires the dragleave event on
// the previous element before firing dragenter on the next one
setTimeout( function() {
collection = collection.not(e.target);
if (collection.size() === 0) {
self.trigger('draghoverend');
}
}, 1);
});
});
};
function setText(text) {
$('p.target').text(text);
}
$(document).ready(function() {
$(window).draghover().on({
'draghoverstart': function() {
setText('enter');
},
'draghoverend': function() {
setText('leave');
}
});
});
Однако Firefox по-прежнему создает проблемы при перетаскивании текстовых элементов, вот скрипка, демонстрирующая: http://jsfiddle.net/tusRy/6/
Является ли это ошибкой Firefox или ее можно приручить JS? Или существует более надежный способ выполнения всего этого?
Спасибо!
UPDATE: обновить скрипт до http://jsfiddle.net/tusRy/6/, чтобы немного уменьшить беспорядок. Чтобы объяснить ожидаемое поведение скрипта:
- Перетащите файл в окно, а p.target должен быть "ENTER" цветным.
- Извлеките файл из окна, а p.target должен "ОСТАВИТЬ" цветной красный.
- Отбросьте файл в окне, а p.target должен "ОСТАВИТЬ" цветной красный.
В firefox событие LEAVE запускается при перетаскивании файла по тексту.
Ответы
Ответ 1
С версии 22.0 Firefox все еще это делает. Когда вы перетаскиваете текст node, он запускает два вида событий dragenter
и dragleave
: один, где целевой объект и связанный с ним таргетинг являются BOTH родительским элементом текста node, а другой, где цель является родительской элемент, а связанный с ним Target - это фактический текст node (даже не соответствующий элемент DOM).
Обходной путь - это просто проверить эти два вида событий в обработчиках dragenter
и dragleave
и игнорировать их:
try {
if(event.relatedTarget.nodeType == 3) return;
} catch(err) {}
if(event.target === event.relatedTarget) return;
Я использую блок try/catch для проверки nodeType, потому что из-за непредвиденных событий события (необъяснимо) из-за пределов документа (например, в других iframe) и попытки доступа к их узлуType вызывают ошибку разрешений.
Здесь реализация:
http://jsfiddle.net/9A7te/
Ответ 2
Я придумал какое-то решение, но для тестирования других браузеров, кроме Chrome и FF, но работающих до сих пор. Вот как выглядит setTimeout
:
setTimeout( function() {
var isChild = false;
// in order to get permission errors, use the try-catch
// to check if the relatedTarget is a child of the body
try {
isChild = $('body').find(e.relatedTarget).length ? true : isChild;
}
catch(err){} // do nothing
collection = collection.not(e.target);
if (collection.size() === 0 && !isChild) {
self.trigger('draghoverend');
}
}, 1);
Весь код здесь - http://jsfiddle.net/tusRy/13/.
Идея состоит в том, чтобы проверить, является ли связанный тэг дочерним по отношению к телу, и в этом случае мы все еще находимся в Браузерах, а событие draghoverend
не должно запускаться. Поскольку это может вызывать ошибки при перемещении из окон, я использовал метод try, чтобы избежать этого.
Ну, возможно, кто-то, у кого больше навыков в JS, может улучшить это:)
Ответ 3
1) Ваша dropzone должна иметь только один дочерний элемент, который может иметь все, что вам нужно. Что-то вроде
<div id="#dropzone">
<div><!--Your contents here--></div>
</div>
2) Используйте этот CSS:
#dropzone * { pointer-events: none; }
Вам может потребоваться включить :before
и :after
, так как *
не применимо к ним.
Этого должно быть достаточно, чтобы позволить работать в Firefox и Chrome. В вашем примере это должно быть достаточно, чтобы добавить:
body * { pointer-events: none; }
В конце CSS. Я сделал это здесь:
Другие примеры:
Ответ 4
Я нашел ответ в невыбранном ответе на этот вопрос SO, спрашивающий о стрельбах для включения дочерних элементов. У меня есть <div>
, который содержит много дочерних элементов. Полупрозрачное наложение <span>
становится видимым над <div>
, если на странице есть dragenter
. Как вы нашли, "dragover" не похож на mouseover
. Он запускает dragleave
всякий раз, когда вы наводите над дочерним элементом.
Решение? Dragout Он делает dragover
более похожим на mouseover
. Очень короткий.