Skip to content

Overview

misha-codes edited this page Mar 10, 2018 · 10 revisions

Level


A level is represented by rows of inline divs (cells) inside the #view node,
it is created through the renderView function. Each cell has an onclick listener,
which alters the cell or cells' textContent and backgroundColor attributes
based on the current properties of the mouseTool object.

Editing


The mouseTool holds two properties: tool and char. The tool is an event
handler which first determines whether its associated action can be performed,
and if so, performs the action.

The lowest-level function responsible for editing a cell is applyEdit, which
takes a cell and a character. Whenever a user edits a cell, the tool will
call applyEdit and pass the mouseTool's char value to it. The cell's new
text content will be set to the char, and its corresponding background color
will be looked up in the PALETTE constant.

Palette

The PALETTE object holds every available character and associates a color
and a short description with it, for example:
'+': {color: 'rgb(255, 100, 100)', help: 'lava'}

Tools

Similarly, the TOOLS array holds all of the available tool functions. It also
stores an icon name which will be assigned to the tool's selection button in the UI.

Two tools are implemented: a brush which simply edits a cell through applyEdit
and a fill tool which implements a scanline flood fill algorithm.

Undo/Redo

A simple array-wrapping HistoryStack class serves to store information about
edited cells. Each record in the stack property of HistoryStack is an object
which holds an array of cells altered by an action and a character value to which
they should be restored.

The reason for introducing a custom class was the need to be able to allow
interaction between a stack and a UI element through event handling.
Every time a method which alters the stack, such as pop is called, a custom
historyupdate event is dispatched to the document, which handles it and alters
the state of undo and redo UI buttons accordingly.

To simplify moving through history states there are two instances of HistoryStack:
past and future. Every time a user makes an alteration to the level, the
future stack is emptied and a history record is pushed to the past stack.

When undo or redo is called, a record is popped from a corresponding stack,
and the cells in it are looped through and restored to the previous state by
applyEdit using the character in the record.
The opposite stack receives a new record that holds the same list of cells
and their prior textContent.

When the past grows too large, older records are removed by calling the drop method.

UI


Toolbar

Storing palette and tool values in objects, allows looping through them to easily
create as many corresponding UI buttons on the fly as needed. Creation of buttons
is abstracted by the createButton function, while other UI elements are either
present in the initial HTML template (see index.html), or created dynamically
through simple DOM manipulation.

As there are only two mouse tools in this editor, and it's not likely that more
will be implemented, not to clutter the layout, undo and redo buttons are
attached to the same node, though their function is different from that of the
mouse tools.

Undo and redo buttons get enabled and disabled as the document
tracks the historyupdate events.

Menu

New

Clicking this will append a span.dialog element to the menu,
containing two <input> fields and two buttons, dialogYes and dialogNo.
The former will attempt to call renderView with the input as parameters, while
the latter will remove the <span> from the document.

Open

This will similarly create a <span> element with the dialog class, but with
a single <textarea> for user input. Clicking dialogYes will first determine if
the string can be interpreted as a grid (i.e. consists of lines of equal length),
then call renderView, with the calculated grid measurements and will loop through
the characters in the string, trying to call applyEdit with the current character
and the corresponding cell. If a character is not present in PALETTE, and an error
message will be displayed in the info <textarea> at the bottom of the toolbar.

Copy

Clicking the copy button will call a copyLevel function, which will loop through
the cell divs and append their textContent to an output string, additionally appending
a newline after every row. The following trick is used to hand out the string to
the user.

The info's textContent is set to the output string, then selected,
copied to clipboard and finally removed from the info. Like this:

info.textContent = level;
info.select();
document.execCommand('Copy');
info.textContent = 'level copied to clipboard';

The user can then paste the string into their text editor to use with their program.

Info

A <textarea> where information about actions and UI elements appears. It was
initially used to display the level as a string, but as seen above it no longer
does that directly. The following css rules are used to hide the cursor, preserve
newlines for copying and prevent resizing:

.info {
  resize: none;
  white-space: pre-line;
  color: transparent;        /* text (and cursor as well) is now hidden */
  text-shadow: 0 0 0 white;  /* but a shadow with no offset is drawn for text*/
}

Icons

The icons are Google's material icons, currently displayed as an icon font and are
linked in the <head> of index.html.

Clone this wiki locally