Changeset View
Changeset View
Standalone View
Standalone View
externals/javelin/src/docs/concepts/sigils_metadata.diviner
- This file was added.
| @title Concepts: Sigils and Metadata | |||||
| @group 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: | |||||
| lang=html | |||||
| <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 @{method:JX.Stratcom.hasSigil} to test | |||||
| if a node has a given sigil, and @{method: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: | |||||
| lang=html | |||||
| <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 @{article: | |||||
| Concepts: Event Delegation} for more information) like this: | |||||
| lang=js | |||||
| 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 | |||||
| @{method:JX.Stratcom.mergeData}: | |||||
| lang=html | |||||
| <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 @{method:JX.Stratcom.getData}, or with | |||||
| @{method:JX.Event.getNodeData} in an event handler: | |||||
| lang=js | |||||
| 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 | |||||
| @{method:JX.Stratcom.addData}. | |||||