MediaQuery.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. var QueryHandler = require('./QueryHandler');
  2. var each = require('./Util').each;
  3. /**
  4. * Represents a single media query, manages it's state and registered handlers for this query
  5. *
  6. * @constructor
  7. * @param {string} query the media query string
  8. * @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
  9. */
  10. function MediaQuery(query, isUnconditional) {
  11. this.query = query;
  12. this.isUnconditional = isUnconditional;
  13. this.handlers = [];
  14. this.mql = window.matchMedia(query);
  15. var self = this;
  16. this.listener = function(mql) {
  17. // Chrome passes an MediaQueryListEvent object, while other browsers pass MediaQueryList directly
  18. self.mql = mql.currentTarget || mql;
  19. self.assess();
  20. };
  21. this.mql.addListener(this.listener);
  22. }
  23. MediaQuery.prototype = {
  24. constuctor : MediaQuery,
  25. /**
  26. * add a handler for this query, triggering if already active
  27. *
  28. * @param {object} handler
  29. * @param {function} handler.match callback for when query is activated
  30. * @param {function} [handler.unmatch] callback for when query is deactivated
  31. * @param {function} [handler.setup] callback for immediate execution when a query handler is registered
  32. * @param {boolean} [handler.deferSetup=false] should the setup callback be deferred until the first time the handler is matched?
  33. */
  34. addHandler : function(handler) {
  35. var qh = new QueryHandler(handler);
  36. this.handlers.push(qh);
  37. this.matches() && qh.on();
  38. },
  39. /**
  40. * removes the given handler from the collection, and calls it's destroy methods
  41. *
  42. * @param {object || function} handler the handler to remove
  43. */
  44. removeHandler : function(handler) {
  45. var handlers = this.handlers;
  46. each(handlers, function(h, i) {
  47. if(h.equals(handler)) {
  48. h.destroy();
  49. return !handlers.splice(i,1); //remove from array and exit each early
  50. }
  51. });
  52. },
  53. /**
  54. * Determine whether the media query should be considered a match
  55. *
  56. * @return {Boolean} true if media query can be considered a match, false otherwise
  57. */
  58. matches : function() {
  59. return this.mql.matches || this.isUnconditional;
  60. },
  61. /**
  62. * Clears all handlers and unbinds events
  63. */
  64. clear : function() {
  65. each(this.handlers, function(handler) {
  66. handler.destroy();
  67. });
  68. this.mql.removeListener(this.listener);
  69. this.handlers.length = 0; //clear array
  70. },
  71. /*
  72. * Assesses the query, turning on all handlers if it matches, turning them off if it doesn't match
  73. */
  74. assess : function() {
  75. var action = this.matches() ? 'on' : 'off';
  76. each(this.handlers, function(handler) {
  77. handler[action]();
  78. });
  79. }
  80. };
  81. module.exports = MediaQuery;