2013-03-29 7 views
14

Ho utilizzato un numero di librerie (incluso il mio) per caricare dinamicamente le risorse in base alle query multimediali che ho delineato nei file CSS. Per esempio:Accesso alle regole di query media CSS tramite JavaScript/DOM

In CSS:

@media screen and (max-width: 480px) { 
    .foo { 
     display: none; 
    } 
    } 

E utilizzando un caricatore di asset; require.js, modernizr.js ecc o utilizzando window.matchMedia e associati addListener() funzioni:

if (function("screen and (max-width: 480px)")){ 
    // Load several files 
    load(['mobile.js','mobile.css']); 
    } 

Dichiarare due volte è imbarazzante/leggera e, per quanto posso trovare, tutte le librerie di supporto e di attività caricatori JS richiedono di ripetere le domande dei media, piuttosto che individuandoli a livello di programmazione da JS/DOM.

Quindi, ho esplorato la possibilità di accedere ai valori in modo programmatico tramite document.stylesheets, ma non sono sicuro che siano accessibili e sembra che ci siano pochissimi documenti da suggerire.

Il più lontano che ho è in cerca di CSSMediaRule e utilizzando console.dir(document.stylesheets) tra gli altri per esplorare l'oggetto del foglio di stile.

Tuttavia, non vengono apportati riferimenti (entro document.stylesheets) alle regole di query dei supporti effettive utilizzate nei CSS: solo le classi da applicare come risultato delle query dei supporti ... Quello che sto cercando di individuare, a livello di programmazione, è :

"schermo e (max-width: 480px)"

esiste un modo di accedere ad interrogazione CSS media regole tramite JavaScript/DOM?

+2

