2012-02-20 5 views
11

En una página, tengo un iframe. En este iframe hay una colección de elementos que necesito para ordenar. Todo el Javascript se está ejecutando en la página principal. Puedo tener acceso a la lista en el documento marco flotante y crear el contexto se puede ordenar mediante el uso de:Creación de una interfaz de usuario jQuery ordenable en un iframe

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

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

Sin embargo, cuando se trata de ordenar los elementos de hecho, estoy recibiendo un comportamiento aberrante. Tan pronto como se hace clic en un elemento, el objetivo del script cambia al documento externo. Si mueve el mouse fuera del iframe, puede mover el elemento y soltarlo haciendo clic, pero no puede interactuar con él dentro del iframe.

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

Por lo tanto, hay una manera de lograr lo que quiero hacer - de preferencia sin tener que pasar alrededor de la piratería en el código de jQuery UI?

Respuesta

9

Agregar dinámicamente jQuery y jQuery UI para el 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'); 

Actualización:Andrew Ingram is correct que jQuery UI posee y utiliza referencias a window y document de la página a la que fue jQuery UI cargado. Al cargar jQuery/jQuery UI en el iframe, tiene las referencias correctas (para el iframe, en lugar del documento externo) y funciona como se esperaba.


Actualización 2: El fragmento de código original tenía un tema sutil: el orden de ejecución de las etiquetas de script dinámicas no está garantizada. Lo he actualizado para que jQuery UI se cargue después de que jQuery esté listo.

También incorporé el código de getify a load LABjs dynamically, por lo que no es necesario un sondeo.

+0

Gracias! Esto parece una solución bastante limpia para mí. ¿Podría agregar una explicación, o un enlace a uno, de por qué esto soluciona el problema? – RARay

+0

@RARay Por favor, mira mi actualización. –

+0

"Esto parece una solución bastante limpia para mí". De Verdad? Esto es una votación directa. Es una solución horrible para la producción. * Hay * para ser una mejor manera que esto. – kamelkev

3

No sé por qué su código no funciona. Parece que debería ser.

Dicho esto, aquí hay dos formas alternativas para implementar esta característica:

  1. Si se puede modificar el marco flotante

    Mueva el JavaScript del documento de nivel superior en iframe-test.html. Esta puede ser la forma más limpia porque acopla el JavaScript con los elementos que realmente está ejecutando.

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

  2. Si sólo controlar el documento principal método de

    Uso del .load jQuery() para buscar el contenido en lugar de un iframe HTML.

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

+0

Por supuesto, pero ese no es mi caso de uso. Yo controlo solo el documento principal. – RARay

+0

Buen punto. He actualizado mi respuesta con una segunda forma de implementar esto, que puede funcionar para usted, incluso si no responde la pregunta. –

+0

Ese es un punto realmente interesante, y algo en lo que no había pensado. No sé si funcionará para el sistema más complejo que generó mi pregunta, pero definitivamente voy a echarle un vistazo. ¡Gracias! – RARay

5

Después de haber jugado con su javascript un poco, Campaña monitor resuelve esto teniendo básicamente una versión personalizada de jQuery UI. Han modificado ui.mouse y ui.sortable para reemplazar las referencias a documentos y ventanas con código que obtiene el documento y la ventana para el elemento en cuestión. document convierte this.element[0].ownerDocument

y tienen una función jQuery personalizada llamada ventana() que les permite reemplazar window con this.element.window() o similar.

+0

Así es como lo estamos manejando ahora. Básicamente, he escrito un complemento que amplía las funciones necesarias con un código que funcionará. Esto es hacky y, me temo, específico de nuestra situación. ¿Puede proporcionar un enlace a un recurso que permita que otros con este problema lo resuelvan? – RARay

+0

Hola Andrew, ¿puedes publicar el enlace para el archivo jQuery personalizado? –

+0

Hola Andrew, puedes publicar un enlace para este, creo que iré con este enfoque. o una guía tal vez. –

1

En lugar de jQuery carga y jQueryUI dentro del marco flotante y la evaluación de las interacciones jQueryUI tanto en padres e hijos - simplemente puede burbuja los eventos de ratón para documentar de los padres:

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

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

esta manera se puede evaluar toda su Javascript en el contexto del documento del padre.

Cuestiones relacionadas