DEV Community

loading...
Cover image for alap - Menus For Links

alap - Menus For Links

Daniel Smith
Creative & Tech, web developer
・5 min read

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:

CleanShot 2021-05-06 at 20 09 10

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>,
Enter fullscreen mode Exit fullscreen mode

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"],
}
Enter fullscreen mode Exit fullscreen mode

When we click on "cars", we get a simple menu:

image

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"],
}
Enter fullscreen mode Exit fullscreen mode

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>. 
Enter fullscreen mode Exit fullscreen mode

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"],
    },
Enter fullscreen mode Exit fullscreen mode

From that, we might get a menu such as:

image

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>
Enter fullscreen mode Exit fullscreen mode

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

.alap_cars1 {
  /* change the font, colors, etc... */
}
Enter fullscreen mode Exit fullscreen mode

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",
  ],
},
Enter fullscreen mode Exit fullscreen mode

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

class="alapListElem violetclass"
Enter fullscreen mode Exit fullscreen mode

which will match a CSS Style Rule:

.violetclass {
  background-color: violet;
}
Enter fullscreen mode Exit fullscreen mode

Giving a result where we can style per-item

image

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"],
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

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",
  }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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

Discussion (0)