Server Side JavaScript Tutorial  

Server Side JavaScript Tutorial Server Side JavaScript mit v8cgi - Teil II



> SQLite arangieren
> Filtern, Validieren und Speichern
> Kleiner Exkurs ins Reich des HTML5

Nach der Einführung in der Welt des SJS sind wir bereit für unser erstes Progrämmchen: Ein klassisches Gästebuch, einfach gehalten, bestehend aus einem Script und eine Art Bootstrap-Datei (Application-Progger werden's kennen), einer SQLite-Datei (Datenbanken sind auch nur Dateien) und einem Frontent-File in HTML5 mit dem Layout.

SQLite arangieren

SQLite-Files müssen «von Hand» zusammengestellt werden. Der folgende Code checkt vorerst ob die Datei vorhanden ist und generiert diese bei bedarf.

//set db
include('sqlite');
if (!new File(memory).exists()) {
var db = new SQLite().open(memory);
db.query("create table entries (
id integer primary key,
name varchar(32),
link varchar(128),
text text
)");
db.close();
}
var db = new SQLite().open(memory);

Vielleicht gibt es elegantere Möglichkeiten um das zu bewerkstelligen?

Die Daten werden in einem Array bestehend aus JSONs eingelesen

//get data    
var result = db.query('SELECT * FROM entries');
var entries = result.fetchObjects();

und anschließend an das Template weitergereicht

//set contents
response.write(
new Template().process('layout', {
msg: msg,
entries: entries,
input: input
}));

Voila!

Filtern, Validieren und Speichern

Jetzt geht es an die Inputs. Zum Filtern benutzen wir die aufgesetzte HTML.escape Funktion. Name und Text sind Pflichtfelder, diese müssen mit dem letzten Datensatz aus der Datenbank verglichen werden um doppelte Einträge zu vermeiden.

//validate inputs
if (input.name || input.text) {

input.name = HTML.escape(input.name);
input.link = HTML.escape(input.link);
input.text = HTML.escape(input.text);

if (!input.name) msg.warning = 'Fehler: Name fehlt';

else if (!input.text) msg.warning = 'Fehler: Textfeld leer';

else { // auf wiederholungen prüfen
var q = "select name, text from entries order by id desc limit 1";
var lastEntry = db.query(q).fetchObjects()[0];

if (lastEntry && lastEntry.name==input.name && lastEntry.text==input.text)
msg.warning = 'Fehler: Dublette!';

}
}

Nach der Prüfung müssen die Daten in die Datenbank:

//update db
if (input.text && msg.warning=='') {

var q = "insert into entries (name, link, text) "
+ "values ('"+input.name+"', '"+input.link+"', '"+input.text+"')";

if (db.query(q)) {
msg.success = 'Dein Post wurde eingetragen.';
input = {};
}
else msg.warning = 'Beim speichern ist Datenbanken-Fehler aufgetreten.';
}

Leider habe ich die Query.js nicht zu SQLite überreden können…

Und hier die (viel zu lange?) vollständige Datei: guestbook.js
//Okt 2009 SJS Tickler Guestbook Script

function guestbook ()
{
var input = request.post;
var memory = 'memory.sql';
var msg = { success:'', warning:'' };
var entries;
var logs;

//set db

//validate inputs

//update db

//get data

//set contents
}

guestbook();


Kleiner Exkurs ins Reich des HTML5

Hier geht es um die Zukunft! Darum will ich euch das HTML5 lehren, so machet mir die Header und die Footer auf.

Über die Jahre haben sich aus dem WebDesign gewisse Standards herausgebildet. Webseiten ähneln im Grunde Listen (section) mit Einträgen (article). Daneben gibt es einen Header, Navigation (nav), Seitenleisten (aside), Benachrichtigungen (dialog) und die Fußzeile (footer).

Aber ein Beispiel sagt ja mehr als Tausend Worte:

Die layout.template
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8" />
<title>SJS Tickler</title>
<!--[if IE]><script src="html5.js"></script><![endif]-->

<style>
section, header, dialog, article {display:block;}
section { width:340px; margin:20px; font:.8em Verdana; }
header { font-weight:bold; }
dialog { padding:4px; }
dialog#success { color:green; }
dialog#fail { color:red; }
article { margin-bottom:1em; border:1px solid #ddd; padding:4px; }
span.entry_name{ font-weight:bold; }
</style>
</head>
<body>

<section id="tickler">

<header>SJS Tickler</header>

<dialog id="success">$(data.msg.success||'')</dialog>
<dialog id="fail">$(data.msg.warning||'')</dialog>



$code(for (var i=0; i < data.entries.length; i++) {
var entry = data.entries[i];
)

<article id="entries">

<span class="entry_id">#$(entry.id)</span>

$code( if (entry.link) { )
<span class="entry_name"><a href="$(entry.link)">$(entry.name)</a>:</span>
$code( } else { )
<span class="entry_name">$(entry.name):</span>
$code( } )

<span class="entry_text">$(entry.text)</span>

</article>

$code( } )

<hr/>

<form id="user_form" method="POST" accept-charset="UTF-8" action="">
<label>Name</label>
<input type="text" name="name" value="$(data.input.name||'')">
<label>Link</label>
<input type="text" name="link" value="$(data.input.link||'')">
<label>Nachricht</label>
<textarea name="text">$(data.input.text||'')</textarea>

<input type="submit">
</form>

</section>

</body>
</html>

Zwei Dinge sind HTML5-Spezifisch: Erstens muss ein kleines Script eingebunden werden, dass den Internet Explorer die neuen Tags beibringt. Zweitens sind die Tags nicht im block-style dargestellt, was aber nicht weiter tragisch ist.

That's easy, isn't it?

Im nächsten Teil will ich in die objektorientierte Programmierung eingehen und mich an einem RSS-Reader versuchen.

Kommentare (9)

  
+
0
Ich habe gerade festgestellt dass in der aktuellen Version (0.6) von v8cgi. Variablen und Funktionen (abgesehen von JSON-Objekte) nicht global bzw. Dateiübergreifen genutzt werden können. Das macht das Coden sehr unflexibel. Z.B. kann ich das Mootools Framework nicht aufsetzen… Meine Totorialreihe werde ich erst wieder fortsetzen (können) wenn dieser Umstand (Bug?)
behoben wurde.
avatar

wildeuter

  • vor ungefähr 10 Monaten
+
0
Was meinst du denn mit nicht global bzw. Dateiübergreifend? Kannst mal bitte einen Use Case erläutern?
avatar

unsicherheitsagent

  • vor ungefähr 10 Monaten
+
0
das einbinden von modulen mit include und requere ist nicht ausgereift. ich habe ein abgespeckte mootools drauf. wenn ich jetzt irgendwo var x = $time() ausgebe, kommt der Fehler $time is undefined.

der die programmiersprache selbst besteht ja auch aus Klassen-Bibliotheken. diese werden dann so
exports.HTML = HTML als global deklariert. das macht es es aber wie gesagt nicht möglich frameworks aus dem klassischen javascript zu verweden…

rhino hin oder hier, es muss schon ein mod sein, das auf dem windows-apache läuft und somit für die «breite masse» verfügbar ist, damit es irgendwie erfolg hat und nicht nur, wie bisher, eine nette spielerei für C-programmierer bleibt.
avatar

wildeuter

  • vor ungefähr 10 Monaten
+
+1
Wer sagt denn das Spidermonkey oder Rhino nich auf Webservern laufen? Auch v8cgi verlässt sich darauf das du Kontrolle über deine Apache-Instanz hast.

Und dass die Variablen im globalen Namespace nicht verfügbar sind ist mir leicht unwahrscheinlich,
schau dir mal das an: racoon.

avatar

unsicherheitsagent

  • vor ungefähr 10 Monaten
+
0
Ach cool! Was es nicht alles schon gibt… Ich werde es mir genauer ansehen. Danke!
avatar

wildeuter

  • vor ungefähr 10 Monaten
+
0
Ach misst, ist bestimmt cool, mootools (2.0) ist implementiert, benötigt aber couchdb — davon hört man immer öfter. Ich will auch auf couchdb in meinem totorial eingehen — nur wird das (noch) nicht für windows supportet, in der nächsten version (0.10) soll das dann laut road map soweit sein…
avatar

wildeuter

  • vor ungefähr 10 Monaten
+
0
couchdb rules — übrigens. musste ich mal loswerden :)
avatar

BuzzEins

  • vor ungefähr 10 Monaten
+
0
glaube ich dir! ich hoffe das blad das windows build erscheint. vorerst muss ich rauskriegen, wie die macher von raccoon das mit mootools hingekriegt haben…
avatar

wildeuter

  • vor ungefähr 10 Monaten
+
+1
Ein etwas besseres ErrorHandling (zumindest unter Linux):

var error = e.stack? (e.stack).replace(/ at /g,'
\n at '): e;
write(error);

Übrigens werden seit release 0.7.0 per parameter showErrors (auch) ohne dem try-catch blog ausgegeben und HTML.dump() funktioniert.
avatar

wildeuter

  • vor ungefähr 10 Monaten

 



Ihre Email bleibt unsichtbar


jeder zweite dofollow :)