O projekcie

Analiza wymagań

Aplikacja (sklep) działa w dwóch trybach: „strona główna” (Rysunek 9.1) oraz „categoria” (Rysunek 9.2). W trybie categoria część adresu, mianowicie, path, jest nazwą categorii.

Rysunek 9.1. Strona główna sklepu

Aplikacja w trybie „strona główna”

Rysunek 9.2. Sklep w trybie „categoria”

Aplikacja w trybie „categoria”

Aplikacja została zaimplementowana w oparciu o moduł express oraz maszynę szablonów ejs. Nie jest to jedyny sposób na tworzenie aplikacji internetowej w node.js

Struktura plików

Struktura plików aplikacji podana jest na poniższym obrazku.

.
.
├── db
│   └── products.js
├── Gruntfile.js
├── package.json
├── public
│   ├── css
│   │   └── styl.css
│   └── favicon.ico
├── serwer.js
└── views
    ├── index.ejs
    └── partials
        ├── category.ejs
        ├── footer.ejs
        ├── header.ejs
        ├── main.ejs
        ├── nav_categories.ejs
        └── ul_categories.ejs

Na najwyższym poziomie znajdują się trzy pliki:

Gruntfile.js

W tym pliku określa się zadanie dla grunta. W szczególności, jakie pliki trzeba zarchiwizować do pliku ropuszka.zip.

package.js

W tym pliku określa się konfiguracja projektu. W szczególności, jakie moduły powinny zostać zainstalowane poleceniem npm install.

serwer.js

W tym pliku jest właściwa aplikacja serwerowa.

Pozostałe pliki umieszczone są w katalogach:

db

Tu znajduje się plik z bazą danych. Obsługa bazy danych została zaimplementowana za pomocą modułu taffydb.

public

W tym katalogu są pliki, które zostaną wysłane do klienta bez zmian. Na przykład, plik styl.css.

views

W tym katalogu znajdują się szablony ejs. Szablony te zawierają znaczniki HTML oraz specjalne znaczniki, w których są zawarte wyrażenia w JavaScript, które zostaną obliczane podczas serwowania strony. Wartości zmiennych dla szablonu obliczane są w serwer.js. Szablon główny, index.ejs, został podzielony na części składowe, które są umieszczone w katalogu views/partials

Plik serwer.js

Na początku ładuje się moduły. Co robi moduł morgan? Zwróć uwagę, że moduł ./db/products z bazą danych nie jest standardowym. Zajrzyj do jego kodu.

/*jshint globalstrict: true, devel: true, node: true */
'use strict';

let express = require('express');
let app = express();
let path = require('path');
let bodyParser = require('body-parser');
let favicon = require('serve-favicon');
let morgan = require('morgan');
let baza = require('./db/products');

Ustawia się ejs jako maszynę szablonów

app.set('view engine', 'ejs');

Rejestruje się moduły do wykorzystania z expresem.

app.use(morgan('dev'));
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, 'public')));

Rejestracja callbacków dla generowania odpowiedzi na żądania klienta. W trybie „strona główna” żądanie przychodzi metodą get na /. W trybie „categoria” żądanie przychodzi metodą get na /:cat, przy czym cat staje się zmienna (zwróć uwagę na dwukropek). Metodą post przychodzą dane z formularza. Czemu tak się dzieję? Czy widzisz, w jaki sposób przekazywane są dane do szablonu?

app.get('/', function (req, res) {
    let categories = baza().distinct("category");
    res.render('index.ejs', {categories: categories});
});

app.get('/:cat', function (req, res) {
    let categories = baza().distinct("category");
    let products = baza({category: req.params.cat}).select("product", "price");
    let category = req.params.cat;
    res.render('index.ejs', {categories: categories, products: products, category: category});
});

app.post('/:cat', function (req, res) {
    let newPrice=req.body.price;
    let newProduct=req.body.product;
    let category = req.params.cat;
    console.log(newProduct, newPrice);
    let categories = baza().distinct("category");
    let products = baza({category: category}).select("product", "price");
    res.render('index.ejs', {categories: categories, products: products, category: category});
});

Uruchamia się serwer na porcie 3000.

app.listen(3000, function () {
    console.log('Serwer działa na porcie 3000');
});

Opracowanie zdarzenia SIGINT (CTRL+C na serwerze).

process.on('SIGINT',function(){
  console.log('\nshutting down');
  process.exit();
});

Szablon główny (index.js)

<%- include("partials/header.ejs") %>

<% if( typeof products == 'undefined') { %>
    <%- include("partials/main.ejs")%>
<% } else {%>
    <%- include("partials/category.ejs")%>
<% } %>

<%- include("partials/footer.ejs") %>

We wszystkich szablonach tryby pracy aplikacji rozróżniane są tak: w trybie „strona główna” zmienna products nie jest określona.