2012-02-20 13 views
11

In una pagina ho un iframe. In questo iframe c'è una raccolta di elementi che devo essere ordinabile. Tutti i Javascript sono in esecuzione nella pagina principale. Posso accedere all'elenco nel documento iframe e creare il ordinabili utilizzando contesto:Creazione di un'interfaccia utente jQuery ordinabile in un iframe

var ifrDoc = $('#iframe').contents(); 

$('.sortable', ifrDoc).sortable({ cursor: 'move' }); 

Tuttavia, quando si cerca di ordinare gli elementi in realtà, sto diventando un comportamento aberrante. Non appena viene cliccato un oggetto, la destinazione dello script cambia nel documento esterno. Se sposti il ​​mouse fuori dall'iframe, puoi spostare l'oggetto in giro e rilasciarlo facendo clic, ma non puoi interagire con esso all'interno dell'iframe.

Esempio: http://robertadamray.com/sortable-test.html

Quindi, c'è un modo per ottenere ciò che voglio fare - preferibilmente senza dover andare in giro l'hacking nel codice jQuery UI?

risposta

9

dinamicamente aggiungere jQuery e jQuery UI per l'iframe (demo):

$('iframe') 
    .load(function() { 
     var win = this.contentWindow, 
      doc = win.document, 
      body = doc.body, 
      jQueryLoaded = false, 
      jQuery; 

     function loadJQueryUI() { 
      body.removeChild(jQuery); 
      jQuery = null; 

      win.jQuery.ajax({ 
       url: 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js', 
       dataType: 'script', 
       cache: true, 
       success: function() { 
        win.jQuery('.sortable').sortable({ cursor: 'move' }); 
       } 
      }); 
     } 

     jQuery = doc.createElement('script'); 

     // based on https://gist.github.com/getify/603980 
     jQuery.onload = jQuery.onreadystatechange = function() { 
      if ((jQuery.readyState && jQuery.readyState !== 'complete' && jQuery.readyState !== 'loaded') || jQueryLoaded) { 
       return false; 
      } 
      jQuery.onload = jQuery.onreadystatechange = null; 
      jQueryLoaded = true; 
      loadJQueryUI(); 
     }; 

     jQuery.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'; 
     body.appendChild(jQuery); 
    }) 
    .prop('src', 'iframe-test.html'); 

Aggiornamento:Andrew Ingram is correct che jQuery UI detiene e utilizza i riferimenti a window e document per la pagina a cui jQuery UI era caricato. Caricando l'interfaccia utente jQuery/jQuery nell'iframe, ha i riferimenti corretti (per l'iframe, anziché il documento esterno) e funziona come previsto.


Update 2: Il frammento di codice originale aveva una questione sottile: l'ordine di esecuzione di tag di script dinamici non è garantita. L'ho aggiornato in modo che l'interfaccia utente di jQuery sia caricata dopo che jQuery è pronto.

Ho anche incorporato il codice getify a load LABjs dynamically, in modo che non sia necessario il polling.

+0

Grazie! Questo mi sembra una soluzione abbastanza pulita per me. Potresti aggiungere una spiegazione o un link a uno dei motivi per cui questo risolve il problema? – RARay

+0

@RARay Si prega di consultare il mio aggiornamento. –

+0

"Mi sembra una soluzione abbastanza pulita per me.". Veramente? Questo è un sondaggio diretto. È una soluzione orribile per la produzione. Lì * deve * essere un modo migliore di questo. – kamelkev

3

Non so perché il tuo codice non funziona. Sembra che dovrebbe essere.

Detto questo, qui ci sono due modi alternativi per implementare questa funzione:

  1. Se è possibile modificare l'iframe

    Spostare il JavaScript dal documento principale in iframe-test.html. Questo può essere il modo più pulito perché accoppia il JavaScript con gli elementi su cui è effettivamente in esecuzione.

    http://dl.dropbox.com/u/3287783/snippets/rarayiframe/sortable-test.html

  2. Se controlli solo il documento principale metodo di

    Utilizzare il .load jQuery() per recuperare il contenuto, invece di un iframe HTML.

    http://dl.dropbox.com/u/3287783/snippets/rarayiframe2/sortable-test.html

+0

Naturalmente, ma non è il mio caso d'uso. Controllo solo il documento principale. – RARay

+0

Buon punto. Ho aggiornato la mia risposta con un secondo modo per implementarlo, che potrebbe funzionare per voi, anche se non risponde alla domanda. –

+0

Questo è un punto davvero interessante, e qualcosa a cui non avevo pensato. Non so se funzionerà per il sistema più complesso che ha generato la mia domanda, ma darò sicuramente un'occhiata. Grazie! – RARay

5

aver giocato con loro un po 'javascript, Campaign Monitor risolve questo problema in pratica avere una versione personalizzata di jQuery UI. Hanno modificato ui.mouse e ui.sortable per sostituire i riferimenti al documento e la finestra con il codice che ottiene il documento e la finestra per l'elemento in questione. document diventa this.element[0].ownerDocument

e hanno una chiamata finestra della funzione jQuery personalizzato(), che permette loro di sostituire window con this.element.window() o simili.

+0

Ecco come lo stiamo gestendo ora. Ho praticamente scritto un plugin che estende le funzioni necessarie con il codice che funzionerà. Questo è hacky e, temo, specifico per la nostra situazione. Puoi fornire un link a una risorsa che consentirebbe ad altri con questo problema di risolverlo? – RARay

+0

Hey Andrew, puoi pubblicare il link per il file jQuery personalizzato? –

+0

Ehi Andrew, puoi pubblicare un link per questo, credo che vada male con questo approccio. o forse una guida. –

1

Invece di carico jQuery e jQueryUI all'interno del iFrame e valutare le interazioni jQueryUI sia in genitore e figlio - si può semplicemente bolla gli eventi del mouse al documento del genitore:

var ifrDoc = $('#iframe').contents(); 

$('.sortable', ifrDoc).on('mousemove mouseup', function (event) { 
    $(parent.document).trigger(event); 
}); 

In questo modo è possibile valutare tutti i vostri Javascript sul contesto del documento del genitore.

Problemi correlati