alap — Menus For Links

Daniel Smith
6 min readMay 14, 2021

--

(imported from original article @ dev.to — better formatting in that version)

Overview

Since the dawn of the web, an HTML link is known to lead to one target. I’ve always thought (since the early 90’s) that was somewhat limiting. What if we could provide more choice?

Alap is a JavaScript package that provides a flexible way to attach menus to links. A JSON object defines an id for each possible link target. Within your HTML, anchors refer to one or more ids. Alap does the work of building up a menus.

Github: DanielSmith/alap

Here is a quick idea of the result:

Big Picture of what is possible…

  • link labels and targets are not hardwired in HTML
  • menus are dynamically generated from matched ids and tags
  • custom css can be applied on a per-menu, and, per-item basis
  • simple expressions: can combine ids and tags with AND, OR, and WITHOUT operations
  • menus dismiss themselves with a timeout, or you can click outside them (or hit escape)

Simple Example

The simplest example is for an HTML anchor to refer to a couple of list element ids.

On the HTML side, that looks like:

I like <a id="cars1" class="alap"
data-alap-linkitems="bmwe36, vwbug">cars</a>,

Alap refers to an object (presumably created from a JSON object from some server call), to find the matches:

bmwe36: {
label: "BMW (E36) - Wikipedia",
url: "http://en.wikipedia.org/wiki/BMW_3_Series_(E36)",
tags: ["e36m3", "bmw", "car", "germany"],
},
vwbug: {
label: "VW Bug",
url: "http://en.wikipedia.org/wiki/Volkswagen_Beetle",
tags: ["vw", "car", "germany"],
}

When we click on “cars”, we get a simple menu:

So far, we’ve mentioned two types of IDs:

  • the HTML DOM ID (such as “cars1”)
  • the property IDs in a JavaScript object (such as “bmwe36” and “vwbug”)

I think of the JavaScript side as “list item IDs”

We could just stop there and have enough to use on a page. Alap is something that potentially transforms writing style — you can write something brisk such as “I can’t wait to travel to my favorite cities”, and have a menu of 10 cities. You don’t have to spell out every last detail in main text.

Using Tags

You probably noticed the tags field in a list item object definition:

vwbug: {
label: "VW Bug",
url: "http://en.wikipedia.org/wiki/Volkswagen_Beetle",
tags: ["vw", "car", "germany"],
}

How are these used?

Let’s say we are interested in all of the links we have for a few cities: Sydney, NYC, and London:

<a id="nycsydlon" class="alap"
data-alap-linkitems=".sydney, .nyc, .london">Sydney, NYC, and London</a>.

This can be thought of much like CSS Classes: We want to match list items that have a tag of “sydney”, “nyc”, or “london”. Here is very edited chunk of list items that would match:

brooklynbridge: {
label: "Brooklyn Bridge",
url: "http://en.wikipedia.org/wiki/Brooklyn_Bridge",
tags: ["nyc", "bridge", "brooklyn", "manhattan"],
},

manhattanbridge: {
label: "Manhattan Bridge",
url: "http://en.wikipedia.org/wiki/Manhattan_Bridge",
tags: ["nyc", "bridge", "manhattan"],
},

sydneyoz: {
label: "Sydney, Australia",
url: "http://en.wikipedia.org/wiki/Sydney",
tags: ["australia", "sydney", "city"],
},

sydneybridgeclimb: {
label: "Sydney Harbour Bridge Tour",
url: "http://www.bridgeclimb.com",
tags: ["australia", "sydney", "tour"],
},

sydneybotanical: {
label: "Sydney Botanical Gardens",
url: "http://www.rbgsyd.nsw.gov.au/",
tags: ["australia", "sydney", "park"],
},

londontowerbridge: {
label: "London - Tower Bridge",
url: "http://en.wikipedia.org/wiki/Tower_Bridge",
tags: ["london", "city", "bridge"],
},

