Skip to content

Instantly share code, notes, and snippets.

@jongacnik
Last active August 29, 2015 14:08
Show Gist options
  • Save jongacnik/d7afb00d4cbc0b30f624 to your computer and use it in GitHub Desktop.
Save jongacnik/d7afb00d4cbc0b30f624 to your computer and use it in GitHub Desktop.
Breakpoints module
/**
* Functionality:
* - adds breakpoint attributes to body & fires callbacks
*
* todo: callback params, height, matchMedia?
*/
var extend = require('extend');
var _data = {
currentBreakpoints : [],
currentIdentifier : null
};
var options = {
breakpoints : [],
attribute : 'data-breakpoint',
waterfall : true,
always : function(){ },
outside : function(){ },
};
var init = function(opts){
options = extend(true, options, opts);
window.addEventListener('resize', _navigate);
};
var _sortBreakpoints = function(){
options.breakpoints.sort(function(a, b) {
return b.max - a.max;
});
};
var _run = function(fcn){
if(typeof fcn === 'function')
fcn();
};
var _navigate = function(){
_sortBreakpoints();
var winW = window.innerWidth;
var tempBreakpoints = [];
var tempIdentifier = false;
for(var i = 0; i <= options.breakpoints.length - 1; i++){
var bp = options.breakpoints[i];
if(('name' in bp) && ('max' in bp)){
if(options.breakpoints[0].max < winW) break; // there are no applicable breakpoints
if(bp.max > winW) {
tempBreakpoints.push(bp); // if screen falls within breakpoint, save it
tempIdentifier = bp;
} else break; // as soon as we out, break
}
}
if(tempIdentifier !== _data.currentIdentifier){ // if there is a change...
_data.currentIdentifier = tempIdentifier;
_data.currentBreakpoints = tempBreakpoints;
_run(options.always); // run always callback
if(!_data.currentIdentifier){ // if we are outside, run outside callback & clear attribute
document.body.setAttribute(options.attribute, '');
_run(options.outside);
} else { // otherwise...
// get closest breakpoint and set attribute
var closest = _data.currentBreakpoints[_data.currentBreakpoints.length-1];
document.body.setAttribute(options.attribute, closest.name);
if(options.waterfall){ // if waterfall, loop through applicable breakpoints and run callbacks
for(var i = 0; i <= _data.currentBreakpoints.length - 1; i++)
_run(_data.currentBreakpoints[i].callback);
} else _run(closest.callback); // otherwise just run closest breakpoint callback
}
}
};
var add = function(opts){
if(('name' in opts) && ('max' in opts)){
options.breakpoints.push({
'name' : opts.name,
'max' : opts.max,
'callback' : opts.callback
});
} else {
console.log('You need at least a name and max value defined');
}
};
module.exports = {
'init' : init,
'add' : add,
'navigate' : _navigate
};
var breakpoints = require('./breakpoints.js');
breakpoints.init({
attribute : 'data-breakpoint', // attribute to be added to body
waterfall : true, // should all applicable callbacks be fired?
});
breakpoints.add({
name : 'mobile',
max : 767,
callback : function(){ console.log('mobile'); }
});
breakpoints.add({
name : 'tablet',
max : 1050,
callback : function(){ console.log('tablet'); }
});
breakpoints.navigate();
/**
* Functionality:
* - adds breakpoint attributes to body & fires callbacks
*
* In Progress! Trying to make this whole thing a little more legible
*/
var extend = require('extend');
var data = {
currentBreakpoints : []
};
var options = {
breakpoints : [],
attribute : 'data-breakpoint',
always : function(){ },
outside : function(){ },
};
var init = function(opts){
options = extend(true, options, opts);
window.addEventListener('resize', update);
};
var run = function(fcn){
if(typeof fcn === 'function') fcn();
};
var arraysEqual = function(arr1, arr2) {
if(arr1.length !== arr2.length)
return false;
for(var i = arr1.length; i--;) {
if(arr1[i] !== arr2[i])
return false;
}
return true;
}
var sortBreakpoints = function(){
options.breakpoints.sort(function(a, b) {
return b.max - a.max;
});
};
var getCurrentBreakpoints = function(){
sortBreakpoints();
var applicable = [];
for(var i = 0; i <= options.breakpoints.length - 1; i++){
var bp = options.breakpoints[i];
if(('name' in bp) && ('max' in bp)){
if(options.breakpoints[0].max < winW) break; // there are no applicable breakpoints
if(bp.max > winW) {
applicable.push(bp); // if screen falls within breakpoint, save it
} else break; // as soon as we out, break
}
}
return applicable;
};
var testBreakpointChange = function(breakpoint){
var currentBreakpoints = getCurrentBreakpoints();
if(arraysEqual(currentBreakpoints, data.currentBreakpoints))
return false;
else {
data.currentBreakpoints = currentBreakpoints;
return true;
}
};
var update = function(){
if(testBreakpointChange) navigate();
};
var navigate = function(){
run(options.always); // run always callback
if(data.currentBreakpoints.length < 1){ // if we are outside, run outside callback & clear attribute
document.body.setAttribute(options.attribute, '');
run(options.outside);
} else { // otherwise...
// get closest breakpoint and set attribute
var closest = data.currentBreakpoints[data.currentBreakpoints.length-1];
document.body.setAttribute(options.attribute, closest.name);
if(options.waterfall){ // if waterfall, loop through applicable breakpoints and run callbacks
for(var i = 0; i <= data.currentBreakpoints.length - 1; i++)
run(data.currentBreakpoints[i].callback);
} else run(closest.callback); // otherwise just run closest breakpoint callback
}
};
var add = function(opts){
if(('name' in opts) && ('max' in opts)){
options.breakpoints.push({
'name' : opts.name,
'max' : opts.max,
'callback' : opts.callback
});
} else {
console.log('You need at least a name and max value defined');
}
};
module.exports = {
'init' : init,
'add' : add,
'navigate' : update
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment