On J.R. Carpenter’s Gorge, Part 2.5: HTML, web pages, and the DOM

html-code-sample-news-template

It ain’t pretty, but it’s what the Web is made of.

This post is part of a series on digital literature. I’m dissecting the JavaScript code of “Gorge”, an infinite poem by J.R. Carpenter that riffs on Nick Montfort’s program “Taroko Gorge”.  The first post, which defines “variables”, “strings” and “arrays”, is here; the second, which explains “functions” and demonstrates how the program chooses randomly from a list of inputs (a.k.a. words), is here. This post is a brief primer on how web pages are written, how HTML works, and what a DOM is. It will help to know this stuff before we move on to Part Three: putting everything together.

As you probably know, web pages are written in a language called HTML (HyperText Markup Language), which consists of a bunch of elements. Elements are basically containers for bits of the page. (If you know anything about JavaScript, you may be thinking, “Hey, that sounds like an object.” You would not be wrong.) They can also be nested: like the branches of a tree, one element can have one or more “child nodes”, or elements that branch off from it.

As well as containing stuff, elements have attributes or characteristics. (If you know anything about JavaScript, you may be thinking, “Hey, that sounds like a property.” Again, you would not be wrong.) One common attribute is called “id”; we use IDs to mark bits of the page that the program is interested in. Because attribute values have to be unique, you can drop an ID into a section of the page and be certain that, when you instruct the program to look for that ID, it’ll take you to the right place. For example, if I wanted a way of quickly referring to a paragraph about Henry Fielding—and let’s say that’s located the top of the second paragraph in the third div of my web page—I might drop the ID “fielding” in there. It saves me from having to tell the program “look out for the top of the second paragraph in the third div”, which is a pain in the arse to write and also less natural, since no one (almost no one) thinks like that. (Also, when you restructure your piece, so that the Fielding paragraph isn’t the second one anymore, the “id” attribute “fielding” will still take you to the right place. Isn’t that convenient.)

The DOM, or Document Object Model, is a mapping from HTML to JavaScript: elements (in HTML) are mapped onto objects (in JavaScript). This allows your JavaScript programs to fiddle with your web page. Now, this may not bother you, but when it was first explained to me, it bothered me because it seemed inefficient. Why do you have to do that? Why can’t you just do things to your web page using HTML? Well, because HTML isn’t a programming language; it’s a markup language, which is like a fancy form of annotating (make this bit bold, make this bit bigger, put a hyperlink here). In order to change the contents of the page, you have to change stuff in the DOM.

Hopefully, this will have given you the vocabulary/conceptual tools to better understand the next post. In that, I’ll talk about how the code for “Gorge” manipulates the DOM to change how the poem appears on its web page.

Advertisements

Bookish and Not-So-Bookish Thoughts

tristan

Tristan (Stuart Skelton) and Isolde (Heidi Melton) at ENO

  1. Gadgette is a site aimed at techy women–like The Pool for geeks. I barely qualify, but I’ve been really enjoying their stuff, especially this article on 6 lessons to forget before you start learning to code.
  2. My parents and brother are in the country. We saw them last weekend, at my gran’s 80th birthday tea, and will see them again soon;  my brother is coming to London for a graduation-present dinner on Friday, and my parents are visiting on Saturday.
  3. It was great to see them and I’m looking forward to seeing them again, but trying to make plans to do so around the rest of my life is so.damn.stressful. I work full-time, so my only weekday options are in the evening. Plus, unfortunately, June is the month when everyone else wanted to plan stuff. Between last Wednesday and next Sunday I’ve had a grand total of three days with nothing penciled in, and those days don’t really coincide with my parents’ availability.  So there’s guilt on my side, frustration on theirs, and dissatisfaction everywhere.
  4. Relatedly, I’m really, really tired. I’ve already canceled one book event last week out of pure exhaustion, and I’m probably going to need to bow out of a dinner party this week as well. Mental health has also been suffering: I’ve developed a new strategy for when I want to self-harm which involves imagining it in great detail without actually doing it, or writing on my arm instead of cutting or scratching. It’s okay, but it’s not exactly a permanent fix. Mother-out-law has been in hospital this week, too, precise nature of ailment unknown. So now that I think about it, there’s been a reasonable amount of stress circulating.
  5. Women With Tattoos is another one of my new favourite sites–beautiful portraits of tattooed ladies, plus interviews. Through it, I’ve also found the woman who I want to do my first tattoo, if and when I get brave enough to follow through.
  6. I went to my first live Wagner performance last weekend: English National Opera is doing Tristan and Isolde (yes, in English; oh well.) It was five hours long and it was excellent; the band made some ravishingly beautiful sounds and Heidi Melton, who sings Isolde, is a new vocal inspiration. The costumes were weird (design aesthetic ranged from “Belle Epoque crazy hair” to “Japanese samurai face masks” to “Beckettian void”), but the singing made none of that matter.

