Od provozovatele projektu Rychlost.CZ
WebDev.wiki > Návody pro webmastery a vývojáře > Díl 2 - přepínání mezi stránkami

Díl 2 - přepínání mezi stránkami - jQuery: Praktická webová aplikace

vydáno: 02.01.2017, seriál: jQuery: Praktická webová aplikace

Toto je 2. díl seriálu jQuery: Praktická webová aplikace, pokud se dostatečně neorientujete, zkuste první díl.

V minulém díle jsme si vytvořili základní strukturu naší webové aplikace. Nyní zkusíme zajistit, aby naše aplikace byla schopna přepínat mezi jednotlivými stránkami.

Menu lišta

Nejdříve budeme potřebovat menu, díky kterému budeme moci přepínat. Pojďme si ho přidat do <body>:

Ukázka:
HTML
<nav class="navbar navbar-fixed-top navbar-dark" style="background-color: #0083ff;">
<a class="navbar-brand" href="#">The Wall</a>
<ul class="nav navbar-nav float-xs-right">
<li class="nav-item active">
<a class="nav-link" href="#" onclick="app.goTo('stories')">Stories</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="app.goTo('stories')">Add</a>
</li>
</ul>
</nav>
Použité tagy: <nav>, <a>, <ul>, <li>

Máme zde několik CSS tříd, které už pro nás Bootstrap má připravené a my je tudíž můžeme rovnou použít. Pojďme si je vysvětlit:

navbar - základní stylování menu lišty
navbar-fixed-top - přilepí menu lištu na horní okraj a zajistí, aby byla stále vidět (i při scrollu)
navbar-dark - položky menu budou světlým písmem, takže jim můžeme dát pozadí syté barvy

Bootstrap nám standardně nastavil i barvu pozadí menu lišty, ale my jsme si ji změnili na modrou pomocí style parametru.

Dále:

navbar-brand - nastyluje “název” aplikace
nav a navbar-nav - nastylují seznam položek menu
float-xs-right - zarovná seznam položek menu doprava a to pro všechny velikosti obrazovek
nav-item - nastyluje položky menu a pokud k ní přidáme i třídu active, tak Bootstrap už pro nás má samozřejmě připraven i speciální vzhled pro aktivní položky menu

Ke každé položce menu jsme si připravili i spuštení funkce app.goTo(), která ještě neexistuje, ale bude právě zajišťovat přepínání stránek při kliku na danou položku.

Rozdělení stránek v HTML

Než ale začneme skriptovat, potřebujeme si vytvořit <div> element pro každou stránku naší aplikace, do <body> za menu tedy přidáme:

Ukázka:
HTML
<div id="page-stories" class="page">Latest stories</div>
<div id="page-story" class="page">Story detail</div>
<div id="page-add" class="page">Add a story</div>
Použité tagy: <div>

Tak, teď už je alespoň něco v naší aplikaci vidět! My ale chceme vidět jen jednu stránku v jeden čas. Půjdeme tedy do screen.css a všechny stránky schováme. Později pak skriptem budeme ukazovat jen tu stránku, která se má zrovna zobrazovat. Obsahům stránek také dáme malé odsazení. Do screen.css přidáme:

Ukázka:
CSS
.page {
display: none;
padding: 24px;
margin-top: 54px;
}
Použité vlastnosti: display, padding, margin-top

Reprezentace stránek v JavaScriptu

Každá stránka v naší aplikaci bude reprenzentována jako položka v objektu app. Když si předem takto připravíme seznam stránek, bude snadnější s nimi pracovat:

Ukázka:
Javascript
window.app = {
stories: {
},
story: {
},
add: {
},
init: function()
{
}
}
$(document).ready(app.init);

Je čas konečně zprovoznit přepínání stránek definováním funkce app.goTo(), kterou si rovněž přidáme do app.js:

Ukázka:
Javascript
window.app = {
stories: {
},
story: {
},
add: {
},
init: function()
{
},
goTo: function(page)
{
}
}

Ve funkci goTo(page) nejdříve zkontrolujeme, jestli stránka, která se má zobrazit (argument page), vůbec existuje v našem objektu app. Pokud ne, zobrazí se místo ní nějaká standardní stránka a tou jsme si řekli, že bude stránka s posledními příspěvky, tedy stories:

if (!app[page])
    page = 'stories';

Následně musíme zařídit, aby se naše aplikace hloupě nepřepínala ze stejné stránky na stejnou stránku. Aktuálně aktivní stránku si později uložíme do nové položky / proměnné v objektu app a bude se jmenovat currentPage. Nyní přidáme jen kontrolu, jestli app.currentPage (aktuálně zobrazená stránka) není stejná, jako page (stránka, na kterou chceme přepnout). Pokud se tedy hodnoty těchto dvou proměnných app.currentPage a page budou rovnat, ukončíme výkon funkce pomocí return:

if (page == app.currentPage)
    return;

Jestliže skript projde přes tuto kontrolu a bude se tedy jednat o jinou stránku k zobrazení než tu, která je aktuálně zobrazena, zobrazíme ji pomocí jQuery fade efektu:

if (app.currentPage)
{
    $('#page-'+app.currentPage).fadeOut(250, function()
    {
        $('#page-'+page).fadeIn(250);
    });
}
else
    $('#page-'+page).fadeIn(250);

