Skip to content

Instantly share code, notes, and snippets.

@lsmith
Created February 3, 2012 00:35
Show Gist options
  • Save lsmith/1726751 to your computer and use it in GitHub Desktop.
Save lsmith/1726751 to your computer and use it in GitHub Desktop.
Button as subclass of Node
<!doctype html>
<head>
<meta charset="utf-8">
<title>Test Page</title>
</head>
<body>
<div id="x">
<button id="btn3">Button 3</button>
<button id="btn4">Button 4</button>
</div>
<script src="http://yui.yahooapis.com/3.5.0pr2/build/yui/yui.js"></script>
<script>
YUI({ filter: 'raw' }).use('node', function (Y) {
var isObject = Y.Lang.isObject,
isString = Y.Lang.isString,
sub = Y.Lang.sub;
Y.Button = Y.extend(function (el) {
this._initButton(el);
},
Y.Node, {
DEFAULT_LABEL: "OK",
setState: function (state) {
var disabled = (state === 'disabled');
this[disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', true);
this[disabled ? 'addClass' : 'removeClass']('yui3-disabled');
this.set('disabled', disabled);
},
TEMPLATE: '<button>{label}</button>',
_createButton: function (values) {
return Y.DOM.create(sub(this.TEMPLATE, values));
},
_initButton: function (el) {
var config = isObject(el) && el,
node, uid;
if (config) {
el = config.srcNode;
}
if (!el || Y.Node.call(this, el) === null) {
Y.Node.call(this, this._createButton(
config ||
{ label: el || this.DEFAULT_LABEL }));
}
if (!this._node) {
// Dunno how this would happen
return null;
}
if (config) {
// Maybe a bad idea
this.setAttrs(config);
if (isObject(config.on)) {
this.on.call(this, config.on);
}
}
// TODO: evaluate current node for proper ARIA role/states
if (!config || !config.noCache) {
Y.Node._instances[this._node._yuid] = this;
}
}
});
var button = new Y.Button();
var button2 = new Y.Button("Some text");
var button3 = new Y.Button('#btn3');
var button4 = new Y.Button({ srcNode: '#btn4' });
var button5 = new Y.Button({
label: "Click here",
on: {
click: function (e) {
console.log('Button 5!');
}
}
});
button.on('click', function (e) {
console.log('Button 1');
});
button4.setState('disabled');
Y.one('#x').prepend(button).prepend(button2);
button5.appendTo('#x');
console.log('Y.one("#bt3") instanceof Y.Button? ',
Y.one('#btn3') instanceof Y.Button);
console.log('Button 4 disabled? ', button4.get('disabled'));
});
</script>
</body>
</html>
@Satyam
Copy link

Satyam commented Feb 5, 2012

Since the current tendency is to use HTML strings to create elements or work from existing markup, since this is best for NodeJS, there is really very little a Button class has to offer, nobody is encouraging creating anything using JavaScript. Regular HTML Buttons already have a disabled property and it is to be expected that screen readers know about it and do not need an aria-disabled attribute. I know, this is just an example but when you try to come up with an attribute that might be worth it there is really not much a Button class could do.

In fact, the only two places where there is room for improvement are toggle buttons and groups of mutually exclusive buttons (radio buttons), otherwise there is not much to do about regular buttons and groups of unrelated buttons, except provide styling, which CSS-Button already does.

I liked the way Derek separated the CSS-Button styles from the Button class. I liked the small footprint of the Button class. What I didn't like is the inconsistency of having a Button class instance for creating them but then having to go to the Node instance to listen for events. One possible solution is to get Button to relay those events fired by Node which, it seems, is the solution adopted, in other words, raising the interface to get all at the Button class level.

I opted for the reverse, instead of raising the interface to the Button level, I moved everything to the Node level and since Nodes already provide for everything a regular Button might provide, there is very little else to do but to handle toggle buttons, which are not native, and groups of radio buttons. The whole class then just provides a single static method to activate the feature on all buttons and button groups identified with a suitable className. Then they can be used as regular buttons would with just the 'selected' attribute added. The looks and the ARIA support is completely transparent. Alternatively, the code might support a type=toggle attribute: '<button type="toggle"> , but I feel it is dangerous, I prefer to stick to using classNames.

In this version, to appease those uncomfortable with my previous tampering of Node, I use ATTRS:

http://satyam.com.ar/yui/3.5/button/usingATTRS.html

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