Демонстрация API истории HTML5

Я читал об API истории HTML5 и до сих пор не нашел простой рабочей демонстрации, которая показывает механику с кодом.

Вот рабочий jsfiddle: 4 кнопки и 4 элемента div. Когда пользователь нажимает кнопка, она показывает соответствующую панель.

Что я хочу сделать, так это:

1) rewrite the URL so that when the user is on panel 4 the url ends with /Panel4
2) make the back button and forward button work with the history API.

Я знаю, что есть плагин history.js, но я хочу понять, как работает API в его простейшей форме.

Надеюсь, jsfiddle поможет тем, кто зайдет на эту страницу в поисках демо кода.

Спасибо.


person frenchie    schedule 13.05.2012    source источник
comment
Это может вам помочь: html5demos.com/history И это тоже: github.com/remy/html5demos/blob/   -  person Wilk    schedule 13.05.2012
comment
У нас уже есть тег для API истории HTML5, пожалуйста, не добавляйте еще один.   -  person Charles    schedule 14.05.2012


Ответы (2)


Хорошо, я сделал этот пример для вас. Начните с HTML-кода (index.html):

<!DOCTYPE html>
<html>
    <head>
        <title>Stackoverflow</title>
        <script type="text/javascript" src="sof.js"> </script>
    </head>
    <body onLoad="load();">
        <ul id="menu">
            <li><a href="/home">home</a></li>
            <li><a href="/about">about</a></li>
            <li><a href="/blog">blog</a></li>
            <li><a href="/photos">photos</a></li>
        </ul>
        <button onclick="back ();">Back</button>
        <button onclick="ff ();">Forward</button>
        <div>
            Action: <span id="action"></span><br/>
            Url: <span id="url"></span><br/>
            Description: <span id="description"></span>
        </div>
    </body>
</html>

А затем файл javascript (sof.js):

меню var, url, описание, действие, данные, historyState, действие;

function $ (id) {return document.getElementById (id);}

// Updates infos
function update (state) {
    action.innerHTML = act;
    url.innerHTML = state.url;
    description.innerHTML = state.description;
}

// Goes back
function back () {
    act = 'Back';
    history.back ();
}

// Goes forward
function ff () {
    act = 'Forward';
    history.forward ();
}

function load () {
    menu = $ ('menu');
    url = $ ('url');
    description = $ ('description');
    action = $ ('action');

    // State to save
    historyState = {
        home: {
            description: 'Homepage'
        } ,
        about: {
            description: 'Infos about this website'
        } ,
        blog: {
            description: 'My personal blog'
        } ,
        photos: {
            description: 'View my photos'
        }
    };

    // This is fired when history.back or history.forward is called
    window.addEventListener ('popstate', function (event) {
        var hs = history.state;

        if ((hs === null) || (hs === undefined)) hs = event.state;
        if ((hs === null) || (hs === undefined)) hs = window.event.state;

        if (hs !== null) update (hs);
    });

    menu.addEventListener ('click', function (event) {
        var el = event.target;
        // Prevents url reload
        event.preventDefault ();

        // Handles anchors only
        if (el.nodeName === 'A') {
            // Gets url of the page
            historyState[el.innerHTML].url = el.getAttribute ('href');
            // Creates a new history instance and it saves state on it
            history.pushState (historyState[el.innerHTML], null, el.href);
            act = 'Normal navigation';
            update (historyState[el.innerHTML]);
        }
    });

    // Handles first visit navigation
    var index = location.pathname.split ('/');
    index = index[index.length-1];
    if (index !== '') {
        historyState[index].url = location.pathname;
        history.pushState (historyState[index], null, location.pathname);
        act = 'First visit';
        update (historyState[index]);
    }
}

И .htaccess для прямого запроса:

RewriteEngine On

RewriteRule ^home$ ./index.html
RewriteRule ^about$ ./index.html
RewriteRule ^blog$ ./index.html
RewriteRule ^photos$ ./index.htm

Каждый раз, когда нажимается якорь, новый экземпляр истории помещается в стек истории, и вместе с ним сохраняется объект (называемый состоянием): локальный URL-адрес изменяется, но загрузка останавливается методом event.preventDefault(). Более того, некоторая информация (например, URL, описание и действие) обновляется.

Затем с помощью кнопок «назад» и «вперед» вы можете перемещаться по истории и использовать «history.state» (или event.state или window.event.state, это зависит от браузера) для получения текущего состояния.

И, в конце концов, если вы введете весь URL-адрес прямо в адресную строку, он будет работать так же, как и с указанным выше .htaccess ;)

Надеюсь, этот пример поможет вам ;)

Чао

Уилк

P.S. Подробнее:

  1. Управление историей браузера
  2. Объект истории
  3. История с инструкциями
person Wilk    schedule 13.05.2012
comment
Я думаю, что есть какая-то проблема с jsFiddle, потому что, когда я нажимаю на якорь, страница загружается, хотя если это не так... Я предлагаю вам попробовать свой локальный хост, создав файлы index.html и sof.js в Интернете корневой каталог сервера;) У меня работает: D - person Wilk; 13.05.2012

Хорошо, я создал, как мне кажется, ПРОСТЕЙШУЮ форму демонстрации API истории.

