Skip to content

Instantly share code, notes, and snippets.

@Zirak
Created July 12, 2013 15:01
Show Gist options
  • Select an option

  • Save Zirak/5985141 to your computer and use it in GitHub Desktop.

Select an option

Save Zirak/5985141 to your computer and use it in GitHub Desktop.
SO-Chat onebox utility and example
Array.some = function (arr) {
return [].some.apply(arr, [].slice.call(arguments, 1));
};
//not a good idea later on, but in dev, it's priceless when chaining
Object.defineProperty(Object.prototype, 'log', {
value : function log () {
console.log(this);
return this;
},
writable : true,
configurable : true
});
var obox = window.obox = {
listeners : [],
init : function () {
this.chatElem = document.getElementById('chat');
var observer =
this.observer =
new MutationObserver(this.onmutations.bind(this));
observer.observe(this.chatElem, { childList : true, subtree : true });
},
//why is this useful?
destroy : function () {
this.observer.disconnect();
},
runOnAllMessages : function (listener) {
var fun = listener ?
this.callListener.bind(this, listener) :
this.callListeners.bind(this);
return [].forEach.call(
this.chatElem.getElementsByClassName('content'), fun);
},
cond : function (predicate, callback) {
var ret = { pred : predicate, fun : callback };
this.listeners.push(ret);
return ret;
},
condAndRun : function (predicate, callback) {
var listener = this.cond(predicate, callback);
this.runOnAllMessages(listener);
return listener;
},
onmutations : function (mutations) {
mutations
.filter(mutationFilterer)
.map(mutationMapper)
.forEach(this.callListeners, this);
function mutationMapper (mutation) {
//console.log(mutation, 'mutationMapper');
return mutation
.addedNodes[0]
.getElementsByClassName('content')[0];
}
function mutationFilterer (mutation) {
//console.log(mutation, 'mutationFilterer');
return mutation.addedNodes.length &&
Array.some(mutation.addedNodes, nodeFilterer);
}
function nodeFilterer (node) {
return node.classList &&
node.classList.contains('message') &&
//chat adds a class for what you just posted, but hasn't been
// received by a server yet, or something of the sorts. some
// classes aren't always there, so we check for 'em all
!node.classList.contains('pending') &&
!node.classList.contains('posted');
}
},
callListener : function (listener, node) {
var match, res = false;
if (match = listener.pred(node)) {
res = listener.fun(node, match);
if (res !== false) {
this.handleListenerReturn(res, node);
}
}
return !!match && res !== false;
},
callListeners : function (node) {
console.log(node, 'callListeners');
var self = this;
this.listeners.some(function (listener) {
return self.callListener(listener, node);
});
},
//this allows you to return an element from a listener, and the element will
// automatically replace the content
handleListenerReturn : function (ret, container) {
console.log(ret, container, 'handleListenerReturn');
if (!ret || !ret.nodeType) {
return;
}
container.textContent = ''; //h4x for clearing the element
container.appendChild(ret);
},
createElement : function () {
var ret = document.createElement('div');
ret.classList.add('onebox');
return ret;
}
};
obox.init();
(function () {
var extensions = {
oga : {
type : 'audio',
codec : 'audio/ogg; codecs="vorbis"'
},
mp3 : {
type : 'audio',
codec : 'audio/mpeg; codecs="mp3"'
},
wav : {
type : 'audio',
codec : 'audio/wav; codecs="1"'
},
webma : {
type : 'audio',
codec : 'audio/webm; codecs="vorbis"'
},
ogv : {
type : 'video',
codec : 'video/ogg; codecs="theora, vorbis"'
},
mp4 : {
type : 'video',
codec : 'video/mp4' //I can't find the exact codec...
},
webmv : {
type : 'video',
codec : 'video/webm; codecs="vorbis, vp8"'
}
};
extensions.webm = extensions.webmv;
var re = new RegExp(
'https?.+\\.(' + Object.keys(extensions).join('|') + ')$',
'i');
obox.condAndRun(
function check_audio_video (node) {
var first = node.firstElementChild;
return first &&
!first.nextSibling && //make sure there isn't any other content
first.tagName === 'A' &&
re.exec(first.href);
},
function audio_video (content, match) {
console.log(content, match, 'audio_video');
var ext = extensions[match[1].toLowerCase()],
box = obox.createElement(),
elem = document.createElement(ext.type);
console.log(ext, elem, elem.canPlayType(ext.codec));
if (!elem.canPlayType(ext.codec)) {
return false;
}
elem.src = match[0];
elem.controls = "controls";
box.appendChild(elem);
return box;
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment