Formularios paso a paso de Rails - Casi convertidos a Ajax - Excepto por el botón Atrás del navegador

Actualmente estoy creando un proceso de registro paso a paso en mi sitio web.

Todo el proceso se ha creado con éxito con exactamente la misma configuración que se ve en los rieles fundidos aquí: http://railscasts.com/episodes/217-multistep-forms

¡Después de que todo funcionara, lo convertí todo a Ajax! Con los botones de envío o los formularios en cada paso, simplemente agregué:

remote:true

Luego, después de agregar el manejo de respuesta adecuado:

respond_to do|format|
  format.js { render 'new' }
  format.html { render 'new' }
end

En new.js.erb tengo esto:

$('#steps_content').fadeOut('fast', function(){
  $('#steps_content').html("<%= j render "#{@subscription.current_step}_step" %>", 
     $('#steps_content').fadeIn('fast', function(){})
  )
});

Aquí está new.html.erb:

<div id='steps_content' >
   <%= render "#{@subscription.current_step}_step" %>
</div>

¡Paso a paso ajaxificado!

De todos modos, dado que todo ha sido Ajaxificado, he estado tratando de obtener la Botón de retroceso del navegador para ir a mi paso anterior, además de tener un botón de retroceso en la página.

Llego allí agregando esto al comienzo de mi new.js.erb:

history.pushState(
   null, 
   '', 
   '#step=<%= j "#{@subscription.current_step}" %>'
);

Y esto hasta el final:

if (!$(window) || !$(window).data('events') || 
    !$(window).data('events')['popstate']) {

      $(window).bind('popstate', function() {
        $.getScript(location.href);
      });

}

¡Esto me ha estado causando una buena cantidad de problemas!

Con la configuración actual: se dispara la animación JQuery. Pensé, solo se desvanece hacia adentro, hacia afuera al mismo paso. Descubrí que la razón por la que sucede es porque todo el código de paso está en la acción de creación (publicación), no en la nueva acción (obtener), que es lo que activa el botón Atrás. Aunque incluso si pongo el código allí, el botón Atrás en el navegador no muestra el parámetro :back_button.

He estado investigando un poco para hacer que el botón Atrás funcione con Ajax, ¡pero todos los casos que encuentro no se aplican realmente! Supongo que esto se debe en parte a que toda mi configuración cambia el paso actual en el código del controlador. Incluso si pusiera el código de mi controlador en la nueva acción, el paso anterior no se cargaría porque no hay un parámetro :back_button.

Supongo que mi primera pregunta sería: ¿Hay alguna manera de agregar el parámetro :back_button SOLAMENTE cuando se presiona el botón Atrás del navegador?

Eso sería ideal, porque entonces todo mi código actual simplemente funcionaría. Sé que uno podría agregar ese parámetro uniéndose a la devolución de llamada de envío ajax de alguna manera, pero SOLO quiero que suceda cuando se presiona el botón Atrás del navegador. Pensé que tal vez podría unirme a history.back de alguna manera, pero eso no parece posible.

Mi pregunta principal: ¿Cómo puedo solucionar esto para que el navegador vuelva al paso correcto?

¿Puedo de alguna manera leer el parámetro de anclaje para establecer el paso actual?

¿Voy a tener que cambiar todo el método que uso para ir a cada paso?

¿Tal vez solo estoy fallando y haciendo algo mal?

¡Siento que estoy tan cerca!

Gracias de antemano compañeros codificadores, cualquier guía que me indique la dirección correcta o cualquier método alternativo que sea más bonito también sería útil. Además, no quiero usar complementos prefabricados para lograr esto.

Si necesitas más información solo házmelo saber.

¡Gracias!

EDIT:

Estoy abriendo esta pregunta para incluir posiblemente complementos/gemas/bibliotecas prefabricados decentes que tienen un respaldo sólido y son lo suficientemente compatibles como para entrar en un entorno de producción.

preguntado el 12 de junio de 12 a las 22:06

3 Respuestas

Uso un complemento de jQuery llamado jQuery BBQ, con buen éxito

Básicamente, le permite enviar una serie de datos (generalmente para registrar su estado ajax) cada vez que el usuario abandona la página actual. Si el usuario hace clic en el botón Atrás, aparece la matriz de estado y le permite escribir un controlador de eventos para restaurar su estado ajax, según la matriz.

De cualquier manera, vale la pena echarle un vistazo, ya que nunca me causó ningún problema de soporte desde que comencé a usarlo hace un año. http://benalman.com/code/projects/jquery-bbq/docs/files/jquery-ba-bbq-js.html

También se ha probado en navegadores modernos (incluido Safari). Es cierto que no sé qué cambios introduce para evitar la falta de soporte de eventos hashchange de Safari, pero funciona bien de todos modos.

Respondido 11 Jul 12, 02:07

Veo que Ryan Bates hizo una conversión de rieles usando este complemento antes de que se llamara jQuery BBQ y parece bastante útil. ¡Lo miraré y volveré a consultar! - Benjamin

También uso esto y encuentro que funciona bastante bien para lo que necesito: arcyqwerty

Puedes ver el evento llamado 'hashchange' con jquery

$(window).bind('hashchange',function(){ 
/*
    do stuff where you want when the back button is hit here
*/
});

Cualquier lógica que quieras poner allí debería funcionar. cuando presionas el botón Atrás. Debería poder rastrear los cambios en esa llamada o lo que sea.

He usado este truco al crear una página que es completamente dinámica y usar la etiqueta de anclaje para navegar entre páginas. funciona para adelante y para atrás. En su caso, es posible que desee asegurarse de no permitir el botón de avance en caso de reenvío o cualquier lógica de validación que tenga.

Respondido 10 Jul 12, 22:07

hashchange no es compatible con Safari: un requisito definitivo. Estaba realmente emocionado de que esto también lo haría. ¿Hay alguna solución para los navegadores que no admiten esto? Creo que voy a editar mi respuesta para solicitar también posibles soluciones prefabricadas. - Benjamin

Acabo de probar esto en Safari con la versión 5.1.6 (7534.56.5) y parece que se dispara. No estoy seguro de si es compatible 'oficialmente', pero parece funcionar para mí. una pregunta parecida stackoverflow.com/questions/4029433/… parece apuntar a que hashchange funciona en la última versión - Wilile

Extraño... déjame jugar un poco más con eso; especialmente porque estoy usando 5.1.7 - Benjamin

¿Cómo lo estás probando? Mi safari definitivamente dice que no funciona usando esto: if "onhashchange" en la alerta de ventana ('ESTO TOTALMENTE ES COMPATIBLE') else alert ('ESTO TOTALMENTE NO ES COMPATIBLE') Eso es script de café por cierto. - Benjamin

Acabo de volver a leer tu comentario: ¿estás diciendo que a pesar de que la declaración if me dice lo contrario, todavía funciona en Safari? - Benjamin

Puede hacerlo con el complemento Jquery Adress: http://www.asual.com/jquery/address/

Respondido 17 Jul 12, 16:07

¿Usas este complemento en absoluto? El Sr. Bates mencionó que la API no es tan intuitiva como JQuery BBQ. ¿Qué piensas al respecto @tekilatexee? - Benjamin

No sé JQuery BBQ. Jquery Adress es muy simple de usar. Puede guardar todas las páginas (con #blabla) en el historial del navegador y cuando el usuario regrese, puede volver a cargar sus datos con AJAX. - Sébastien - Vélhost

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.