YUI.add('video-frames', function(Y) { var Lang = Y.Lang, Widget = Y.Widget, Node = Y.Node; var NS = Y.namespace('mazzle'); NS.VideoFrames = VideoFrames; /* VideoFrames class constructor */ function VideoFrames(config) { VideoFrames.superclass.constructor.apply(this, arguments); } /* * Required NAME static field, to identify the Widget class and * used as an event prefix, to generate class names etc. (set to the * class name in camel case). */ VideoFrames.NAME = "video-frames"; /* * The attribute configuration for the VideoFrames widget. Attributes can be * defined with default values, get/set functions and validator functions * as with any other class extending Base. */ VideoFrames.ATTRS = { frameServer: { value: null }, maxFrames: { value: 50 }, frames: { value: [] }, related: { value: [] }, duration: { value: null }, confirm: { value: false }, video: { value: null }, interval : { value: 10 }, showRelated : { value: true }, showTime : { value: false }, selected : { value: null } }; /* Static constants used to define the markup templates used to create VideoFrames DOM elements */ VideoFrames.LIST_CLASS = 'frames-list'; VideoFrames.LIST_TEMPLATE = ''; /* VideoFrames extends the base Widget class */ Y.extend(VideoFrames, Widget, { initializer: function() { this.listNode = null; }, destructor : function() { }, renderUI : function() { var content = this.get("contentBox"); this._renderFrameList(content); }, bindUI : function() { this.after("framesChange", this._renderFrames); this.after("relatedChange", this._renderRelated); // frame click Y.delegate("click", this._onFrameSelect, this.listNode, "li .image", this); Y.delegate("mouseover", this._onFrameHover, this.get("contentBox"), "li", this); Y.delegate("click", this._onRoleSelect, this.get("contentBox"), "li div.frame-confirm", this); }, syncUI : function() { this._renderFrames(); }, _renderFrameList : function(node) { var list = node.appendChild(Node.create(VideoFrames.LIST_TEMPLATE)); // create list elements var maxFrames = this.get("maxFrames"); for(var i=0; i < maxFrames; i++) { list.append(''); } this.listNode = list; if(this.get("showRelated")) { // create list for related frames node.appendChild('
similar annotations:
'); related = node.appendChild(Node.create(VideoFrames.LIST_TEMPLATE)); related.addClass("related"); for(var i=0; i < maxFrames; i++) { related.append(''); } this.relatedNode = related; } }, _renderFrames : function() { var frames = this.get("frames"); this.listNode.all("li").removeClass("selected"); this.set("selected", null); this._updateFrames(this.listNode, frames); }, _renderRelated : function() { var frames = this.get("related"); if(this.relatedNode) { this._updateFrames(this.relatedNode, frames); } }, _updateFrames : function(node, frames) { var time = 0; var interval = this.get("interval")*1000; node.all("li").each(function(node, i) { if(frames[i]) { var startTime = frames[i].startTime; node.setContent(this.formatFrame(frames[i])); if(time==0 || interval==0 || startTime>time+interval) { node.removeClass("hidden"); } time = startTime; } else { node.setContent(""); node.addClass("hidden"); } }, this); }, formatFrame : function(frame) { var frameServer = this.get("frameServer"), video = frame.video || this.get("video"), time = frame.startTime/1000, label = frame.tag ? (frame.tag.label ? frame.tag.label : frame.tag.value) : '', role = frame.role ? frame.role : '', endTime = frame.duration ? time+(frame.duration/1000) : null; var html = '
' +'' +'
'; if(this.get("confirm")) { //html += '
click to confirm
'; html += '
' +this._roleLabel(role) +label+' '+this.formatTime(time)+'
'; } else { html += '
'+label+' '+this.formatTime(time); if(endTime) { html += ' -- '+this.formatTime(endTime); } html += '
'; } return html; }, formatTime : function(totalSeconds) { if(this.get("showTime")) { var minutes = Math.floor(totalSeconds / 60); var seconds = Math.floor(totalSeconds % 60); var spacer = (seconds<10) ? 0 : ''; return ''+minutes+':'+spacer+seconds+''; } else { return ''; } }, _roleLabel : function(role) { if(role=="depicted") { return "depicts "; } else if(role=="associated") { return "associated with "; } else if(role=="rejected") { return "not "; } else { return ""; } }, _onFrameSelect : function(e) { var node = e.currentTarget.get("parentNode"), list = node.get("parentNode"); index = list.all("li").indexOf(node), frame = this._getFrame(list, index), arg = {li:node, index:index, frame:frame}; this.set("selected", frame); list.all("li").removeClass("selected"); node.addClass("selected"); Y.log('clicked frame '+frame+' at index '+index); this.fire("frameSelect", arg); }, _onFrameHover : function(e) { var node = e.currentTarget, list = node.get("parentNode"), index = list.all("li").indexOf(node), frame = this._getFrame(list, index); arg = {li:node, index:index, frame:frame}; this.fire('frameHover', arg); }, _onRoleSelect : function(e) { var target = e.currentTarget, node = e.currentTarget.get("parentNode"), list = node.get("parentNode"); index = list.all("li").indexOf(node), frame = this._getFrame(list, index), tag = frame.tag.label; Y.log('frame role selected at index '+index); var type = "depicted"; if(frame.confirm) { if(frame.confirm=="depicted") { type="associated"; } else if(frame.confirm=="associated") { type = "rejected"; } target.replaceClass(frame.confirm, type); } else { target.addClass(type); }; frame.confirm = type; e.target.setContent(this._roleLabel(type)+tag); this.fire("roleSelect", {type:type, index:index, frame:frame}); }, _getFrame : function(list, index) { if(list.hasClass("related")) { return this.get("related")[index]; } else { return this.get("frames")[index] } } }); }, 'gallery-2010.03.02-18' ,{requires:['node','widget','io-base','json-parse']});