Alexander Gromnitsky's Blog

Hyperlinks without <a> & JavaScript

Latest update:

This tweet, written for leetcode champions,

@jacobmparis · Jun 15

Senior developer quiz:

using ONLY html, and NO javascript

make a link that will navigate to another page

got me thinking: what are the most silliest ways of doing it? Here I present 6 professional approaches, where 5 of which work in modern browsers, & 1 in legacy user-agents.

The spec:

  • no HTML <a> element;
  • no JavaScript;
  • must render inside a web page;
  • a hyperlink should be blue, underlined & h/v centered inside a viewport.

No JS rules out any WASM solutions, for the latter requires the former for bootstrapping.

Forms

The twitter thread has a similar example, & I like it for its clarity:

<!doctype html>
<form action="https://sigwait.org">
  <input type="submit" value="oh noes">
</form>
<style>
  body { margin: 0; display: grid; place-items: center; height: 100vh; }
  input {
    border: 0;
    text-decoration: underline;
    color: blue;
    background: inherit;
    cursor: pointer;
  }
</style>

This is how the page renders in an iframe:

Ain't it grand.

Map

The variation of this is also present in the twitter thread. HTML 3.2 (1997) niceties still rock:

<!doctype html>
<div>
  <map name="hyperlink">
    <area shape="default" href="https://sigwait.org" alt="omglol">
  </map>
  <img usemap="#hyperlink" alt="omglol" src="hyperlink.png">
</div>
<style>body{margin:0;display:grid;place-items:center;height:100vh;}</style>

SVG

Now we begin with what I didn't see in the replies to the tweet above.

Do you know that SVG has an <a> element too? We're not cheating--that DSL isn't HTML, hence we can use it:

<!doctype html>
<svg viewBox="0 0 100 100">
  <a href="https://sigwait.org">
    <text x="50" y="50" text-anchor="middle">oh noes</text>
  </a>
  <style>
    svg { width: 100%; height: 85vh; }
    a text { text-decoration: underline; fill: blue; }
  </style>
</svg>

MathML

This little language is repeatedly ignored; everybody prefers rendering TeX with JS instead of directly writing formulas in MathML.

The href attribute only works in Firefox or Webkit, while Chrome simply renders black text without proper underlining:

<!doctype html>
<math style="font-size: 150%">
  <munder>
    <mtext href="https://sigwait.org">oh noes</mtext>
    <mo style="color: blue">&#x005F;</mo>
  </munder>
</math>
<style>body{margin:0;display:grid;place-items:center;height:95vh;}</style>

PDF

Most browsers can render PDFs, & PDFs have a concept of hyperlinking as well. We can generate a minimal .pdf file that contains nothing but a link, & then embed such a PDF into a web page.

Here's a makefile (because why not), that injects the links' name/path into a TeX template to produce a pdf:

$ cat pdf-hyperlink
#!/usr/bin/make -f

$(if $(and $(n), $(h)),,$(error Usage: pdf-hyperlink [-s] n=name h=addr out.pdf))

devnull := $(if $(findstring s,$(word 1, $(MAKEFLAGS))),> /dev/null)

%.pdf:
    pdflatex -jobname "$(basename $@)" -interaction=batchmode '\documentclass[border=2pt]{standalone}\usepackage{hyperref}\hypersetup{colorlinks=true}\usepackage{ulem}\begin{document}\href{'$(call se,$(h))'}{\textcolor{blue}{\uline{'$(call se,$(n))'}}}\end{document}' $(devnull)
    @rm -f $(foreach v,log out aux,"$(basename $@).$(v)")

se = '$(subst ','\'',$1)'

To get object.pdf file, run:

$ ./pdf-hyperlink n='oh noes' h='https://sigwait.org' object.pdf
$ du *pdf
16K     object.pdf

Embed:

<!doctype html>
<object type="application/pdf" data="object.pdf?#zoom=400"></object>
<style>
  body{margin:0;display:grid;height:100vh;}
  object{width:100%;height:100%;}
</style>

Unfortunately, Chrome for Android doesn't display it inline (Firefox does). Also, the link isn't vertically centered.

Java applet

Does anyone remember applets? 5 years ago, every browser killed them, although there are still enterprise folks who use this forefront of Web development (I assume via a dedicated VM with an old web browser).

This is nothing more than a computer archaeology, but for the sake of completeness, let's write a Java applet that only draws a hyperlink. To test it, though, you'll need to download jdk-8u261 & firefox-52.9.0esr, then enable the NPAPI plugin:

$ file ~/.mozilla/plugins/libnpjp2.so
/home/alex/.mozilla/plugins/libnpjp2.so: symbolic link to /mnt/hdd3/junk/java-applets/jdk1.8.0_261/jre/lib/amd64/libnpjp2.so
$ cat ~/.java/deployment/security/exception.sites
http://127.0.0.1
https://sigwait.org
$ grep expiration ~/.java/deployment/deployment.properties
deployment.expiration.check.enabled=false

& forbid Firefox to update itself.

The applet:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.net.*;
import java.util.*;

public class HyperlinkApplet extends Applet implements MouseListener {
  public void init() {
    addMouseListener(this);
    setCursor(new Cursor(Cursor.HAND_CURSOR));
  }

  public void paint(Graphics g) {
    g.setColor(Color.BLUE);
    Font font = new Font(Font.SERIF, Font.PLAIN, 32);
    Map attr = font.getAttributes();
    attr.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
    g.setFont(font.deriveFont(attr));
    g.drawString(getParameter("name"), 0, 32);
  }

  public void mouseClicked(MouseEvent e) {
    try {
      getAppletContext().showDocument(new URL(getParameter("url")));
      repaint();
    } catch (Exception err) {
      err.printStackTrace();
    }
  }

  public void mouseEntered(MouseEvent e) {}
  public void mouseExited(MouseEvent e) {}
  public void mousePressed(MouseEvent e) {}
  public void mouseReleased(MouseEvent e) {}
}

To compile, run:

$ alias javac.8u261=/mnt/hdd3/junk/java-applets/jdk1.8.0_261/bin/javac
$ javac.8u261 HyperlinkApplet.java

It's very robust (no) & versatile, with no hardcoded links!

<!doctype html>
<applet code="HyperlinkApplet.class">
  <param name="name" value="oh noes">
  <param name="url" value="https://sigwait.org">
  BLIMEY, NO JAVA!
</applet>
<style>
  body{margin:0;display:grid;place-items:center;height:100vh;}
  applet{width:7em;height:3em;}
</style>

There is a probability of 0.99(9) that you won't see a preview here, but trust me, it works.


Tags: ойті
Authors: ag