Používame Gulp.js (1) - Vytvorenie jednoduchej web stránky

Publikoval Michal Kočí dňa 3.8.2015 o 11:00 v kategórii Gulp.js

Ak ešte nepoužívate skvelý nástroj na automatizáciu - Gulp.js - a chceli by ste, alebo by ste chceli vidieť, s čím vám vie pomôcť, potom je tento mini seriál určený práve pre vás.

Seriál začneme tým, že si spravíme jednoduchú stránku, ktorá bude zobrazovať aktuálne počasie v Bratislave. Najskôr ju spravíme bežným spôsobom, bez optimalizácií čiže až priam nepekným spôsobom. No a postupne ju budeme vylepšovať práve použitím rôznych Gulp.js taskov.

Chceli by ste sa Gulp naučiť rýchlo, ľahko a v praxi? Je súčasťou mojho Node.js školenia - kurzu na ktorom sa naučíte programovať serverové aplikácie v JavaScripte.

Informácie o počasí

Spravíme si jednoduchú stránku, ktorá zobrazí aktuálne počasie v danom meste, v našom prípade v Bratislave.

Informácie o aktuálnom počasí zoberieme z webu OpenWeatherMap. Ten poskytuje API (programovacie rozhranie) na zistenie aktuálneho počasia v tisíckach miest.

API na prvý pokus funguje aj bez overenia, t.j. bez API klúča. Avšak v dokumentácii API nájdete zmienku "We keep right to not to process API requests without API key", takže sa vám môže stať, že bez API klúča vám to fungovať nebude.

Ak vám to nepôjde, vygenerujte si API klúč a pridajte ho do každého requestu, ktorý voči API robíte a to ako hodnotu querystring parametra APPID. Navštívte OpenWeatherMap registráciu a zaregistrujte sa - je to zadarmo a stačí vám na to váš e-mail a heslo. Hneď po registrácii vás vezme na stránku vášho profilu, kde uvídíte vám pridelený API klúč.

Testovanie API

Osobne na testovanie API najradšej používam doplnok do Chrome - Postman-REST Client. Ak ho ešte nemáte nainštalovaný, nainštalujte si ho. Samozrejme, ak máte radšej iný nástroj, použite ten. Napríklad Fiddler. Postman je jednoduchý no napriek tomu veľmi šikovný. Po inštalácii ho nájdete vo vašich Chrome aplikáciach, tak si ho spustite.

Skúsme si teda načítať počasie pre Bratislavu. Pozrieme si popis API a nájdeme si metódu, ktorou vieme získať počasie pre ľubovoľné mesto podľa jeho názvu. Super, takže vieme, že URL bude vyzerať nasledovne:

api.openweathermap.org/data/2.5/weather?q=Bratislava

V Postmanovi si tento dotaz spustíme tak, že zadáme túto URL, request necháme ako GET a klikneme na Send. Vráti sa nám nasledovná odpoveď:

Prvotné volanie API počasia cez Postmana

Ak sa vám nevrátila odpoveď, je pravdepodobné, že ste volali API bez vášho API kľúča a volanie zlyhalo. V takom prípade pridajte API kľúč do URL a spustite dotaz znova:

api.openweathermap.org/data/2.5/weather?q=Bratislava&APPID=VAS_API_KLUC

Všimnite si niekoľko vecí:

Postman rozoznal formát odpovede (JSON) a zobrazil vám ho pekne naformátovaný. Ako to zistil? Predsa podľa hlavičky Content-Type z HTTP odpovede. Hlavičky si zobrazíte ak sa pri odpovedi prepnete zo záložky Body do Headers:

Hlavičky odpovede na dopyt na aktuálne počasie cez Postmana

Ďalšia vec, ktorú si zrejme všimnete je teplota - 307 stupňov. To asi nebudú stupne Celsia :) Takže si pozrieme znovu dokumentáciu API a zistíme si, ako sa dá dotaz ďalej konfigurovať.

V dokumentácii vidíme, že parametrom units s hodnotou metric vieme prepnúť na stupne Celsia. API podporuje rôzne jazyky a napriek tomu, že slovenčina medzi nimi nie je uvedená, ak vyskúšame hodnotu sk pre parameter lang, začnú sa nám vracať texty v slovenčine (ISO kód češtiny je cs, ktorý tu nefunguje, zato funguje cz čo je však kód krajiny).

Prekonfigurujme teda URL na nasledovné:

api.openweathermap.org/data/2.5/weather?q=Bratislava&units=metric&lang=sk

