...

понедельник, 27 января 2014 г.

[Из песочницы] Пишем блог с Full-Fjax навигацией сами и с нуля. Часть 1

Всем привет.

В этой теме мы будем рассматривать реализацию 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://ift.tt/mOIMeg">
<html xmlns="http://ift.tt/lH0Osb" 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 типов данных.


Если у Вас есть какие-либо пожелания, о том, что бы Вы хотели видеть в следующей статье — пишите.

Если у Вас есть свое мнение, по поводу того, что и как можно было бы сделать лучше — пишите, буду рад.


Так же рад буду и конструктивной критике.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий