build/borealis.js
//////////////////////////////
// eq.js
// The global borealis object that contains all borealis functionality.
//
// borealis.nodes - List of all nodes to act upon when borealis.states is called
// borealis.nodesLength - Number of nodes in borealis.nodes
//
// borealis.refreshNodes - Call this function to refresh the list of nodes that borealis should act on
// borealis.sortObj - Sorts a key: value object based on value
// borealis.query - Runs through all nodes and finds their widths and points
// borealis.nodeWrites - Runs through all nodes and writes their image source
//////////////////////////////
(function (borealis) {
'use strict';
function Borealis() {
this.nodes = [];
this.brlLength = 0;
this.widths = [];
this.points = [];
this.callback = undefined;
}
//////////////////////////////
// Add event (cross browser)
// From http://stackoverflow.com/a/10150042
//////////////////////////////
function addEvent(elem, event, fn) {
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent('on' + event, function () {
// set the this pointer same as addEventListener when fn is called
return (fn.call(elem, window.event));
});
}
}
//////////////////////////////
// Query
//
// Reads nodes and finds the widths/points
// nodes - optional, an array or NodeList of nodes to query
// callback - Either boolean (`true`/`false`) to force a normal callback, or a function to use as a callback once query and nodeWrites have finished.
//////////////////////////////
Borealis.prototype.query = function (nodes, callback) {
var proto = Object.getPrototypeOf(borealis);
var length;
if (callback && typeof(callback) === 'function') {
proto.callback = callback;
}
if (nodes && typeof(nodes) !== 'number') {
length = nodes.length;
}
else {
nodes = proto.nodes;
length = proto.nodesLength;
}
var widths = [], points = [], i;
for (i = 0; i < length; i++) {
widths.push(nodes[i].offsetWidth);
try {
points.push(proto.sortObj(nodes[i].getAttribute('data-borealis-srcs')));
}
catch (e) {
points.push({});
}
}
proto.widths = widths;
proto.points = points;
if (nodes && typeof(nodes) !== 'number') {
proto.nodeWrites(nodes, widths, points);
}
else if (callback && typeof(callback) !== 'function') {
proto.nodeWrites();
}
else {
window.requestAnimationFrame(proto.nodeWrites);
}
};
//////////////////////////////
// NodeWrites
//
// Writes the data attribute to the object
// nodes - optional, an array or NodeList of nodes to query
// widths - optional, widths of nodes to use. Only used if `nodes` is passed in
// points - optional, points of nodes to use. Only used if `nodes` is passed in
//////////////////////////////
Borealis.prototype.nodeWrites = function (nodes) {
var i,
length,
callback,
proto = Object.getPrototypeOf(borealis),
widths = proto.widths,
points = proto.points;
if (nodes && typeof(nodes) !== 'number') {
length = nodes.length;
}
else {
nodes = proto.nodes;
length = proto.nodesLength;
}
for (i = 0; i < length; i++) {
// Set object width to found width
var objWidth = widths[i];
var obj = nodes[i];
var brlSrcs = points[i];
// Get keys for states
var brlSrcsLength = brlSrcs.length;
if (brlSrcsLength === 1) {
obj.setAttribute('src', brlSrcs[0].value);
}
// Be greedy for smallest state
else if (objWidth < brlSrcs[1].key) {
obj.setAttribute('src', brlSrcs[0].value);
}
// Be greedy for largest state
else if (objWidth >= brlSrcs[brlSrcsLength - 1].key) {
obj.setAttribute('src', brlSrcs[brlSrcsLength - 1].value);
}
// Traverse the states if not found
else {
for (var j = 0; j < brlSrcsLength; j++) {
var current = brlSrcs[j];
var next = brlSrcs[j + 1];
if (j === 0 && objWidth < current.key) {
obj.setAttribute('src', brlSrcs[0].value);
break;
}
if (next.key === undefined) {
obj.setAttribute('src', next.value);
break;
}
if (objWidth >= current.key && objWidth < next.key) {
obj.setAttribute('src', current.value);
break;
}
}
}
}
// Run Callback
if (proto.callback) {
callback = proto.callback;
proto.callback = undefined;
callback(nodes);
}
};
//////////////////////////////
// Refresh Nodes
// Refreshes the list of nodes for borealis to work with
//////////////////////////////
Borealis.prototype.refreshNodes = function () {
var proto = Object.getPrototypeOf(borealis);
proto.nodes = document.querySelectorAll('[data-borealis-srcs]');
proto.nodesLength = proto.nodes.length;
};
//////////////////////////////
// Sort Object
// Sorts a simple object (key: value) by value and returns a sorted object
//////////////////////////////
Borealis.prototype.sortObj = function (obj) {
var arr = [];
var objSplit = obj.split(',');
for (var i = 0; i < objSplit.length; i++) {
if (i === 0) {
arr.push({
'key': -1,
'value': objSplit[i]
});
}
else {
var sSplit = objSplit[i].replace(/:+/, '\x01').split('\x01');
arr.push({
'key': parseFloat(sSplit[0]),
'value': sSplit[1].replace(/^\s+|\s+$/g, '')
});
}
}
return arr.sort(function (a, b) { return a.value - b.value; });
};
//////////////////////////////
// Style Images
// Adds styling to set up width and height appropriately
//////////////////////////////
Borealis.prototype.styleImages = function (nodes) {
nodes = nodes || Object.getPrototypeOf(borealis).nodes;
var nodeLength = nodes.length;
for (var i = 0; i < nodeLength; i++) {
nodes[i].style.width = 100 + '%';
nodes[i].style.height = 'auto';
}
};
//////////////////////////////
// We only ever want there to be
// one instance of Borealis in an app
//////////////////////////////
borealis = borealis || new Borealis();
//////////////////////////////
// Window Onload
//
// Fires on load
//////////////////////////////
addEvent(window, 'DOMContentLoaded', function () {
borealis.refreshNodes();
borealis.styleImages();
borealis.query(undefined, true);
});
//////////////////////////////
// Window Resize
//
// Loop over each `eq-pts` element and pass to eqState
//////////////////////////////
addEvent(window, 'resize', function () {
borealis.refreshNodes();
window.requestAnimationFrame(borealis.query);
});
// Expose 'borealis'
if (typeof module !== 'undefined' && module.exports) {
module.exports = borealis;
} else if (typeof define === 'function' && define.amd) {
define(function () {
return borealis;
});
} else {
window.borealis = borealis;
}
})(window.borealis);