Skip to content

Commit ea49b48

Browse files
committed
Merge pull request #43 from weblinc/master
Rewrite of addListener to use window.resize rather than setInterval
2 parents fa1fcbc + 0903df1 commit ea49b48

File tree

1 file changed

+72
-44
lines changed

1 file changed

+72
-44
lines changed

matchMedia.addListener.js

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,75 @@
11
/*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */
22
(function(){
3-
// monkeypatch unsupported addListener/removeListener with polling
4-
if( !window.matchMedia( "all" ).addListener ){
5-
var oldMM = window.matchMedia;
6-
7-
window.matchMedia = function( q ){
8-
var ret = oldMM( q ),
9-
listeners = [],
10-
last = ret.matches,
11-
timer,
12-
check = function(){
13-
var list = oldMM( q ),
14-
unmatchToMatch = list.matches && !last,
15-
matchToUnmatch = !list.matches && last;
16-
17-
//fire callbacks only if transitioning to or from matched state
18-
if( unmatchToMatch || matchToUnmatch ){
19-
for( var i =0, il = listeners.length; i< il; i++ ){
20-
listeners[ i ].call( ret, list );
21-
}
22-
}
23-
last = list.matches;
24-
};
25-
26-
ret.addListener = function( cb ){
27-
listeners.push( cb );
28-
if( !timer ){
29-
timer = setInterval( check, 1000 );
30-
}
31-
};
32-
33-
ret.removeListener = function( cb ){
34-
for( var i =0, il = listeners.length; i< il; i++ ){
35-
if( listeners[ i ] === cb ){
36-
listeners.splice( i, 1 );
37-
}
38-
}
39-
if( !listeners.length && timer ){
40-
clearInterval( timer );
41-
}
42-
};
43-
44-
return ret;
45-
};
46-
}
3+
// Bail out for browsers that have addListener support
4+
if (window.matchMedia && window.matchMedia('all').addListener) {
5+
return false;
6+
}
7+
8+
var localMatchMedia = window.matchMedia,
9+
hasMediaQueries = localMatchMedia('only all').matches,
10+
isListening = false,
11+
timeoutID = 0, // setTimeout for debouncing 'handleChange'
12+
queries = [], // Contains each 'mql' and associated 'listeners' if 'addListener' is used
13+
handleChange = function(evt) {
14+
// Debounce
15+
clearTimeout(timeoutID);
16+
17+
timeoutID = setTimeout(function() {
18+
for (var i = 0, il = queries.length; i < il; i++) {
19+
var mql = queries[i].mql,
20+
listeners = queries[i].listeners || [],
21+
matches = localMatchMedia(mql.media).matches;
22+
23+
// Update mql.matches value and call listeners
24+
// Fire listeners only if transitioning to or from matched state
25+
if (matches !== mql.matches) {
26+
mql.matches = matches;
27+
28+
for (var j = 0, jl = listeners.length; j < jl; j++) {
29+
listeners[j].call(window, mql);
30+
}
31+
}
32+
}
33+
}, 30);
34+
};
35+
36+
window.matchMedia = function(media) {
37+
var mql = localMatchMedia(media),
38+
listeners = [],
39+
index = 0;
40+
41+
mql.addListener = function(listener) {
42+
// Changes would not occur to css media type so return now (Affects IE <= 8)
43+
if (!hasMediaQueries) {
44+
return;
45+
}
46+
47+
// Set up 'resize' listener for browsers that support CSS3 media queries (Not for IE <= 8)
48+
// There should only ever be 1 resize listener running for performance
49+
if (!isListening) {
50+
isListening = true;
51+
window.addEventListener('resize', handleChange, true);
52+
}
53+
54+
// Push object only if it has not been pushed already
55+
if (index === 0) {
56+
index = queries.push({
57+
mql : mql,
58+
listeners : listeners
59+
});
60+
}
61+
62+
listeners.push(listener);
63+
};
64+
65+
mql.removeListener = function(listener) {
66+
for (var i = 0, il = listeners.length; i < il; i++){
67+
if (listeners[i] === listener){
68+
listeners.splice(i, 1);
69+
}
70+
}
71+
};
72+
73+
return mql;
74+
};
4775
}());

0 commit comments

Comments
 (0)