Skip to content

Instantly share code, notes, and snippets.

@zacs
Created January 19, 2014 02:44
Show Gist options
  • Save zacs/8499789 to your computer and use it in GitHub Desktop.
Save zacs/8499789 to your computer and use it in GitHub Desktop.
Code for adding Grantland-style footnotes to Jekyll.
var Utils = {
cache: {},
watchResize: function(callback) {
//throttled resize
var resizing;
callback.size = 0;
function done()
{
var curr_size = window.innerWidth;
clearTimeout(resizing);
resizing = null;
// only run on a true resize
if (callback.size != curr_size)
{
callback();
callback.size = curr_size;
}
}
window.addEventListener('resize', function() {
if (resizing)
{
clearTimeout(resizing);
resizing = null;
}
resizing = setTimeout(done, 50);
});
},
MQ: function() {
//get current breakpoint/layout
return window.getComputedStyle(document.body, ':after').getPropertyValue('content').replace(/"/g, '');
}
};
var footnotes = {
config: {
footnoteClass: 'footnote',
activeClass: 'active-footnote',
contentWidth: 600,
offset: 20,
notePositions: []
},
getTarget: function(x) {
x = x || window.event;
return x.target || x.srcElement;
},
deactivate: function() {
//turn off any active footnotes just in case
var actives = document.querySelectorAll('.' + footnotes.config.activeClass);
for (var i = actives.length - 1; i >= 0; i--) {
actives[i].classList.remove(footnotes.config.activeClass);
}
},
hideNote: function(e) {
var target = footnotes.getTarget(e);
if (target.classList.contains(footnotes.config.footnoteClass)) {
footnotes.deactivate();
}
},
setPosition: function(target) {
var length = target.length;
for (var i = 0; i < length; i++) {
var note = footnotes.getNote($(target[i]));
if ($('.footnotes').css('position') == 'absolute') {
var body = $(this.ie6 ? document.body : document);
notePosX = Math.round((body.width() - footnotes.config.contentWidth) / 2) + footnotes.config.contentWidth + footnotes.config.offset;
notePosY = $(target[i]).position().top;
var fnLength = footnotes.config.notePositions.length;
for (var j = 0; j < fnLength; j++) {
if (notePosY <= footnotes.config.notePositions[j].bottom) {
notePosY = footnotes.config.notePositions[j].bottom + 20;
}
}
//make a note of both the offset and the height
footnotes.config.notePositions.push({top: notePosY, bottom: $(note)[0].offset + notePosY});
} else {
notePosX = $(target[i]).position().left;
//make sure it doesn't hang over the side
if (notePosX - (note.offsetWidth / 2) > 0) {
notePosX = notePosX - (note.offsetWidth / 2);
} else {
notePosX = 0;
}
//apply a little space so it sits below the link
notePosY = $(target[i]).position().top + footnotes.config.offset;
note.classList.add(footnotes.config.activeClass);
}
note.style.cssText = 'left:' + notePosX + 'px;top:' + notePosY + 'px;';
}
},
getNote: function(target) {
var noteLoc = target[0].hash.substr(1);
var note = document.getElementById(noteLoc);
return note;
},
toggleNote: function(e) {
var target = footnotes.getTarget(e);
var MQ = Utils.MQ();
if (target.classList.contains(footnotes.config.footnoteClass)) {
e.preventDefault();
var note = footnotes.getNote($(target));
if (note) {
if (note.classList.contains(footnotes.config.activeClass)) {
footnotes.deactivate();
} else {
footnotes.deactivate();
if (getComputedStyle($('.footnotes')[0]).position != 'absolute') {
footnotes.setPosition($(target));
}
}
}
return false;
} else {
footnotes.deactivate();
}
},
init: function(container) {
if (container) {
// set on state
container.addEventListener('mouseover', footnotes.toggleNote);
container.addEventListener('touchend', footnotes.toggleNote);
//set off state
container.addEventListener('mouseout', footnotes.hideNote);
if ($('.footnotes').css('position') == 'absolute') {
//if large, we need to set the position right away
footnotes.setPosition($('.' + footnotes.config.footnoteClass));
}
$('.footnotes').css({"visibility": "visible"});
}
}
};
// This should be called when the document is ready...
$( ".reversefootnote" ).remove();
if ($('.' + footnotes.config.footnoteClass).length > 0) {
$(window).bind('load', function() {
setTimeout(function() {
footnotes.init($('body')[0]);
}, 200);
});
Utils.watchResize(function() {
footnotes.config.notePositions = [];
footnotes.init($('body')[0]);
});
}
.footnotes {
visibility: hidden;
position: absolute;
left: 0;
top: 0;
width: 200px;
}
.footnotes ol li {
position: absolute;
top: 0px;
width: 160px;
margin-top: -10px;
}
.footnotes ol li p {
width: 160px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment