diff --git a/src/core/util/media.js b/src/core/util/media.js index 0033a0d6985..6ea2eb4e6b4 100644 --- a/src/core/util/media.js +++ b/src/core/util/media.js @@ -10,21 +10,19 @@ angular.module('material.core') * @example $mdMedia('(min-width: 1200px)') == true if device-width >= 1200px * @example $mdMedia('max-width: 300px') == true if device-width <= 300px (sanitizes input, adding parens) */ -function mdMediaFactory($mdConstant, $mdUtil, $rootScope, $window) { - var queriesCache = $mdUtil.cacheFactory('$mdMedia:queries', {capacity: 15}); - var resultsCache = $mdUtil.cacheFactory('$mdMedia:results', {capacity: 15}); - - angular.element($window).on('resize', updateAll); +function mdMediaFactory($mdConstant, $rootScope, $window, $cacheFactory) { + var queries = {}; + var results = {}; return $mdMedia; function $mdMedia(query) { - var validated = queriesCache.get(query); + var validated = queries[query]; if (angular.isUndefined(validated)) { - validated = queriesCache.put(query, validate(query)); + validated = queries[query] = validate(query); } - var result = resultsCache.get(validated); + var result = results[validated]; if (angular.isUndefined(result)) { result = add(validated); } @@ -38,20 +36,16 @@ function mdMediaFactory($mdConstant, $mdUtil, $rootScope, $window) { } function add(query) { - return resultsCache.put(query, !!$window.matchMedia(query).matches); + var result = $window.matchMedia(query); + result.addListener(onQueryChange); + return (results[result.media] = !!result.matches); } - function updateAll() { - var keys = resultsCache.keys(); - var len = keys.length; - - if (len) { - for (var i = 0; i < len; i++) { - add(keys[i]); - } - - // Trigger a $digest() if not already in progress - $rootScope.$evalAsync(); - } + function onQueryChange() { + var query = this; + $rootScope.$evalAsync(function() { + results[query.media] = !!query.matches; + }); } + } diff --git a/src/core/util/media.spec.js b/src/core/util/media.spec.js index 41346b431f7..fb870354fd4 100644 --- a/src/core/util/media.spec.js +++ b/src/core/util/media.spec.js @@ -1,28 +1,32 @@ describe('$mdMedia', function() { var matchMediaResult; - var queriesCache; - var resultsCache; + var listeners; + function runListeners() { + listeners.forEach(function(cb) { + cb.context.matches = matchMediaResult; + cb.call(cb.context, cb); + }); + } beforeEach(module('material.core')); beforeEach(inject(function($cacheFactory, $mdMedia, $window) { matchMediaResult = false; - - queriesCache = $cacheFactory.get('$mdMedia:queries'); - resultsCache = $cacheFactory.get('$mdMedia:results'); - - spyOn($window, 'matchMedia').andCallFake(function() { - return {matches: matchMediaResult}; + listeners = []; + + spyOn($window, 'matchMedia').andCallFake(function(media) { + return { + media: media, + matches: matchMediaResult, + addListener: function(listener) { + listener.context = this; + listeners.push(listener); + } + }; }); })); - afterEach(function() { - queriesCache.removeAll(); - resultsCache.removeAll(); - }); - - it('should look up queries in `$mdConstant.MEDIA`', inject( function($mdConstant, $mdMedia, $window) { $mdConstant.MEDIA.somePreset = 'someQuery'; @@ -30,38 +34,26 @@ describe('$mdMedia', function() { $mdMedia('somePreset'); expect($window.matchMedia).toHaveBeenCalledWith('someQuery'); - delete($mdConstant.MEDIA.somePreset); + delete $mdConstant.MEDIA.somePreset; } )); - it('should look up validated queries in `queriesCache`', inject(function($mdMedia, $window) { - queriesCache.put('originalQuery', 'validatedQuery'); - - $mdMedia('originalQuery'); - expect($window.matchMedia).toHaveBeenCalledWith('validatedQuery'); - })); - it('should validate queries', inject(function($mdMedia, $window) { $mdMedia('something'); expect($window.matchMedia).toHaveBeenCalledWith('(something)'); })); - it('should cache validated queries in `queriesCache`', inject(function($mdMedia) { - $mdMedia('query'); - expect(queriesCache.get('query')).toBe('(query)'); - })); + it('should return cached results if available', inject(function($mdMedia, $window) { + expect($window.matchMedia.callCount).toBe(0); - it('should return cached results if available', inject(function($mdMedia) { - resultsCache.put('(query)', 'result'); - expect($mdMedia('(query)')).toBe('result'); - })); + expect($mdMedia('query')).toBe(false); + expect($window.matchMedia.callCount).toBe(1); - it('should cache results in `resultsCache`', inject(function($mdMedia) { - $mdMedia('(query)'); - expect(resultsCache.get('(query)')).toBe(false); + expect($mdMedia('query')).toBe(false); + expect($window.matchMedia.callCount).toBe(1); })); - it('should recalculate on resize', inject(function($mdMedia, $window) { + it('should change result when listener is called', inject(function($mdMedia, $window, $timeout) { matchMediaResult = true; expect($mdMedia('query')).toBe(true); expect($window.matchMedia.callCount).toBe(1); @@ -73,9 +65,9 @@ describe('$mdMedia', function() { expect($mdMedia('query')).toBe(true); expect($window.matchMedia.callCount).toBe(1); - angular.element($window).triggerHandler('resize'); + runListeners(); + $timeout.flush(); expect($mdMedia('query')).toBe(false); - expect($window.matchMedia.callCount).toBe(2); })); }); diff --git a/src/core/util/util.js b/src/core/util/util.js index 7ef7dcc33d6..21f2f3a33ea 100644 --- a/src/core/util/util.js +++ b/src/core/util/util.js @@ -10,7 +10,7 @@ var nextUniqueId = ['0','0','0']; angular.module('material.core') -.factory('$mdUtil', function($cacheFactory, $document, $timeout) { +.factory('$mdUtil', function($document, $timeout) { var Util; return Util = { @@ -48,11 +48,6 @@ angular.module('material.core') }; }, - /** - * @see cacheFactory below - */ - cacheFactory: cacheFactory, - // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. @@ -183,46 +178,6 @@ angular.module('material.core') } }; - - /* - * Inject a 'keys()' method into Angular's $cacheFactory. Then - * head-hook all other methods - * - */ - function cacheFactory(id, options) { - var cache = $cacheFactory(id, options); - var keys = {}; - - cache._put = cache.put; - cache.put = function(k,v) { - keys[k] = true; - return cache._put(k, v); - }; - - cache._remove = cache.remove; - cache.remove = function(k) { - delete keys[k]; - return cache._remove(k); - }; - - cache._removeAll = cache.removeAll; - cache.removeAll = function() { - keys = {}; - return cache._removeAll(); - }; - - cache._destroy = cache.destroy; - cache.destroy = function() { - keys = {}; - return cache._destroy(); - }; - - cache.keys = function() { - return Object.keys(keys); - }; - - return cache; - } }); /*