+
+
diff --git a/index.js b/index.js
index e69de29..90e5464 100644
--- a/index.js
+++ b/index.js
@@ -0,0 +1,118 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2016 Kristaps Dzonsons
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+(function(root) {
+ 'use strict';
+
+ /*
+ * Send a GET query to the give url.
+ * Invokes "setup" before running anything, "error" upon network
+ * error (with the HTTP error code and response text), and
+ * success with the response text on 200.
+ */
+ function sendQuery(url, setup, error, success)
+ {
+ var xmh = new XMLHttpRequest();
+ var v;
+
+ if (null !== setup)
+ setup();
+
+ xmh.onreadystatechange = function() {
+ v = xmh.responseText;
+ if (xmh.readyState === 4 &&
+ xmh.status === 200) {
+ if (null !== success)
+ success(v);
+ } else if (xmh.readyState === 4) {
+ if (null !== error)
+ error(xmh.status, v);
+ }
+ };
+
+ xmh.open('GET', url, true);
+ xmh.send(null);
+ }
+
+ /*
+ * Send a POST query to the give url with the form.
+ * Invokes "setup" before running anything (given the form),
+ * "error" upon network error (with the form, HTTP error code,
+ * and response text), and success with the form and response
+ * text on 200.
+ */
+ function sendForm(form, setup, error, success)
+ {
+ var xmh = new XMLHttpRequest();
+ var v;
+
+ if (null !== setup)
+ setup(form);
+
+ xmh.onreadystatechange=function() {
+ v = xmh.responseText;
+ if (xmh.readyState === 4 &&
+ xmh.status === 200) {
+ if (null !== success)
+ success(form, v);
+ } else if (xmh.readyState === 4) {
+ if (null !== error)
+ error(form, xmh.status, v);
+ }
+ };
+
+ xmh.open(form.method, form.action, true);
+ xmh.send(new FormData(form));
+ return(false);
+ }
+
+ function stdError(code, resp) {
+ console.log("ERREUR " + code + ": " + resp);
+ }
+
+ function indexSuccess(resp) {
+ var res;
+
+ try {
+ res = JSON.parse(resp);
+ } catch (error) {
+ console.log('JSON parse fail: ' + resp);
+ return(null);
+ }
+ app.message = res.length + " books";
+ }
+
+ /*
+ * Configure the index page.
+ */
+ function loadIndex()
+ {
+ sendQuery('cgi-bin/bouquins/books',
+ null, stdError, indexSuccess);
+ }
+
+ root.loadIndex = loadIndex;
+})(this);
+
+document.addEventListener('DOMContentLoaded', function() {
+ loadIndex();
+});
+var app = new Vue({
+ el: '#app',
+ data: {
+ message: 'Hello Vue!'
+ }
+})