Vous êtes sur la page 1sur 5

2017519 AJAXyelobjetowindow.

history

EduardoCasas ProgramadorenMadrid

AJAX y el objeto window.history


18denoviembrede2012
JavaScript

ElobjetohistorydeJavaScriptcontieneunalistadelasURLquehemosvisitadoenelmismotab,entrelascualespodemosdesplazarnos
yaccederaellas.AntesdelallegadadeHTML5esteobjetoresultabaintildecaraatrabajarconaplicacionesbasadasenAJAX,teniendo
que recurrir a otros mtodos menos naturales y limitados. Sin embargo, el desarrollo de su especificacin lo ha convertido en el
complementoidealparatrabajarconestatecnologa.

Hastaahora,elobjetohistory(asuvezpropiedaddelobjeto"window")disponadetresmtodosquenospermitaninteraccionarconelhistorial
denavegacindenuestronavegador:

back():cargalaURLdelestadoanterior

forward():cargalaURLdelestadosiguiente

go(nmero):cargalaURLdelestadoindicadoenelpar&aacutemetro

Yunanicapropiedad:

length:indicaelnmerodeelementosdisponiblesenelhistorialdenavegacin

Aunqueexistanalternativasgraciasaleventohaschange,estosmtodosresultabaninsuficentesalahoradetrabajarconpginascargadaspor
mediodeAJAX,puestoquenohabamaneradeasociarunestadoalhistorial,demaneraquealretroceder/avanzarpormediodelosbotonesde
nuestronavegadorseperdalainformacin.

Peroeldesarrollodelobjetonoshatraidodosnuevosmtodos(pushStateyreplaceState)quesolucionanesteproblema,ademsdeotranueva
propiedadstate:

El mtodo pushState aade un nuevo estado a nuestra lista mientras que replaceState sustituye el estado actual. Como veremos, ambos
mtodosfuncionandeformamuyparecidayrequirentresparmetros:

state:jsonquereprentaelestadodelnuevoelementoaadidoalhistorial
title:titulodelnuevoelemento(noconfundirconelcontenidodelelementotitledehtml).Esteparmetroannoessoportadoenlamayora
denavegadoresporloqueledaremosunvalornull.

url:URL(relativaoabsoluta)asociadaalnuevoelemento

Porotrolado,lanuevapropiedadstatedevuelveelvalordelestadoenelquenosencontramos,sintenerquedependerdeleventopopstate.

Aunquelaespecificacinaunestendesarrollolamayoradelosnavegadoresmodernosyasoportanestosnuevos mtodos, a excepcin de


InternetExplorer(<10)ySafari(parcialmente).Porcierto,enlapginadedesarrolladoresdeMozillamencionanotrostresmtodosms,quesin
embargonosonestndar,raznporlaquehedecididoignorarlos.

ParaestudiarlaimplementacindelasnuevascaractersticasdelobjetohistoryenunaaplicacinAJAXhecreadounapequeoejemplocuyo
repositorio he subido a github. Esta aplicacin est desarrollada en PHP y jQuery y consta de los siguientes elementos: el fichero de entrada
index.php,elcualcontienelaplantillayseencargadellamaralasvistascontenidosenlacarpetaviewslacarpetajsquecontienelalibrerade
jQueryyelficherofile.jsquecontienelasllamadasalosmtodosdelobjetohistoryunfichero.htaccessparaforzarelpatrnfrontcontroller.

Empezamosporesteltimo:

1 #.htaccess ?
2
3 RewriteEngineon
4
5 nRewriteCond%{REQUEST_FILENAME}!f
6 RewriteRule^(.*)$index.php[L]

Aqusimplementeforzamosunnicopuntodeentrada(elficheroindex.php)siemprequelaurlnocorrespondaaladeunficheroexistenteen
nuestraapp.

Elficheroindex.php:

