jQuery-UIのdraggableで、画面がスクロールしている状態でドラッグすると掴んでいるものが上方にすっ飛んでしまうとき

あぁぁぁぁぁ。IE対応に捧げる時間ほど無意味なものはないですよね。

対応方法は以下。

  • 画面全体を適当な要素(ただしposition:relative)で括ってしまう
  • draggableにする要素は上記要素の子要素にしておく
  • イメージ的にはこんな感じ(適当なので動くか不明)
<head>
<script type="text/javascript">
$(function() {
  $('#box').draggable();
})
</script>
</head>
<body>
<div id="world" style="position:relative">
  <div id="box" style="border:green 2px solid">掴んで離せ</div>
 :
</div>
</body>

ただ、今回やりたかったのは「HTMLには手を加えない」という条件があったため、上記例でいうところのworldを動的に埋め込む必要がありました。要はbodyの子要素を適当なidで動的に包む感じですね。

で、jQueryのwrapAllとかprependToとかを使ってみたのですが、上手くいくHTMLもあれば画面が崩れたまま固まっちゃうHTMLもあり(FFでも)、結構はまってました。

色々試した結果、「bodyの中にscriptタグがある場合、それを移動させちゃうと固まる」ということが分かりました。まぁ、そんなお行儀のわるいHTMLが存在していること自体むにゃむにゃむにゃ…

じゃあscriptタグ消しちゃえ!と、結局こんな感じでいけたような気がします。

$('body').prepend("<div id='world'></div>")
$('body script').remove();
$('body').children('[id!=world]').each(function() {
  $(this).prependTo('#world');
})

イベントが無くなっているような雰囲気が出ていますが、まぁあまり気にしないでおきましょう。