Created
May 17, 2011 10:16
-
-
Save wrumsby/976238 to your computer and use it in GitHub Desktop.
Experimenting with broadcasting custom events in YUI 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
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
Lines 117 and 181-185 could be performed in listeners for
task:completed
andtask:selected
events respectively.That way if there is anything else that fires those events the user interface will continue to be updated appropriately.