A výsledok hneď bude vyzerať použiteľnejšie:

Výsledok volania v slovenčine so stupňami Celsia

Prvá verzia web stránky

Takže API vyzerá dobre, vieme s ním robiť základné operácie a nič nám nebráni pripraviť prvú verziu stránky. Ideme ju spraviť metódou quick&dirty, čiže čo najrýchlešie a najjednoduchšie aj za cenu čistoty riešenia. Čo nevadí, lebo celú stránku na konci zoptimalizujeme, to je koniec koncov náš cieľ.

Aby sme si zjednodušili prácu pri volaní API a prácu s DOMom, použijeme jQuery a pre volanie API použijeme konkrétne metódu jQuery.ajax, ktorá je najvšestrannejšia.

jQuery je často zatracované, ale sú stále scenáre, kde sa vyslovene hodí. A ak ho viete správne použiť a viete, kedy sa moc nehodí, ste za vodou. Ak sa chcete jQuery naučiť poriadne, dojdite na moje jQuery školenie.

Keďže chceme aby počasie vyzeralo aspoň trochu k svetu, použijeme Material Design Lite, Material Icons a Weather Icons. Všetko čo sa jednoducho dá si stiahneme lokálne, aby to bolo súčasťou našej web stránky a nemuseli sme to sťahovať z internetu.

Stránka po navštívení a načítaní dát bude vyzerať približne takto. Dnes je/bolo docela teplo.

Widget s aktuálnym počasím

HTML Markup stránky s počasím

Fajn, pozrime sa ako vyzerá markup. Je jednoduchý, nalinkujeme štýly, fonty a skripty a to ako cudzie, tak aj naše vlastné.

<!DOCTYPE html>
<html>
  <head>
    <title>Počasie</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/material.css">
    <link rel="stylesheet" href="css/weather-icons.css">
    <link rel="stylesheet" href="css/weather.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
  </head>
  <body>
    <h1>Aktuálne počasie</h1>
    <div class="mdl-card mdl-shadow--2dp" id="weather">
      <div class="mdl-card__media">
        <h1>
          <span class="icon wi"></span>
          <span class="degrees"></span>
        </h1>
      </div>
      <div class="mdl-card__supporting-text">
        <h1>Bratislava</h1>
      </div>
      <div class="mdl-card__actions mdl-card--border">
        <h5 class="description"></h5>
        <div class="progress mdl-progress mdl-js-progress mdl-progress__indeterminate progress-demo"></div>
      </div>
      <div class="mdl-card__menu">
        <button type="button" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" id="refresh-weather">
          <i class="material-icons">refresh</i>
        </button>
      </div> 
    </div>
    <script src="js/jquery-2.1.4.js"></script>
    <script src="js/material.js"></script>
    <script src="js/weather.js"></script>
  </body>
</html>

Samotná stránka okrem nadpisu obsahuje jednu kartu. Táto obsahuje názov mesta a niekoľko placeholderov, do ktorých načítame dáta z API. A tlačítko na aktualizáciu informácií.

Javascript stránky s počasím

Počas načítavania dát z API sa v karte zobrazuje progress bar, ktorý indikuje, že sa niečo deje. Po načítaní dát skontrolujeme vrátené dáta a informácie, ktoré máme k dispozícii zobrazíme, ak niektoré v dátach nie sú, zobrazíme N/A.

Takto vyzerá prvá verzia skriptu:

var weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?units=metric&lang=sk&q=Bratislava';
var elements = {};

function getWeatherClassName(icon) {
  switch(icon) {
    case '01d':
      return 'wi-day-sunny';
    case '01n':
      return 'wi-night-clear';
    case '02d':
      return 'wi-day-sunny-overcast';
    case '02n':
      return 'wi-night-partly-cloudy';
    case '03d':
    case '03n':
      return 'wi-cloud';
    case '04d':
    case '04n':
      return 'wi-cloudy';
    case '09d':
    case '09n':
      return 'wi-showers';
    case '10d':
      return 'wi-day-rain';
    case '10n':
      return 'wi-night-rain';
    case '11d':
    case '11n':
      return 'wi-thunderstorm';
    case '13d':
    case '13n':
      return 'wi-snow';
    case '50d':
    case '50n':
      return 'wi-fog';
    default:
      return 'wi-alien';
  }
}

function cacheElements() {
  elements.weather = $('#weather');
  elements.progress = elements.weather.find('.progress');
  elements.degrees = elements.weather.find('.degrees');
  elements.description = elements.weather.find('.description');
  elements.icon = elements.weather.find('.icon');
  elements.refresh = elements.weather.find('.refresh');
};

function refreshUi(loading, data) {
  if(loading) {
    elements.degrees.html('&nbsp;');
    elements.description.html('&nbsp;');
    elements.icon.hide();
    elements.progress.css('visibility', 'visible');
  } else {
    elements.progress.css('visibility', 'hidden');
    if(data) {
      elements.description.text(data.weather && data.weather.length && data.weather[0].description ? data.weather[0].description : 'N/A');
      elements.degrees.text(data.main && typeof data.main.temp != undefined ? Math.round(data.main.temp) + '°C' : 'N/A');
      if(data.weather && data.weather.length && data.weather[0].icon) {
        elements.icon.addClass(getWeatherClassName(data.weather[0].icon)).show();
      }
    } else {
      elements.description.text('N/A');
      elements.degrees.text('N/A');
    }
  }
}

function refresh() {
  refreshUi(true);

  $.ajax({
    method: 'GET',
    url: wetaherUrl,
    success: function(data) {
      console.log('success', data);
      refreshUi(false, data);
    },
    error: function(jqXHR, textStatus) {
      console.log('error', textStatus);
      refreshUi(false);
    }
  });
}

$(document).ready(function() {
  cacheElements();
  elements.refresh.on('click', refresh);
  refresh();
});

Na skripte nie je nič zložité, ale pozrime sa na neho trochu detailnejšie, nech vieme, čo sa deje. Prvá metóda getWeatherClassName nám ná základe názvu ikony, ktorú vracia API, vráti názov triedy, ktorá bude na ikonke použitá.

Namapovanie som pripravil raz, pozrel som sa aké hodnoty pre obrázky API vracia a našiel som k nim ekvivalent vo fonte, ktorý použijeme. Samotné API poskytuje obrázky, ktoré sa dajú použiť ale tie sú malé, nepekné a hlavne nie sú vektorové, preto použijeme radšej font. Použitie fontu je lepšie, môžete zväčšovať veľkosť a "obrázky" budú stále vyzerať ostro a pekne.

Ďalšia metóda je cacheElements. Tá sa volá raz, po načítaní stránky a jej úlohou je, aby v DOMe našla patričné elementy cez jQuery a výsledok si zapamätala (nakešovala). Dôvod je ten, že počasie obsahuje tlačítko na aktualizáciu údajov. Pokiaľ by sme ich nemali zapamätané, museli by sme ich zase vyhľadať v DOMe, čo je zbytočné a neefektívne. Prácu s DOMom treba minimalizovať, pokiaľ sa to dá.

Tretia metóda je refreshUI, ktorá aktualizuje hodnoty na stránke. Berie dva parametre, prvý indikuje či je stav načítavania (vtedy schováme údaje a zobrazíme progress bar) a druhý obsahuje samotné dáta. Ak dáta nemáme, znamaná to chybu pri volaní API a zobrazíme náhradné texty N/A (Not available). Ak dáta máme, skontrolujeme ešte či máme k dispozícii práve tie, ktoré budeme zobrazovať a podľa toho ich zobrazíme. Keďže čítame dáta z externého systému, je lepšie si overiť model, či obsahuje to, čo chceme používať.

No a posledná metóda je refresh, ktorá použitím jQuery.ajax zavolá API a podľa úspechu či neúspechu zavolá funkciu refreshUI s patričnými hodnotami podľa logiky uvedenej v predchádzajúcom odstavci.

Keď je dokument pripravený, teda jQuery zavolá callback, ktorý mu predávame pri volaní metódy ready, tak si nakešujeme elementy, zaregistrujeme metódu refresh pre tlačítko aktualizácie a vyvoláme obnovu dát - v tomto momente je to prvé načítanie dát z API.

Nabudúce

Toľko teda ukážková stránka a skript, celý projekt nájdete na mojom githube v adresári 01, okrem markupu a tohto skriptu sú tam ešte drobné štýly a samozrejme všetky externé veci, ktoré používame.

Nabudúce začneme s týmto projektom pracovať s použitím Gulpu, takže ostaňte naladení...

Mohlo by ťa tiež zaujímať

Páčil sa ti príspevok?

Zdieľaj príspevok alebo si ho odlož na neskôr

Sleduj ma

Ak nechceš premeškať príspevky ako je tento, sleduj ma na Twitteri, alebo ak máš RSS čítačku, môžeš sledovať môj RSS kanál.