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行目で発生しているので該当コードを見てみる。
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 {
発生箇所はここ。
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は使うなってことか。