Bookish and Not-So-Bookish Thoughts

st-ives-wide

    1. We booked a holiday! Oh my giddy aunt. We’re going to St. Ives for five days in August. It is stupidly expensive and long to get there by train, but who cares? We’re staying in a little flat in the center of town, and we won’t have to do anything all week but there’ll be plenty to do if we get bored. I plan to read and cook and sit in the sun. The Tate, the Barbara Hepworth Museum, and the seaside are all I want. Oh, and maybe some hikes.
    2. I’m still plugging away at JavaScript. I’m trying to do half an hour a day, but it’s hard and it makes me cry a lot (or, if not cry, at the very least wring my hands til my wrists feel loose). I wish it came more easily. This sounds, I know, ridiculously arrogant, but I am just not used to having to work hard at learning something. It fucks with my self-esteem no end.
    3. Saw my friend and former housemate Ollie on the weekend; we went to the National Portrait Gallery. I was especially interested in an exhibition showing photographic portraits of black migrants in England before the Windrush’s voyage in the 1940s. There were some from 1891, when an “African choir” came on tour to London and also visited Queen Victoria at Osborne House on the Isle of Wight; they looked so modern, staring straight out of the frame, the photographic techniques good enough by then to capture fine details of their clothing texture, skin and hair. There was another display case of smaller portraits, including some of a band of Pygmies who came to London in 1905, and one of an Ethiopian prince whose father committed suicide upon defeat by the British and who was brought back to England by a military commander called Tristram Speedy. He went to Rugby and to Sandhurst, but died of pleurisy at 18. Such curious, little-known lives.
    4. I bought a little chunky journal on Saturday, after bidding Ollie farewell but before getting the Tube back home. It’s grey with a flower pattern on the front, and only cost £3.99. It feels inviting, but unthreatening, and I like it very much. I’m hoping to re-establish the habit of journaling by hand. So far, it’s working.
    5. My novel carries on apace. I can’t say I write a thousand words a day, but I try to write a little bit most days. I’m slowly discovering what one of my characters is all about; he’s a surprisingly complicated chap, not entirely nice or passive. I’m also approaching a point at which I’m going to have to switch to writing about one of the other POV characters for a while. It stops me from getting bored or stuck in a rut.
    6. Now that the weather is sunny again, I am getting broody about dogs. There was a beautiful wrinkly brown shar pei in the park over the weekend which I literally couldn’t stop raving about. The Chaos asked me why I always have to like “the fugly ones”. It’s because they’re fugly. Fugly dogs are the most beautiful.
chinese_shar-pei_5445450

This will never NOT be perfect.

On J.R. Carpenter’s Gorge, Part Two: Choosing the Words

words1

This post is the second in a series on digital literature. I’m dissecting the JavaScript code of “Gorge”, an infinite poem by J.R. Carpenter that riffs on Nick Montfort’s program “Taroko Gorge”.  The first post, which defines “variables”, “strings” and “arrays”, is here.

At the end of the last post, I said that we would continue by looking at how to choose a substring from an array, and what happens from there. In order to understand how the program selects a substring, you have to understand something else first: what a function is, and how it works within a program.

It’s hard to meaningfully define a function in non-technical terms because it is so basic a thing that breaking it down further is difficult; at the same time, too vague a definition will be imprecise and therefore meaningless. The best I can do for you right now is to say that functions are basically chunks of code that, as the name might suggest, do something. When you call a function, you’re invoking the code in it. If similes are your thing, you could say that calling a function is like casting a spell: you can have the spell written down, but it doesn’t do anything until you bring it into existence.

Functions have names, arguments, and bodies. This is probably best illustrated by actual code:

 function rand_range(max) {
   return Math.floor(Math.random() * (max+1));
 }

The name of that function is rand_range, the argument that we pass to it is max, and the second line (beginning with the word return) is the body of the function. It is, in other words, what the function will do, when it is called, with the argument max. max, as you may have guessed by now, is just a variable representing a maximum value. If we say that max is 3, the function will execute with 3 taking max‘s place.

What does that mean, practically speaking? What will the function actually do when called? Its name should give you a clue: looking at something called rand_range, it’s a safe bet that it’ll have something to do with a random number that falls within a predetermined range. Add the fact that the argument has been named max, and you can further guess that the value of max represents the top end of that predetermined range. Now all you have to contend with is Math.floor and Math.random. Math.floor is a function (functions can call each other) that returns the largest integer less than or equal to a given number (in this case, max); Math.random returns a pseudo-random (which is to say, more or less random for most purposes but not strictly random, since that’s pretty hard to achieve) integer between 0 (inclusive) and 1 (exclusive). You can scale that up or down; in the event that max is 3, as I suggested earlier, Math.random returns an integer between 0 and 3, not including 3. This is why the function includes (max + 1), which extends our range by 1, allowing us to include 3.

