94 lines
2.9 KiB
Plaintext
94 lines
2.9 KiB
Plaintext
var QueryHandler = require('./QueryHandler');
|
|
var each = require('./Util').each;
|
|
|
|
/**
|
|
* Represents a single media query, manages it's state and registered handlers for this query
|
|
*
|
|
* @constructor
|
|
* @param {string} query the media query string
|
|
* @param {boolean} [isUnconditional=false] whether the media query should run regardless of whether the conditions are met. Primarily for helping older browsers deal with mobile-first design
|
|
*/
|
|
function MediaQuery(query, isUnconditional) {
|
|
this.query = query;
|
|
this.isUnconditional = isUnconditional;
|
|
this.handlers = [];
|
|
this.mql = window.matchMedia(query);
|
|
|
|
var self = this;
|
|
this.listener = function(mql) {
|
|
// Chrome passes an MediaQueryListEvent object, while other browsers pass MediaQueryList directly
|
|
self.mql = mql.currentTarget || mql;
|
|
self.assess();
|
|
};
|
|
this.mql.addListener(this.listener);
|
|
}
|
|
|
|
MediaQuery.prototype = {
|
|
|
|
constuctor : MediaQuery,
|
|
|
|
/**
|
|
* add a handler for this query, triggering if already active
|
|
*
|
|
* @param {object} handler
|
|
* @param {function} handler.match callback for when query is activated
|
|
* @param {function} [handler.unmatch] callback for when query is deactivated
|
|
* @param {function} [handler.setup] callback for immediate execution when a query handler is registered
|
|
* @param {boolean} [handler.deferSetup=false] should the setup callback be deferred until the first time the handler is matched?
|
|
*/
|
|
addHandler : function(handler) {
|
|
var qh = new QueryHandler(handler);
|
|
this.handlers.push(qh);
|
|
|
|
this.matches() && qh.on();
|
|
},
|
|
|
|
/**
|
|
* removes the given handler from the collection, and calls it's destroy methods
|
|
*
|
|
* @param {object || function} handler the handler to remove
|
|
*/
|
|
removeHandler : function(handler) {
|
|
var handlers = this.handlers;
|
|
each(handlers, function(h, i) {
|
|
if(h.equals(handler)) {
|
|
h.destroy();
|
|
return !handlers.splice(i,1); //remove from array and exit each early
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Determine whether the media query should be considered a match
|
|
*
|
|
* @return {Boolean} true if media query can be considered a match, false otherwise
|
|
*/
|
|
matches : function() {
|
|
return this.mql.matches || this.isUnconditional;
|
|
},
|
|
|
|
/**
|
|
* Clears all handlers and unbinds events
|
|
*/
|
|
clear : function() {
|
|
each(this.handlers, function(handler) {
|
|
handler.destroy();
|
|
});
|
|
this.mql.removeListener(this.listener);
|
|
this.handlers.length = 0; //clear array
|
|
},
|
|
|
|
/*
|
|
* Assesses the query, turning on all handlers if it matches, turning them off if it doesn't match
|
|
*/
|
|
assess : function() {
|
|
var action = this.matches() ? 'on' : 'off';
|
|
|
|
each(this.handlers, function(handler) {
|
|
handler[action]();
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = MediaQuery;
|