読者です 読者をやめる 読者になる 読者になる

ボクココ

サービス開発を成功させるまでの歩み

リストのドラッグアンドドロップの決定版 - html5sortable -

JavaScript

ども。@kimihom です。

JavaScriptによるドラッグアンドドロップは、何か難しそうでとっつきにくい雰囲気があるかもしれない。そんな不安を一気に跳ね除けてしまうライブラリを紹介しよう。 voidberg/html5sortable · GitHub

html5sortable を使えば、tableul などでリスト化された項目に対して、簡単にドラッグアンドドロップの機能を追加してくれる。しかも各種イベントを提供してくれているため、それに伴ってサーバー側でデータを反映する、といったことも容易に行うことが可能だ。デモサイトでどんなことをできるか確認してみよう。

f:id:cevid_cpp:20151001021107p:plain

jQueryやAngularJSなどで便利なプラグインを提供してくれている。

最近はHTML5でドラッグアンドドロップのイベントを取得できるような取り決めがあり、html5sortableはその仕様をうまくラッピングしている。それ以前のドラッグアンドドロップのjQueryプラグインなどはHTML5に頼らずに全て自前で実装していたため、コード量が多くなってしまったり、これからのブラウザの対応が難しかったりするが、html5sortableならHTML5の仕様に沿ったドラッグアンドのラッパーであるため、これからも安心して利用できるだろう。

実装方法 (jQuery)

基本的なドラッグアンドドロップを実現するには、まずは普通に ul , li 要素を使ってリストを生成し、以下のような初期設定をするだけで済む。

$('ul.sortable').sortable({
  placeholder: '<li>&nbsp;</li>', 
  connectWith: 'connected'
}).bind('sortstart', function(e, ui) {
    /*
    ui.item contains the current dragged element
    ui.placeholder contains the placeholder element
    ui.startparent contains the element that the dragged item comes from
    */
}).bind('sortstop', function(e, ui) {
    /* 
    ui.item contains the element that was dragged.
    ui.startparent contains the element that the dragged item came from.
    */
}).bind('sortupdate', function(e, ui) {
    /*
    ui.item contains the current dragged element.
    ui.index contains the new index of the dragged element (considering only list items)
    ui.oldindex contains the old index of the dragged element (considering only list items)
    ui.elementIndex contains the new index of the dragged element (considering all items within sortable)
    ui.oldElementIndex contains the old index of the dragged element (considering all items within sortable)
    ui.startparent contains the element that the dragged item comes from
    ui.endparent contains the element that the dragged item was added to (new parent)
    */
})
  • placeholderを指定すると、ドラッグしたあとの要素をどんなように見せるかを指定できる。ここは何もない<li>要素を表示する、などが一般的かと思う。
  • connectWithを指定すると、別の位置にある複数のul要素を連携させることができる。別のところから別のところへドラッグアンドドロップが可能だ。
  • sortstart をバインドすると、ドラッグ開始時のイベントを取得できる。ここで例えばドロップ可能な位置に対してボーダーを入れたりなどする。
  • sortstop をバインドすると、ドロップした後のイベントを取得できる。ドロップ可能な位置に表示していたボーダーを消すなどする。
  • sortupdate は実際にドラッグアンドドロップが終わった時のイベントを取得できる。ここでサーバーにデータをアップロードして順番を適用などする。

uiで取ってこれる内容は英語でコメントしてあるが、適宜console.logなどで出力すれば、どんな値が取ってこれるのかわかることだろう。

後は CSS 勝負!

この原理さえわかってしまえば、後はCSSでどう見せるかだけだ。例えば float: left などを使って横並びにすれば、グリッド構成のドラッグアンドドロップも実現できるし、connectWith をうまく利用して、全く別のところからどこかにドロップさせて適用する、みたいなこともできてしまう。

ドラッグアンドドロップで要素の移動をさせたい、というのであればこのライブラリだけで何でもできるようになるだろう。

注意事項

  • ちなみに、ドラッグアンドドロップによるファイルアップロードはこれとはまた別の話なので注意していただきたい。 それはHTML5 の FileAPIなどを利用しないと実現できない。
  • Chrome, Firefox, Safari, Opera, IE9+ でのみ動くようである。