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"><ul>
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
orul
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.
operator | description | example | meaning |
---|---|---|---|
+ | AND | .nyc + .bridge | items tagged with nyc AND bridge |
⏐ | OR | .nyc ⏐ .bridge | items tagged with nyc OR bridge |
- | WITHOUT | .nyc - .bridge | items tagged with nyc, WITHOUT a tag of bridge |
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
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.
Photo by Joshua Hoehne on Unsplash
Top comments (0)