Accediendo a la hoja de estilo entre dominios con .cssRules

Recibo este error en Firebug cuando bash acceder a algunos archivos CSS alojados en dominios externos:

Security error" code: "1000 rules = styleSheets[i].cssRules; 

El código que estoy usando es:

 $(document).ready(function () { $("p").live('mousedown', function getCSSRules(element) { element = $(this); var styleSheets = document.styleSheets; var matchedRules = [], rules, rule; for (var i = 0; i < styleSheets.length; i++) { rules = styleSheets[i].cssRules; for (var j = 0; j < rules.length; j++) { rule = rules[j]; if (element.is(rule.selectorText)) { matchedRules.push(rule.selectorText); } } } alert(matchedRules); }); }); 

¿Hay alguna manera de arreglar esto, además de mover todos los archivos CSS en el mismo dominio?

La única solución real a este problema es que CORS cargue su CSS en primer lugar. Al usar CORS XMLHttpRequest para cargar el CSS desde un dominio externo, y luego inyectar el texto de respuesta (en realidad responseCSS en este caso) en la página a través de algo como:

 function loadCSSCors(stylesheet_uri) { var _xhr = global.XMLHttpRequest; var has_cred = false; try {has_cred = _xhr && ('withCredentials' in (new _xhr()));} catch(e) {} if (!has_cred) { console.error('CORS not supported'); return; } var xhr = new _xhr(); xhr.open('GET', stylesheet_uri); xhr.onload = function() { xhr.onload = xhr.onerror = null; if (xhr.status < 200 || xhr.status >= 300) { console.error('style failed to load: ' + stylesheet_uri); } else { var style_tag = document.createElement('style'); style_tag.appendChild(document.createTextNode(xhr.responseText)); document.head.appendChild(style_tag); } }; xhr.onerror = function() { xhr.onload = xhr.onerror = null; console.error('XHR CORS CSS fail:' + styleURI); }; xhr.send(); } 

De esta forma, los archivos CSS serán interpretados por el navegador como provenientes del mismo dominio de origen que la respuesta de la página principal y ahora tendrá acceso a las propiedades cssRules de sus hojas de estilo.

A partir de 2013, puede establecer el atributo “crossorigin” en el -Elemento para indicar al navegador que este CSS es de confianza ( Mozilla , W3 ). Para que esto funcione, el servidor que aloja CSS debe establecer el encabezado Access-Control-Allow-Origin: * .

Después de eso, puedes acceder a sus reglas a través de Javascript.

Si tiene control sobre el dominio donde está alojada la hoja de estilo externa, puede ser útil agregar un encabezado de Access-Control-Allow-Origin apropiado .

 Access-Control-Allow-Origin: http://stylesheet-user.example.com 

Escribí una pequeña función que resolverá el problema de carga cross-browser incluyendo FF. Los comentarios en GitHub ayudan a explicar el uso. Código completo en https://github.com/srolfe26/getXDomainCSS .

Descargo de responsabilidad: El código a continuación es jQuery dependiente.

A veces, si extraes CSS desde un lugar en el que no puedes controlar la configuración de CORS hasta que obtengas el CSS con una etiqueta , el problema principal se resuelve y se convierte en conocimiento cuando has solicitado el CSS. cargado y listo para usar. En IE más antiguo, podría tener un oyente on_load ejecutado cuando se carga el CSS.

Los navegadores más nuevos parecen requerir un sondeo anticuado para determinar cuándo se carga el archivo, y tienen algunos problemas entre navegadores para determinar cuándo se satisface la carga. Vea el código a continuación para captar algunas de esas peculiaridades.

 /** * Retrieves CSS files from a cross-domain source via javascript. Provides a jQuery implemented * promise object that can be used for callbacks for when the CSS is actually completely loaded. * The 'onload' function works for IE, while the 'style/cssRules' version works everywhere else * and accounts for differences per-browser. * * @param {String} url The url/uri for the CSS file to request * * @returns {Object} A jQuery Deferred object that can be used for */ function getXDomainCSS(url) { var link, style, interval, timeout = 60000, // 1 minute seems like a good timeout counter = 0, // Used to compare try time against timeout step = 30, // Amount of wait time on each load check docStyles = document.styleSheets // local reference ssCount = docStyles.length, // Initial stylesheet count promise = $.Deferred(); // IE 8 & 9 it is best to use 'onload'. style[0].sheet.cssRules has problems. if (navigator.appVersion.indexOf("MSIE") != -1) { link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet"; link.href = url; link.onload = function () { promise.resolve(); } document.getElementsByTagName('head')[0].appendChild(link); } // Support for FF, Chrome, Safari, and Opera else { style = $(' 

Tuve un problema similar en Firefox y Chrome. Lo he resuelto de una manera dura al agregar a mi dominio un archivo css que incluía el dominio externo css, como este:

  

Es rápido pero sucio. Se recomienda mantener todos los archivos css en su dominio.

Si esto se activa para usted porque algunos de sus CSS pueden provenir de otro lado pero NO del bit que le interesa, use un bloque try … catch como este:

 function cssAttributeGet(selectorText,attribute) { var styleSheet, rules, i, ii; selectorText=selectorText.toLowerCase(); if (!document.styleSheets) { return false; } for (i=0; i