Snippets, markup from the page

A snippet is a piece of HTML written in the page and used by code as a template. The page’s author writes the markup, with its classes and its structure. The code makes copies and fills in only the content. Domite keeps the snippets, and Silk and Web each make them their own way, from the same markup. This page builds on Building the page with Silk and Building the page with Web.

Marking a snippet

Write the snippet into index.html, with a name in data-snippet and its caret in data-snippet-caret. The caret is the element that takes the contents:

<ul id="items"></ul>
<li data-snippet="item" class="item"><input type="checkbox"> <label data-snippet-caret></label></li>

When Amber starts, Domite takes every element with data-snippet off the page and keeps it under its name. The attribute goes, and the caret’s mark goes from every copy. A snippet inside another snippet is taken off it, and becomes a snippet of its own.

Three more forms are worth knowing:

The snippets stand in the page until Amber has started. To keep them out of sight until then, put them into a <div hidden>. The copies come out visible, since the snippet itself carries no hidden.

Importing the snippets

The snippets come with packages of their own. Add 'silk/Silk-Snippets' to the imports of your package to use them with Silk, and 'amber/web/Web-Snippets' to use them with Web. Both bring Domite’s 'domite/DOMite-Snippets' along. In Helios, edit the package definition as the libraries page shows, save, commit, and reload:

Package
	named: 'HelloAmber'
	imports: {'amber/jquery/Web-JQuery'. 'amber/web/Web'. 'amber/web/Web-Snippets'. 'silk/Silk'. 'silk/Silk-Snippets'}
	transport: (AmdPackageTransport namespace: 'amber-helloamber')

With Silk

Silk makes a snippet the way it makes an element, by sending its name as a message. It tries an element first, so a name in capitals is still an element. With the markup above:

'#items' asSilk item: 'Milk'

This puts <li class="item"><input type="checkbox"> <label>Milk</label></li> into the list. The message answers a Silk on the caret, the label, with the cursor at its end. So attrAt:put: sets an attribute of the label, << puts more into it, and on:bind: binds an event to it. The whole copy is the Silk’s frame, a DOM element. Silk fromElement: wraps it, and the cut from the Silk page takes it out:

| item whole |
item := '#items' asSilk item: 'Milk'.
whole := Silk fromElement: item frame.
item on: #click bind: [ whole copy setToBefore cutUpTo: whole copy setToAfter ]

Clicking Milk now removes the whole item. The other forms follow the element messages:

A name that Silk understands already, such as reset, stays Silk’s. A name that is no selector, such as shop-item, cannot be sent at all. Both are reached by aSilk newSnippet: 'shop-item', which answers the same kind of Silk.

With Web

Web makes each snippet a tag message of the canvas, named after the snippet. The message answers a brush on the caret:

'#items' asBrush with: [ :html |
	html item with: 'Milk'; onClick: [ console log: 'Milk' ] ]

The brush takes attributes, contents and events like any other. html note with: 'Saved.' fills a snippet that is its own caret. html rule puts a snippet with no caret, and its brush refuses contents: “This snippet marks no caret, so it takes no contents.”

A name that is no selector is reached by html snippet: 'shop-item' asSnippet. Pick names that are not tags. The snippet’s message replaces a tag message of the same name. A snippet named span makes html span put the snippet.

Both at once

Silk and Web read the same snippets, so one page can use both:

'#items' asSilk item: 'from Silk'.
'#items' asBrush with: [ :html | html item with: 'from Web' ]

This puts two items of the same markup into the list.

Snippets added later

Markup that arrives after Amber has started, from a server or a template, gives up its snippets to DomiteSnippets current installSnippetsIn: aNode. Silk and Web see them at once. 'item' asSnippet answers the element kept under a name, for code that wants the original.