llamada de procedimiento no válido o argumento cuestión es decir, cuando la iteración a través document.styleSheets utilizando $ each ()
-
21-09-2019 - |
Pregunta
He escrito el código que itera sobre todas las reglas de hojas de estilo globales y los almacena en una matriz / objeto. Yo uso este diccionario como objeto después de cambiar las reglas globales en lugar de crear estilos en elementos individuales.
Después de roturas de código en Internet Explorer 8, pero funciona bien en Firefox3.7 y Chrome4.
var allRules;
$(function() {
var fileRules;
allRules = [];
$.each(document.styleSheets, function() {
// get rules for any browser (IE uses rules array)
fileRules = this.cssRules || this.rules;
$.each(fileRules, function() {
allRules[this.selectorText] = this;
});
});
});
Me sale error Invalid procedure call or argument
. Cuando trato de depurarlo, repite este código con éxito a través de dos archivos de hojas de estilo CSS con reglas pero cuando se hace iteración de la segunda, se produce un error.
Me parece que no puede encontrar un error en el código.
Solución
El problema
Después de pruebas exhaustivas descubrí que document.styleSheets
no es una matriz regular en el IE. Es por eso que se rompe en la llamada $.each()
cuando se llega al final.
Si echamos un vistazo a la función jQuery en sí tiene un bucle for
para iterar sobre un objeto que tiene una propiedad length
, creyendo falsamente que es una matriz. document.styleSheets
tiene la propiedad length
, pero no es, evidentemente, una matriz. Así que cuando se ejecuta este bucle for
en $.each()
:
for (var value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[++i]){}
falla después del último elemento ha sido repiten a lo largo. Como podemos ver este bucle for
no incrementa i
por su propia cuenta, sino más bien la incrementa, mientras que la asignación de un nuevo valor a value
.
Podemos comprobar esto manualmente. Escribir estas dos líneas en la barra de direcciones de cualquier navegador:
javascript:var a=[1,2,3];alert(a[3]);void(0);
javascript:alert(document.styleSheets[document.styleSheets.length]);void(0);
La primera de ellas funciona muy bien en todos los navegadores, pero la segunda falla en IE.
La solución
Tenemos que volver a escribir la iteración sobre las hojas de estilo
var allRules;
$(function() {
var fileRules;
allRules = {};
// can't use $.each() over document.styleSheets because it's not an array in IE
for (var i = 0; i < document.styleSheets.length; i++)
{
fileRules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
$.each(fileRules, function() {
allRules[this.selectorText] = this;
});
}
});
Otros consejos
¿Podría ser que la regla de análisis en sí está fallando? Experimentar con otras hojas de estilo y reordenar las reglas para asegurarse de que no hay un problema al analizar la regla por alguna razón.
verdadero código es:
var fileRules;
(function ($) {
allRules = {};
for (var i = 0; i < document.styleSheets.length; i++) {
fileRules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
$.each(fileRules, function () {
allRules[this.selectorText] = this;
})(jQuery);
}
});