Created
July 18, 2012 13:41
-
-
Save mikewilcox/3136275 to your computer and use it in GitHub Desktop.
Example file of a an event connection system
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
(function(b){ | |
// NOTE: "b" is the main library, "bv" (BetterVideo) | |
var cons = {}, aListeners = {}; | |
var fns = []; | |
var theOne; | |
var topics = {}; | |
var d_topics = {}; | |
var DEFAULT_TIMER = 30; | |
var WKADJUST = (b.is_chrome && b.is_chrome()) ? -20 : -120; // don't break if sniff.js is not incl | |
var tch = 'ontouchstart' in window.document; | |
var eventMap = { | |
'click': tch ? 'touchend' : 'click', | |
'mouseup': tch ? 'touchend' : 'mouseup', | |
'mousedown': tch ? 'touchstart' : 'mousedown', | |
'mousemove': tch ? 'touchmove' : 'mousemove' | |
}; | |
var normalize = function(evt){ | |
evt.explicitOriginalTarget = evt.currentTarget = evt.toElement; | |
evt.target = evt.srcElement; | |
return evt; | |
} | |
var standardsScroll = function(evt){ | |
//console.log("scroll", evt.wheelDelta/120, " - - ", evt.wheelDeltaX, evt.wheelDeltaY) | |
var o = { | |
type:"scroll" | |
} | |
if(evt.wheelDelta){ | |
//console.log("WHEELDELTA"); | |
// Safari | |
if(evt.wheelDeltaX){ | |
o.horizontal = true; | |
o.vertical = false; | |
o.scrollX = evt.wheelDeltaX/WKADJUST; | |
o.scrollY = 0; | |
}else{ | |
o.horizontal = false; | |
o.vertical = true; | |
o.scrollX = 0; | |
o.scrollY = evt.wheelDeltaY/WKADJUST; // Saf is backwards! | |
} | |
}else{ | |
//console.log("SCROLL"); | |
if(evt.axis == evt.HORIZONTAL_AXIS){ | |
o.horizontal = true; | |
o.vertical = false; | |
o.scrollX = evt.detail; | |
o.scrollY = 0; | |
}else{ | |
o.horizontal = false; | |
o.vertical = true; | |
o.scrollX = 0; | |
o.scrollY = evt.detail; | |
} | |
} | |
return o; | |
} | |
var groupHandles = {}; | |
var groups = { | |
add: function(type, handle){ | |
if(!groupHandles[type]) groupHandles[type] = []; | |
groupHandles[type].push(handle); | |
}, | |
remove: function(type){ | |
groupHandles[type].forEach(function(handle){ | |
handle.remove(); | |
}); | |
}, | |
pause: function(type){ | |
groupHandles[type].forEach(function(handle){ | |
handle.remove(); | |
}); | |
}, | |
resume: function(type){ | |
groupHandles[type].forEach(function(handle){ | |
handle.remove(); | |
}); | |
} | |
}; | |
//var log = b.log('ON', 1); | |
b.mix({ | |
multi:{ | |
sub: function(obj, ctx){ | |
var subs = []; | |
for(var nm in obj){ | |
subs.push(b.sub(nm, ctx, obj[nm])); | |
} | |
return { | |
remove: function(){ | |
b.each(subs, function(s){ s.remove(); }); | |
}, | |
pause: function(){ | |
b.each(subs, function(s){ s.pause(); }); | |
}, | |
resume: function(){ | |
b.each(subs, function(s){ s.resume(); }); | |
} | |
} | |
}, | |
on: function(obj, source, ctx, type){ | |
var subs = []; | |
ctx = ctx || null; | |
for(var nm in obj){ | |
subs.push(b.on(source, nm, !!ctx?ctx:obj[nm], !!ctx?obj[nm]:null, type)); | |
} | |
return { | |
remove: function(){ | |
b.each(subs, function(s){ s.remove(); }); | |
}, | |
pause: function(){ | |
b.each(subs, function(s){ s.pause(); }); | |
}, | |
resume: function(){ | |
b.each(subs, function(s){ s.resume(); }); | |
} | |
} | |
} | |
}, | |
sub: function(channel, ctx, method, type){ | |
if(!topics[channel]){ | |
topics[channel] = {}; d_topics[channel] = {}; | |
} | |
var cb = this.bind(ctx, method); | |
var uid = this.uid("sub"); | |
topics[channel][uid] = cb; | |
var handle = { | |
remove: function(){ | |
delete topics[channel][uid]; | |
}, | |
pause: function(){ | |
this.cb = topics[channel][uid]; | |
topics[channel][uid] = function(){} | |
}, | |
resume: function(){ | |
if(!this.cb) return; | |
topics[channel][uid] = this.cb; | |
} | |
}; | |
if(type) groups.add(handle); | |
return handle; | |
}, | |
pub: function(channel){ | |
//console.log('pub:', channel, topics[channel]) | |
if(!topics[channel]) return; | |
var args = Array.prototype.slice.call(arguments); | |
args.shift(); | |
for(var nm in topics[channel]){ | |
topics[channel][nm].apply(null, args); | |
} | |
}, | |
on: function(object, name, ctx, method, type){ | |
//if(name == "unload") return this.unload(ctx, method, type); | |
//log('on', name) | |
var _o = object; | |
if(object === "timer" || object === "timeout" || object === "interval"){ | |
console.error('on.timer removed', object, name, method); | |
//console.trace(); | |
} | |
name = eventMap[name] || name; | |
if(typeof(object) == "string") object = this.byId(object); | |
if(!object){ | |
console.error("no 'on' object found:", _o, "(", "event:", name, "method:", method, ")"); | |
console.trace(); | |
return null; | |
} | |
if(type == "once"){ | |
return this.once(object, name, ctx, method); | |
} | |
if(typeof(name) != "string"){ // ctx is 2nd, name 3rd | |
var c = ctx; ctx = name; name = c; | |
} | |
if(typeof(name) != "string"){ // name is an object of name/methods | |
for(var nm in name){ | |
this.on(object, nm, ctx, name[nm]); | |
} | |
return 0; // no handle for this. | |
} | |
var fn = !!method ? this.bind(ctx, method) : ctx; | |
var paused = function(){} | |
var resumed = fn; | |
var realFn; | |
var newFn = object[name]; | |
if(object.addEventListener){ // Silverlight? | |
//console.log("object.addEventListener:", name); | |
if(name == "scroll"){ | |
name = b.is_ff() ? "DOMMouseScroll" : "mousewheel"; | |
var _fn = fn; | |
fn = function(evt){ | |
//console.log("onscroll"); | |
_fn(standardsScroll(evt), evt); | |
} | |
// FIXME: | |
// fn is used for pause, so _fn breaks it | |
// maybe addEventListener should be duplicated here | |
} | |
if(name == "mouseenter" || name == "mouseleave"){ | |
name = name == "mouseenter" ? "mouseover" : "mouseout"; | |
realFn = function(evt){ | |
if(!b.isDescendant(evt.relatedTarget, object)){ | |
fn(evt); | |
} | |
} | |
object.addEventListener(name, realFn, false); | |
}else{ | |
realFn = function(evt){ | |
fn(evt); | |
} | |
object.addEventListener(name, realFn, false); | |
} | |
}else if(object.attachEvent){ | |
//console.log("object.attachEvent", name); | |
if(name == "scroll") name = "mousewheel"; | |
var realFn = function(){ | |
fn(normalize(window.event)); | |
} | |
object.attachEvent("on"+name, realFn); | |
}else{ // AOP | |
//console.log("object.AOP", name); | |
object[name] = function(){ | |
// the 'before' looks backwards, but it works | |
if(type!="before") newFn.apply(object, arguments); | |
fn.apply(null, arguments); | |
if(type=="before") newFn.apply(object, arguments); | |
} | |
} | |
var handle = { | |
remove: function(){ | |
fn = paused; | |
// does not work with AOP: object.removeEventListener(name, realFn, false); | |
}, | |
pause: function(){ | |
fn = paused; | |
}, | |
resume: function(){ | |
fn = resumed; | |
} | |
}; | |
if(type) groups.add(type, handle); | |
return handle; | |
}, | |
once: function(object, name, ctx, method){ | |
var fn = this.bind(ctx, method); | |
var handle = this.on(object, name, function(){ | |
handle.remove(); | |
fn.apply(null, arguments); | |
}); | |
}, | |
press: function(node, source, method, arg){ | |
var fn = this.bind(source, method); | |
var passArg = arg; | |
var handle, offHandle, downHandle; | |
var tch = bv.supports.touch(); | |
var fire = function(){ | |
handle = setInterval(function(){ | |
fn(passArg); | |
}, 20); | |
} | |
var stop = function(evt){ | |
offHandle.pause(); | |
clearInterval(handle); | |
} | |
downHandle = this.on(node, tch ? "touchstart" : "mousedown", function(evt){ | |
//console.log("PRESS"); | |
b.stopEvent(evt); | |
offHandle.resume(); | |
fire(); | |
}); | |
offHandle = this.on(document, tch ? "touchend" : "mouseup", function(evt){ | |
//console.log("RELEASE CANCEL") | |
b.stopEvent(evt); | |
stop(); | |
}); | |
stop(); | |
return downHandle; | |
}, | |
bind: function(ctx, func, dbg){ | |
// NON-DEBUG | |
//if(dbg) | |
//return b.bindX(ctx, func, dbg); | |
if(typeof(func) == "string"){ | |
if(!func){ func = ctx; ctx = window; } | |
return function(){ | |
ctx[func].apply(ctx, arguments); } | |
}else{ | |
var method = !!func ? ctx.func || func : ctx; | |
var scope = !!func ? ctx : null; | |
return function(){ method.apply(scope, arguments); } | |
} | |
}, | |
partial: function(o, f){ | |
f = typeof(f)=="string" ? o[f] : !o.f ? this.bind(o, f) : o.f; | |
return function(args){ | |
f.apply(o, args); | |
} | |
}, | |
mouse: function(e, noscroll){ | |
var posx = 0; | |
var posy = 0; | |
var d = document; | |
if (e.pageX || e.pageY){ | |
posx = e.pageX; | |
posy = e.pageY; | |
if(noscroll){ | |
posx -= d.body.scrollLeft + d.documentElement.scrollLeft | |
posy -= d.body.scrollTop + d.documentElement.scrollTop; | |
} | |
//console.info("pageY:", posy); | |
}else if (e.clientX || e.clientY){ | |
posx = e.clientX; | |
posy = e.clientY; | |
//console.info("clientY:", posy); | |
if(!noscroll){ | |
posx += d.body.scrollLeft + d.documentElement.scrollLeft | |
posy += d.body.scrollTop + d.documentElement.scrollTop; | |
} | |
} | |
return { | |
x:posx, | |
y:posy | |
}; | |
}, | |
stopEvent: function(evt){ | |
evt = evt || window.event; | |
if(!evt) return false; | |
if(evt.preventDefault){ | |
evt.preventDefault(); | |
evt.stopPropagation(); | |
}else{ | |
evt.cancelBubble = true; | |
evt.returnValue = false; | |
} | |
return false; | |
} | |
}); | |
b.sub.debug = function(){ | |
//console.dir(d_topics); | |
} | |
b.on.remove = groups.remove; | |
b.on.pause = groups.pause; | |
b.on.resume = groups.resume; | |
})(window.bv); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment