Skip to content

Instantly share code, notes, and snippets.

@kares
Created January 23, 2010 11:36
Show Gist options
  • Save kares/284556 to your computer and use it in GitHub Desktop.
Save kares/284556 to your computer and use it in GitHub Desktop.
/**
* A helper for embedding gists from http://gist.github.com/
* @param args the gist to embed full URL or ID only
* - asyncLoad - will load gist via ajax (non-blocking)
* - loadHTML - the HTML to use while gist is not loaded
* - removeStyleLink removes the embedded css link (useful
* for custom gist styling)
*/
function embedGist(args) {
if ( ! args ) throw 'no arguments given';
if ( ! args.id && ! args.url ) throw "'id' or 'url' is required";
// 'normalize' - make sure args.id and args.url are corect :
if ( args.id && ! args.url ) {
args.url = 'http:\/\/gist.github.com\/' + args.id + '.js';
}
else {
if ( args.id ) args.id = args.id.toString();
else {
var url = args.url;
args.id = url.substring(url.lastIndexOf('/') + 1);
args.id = args.id.replace('.', '_');
}
}
var wrapperId = args.id + '-' + (new Date()).getTime();
/* NOTE: Opera, IE write the script 'content' after the div not inside !
var wrapper = '<div id="'+ wrapperId +'">';
if ( args.asyncLoad ) wrapper += args.loadHTML || '';
else wrapper += '<script src="'+ args.url +'"><\/script>';
wrapper += '<\/div>';
document.write(wrapper); */
var wrapper = '<div id="'+ wrapperId +'">';
if ( args.asyncLoad ) {
wrapper += (args.loadHTML || '') + '</div>';
}
else {
wrapper += '</div><script src="'+ args.url +'"><\/script>';
}
document.write(wrapper);
args.wrapperId = wrapperId;
if (embedGist.gistList) embedGist.gistList.push( args );
else loadNextGist(args); // immediately - onload already happened
}
/**
* a document.write replacement :
*/
embedGist.writeFunc = function() {
var args = arguments;
if ( args && args[0] ) {
embedGist.log('document.write() args[0] = ', args[0]);
var self = embedGist;
self.writeBuffer = (self.writeBuffer || '') + args[0];
}
else {
embedGist.log('document.write() ! args = ', args);
}
};
embedGist.getWriteBuffer = function() {return this.writeBuffer || '';};
embedGist.clearWriteBuffer = function() {this.writeBuffer = null;};
/**
* a custom list used to store args for which embedGist() has
* been called (for later processing - when the DOM is ready)
*/
embedGist.gistList = []; // a list of embedded gists
embedGist.gistList.yieldNext = function(callback) {
var self = this; //embedGist.gistList;
if ( ! self.next ) self.next = 0;
embedGist.log('yieldNext() next = ', self.next);
var nextElem = self[ self.next++ ]; // the args
if ( nextElem ) {
callback( nextElem );
return true;
}
else {
embedGist.log('yieldNext() no next - done !');
return false;
}
};
/**
* load the given gist as a script element and invoke callback when ready.
*/
embedGist.doLoad = function(args, callback) {
embedGist.log('doLoad() args = ', args);
// gist loading (args is the original embedGist args) :
var $wrapper = document.getElementById(args.wrapperId), self = this;
var removeLinkSibling = function($elem) { // removing embed.css
/*
var childNodes = $elem.childNodes;
for ( var i=0; i<childNodes.length; i++ ) {
if (childNodes[i].nodeName.toLowerCase() == 'link') {
$elem.removeChild(childNodes[i]);
break;
}
} */
var linkNode = $elem;
while ( linkNode && linkNode.nodeName.toLowerCase() != 'link' ) {
linkNode = linkNode.nextSibling;
}
if ( linkNode ) linkNode.parentNode.removeChild(linkNode);
};
if ( args.asyncLoad ) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', args.url);
var appendScriptHTML = function() {
var scriptHTML = self.getWriteBuffer();
embedGist.log('doLoad() scriptHTML.len = ', scriptHTML.length);
// insert the HTML just after the script node :
var tempDiv = document.createElement('div');
tempDiv.style.display = 'none';
var parentNode = script.parentNode;
parentNode.insertBefore(tempDiv, script.nextSibling);
tempDiv.innerHTML = scriptHTML;
// remove the link if requested :
if ( args.removeStyleLink ) removeLinkSibling(tempDiv.firstChild);
// hide the "loading" HTML :
$wrapper.style.visibility = 'hidden';
// now get rid of the temporary div wrapper :
while ( tempDiv.childNodes[0] ) { // as NodeList is live
parentNode.insertBefore(tempDiv.childNodes[0], tempDiv);
}
tempDiv.parentNode.removeChild(tempDiv);
}
if (script.readyState) { // IE
script.onreadystatechange = function() {
if (script.readyState == "loaded" ||
script.readyState == "complete") {
script.onreadystatechange = null;
appendScriptHTML(); callback();
}
};
}
else { // non-IE
script.onload = function() {
appendScriptHTML(); callback();
};
}
//var head = document.getElementsByTagName('head')[0];
//head.appendChild(script);
//$wrapper.appendChild(script);
$wrapper.parentNode.insertBefore(script, $wrapper.nextSibling);
}
else {
if ( args.removeStyleLink ) removeLinkSibling($wrapper.nextSibling);
callback();
}
if ( ! args.keepWrapper ) $wrapper.parentNode.removeChild($wrapper);
}
/**
* load all stored gist elements by iterating with doLoad() for each
*/
embedGist.doLoadAll = function(document) {
var self = this, gistList = self.gistList;
if ( ! gistList ) return; // already loaded or nothing to load
embedGist.log('doLoadAll() gistList.len = ', gistList.length);
var documentWrite = document.write;
var loadAndYieldNext = function(args) {
document.write = self.writeFunc;
self.doLoad(args, function() {
self.clearWriteBuffer();
document.write = documentWrite; // restore document.write
gistList.yieldNext(loadAndYieldNext); // recurse to next
});
};
gistList.yieldNext(loadAndYieldNext);
this.gistList = null;
};
/**
* logging helper
*/
embedGist.log = function() {
var debug = true;
try {
if ( debug && console ) console.log(arguments);
} catch (e) { /* */ }
}
if ( document.addEventListener ) { // non-IE
embedGist.loadFunc = function() {
document.removeEventListener( "DOMContentLoaded", embedGist.loadFunc, false );
embedGist.doLoadAll(document);
};
document.addEventListener("DOMContentLoaded", embedGist.loadFunc, false);
}
else if ( document.attachEvent ) { // IE
embedGist.loadFunc = function() {
if (document.readyState === "complete") { // make sure body exists
document.detachEvent( "onreadystatechange", embedGist.loadFunc );
embedGist.doLoadAll(document);
}
};
document.attachEvent("onreadystatechange", embedGist.loadFunc);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment