2013-01-07 3 views
6

sto cercando di tenere traccia di un DragEnter/partire per l'intero schermo, che è finora lavorando bene in Chrome/Safari, per gentile concessione del plugin draghover da https://stackoverflow.com/a/10310815/698289 come in:Firefox cottura DragLeave durante il trascinamento sul testo

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

Tuttavia Firefox è ancora mi dà problemi quando mi trascino sopra gli elementi di testo, ecco un violino per dimostrare: http://jsfiddle.net/tusRy/6/

è questo un bug di Firefox o può questo essere addomesticato con JS? O c'è un metodo più robusto per eseguire tutto questo?

Grazie!

AGGIORNAMENTO: aggiornamento violino a http://jsfiddle.net/tusRy/6/ per ridurre un po 'la confusione. Per spiegare il comportamento previsto del violino:

  • Trascinare un file nella finestra e p.target deve essere "ENTER" colorato in giallo.
  • Trascinare un file fuori dalla finestra e p.target dovrebbe essere "LEAVE" colorato in rosso.
  • Rilasciare un file nella finestra e p.target dovrebbe essere "LEAVE" colorato in rosso.

In firefox, l'evento LEAVE viene attivato quando si trascina il file sul testo.

+0

Ho lavorato su questo per ora utilizzando un div overlay, come per http://jsfiddle.net/tusRy/7/ tuttavia non sono molto contento di questa soluzione THE, quindi lascerò questa domanda aperta finché non arriva un'idea migliore. – DanH

risposta

1

Mi è venuta una specie di soluzione, ancora da testare su altri browser diversi da Chrome e FF, ma lavorando fino ad ora. Questo è come il setTimeout appare ora:

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); 

L'intero codice qui - http://jsfiddle.net/tusRy/13/.

L'idea è di verificare se il tag correlato è figlio del corpo, nel qual caso siamo ancora nei browser e l'evento draghoverend non deve essere attivato. Poiché questo può generare errori quando si sposta fuori dalle finestre, ho usato un metodo di prova per evitarlo.

Be ', forse qualcuno con maggiori competenze su JS potrebbe migliorare questo :)

8

A partire dalla versione 22.0 Firefox sta ancora facendo questo. Quando si trascina su un nodo di testo, vengono attivati ​​due tipi di eventi dragenter e dragleave: uno in cui il target dell'evento e relatedTarget sono ENTRAMBI l'elemento padre del nodo di testo e un altro in cui il target è l'elemento padre e il relativoTarget è il testo effettivo nodo (nemmeno un vero elemento DOM).

La soluzione è solo quello di verificare la presenza di questi due tipi di eventi nelle vostre dragenter e dragleave gestori e ignorarli:

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

Io uso un blocco try/catch per verificare il nodeType perché a volte gli eventi del fuoco (inspiegabilmente) dall'esterno del documento (ad esempio in altri iframe) e tentando di accedere al proprio nodeType genera un errore di autorizzazione.

Ecco l'attuazione: http://jsfiddle.net/9A7te/

+1

Credo ci sia un problema con la gestione degli eventi di jQuery-2.1.1 per dragenter e dragleave: ho notato che invece di segnalare il nodo di testo incriminato come event.target su dragenter e dragleave, passa invece l'elemento padre del nodo di testo . Se stai ancora notando problemi, mi chiedo se andare nativo qui potrebbe aiutarti. – Gavin

+1

dal modo in cui questa risposta mi ha aiutato di più. E nel caso in cui la mia risposta sopra non fosse molto chiara: intendevo che all'interno di questo bug, jQuery stesso sta copiando in modo errato i target degli eventi sul suo oggetto Event personalizzato. Ho implementato un controllo nodeType basato su event.originalEvent.target e event.originalEvent.relatedTarget con buoni risultati – Gavin

+1

Funziona perfettamente! L'ho aggiunto al plugin stesso per evitare di dover riscriverlo nel gestore di eventi finale. Funziona perfettamente bene in Chrome e Firefox. Non ho provato altri browser per verificare eventuali bug sciocchi, ma questi sono gli unici due browser principali che devo supportare in genere. – Demonslay335

1

1) La vostra zona di lancio dovrebbe avere un solo elemento figlio, che potrebbe avere tutto il necessario.Qualcosa di simile

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

2) Usare questo CSS:

#dropzone * { pointer-events: none; } 

Potrebbe essere necessario includere il :before e :after dal momento che il * non si applicano a loro.

Questo dovrebbe essere sufficiente per consentire il rilascio di Firefox e Chrome. Nel tuo esempio, dovrebbe essere sufficiente aggiungere:

body * { pointer-events: none; } 

Alla fine del CSS. L'ho fatto qui:

Altri esempi:

1

ho trovato la risposta in una risposta non selezionata a questa domanda SO chiedendo di dragleave firing on child elements. Ho uno <div> che ha molti elementi figli. Una sovrapposizione semi-opaca <span> diventa visibile su ogni volta che c'è uno dragenter nella pagina. Come hai scoperto, "dragover" non è come mouseover. Attiva dragleave ogni volta che si passa con il mouse su un elemento figlio.

La soluzione? Dragout Rende lo dragover più simile a mouseover. Molto corto.