Toto je 5. díl seriálu jQuery: Praktická webová aplikace, pokud se dostatečně neorientujete, zkuste předchozí díl či díl první.
Toto je 5. díl seriálu jQuery: Praktická webová aplikace, pokud se dostatečně neorientujete, zkuste předchozí díl či díl první.
Naše webová aplikace v tomto stádiu umí, kromě základních věcí, odesílat příspěvky a zobrazovat aktuální příspěvky. Poslední částí naší aplikace bude zobrazování detailu příspěvku s kompletním textem.
Začneme opět tím, že si do elementu <div>
určeného pro stránku detailu příspěvku (#page-story
) vložíme HTML, které je nezbytné pro zobrazení příspěvku:
<div id="page-story" class="page"><h1 id="story-title"></h1><p id="story-text"></p><p id="story-created" class="text-muted"></p><a href="#" onclick="app.goTo('stories')">← Back</a></div>
Element <a>
s voláním funkce app.goTo('stories')
při kliku bude fungovat jako tlačítko zpět, které uživatele navrátí na hlavní stránku (stories
). Zbytek tohoto HTML asi není třeba vysvětlovat.
Do části app.story
našeho JavaScriptu v souboru app.js si přidáme funkci display()
:
// ...story: {display: function(id){}},// ...
Zde v argumentu id vždy dostaneme číselný identifikátor příspěvku, který se má zobrazit. Díky tomu bude velmi jednoduché vytvořit dotaz na náš REST API server. Dotaz na adresu /post?id=ID
nám vrátí veškeré potřebné informace o příspěvku, který máme v databázi uložený s číslem ID.
Funkce display()
pomocí jQuery funkce $.get()
načte zmíněné informace a ty budeme moci vložit do HTML, které jsme si dříve připravili:
// ...story: {display: function(id){$.get('http://mk.e0.cz/s/webdev.wiki/app/posts', {id: id}, function(response){$('#story-title').html(response.author + "'s story");$('#story-text').html(response.text);$('#story-created').html(new Date(response.created * 1000));app.goTo('story');});}},// ...
Nakonec, po načtení a vložení obsahu příspěvku do předpřipraveného HTML kódu v <div id=”page-story”>
, nezapomeneme na stránku story přepnout pomocí app.goTo('story')
.
Pokud nyní na hlavní stránce klikneme na některý z odkazů “Read it all”, zobrazí se nám celý příspěvek.
V tomto pětidílném seriálu jsme si ukázali jak vytvořit moderní webovou aplikaci. Tento příklad by vám měl pomoci s představou o základní struktuře a fungování aplikace tak, abyste si mohli vytvořit vlastní s mnohými stránkami, širší funkcionalitou a dalšími efekty.
Jak už je ve světě programování zvykem, automatizuje se automatizace. JavaScriptové webové aplikace už se vyvíjejí nějaký pátek a tak existují frameworky a knihovny, které ještě více usnadňují jejich tvorbu tím, že už zahrnují funkcionalitu, která se v nich běžně implementuje. Například naše přepínání stránek, načítání dat z API serverů, rozdělování HTML do šablon (aby se brzy ze souboru index.html nestal nekonečný kus HTML, ve kterém je těžké se orientovat), zobrazení stránky podle adresy za # (tvz. routing) a další.
Nejpopulárnějšími frameworky pro JavaScriptové webové aplikace v době psaní tohoto článku jsou Angular, React a Aurelia. Dalším krokem ve studiu tvorby webových aplikací je jednoznačně nějaký framework tohoto typu.
Pro úplnost, celý zdrojový kód naší příkladové aplikace:
.page {display: none;padding: 24px;margin-top: 54px;}
window.app = {stories: {start: function(){app.stories.load();},load: function(){$('#stories-loading').show();$.get('http://mk.e0.cz/s/webdev.wiki/app/posts', function(response){$('#stories').html('');if (response.length){var html = '';for (var i in response){html += '<div class="card card-block">';html += '<h4 class="card-title">' + response[i].author + '\'s story</h4>';html += '<p class="card-text">' + response[i].text + '</p>';html += '<p class="card-text"><small class="text-muted">' + new Date(response[i].created * 1000) + '</small></p>';html += '<a href="#" onclick="app.story.display(' + response[i].id + ')" class="card-link" style="float: right;">Read it all</a>';html += '</div>';}$('#stories').html(html);}else$('#stories').html('No stories! Time to tell yours.');}).always(function(){$('#stories-loading').hide();});}},story: {display: function(id){$.get('http://mk.e0.cz/s/webdev.wiki/app/posts', {id: id}, function(response){$('#story-title').html(response.author + "'s story");$('#story-text').html(response.text);$('#story-created').html(new Date(response.created * 1000));app.goTo('story');});}},add: {post: function(){var text = $('#add-text');var author = $('#add-author');if (text.val() && author.val()){$.post('http://mk.e0.cz/s/webdev.wiki/app/posts', {text: text.val(), author: author.val()}, function(response){text.val('');author.val('');app.goTo('stories');});}elsealert('It is necessary to fill both text and your nickname.');}},init: function(){app.goTo('stories');window.setInterval(app.stories.load, 1000 * 60 * 5);},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);
<!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"><div id="stories-loading" style="display: none;"><div class="alert alert-info" role="alert"><strong>Loading stories...</strong></div></div><div id="stories"></div></div><div id="page-story" class="page"><h1 id="story-title">Story title</h1><p id="story-text">The story text.</p><p id="story-created" class="text-muted">Created</p><a href="#" onclick="app.goTo('stories')">← Back</a></div><div id="page-add" class="page"><div class="col-xs-12" style="text-align: center;"><h1>What's on your mind?</h1></div><div class="col-xs-12 col-md-6"><label for="add-text">Your thoughts</label><textarea id="add-text" class="form-control" rows="5"></textarea></div><div class="col-xs-12 col-md-6"><label for="add-author">Your nickname</label><input id="add-author" type="text" class="form-control" maxlength="30"></div><div class="col-xs-12" style="text-align: center; margin: 24px;"><button class="btn btn-primary" onclick="app.add.post()">Share</button></div></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>