LoginSignup
12
14

More than 5 years have passed since last update.

ChromeでCSSStyleSheet.insertRuleにハマった

Last updated at Posted at 2013-10-19

Ajax通信中のインジケーター(グルグル回るやつ)に画像ではなくSVGを挿入してくれる NETEYE Activity Indicator を導入してちょっとハマったのでメモ。

他の画面では順調にグルグル回っていたのにある画面でChromeのみ以下のエラーが発生した。

Uncaught HierarchyRequestError: A Node was inserted somewhere it doesn't belong.

HierarchyRequestErrorが発生していてどうもDOM操作を誤っているような感じで、エラーメッセージも「ノードが属さない箇所に挿入しようとした」といった内容。

エラーが jquery.activity-indicator-1.0.0.js の150行目で発生しているので該当コードを見てみる。

jquery.activity-indicator-1.0.0.js
129:   // Check if Webkit CSS animations are available, as they work much better on the iPad
130:   // than setTimeout() based animations.
131:   
132:   if (document.createElement('div').style.WebkitAnimationName !== undefined) {
133:
134:       var animations = {};
135:   
136:       /**
137:        * Animation strategy that uses dynamically created CSS animation rules.
138:        */
139:       animate = function(el, steps, duration) {
140:           if (!animations[steps]) {
141:               var name = 'spin' + steps;
142:               var rule = '@-webkit-keyframes '+ name +' {';
143:               for (var i=0; i < steps; i++) {
144:                   var p1 = Math.round(100000 / steps * i) / 1000;
145:                   var p2 = Math.round(100000 / steps * (i+1) - 1) / 1000;
146:                   var value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\n';
147:                   rule += p1 + value + p2 + value; 
148:               }
149:               rule += '100% { -webkit-transform:rotate(100deg); }\n}';
150:               document.styleSheets[0].insertRule(rule);
151:               animations[steps] = name;
152:           }
153:           el.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite');
154:       };
155:   }
156:   else {

発生箇所はここ。

jquery.activity-indicator-1.0.0.js
150:               document.styleSheets[0].insertRule(rule);

DeveloperToolsでオブジェクトを見ても特におかしな所はなく困り果てていたが、document.styleSheets[0]が指すCSSファイルに正常/エラーとで差があった。

@import 'common.css';
@import 'hoge.css';

こんな具合に外部ファイルをインポートしているだけのCSSファイルをHTML上で最初に定義されている場合(= document.styleSheets[0])にHierarchyRequestErrorが発生しているようだったので、スタイルが定義されたCSSと読み込み順序を変えてみたらHierarchyRequestErrorは発生しなかった。

推測だがWebkitベースのブラウザではインポートをしているだけだとCSSOM上にノードがないとみなされている模様。そう考えると以下のメッセージもうなずける。

A Node was inserted somewhere it doesn't belong.

PullRequestしようと思ったけど、よくよく調べてみたら1年以上前に同じ問題でissueが上がっていてPullRequestが取り込まれていないっぽいだけだった。。

滅多に使わないだろうけどCSSStyleSheet.insertRuleを使用する場合は要注意だね。

2013/11/14追記

Google Chrome31にバージョンアップするとこんなエラーが出た。

Uncaught TypeError: Failed to execute 'insertRule' on 'CSSStyleSheet': 2 arguments required, but only 1 present. jquery.activity-indicator-1.0.0.min.js:10

insertRuleは使うなってことか。

12
14
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14