В этой теме мы будем рассматривать реализацию full-ajax навигации на примере обычного блога. Если кому-то интересно, прошу под кат.
В очередной раз просматривая хабрахабр, меня посетила мысль наваять что-нибудь свое. Поэтому заказав пиццу и вооружившись большой кружкой чая — начал думать.
Я заметил, что на хабре много постов о том, как написать блог с использованием Fat-Free Framework, symfony, Zend и так далее… И тут у меня в голове закралась идея написать блог с ajax навигацией. А почему бы и нет? На хабре я не встретил такой статьи, может быть плохо искал…
Для того, чтобы пост не получился слишком большой я решил разделить его на несколько частей. Хочу обратить Ваше внимание на то, что это мой первый пост на хабре, да и писарь из меня никудышный. Поэтому, если что не так, извиняйте.
Итак, приступим.
Демо.
Ссылки в нашем блоге будут следующего вида:
http://localhost/#!/
http://localhost/#!/page
http://localhost/#!/another-apge
Такие ссылки Вы могли видеть в твиттере.
В нашей корневой директории создаем индексный файл, в котором будет немного верстки нашего кульного блога.
Я над дизайном заморачиваться не стал, так как это пост не об этом. Поэтому без комментариев выкладываю его содержание:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="description" content="" /> <meta name="keywords" content="" /> <meta name="generator" content="" /> <title>My thirst Ajax Blog</title> <script type="text/javascript" src="inc/ajax.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <link type="text/css" rel="stylesheet" href="style.css"/> </head> <body> <div id="content"> <h1><a href="/#!/">Мой блог</a> <span>v1.0</span></h1> <p> <a href="/#!/">Home page</a> <a href="/#!/about">About page</a> </p> <hr /> <div id="posts"></div> </div> <div id="preloader"> <div style="position: absolute; left: 50%; margin-left: -50px; top: 50%; margin-top: -50px;"> <img src="loading.gif" title="Loading..." alt="Loading.." /> </div> </div> </body> <script> $(document).ready(function(){ ajax.onLoadStart = function(){ $('#preloader').show(); }; ajax.onLoadEnd = function(){ $('#preloader').hide(); }; ajax.init(); }); </script> </html>
Единственное, на что хотелось бы обратить внимание, это яваскрипт в конце страницы, который собственно и будет инициализировать нашу ajax-навигацию по блогу.
Чуть не забыл про стили, содержимое style.css:
html, body, div, ul { margin: 0; padding: 0; } body { color: #262626; background: #f4f4f4; font: normal 12px/18px Verdana, sans-serif; } #content { position: absolute; width: 800px; right: 0px; left: 0px; margin: 40px auto 0 auto; padding: 0 60px 30px 60px; border: solid 1px #cbcbcb; background: #fafafa; -moz-box-shadow: 0px 0px 10px #cbcbcb; -webkit-box-shadow: 0px 0px 10px #cbcbcb; } h1 { margin: 30px 0 15px 0; font-size: 30px; font-weight: bold; font-family: Arial; } h1 span { font-size: 50%; letter-spacing: -0.05em; } hr { border: none; height: 1px; line-height: 1px; background: #E5E5E5; margin-bottom: 20px; padding: 0; } p { margin: 0; padding: 7px 0; } a { outline: none; } link { color: #000; text-decoration: none; } a:visited, a:link { color: #000; text-decoration: none; } a:hover { color: #000; text-decoration: none; } a:active { color: #000; text-decoration:none; } #preloader{ display: none; position:fixed; z-index: 777; background:none repeat scroll 0 0 #000000; cursor:wait; width:100%; height:100%; top:0; left:0; opacity:0.7; -moz-opacity: 0.5; -khtml-opacity: 0.5; }
Здесь все понятно, идем дальше… Файл ajax.js:
var ajax = { /** * Скрипт, который будет обрабатывать наши ajax запросы. */ ajSrc: 'ajax.php', ajUrl: '', /** * Функция, которая будет вызываться при начале загрузки */ onLoadStart: function(){}, /** * Функция, которая будет вызываться после получения ответа */ onLoadEnd: function(){}, /** * Мы организовали навигацию при помощи урлов вида #!/my-url. * Поэтому эта функция проверяет адресную строку на соответствие урла такому виду и в случае чего, отправляет запрос. * @return {Boolean} */ checkAjaxNav: function(){ hash = document.location.hash; navInd = hash.substr(0, 3); if(navInd != '#!/'){ this.ajUrl = hash; return false; } hash = hash.substr(2); if( hash != this.ajUrl ){ this.ajUrl = hash; this.sendData(hash); } return true; }, /** * Отправляем запрос на сервер * @param ajaxData */ sendData: function(ajaxData){ this.onLoadStart(); $.post(this.ajSrc, { ajax_data: ajaxData }, function( data ){ ajax.receiveData(data); }, 'json'); }, /** * Получаем ответ от сервера и обрабатываем его. * @param data */ receiveData: function( data ){ for( var key in data ){ var val = data[key]; if( 'eval' == key ) eval(val); else $(key).html(val); } this.onLoadEnd(); }, /** * Инициализируем нашу навигацию */ init: function(){ this.checkAjaxNav(); $(window).bind('hashchange', function(){ ajax.checkAjaxNav(); }); } };
Здесь видно, что мы будем отправлять запросы функцией sendData()
на наш обработчик ajax.php
.
Перед тем, как запрос будет отправлен, вызывается функция onLoadStart()
в которой можно выполнять что-то. Например показать пользователю красивый индикатор загрузки, прикрутить валидацию форм и т.д.
После того, как наш запрос будет обработан, вызывается функция receiveData()
, в которой мы обрабатываем полученные данные и вызываем функцию onLoadEnd()
, которая скрывает наш индикатор загрузки и выполняет какие-то другие функции. Например, ре-инициализация форм страницы и т.д
Обработчик ajax.php
<?php error_reporting(0); define("coolBlogCms", true); define("DIR", getcwd() . "/"); define("INC", DIR . "inc/"); require_once INC . "myAjax.php"; $blog = new myAjax(); if( isset($_POST['ajax_data']) ){ $ew = $blog->receiveData(); switch($ew[1]){ case 'about': $html['#posts'] = <<<HTML This is about page. Loaded from my ajax cms. HTML; break; default: $html['#posts'] = <<<HTML This is the main page of my cool blog. Thank's for reading. HTML; break; } $blog->sendData($html); } ?>
Это небольшой контролер, который будет обрабатывать наши запросы и данные. Пока что здесь нет ничего сверх естественного.
Функция receiveData()
получает данные POST-запроса. А sendData()
отправляет данные. Сейчас это только json, но дальше мы прикрутим еще что-нибудь.
Данные мы будем отправлять массивом, в котором ключом будет выступать селектор элементов или #id элемента на конечной странице, а значением — некие данные.
Так же этой функцией мы можем отправлять js код, который затем выполнится на странице при помощи eval()
Пример для наглядности:
$arr = array(); $arr['#first_div'] = "First div content"; $arr['#second_div'] = "Second div content"; $arr['.another_divs'] = "Content that will be placed to several divs"; $blog->sendData($arr, "alert('Hello world !');");
myAjax.php
<?php if(!defined("coolBlogCms")) exit; class myAjax{ /** * @return bool */ public function receiveData(){ if( !isset($_POST['ajax_data']) ){ return false; } $data = $_POST['ajax_data']; $data = explode('/', $data); unset( $_POST['ajax_data'] ); return $data; } /** * @param $data * @param string $eval * @return bool */ public function sendData( $data, $eval = '' ){ if(!$data && !$eval) return false; if( !headers_sent() ){ header('Content-Type: application/json; charset=utf-8' ); } echo json_encode( array_merge($data, array('eval' => $eval)) ); return true; } }
Вот и все. Если читателям будет интересно продолжение, то я с радостью напишу вторую часть статьи. Примерное содержание второй части:
- Организация БД для хранения постов, комментариев
- Обработчик форм
- * Допиливание существующего функционала
- Оптимизация кода
В качестве БД можно расмотреть такие варианты как традиционная MySQL, или MongoDb.
* Планируется добавление xml и plain типов данных.
Если у Вас есть какие-либо пожелания, о том, что бы Вы хотели видеть в следующей статье — пишите.
Если у Вас есть свое мнение, по поводу того, что и как можно было бы сделать лучше — пишите, буду рад.
Так же рад буду и конструктивной критике.
ссылка на оригинал статьи http://habrahabr.ru/post/210402/
Добавить комментарий