londonhyde: {
label: "London - Hyde Park",
url: "http://www.royalparks.gov.uk/Hyde-Park.aspx",
tags: ["london", "city", "park"],
},

From that, we might get a menu such as:

Custom CSS

There are two CSS areas that are easy to customize with alap:

  • the menu itself
  • an individual list item

the alapelem div

The container for the alap menu is a div with the id of alapelem

It also sets a class named alapelem

It also picks up a class that is named from the anchor that was clicked. Example:

<!-- here is our anchor -->
<a id="cars1" class="alap" data-alap-linkitems="bmwe36, vwbug">cars</a>

<!-- the anchor id of "cars1" gives us a class of "alap_cars1" -->
<div id="alapelem" class="alapelem alap_cars1">

This means that in our CSS Styles, we could do something special for a specific menu:

.alap_cars1 {
/* change the font, colors, etc... */
}

Per-Item override

We can also target CSS for an individual list item. This is done by using the cssClass property in a list item definition:

kittyatola_yt: {
label: "Kitty - Atola Visuals (YouTube)",
url: "https://www.youtube.com/c/atolavisuals/videos",
cssClass: "violetclass",
tags: [
"atolavisuals",
"lapeople",
"cinematography",
"video",
"photography",
"techreview",
"youtube",
],
},

In turn, that particular list item generates an extra class (besides alapListElem):

class="alapListElem violetclass"

which will match a CSS Style Rule:

.violetclass {
background-color: violet;
}

Giving a result where we can style per-item

Overall Config File, And Settings

Before diving into settings, let’s see the overall structure of the Config file:

  • settings
  • macros
  • allLinks
export const alapConfig = {
settings: {
listType: "ul",
menuTimeout: 5000,
},

macros: {
cars1: {
linkItems: "vwbug, bmwe36",
config: {
somekey: "somevalue",
},
},
},

allLinks: {
vwbug: {
label: "VW Bug",
url: "http://en.wikipedia.org/wiki/Volkswagen_Beetle",
tags: ["vw", "car", "germany"],
}
}
};

Global Settings

As you can see, we have two possible settings at the global level:

  • listType — ol or ul for ordered, or unordered list
  • menuTimeout — time in ms, before menu dismisses itself (if you mouse away)

Macros

Throughout this article, We have been referring to list item definitions within the allLinks object. The other main item in the Config is macros.

Here is a sample:

cars1: {
linkItems: "vwbug, bmwe36",
config: {
somekey: "somevalue",
}
}

For the moment, the config section within a macro is not being used.

A macro is referred to in an anchor definition via the @ character. Example:

<a id="cars1" class="alap" data-alap-linkitems="@cars1">cars</a>

What is the benefit of using a macro?

A macro lets you say “in my HTML, don’t hardwire specifics about the menu I want. Go look it in up in the Config. Grab it from the linkItems field there".

As a convenience, if you just specify “@”, the macro will get its name from the id of the anchor tag. Example: id="germanbeer" data-alap-linkitems="@" would be like specifying the macro as "@germanbeer"

Simple Expressions

Simple expressions let us do AND, OR, and WITHOUT operations.

Note: using | for OR is much like a list of comma separated items (nyc, bridge). I include the | operator to be more complete in what one would expect from expressions.

Expressions can be built up. You can say something like “Show me the links for all of the bridges you know of, but toss out the ones from NYC and London”:

.bridges - .nyc - .london

Summing Up For Now

Photo by Joshua Hoehne on Unsplash

This gives a brief look at what alap does. It’s a means of attaching menus to links. Since we use a JSON object to define our labels, link targets, tags, and more, we gain a lot of runtime flexibility. Anchors become a placeholder that express “this is what I want”, and alap builds a menu based on the data available.

Originally published at https://dev.to on May 14, 2021.

--

--

Daniel Smith

codes/writes, LAMP / MEVN / MERN, loves film, music, and bantering - I am available for projects — javajoint [at the domain of] gmail [which is a dot] com