Tato část je trochu složitější, pojďme si ji vysvětlit:

Při zobrazení první (standardní) stránky (tedy stories) ještě není proměnná app.currentPage definována, má tedy hodnotu undefined. Pomocí podmínky if (app.currentPage) zjistíme, jestli už přepínáme z nějaké zobrazené stránky na jinou stránku v naší webové aplikaci a nebo (else) jestli se naše aplikace právě načetla a teprve zobrazuje první stránku (stories).

V případě, že se naše aplikace teprve načetla a teprve zobrazujeme první stránku (část za else) použijeme jQuery efekt fade pomocí funkce fadeIn() což neudělá nic jiného, než že nám zviditelní element <div> s ID #page-stories spolu s jeho veškerým obsahem, který do něj později nahrajeme jinou funkcí. Zobrazí se tak stránka stories s posledními příspěvky uživatelů.

Pokud se jedná o přepnutí z jedné stránky naší webové aplikace na jinou, nejdříve pomocí jQuery funkce fadeOut() schováme aktuálně zobrazenou stránku, kterou už v této době máme uloženou v app.currentPage. Jakmile efekt schování doběhne a aktivuje se callback funkce, hned se začne zobrazovat nová stránka pomocí funkce fadeIn(). Celý efekt přepnutí mezi stránkami trvá tak 500 milisekund, tedy půl sekundy.

A nyní si pro příští přepnutí mezi stránkami uložíme tuto novou stránku (page), na kterou jsme právě přepnuli, jako aktuální stránku (app.currentPage):

app.currentPage = page;

Na konec do funkce app.init() budeme chtít přidat kód:

app.goTo('stories');

Aby se při prvním spuštění aplikace zobrazila právě stránka stories.

Aktivace funkce start() při přepnutí stránky

Na konci funkce goTo() se nám bude ještě hodit malé udělátko. Řekněme, že při spuštění stránky stories budeme chtít načíst poslední příspěvky ze serveru nějakou funkcí, kterou budeme mít uvnitř app.stories, mohla by se jmenovat třeba start(), položka stories by tedy vypadala takto:

Ukázka:
Javascript
window.app = {
stories: {
start: function()
{
}
},
// ...
}

Je velmi pravděpodobné, že taková funkce při zobrazení stránky se nám bude hodit u více stránek než jen u stories. Pojdme tedy univerzálně už ve funkci goTo() zjišťovat, jestli stránka, na kterou právě přepínáme takovou funkci má a pokud ano, tak ji provedeme:

if (app[page].start)
    app[page].start();

Když nyní spustíme naši aplikaci a kdykoli přepneme na stránku stories, měl by se nám v konzoli vypsat text "Stories".

Změna aktivní položky menu

S přepnutím na jinou stránku by se měla změnit i aktivní položka menu na korespondující stránku. Konkrétně mluvíme o vyjmutí CSS třídy active z aktivní položky menu korespondující se stránkou, ze které právě přepínáme a přidání CSS třídy active do položky menu korespondující se stránkou, na kterou právě přepínáme.

Zní to složitě, ale nebudeme se s tím trápit. Řádek:

$('nav li.active').removeClass('active');

nejdříve odstraní CSS třídu active obecně ze všech položek menu, které ji náhodou mají a řádek:

$('nav a[onclick="app.goTo(\'' + page + '\')"]').parent().addClass('active');

Přidá CSS třídu active do odkazu na stránku, kterou právě zobrazujeme.

Oba tyto řádky přidáme na konec funkce app.goTo().

Rekaputulace

Tímto máme přepínání mezi stránkami hotové. Příště se podíváme na přidávání příspěvků.

Na závěr rekapitulace celé naší webové aplikace:

Ukázka:
CSS
.page {
display: none;
padding: 24px;
margin-top: 54px;
}
Použité vlastnosti: display, padding, margin-top
Javascript
window.app = {
stories: {
start: function()
{
console.log('Stories');
}
},
story: {
},
add: {
},
init: function()
{
app.goTo('stories');
},
goTo: function(page)
{
if (!app[page])
page = 'stories';
if (page == app.currentPage)
return;
if (app.currentPage)
{
$('#page-'+app.currentPage).fadeOut(250, function()
{
$('#page-'+page).fadeIn(250);
});
}
else
$('#page-'+page).fadeIn(250);
app.currentPage = page;
if (app[page].start)
app[page].start();
$('nav li.active').removeClass('active');
$('nav a[onclick="app.goTo(\'' + page + '\')"]').parent().addClass('active');
}
}
$(document).ready(app.init);
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>The Wall</title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="screen.css">
</head>
<body>
<nav class="navbar navbar-fixed-top navbar-dark" style="background-color: #0083ff;">
<a class="navbar-brand" href="#">The Wall</a>
<ul class="nav navbar-nav float-xs-right">
<li class="nav-item active">
<a class="nav-link" href="#" onclick="app.goTo('stories')">Stories</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="app.goTo('add')">Add</a>
</li>
</ul>
</nav>
<div id="page-stories" class="page">Latest stories</div>
<div id="page-story" class="page">Story detail</div>
<div id="page-add" class="page">Add a story</div>
<script type="text/javascript" src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>