Skip to content

Instantly share code, notes, and snippets.

@mikewilcox
Created July 18, 2012 13:41
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 mikewilcox/3136275 to your computer and use it in GitHub Desktop.
Save mikewilcox/3136275 to your computer and use it in GitHub Desktop.
Example file of a an event connection system
(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