1 //index.php
https://www.eduardocasas.com/es/blog/18112012/ajaxyelobjetowindowhistory 1/5
2017519 AJAXyelobjetowindow.history
1 //index.php ?
2
EduardoCasas ProgramadorenMadrid
3 <?php
4 $uri=explode('/',$_SERVER['REQUEST_URI']);
5 $view=end($uri);
6 if(empty($view)||$view==='index.php'){
7 header('location:index');
8 }
9 ?>
10 <!DOCTYPEhtml>
11 <htmllang="es">
12 <head>
13 <metacharset="UTF8">
14 <title>historyObjectExample</title>
15 &
16 lt;scriptsrc="js/jquery.js"></script>
17 <scriptsrc="js/file.js"></script>
18 </head>
19 <body>
20 <nav>
21 <?phpinclude'views/'.$view.'.html';?>
22 </nav>
23 <buttonid="previous">Previous</button>
24
25 <buttonid="forward">Forward</button>
26 <p>Numberofpagesinthehistorystack:<span><span></p>
27 </body>
28 </html>

ElscriptenPHPidentificaelslugdelaurlparaasociarlavistacorrespondiente.Pordefectoser"index".ElcdigoHTMLcontienelaplantilla,la
cualestcompuestadeunmendenavegacindefinidoporlavista,dosbotonesquenospermitenmovernosatravsdenuestrohistorialde
navegacin(anlogosalosbotonesatrsyadelantedenuestronavegador)yuntextoqueindicaelnmerodeelementosincluidoslalista.

Las vistas las he hecho lo ms sencillas posibles y nicamente contienen el men de navegacin, resaltando el elemento que se corresponde
conlapropiavista:

1 <!views/index.html> ?
2
3 <ul>
4 <li><strong>index</strong></li>
5 <li><ahref="page1">page1</a></li>
6 <
7 li><ahref="page2">page2</a></li>
8 </ul>
9
10 <!views/page1.html>
11
12 <ul>
13 <li><ahref="index">index</a></li>
14 <li><strong>page1</strong></li>
15 <li><ahref="page2">page2</a></li>
16 </ul>
17
18 <!views/page2.html>
19
20 <ul>
21 <li><ahref="index">index</a></li>
22 <li><ahref="page1">page1</a></li>
23 <li><strong>page2</strong>&
24 lt;/li>
25 </ul>

Yporltimo,elficherofile.jsqueeselquerealmentenosinteresa:

1 //js/file.js ?
2
3 $(document).ready
4 (
5 function()
6 {
7 $('#previous').click
8 (
9 function()
10 {
11 window.history.back();
12 }
13 );
14 $('#forward').click
15 (
16
17 function()
18 {
19 window.history.forward();
20 }
21 );
22 functionloadView(view)
23 {
24 $('nav').load('views/'+view+'.html');
https://www.eduardocasas.com/es/blog/18112012/ajaxyelobjetowindowhistory 2/5
2017519 AJAXyelobjetowindow.history
24 $('nav').load('views/'+view+'.html');
25 }
EduardoCasas ProgramadorenMadrid
26 functionprintHistoryLength()
27 {
28 $('span').text(window.history.length);
29 }
30 $('nav').on
31 (
32 'click',
33 'a',
34 function(event)
35 {
36 if(typeofwindow.history.pushState=='
37 function'){
38 event.preventDefault();
39 varview=$(this).attr('href');
40 window.history.pushState(view,null,view);
41 loadView(view);
42 printHistoryLength();
43 }
44 }
45 );
46 window.history.replaceState($('strong').text(),null,$('strong').text());
47 printHistoryLength();
48 r
49 window.onpopstate=function(event)
50 {
51 loadView(window.history.state);
52 };
53 }
54 );

Vamosaestudiarestedocumentoporpartes:

1 $('#previous').click ?
2 (
3 function()
4 {
5 window.history.back();
6 }
7 );
8 $('#forward').click
9 (
10 function()
11 {
12 window.history.forward();
13 }
14 );

Estas funciones asociadas al evento click para los botones #previous y #forward nos permiten simular el comportamiento de los botones del
navegador"Atrs"(mtodowindow.history.back)y"Adelante"(window.history.forward),respectivamente.

1 functionloadView(view) ?
2 {
3 $('nav').load('views/'+view+'.html');
4 }
5 functionprintHistoryLength()
6 {
7 $('span').text(window.history.length);
8 }

Paranorepetircdigo,declaramoslasfuncionesloadViewyprintHistoryLength.LaprimeracargavaAJAXlasvistascontenidasenlacarpeta
view mediante el mtodo load de jQuery . La segunda simplemente pinta el nmero de elementos almacenados en nuestro historial de
navegacin.

1 $('nav').on ?
2 (
3 'click',
4 'a',
5 function(event)
6 {
7 if(typeofwindow.history.pushState=='function'){
8 event.preventDefault();
9 varview
10 =$(this).attr('href');
11 window.history.pushState(view,null,view);
12 loadView(view);
13 printHistoryLength();
14 }
15 }
16 );

AqumesirvodelmtodoondejQuery(>=1.7)necesarioparapoderasociareleventoclickalosenlacesdelmendenavegacindelasvistas
cargadasvaAJAX.

https://www.eduardocasas.com/es/blog/18112012/ajaxyelobjetowindowhistory 3/5
2017519 AJAXyelobjetowindow.history
Lo primero que hacemos es comprobar si el navegador soporta el mtodo history.pushState. De ser as, invocamos dicho mtodo al que
EduardoCasas ProgramadorenMadrid
pasamosalosparmetros"state"y"url"lavariableurl,lacualcorrespondeconelslugalqueapuntaelenlaceencuestin.Comonovamosa
utilizar el parmetro "title", le damos un valor nulo. Una vez aadido el nuevo estado, podemos observar como por arte de magia la URL de
nuestronavegadorcambiaalvalordado.AcontinuacinllamamosalasfuncionesloadView,alaquelepasamoscomoparmetrodichoslug,y
printHistoryLength.

Encasodequeelnavegadornosoporteelmtodo,laaplicacinsecomportardemaneranaturalrecargandolapginaalabrirelnuevoenlace
.

1 window.history.replaceState($('strong').text(),null,$('strong').text()); ?
2 printHistoryLength();

Estas dos lneas son necesarias al cargar la pgina inicial. Para poder asignarle un estado (por defecto siempre es null) debemos invocar el
mtodohistory.replaceStatepasandoelvalordelslugdelapginaactualalosparmetros"state"y"url".Delocontrarionopodramosaccedera
ellapormediodelhistorialdenavegacin.AcontinuacinllamamosalafuncinprintHistoryLengthparapintarelnmerodesitiosalmacenados
en la lista. Notar que si en su lugar hubieramos utilizado el mtodo replaceState, al recargar la pgina el nmero de sitios almacenados
aumentaraen+1(algoqueenunprincipionodeberainteresarnos).

1 window.onpopstate=function(event) ?
2 {
3 loadView(window.history.state);
4 };

Porltimodefinimoslafuncinasociadaaleventopopstate,lacualselanzarcadavezquenaveguemosatravsdelhistorial.Hayqueteneren
cuenta que para poder visualizar el contenido de cada estado almacenado debemos llamar a la funcin loadView y pasarle el slug como
parmetro, de lo contrario podramos desplazarnos por el historial pero, logicamente, no se cargara la vista asociada. Es decir, lo que en
realidadhacemosessimularlasaccionesderetroceder/avanzarentrelaspginasalmacenadasennuestrohistorial.

Por cierto, sealar que tambin podramos haber utilizado la propiedad event.state en lugar de history.state, aunque de esta manera nos
ahorramosproblemasconGoogleChrome.Debemostenerencuentaqueestenavegadordisparaeleventoonpopstatecadavezquesecarga
una pgina, de manera que en nuestro caso, al cargar la pgina inicial la propiedad event.sate habra devuelto un valor nulo, saltando por lo
tantounerrorenlaaplicacin.

Dichotodoesto,debemossaberquesiguendndosealgunosproblemas.Elmsobvio,queenGoogleChromeelcontenidodenuestrapgina
inicial ser cargado dos veces (primero por PHP y luego por AJAX debido al evento popstate), lo que no es para nada deseable. Adems,
tambinexistenincompatibilidadesconalgunasversionesantiguasdeSafariyOpera.Paraevitarestosproblemasyfacilitarsuimplementacin
crossbrowserBenjaminLuptonhacreadolalibreriahistory.jsqueademsescompatibleconframeworkscomojQueryoMootools.

Comentarios

Identifcateparaescribiruncomentario.

Noexistencomentariosparaesteartculo.

License:CreativeCommonsAttribution3.0Unported
PoweredbySymfony3
ForkmeonGitHub

https://www.eduardocasas.com/es/blog/18112012/ajaxyelobjetowindowhistory 4/5
2017519 AJAXyelobjetowindow.history

https://www.eduardocasas.com/es/blog/18112012/ajaxyelobjetowindowhistory 5/5

Vous aimerez peut-être aussi