Skip to content
This repository was archived by the owner on Jul 3, 2024. It is now read-only.

Commit c09871d

Browse files
Merge pull request #12 from dryan/master
Importing eCSStender::matchMedia method
2 parents 66de01a + 81b8e2e commit c09871d

File tree

3 files changed

+310
-4
lines changed

3 files changed

+310
-4
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
*v1.2.8 (2011-07-14)
2+
* added eCSStender::matchMedia() method
3+
14
*v1.2.6.6* (2010-08-26)
25
* bugfix: don't call determinePath() on embedded stylesheets
36

src/eCSStender.js

Lines changed: 222 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,28 @@ License: MIT License (see homepage)
5656
HYPHEN = '-',
5757
OPEN_CURLY = '{',
5858
CLOSE_CURLY = '}',
59+
COMMA = ',',
5960
DIV = 'div',
6061
TYPE = 'type',
6162
COMPLETE = 'complete',
63+
BODY = 'body',
64+
ORIENTATION = 'orientation',
65+
PORTRAIT = 'portrait',
66+
LANDSCAPE = 'landscape',
67+
WIDTH = 'width',
68+
MAXWIDTH = 'max-width',
69+
MINWIDTH = 'min-width',
70+
DEVWIDTH = 'device-width',
71+
DEVMAXWIDTH = 'max-device-width',
72+
DEVMINWIDTH = 'min-device-width',
73+
HEIGHT = 'height',
74+
MAXHEIGHT = 'max-height',
75+
MINHEIGHT = 'min-height',
76+
DEVHEIGHT = 'device-height',
77+
DEVMAXHEIGHT = 'max-device-height',
78+
DEVMINHEIGHT = 'min-device-height',
79+
PX = 'px',
80+
PT = 'pt',
6281

6382
// Regex Bits
6483
ANYTHING = '.*?',
@@ -76,6 +95,7 @@ License: MIT License (see homepage)
7695
__s = 0, // index of current stylesheet
7796
__style_objects = {}, // style rules to track
7897
__media_groups = {},
98+
__media_queries = {}, // all styles where a CSS3-style media queries is in use
7999
__xhr = NULL,
80100
__initialized = FALSE,
81101
__ignored_css = [],
@@ -121,11 +141,13 @@ License: MIT License (see homepage)
121141
REGEXP_ATRULE = /@([\w-]+)(.*?)\{([^}]*)\}/ig,
122142
// for splitting properties from values
123143
REGEXP_P_V = /:(?!\/\/)/,
144+
// for detecting CSS3-style media queries
145+
REGEXP_MQ_PARENS = /\(.*:.*\)/,
124146

