7GUIs

7GUIs is a programming benchmark to compare implementations in terms of their notation.

Essential:

github.com/getify/You-Dont-Know-JS

Description:

7GUIs, also known as 7 Graphical User Interfaces, stand as a diligent comparison between diverse approaches to GUI development. This specific benchmark defines seven tasks that represent typical challenges in GUI programming; in addition, it provides a recommended set of evaluation dimensions, as identifying and propagating better approaches to GUI programming (ultimately pushing programming further) is not an easy task.

In this case, we will use vanilla HTML, CSS, and JavaScript for each task - and try our best to survive all of them.

Table of Contents

  1. 1. Counter
  2. 2. Temperature Converter
  3. 3. Flight Booker
  4. 4. Timer
  5. 5. CRUD
  6. 6. Circle Drawer
  7. 7. Cells

1. Counter

Challenge

Understanding the basic ideas of a language (or toolkit).

Criteria

    ▪ Build a frame containing a label or read-only textfield and a button.

    ▪ Initially, the value in the textfield is 0.

    ▪ Each click of the button increases the value in textfield by 1.

Counter serves as a gentle introduction to the basics of the language, paradigm, and toolkit for one of the simplest GUI applications imaginable. Thus, Counter reveals the required scaffolding and how the very basic features work together to build a GUI application. A good solution will have almost no scaffolding:

Demo:

Although this example has been adjusted to this site’s needs, here’s how we could achieve a similar result with plain JavaScript.

First, let’s introduce the HTML section and its corresponding styles for a simple counter:

Example:

Now, let’s focus on the JavaScript part, which we’ll keep as simple as the rest:

Example:


2. Temperature Converter

Challenge

Bidirectional data flow, user-provided text input.

Criteria:

The task is to build a frame containing 2 textfields representing the temperature in Celsius and Fahrenheit.

    ▪ Initially, both textfields are empty.

    ▪ When the user enters a numerical value into a textfield, the corresponding value in the other is automatically updated.

    ▪ When the user enters a non-numerical string into a textfield, the value in the other is not updated.

    ▪ Celsius to Fahrenheit formula F = C * (9/5) + 32.

    ▪ Fahrenheit to Celsius formula: C = (F - 32) * (5/9).

Temperature Converter increases the complexity of Counter by having bidirectional data flow between the Celsius and Fahrenheit inputs and the need to check the user input for validity. A good solution will make the bidirectional dependency very clear with minimal boilerplate code.

Demo:

Let’s see what happens now when it comes to the HTML and CSS part:

Example:

And the JavaScript logic behind it:

Example:

Now, coffee break before we keep going!


3. Flight Booker

Challenge

The simplification of using textfields for date input instead of specialized date picking widgets.

Criteria

The task is to build a frame containing a combobox with two options (“one-way flight” and “return flight”), two textfields representing the start and return date, and a button for submitting the selected flight.

    ▪ The return textfield is enabled if the combobox’s value is “return flight”.

    ▪ When the “return flight” date is strictly before time or wrong-formatted, it’s not possible to submit.

    ▪ When submitting, a message is displayed informing the user of their selection.

    ▪ Initially, the combobox has the value “one-way flight”, and both textfields have the same (arbitrary) date. It is implied that the return textfield is disabled.

The focus of Flight Booker lies on modelling constraints between widgets on the one hand, and modelling constraints within a widget on the other hand. Such constraints are very common in everyday interactions with GUI applications, and a good solution for Flight Booker should make the constraints clear, succinct, and explicit in the source code, not hidden behind a lot of scaffolding.

Demo:

Now, let’s delve into the HTML section and its corresponding styles:

Example:

Now, as for the JavaScript part, let’s keep it simple:

Example:


4. Timer

Challenge

Concurrency, competing user/signal interactions, responsiveness.

Criteria

In this case, we have to build a frame containing a gauge for an elapsed time. It will incorporate:

    ▪ A label which shows the elapsed time as a numerical value.

    ▪ A slider by which the duration of the timer can be adjusted while the timer is running.

    ▪ A reset button.

When it comes to certain functionalities, we can’t forget that:

    ▪ Adjusting the slider must immediately reflect on the duration and gauge.

    ▪ When the elapsed time ≥ duration, the timer stops (full gauge).

    ▪ If the duration is increased (meaning that duration > elapsed time), the timer starts to tick until elapsed time ≥ duration again.

    ▪ Clicking the reset button will reset the elapsed time to zero.

