2013-01-07 14 views
6

Ja próbuje śledzić dragenter/pozostawić na całym ekranie, który do tej pory działa bez zarzutu w Chrome/Safari, uprzejmości wtyczki draghover od https://stackoverflow.com/a/10310815/698289 jak w:Firefox wypalania dragleave podczas przeciągania na tekst

$.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'); 
     } 
    }); 
}); 

jednak Firefox jest wciąż daje mi problemów, gdy przeciągam nad adnotacji, oto skrzypce wykazać: http://jsfiddle.net/tusRy/6/

jest to błąd Firefox lub może to być oswojone z JS? Czy istnieje bardziej niezawodna metoda wykonania tego wszystkiego?

Dzięki!

AKTUALIZACJA: Zaktualizowane skrzypce do http://jsfiddle.net/tusRy/6/ w celu zmniejszenia bałaganu. Aby wyjaśnić oczekiwane zachowanie skrzypiec:

  • Przeciągnij plik do okna, a p.target powinno być "ENTER" w kolorze żółtym.
  • Przeciągnij plik poza okno, a p.target powinno być "LEAVE" w kolorze czerwonym.
  • Upuść plik w oknie, a p.target powinien mieć wartość "LEAVE" w kolorze czerwonym.

W firefox zdarzenie LEAVE jest wyzwalane po przeciągnięciu pliku przez tekst.

+0

Pracowałem nad tym teraz, używając nakładki div, jak na http://jsfiddle.net/tusRy/7/ jednak nie jestem zadowolony z tego, że to jest rozwiązanie, więc zostawię to pytanie otwarte dopóki nie pojawi się lepszy pomysł. – DanH

Odpowiedz

1

Wpadłem na pewnego rodzaju rozwiązanie, ale do przetestowania w innych przeglądarkach innych niż Chrome i FF, ale działa do tej pory. Jest to, jak wygląda teraz 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); 

cały kod tutaj - http://jsfiddle.net/tusRy/13/.

Chodzi o to, aby sprawdzić, czy powiązany tag jest dzieckiem ciała, w którym to przypadku nadal znajdujemy się w przeglądarce, a zdarzenie draghoverend nie powinno być wyzwalane. Ponieważ może to powodować błędy przy wyjściu z okna, użyłem metody try, aby tego uniknąć.

No, może ktoś z bardziej umiejętności na JS mogłoby poprawić ten :)

8

Począwszy od wersji 22.0 Firefox jest jeszcze to robi. Po przeciągnięciu przez węzeł tekstowy uruchamia dwa rodzaje zdarzeń: dragenter i dragleave: jeden, w którym cel zdarzenia i relatedTarget są ZARÓWNYM elementem nadrzędnym węzła tekstowego, a drugi, w którym elementem docelowym jest element nadrzędny, a pokrewny element Target jest tekstem rzeczywistym węzeł (nawet niepoprawny element DOM).

Rozwiązaniem jest tylko w celu sprawdzenia tych dwóch rodzajów zdarzeń w swoim dragenter i dragleave teleskopowe i ich ignorować:

try { 
    if(event.relatedTarget.nodeType == 3) return; 
} catch(err) {} 
if(event.target === event.relatedTarget) return; 

Używam bloku try/catch, aby sprawdzić NODETYPE bo czasami ogień zdarzenia (niewytłumaczalny) spoza dokumentu (np. w innych elementach iframe) i próba dostępu do ich nodeType powoduje błąd uprawnień.

Oto realizacja: http://jsfiddle.net/9A7te/

+1

Wierzę, że istnieje problem z obsługą zdarzeń jQuery-2.1.1 dla dragenter i dragleave: Zauważyłem, że zamiast zgłaszania obraźliwego węzła tekstowego jako event.target na dragenter i dragleave, zamiast tego przechodzi on przez element macierzysty węzła tekstowego . Jeśli nadal dostrzegasz problemy, zastanawiam się, czy pomoc dla Ciebie może być dostępna tutaj. – Gavin

+1

przy okazji ta odpowiedź pomogła mi najbardziej. I na wypadek, gdyby moja odpowiedź powyżej była niezbyt jasna: chodziło mi o to, że w tym błędzie jQuery niesłusznie kopiuje cele zdarzeń do swojego niestandardowego obiektu Event. Zaimplementowałem sprawdzanie nodeType na podstawie zdarzeń event.originalEvent.target i event.originalEvent.relatedTarget z dobrymi wynikami. – Gavin

+1

Działa doskonale! Dodałem go do samej wtyczki, aby uniknąć konieczności ponownego zapisu w module obsługi zdarzeń końcowych. Działa doskonale w Chrome i Firefox. Nie testowałem w innych przeglądarkach, aby zweryfikować jakiekolwiek głupkowate błędy, ale są to jedyne dwie główne przeglądarki, które muszę obsługiwać. – Demonslay335

1

1) Twój zrzutowisko powinien mieć tylko jeden element podrzędny, który może mieć wszystko, czego potrzebujesz.Coś jak

<div id="#dropzone"> 
    <div><!--Your contents here--></div> 
</div> 

2) Za pomocą tej CSS:

#dropzone * { pointer-events: none; } 

może zaistnieć potrzeba obejmują :before i :after od * nie stosują się do nich.

To powinno wystarczyć, aby drop działał w przeglądarkach Firefox i Chrome. W twoim przykładzie powinno wystarczyć dodanie:

body * { pointer-events: none; } 

Pod koniec CSS. Zrobiłem go tutaj:

Inne przykłady:

1

Znalazłem odpowiedź w nieaktywnym odpowiedź do tego pytania SO z pytaniem o dragleave firing on child elements. Mam <div>, który ma wiele elementów podrzędnych. Półprzezroczysta nakładka <span> staje się widoczna nad <div>, gdy na stronie znajduje się dragenter. Jak odkryłeś, "dragover" nie jest jak mouseover. Wywołuje on dragleave po najechaniu myszą na element potomny.

Rozwiązanie? Dragout To sprawia, że ​​dragover działa bardziej jak mouseover. Bardzo krótki.

Powiązane problemy