Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save subtleGradient/759332 to your computer and use it in GitHub Desktop.
Save subtleGradient/759332 to your computer and use it in GitHub Desktop.
What is the best syntax to use for declarative markup in HTML5?

Declarative Component Mapping Syntax Options

Language / Prior Art ‘Valid’ HTML HTML Mapping Example Example with Args
‘Valid’ CSS Selectable CSS Mapping CSS Select CSS Selector w Args
JavaScript MooTools Multiple instance Separate Args new Foo(element); new Bar(element) new Foo(element, {a:"a", bB:"b B", c:{c:1}}); new Bar(element, {d:"d"})
HTML attr Dojo <1.6 NO 1 Element per instance <div nsType=foo> <div nsType=foo a=a bB="b B" c.c=1>
CSS: A Single + Args [nsType] [nsType=Foo][a=a][bB~=b][bB~=B][c.c=1]
data-* Dojo 1.6+ YES 1 Element per instance <div data-ns="Foo"> <div data-ns="Foo" data-ns-a="a" data-ns-b-b="b B" data-ns-c.c="1">
CSS: A Single + Args [data-ns-type] [data-ns-type=Foo][data-ns-a=a][data-ns-bB~=b][data-ns-bB~=B][data-ns-c.c=1]
class & attr Apple iAd NO Multiple instances Combined Args <div class="ad-foo ad-bar"></div> <div class="ad-foo ad-bar" ad-title="MyBarButton"></div>
CSS: A+ Multi + Args .ad-foo, .ad-bar .ad-foo[ad-title], .ad-bar[ad-title]
data-* Hue Behavior YES Multiple instances Combined Args <div data-filters="ns.foo, ns.bar"> <div data-filters="ns.foo, ns.bar" data-a="a" data-b-b="b B" data-c='{"c":1}' data-d="d">
CSS: D All + Args [data-filters] [data-filters][data-a=a][data-bB~=b][data-bB~=B]
data-* & CSS YES Multiple instances Separate Args <div data-ns data-ns.foo data-ns.bar> <div data-ns data-ns.foo="a:a; b-b:b B; c{c:1}" data-ns.bar="d:d">
CSS: B Multi [data-ns] [data-ns.foo], [data-ns.bar]
attr & CSS NO Multiple instances Separate Args <div ns foo bar> <div ns foo="a:a; b-b:b B; c{c:1}" bar="d:d">
CSS: B Multi [ns] [ns][foo], [ns][bar]
data-* YES Multiple instances Separate Args <div data-ns="Foo Bar Baz"> <div data-ns="Foo Bar Baz" value=HTML data-foo.value=FOO data-bar.value=BAR>
CSS: A++ Multi + Multi Args [data-ns] [data-ns~=Foo][value=Frog]:not([data-foo.value]), [data-ns~=Foo][data-foo.value=Frog]
HTML attr NO Multiple instances Separate Args <div ns="Foo Bar Baz"> <div ns="Foo Bar Baz" value=HTML foo.value=FOO bar.value=BAR>
CSS: A++ Multi + Multi Args [ns] [ns~=Foo][value=Frog]:not([foo.value]), [ns~=Foo][foo.value=Frog]
data-* YES Multiple instances Separate Args <div data-ns="Foo, Bar, Baz"> <div data-ns="Foo:value(FOO), Bar:value(BAR), Baz:value(HTML)" value=HTML>
CSS: D- All [data-ns]
data-* YES Multiple instances Separate Args <div data-ns="Foo, Bar, Baz"> <div data-ns="Foo[value=FOO], Bar[value=BAR], Baz[value=HTML]" value=HTML>
CSS: D- All [data-ns]
<meta data-is=DataStore.JSON name=jsonStore content=dataItems.json>
<meta data-is=Model.Forest name=continentModel
content=jsonStore data-query=type:continent
data-root-id=continentRoot data-root-label=Continents data-children-attrs=children
>
<table data-is=DataGrid.Tree id=grid data-model=continentModel>
<thead>
<tr>
<th data-field=name style=width:auto>Name
<th data-field=population style=width:auto>Population
<th data-field=timezone style=width:auto>Timezone
</thead>
</table>
<span dojoType="dojo.data.ItemFileWriteStore"
jsId="jsonStore" data="dataItems"></span>
<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel"
store="jsonStore" query="{type:'continent'}"
rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
<table jsid="grid" dojoType="dojox.grid.TreeGrid" class="grid" treeModel="continentModel">
<thead>
<tr>
<th field="name" width="auto">Name</th>
<th field="population" width="auto">Population</th>
<th field="timezone" width="auto">Timezone</th>
</tr>
</thead>
</table>
<a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/grid/tests/test_treegrid_model.html" title="dojox.grid.TreeGrid Model-based test">Example from Dojo Toolkit dojox.grid.TreeGrid Model-based test</a>
@digitarald
Copy link

Maybe I am not thinking abstract enough, but I saw the mapping for data-[class]="[options-table]" and data-[class]-[options-key]="[options-value]" … which than maps to our classy new Class(element, options).

class could be either mapped in a sheet, auto-detected from the name or, just a thought, referenced in the HTML (<div data-require="table=App.Core.Table; zebra=App.More.Zebra" data-table="{…}" data-zebra-selectable="true">). The latter provides a nice way to avoid all kind of sheets, since all references are kept in one place.

I don't feel comfortable with the sheets, they need to be generic enough to be external and than would need to define resources shared within the whole application. Having them inline as attributes

@rolfnl
Copy link

rolfnl commented Jan 4, 2011

Yes, my thoughts too. Or is w3c coming with something like a behavior sheet recommendation (I don't keep up with the specs/updates)? It's a nice idea, but I wouldn't use it. JSON for options is probably the easiest way to go as it already works and it's relatively easy to implement. I like Ryan's idea in his Element.Filters that the choice of parser is optional.
I'd like to hear cpojer's thoughts as well.

@ryan, goconnect is goconnect.org?

@digitarald
Copy link

Thomas, I'd like to see more practical examples than smelling and singing cheese ;)

@rolfnl
Copy link

rolfnl commented Jan 4, 2011

@digitarald++ for the mapping, which feels like it should be. Though I also like it when you can describe your custom behavior/filter that might instantiate more than one classes or a singleton that does a bunch of stuff. Kind of like Ryan's Element.Filters

@rolfnl
Copy link

rolfnl commented Jan 4, 2011

Thomas, how can you sing a fast show tune and dance a slow waltz at the same time? or did you forgot the chain option? Plus, I wouldn't mix low culture hamburger cheddar with high culture waltz stuff.. (naah, on 2nd thought, waltz is simple == low culture.. mix is good)

@subtleGradient
Copy link
Author

Dancing and Singing have nothing to do with what that element IS but is more about how that thing behaves.

e.g.

Bob is a Person and acts like a Clown

<div name=bob is=Person age=37 height="5feet 3in" acts-like="Clown" clown='{"nose-color":"Red", "nose-sound":"honk"}'>

May map to something like…

new Person(element, { name:"bob", age:37, height:"5feet 3in" });
new Clown(element, { name:"bob", age:37, height:"5feet 3in", "nose-color":"Red", "nose-sound":"honk" });

Edgar is a Cow and acts like a Person

<div name=edgar is=Cow age=37 acts-like="Person" clown='{"height":"5feet 3in"}'>

May map to something like…

new Cow(element, { name:"edgar", age:37 });
new Person(element, { name:"edgar", age:37, height:"5feet 3in" });

Ralph is a Person and acts like a Ninja

etc…

So all the attributes of an element could merge in all the specific attributes of that 'acts-like' thing and give you a single object. But all that is kindof OT for this thread. I think I have solved the original question that this thread posed, that is, what is the best syntax to use for declarative markup.

@subtleGradient
Copy link
Author

@digitarald Mapping of alias to specific JS namespace should happen in JS, not HTML. e.g. SubtleBehavior.defineAlias({zebra: My.NameSpace.Of.Doom.Zembra, foo:Foo, bar:MySuperBar})

@subtleGradient
Copy link
Author

See https://gist.github.com/765730 for the thread about Behavior Sheets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment