Skip to content

Overview

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

Level


A level is represented by rows of inline <div>s (cells) inside the #view node,
it is created through the renderView function. Each cell has an onclick handler,
which passes the event object to the tool property 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 char is a single character string
that determines how the targeted cell's textContent and style.backgroundColor
attributes should be altered.

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 color will be
looked up in the PALETTE constant and set as the cell's background color.

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 is powered by the scanline flood fill algorithm.

Undo/Redo

A simple array-wrapping HistoryStack class is used 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: {cells: [cell0, cell1, ...], char: char}.

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, and its handler 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 but with the char value switched.

When the past stack 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
and dialog boxes is abstracted, while other UI elements are either present in the
initial HTML template, or created dynamically through simple DOM manipulations.

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;        /* the cursor (and the text as well) is now invisible */
  text-shadow: 0 0 0 white;  /* but a shadow with no offset is drawn for the 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