jQuery と object タグの怪
Silverlightコンテンツを埋め込むjQueryプラグイン - Programmable Life で困ってたので一緒に悩んでみた。
でも何故かIEでは動かない。誰か動くようにしてけれ!
Silverlightコンテンツを埋め込むjQueryプラグイン - Architect Life
object を作れていない?
手元に環境を作って動かしてみると、<object> に <param> を追加するところで JavaScript エラーが出る。状況を切り分けるために、<param> を追加する部分をコメントアウトしてみた。
IE DOM Explorer で眺めてみると DIV タグが追加されている。
どうやら
var obj = $('<object>').attr({ ... });
のところで object タグが作られていないようだ。
jQuery でよく見る現象だ。こういうときは閉じ括弧を入れてあげると大抵うまくいく。
var obj = $('<object/>').attr({ ... });
IE DOM Explorer で確認したら <object> になってた。
でも、だめ
一歩前進したのでコメントアウトを外してみた。
が、やっぱり append のところでエラーがでる。
obj.append( // ←ココ $('<param>').attr({ name: name, value: value }) );
同じ作戦で <param></param>
のようにやってみたが変わらず。
仕方がないので、jQuery の $('<param>')
から呼ばれる clean のソースを読んでみた。
IE で $('<param>')
とすると、内部ではこんな処理をしてる。
var div = document.createElement("div"); div.innerHTML = "div<div>" + html + "</div>"; div = div.lastChild; return jQuery.makeArray( div.childNodes );
空の div タグを作って、その中に innerHTML で HTML 文字列を流し込んで DOM ノードを作成しているようだ。
ここでピーンときた。仕様上は param タグは、本来は object タグの内部にしか入れることができない。なので、<div><param></div>
のような HTML を innerHTML で設定すると、このときに生成される param タグは本来の param タグではなく、何か別のものになってるんじゃないだろうか。だから、object に appendChild すると不正なノードを追加したのでエラーになる。
あくまで想像。
同じような工夫は歯が立たない
同様の問題は既に jQuery で対応されている。例えば td タグなどを生成するときに単に innerHTML でノード生成するとエラーに出くわすので、一旦 table で囲ってから innerHTML する、といった泥臭いことをしている。
param タグに関しても、同じ仕組みを使えばうまくいくはず、と信じて前後を object タグで囲ってから innerHTML してみた。
が、うまく行かない…。
// IE7 で検証したよ div.innerHTML = "<object><param></object>"; alert(div.innerHTML); // <OBJECT></OBJECT> div.innerHTML = "<object><param/></object>"; alert(div.innerHTML); // <OBJECT></OBJECT>
なぜか param が消える。ナゼジャー!
仕方がないから諦めた
ということで、諦めて次のように置き換えたらうまく行った。
$(document.createElement('param')).attr({
jQuery に任せず、自分で作っちゃえ!ということですな。
そして…
IE DOM Explorer で眺めてみたら、ちゃんと object の中に param が入って理想的な DOM ノードが構築されていた。
おお、完璧。
しかし…肝心の Silverlight コンテンツが表示されない。
ナゼダ…。
さらに、代替コンテンツの「Microsoft Silverlight を取得」のリンクもなぜか object ノードに入っていない。上と同じく document.createElement 作戦を試したが、それでもエラー。
不思議だ…。
まとめ
- object は鬼門
- 謎な挙動が多い
- 同じようなことを Flash でやる超有名ライブラリの SWFObject は object 全体を innerHTML で作成してる。ソースを読んでてもバッドノウハウの塊っぽい
→ jQuery と object タグの怪 (その2) に続く。