Page MenuHomePhabricator
Diviner Javelin Tech Docs Concepts: Sigils and Metadata

Concepts: Sigils and Metadata
Javelin Technical Documentation (concepts)

Explains Javelin's sigils and metadata.

Overview

Javelin introduces two major concepts, "sigils" and "metadata", which are core parts of the library but don't generally exist in other Javascript libraries. Both sigils and metadata are extra information you add to the DOM which Javelin can access. This document explains what they are, why they exist, and how you use them.

Sigils

Sigils are names attached to nodes in the DOM. They behave almost exactly like CSS class names: sigils are strings, each node may have zero or more sigils, and sigils are not unique within a document. Sigils convey semantic information about the structure of the document.

It is reasonable to think of sigils as being CSS class names in a different, semantic namespace.

If you're emitting raw tags, you specify sigils by adding a data-sigil attribute to a node:

<div data-sigil="newsfeed">
  <div data-sigil="story">
    ...
  </div>
  <div data-sigil="story">
    ...
  </div>
</div>

However, this should be considered an implementation detail and you should not rely on it excessively. In Javelin, use JX.Stratcom.hasSigil() to test if a node has a given sigil, and JX.Stratcom.addSigil() to add a sigil to a node.

Javelin uses sigils instead of CSS classes to rigidly enforce the difference between semantic information and style information in the document. While CSS classes can theoretically handle both, the conflation between semantic and style information in a realistic engineering environment caused a number of problems at Facebook, including a few silly, preventable, and unfortunately severe bugs.

Javelin separates this information into different namespaces, so developers and designers can be confident that changing CSS classes and presentation of a document will never change its semantic meaning. This is also why Javelin does not have a method to test whether a node has a CSS class, and does not have CSS selectors. Unless you cheat, Javelin makes it very difficult to use CSS class names semantically.

This is an unusual decision for a library, and quite possibly the wrong tradeoff in many environments. But this was a continual source of problems at Facebook's scale and in its culture, such that it seemed to justify the measures Javelin takes to prevent accidents with style information having inadvertent or unrealized semantic value.

Metadata

Metadata is arbitrary pieces of data attached to nodes in the DOM. Metadata can be (and generally is) specified on the server, when the document is constructed. The value of metadata is that it allows handlers which use event delegation to distinguish between events which occur on similar nodes. For instance, if you have newsfeed with several "Like" links in it, your document might look like this:

<div data-sigil="newsfeed">
  <div data-sigil="story">
    ...
    <a href="..." data-sigil="like">Like</a>
  </div>
  <div data-sigil="story">
    ...
    <a href="..." data-sigil="like">Like</a>
  </div>
</div>

You can install a listener using Javelin event delegation (see Concepts: Event Delegation for more information) like this:

JX.Stratcom.listen(
  'click',
  ['newsfeed', 'story', 'like'],
  function(e) {
    // ...
  });

This calls the function you provide when the user clicks on a "like" link, but you need to be able to distinguish between the different links so you can know which story the user is trying to like. Javelin allows you to do this by attaching metadata to each node. Metadata is attached to a node by adding a

data-meta## attribute which has an index into data later provided to

JX.Stratcom.mergeData():

<div data-sigil="newsfeed">
  <div data-sigil="story" data-meta="0_0">
    ...
    <a href="..." data-sigil="like">Like</a>
  </div>
  <div data-sigil="story" data-meta="0_1">
    ...
    <a href="..." data-sigil="like">Like</a>
  </div>
</div>
...
<script type="text/javascript">
  JX.Stratcom.mergeData(0, [{"storyID" : 12345}, {"storyID" : 23456}]);
</script>

This data can now be accessed with JX.Stratcom.getData(), or with JX.Event.getNodeData() in an event handler:

JX.Stratcom.listen(
  'click',
  ['newsfeed', 'story', 'like'],
  function(e) {
    var id = e.getNodeData('story').storyID;
    // ...
  });

You can also add data to a node programmatically in Javascript with JX.Stratcom.addData().