Timer deals with concurrency in the sense that a timer process that updates the elapsed time runs concurrently to the user’s interactions with the GUI application. Also, the fact that the slider adjustments must be reflected immediately tests the responsiveness of the solution, forcing us to make it clear that the signal is a timer tick.

Demo:

As always, let’s try it with not much scaffolding involved. HTML and CSS time:

Example:

Now, let’s check the JavaScript implications:

Example:


5. CRUD

Challenge

Separating the domain and presentation logic, managing mutation, building a non-trivial layout.

Criteria

In this case, we’ll build a frame containing prefix, name, and surname textfields (with labels), a list box, and buttons allowing to create, update, and delete the data.

List box:

    ▪ The list box will present a view of the data in the database that consists of a list of names.

    ▪ At most one entry can be selected in the box at a time.

Textfield:

    ▪ By entering a string into the prefix textfield, the user can filter the names whose surname start with the entered prefix.

Buttons:

    ▪ Clicking the create button will append the resulting name from concatenating the strings in the name and surname textfields to the list box.

    ▪ The update and delete buttons are enabled if an entry in the list box is selected.

    ▪ In contrast to the create button, the update button will not append the resulting name but instead replace the selected entry with the new name.

    ▪ The delete button will remove the selected entry.

CRUD (Create, Read, Update, and Delete) represents a typical graphical business application. The primary challenge is the separation of domain and presentation logic in the source code that is more or less forced on the implementer due to the ability to filter the view by a prefix.

What matters the most here is that the approach to managing the mutation of the list of names is tested, and a good solution should have a clear separation between the domain and presentation logic without much overhead, a mutation management that is fast but not error-prone, and a natural representation of the layout.

Demo:

Let’s see how to achieve it by starting with the HTML and its according styles:

Example:

Now, the JavaScript part could look somehow like this:

Example:


6. Circle Drawer

Challenge

Understanding the basic ideas of a language/toolkit.

Criteria

With Circle Draw, we will have to build a frame containing an undo and redo button, as well as a canvas area.

Let’s take into account, however, the following requirements:

    ▪ Left-clicking inside an empty area inside the canvas will create a circle with a fixed diameter.

    ▪ Right-clicking a selected circle will make a popup “Adjust diameter” menu appear.

    ▪ Clicking on “Adjust diameter” will open another frame with a slider that adjusts the diameter of the selected circle.

    ▪ Closing this frame will mark the last diameter as significant for the undo/redo history.

    ▪ Clicking undo will remove the last significant change.

    ▪ Clicking redo will reapply the last undoed change.

Circle Drawer’s goal is, among other things, to test how good the common challenge of implementing an undo/redo functionality for a GUI application can be solved. Moreover, Circle Drawer tests how dialog control (the challenge of retaining context between successive GUI operations) is achieved in the source code.

Demo:

If it sounds simple enough, let’s get started with some HTML and CSS:

Example:

Now, the logic behind it:

Example:


7. Cells

Challenge

Change propagation, widget customization, implementing a more authentic/involved GUI application.

Criteria

Now, we will create a simple but usable spreadsheet application. How? Following these requirements, of course:

    ▪ The spreadsheet should be scrollable.

    ▪ The rows should be numbered from 0 to 99, and the columns from A to Z.

    ▪ Double-clicking a cell showing a formula’s result should allow the user to change such formula.

    ▪ After having finished editing, the formula is parsed, evaluated, and its updated value is shown.

Cells is a more authentic task that tests if a particular approach also scales to a somewhat bigger application. The two primary GUI-related challenges are intelligent propagation of changes and widget customization. Admittedly, there is a substantial part that is not necessarily very GUI-related, but that is just the nature of a more authentic challenge! Finally, the domain-specific code should be clearly separated from the GUI-specific code, and the resulting spreadsheet widget has to be reusable.

Demo:

Curious about how to code something similar? Let’s start with the HTML and CSS wombo-combo, then:

Example:

And the JavaScript chunk of code:

Example:

As for the possible formulas, here’s some insight on it (note that , implies two specific cells, while : implies an entire range of them):

FormulaExampleDescription
Sum=SUM(B2:B3)Calculates the sum of a range of cells.
Subtract=SUBTRACT(A2, B2)Subtracts one value from another.
Multiply=MULTIPLY(A2, B2)Multiplies two values.
Divide=DIVIDE(A2, B2)Divides one value by another.

Feel free to share with me your own version of the 7GUIs - and happy coding! 🚀

All Notes: