Динамическое обновление и смена контента при переходе по URL без перезагрузки страницы сайта HTML5, JavaScript, PHP, jQuery

Как при переходе по странице сайта динамически обновить контент на странице, без перезагрузки сайта, используя HTML5, JavaScript, PHP, jQuery

Динамическое обновление и смена контента при переходе по URL без перезагрузки страницы сайта HTML5, JavaScript, PHP, jQuery
8 месяцев назад

Динамическое обновление и смена контента при переходе по URL без перезагрузки страницы сайта HTML5, JavaScript, PHP, jQuery

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

В свою бытность подобные задачи, реализовывались посредством использования фреймов, однако пользователи переходя по ссылкам, перемещались по страницам скачкообразно, нарушая видимое место перехода, которое надо было снова искать. Зрительно это выглядело не совсем красиво, да и 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 и пропишем:
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 записывает в историю браузера адреса страниц, которые позволяют пользователям использовать браузерную кнопку назад.

Для наиболее лучшего восприятия, добавим немного стилизации.
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
<IfModule mod_rewrite.c>

# Enables mod_rewrite
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

</IfModule>
1,5K
Демо
Комментарии
  • Arlo 4 месяца назад
    Thank you very much, this is the best version of the code.
    Ответить
  • Сергей2 месяца назад
    Добрый день.nnОфигенный код, очень долго искал такое решение.nСпасибо большое Вам!nВопрос history.js почему не приложили код и вообще он нужен? Зачем?
    Ответить
  • No name1 месяц назад
    history.js нужен для реализации переходов без перезагрузки страницыn
    Ответить
  • Ник1 месяц назад
    Файл history.js задаёт историю браузеру, чтобы при нажатии кнопки назад контент подгружался также динамично как и при переходах.
    Ответить
  • Sovlarus1 месяц назад
    Все сделал ровно по инструкции, но при нажатии на пункт меню меня выкидывает на несуществующую страницу.nНапример, О нас ведет на страницу httpsite.ruabout, а замены контента не происходит.
    Ответить
    • Сергей1 месяц назад
      Sovlarus, скорее всего у вас конфликт правил в файле htaccess. Модуль modrewrite.c включен?
      Ответить
  • Ильдар1 неделя назад
    Все ровно при клике в подгружаемом контенте страница обновляется как ни крути
    Ответить
    • Simple5 дней назад
      Ильдар, history.js подключен?
      Ответить

×
Используя сайт, вы подтверждаете, что вы прочитали и поняли политику о куки, политику конфиденциальности и наше пользовательское соглашение.