The next function is called choose. It exists in order to produce a random selection from the arrays that we discussed earlier, the ones like above (“appetite, brain, craving, desire”), below (“aroma, bladder, blood vessel, bowl”), and trans (“agitate, attract, bite, boil”). choose looks like this:

 function choose(array){
   return array[rand_range(array.length-1)];
 }

When you insert the name of an array—let’s say above[rand_range(array.length-1)] selects a random value from that array. (The -1 bit is there because the first thing in an array is denoted Thing 0. Computers like to start counting at 0. So -1 just means that you get the whole range of the array from the first (zeroth?) item to the last.) Then return array returns the index that’s been selected. So if we were to do this with above, the index might be, e.g., 3, which would return ‘digestive juice’ (since we’re counting from 0, remember!)

The next function is where we start to get into the actual construction of the poem, and it’s followed by two other functions that are very similar. These functions haven’t been renamed since their inception as part of Taroko Gorge, so they may at first glance appear irrelevant to the content of Gorge, but they’re doing the right things. There’s a section in the middle of this first function that doesn’t work in Gorge, which you’ll probably be able to spot straight away. It doesn’t do anything bad; it just doesn’t get evaluated.

 function path() {
 var p=rand_range(1);
 var words=choose(above);
 if ((words=='forest')&&(rand_range(3)==1)){
   words='monkeys '+choose(trans);
 } else {
   words+=s[p]+' '+choose(trans)+s[(p+1)%2];
 }
 words+=' the '+choose(below)+choose(s)+'.';
 return words;
 }

And breathe.

var p is defined as rand_range(1), which we know means “a random whole number between 0 and 1”. Practically speaking, that means “either 0 or 1”. We don’t know what we’ll be doing with var p yet, so we’ll just put that away for later use.

var words=choose(above), as we know from our adventures with choose(array) previously, means that words is set to a random selection from the list of words in the array above.

The if statement says that if the value of words happens to be “forest”, and if the rand_range value is 1 (with the max value defined as 3, so the value could be 0, 1, 2 or 3), then “forest” will be replaced with the word “monkeys” and a random selection from the transarray. Since we don’t have the word “forest” in any of our arrays, this piece of code will actually never be used. It’s a leftover from Montfort’s original version.

else means “otherwise”, so this is where we can start paying attention again: if the conditions of the if statement are not met (and they won’t be), this is what will happen next.

words+=s[p] is a random pluralizer. It takes a var from earlier up in the program, which I realize now I may have skated over somewhat in the first post. This is s, which is defined as 's,'.split(','). What this means is that s is actually another array, split on its comma, so that the array consists of the letter ‘s’ and nothing, known in programming as ‘the empty string’. Therefore, words+=s[p] means that when p=0, s will be added on to the end of whatever value we got from words. (words+=s[p] is a short-hand for words=words+s[p]. “Adding” a string means that it is glued on to the end of whatever comes before.) As we start counting from 0, that means a letter ‘s’ will be added, making the word plural. When p is 1, the second element of the array s will be added to the end of words, which in this case means nothing at all.

After this will come a space (signified by ' '), no matter whether the value of var words has been pluralized or not. Then a word will be selected from the trans array, which will be pluralized half of the time. This is signified by (p+1) % 2, where % means “the remainder after division by”. Cast your mind back to elemento-primary school! When p is 0, we get 0+1, which is 1, and the remainder of 1 divided by 2 is 1. We’ll add element 1 of array s again, which is empty string. When p is 1, we get 1+1, which is 2, and the remainder of 2 divided by 2 is 0, so we’ll append the first element of array s (remember, the first element is element 0!), which is the letter ‘s’.

The final section has the addition of the word ‘the’ to whatever comes out of words, a random selection from the array below, a random selection from the array s (another choice between pluralizing or not), and the addition of a full stop. return words is the piece of code that will actually return the value for function path(), when it’s called.

More next time, including a couple of other functions that select words from arrays using different criteria, and the beginnings of how the program fits all of these functions together to produce the poem itself.

On J.R. Carpenter’s “Gorge”, Part One: String Theory

intestines

There’s this thing called digital literature. To those of us with a disposition to love physical books, their material essences, the phrase can be alienating, disturbing even. It makes me think of some immense ethereal database, to which novels and poems and plays can be hooked and uploaded, a Matrix of the creative mind. It doesn’t, in those terms, sound particularly appealing, but rather like a vast, crammed forest. It sounds like somewhere you could get lost—not in the exciting, carefree, sight-seeing way, but more in the “oh God this industrial wasteland is nowhere near our hotel and also it’s raining” sort of way.

Fight this fear. Digital lit is really, really neat, not least because it’s so much less interested in uploading Madame Bovary to the Cloud than it is in finding out completely new ways of creating things with words, using technology and programming languages as tools to assist in the endeavour. I’m going to be writing a series of posts exploring one instance of digital literature, breaking it down into its source code, looking at that code, assessing how it works, and finally deciding what it’s worth as literature. If you have never seen computer code in your life before, I urge you not to navigate away immediately; until this summer, I’d never had a proper look either, so I promise you that everything will be explained for the layman, clearly and accurately. (I live with a real live computer scientist, who checks all of these posts for accuracy.) Plus, the possibilities for what you can do with code are literally infinite—it’s expressed in languages just like literature is—so it’s worth your while to know something about what can be done with it.

In 2009, Nick Montfort wrote a program that created a neverending poem called “Taroko Gorge“. (Do you see what I mean about these things being really neat? A neverending poem! Holy shit!) You might think that this would require a great deal of complicated and arcane mathematics and large word banks upon which to draw—not a bit of it. Such are the joys of combinatorics that you don’t actually need very many resources in order to create a large number of variations. It’s likely that, given some complicated and arcane mathematics and large word banks, you could create a more complex, nuanced and interesting neverending poem, and this is a notion worth exploring, but we’ll get to that later. For now, let’s look at the code.

The code I am going to look at here actually belongs to an adaptation of Montfort’s program by a poet and programmer called J.R. Carpenter. (She’s commented on this post, so check out her comment below!) I came across it while looking at a zine called Hack Circus, which I’d recommend wholeheartedly. They describe themselves as an artistic collective interested in “the entertaining and engaging side of inventive thought, whether that manifests physically with wires and batteries, or conceptually in artistic or philosophical ways”—or, as their website tagline succinctly puts it, “fantasy technology and everyday magic.” It’s a playground for the imagination; every article is a jumping-off point for something fascinating and bizarre.

Carpenter calls her iteration of the work “Gorge“. You’ll realise why when we start to look at her inputs: the poem that “Gorge” produces is, yes, about the body and its processes, while the poem generated by “Taroko Gorge” is about the natural world and has a serene, secluded feel to it. But that’s nothing to do with the structures of either poem; it’s entirely down to the words. If you look at their skeletons, these two poems are built the same way, and I’m just not sure that structure should be irrelevant to two poems with completely different emphases. It’s as though Allen Ginsberg’s “Howl” and Marlowe’s “Come live with me and be my love” were written in the same meter and idiom.

On the other hand, both “Leda and the Swan” and “The Windhover” are sonnets about birds, and they still manage to capture their own very different essences in similar forms. (On the other other hand, “The Windhover” is extremely cavalier about meter. You could keep having this argument forever.)

So, Carpenter’s code starts like this:

var t = 0;
var n = 0;
var paths = 0;
var above = 'appetite, brain, craving, desire, digestive juice, enzyme, gaze, glaze, gorge, gullet, head, incisor, intellect, jaw, knowledge, language, maw, mandible, mind, molar, muscle, mouth, nose, sight, smell, spit, sweat, spirit, thirst, throat'.split (',');
var below = 'aroma, bladder, blood vessel, bowl, bowel, crust, dip, dressing, film, gut, lip, lower lip [etc etc]'.split (',');
var trans = 'agitate, attract, bite, boil, braise [etc]'.split (',');
var imper = 'become, confuse, cut, decant, enter [etc]'.split (',');
imper = imper.split (',');
var intrans = 'absorb, age, assimilate, balance [etc]'.split (',');
var s = 's,'.split (',');
var texture = 'acrid, barely perceptible, cautious [etc]'.split (',');

In JavaScript, the programming language that this code is written in, var introduces a variable. A variable in programming is just a thing that gets assigned a value. We’ll worry about var t, var n, and var paths later; we don’t have enough information about them right now to assess them meaningfully, other than to note that they have all been assigned a value of 0. What we do have is a large amount of information about the other variables, all of which seem to have been assigned multiple different values. But if you scroll to the right, you’ll see that the whole shebang—all of the words associated with, say, var above—are within one set of quotation marks. And what that makes them is one value, because they’re a string. A string is everything inside a set of quotation marks, which all gets lumped together and treated as one. So, for instance, ‘appetite, brain, craving, desire’: the program will treat that list of adjectives as one value for our variable, unless told otherwise. What tells it otherwise is the piece at the end of each line, .split (',').

What .split (',') does is split up the string (hence the name; everything in programming has or should have an eminently reasonable name) into an array of substrings. The advantage of writing like this is that it prevents the programmer from having to type out a whole bunch of quotation marks (like, ‘appetite’, ‘brain’, ‘craving’, ‘desire’ and so on). The advantage of making an array of substrings, instead of one massive string, is that now, in theory, we can choose any one of those substrings to be the value of our variable above.

Next up: How we choose a substring, and what happens after that.