2012-05-17 21 views
6

Pracuję nad małym projektem, w którym chcę stworzyć stronę w stylu Ajax. Treść jest ładowana za pomocą jQuery's load(). Jak niektórzy z was wiedzą, wadą tego jest to, że adres URL nie zmienia się odpowiednio do wyświetlanej treści. Aby to zadziałało, możesz użyć pushState(). Ponieważ nie jest to obsługiwane w różnych przeglądarkach, użyłem wtyczki history.js.pushState() i popState(): manipulowanie historią przeglądarek

Działa to całkiem nieźle, ale problem polega na tym, że moje przyciski przewijania do przodu i do przodu nie działają tak, jak powinny i nie mam pojęcia, co robię źle. Adres URL zmienia się prawidłowo, a treść również, ale tytuł wcale się nie zmienia. Z tytułem mam na myśli to, co jest pokazane jako tytuł okna (lub zakładki) okna przeglądarki. To znaczy. <title> załadowanej strony LUB atrybut tytułu linku, który odnosi się do tej strony (są one takie same). Myślę, że ma to związek z tym, że nazywam tylko sekcją strony, której tytuł jest mi potrzebny (tj. Dodając #content do load()). Nadal chcę jednak tytuł tej strony. Oto przypadek testowy tego, co mam do tej pory. (Niedostępne więcej od 28 grudnia 2013 roku) jQuery pliku:

$(document).ready(function() { 
    var firstLink = $("ul > li:first-child > a"); 
    var menuLink = $("ul > li > a"); 
    var firstLoadedHtml = firstLink.attr("href") + " #content"; 

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast"); 
    firstLink.addClass("active"); 

    menuLink.click(function(e) { 
     history.pushState(null, null, this.href); 

     e.preventDefault(); 
     e.stopImmediatePropagation(); 

     var CurLink = $(this); 
     var newLoadedHtml = CurLink.attr("href") + " #content"; 
     var oldSection = $(".contentPage"); 

     $("#sectionContainer").hide().load(newLoadedHtml).fadeIn("fast"); 
     menuLink.removeClass("active"); 
     CurLink.addClass("active"); 
    }); 

    $(window).bind('popstate', function() { 
      var returnLocation = history.location || document.location; 

      $('#sectionContainer').load(returnLocation + "#content"); 
    }); 
}); 

Ja również zauważyć, że po powrocie do strony podstawowej (tj/sectionLoaderTest /) to gaśnie na chwilę i dopiero po jakimś czasie treść pierwszej strony jest ładowana. Czy istnieje sposób na zoptymalizowanie tego?

Dodatkowo używam jQuery, aby dodać aktywną klasę do klikniętego łącza. Jak mogę się upewnić, że zmieni się to odpowiednio do historii? Czy poprawne łącze jest podświetlone, gdy użytkownik nawiguje z powrotem?

Więc trzy pytania:

  1. Zdobądź tytuł pracy, kiedy idziesz do przodu i do tyłu
  2. Optymalizacja czasu ładowania mainpage
  3. Fix aktywnej klasy idąc do przodu i do tyłu

Witaj!

UWAGA 1: Chciałbym zbudować na history.js i własnego skryptu i jako takie utrzymanie wsparcia dla < HTML5 przeglądarek. Wolałbym to, ponieważ: 1. Wiem, że to musi zadziałać, jest coś, co idzie źle. 2. Oszczędziło mi to czas, gdybym mógł zobaczyć swoje rozwiązanie i wdrożyć je w scenariuszu, który już napisałem, zamiast opracowywać zupełnie nowy scenariusz.

UWAGA 2: Nagroda zostanie przyznana tylko osobie, która może odpowiedzieć na wszystkie moje pytania (3)!

+0

Nadal nie masz racji, zobacz przykład takich jak http://stackoverflow.com/questions/6622449/why-is-history-pushstate-not-supported-in-ie-are-there-some -inne-sposoby-do-ach/9470183 # 9470183 – devote

+0

Twój komentarz nie jest naprawdę pomocny. Nie muszę implementować history.js (jeszcze), staram się tylko zrozumieć, co na razie robi pushState. Chcę rozwiązać ten problem. –

+0

Mój komentarz wskazuje na twój błąd, jak rozmieścić metody przetwarzania zdarzenia.Metoda przechwytywania zdarzenia popstate, które wysłałeś nie jest poprawna, usuń go z metody działa po kliknięciu. – devote

Odpowiedz

11

Odpowiedź 1 - Get roboczym tytułem idąc do przodu i do tyłu

O ile zrozumiałem, chcesz zmienić tytuł dokumentu HTML z linkiem jest załadowany w div. Podczas ładowania pliku w div za pomocą jQuery .load wstawiasz tylko tekst odpowiedzi pełnej po wywołaniu zapytania ajax. Tak więc ze wszystkimi rzeczami, które nie powinny być w div jak tag title lub meta. Jednak tytuł bieżącego dokumentu (http://bramvanroy.be/sectionLoaderTest/index.html) jest zdefiniowany w title, który znajduje się wewnątrz znacznika head, a nie w znaczniku title wewnątrz elementu div, dlatego tytuł dokumentu się nie zmienia.

Jak mogę to naprawić?

Dobre pytanie, ponieważ element title wewnątrz elementu div jest nieważny, większość przeglądarek usunie go, więc nie można po prostu użyć tego:

document.title = $("#sectionContainer title").text(); 

ponieważ element title może nie istnieć.

Potrzebujemy więc bezpośredniej odpowiedzi z funkcji jQuery .load. Mogę go dodając argument wywołania zwrotnego do funkcji:

$("#sectionContainer") 
    .hide() 
    .load(newLoadedHtml, function(responseText) { 
     document.title = $(responseText).filter("title").text(); 
    }) 
    .fadeIn("fast"); 

Co może nie zrozumieć, dlaczego używam .filter a nie funkcji .find. Dzieje się tak dlatego, że jQuery przetwarza znaczniki html, head i body poza plikiem html, ale nie usuwa tam elementów potomnych.

Odpowiedź 2 - Optymalizacja czasu ładowania mainpage

Dokument trafia do ładowanego od góry do dołu.

Najpierw należy załadować css, JavaScript itd., A następnie główny dokument. Ponieważ jQuery zawsze czeka na dokument przed jego wykonaniem, nie byłoby złym pomysłem umieszczenie wszystkich elementów script tuż przed końcem ciała, aby wcześniej można było załadować kod HTML.

BtW Po prostu miałem ten problem po raz pierwszy, po tym jak wszystko zostało zbuforowane, a dokument ładował się bardzo szybko.

Odpowiedź 3 - Fix aktywnej klasy idąc do przodu i do tyłu

powiedziałbym pętla koryta atrybuty href rodzaje a elementów i porównać je z danymi z History.getState(). Powinno być łatwe.

Zrobiłeś jakieś błędy w kodzie - Twój stały kod:

Państwo załączony hash #content do wszystkich adresów URL .. to nie ma sensu, a zostanie ona usunięta przez jQuery ponownie: https://github.com/jquery/jquery/blob/master/src/ajax.js#L617 (Comes z linii: 158, 190, 337, 617 - rhash jest linia 6)

$(document).ready(function() { 
    var firstLink = $("ul > li:first-child > a"); 
    var menuLink = $("ul > li > a"); 
    var firstLoadedHtml = firstLink.attr("href"); 

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast"); 
    firstLink.addClass("active"); 

    menuLink.click(function(e) { 

     e.preventDefault(); 
     e.stopImmediatePropagation(); 

     var newLoadedHtml = $(this).attr("href"); 

     History.pushState(null, newLoadedHtml, newLoadedHtml); 

     $("#sectionContainer") 
      .hide() 
      .load(newLoadedHtml, function(responseText) { 
       document.title = $(responseText).filter("title").text(); 
      }) 
      .fadeIn("fast"); 
    }); 

    History.Adapter.bind(window, "statechange", function() { 
     menuLink.removeClass("active"); 
     $("a[href='" + History.getState().title + "']").addClass("active"); 
     $('#sectionContainer').load(document.location.href, function(responseText) { 
      document.title = $(responseText).filter("title").text(); 
     }); 
    }); 
}); 
+0

Może mi brakować czegoś (dość zajęty wieloma rzeczami w tym samym czasie), ale to nie działa. Tytuł dotyczący zmian pierwszego i ostatniego linku do tego, który jest zdefiniowany w polu "obejmuje". Również (i co ważniejsze) przyciski wstecz nie zmieniają już treści. Mam przeczucie, że to bardzo podstawowa rzecz, na którą patrzę. Sprawa testowa została zmieniona: http://bramvanroy.be/sectionLoaderTest/ –

+0

Pierwsza strona ('Home') ma dobry tytuł na dokumencie, wszystkie pozostałe strony mają tytuł" Untitled Document "jako tytuł. Niestety masz rację, nie zmienia już zawartości historii wstecz/dalej. Dzieje się tak, ponieważ 'document.location' jest obiektem i potrzebujesz łańcucha, zanim został on' document.location + "#content" 'Zwrócił ciąg znaków. Więc potrzebujesz 'document.location.href', spójrz na moją edycję. – noob

+1

W końcu zrobiłem nową edycję, która zadziała! ** TESTED ** Nawet poprawny link zawsze będzie miał klasę "aktywny"! – noob