# The Genealogist Part 4: Improving the GUI
In this part of the tutorial we will add GUI parts for the db updating functionality that we added in [part 3](http://www.swi-prolog.org/pengines/GenealogistUpdate.html). From now on we are also going to try to adhere to the so called [principle of separation of concerns](http://en.wikipedia.org/wiki/Separation_of_concerns) and split our HTML, CSS and JavaScript up into separate files. Here is how the apps directory looks like in the final version of our web application:
~~~~
apps/
genealogist/
genealogist.pl
index.html
js/
genealogist.js
css/
genealogist.css
swish\
scratchpad\
~~~~
The file =|genealogist.pl|= has not changed since part 3, so we will not say more about it here. The CSS in =|genealogist.css|= is fairly uninteresting so we keep silent about that too. Let us begin by looking at the HTML:
~~~~
Genealogist
The Genealogist
Query
Update
Parent is:
Male
Female
Output
~~~~
Stripped from JavaScript and styling information it does a pretty good job at describing the structure of our GUI.
Here is the JavaScript file:
~~~~
/* JavaScript for the Genealogist application */
var pengine;
function ask() {
var query = $("#query").val();
if (query) {
pengine = new Pengine({
application: 'genealogist',
ask: query,
onsuccess: function() {
writeln(JSON.stringify(this.data));
if (this.more) {
disableButtons(true, false, false, false);
} else {
writeln("No more solutions");
disableButtons(false, true, true, true);
}
},
onfailure: function() {
writeln("Failure");
disableButtons(false, true, true, true);
},
onstop: function() {
writeln("Stopped");
disableButtons(false, true, true, true);
},
onabort: function() {
writeln("Aborted");
disableButtons(false, true, true, true);
},
onerror: function() {
writeln("Error: " + this.data);
disableButtons(false, true, true, true);
}
});
}
}
function next() {
pengine.next();
}
function stop() {
pengine.stop();
}
function abort() {
pengine.abort();
}
function update(op) {
var pred = op + $("input[name=sex]:checked").val(),
X = $("#X").val().toLowerCase() || '_',
Y = $("#Y").val().toLowerCase() || '_',
command = pred + '(' + X + ',' + Y + ')';
Pengine({
application: 'genealogist',
ask: command,
onsuccess: function() {
writeln(command);
$("#X,#Y").val("");
},
onerror: function() {
writeln("Error: " + this.data);
}
});
}
function writeln(string) {
$('#output').append(string + " ");
}
function disableButtons(ask, next, stop, abort) {
$("#ask-btn").prop("disabled", ask);
$("#next-btn").prop("disabled", next);
$("#stop-btn").prop("disabled", stop);
$("#abort-btn").prop("disabled", abort);
}
$(document).ready(function() {
$("#sample-queries").on("change", function() {
$("#query").val($("#sample-queries option:selected").text());
});
$("#ask-btn").on("click", ask);
$("#next-btn").on("click", next);
$("#stop-btn").on("click", stop);
$("#abort-btn").on("click", abort);
$("#assert-btn").on("click", function() {
update('assert_');
});
$("#retract-btn").on("click", function() {
update('retract_');
});
$("#clear-btn").on("click", function() {
$('#output').html('');
});
});
~~~~
So, where are we? Well, the Genealogist should now allow us to:
- Query the database from more than one client at a time.
- Update the database of parent-child relationships incrementally and from more that one client at a time.
- All this without compromising the safety of the pengine server
There are still some problems left to be solved. For example, if you shut down the server and start it again, the database will turn out to be empty. Here, we will only point you to library(persistency) which may be able to help.