Он не может работать в jsfiddle, потому что ему нужно работать в своем собственном окне. Однако он будет работать, если вы скопируете и вставите код в блокнот, добавите ссылку на jquery, где указано, и сохраните его на рабочем столе в виде html-файла. Конечно, это не работает в IE, но мы все это знаем. Я добавил две версии: ту, которая работает без компонента перезаписи URL-адреса (она будет работать с вашего рабочего стола), и я также закомментировал версию, в которой вы можете манипулировать URL-адресом. Для последнего вам нужно запустить его с сервера, удаленного или локального.

Я изо всех сил пытался заставить его работать во всех браузерах, потому что Chrome, Safari и Firefox работают по-разному! Вот код:

    <html>
    <head>
    <style type="text/css">

    .Panel{
       width:200px;
       height:100px;
       background:red;
       display:none;
       color:white;
       padding:20px 20px;}

    .ChangeButton{
       margin:10px 10px;
       float:left;}   

    </style>

   // add reference to jquery.js file here 
   // <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>        

    <script type="text/javascript">

    var TheURL; // if you don't need URL rewrite, then we're always going to 
                // show the same URL. Remove this line if you want URL rewrite.

    var MyDivs = { // this object stores the name and the URL of each possible state
       ShowPanel1: {panelID:'Panel1', DisplayURL:'/panel1'},
       ShowPanel2: {panelID:'Panel2', DisplayURL:'/panel2'},
       ShowPanel3: {panelID:'Panel3', DisplayURL:'/panel3'},
       ShowPanel4: {panelID:'Panel4', DisplayURL:'/panel4'},
    };

    $(document).ready(function () {

    TheURL = document.URL; // You can remove this line if you're doing
                           // URL rewrite

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

       //cross-browser nightmare here!!!!!
       var HistoryState = history.state;

       if (HistoryState === null || HistoryState === undefined) {
            HistoryState = event.state; }

       if (HistoryState === null || HistoryState === undefined) {
            HistoryState = window.event.state; }

       SwitchPanel(HistoryState);
    });

    $('.ChangeButton').click(function () {
           DoChange(parseInt($(this).attr('id').charAt(6), 10)); });

    DoChange(1);

    });

    function DoChange(ButtonID) {

       switch (ButtonID) {

       // here's the 2-version option: 
       // toggle the commented and uncommented history.pushState
       // lines to see the change to the URL in action
       case 1:
           SwitchPanel(MyDivs.ShowPanel1.panelID);
           history.pushState(MyDivs.ShowPanel1.panelID, "", TheURL);
           // history.pushState(MyDivs.ShowPanel1.panelID, "", MyDivs.ShowPanel1.DisplayURL);
           break;
       case 2:
           SwitchPanel(MyDivs.ShowPanel2.panelID);
           history.pushState(MyDivs.ShowPanel2.panelID, "", TheURL);
           // history.pushState(MyDivs.ShowPanel2.panelID, "", MyDivs.ShowPanel2.DisplayURL);
           break;
       case 3:
           SwitchPanel(MyDivs.ShowPanel3.panelID);
           history.pushState(MyDivs.ShowPanel3.panelID, "", TheURL);
           // history.pushState(MyDivs.ShowPanel3.panelID, "", MyDivs.ShowPanel3.DisplayURL);
           break;
       case 4:
           SwitchPanel(MyDivs.ShowPanel4.panelID);
           history.pushState(MyDivs.ShowPanel4.panelID, "", TheURL);
           // history.pushState(MyDivs.ShowPanel4.panelID, "", MyDivs.ShowPanel4.DisplayURL);
           break;
       }
    }

    function SwitchPanel(PanelID) {

       if (PanelID === null) {return false;}

       $('.Panel').hide();
       $('#' + PanelID).fadeIn('medium');
    }

    </script>
    </head>

    <body>

    <input type="button" id="Button1" class="ChangeButton" value="panel 1" />
    <input type="button" id="Button2" class="ChangeButton" value="panel 2" />
    <input type="button" id="Button3" class="ChangeButton" value="panel 3" />
    <input type="button" id="Button4" class="ChangeButton" value="panel 4" />

    <div id="PanelContainer" style="clear:both;">

       <div class="Panel" id="Panel1">panel 1</div>
       <div class="Panel" id="Panel2">panel 2</div>
       <div class="Panel" id="Panel3">panel 3</div>
       <div class="Panel" id="Panel4">panel 4</div>

    </div>

    </body>
    </html>

Проголосуйте, если это работает для вас.

Наслаждайтесь!

person Community    schedule 16.05.2012
comment
Интересно, как вы можете использовать событие popstate, чтобы заставить его работать в любом браузере;) Однако в вашем примере нет навигации по URL-адресу, как вы просили. - person Wilk; 17.05.2012
comment
@Wilk: хорошо, я добавил эту функцию обновления URL; Я решил не использовать перезапись URL для своего приложения. И, конечно, это не работает в IE, но я не искал это, просто что-то простое, что я могу разместить на своем сайте. Для IE я просто говорю пользователям, что ответный удар приведет к их выходу из системы с сообщением об отмене или продолжении. Мое приложение будет запущено в октябре, и к тому времени должен быть запущен IE10. - person frenchie; 17.05.2012
comment
огромное спасибо! Я только что отредактировал свое решение по вашему предложению: D Теперь оно хорошо работает и в Chrome;) - person Wilk; 24.05.2012