Откопал в архиве старого сайта свою небольшую статью про то, как сделать простейшую страницу новостей сайта с применением Ajax. Такая техника очень часто применяется на блого-подобных сайтах, типа news2.ru.

Статьи в блогах практически никогда не выводятся полностью. Чаще всего отображается небольшой абзац, а ниже указана ссылка на её продолжение.

Конечно, если новость очень большая, и в ней находятся изображения, видео и т.п., то проще и правильнее выводить их в новых страницах. Но если новость не очень длинная и ограничивается лишь текстом, то можно выводить её описанным ниже способом.

Суть в следующем: представьте, что мы выводим на странице абзац статьи фиксированной длины, например, 100 символов. Остальная часть статьи обрезается, и в конце отображённого абзаца выводится многоточие-ссылка, при нажатии на которую к статье подгружается остальная её часть. И всё это происходит без перезагрузки страницы. Новости будут выводиться погодично, т.е. не всей кучей сразу, а только за тот год, который мы хотим.

Итак, чтобы создать сие чудо, нам понадобится следующее:

  • index.htm – страница, куда будут вставляться наши новости
  • news.dat – файл новостей в текстовом формате
  • news.php – скрипт обработки Ajax-запросов и форматирования новостей
  • carbon_js_core_compressed.js, carbon_js_ajax_compressed.js, carbon_js_dom_compressed.js – обжатая версия моего фреймворка для реализации Ajax-запросов и отображения новостей

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

<div class="news_block"></div>

В этот блочный элемент будут вставляться наши новости. Далее, создадим файл news.dat. В нём будут находиться наши новости в следующем формате:

ЧЧ месяц ГГГГ¤Заголовок¤Новость. Длинная новость. Очень длинная новость.

Например:

17 января 2010¤Наш сайт стал динамичнее!¤Теперь новости нашего сайта выводятся через Ajax, без перезагрузки страницы!

Для каждой новости отдельная строка. Конечно, новости придётся записывать в этот файл вручную, но, если вы хорошо знаете PHP, то можете написать утилиту (а ля Админ-центр), которая сама будет записывать вашу новость в этот файл.

Теперь рассмотрим сам алгоритм вывода новостей таким способом. Создадим функцию, которая будет делать запрос к файлу news.php и получать от него новости за переданный ей год:

function newsFrom(year) {
	Q().ajax({
		url: "news.php",
		params: {"year": year},
		onSuccess: function(jsRequest) {
			Q("div.news_block").html(jsRequest.responseText);
		}
	});
}
CarbonJS.loadModules(["ajax", "dom"], function() {
	newsFrom(new Date().getFullYear());  // При загрузке страницы будут подгружаться новости за текущий год.
});

Всего скрипту news.php могут передаваться 2 параметра – year и num. Параметр num отвечает за подгрузку полной статьи указанного года и индекса этой новости в массиве статей данного года.

Наш файл news.php будет вести себя следующим образом: если скрипту передан только параметр year, то он будет отображать все новости за данный год. Если передан year и num, то выведется полная выбранная статья. Если же вызвать скрипт без параметров, то выведется альтернативная страница, содержащая все новости (не обрезанные). Это пригодится нам для того, чтобы не обездолить посетителей сайта с отключённым JavaScript или без поддержки Ajax.

Файл news.php должен выглядеть примерно вот так:

