Реализация изменения URL в Lifehacker с помощью Ajax - PullRequest
4 голосов
/ 20 ноября 2011

Я вижу, что Lifehacker может изменять URL при использовании AJAX для обновления части страницы.Я предполагаю, что это может быть реализовано с помощью плагина HTML5 или history.js, но я предполагаю, что lifehacker не использует ни того, ни другого.

Кто-нибудь знает, как они это делают?Я новичок в AJAX и только что смог обновить часть страницы с помощью Ajax.


Спасибо @Robin Anderson за подробный пошаговый алгоритм.Я попробовал, и он работает нормально.Однако прежде чем я смогу протестировать его на производстве, я бы хотел запустить у вас код, который у меня есть.Я все сделал правильно?

<script type="text/javascript">  
var httpRequest;  
var globalurl;
    function makeRequest(url) {  
    globalurl = url;
    /* my custom script that retrieves original page without formatting (just data, no templates) */
    finalurl = '/content.php?fname=' + url ;

    if(window.XMLHttpRequest){httpRequest=new XMLHttpRequest}else if(window.ActiveXObject){try{httpRequest=new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{httpRequest=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}  

    /* if no html5 support, just load the page without ajax*/
    if (!(httpRequest && window.history && window.history.pushState)) {     
            document.href = url;
            return false;  
    } 

    httpRequest.onreadystatechange = alertContents;  
    alert(finalurl);    /* to make sure, content is being retrieved from ajax */
    httpRequest.open('GET', finalurl);  
    httpRequest.send();  
    } 

    /* for support to back button and forward button in browser */
    window.onpopstate = function(event) {
            if (event.state !== null) {
                    document.getElementById("ajright").innerHTML = event.state.data;
            } else {
                    document.location.href = globalurl;
                    return false;
            };
    };    

    /* display content in div */
    function alertContents() {  
            if (httpRequest.readyState === 4) {  
            if (httpRequest.status === 200) {  
                    var stateObj = { data: httpRequest.responseText};
                    history.pushState(stateObj, "", globalurl);     
                    document.getElementById("ajright").innerHTML = httpRequest.responseText;
            } else {  
                    alert('There was a problem with the request.');  
            }  
            }  
    }  
    </script> 

PS: я не знаю, как вставить код в комментарий, поэтому я добавил его сюда.

Ответы [ 2 ]

8 голосов
/ 20 ноября 2011

Не требуется иметь разметку HTML5, чтобы использовать API истории в браузере, даже если это функция HTML5.

Одна очень быстрая и простая реализация загрузки всех переходов страниц с помощью AJAX:

  1. Подключить все ссылки, кроме rel = "external", к функции "ChangePage"
  2. Когда запускается ChangePage, проверьте, поддерживается ли API истории в браузере.
  3. Если API истории не поддерживается, добавьте хештег или сделайте загрузку обычной полной страницы в качестве запасного варианта.
  4. Если поддерживается API истории:
    1. Предотвращение нормального поведения ссылки.
    2. Вставьте новый URL в историю браузера.
    3. Сделайте AJAX-запрос на новый URL и извлеките его содержимое.
    4. Найдите ваш div содержимого (или аналогичный элемент) в ответе, извлеките из него HTML-код и замените HTML-код соответствующего элемента на текущей странице новым.

Это будет легко реализовать, легко управлять кэшами и хорошо работать с роботами Google, недостатком является то, что это не так уж «оптимизировано», и это потребует некоторых дополнительных затрат (по сравнению с более сложным решением) когда вы меняете страницы.

Также будет иметь обратную совместимость, поэтому старые браузеры или «не посетители JavaScript» просто получат обычную загрузку страницы.

Интересные ссылки по теме

Edit:

Еще одна вещь, о которой стоит упомянуть, это то, что вы не должны использовать это вместе с приложениями ASP .Net Web Forms, вероятно, испортит обработку обратной передачи.

Добавление кода:

Я собрал небольшую демонстрацию этой функции, которую вы можете найти здесь .

Он просто использует HTML, Javascript (jQuery) и чуть-чуть CSS, я бы порекомендовал вам проверить его перед использованием. Но я проверил это в Chrome, и, похоже, он работает прилично.

Некоторые тесты, которые я бы порекомендовал:

  • Тест в хороших браузерах Chrome и Firefox.
  • Протестируйте его в устаревшем браузере, таком как IE7
  • Протестируйте его без Javascript (просто установите Noscript или аналог Chrome / Firefox)

Вот javascript, который я использовал для достижения этого, вы можете найти полный исходный код в демонстрационной версии выше.

/*
    The arguments are:          
        url: The url to pull new content from
        doPushState: If a new state should be pushed to the browser, true on links and false on normal state changes such as forward and back.
*/
function changePage(url, doPushState, defaultEvent)
{
    if (!history.pushState) { //Compatability check
        return true; //pushState isn't supported, fallback to normal page load
    }

    if (defaultEvent != null) { 
        defaultEvent.preventDefault(); //Someone passed in a default event, stop it from executing
    }

    if (doPushState) {  //If we are supposed to push the state or not
        var stateObj = { type: "custom" }; 
        history.pushState(stateObj, "Title", url); //Push the new state to the browser
    }               

    //Make a GET request to the url which was passed in
    $.get(url, function(response) {             
        var newContent = $(response).find(".content");      //Find the content section of the response
        var contentWrapper = $("#content-wrapper");         //Find the content-wrapper where we are supposed to change the content.
        var oldContent = contentWrapper.find(".content");   //Find the old content which we should replace.

        oldContent.fadeOut(300, function() { //Make a pretty fade out of the old content
            oldContent.remove(); //Remove it once it is done
            contentWrapper.append(newContent.hide()); //Add our new content, hidden
            newContent.fadeIn(300); //Fade it in!
        });

    });
}


//We hook up our events in here
$(function() {
    $(".generated").html(new Date().getTime()); //This is just to present that it's actually working.

    //Bind all links to use our changePage function except rel="external"
    $("a[rel!='external']").live("click", function (e) { 
        changePage($(this).attr("href"), true, e);
    });

    //Bind "popstate", it is the browsers back and forward
    window.onpopstate = function (e) { 
        if (e.state != null) {
            changePage(document.location, false, null); 
        }
    }
}); 
0 голосов
/ 20 ноября 2011

DOCTYPE не влияет на то, какие функции может использовать страница.

Возможно, они напрямую используют HTML5 History API.

...