125147
// eCSStender Object
126148
eCSStender = {
127149
name: ECSSTENDER,
128-
version: '1.2.7',
150+
version: '1.2.8',
129151
fonts: [],
130152
pages: {},
131153
at: {},
@@ -158,6 +180,7 @@ License: MIT License (see homepage)
158180
{
159181
validateCache();
160182
runTests();
183+
getMediaQueryStyles();
161184
eCSStend();
162185
triggerCallbacks();
163186
writeBrowserCache();
@@ -181,6 +204,15 @@ License: MIT License (see homepage)
181204
__xhr = TRUE;
182205
}
183206
}
207+
function getMediaQueryStyles() {
208+
var mediaQueryRegex = newRegExp(REGEXP_MQ_PARENS);
209+
for( var styleObject in __style_objects ) {
210+
if( mediaQueryRegex.test(styleObject) ) {
211+
__media_queries[ styleObject ] = __style_objects[ styleObject ];
212+
}
213+
}
214+
eCSStender.mediaQueryStyles = __media_queries;
215+
}
184216
function parseStyles()
185217
{
186218
var s=0, sLen=__stylesheets.length, media, m, mLen;
@@ -2428,7 +2460,194 @@ License: MIT License (see homepage)
24282460
}
24292461
};
24302462
eCSStender.toggleClass = toggleClass;
2431-
2463+
/**
2464+
* eCSStender.matchMedia()
2465+
* returns true if the media query matches the state of rendered document
2466+
* and false if it does not (does not take into account things like "screen",
2467+
* "print" or "handheld", though native support does)
2468+
*
2469+
* based on http://dev.w3.org/csswg/cssom-view/
2470+
* uses native matchMedia if available
2471+
*
2472+
* @param str query - the media query to test
2473+
*/
2474+
function matchMedia( query ) {
2475+
if( defined( WINDOW.matchMedia ) ) {
2476+
console.log(query, WINDOW.matchMedia(query).matches);
2477+
return WINDOW.matchMedia( query ).matches;
2478+
} else {
2479+
function convertToPixels( val ) {
2480+
var
2481+
number = parseInt(val.replace(/[^\d]+/g, ''), 10),
2482+
unit = val.replace(number, '');
2483+
switch(unit) {
2484+
case PX:
2485+
break;
2486+
case PT:
2487+
number = number * 96 / 72;
2488+
break;
2489+
default:
2490+
break;
2491+
}
2492+
return number;
2493+
}
2494+
var
2495+
getWidth,
2496+
getHeight;
2497+
getWidth = function() {
2498+
var _body = document.getElementsByTagName(BODY)[0];
2499+
return _body.clientWidth + convertToPixels( getCSSValue( _body, 'margin-left' ) ) + convertToPixels( getCSSValue( _body, 'margin-right' ) );
2500+
}
2501+
if( defined( window.innerHeight ) ) {
2502+
getHeight = function() { return window.innerHeight; }
2503+
} else if ( defined( document.documentElement ) && defined( document.documentElement.clientHeight ) && document.documentElement.clientHeight ) {
2504+
getHeight = function() { return document.documentElement.clientHeight; }
2505+
} else {
2506+
getHeight = function() { return document.getElementsByTagName(BODY)[0].clientHeight; }
2507+
}
2508+
2509+
matchMedia = function( query ) {
2510+
if(query.indexOf(COMMA) > -1) { // handle OR conditions
2511+
var
2512+
queries = query.split(COMMA),
2513+
i = queries.length;
2514+
while( i ) {
2515+
var q = queries[i - 1];
2516+
q = trim(q);
2517+
if( matchMedia(q) ) { // if any of the conditions match, we can return true and bail
2518+
return TRUE;
2519+
}
2520+
i--;
2521+
}
2522+
}
2523+
var
2524+
queries = query.split(' and '), // split the query into each condition
2525+
matches = TRUE, // optimism
2526+
mediaQueryRegex = newRegExp(REGEXP_MQ_PARENS),
2527+
W = getWidth(),
2528+
DW = screen.width,
2529+
H = getHeight(),
2530+
DH = screen.height;
2531+
i = queries.length;
2532+
while ( i ) {
2533+
var q = queries[i - 1];
2534+
if(mediaQueryRegex.test(q)) { // we only test query parts in the style of (property:value)
2535+
var
2536+
q = q.split(COLON),
2537+
prop = q[0].toLowerCase(),
2538+
val = q[1];
2539+
2540+
prop = prop.replace(/^\(/, EMPTY);
2541+
val = val.replace(/\)$/, EMPTY);
2542+
2543+
if( prop != ORIENTATION ) {
2544+
val = convertToPixels(val);
2545+
}
2546+
switch( prop ) {
2547+
case ORIENTATION:
2548+
switch( val ) {
2549+
case LANDSCAPE:
2550+
if( W < H )
2551+
{
2552+
matches = FALSE;
2553+
}
2554+
break;
2555+
case PORTRAIT:
2556+
if( W > H )
2557+
{
2558+
matches = FALSE;
2559+
}
2560+
break;
2561+
default:
2562+
// we only support landscape and portrait
2563+
break;
2564+
}
2565+
break;
2566+
case WIDTH:
2567+
if( W != val )
2568+
{
2569+
matches = FALSE;
2570+
}
2571+
break;
2572+
case MAXWIDTH:
2573+
if( W > val )
2574+
{
2575+
matches = FALSE;
2576+
}
2577+
break;
2578+
case MINWIDTH:
2579+
if( W < val )
2580+
{
2581+
matches = FALSE;
2582+
}
2583+
break;
2584+
case DEVWIDTH:
2585+
if( DW != val )
2586+
{
2587+
matches = FALSE;
2588+
}
2589+
break;
2590+
case DEVMAXWIDTH:
2591+
if( DW > val )
2592+
{
2593+
matches = FALSE;
2594+
}
2595+
break;
2596+
case DEVMINWIDTH:
2597+
if( DW < val )
2598+
{
2599+
matches = FALSE;
2600+
}
2601+
break;
2602+
case HEIGHT:
2603+
if( H != val )
2604+
{
2605+
matches = FALSE;
2606+
}
2607+
break;
2608+
case MAXHEIGHT:
2609+
if( H > val )
2610+
{
2611+
matches = FALSE;
2612+
}
2613+
break;
2614+
case MINHEIGHT:
2615+
if( H < val )
2616+
{
2617+
matches = FALSE;
2618+
}
2619+
break;
2620+
case DEVHEIGHT:
2621+
if( DH != val )
2622+
{
2623+
matches = FALSE;
2624+
}
2625+
break;
2626+
case DEVMAXHEIGHT:
2627+
if( DH > val )
2628+
{
2629+
matches = FALSE;
2630+
}
2631+
break;
2632+
case DEVMINHEIGHT:
2633+
if( DH < val )
2634+
{
2635+
matches = FALSE;
2636+
}
2637+
break;
2638+
default:
2639+
break;
2640+
}
2641+
}
2642+
i--;
2643+
};
2644+
2645+
return matches;
2646+
}
2647+
return matchMedia( query );
2648+
}
2649+
}
2650+
eCSStender.matchMedia = matchMedia;
24322651
/*-------------------------------------*
24332652
* DOM Loaded Trigger *
24342653
* Based on jQuery's *
@@ -2480,5 +2699,5 @@ License: MIT License (see homepage)
24802699
}
24812700
}
24822701
})();
2483-
2702+
24842703
})();

tests/js/core.js

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,89 @@ eCSStender.onComplete(function(){
178178
matches = eCSStender.lookup({'selector':'#bar'},'*');
179179
ok( matches.length===0, 'array of css files ignored' );
180180
});
181-
181+
module('Media Queries');
182+
test( 'eCSStender::matchMedia', function(){
183+
ok( typeof(eCSStender.matchMedia) == 'function', 'eCSStender::matchMedia() exists' );
184+
if( typeof(window.matchMedia) != 'undefined' && false ) {
185+
ok(true, 'window.matchMedia exists, these tests are using the native method');
186+
}
187+
var
188+
W = $(window).width(),
189+
H = $(window).height(),
190+
DW = screen.width,
191+
DH = screen.height,
192+
O = W > H ? 'landscape' : 'portrait';
193+
194+
// orientation
195+
ok( eCSStender.matchMedia('screen and (orientation:portrait)') == (O == 'portrait'), '(orientation:portrait) ' + (O == 'portrait' ? 'matched' : 'does not match') );
196+
ok( eCSStender.matchMedia('screen and (orientation:landscape)') == (O == 'landscape'), '(orientation:landscape) ' + (O == 'landscape' ? 'matched' : 'does not match') );
197+
198+
// width
199+
ok( eCSStender.matchMedia('screen and (width:' + W + 'px)'), 'width set to window width matches' );
200+
ok( !eCSStender.matchMedia('screen and (width:' + (W - 100) + 'px)'), 'width set to window width - 100 does not match' );
201+
ok( !eCSStender.matchMedia('screen and (width:' + (W + 100) + 'px)'), 'width set to window width + 100 does not match' );
202+
203+
// max-width
204+
ok( eCSStender.matchMedia('screen and (max-width:' + W + 'px)'), 'max-width set to window width matches' );
205+
ok( !eCSStender.matchMedia('screen and (max-width:' + (W - 100) + 'px)'), 'max-width set to window width - 100 does not match' );
206+
ok( eCSStender.matchMedia('screen and (max-width:' + (W + 100) + 'px)'), 'max-width set to window width + 100 matches' );
207+
208+
// min-width
209+
ok( eCSStender.matchMedia('screen and (min-width:' + W + 'px)'), 'min-width set to window width matches' );
210+
ok( eCSStender.matchMedia('screen and (min-width:' + (W - 100) + 'px)'), 'min-width set to window width - 100 matches' );
211+
ok( !eCSStender.matchMedia('screen and (min-width:' + (W + 100) + 'px)'), 'min-width set to window width + 100 does not match' );
212+
213+
// device-width
214+
ok( eCSStender.matchMedia('screen and (device-width:' + DW + 'px)'), 'device-width set to device-width matches' );
215+
ok( !eCSStender.matchMedia('screen and (device-width:' + (DW - 100) + 'px)'), 'device-width set to device-width - 100 does not match' );
216+
ok( !eCSStender.matchMedia('screen and (device-width:' + (DW + 100) + 'px)'), 'device-width set to device-width + 100 does not match' );
217+
218+
// max-device-width
219+
ok( eCSStender.matchMedia('screen and (max-device-width:' + DW + 'px)'), 'max-device-width set to device-width matches' );
220+
ok( !eCSStender.matchMedia('screen and (max-device-width:' + (DW - 100) + 'px)'), 'max-device-width set to device-width - 100 does not match' );
221+
ok( eCSStender.matchMedia('screen and (max-device-width:' + (DW + 100) + 'px)'), 'max-device-width set to device-width + 100 matches' );
222+
223+
// min-device-width
224+
ok( eCSStender.matchMedia('screen and (min-device-width:' + DW + 'px)'), 'min-device-width set to device-width matches' );
225+
ok( eCSStender.matchMedia('screen and (min-device-width:' + (DW - 100) + 'px)'), 'min-device-width set to device-width - 100 matches' );
226+
ok( !eCSStender.matchMedia('screen and (min-device-width:' + (DW + 100) + 'px)'), 'min-device-width set to device-width + 100 does not match' );
227+
228+
// height
229+
ok( eCSStender.matchMedia('screen and (height:' + H + 'px)'), 'height set to window height matches' );
230+
ok( !eCSStender.matchMedia('screen and (height:' + (H - 100) + 'px)'), 'height set to window height - 100 does not match' );
231+
ok( !eCSStender.matchMedia('screen and (height:' + (H + 100) + 'px)'), 'height set to window height + 100 does not match' );
232+
233+
// max-height
234+
ok( eCSStender.matchMedia('screen and (max-height:' + H + 'px)'), 'max-height set to window height matches' );
235+
ok( !eCSStender.matchMedia('screen and (max-height:' + (H - 100) + 'px)'), 'max-height set to window height - 100 does not match' );
236+
ok( eCSStender.matchMedia('screen and (max-height:' + (H + 100) + 'px)'), 'max-height set to window height + 100 matches' );
237+
238+
// min-height
239+
ok( eCSStender.matchMedia('screen and (min-height:' + H + 'px)'), 'min-height set to window height matches' );
240+
ok( eCSStender.matchMedia('screen and (min-height:' + (H - 100) + 'px)'), 'min-height set to window height - 100 matches' );
241+
ok( !eCSStender.matchMedia('screen and (min-height:' + (H + 100) + 'px)'), 'min-height set to window height + 100 does not match' );
242+
243+
// device-height
244+
ok( eCSStender.matchMedia('screen and (device-height:' + DH + 'px)'), 'device-height set to device-height matches' );
245+
ok( !eCSStender.matchMedia('screen and (device-height:' + (DH - 100) + 'px)'), 'device-height set to device-height - 100 does not match' );
246+
ok( !eCSStender.matchMedia('screen and (device-height:' + (DH + 100) + 'px)'), 'device-height set to device-height + 100 does not match' );
247+
248+
// max-device-height
249+
ok( eCSStender.matchMedia('screen and (max-device-height:' + DH + 'px)'), 'max-device-height set to device-height matches' );
250+
ok( !eCSStender.matchMedia('screen and (max-device-height:' + (DH - 100) + 'px)'), 'max-device-height set to device-height - 100 does not match' );
251+
ok( eCSStender.matchMedia('screen and (max-device-height:' + (DH + 100) + 'px)'), 'max-device-height set to device-height + 100 matches' );
252+
253+
// min-device-height
254+
ok( eCSStender.matchMedia('screen and (min-device-height:' + DH + 'px)'), 'min-device-height set to device-height matches' );
255+
ok( eCSStender.matchMedia('screen and (min-device-height:' + (DH - 100) + 'px)'), 'min-device-height set to device-height - 100 matches' );
256+
ok( !eCSStender.matchMedia('screen and (min-device-height:' + (DH + 100) + 'px)'), 'min-device-height set to device-height + 100 does not match' );
257+
258+
// complex rules
259+
ok( eCSStender.matchMedia('screen and (min-width:' + (W - 100) + 'px) and (max-width:' + (W + 100) + 'px)'), '' + 'screen and (min-width:' + (W - 100) + 'px) and (max-width:' + (W + 100) + 'px) matches');
260+
ok( eCSStender.matchMedia('screen and (min-height:' + (H - 100) + 'px) and (max-height:' + (H + 100) + 'px)'), '' + 'screen and (min-height:' + (H - 100) + 'px) and (max-height:' + (H + 100) + 'px) matches');
261+
ok( eCSStender.matchMedia('screen and (min-width:' + (W - 100) + 'px), screen and (max-width:' + (W + 100) + 'px)'), '' + 'screen and (min-width:' + (W - 100) + 'px), screen and (max-width:' + (W + 100) + 'px) matches');
262+
ok( eCSStender.matchMedia('screen and (min-width:' + (W - 100) + 'px) and (orientation:' + O + ')'), '' + 'screen and (min-width:' + (W - 100) + 'px) and (orientation:' + O + ') matches');
263+
ok( !eCSStender.matchMedia('screen and (min-width:' + (W - 100) + 'px) and (orientation:' + ( O == 'portrait' ? 'landscape' : 'portrait' ) + ')'), '' + 'screen and (min-width:' + (W - 100) + 'px) and (orientation:' + ( O == 'portrait' ? 'landscape' : 'portrait' ) + ') does not match');
264+
ok( !eCSStender.matchMedia('screen and (max-width:' + (W - 100) + 'px), screen and (orientation:' + ( O == 'portrait' ? 'landscape' : 'portrait' ) + ')'), '' + 'screen and (max-width:' + (W - 100) + 'px), screen and (orientation:' + ( O == 'portrait' ? 'landscape' : 'portrait' ) + ') does not match');
265+
});
182266
});

0 commit comments

Comments
 (0)