<?php
header("content-type: text/html; charset=utf-8");
function utf8_strlen($s) {
	return preg_match_all('/./u', $s, $tmp);
}
function utf8_substr($s, $offset, $len = 'all') {
	if ($offset < 0) $offset = utf8_strlen($s) + $offset;
	if ($len != "all") {
		if ($len < 0) $len = utf8_strlen($s) - $offset + $len;
		$xlen = utf8_strlen($s) - $offset;
		$len = ($len > $xlen) ? $xlen : $len;
		preg_match('/^.{' . $offset . '}(.{0,'.$len.'})/us', $s, $tmp);
	} else {
		preg_match('/^.{' . $offset . '}(.*)/us', $s, $tmp);
	}
	return (isset($tmp[1])) ? $tmp[1] : false;
}
if (isset($_REQUEST['year']) && is_numeric($_REQUEST['year']) && $_REQUEST['year'] >= 2010) {
	$news = array();
	$inc = 0;
	$file = fopen("news.tpl", "r");
	if (!isset($_REQUEST['num']) || !is_numeric($_REQUEST['num'])) echo "<ul>\n";
	while (!feof($file)) {
		$s = fgets($file);
		$arr = split("¤", $s);
		if (substr($arr[0], -4, 4) == $_REQUEST['year']) {
			array_push($news, $arr[2]);
			if (!isset($_REQUEST['num']) || !is_numeric($_REQUEST['num'])) {
				echo "<li><div class=\"news_short\">$arr[1]</div>\n";
				if (utf8_strlen($arr[2]) > 70) {
					echo "<span id=\"news$inc\">" . utf8_substr($arr[2], 0, 70) . "<a href=\"javascript:void(0)\" class=\"content\" title=\"Читать дальше\" style=\"font-weight: bolder\" onClick='getNews(\"" . substr($arr[0],-4,4) . "\",\"$inc\")'>...</a></span>\n";
				} else {
					echo "<span id=\"news$inc\">$arr[2]</span>\n";
				}
				echo "<div class=\"news_hr\"></div><div class=\"news_date\">$arr[0]</div><br></li>\n\n";
			}
			$inc++;
		}
	}
	if (isset($_REQUEST['num']) && is_numeric($_REQUEST['num']) && $_REQUEST['num'] >= 0 && $_REQUEST['num'] < count($news)) {
		echo $news[$_REQUEST['num']];
	} else {
		echo "</ul>\n";
	}
	fclose($file);
} elseif (!isset($_REQUEST['year'])) {
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Новости сайта (не-Ajax версия)</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<ul>
<?php
	$file = fopen("news.dat", "r");
	while (!feof($file)) {
		$s = fgets($file);
		$arr = split("¤", $s);
		echo "<li><div>$arr[1]</div>\n";
		echo "$arr[2]\n";
		echo "<div>$arr[0]</div><br></li>\n\n";
	}
	fclose($file);
?>
</ul>
</body>
</html>
<?php } ?>

Этот простой скрипт построчно обрабатывает файл с новостями (news.dat) и, в зависимости от переданных параметров, отображает нам то, что нужно.

Если вы внимательно просмотрели этот скрипт, то могли заметить JS-функцию getNews(), которая запускается при щелчке на многоточие:

function getNews(year, index) {
	Q().ajax({
		url: "news.php",
		params: {
			"year": year,
			"num": index
		},
		onSuccess: function(jsRequest) {
			Q("#news" + index).html(jsRequest.responseText);
		}
	});
}

Её задача – замена блока с обрезанной статьёй на её полную версию.

Последнее, что осталось сделать – это добавить ссылки на новости за те годы, которые есть в файле news.dat. Мы не будем заморачиваться и выводить их скриптом автоматически – вы можете потом сделать это сами. Мы просто добавим их в код страницы вручную:

Новости за <a href="javascript:void(0)" onClick="newsFrom('2010')" class="pages">2010</a> <a href="javascript:void(0)" onClick="newsFrom('2009')" class="pages">2009</a> <a href="javascript:void(0)" onClick="newsFrom('2008')" class="pages">2008</a> год.

Итак, окончательно наша страница должна иметь следующие элементы:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Новости сайта</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script type="text/javascript" src="carbon_js_core_compressed.js"></script>
<script type="text/javascript">
function newsFrom(year) {
	Q().ajax({
		url: "news.php",
		params: {"year": year},
		onSuccess: function(jsRequest) {
			Q("div.news_block").html(jsRequest.responseText);
		}
	});
}
function getNews(year, index) {
	Q().ajax({
		url: "news.php",
		params: {
			"year": year,
			"num": index
		},
		onSuccess: function(jsRequest) {
			Q("#news" + index).html(jsRequest.responseText);
		}
	});
}
CarbonJS.loadModules(["ajax", "dom"], function() {
	newsFrom(new Date().getFullYear());
});
</script>
</head>
<body>
<div class="news_block"><a href="news.php">Альтернативная страница новостей</a></div>
Новости за <a href="javascript:void(0)" onClick="newsFrom('2010')" class="pages">2010</a> <a href="javascript:void(0)" onClick="newsFrom('2009')" class="pages">2009</a> <a href="javascript:void(0)" onClick="newsFrom('2008')" class="pages">2008</a> год.
</body>
</html>

Приведённый пример является самым простым и может использоваться на простых сайтах, на которых не используются какие-либо CMS.