Category Archives: Uncategorized

Simple web form generator to PDF

Recently I was asked how to complete a Refugee Action Microsoft Word application form by someone who had no Microsoft software. Nothing I tried (third party applications, web-based document editors) was able to even lay out the form correctly, let alone edit the fields without causing damage to the document structure. Here is a PDF version of Refugee Action’s Word document generated by LibreOffice. Some of the formatting / form control issues present in the original document when opened by non-Word applications are present in the PDF.

Organisations with a web presence should be collecting form data with HTML to accommodate the widest possible audience of WWW users and styling it for physical presentation in a portable format (such as PDF) as a separate activity. Separating the data from the form presentation also offers the opportunity of directly importing form data into office databases.

I’ve thrown together a little demo in Firtl’s sandpit to demonstrate a form-filler service.  I chose a text-based Document/Section/Field scheme and created a text file to describe the fillable form. I use a zip file for export / import, but it would be straightforward to provide import/export in other (CSV, XML, JSON etc) formats.

The URL of a form definition is passed to the form-filler service as the ‘def’ query parameter. See how the Refugee Action application looks as a web-based form here. The form submission controls (at the bottom of the web page) allow you to ‘Update’ the page, ‘Download PDF’ and ‘Download Zip’. ‘Update’ does mostly nothing except in the case of image upload: it shows a thumbnail of the uploaded image. It could easily provide some generic validation such as ensuring mandatory fields are filled and checking data types (date / number etc).

The ‘Download PDF’ button uses the form data, the document definition file and some server-side LaTeX to produce a static PDF document containing the form data. The ‘Download Zip’ button allows you to download just the form data on its own. It allows users to save the form content and upload it later (see bottom of every form-filler page for upload form) to continue editing. I tested the form-filler on an Android smartphone by creating the Zipped form content on my desktop PC and then sending it to the Android device via email.

The web forms are plain HTML so should work perfectly with any recent* browser. The Refugee Action demo has their logo applied with a simple CSS stylesheet specified in the form definition file. If no stylesheet is specified, some default styles are included in the page source. Note that the styles apply only to the web form and not to the generated PDF.

Firtl’s form-filler service uses HTTP POST to send form data to the web service, so it’s not possible to provide a clickable link to a convincing example of the PDF-generation in action. Instead I’ve uploaded my test form data zip file to this blog. Download the zip file, navigate to the foot of the demonstration form, select the downloaded zip file and click ‘Upload’. You should see nearly every form field filled with test data. Clicking on the ‘Download PDF’ button should give you the completed document.

The Refugee Action example demonstrates almost all the features built into this basic form generation demo. I’ve included a couple more examples below.

Note that there’s currently nothing stopping you hosting your own form definition file and using the form-filler service to generate web forms, zipped form content and PDF documents. I’d appreciate a mention if you do!

Hello, World (form definition file is here)

Maths Test (form definition file is here)

*’recent browser’ – I tested this on a 2007 Nokia 6500 Classic’s S40 browser. Editing the document, creating the zip and downloading the PDF worked perfectly. The Nokia has no software for viewing zips or PDFs, but can still send them as MMS or email attachments. Try editing a Word document on a phone like that!

Measuring tube question generator

Here’s a little demo of on-the-fly image creation based on a Key Stage 1 homework my daughter brought home. Every time you visit this page you should see a different question. A new question is asked after each time you press the ‘Am I right?’ button.





This page requests a ‘measuring tube’ JSON object from the Firtl server. Server-side code selects a measuring tube template from a set of different capacities and major/minor measurement ‘ticks’, calculates a random fill that lines up nicely with one of the ticks and returns a JSON object containing the fill level and an URL for the image. The image itself is not drawn by the server until it receives the request caused by setting the img’s src attribute.

Screenshot (PNG) of large web page from Firefox

Was having little luck with printing-to-PDF and addons until I saw a comment to the effect that Firefox has a command line interface since many version ago. Just press shift-F2 and a prompt appears at the foot of the Firefox window. Entering ‘help’ lists the available commands, one of which is ‘screenshot’.

You can get help for screenshot with ‘help screenshot’ but the option format seems to be out of date (in version 22.0). The way to enter the command line swithces is to precede them with ‘–‘. As soon as you type the double-dash you should be prompted with the available arguments. So for example to copy the entire current webpage to your clipboard, you’d type shift-F2 (the CLI doesn’t seem to notice if you change tabs) and enter:

screenshot --clipboard --fullpage

To save the whole current webpage press shift-F2 and enter:

screenshot screen.png --fullpage

Hope this helps!

LEGO NXT robot head with webcam and JavaCV

While I was finding out how to use a webcam for motion detection with Java via JavaCV, I built this little robot head from LEGO Mindstorms with LeJOS on the NXT. Having Java on both sides of the USB connection makes communicating the direction ‘to look at’ simple and reliable.

I use JavaCV to find the largest difference (what moved the most) between successive images from the webcam and send its position in the webcam’s view to the NXT via the USB cable. The NXT reads the position and controls yaw-pitch on the two ‘neck’ motors to match.

Emily made the robot’s head from a small, plastic soft fruit punnet (the holes in the bottom fit just right onto the ends of LEGO struts) covered with kitchen tissue strips fixed with glue stick. Make-up is by washable marker pen.

MySQL Select 1 in N rows / every Nth row UDF

I wrote this MySQL UDF because I need to create sub-samples of time series data in a logging application, and I need to brush up on my MySQL UDF skills for a code review of some older UDFs. The function sample() takes a single argument which is the limit of its internal counter. The return value is the current value of the internal counter.

SELECT country_name, sample(3) AS sample FROM countries

would return a result like

country_name          sample
Andorra               0
United Arab Emirate   1
Afghanistan           2
Antigua and Barbuda   0
Anguilla              1
Albania               2
Armenia               0

You can select every one out of every 3 rows like this:

SELECT country_name FROM countries WHERE sample(3, country_name) = 0

The second argument to the function is not used by the function: it’s a hack to get MySQL to execute the function on every row.

[Update March 2015 – to compile on Ubuntu you need header files from the libmysqlclient-dev package)]

Compile the UDF (on Ubuntu) like this:

g++ -fPIC -I/usr/include/mysql -o libsample.so -shared sample.cpp

mv or cp libsample.so to /usr/lib/mysql/plugin/, link it to /usr/lib, run ldconfig and in MySQL enter:

CREATE FUNCTION sample RETURNS INT SONAME 'libsample.so';

Here’s the code:

/* sample(N) returns a value that cycles from 0 to N - 1
 add a column to use in a WHERE clause to sample 1 row
 from every 10:
 select name from user where sample(10, name) = 1;
 The column isn't used by MySQL, it's a hack to get MySQL
 to invoke the function on every row:
 19th May 2013, sean@firtl.com
 */
#ifdef STANDARD
#include <string.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include <my_global.h>
#include <my_sys.h>
#endif
#include <mysql.h>
#include <m_ctype.h>
#include <m_string.h>

#ifdef HAVE_DLOPEN

// http://dev.mysql.com/doc/refman/5.0/en/udf-calling.html
extern "C" {
	my_bool	sample_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
	void sample_deinit(UDF_INIT *initid);
	longlong sample(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
}

my_bool sample_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
	// http://dev.mysql.com/doc/refman/5.0/en/udf-arguments.html
	if (args->arg_count < 1)
	{
		strcpy(message, "Requires at least one argument");
		return 1;
	}
	else if (args->arg_type[0] != INT_RESULT)
	{
		strcpy(message, "Requires a number argument");
		return 1;
	}

  int* workspace = new int[2];

	initid->ptr = (char*)workspace;
	workspace[0] = *((long long*) args->args[0]);
	workspace[1] = 0;
	return 0;
}

void sample_deinit(UDF_INIT *initid)
{
	if (initid->ptr != NULL)
		delete [] initid->ptr;
}

longlong sample(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
	int* d = (int*) initid->ptr;
	(d[1])++;
	if (d[1] >= d[0])
		d[1] = 0;
	return d[1];
}

#endif /* HAVE_DLOPEN */