Procedimento inválido Ligue ou argumento, isto é, quando itera através do document.stylesheets usando $ .EECH ()
-
21-09-2019 - |
Pergunta
Eu escrevi este código que itera sobre todas as regras da folha de estilo global e as armazena em uma matriz/objeto. Eu uso esse objeto semelhante ao dicionário posteriormente para alterar as regras globais, em vez de definir estilos em elementos individuais.
Após as quebras de código no IE8, mas funciona bem no Firefox3.7 e 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;
});
});
});
eu recebo Invalid procedure call or argument
erro. Quando tento depurar, esse código itera com sucesso através de dois arquivos de folha de estilo CSS com regras, mas quando a segunda é feita, ela falha.
Não consigo encontrar um erro neste código.
Solução
O problema
Após testes completos, descobri que document.styleSheets
Não é uma matriz regular no IE. É por isso que quebra $.each()
Ligue quando chegar ao fim.
Se dermos uma olhada na função jQuery, ele tem um for
loop para iterar sobre um objeto que tem um length
Propriedade, acreditando falsamente que é uma matriz. document.styleSheets
tem length
propriedade, mas obviamente não é uma matriz. Então, quando isso for
loop in $.each()
É executado:
for (var value = object[0];
i < length && callback.call( value, i, value ) !== false;
value = object[++i]){}
Falha depois que o último elemento foi iterado. Como podemos ver isso for
O loop não aumenta i
por si só, mas o incrementam ao atribuir um novo valor a value
.
Podemos verificar isso manualmente também. Escreva essas duas linhas na barra de endereços de qualquer navegador:
javascript:var a=[1,2,3];alert(a[3]);void(0);
javascript:alert(document.styleSheets[document.styleSheets.length]);void(0);
O primeiro funciona bem em todos os navegadores, mas o segundo falha no IE.
A solução
Temos que reescrever a iteração sobre as folhas 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;
});
}
});
Outras dicas
Será que a própria regra da análise está falhando? Tente experimentar diferentes folhas de estilo e reordenar as regras para garantir que não haja um problema para analisar a regra por algum motivo.
O código true é:
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);
}
});