
4 года назад
Динамическое обновление и смена контента при переходе по URL без перезагрузки страницы сайта HTML5, JavaScript, PHP, jQuery
Современные тенденции и подходы в веб-разработке открывают новые возможности использования динамики переходов по URL – без перезагрузки страниц. Данный способ, заключается в создании алгоритма, при котором пользователь, просматривая сайт не обновляет страницу целиком, а подгружает лишь некоторые её части и блоки, что значительно увеличивает скорость загрузки сайта и зрительно способствует лучшему восприятию.
В свою бытность подобные задачи, реализовывались посредством использования фреймов, однако пользователи переходя по ссылкам, перемещались по страницам скачкообразно, нарушая видимое место перехода, которое надо было снова искать. Зрительно это выглядело не совсем красиво, да и URL адрес основного фрейма никак не менялся, оставался прежним. Скопировать такую ссылку было нельзя.
В данной статье мы поговорим о том, как используя HTML5, JavaScript, PHP и jQuery реализовать динамическую подгрузку контента, со сменой URL, при этом не перезагружая страницу сайта целиком.
А теперь давайте приступим! Создадим и откроем файл index.php и пропишем туда нужную нам разметку:
В свою бытность подобные задачи, реализовывались посредством использования фреймов, однако пользователи переходя по ссылкам, перемещались по страницам скачкообразно, нарушая видимое место перехода, которое надо было снова искать. Зрительно это выглядело не совсем красиво, да и URL адрес основного фрейма никак не менялся, оставался прежним. Скопировать такую ссылку было нельзя.
В данной статье мы поговорим о том, как используя HTML5, JavaScript, PHP и jQuery реализовать динамическую подгрузку контента, со сменой URL, при этом не перезагружая страницу сайта целиком.
А теперь давайте приступим! Создадим и откроем файл index.php и пропишем туда нужную нам разметку:
cont.php
<?php
include("class.php");
?>
<!doctype html>
<html lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name=viewport content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css" type="text/css" media="screen">
<script src="jquery-3.2.1.min.js"></script>
<script src="history.js"></script>
<script src="document.js"></script>
<title><?php echo $data->title(); ?></title>
</head>
<body>
<div id="footer-l">
<div id="page-l">
<div id="logo">logo</div>
<nav><ul class="nav"><?php echo $data->menu(); ?></ul></nav>
</div>
</div>
<div id="footer-r">
<div class="content"><?php echo($data->content($data->state(),$data->title())); ?></div>
</div>
</body>
</html>
В представленном коде как мы видим ничего сложного нет, в файле index.php содержится в основном html-разметка страницы.
$data->title() – вывоз функции названия страницы
$data->menu() – меню сайта
$data->content() – вывод основного содержимого блока content
А теперь создадим и откроем файл class.php и пропишем:
$data->title() – вывоз функции названия страницы
$data->menu() – меню сайта
$data->content() – вывод основного содержимого блока content
А теперь создадим и откроем файл class.php и пропишем:
class.php
<?php
$menu = array(
'1' => array("name" => "Главная", "page" => "./"),
'2' => array("name" => "О нас", "page" => "./about"),
'3' => array("name" => "Контакты", "page" => "./contacts")
);
class load_page_vars {
function title(){
global $menu;
$item = $menu;
$str = '';
$i=0;
foreach($item as $k => $value)
{
$i++;
if($item[$i]["page"] == ".".$this->state())
{
return $item[$i]["name"];
}
}
}
function menu(){
global $menu;
$str = '';
$i=0;
foreach($menu as $k => $value)
{
$i++;
$str.= "<li><a href='".$menu[$i]["page"]."' ".($menu[$i]["page"] == ".".$this->state() ? 'class="selected"' : '')." title='".$menu[$i]["name"]."'>".$menu[$i]["name"]."</a></li>";
}
//$this->state($page_title);
return $str;
}
function content($page, $name){
$post = array(
'page' => ".".$page,
'name' => $name,
'password' => 'bar',
'submit' => TRUE,
);
$data = http_build_query($post);
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($data) . "\r\n",
'content' => $data,
)
);
$context = stream_context_create($opts);
$url = $this->siteURL()."/content.php";
$content = file_get_contents($url,FALSE,$context);
return $content;
}
function state() {
$request = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
$str_repl = str_replace($request, '', $_SERVER['REQUEST_URI']);
return $str_repl;
}
function siteURL()
{
if (isset($_SERVER['HTTPS']) &&
($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$protocol = 'https://';
}
else {
$protocol = 'http://';
}
$siteUrl = $protocol.$_SERVER["HTTP_HOST"].$_SERVER["PHP_SELF"];
return dirname($siteUrl);
}
}
$data = new load_page_vars();
?>
В class.php содержатся функции, отвечающие за вывод названия страницы, меню, контент
document.js
window.onload = function() {
function reAnswer(state, title){
$.ajax ({
url: "content.php",
type: "POST",
data: {page: state, name:title},
success: function (result) { $(".content").html(result);
}
});
}
function handlerAnchors() {
$("ul.nav li a").removeClass('selected');
$(this).addClass('selected');
var state = {
title: this.getAttribute( "title" ),
url: this.getAttribute( "href", 2 )
}
history.pushState( state, state.title, state.url );
document.title = state.title;
reAnswer(state.url, state.title);
return false;
}
var anchors = document.getElementsByTagName( 'a' );
for( var i = 0; i < anchors.length; i++ ) {
anchors[ i ].onclick = handlerAnchors;
}
window.onpopstate = function( e ) {
$("ul.nav li a").removeClass('selected');
$('ul.nav li a[href$="' + history.state.url + '"]').addClass('selected');
document.title = history.state.title;
reAnswer(history.state.url, history.state.title);
}
}
Функция reAnswer отправляет файлу content.php POST массив с данными нужной нам страницы. При успешной отправки и получении данных, функция success, выводит в блок .content описание страницы, согласно введенному URL адресу.
Функция handlerAnchors вызывается при клике и смене адреса страницы. Она содержит массив state, в который записываются адреса и названия посещенных страниц.
history.pushState записывает в историю браузера адреса страниц, которые позволяют пользователям использовать браузерную кнопку назад.
Для наиболее лучшего восприятия, добавим немного стилизации.
Функция handlerAnchors вызывается при клике и смене адреса страницы. Она содержит массив state, в который записываются адреса и названия посещенных страниц.
history.pushState записывает в историю браузера адреса страниц, которые позволяют пользователям использовать браузерную кнопку назад.
Для наиболее лучшего восприятия, добавим немного стилизации.
style.css
@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto');
html, body {
height: 100%;
}
body {
color: #4f4f5a;
font-family: 'Roboto', sans-serif;
font-size: 16px;
padding: 0;
margin: 0;
}
.nav {
margin-top: 50px;
padding: 0;
}
.nav:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.nav li {
margin: 0 10px 0 0;
padding: 0;
list-style: none;
}
.nav li a {
padding: 10px 15px;
margin: 3px 0;
display: table;
color: #000;
font-size: 18px;
text-decoration: none;
}
.nav a:hover {
background: #f6f6f6;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.nav a:focus {
outline: none;
}
.nav .selected {
background: #f6f6f6;
color: #000;
text-decoration: none;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.content {
width: calc(100% - 180px);
margin: 70px 70px 70px auto;
padding: 20px;
height: 300px;
overflow: auto;
border: 1px solid #f3f3f3;
background: #FFF;
color: #000;
}
.content p {
margin: 0 0 10px;
}
#page-l {
padding: 30px;
}
#logo {
display: table;
margin: 20px 0;
background: #f66035;
color: #fff;
font-weight: bold;
padding: 5px;
font-size: 26px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
#footer-l {
float: left;
width: 300px;
height: 100%;
background: #fff;
-webkit-box-shadow: -6px 0px 15px 0px rgba(0,0,0,0.75);
-moz-box-shadow: -6px 0px 15px 0px rgba(0,0,0,0.75);
box-shadow: -6px 0px 15px 0px rgba(0,0,0,0.75);
}
#footer-r {
float: left;
width: calc(100% - 302px);
}
#footer-r:after {
display : table;
content : " ";
clear : both;
}
@media (max-width:550px) {
#footer-l, #footer-r {
width: 100%;
}
#footer-l {
#border: 0 none;
height: auto;
}
.content {
width: calc(100% - 40px);
margin: 0;
border: 0 none;
}
}
content.php
<?php
switch ($_POST["page"]) {
case "./":
echo "<h1>".$_POST["name"]."</h1>";
echo "<p>Текст...</p>";
break;
case "./about":
echo "<h1>".$_POST["name"]."</h1>";
echo "<p>Текст...</p>";
break;
case "./contacts":
echo "<h1>".$_POST["name"]."</h1>";
echo "<p>Текст...</p>";
break;
}
?>
В файл content.php посредством POST запроса отправляется массив, согласно которому switch выводит нужную нам информацию на страницу.
.htaccess
RewriteEngine on
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
# Sets the base folder of the State sample
RewriteBase /webdevelopment/dynamic-page
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php
SetEnvIf X-Forwarded-Proto https SERVER_PORT=443
SetEnvIf X-Forwarded-Proto https HTTPS=on
RewriteCond %{HTTP:HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
17,5K
Комментарии
- Arlo 3 года назадThank you very much, this is the best version of the code.Ответить
- Сергей3 года назадДобрый день. Классный код, очень долго искал такое решение. Спасибо большое Вам! Вопрос history.js почему не приложили код и вообще он нужен? Зачем?Ответить
- No name3 года назадhistory.js нужен для реализации переходов без перезагрузки страницыОтветить
- Ник3 года назадФайл history.js задаёт историю браузеру, чтобы при нажатии кнопки назад контент подгружался также динамично как и при переходах.Ответить
- Sovlarus3 года назадВсе сделал ровно по инструкции, но при нажатии на пункт меню меня выкидывает на несуществующую страницу. Например, О нас ведет на страницу about, а замены контента не происходит.Ответить
- Сергей3 года назадSovlarus, скорее всего у вас конфликт правил в файле htaccess. Модуль modrewrite.c включен?Ответить
- Ильдар3 года назадВсе ровно при клике в подгружаемом контенте страница обновляется как ни крутиОтветить
- Simple3 года назадИльдар, history.js подключен?Ответить
- Дмитрий3 года назадПри попытке обновить страницу, ошибка 500. Internal Server Error. Любая страница, кроме главной. Почему так происходит ?Ответить
- Александр3 года назадВсе круто! Спасибо! Только еще вопрос как создать ссылку на конкретную страницу? не из массива. Например в тексте страницы помимо меню будет еще ссылка на другую страницуОтветить
- Дмитрий3 года назадГде файл history.js????? Нечего не работает зачем такое выкладывать отстой твой сайт г....о!!!!Ответить
- SERG2 года назадНе гоните пургу! Все работает! Если нужен history.js, открой исходный код демо и скачай оттуда, тормоз!!!Ответить
- Алекс2 года назадВсе работает, кто не разобрался совсем тук-тук!Ответить
- Алексей2 года назадМожет я что-то не понял, но твой демо не работает без перезагрузки... каждый раз вижу обновлениеОтветить
- irmaseoru2 года назадСпасибо, очень полезная информацияОтветить
- Александр2 года назадОчень круто! Огромное спасибоОтветить
- Farmer1 год назадСпасибо за годный пример! Для тех, кому нужен history.js - как писали выше, открывайте демо, нажимайте f12, ищите подключаемый файл history.js, открывайте его в новой вкладке и копируйте содержимое. Для тех, у кого при обновлении страницы вылетает ошибка - в файле .htaccess в строке RewriteBase поменяйте путь до своего index файла, или поставьте /Ответить
- Евген1 год назадХватит уже говнокодить.Ответить
- Александр4 месяца назадОчень крутое решение, огромнейшее спасибо. На основе данного кода хочу создать базовый движок для сайта.Ответить