You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.7 KiB

(function() {
// Run callback when DOM is ready
function DOMReady(fn) {
// Run now if DOM has already loaded as we're loading async
if(['interactive', 'complete'].indexOf(document.readyState) >= 0) {
fn();
// Otherwise wait for DOM
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
// Feature tester
function FeatureTester(tests) {
var self = this;
self.tests = tests;
self.test = function(features) {
if(!features || !features.length) {
return false;
}
return features.every(function(feature) {
return self.tests[feature];
});
}
}
// Init once, don't re-detect features each time
var supports = new FeatureTester({
localStorage: (function() {
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
return true;
} catch (e) {
return false;
}
})(),
inlineSVG: (function() {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (
typeof SVGRect != 'undefined'
&& div.firstChild
&& div.firstChild.namespaceURI
) == 'http://www.w3.org/2000/svg';
})(),
querySelector: typeof document.querySelector === 'function',
classList: 'classList' in document.createElement('div')
});
// Favourite nodes
var favouriteNodes = {
// Key used in localStorage
storageKey: 'heartedNodes',
// Url to heart SVG
heartPath: '/assets/heart.svg',
// Class added to heart SVG element when active
activeClass: 'hearted',
// Gets current node hash
getCurrentNode: function() {
var node = /^\/node\/([a-zA-Z0-9]+)/.exec(window.location.pathname);
return node ? node[1] : node;
},
// Gets hearted nodes
getHeartedNodes: function() {
return JSON.parse(localStorage.getItem(favouriteNodes.storageKey)) || [];
},
// Saves hearted nodes
saveHeartedNodes: function(heartedNodes) {
return localStorage.setItem(favouriteNodes.storageKey, JSON.stringify(heartedNodes));
},
// Checks if node is hearted
isHearted: function(node) {
return favouriteNodes.getHeartedNodes().indexOf(node) > -1;
},
// Heart node
heart: function(node) {
var heartedNodes = favouriteNodes.getHeartedNodes();
heartedNodes.push(node);
return favouriteNodes.saveHeartedNodes(heartedNodes);
},
// Unheart node
unHeart: function(node) {
var heartedNodes = favouriteNodes.getHeartedNodes();
var nodeIndex = heartedNodes.indexOf(node);
heartedNodes.splice(nodeIndex, 1);
return favouriteNodes.saveHeartedNodes(heartedNodes);
},
// Load SVG, run callback when loaded
loadSVG: function(cb) {
// Get heart SVG
var xhr = new XMLHttpRequest();
xhr.open('GET', favouriteNodes.heartPath);
xhr.addEventListener('load', function() {
// Create heart SVG elem
var div = document.createElement('div');
div.innerHTML = xhr.responseText;
favouriteNodes.heartEl = div.firstChild;
// Show heart as active if we've already hearted this node
var node = favouriteNodes.getCurrentNode();
if(favouriteNodes.isHearted(node)) {
favouriteNodes.heartEl.classList.add(favouriteNodes.activeClass);
}
// Add click handler
favouriteNodes.heartEl.addEventListener('click', function() {
// Heart/unheart node
var node = favouriteNodes.getCurrentNode();
if(favouriteNodes.isHearted(node)) {
favouriteNodes.heartEl.classList.remove(favouriteNodes.activeClass);
favouriteNodes.unHeart(node);
} else {
favouriteNodes.heartEl.classList.add(favouriteNodes.activeClass);
favouriteNodes.heart(node);
}
});
// Run callback
cb(favouriteNodes.heartEl);
});
xhr.send();
}
};
// Init favourite nodes
if(supports.test(['localStorage', 'inlineSVG', 'querySelector', 'classList'])) {
// Start loading heart SVG before DOM
favouriteNodes.loadSVG(function(heartEl) {
// Then inject into DOM when it's ready
DOMReady(function() {
var titleEl = document.querySelector('h2.node-title');
if(titleEl) {
titleEl.insertBefore(heartEl, titleEl.firstChild);
}
});
});
}
// Add ios class to body on iOS devices
if(supports.test(['classList'])) {
DOMReady(function() {
if(
/iPad|iPhone|iPod/.test(navigator.userAgent)
&& !window.MSStream
&& document.body.classList
) {
document.body.classList.add('ios');
}
});
}
})();