Combinatorial content by JavaScript

Home


Research


Music


Video


Programming


Text


Portfolio


Links


About me


The website in question

I'll explain how to make a web page which displays unique combinations of fragments of content, which means that similarly to Queneau's ten million poems, the page will assemble different combinations each time it is visited. Incidentally, this page itself is a static web page. No scripts here, only descriptions of how to write them.


Most of the web pages on this domain are static and use no scripting whatsoever. The only exception are the few pages that display mathematical formulae. Since I have had little interest in dynamic web pages, until quite recently, I had not bothered looking into JavaScript or any other languages for web scripting. But, in the spirit of my generative text program Peptalk, I started experimenting with a web page that would load random selections of text and images and create unique combinations every time it is loaded.

Having some background in C programming, the basics of JavaScript turned out to be surprisingly easy. The intricacies are in getting it to interact correctly with html and css.

In my very dynamic web page, almost every element is chosen randomly from a list and loaded by script. The trick for generating random integers and selecting items from a list is described in many tutorials and beginners' guides, but I'll include it here for completeness. Say you have a separate JavaScript file. In it, near the top, goes the following function declaration which will be called many times throughout the script.


function rnd(n)
{
	var xi = Math.floor(Math.random() * n) ;
	return xi;
}

This function returns random integers in the range 0 to n–1. In the html document, an element with an id tag can be replaced by a random element. Suppose we have a text paragraph, something like this:

<p id="will_be_replaced"> this text will be modified </p>

In the script file we define a function, let's call it replace().


function replace()
{
	var newtext = ["one phrase", "other phrase"] ;
	var x = rnd(newtext.length) ;
	document.getElementById('will_be_replaced').innerHTML = newtext[x] ;
}

The innerHTML works with text replacements, but if instead you wish to point a link to a random web page it looks slightly different. This example changes the text of the link as well as the address it points to. First, the relevant line in the html document:

<a href="javascript:websurf()" id="link_name">link text to be replaced</a>

In the script file, we define a websurf function which takes you to an undisclosed random location. Such link roulettes are perhaps not considered good practice since the destination is obscured and you will have to trust the website owner that they do not lead to anything nefarious.


function websurf()
{
	var address = ["https://example.com", "example.net", "http://weirdo.info"] ;
	var x = rnd(address.length) ;
	window.location = address[x] ;
}

The function to replace the link text is similar to the replace() function that modifies text inside of a paragraph, except in its last line.


function change_text()
{
	var linktext = ["silly link", "somewhere", "not here"] ;
	var x = rnd(linktext.length) ;
	document.getElementById('link_name').text = linktext[x] ;
}

In other words, instead of .innerHTML we use .text to access the element to be replaced.

Inserting text files and images

The first component I looked into was a text box which is filled with content from one of several plain text files written in various languages. For this I used the html <object> element to insert the plain text file.


<object id="postbox" type="text/plain;charset=UTF-8" data="" width="500" height="300">

Default text goes here (if content can't be displayed).
</object>

The empty data field will be filled with text from one of the input files. As I experimented with this at home, I had specified the parameter of type only as "text/plain", and everything worked fine. However, after I uploaded the files it turned out that the non-ascii letters of non-english languages turned into garbage, and it took some time to troubleshoot this. Obviously the character set should be utf-8, but that was already declared in the html head section. After trying various places to specify the character set of this object and after days of web searches, I finally found what ought to be the correct solution. It's just that it doesn't work on Firefox, although it does work on some other browsers.

The function that inserts a file into the object box is structurally similar to the other text replacement functions. Assuming that the text files are put into a directory called "textcatalog" it might look as follows:


function textbox()
{
	var textfiles = ["file1.txt", "file2.txt"] ; // actually many more files
	const tbox = document.getElementById('postbox');
	var x = rnd(textfiles.length) ;
	tbox.data = "textcatalog/" + textfiles[x] ; // string concatenation
}

For insertions of images into the web page I used the function document.write(), which simply injects html code at the specified point where it's called in the html document. The idea is simple enough, but it took me a few attempts to figure out that some escape sequences were necessary. Here all image files are placed in a directory named "pic" and the variable insertcode holds the html code that loads the chosen image. The + sign does string concatenation and the backslash is used for escape characters.


function insert_image()
{
	var im = ["img1.jpg", "img2.jpg"] ; // long list of small pictures
	var x = rnd(im.length);
	var insertcode = "<img src=\"pic/" + im[a] + "\" alt=\"arbitrary\" width=\"250\" height=\"250\"> " ;	
	document.write(insertcode) ;
}

In the html document, this is called at the appropriate location by <script>insert_image();</script>.

Finally, all the elements have to be loaded into the document at some point, as the cause of some action. Perhaps the cleanest way to do so is to load everything at once as the page itself loads. In the <head> section I include the JavaScript file, and then in the body section everything is loaded with <body onload="inject()"> where the function inject() collects and calls all the other functions. Hence it should be put at the bottom of the JavaScript file.


function inject()
{
	replace();
	websurf();
	change_text();
	textbox();
	// etc.
}

For even more variability, style elements such as the page colour and layout could be dynamically altered, but that's an experiment for another day. To see everything in action, visit the marvelous web page!