Ops, collegamento sbagliato, [ecco l'articolo che stavo cercando in coderwall] (https: // coderwall. com/p/_ldtkg) – steveax

+2

Buona domanda. Per i miei scopi, ho sempre controllato se elementi specifici erano visibili o meno, poiché la mia interazione JavaScript si applicava a quegli elementi. Tuttavia, dovrebbe esserci una soluzione migliore e più generale. – Brad

+0

Ehi, controlla. Può essere una soluzione. https://github.com/nathansmith/adapt/blob/master/assets/js/adapt.js –

risposta

11

Per le regole ottenere l'uso trasversale variante del browser:

var styleSheet = document.styleSheets[0]; 
var rules = styleSheet.cssRules || styleSheet.rules; // IE <= 8 use "rules" property 

Per rilevare oggetto CSSMediaRule nella lista regole uso (non funziona in IE < = 8, perché "CSSMediaRule" classe disponibile solo in IE> = 9):

var i = 0; 
if (rules[i].type == 4) 
{ 
    // Do something 
} 

Alcune funzioni per gli stili di ottenere da DOM corrente (non funziona in IE < = 8):

function getCssRulesFromDocumentStyleSheets(media) 
{ 
    var resultCssRules = ''; 
    for (var i = 0; i < document.styleSheets.length; i++) 
    { 
     var styleSheet = document.styleSheets[i]; 

     if (isRuleFromMedia(styleSheet, media)) 
      resultCssRules += getCssRulesFromRuleList(styleSheet.cssRules || styleSheet.rules, media); 
    } 

    return resultCssRules; 
} 

function getCssRulesFromRuleList(rules, media) 
{ 
    var resultCssRules = ''; 
    for (var i = 0; i < rules.length; i++) 
    { 
     var rule = rules[i]; 
     if (rule.type == 1) // CSSStyleRule 
     { 
      resultCssRules += rule.cssText + "\r\n"; 
     } 
     else if (rule.type == 3) // CSSImportRule 
     { 
      if (isRuleFromMedia(rule, media)) 
       resultCssRules += getCssRulesFromRuleList(rule.styleSheet.cssRules || rule.styleSheet.rules, media); 
     } 
     else if (rule.type == 4) // CSSMediaRule 
     { 
      if (isRuleFromMedia(rule, media)) 
       resultCssRules += getCssRulesFromRuleList(rule.cssRules || rule.rules, media); 
     } 
    } 

    return resultCssRules; 
} 

function isRuleFromMedia(ruleOrStyleSheet, media) 
{ 
    while (ruleOrStyleSheet) 
    { 
     var mediaList = ruleOrStyleSheet.media; 
     if (mediaList) 
     { 
      if (!isMediaListContainsValue(mediaList, media) && !isMediaListContainsValue(mediaList, 'all') && mediaList.length > 0) 
       return false; 
     } 

     ruleOrStyleSheet = ruleOrStyleSheet.ownerRule || ruleOrStyleSheet.parentRule || ruleOrStyleSheet.parentStyleSheet; 
    } 

    return true; 
} 

function isMediaListContainsValue(mediaList, media) 
{ 
    media = String(media).toLowerCase(); 

    for (var i = 0; i < mediaList.length; i++) 
    { 
     // Access to mediaList by "[index]" notation now work in IE (tested in versions 7, 8, 9) 
     if (String(mediaList.item(i)).toLowerCase() == media) 
      return true; 
    } 

    return false; 
} 

Funzioni esempio d'uso:

<style type="text/css"> 
    @media screen and (max-width: 480px) { 
     p { margin: 10px; } 
    } 

    @media screen and (max-width: 500px) { 
     p { margin: 15px; } 
    } 

    @media print { 
     p { margin: 20px; } 
    } 
</style> 

<!-- ... --> 

<script type="text/javascript"> 
    alert(getCssRulesFromDocumentStyleSheets('print')); 
    alert(getCssRulesFromDocumentStyleSheets('screen and (max-width: 480px)')); 
    // For IE (no space after colon), you can add fix to "isMediaListContainsValue" function 
    alert(getCssRulesFromDocumentStyleSheets('screen and (max-width:480px)')); 
</script> 

Ecco un JS Fiddle per esso: https://jsfiddle.net/luisperezphd/hyentcqc/

+0

questa funzione cerca la corrispondenza esatta, ad es. "schermo e (max ..." e non per una corrispondenza parziale es. "schermo", vero? Sto provando a clonare, cancellare e ricreare classi per schermo (non importa quali dimensioni) a "tutti" (dato che posso basta cambiare il supporto per le regole esistenti) Pensi che questo possa essere usato per quello? grazie. – sergio

5

Questo è come lo faccio:

in CSS creare classi per esporre o nascondere i contenuti in vari punti di interruzione. Questa è comunque una pratica utilità. Questi sono già disponibili in Twitter Bootstrap, ad esempio.

<style type="text/css"> 
    .visible-sm, .visible-md, .visible-lg{ 
    display:none; 
    } 
    @media (max-width: 480px) { 
    .visible-sm{ 
     display: block; 
    } 
    } 
    @media (min-width: 481px) and (max-width: 960px) { 
    .visible-md{ 
     display: block; 
    } 
    } 
    @media (min-width: 961px) { 
    .visible-lg{ 
     display: block; 
    } 
    } 
</style> 

In tutti i tuoi documenti aggiungi campate vuote con queste classi. Non verranno visualizzati nella pagina se si mantengono in linea gli span.

<span id="media_test"> 
    <span class="visible-sm"></span> 
    <span class="visible-md"></span> 
    <span class="visible-lg"></span> 
</span> 

Aggiungi questa breve estensione jquery al file di script. Imposta una nuova classe nel tag body corrispondente alla media query corrente.

(function ($) { 
    $.fn.media_size = function() { 
    //the default port size 
    var size = 'lg'; 
    //the sizes used in the css 
    var sizes = ['sm','md','lg']; 
    //loop over to find which is not hidden 
    for (var i = sizes.length - 1; i >= 0; i--) { 
    if($('#media_test .visible-'+sizes[i]).css("display").indexOf('none') == -1){ 
     size = sizes[i]; 
     break; 
    }; 
    }; 
    //add a new class to the body tag 
    $('body').removeClass(sizes.join(' ')).addClass(size); 
    } 
}(jQuery)); 
$(document).media_size(); 

Ora si dispone di un'integrazione automatica con le query multimediali del vostro css Stile Modernizr.

È possibile scrivere javascript (jQuery), che è subordinata, sulla base di media query:

<a href="#">how big is this viewport?</a> 

<script type="text/javascript"> 
    $('.sm a').click(function(e){ alert('Media queries say I\'m a small viewport');}); 
    $('.lg a').click(function(e){ alert('Media queries say I\'m a large viewport');}); 
</script>