CodeIgniter + jQuery (ajax) + HTML5 pushstate: Как сделать чистую навигацию с реальными URL-адресами? - PullRequest
8 голосов
/ 10 июля 2011

Я сейчас пытаюсь создать новый сайт, ничего особенного, красивого и маленького, но я застрял в самом начале.Мои проблемы - чистые URL и навигация по страницам.Я хочу сделать это "правильным образом".

Что бы я хотел иметь:

  • Я использую CodeIgniter для получения чистых URL-адресов, таких как "www.example.com/hello/world"
  • jQuery помогает мне использовать ajax, поэтому я могу .load () дополнительный контент
  • Теперь я хочу использовать такие функции HTML5, как pushstateчтобы избавиться от # в URL-адресе

Можно иметь возможность перемещаться назад и вперед без обновления страницы, но страница все равно будет отображать правильное содержимое в соответствии с текущим URL-адресом.

Также должна быть возможность перезагрузить страницу без получения ошибки 404.Сайт должен существовать благодаря CodeIgniter. (есть контроллер и представление)

Например:
Очень простой веб-сайт.Две ссылки, называемые «foo» и «bar», и поле emtpy div под ними.Основным URL-адресом является example.com
Когда вы нажимаете «foo», URL-адрес меняется на «example.com/foo» без перезагрузки, и блок div получает новое содержимое с помощью jQuery .load ().То же самое относится и к другой ссылке, но, разумеется, к другому содержанию и URL.
После нажатия «foo», а затем «bar» кнопка «Назад» вернет меня на «example.com/foo» с соответствующим содержанием.Если я загружу эту ссылку напрямую или обновлю страницу, она будет выглядеть так же.Нет ошибки 404 или что-то в этом роде.

Просто подумайте об этой странице и скажите, как вы это сделаете.Мне бы очень хотелось иметь такую ​​навигацию, поэтому я попробовал несколько вещей.


Пока ...
Я знаю, как использовать CodeIgniter для получения URL-адресовкак это.Я знаю, как использовать jQuery для загрузки дополнительного контента, и хотя я не совсем понимаю, что такое hstml5 pushstate, я по крайней мере заставил его работать как-то.Но я не могу заставить его работать все вместе.Мой код сейчас беспорядок, вот почему я не хочу публиковать его здесь.Я посмотрел на разные учебники и скопировал немного кода вместе.Думаю, было бы лучше загрузить папку CI.

Некоторые учебники, на которые я смотрел:

(макс. Число достигнутых ссылок: /)

Я думаю, что моя главная проблема в том, что каждый пытается сделать его совместимым со всеми браузерами и различнымиверсии, добавляет плагины scripts / jQuery и еще много чего, и я запутался в дополнительном коде.Между моими скрипт-тегами больше кода, чем в реальном HTML-контенте.Может ли кто-нибудь опубликовать самый простой способ использования HTML5 для моей страницы примера?


Моя неудачная попытка:
На моей тестовой странице, когда я возвращаюсь, URLизменения, но в окне div все равно будет отображаться тот же контент, а не старый.Я также не знаю, как изменить URL в скрипте в соответствии с атрибутом href по ссылке.Есть ли что-то вроде $ (this) .attr ('href'), которое меняется в зависимости от того, по какой ссылке я нажимаю?Прямо сейчас мне придется использовать скрипт для каждой ссылки, что, конечно, плохо.Когда я обновляю сайт, CodeIgniter запускает и загружает представление, но на самом деле только само представление, которое я загрузил с помощью ajax, а не всю страницу.Но я думаю, это должно быть легко исправить с помощью макета и правильных настроек контроллера.Пока не обращали на это большого внимания.


Заранее благодарен за любую помощь.Если у вас есть предложения, идеи или просто хотите что-то упомянуть, пожалуйста, дайте мне знать.

regards
DiLer

Ответы [ 2 ]

9 голосов
/ 10 июля 2011

Я поместил успешный минимальный пример истории HTML5 здесь: http://cairo140.github.com/html5-history-example/one.html

На мой взгляд, самый простой способ войти в push5-состояние HTML5 - это некоторое время игнорировать инфраструктуру и использовать максимально упрощенный переход состояния: полная замена элементов <body> и <title>. За пределами этих элементов остальная часть разметки, вероятно, просто шаблонная, хотя, если она меняется (например, если вы изменяете класс на HTML в бэкэнде), вы можете адаптировать это.

То, что делает такой динамический бэкэнд, как CI, - это, по сути, имитация существования данных в определенных местах (идентифицируемых по URL) путем их динамического генерирования на лету. Мы можем абстрагироваться от влияния фреймворка, буквально создав ресурсы и разместив их в тех местах, через которые ваш веб-сервер (вероятно, Apache) просто идентифицирует их и передает через них. У нас будет очень простая структура файловой системы относительно корня домена:

/one.html
/two.html
/assets/application.js

Это только три файла, с которыми мы работаем.

Вот код для двух файлов HTML. Если вы на уровне, когда имеете дело с функциями HTML5, вы должны понимать разметку, но если я ничего не прояснил, просто оставьте комментарий, и я проведу вас через него: 1013 *

one.html

<!doctype html>
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
    <script src="assets/application.js"></script>
    <title>One</title>
  </head>
  <body>
    <div class="container">
      <h1>One</h1>
      <a href="two.html">Two</a>
    </div>
  </body>
</html>

two.html

<!doctype html>
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
    <script src="assets/application.js"></script>
    <title>Two</title>
  </head>
  <body>
    <div class="container">
      <h1>Two</h1>
      <a href="one.html">One</a>
    </div>
  </body>
</html>

Вы заметите, что если вы загрузите one.html через браузер, вы можете нажать на ссылку two.html, которая загрузит и отобразит новую страницу. И с two.html вы можете сделать то же самое обратно к one.html. Круто.

Теперь по части истории:

активы / application.js

$(function(){
    var replacePage = function(url) {
        $.ajax({
            url: url,
            type: 'get',
            dataType: 'html',
            success: function(data){
                var dom = $(data);
                var title = dom.filter('title').text();
                var html = dom.filter('.container').html();
                $('title').text(title);
                $('.container').html(html);
            }
        });
    }

    $('a').live('click', function(e){
        history.pushState(null, null, this.href);
        replacePage(this.href);
        e.preventDefault();
    });

    $(window).bind('popstate', function(){
        replacePage(location.pathname);
    });
});

Как это работает

Я определяю replacePage в обратном вызове jQuery ready, чтобы выполнить простую загрузку URL-адреса в аргументе и заменить содержимое элементов title и .container на удаленные.

Вызов live означает, что любая ссылка, нажатая на страницу, вызовет обратный вызов, и обратный вызов переводит состояние в href в ссылке и вызывает replacePage. Он также использует e.preventDefault, чтобы предотвратить нормальную обработку ссылки.

Наконец, есть событие popstate, которое срабатывает, когда пользователь использует браузерную навигацию по страницам (назад, вперед). Мы привязываем простой обратный вызов к этому событию. Следует отметить, что мне не удалось заставить версию на странице «Погружение в HTML» по какой-то причине работать в FF для Mac. Понятия не имею, почему.

Как его продлить

Этот чрезвычайно простой пример может быть более или менее перенесен на любой сайт, потому что он выполняет очень творческий переход: замена HTML. Я предлагаю вам использовать это в качестве основы и перейти к более творческим переходам. Одним из примеров того, что вы могли бы сделать, было бы подражать тому, что делает Github с навигацией по каталогам в своих репозиториях. Это промежуточный маневр, который требует поплавков и управления переполнением. Вы можете начать с более простого перехода, например, добавив .container на загруженной странице в DOM, а затем анимируя старый контейнер в {height: 0}.

Обращаясь к вашему конкретному "Например"

Вы на правильном пути для использования истории HTML5, но вам необходимо уточнить ваше представление о том, что именно будут содержать /foo и /bar. По сути, у вас будет три страницы: /, /foo и /bar. / будет иметь пустой контейнер div. /foo будет идентичным /, за исключением того, что в контейнере div есть содержимое foo. /bar будет идентичным /foo, за исключением того, что в контейнере div есть некоторое содержание бара. Теперь возникает вопрос, как вы могли бы извлечь содержимое контейнера через Javascript. Предполагая, что ваш тег /foo body выглядит примерно так:

<body>
  <a href="/foo">foo</a>
  <a href="/bar">bar</a>
  <div class="container">foo</div>
</body>

Затем вы извлекаете его из ответа с data по var html = $(data).filter('.container').html() и затем возвращаете его на родительскую страницу через $('.container').html(html).Вы используете filter вместо гораздо более разумного find, потому что по какой-то дурацкой причине анализатор DOM jQuery создает объект jQuery, содержащий каждого дочернего элемента head и каждого дочернего элемента body вместо просто объекта jQuery.обертывание элемента html.Я не знаю почему.

Остальные просто адаптируют это обратно в версию "vanilla" выше.Если вы застряли на каком-либо конкретном этапе, дайте мне знать, и я могу помочь вам лучше, хотя это.

Код

https://github.com/cairo140/html5-history-example

2 голосов
/ 19 марта 2012

Попробуйте это в вашем контроллере:

if (!$this->input->is_ajax_request())
    $this->load->view('header');

$this->load->view('your_view', $data);

if (!$this->input->is_ajax_request())
    $this->load->view('footer');
...