Skip to content

Instantly share code, notes, and snippets.

@wrumsby
Created May 17, 2011 10:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wrumsby/976238 to your computer and use it in GitHub Desktop.
Save wrumsby/976238 to your computer and use it in GitHub Desktop.
Experimenting with broadcasting custom events in YUI 3
<!DOCTYPE html>
<html>
<head>
<title>Custom Events</title>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?3.3.0/build/cssbase/base-min.css">
<style>
body {
font-family: sans-serif;
}
.yui3-widget {
border: 1px solid blue;
}
.yui3-tasklist {
position: absolute;
top: 0px;
left: 0px;
width: 200px;
}
.yui3-tasklist .task {
padding: 8px;
}
.yui3-tasklist .task:hover {
background-color: yellow;
cursor: pointer;
}
.yui3-tasklist .task.completed {
text-decoration: line-through;
}
.yui3-tasklist .task.completed:hover {
cursor: default;
}
.yui3-tasklist .task.selected {
font-weight: bold;
}
.yui3-task {
position: absolute;
top: 0px;
left: 220px;
width: 600px;
}
.yui3-task .yui3-widget-hd {
padding-left: 0;
margin-left: 0;
}
#count {
position: absolute;
top: 220px;
left: 20px;
}
#count:before {
content: 'TODO: ';
}
</style>
<script src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
<script>
YUI.add('scratch-task', function(Y) {
var Base = Y.Base,
Widget = Y.Widget,
WidgetStdMod = Y.WidgetStdMod,
Lang = Y.Lang;
Y.Task = Base.create('task', Widget, [WidgetStdMod], {
initializer: function(config) {
this.publish('completed', {
broadcast: 2,
emitFacade: true,
monitored: true
});
},
destructor: function() {
},
renderUI: function() {
Y.log('renderUI');
},
bindUI: function() {
Y.log('bindUI');
Y.Global.on('task:selected', Y.bind(function(e) {
this.set('task', e.task);
this.syncUI();
}, this));
},
syncUI: function() {
Y.log('syncUI');
var task = this.get('task');
if (task) {
this.setStdModContent(WidgetStdMod.HEADER, Y.substitute('<h2>{name}</h2>', task));
if (task.isCompleted) {
this.setStdModContent(WidgetStdMod.FOOTER, '<button disabled="disabled">Complete</button>');
} else {
this.setStdModContent(WidgetStdMod.FOOTER, '<button>Complete</button>');
}
// create a delegate because of the way std mod is rendered - see http://yuilibrary.com/projects/yui3/ticket/2529440
Y.delegate('click', Y.bind(function(e) {
var task = this.get('task');
task.isCompleted = true;
e.target.set('disabled', true);
this.fire('task:completed', { task: task });
}, this), this.getStdModNode(WidgetStdMod.FOOTER), 'button');
} else {
this.setStdModContent(WidgetStdMod.HEADER, '');
this.setStdModContent(WidgetStdMod.FOOTER, '');
}
}
}, {
ATTRS: {
task: {
}
}
});
}, '1.0.0', { requires: ['base', 'widget', 'widget-stdmod', 'node', 'substitute', 'event'] });
</script>
<script>
YUI.add('scratch-tasklist', function(Y) {
var Widget = Y.Widget,
Lang = Y.Lang;
function TaskList(config) {
TaskList.superclass.constructor.apply(this, arguments);
}
TaskList.NAME = 'taskList';
TaskList.ATTRS = {
tasks: {
value: [],
validator: Lang.isArray
}
};
Y.extend(TaskList, Widget, {
initializer: function(config) {
this.publish('task:selected', {
broadcast: 2,
emitFacade: true,
monitored: true
});
},
destructor: function() {
},
renderUI: function() {
},
bindUI: function() {
Y.delegate('click', Y.bind(function(e) {
var target = e.target,
id = target.getData('id'),
tasks = this.get('tasks'),
task;
for (task in tasks) {
if (tasks[task].id === id) {
this.fire('task:selected', { task: tasks[task] });
}
}
target.get('parentNode').all('.selected').each(function(node) {
node.removeClass('selected');
});
target.addClass('selected');
}, this), this.get('contentBox'), 'li');
Y.Global.on('task:completed', Y.bind(function(e) { this.syncUI(); }, this));
},
syncUI: function() {
var contentBox = this.get('contentBox'),
tasks = this.get('tasks'),
task,
node;
contentBox.empty(true);
for (task in tasks) {
node = contentBox.appendChild(Y.substitute('<li class="task">{name}</li>', tasks[task]));
node.setData('id', tasks[task].id);
if (tasks[task].isCompleted) {
node.addClass('completed');
}
}
}
});
Y.TaskList = TaskList;
}, '1.0.0', { requires: ['node', 'widget', 'event', 'substitute'] });
</script>
</head>
<body>
<div id="#container">
<ul id="tasks"></ul>
<span id="count"></span>
<div id="task"></div>
</div>
<script>
(function() {
var tasks = [{
id: 1,
name: 'Make a Cup of Coffee',
isCompleted: false
}, {
id: 2,
name: 'Do the Dishes',
isCompleted: false
}, {
id: 3,
name: 'Have a Nap',
isCompleted: false
}];
YUI().use('scratch-tasklist', function(Y) {
new Y.TaskList({ tasks: tasks, srcNode: '#tasks', render: true });
});
YUI().use('scratch-task', 'event-custom', function(Y) {
var task = new Y.Task({ srcNode: '#task', render: true });
Y.Global.on('task:selected', function(e) {
task.set('task', e.task);
});
});
YUI().use('event-custom', 'node', function(Y) {
var setCount = function() {
var n = tasks.length,
i;
for (i = 0; i < tasks.length; i++) {
if (tasks[i].isCompleted) {
n--;
}
}
Y.one('#count').setContent(n);
};
Y.Global.on('task:completed', setCount);
setCount();
});
YUI().use('event-custom', 'substitute', function(Y) {
Y.Global.on('task:completed', function(e) {
Y.log(Y.substitute('{name} Task (id: {id}) completed', e.task));
});
Y.Global.on('task:selected', function(e) {
Y.log(Y.substitute('{name} Task (id: {id}) selected', e.task));
});
});
}());
</script>
</body>
</html>
@slieschke
Copy link

Lines 117 and 181-185 could be performed in listeners for task:completed and task:selected events respectively.

That way if there is anything else that fires those events the user interface will continue to be updated appropriately.

@slieschke
Copy link

target.get('parentNode').all('.selected').each(function(node) {
    node.removeClass('selected');
});

target.get('parentNode').all('.selected').removeClass('selected');

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