The Making of Wall of Text

Louis Stowasser
2 min readNov 12, 2014

--

Wall of Text.co is a multiplayer note-taking app for purists. Collaborate on an infinite canvas of text, kind of like a whiteboard.

The power of anonymous speech (/reddit wall)

Genesis

The inspiration for Wall of Text.co came from a web app called yourworldoftext.com. I liked the concept of an infinite grid of text for general note-taking and brainstorming, like a whiteboard. Click anywhere and start typing. Though yourworldoftext.com wasn’t built for such purposes so I decided to build one that was; with colors!

Technical Details

Front End

Text is grouped together as “blobs” rather than a grid of characters. Blobs have a position on the grid which is translated to a position on the screen. The grid dimensions are the size of one mono-space character at 14px which turned out to be 8.39px wide and 14px high.

Text blobs are rendered as a <PRE> element with position: absolute and the screen position set to the CSS left/top properties.

Scrolling is done with a CSS transform (translate(x, y)) on the parent <DIV> that contains all the blobs. This makes it essentially infinite. No chunking necessary. All blobs in a wall are downloaded when the page loads.

Selecting a blob at a specific index in the text proved to be one of the bigger challenges. There is nothing in the click event object that tells you the string position in a DOM element. I accomplished it by splitting the text into <SPAN> elements by spaces and newlines. The <SPAN> that was clicked will be eventData.target. I could find the index of the <SPAN> by summing all preceding <SPAN> lengths.

So now we have the index of the word but a user could click in the middle of a word. To find the index relative to the word we can use eventData.clientX and subtracting it by the position of the <SPAN> (which we can get from span.getBoundingClientRect()). Once you get the result and divide it by grid width (8.39) you have the offset within the word, add it together and we know the index in the blob where the user clicked.

Back End

A blob is given a unique-ish ID and is stored as a JSON string in redis using:

hset wall:<wallName> <blobID> <blob data>

To return all the blobs for a wall:

hgetall wall:<wallName>

Real-time communication is done through socket.io using the room feature.

Community Response

Once it was on HN it quickly turned into an interactive art piece with all sorts of offensive comments and ASCII collages as you can see in the screenshot above. Unintended function is always a nice surprise.

Have a play with Wall of Text at http://walloftext.co

--

--

Louis Stowasser

I like all things JavaScript and HTML5. I am the creator of Crafty, @AcademicKarma and work for Mozilla.