さんまがおいしい季節だねー(´・ω・`)

名前空間に影響せずにカスタマイズ可能な document.write を利用した JavaScript 埋め込みコードの記述方法

JavaScript — タグ: , — さくら @ 2009/04/14 20:32

さくらです♪こんばんわ♡☆彡

今日取り上げるのは、一切名前空間に影響を与えずにカスタマイズ可能な document.write を使った JavaScript コードを書く方法よ。

さくらが実際に遭遇した問題は、ブログパーツとして配布する Flash の埋め込み用コード中の、幅とか高さを変数で指定したいってことだったの。いくつか方法はあるんだけど、とりあえず思いつくのは object タグと embed タグを document.write で埋め込む方法ね。だいたいこんな感じになると思うわ。

document.write(
  '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
  ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"' +
  ' width="300" height="270">' +
  '<param name="movie" value="myflash.swf" />' +
  '<param name="quality" value="high" />' +
  '<embed src="myflash.swf" quality="high" width="300" height="270"' +
  ' type="application/x-shockwave-flash"' +
  ' pluginpage="http://www.macromedia.com/go/getflashplayer">' +
  '</embed>' +
  '</object>');

ポイントは太字箇所ね。
今回は似たようなブログパーツを何個か配布するって話だったんで、太字箇所だけ違うファイルをいくつか用意する必要があったの。厳密に言うと flashvars とかもセットしてたんで、カスタマイズしたい箇所はもうちょっと多かったんだけど、話を簡単にしたいからこのまま進めるわよ。

で、カスタマイズできるようにする場合にまず思いつくのは変数にしちゃうことね。だいたいこんな感じになるわね。

var movie = "myflash.swf";
var width = 300;
var height = 270;

document.write(
  '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
  ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"' +
  ' width="' + width + '" height="' + height + '">' +
  '<param name="movie" value="' + movie + '" />' +
  '<param name="quality" value="high" />' +
  '<embed src="' + movie + '" quality="high" width="' + width + '" height="' + height + '"' +
  ' type="application/x-shockwave-flash"' +
  ' pluginpage="http://www.macromedia.com/go/getflashplayer">' +
  '</embed>' +
  '</object>');

でもこのコードは問題ありありアリーデベルチだわ。
ブログパーツとして配布するって言ってるんだから、この JavaScript ファイルを他の人のページから読み込んでもらって実行されるの。読み込み用 HTML コードは普通こんな感じになるんだけど…

<script type="text/javascript" src="http://.../myblogparts.js"></script>

iframe 使ってる場合と違って、これだと配布してる JavaScript コードは読み込んだページのコンテキストで実行されるから、読み込み元ページで width とか height って変数使ってたら元のコードをぶっ壊すことになるの。名前空間に影響するっていうのはそういう意味よ。変数名を長ったらしくして他のコードと衝突するのを回避したりすることもあるんだけど、単に同じ名前が使用される確率の問題だから、ブログパーツみたいに不特定多数にコードを配布する場合は却下ね。

上のコードを関数にしても同じよ。

function embedMyFlash(movie, width, height) {
  // 上のコードの document.write と同じなんで省略
}
embedMyFlash("myflash.swf", 300, 270);

関数だって名前を持ってんだから名前空間に影響するわ。確かに上の変数を使ったコードと比べると、名前の数が減ってるから衝突する確率が1/3になってるけど、衝突する可能性が無くなった訳じゃないの。

何が問題かだいたい共有できたかしら?
じゃーそろそろ解決するわね。答え自体は思いついちゃえば簡単よ。
無名関数をそのまま呼んじゃえばいいの!

(function() {
  var movie = "myflash.swf";
  var width = 300;
  var height = 270;

  document.write(
    '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
    ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"' +
    ' width="' + width + '" height="' + height + '">' +
    '<param name="movie" value="' + movie + '" />' +
    '<param name="quality" value="high" />' +
    '<embed src="' + movie + '" quality="high" width="' + width + '" height="' + height + '"' +
    ' type="application/x-shockwave-flash"' +
    ' pluginpage="http://www.macromedia.com/go/getflashplayer">' +
    '</embed>' +
    '</object>');
})();

(function() {})() って形で無名関数を括弧でくくればそのまま関数として呼び出せるわ。
movie とかは関数ローカルのスコープに属してるから、他の定義に影響することは無くってよ!

この方法、amachang自分用メモとかに書いてるからそれなりに知られてる方法だと思うんだけど、なんて言うか探しにくいのよね。Young risk taker.[Javascript] クロージャを利用したイベントリスナの登録にもこの方法とクロージャを組み合わせる方法が紹介されてるけど、別にクロージャをどうこうしたい訳じゃなくて単に無名関数を直接呼び出したいだけだしね。

そうね、何か適当な名前がこの方法に付いてたら探しやすいのかしら?
普通に考えたら無名関数の直接呼び出しとかになるんでしょうけど…
え?もうイっちゃうの?!
挿れてスグだよ……
ぃくッ!ィクッ!!
イクーーーーッ!!!

とかどうかしら?ww

(本当はちゃんとした名前付いてるのかもしれないけど、知らないものはなんともできないわww
ご存知の方はコメントしてね!)

さくら

0 Comments »

コメントはまだありません。

この投稿へのコメントの RSS フィード。 TrackBack URI

コメントする

Copyright © 2017 さくらたんどっとびーず | powered by WordPress with Barecity