Custom HTML Tags with YUI

How to Use the Tag Module

  • Stephen Murphy
  • Yahoo! Search Team

Who Am I?

What's a Custom HTML Tag?

Example

Simple HTML

HTML

Copyright © <ydate data-format="%Y"></ydate> Yahoo! Inc.

Output

Copyright © Yahoo! Inc.

Example (cont)

Dynamically Create More Tags

JavaScript

btn.on('click', function(e) {
    container.append('<ydate data-format="%T"></ydate>, ');
});

Output

Example (cont)

Update Existing Tag

HTML

<ydate data-format="%T"></ydate>

JavaScript

btn.on('click', function(e) {
    container.one('ydate').tag.set('date', new Date());
});

Output

Example (cont)

ydate Definition

Y.Tag.register('ydate', {
    created: function(config) {
        this.addAttr('date', {
            value: new Date(),
            setter: function(value) {
                var date = Y.DataType.Date.format(value, {format: config.format});
                this.get('host').setHTML(date);
                return value;
            }
        });
    }
});

Benefits

Get rid of boilerplate markup generation and object instantiation.

Old and Busted

Y.one('body').append('<div id="foo"></div>');
new Y.Foo({
    srcNode: '#foo'
});

New Hotness

Y.one('body').append('<foo></foo>');

Benefits (cont)

  • Easier for non-programmers to use your component – it's just HTML.
  • Large projects will benefit from not needing to explicitly require modules.
  • Simply append a tag and let the DOM do the work.

How Does It Work?

Inserted Event

Event fires whenever a selector matches a node. Tag uses this for inserted node events.

How Does It Work? (cont)

Node Class Plugin

Tag plugin available on all Nodes.

Registering Attributes

Load higher resolution image if available.

<img highdpi highdpi:alt="@2x" src="img.jpg" />

Tag can have multiple attributes with configs.

<foo data-name="Foo Inc."
    bar bar:name="Bar Inc."
    baz baz:name="Baz Inc."></foo>

Registering Attributes (cont)

highdpi Definition

Y.Tag.register('[highdpi]', {
    created: function(config) {
        if (Y.config.win.devicePixelRatio <= 1) {return;}

        var host = this.get('host'),
            alt = config.alt || '@2x',
            src = host.get('src').replace(/(\.[a-zA-Z]+)$/, function(m) {return alt + m;});
        
        if (src) {
            Y.io(src, {
                method: 'HEAD',
                onsuccess: function(e) {
                    host.set('src', src);
                }
            });
        }
    }
});

Registering Attributes (cont)

Flexible Registration

Y.Tag.register('example, [example]', {});

Attribute Benefits

Provides more graceful degredation by enhancing existing elements.

Attributes can support multiple registered components.

Tag Registry

A Collection of Predefined Tags

yautocomplete

<yautocomplete data-max-results="i:5"></yautocomplete>

ybutton

<ybutton data-label="TEST BUTTON"></ybutton>

Tag Registry (cont)

ydial Tag

<ydial data-min="-100" data-max="100" data-value="0"></ydial>

Tag Registry (cont)

ycalendar Tag

<ycalendar></ycalendar>

Data Binding

Using the ybind Tag

Hello, ! Have a good day, .

<input id="name" type="text" placeholder="Enter your name" />
<p>   Hello, <span ybind="#name" ybind:refkeyup></span>! Have a good day,   <ybind data-ybind="#name" data-refkeyup></ybind>. </p>

Age:


Age:

Data Binding (cont)

Using the ybind Tag

Total clicks:

<click-counter>
<form ybind="click-counter" ybind:onsubmit="clicked">
<input type="submit" value="Click" />
</form>
<p>Total clicks: <span ybind="click-counter" ybind:refcount-change></span></p>
</click-counter>
Y.Tag.register('click-counter', {
created: function(config) {
this.addAttr('count', {value: 0});
},
clicked: function(e) {
e.preventDefault();
this.set('count', this.get('count') + 1);
}
});

What's Next?

Next release will support registering of classes.

Experiment with server-side support using Node.js and JSDOM.

Learn More

Questions/Comments?