2012-08-17 6 views
8

tengo la siguiente aplicación de prueba: http://dev.driz.co.uk/ajax/Utilizando los botones de avance y retroceso con la API Historia

Puede hacer clic en los enlaces para cargar en otras páginas usando jQuery AJAX y hay dos tipos, globalTabs y localTabs que se cargan en contenido en diferentes paneles. NOTA: Que cada página es en realidad la página completa, pero solo tomamos el contenido que queremos utilizando el método jQuery find.

Para mejorar esto, estoy usando la API de historial de HTML5 (History.js para navegador cruzado).

Los títulos y las URL cambian bien y la pila del historial se está presionando para que funcione correctamente y, cuando uso los botones para avanzar y retroceder, la URL y el título se revierten.

Ahora la parte complicada es volver a cargar el contenido desde el estado anterior y más complicado cargar el tipo correcto, p. ajax global o local. Para lograr esto, creo que necesito pasar TANTO los datos y el tipo al estado de inserción para que pueda reutilizarse nuevamente para el estado emergente ...

¿Alguien puede ayudarme a orientarme en la dirección correcta? Tengo todas las primeras partes funcionando, solo un caso de pasar este tipo de ajax al estado push y luego reutilizarlo con el cambio de estado emergente.

Para mejorar esto que volver a escribir como sigue para indicar mi plan para pasar el tipo y datos:

NOTA: la Historia en mayúsculas se debe a que estoy usando History.js

var App = { 

    init: function() { 

     $(document).ready(function() { 

      $('.globalTabs li a').live('click', function (e) { 
       e.preventDefault(); 
       App.globalLoad($(this).attr('href')); 
      }); 

      $('.localTabs li a').live('click', function (e) { 
       e.preventDefault(); 
       App.localLoad($(this).attr('href')); 
      }); 

     }); 

     window.addEventListener('popstate', function(event) { 

      // Load correct content and call correct ajax request... 

     }); 

    }, 

    localLoad: function (url) { 

     $.ajax({ 
      url: url, 
      success: function (responseHtml) { 
       $('.localContent').html($(responseHtml).find('#localHtml')); 

       $data = { $(responseHtml).find('#localHtml'), 'local'}; 

       History.pushState($data, $(responseHtml).filter('title').text(), url); 
      } 
     }); 

    }, 

    globalLoad: function (url) { 

     $.ajax({ 
      url: url, 
      success: function (responseHtml) { 
       $('.mainContent').html($(responseHtml).find('#globalHtml')); 

       $data = { $(responseHtml).find('#globalHtml'), 'global'}; 

       History.pushState($data, $(responseHtml).filter('title').text(), url); 
      } 
     }); 

    } 

}; 

App.init(); 

ACTUALIZACIÓN: Para aclarar esta pregunta, son dos problemas con los que busco ayuda.

1.) Obtiene los botones de retroceso y avance que funcionan con las solicitudes ajax para que carguen los datos correctos en el área de contenido.

2.) Cargando el contenido en el área correcta al pasar también el contenido con el método pushState para que sepa si es una div global o una solicitud div local.

Respuesta

12

el objeto de datos es incorrecto, es por eso que obtienes ese problema. Un objeto se define por la clave, valora par:

object = {key:'value'}; 
$data = { text:$(responseHtml).find('#globalHtml'), type:'global', url:'the_url'}; 

no

$data = { $(responseHtml).find('#globalHtml'), 'global'}; 

Usando la definición del objeto que va a recuperar los datos utilizando la historia.getState()

History.Adapter.bind(window,'statechange',function(){ 
    var data = History.getState().data; 
    if(data){ 
     var html = data.text; 
     var type = data.type; 
     var type = data.url; 
     if(html && type){ 
      if(type == 'global'){ 
       // just change html 
       $('.mainContent').html(html); 
       // call the App object's function 
       if(url) App.localLoad(url); 
      }else{ 
       $('.localContent').html(html); 
      } 
     } 
    } 
}) 

NOTA:

  • cuando stateChange evento conseguir de despedidos si hay datos presentes que se disparará el Ajax llama
  • para simular la llamada AJAX sin hacer que acaba de cambiar el título también , creo que va a cubrirlo

EDITAR

  • el objeto de datos se toma realmente de History.getState(). Datos no History.getState()
  • añade otro parámetro al objeto almacenado para preservar url
  • usando la url y el tipo se puede hacer una llamada a la misma función que en el evento de clic

PROBLEMA:

Uncaught TypeError: Converting circular structure to JSON

Un objeto hace referencia a sí mismo en alguna parte; de ahí el mensaje "estructura circular". Eso significa que intentas codificar un objeto que tiene una referencia a sí mismo, esto generalmente ocurre con los elementos DOM. Que realmente debería pensar en cambiar

$data = { $(responseHtml).find('#localHtml'), 'local'}; 

a:

$data = { html:$(responseHtml).find('#localHtml').html(), type:'local'}; 

Aviso las claves para el objeto (html y tipo) y la llamada a la función html (.html()), de esta manera usted no envía innecesaria datos, solo el html. Si es necesario utilizar los datos HTML cuando se carga como un objeto DOM sólo tiene que utilizar esto:

var DOM_Element_loaded = $('<div>').html(html_loaded); 

ahora se puede utilizar para buscar DOM_Element_loaded/manipular datos en el HTML cargada sin necesidad de adjuntarlo al cuerpo.

+0

¿Y cómo lo disparo entonces? ¿No mencionas popstate? Como lo que tengo que hacer es cambiar el contenido y luego titular (efectivamente replicando EXACTAMENTE lo que hizo la llamada ajax) cuando un usuario usa los botones hacia atrás y hacia adelante, pero en lugar de ajax usará los datos del historial como punto sin volver a cargarlo en obviamente. – Cameron

+0

También me aparece el error: 'TypeError no detectado: conversión de la estructura circular a JSON' ¿Alguna idea de lo que está mal? http://dev.driz.co.uk/ajax/ – Cameron

+0

edité mi respuesta, sobre el error json, solo asegúrate de pasar objetos simples, sin funciones – cuzzea

0

NOTA: esto es realmente más de un comentario que una respuesta, pero se obtiene un mejor resaltado de sintaxis con respuestas de respuesta.

Esto es lo que hice cuando me encontré con este problema. Si mal no recuerdo, esto evitó el problema de solicitud doble.

window.onpopstate = function(event) { 
    if (event.state && event.state.initialHref) { 
    // make an AJAX request 
    // URL for AJAX request is event.state.initialHref 
    } 
} 

Cuando uso history.pushState()/history.replaceState(), estoy definiendo una propiedad initialHref en el objeto para la primera discusión. Estoy usando una URL absoluta para este valor, no uno relativo.

Cuestiones relacionadas