【jQuery】要素をコピーする
こんにちは、マリンです。
今回は要素をコピーする方法をご紹介しようと思います。
概要
ユーザー一覧を表示しているテーブルの行にコピーボタンを表示。
そのボタンを押すとその行のコピーを直下に挿入します。
userモデルにはnameとemailのカラムがあるとします。
コントローラには@users = User.all
を記述しておきます。
ソースコード
views/users/index.html.erb
<table> <tbody> <% @users.each do |user| %> <tr class="copy-row"> <td><%= user.name %></th> <td><%= user.email %></th> <td><%= link_to 'copy', "#", class: 'copy-user' %></td> </tr> <% end %> </tbody> </table> <script> users.copy(); </script>
assets/javascripts/users.coffee
class UsersController copy: -> $('.copy-user').on 'click', () -> currentRow = $(@).parents('.copy-row') currentRow.clone(true).innsertAfter(currentRow) false this.users = new UsersController
解説
HTML
まずはビューの方の解説です。
あまり説明することはないのですが...
<tr class="copy-row">
行全体をコピー対象にするためtr
にクラスをつけます。
tr
だけでも良いのですが、もし入れ子になっていた時など、
予期しないtr
を取ってこないためにも指定した方が安全だと思います。
<td><%= link_to 'copy', "#", class: 'copy-user' %></td>
ここがコピーボタンになります。
link_to
である必要は特にないのですが、
jQueryのソースの最後に使っているfalse
の説明のためこれにしました。
copy-user
と言うクラスをクリックのセレクターにします。
<script> users.copy(); </script>
jQueryの呼び出しです。
CoffeeScript
では本題のjQueryの部分です。
class UsersController . . . this.users = new UsersController
まず最初と最後のこの記述ですが、
このように書くと、HTMLの最後に書いたような記述で
メソッドを指定して呼び出すことができます。
仕組みについては現在勉強中です。すみません...
ちゃんと理解したらまた記事に書きます。
$(.copy-user).on 'click', () -> currentRow = $(@).parents('.copy-row')
まずはリンクをクリックした時に、
そのリンク(またはボタン等)の親の行を持ってきます。
currentRow.clone(true).innsertAfter(currentRow)
ここがキモです。
まずcurrentRow
(コピー対象の行)をclone(true)
でコピーします。
引数のtrue
で対象のイベントや変数もコピーしてくれます。
ちなみに(true, false)
と第2引数をとることもでき、
この場合は子要素のイベントはコピーされません。
こちらを参考にさせていただきました。
jQuery リファレンス:clone
次にinnsertAfter(currentRow)
でオリジナルの直下に挿入しています。
.clone
はただ要素の中身諸々をコピーするだけですので、
このように必ずどこかに表示してあげないと画面には反映されません。
なお、もしコピーする行に固有のid
とかが付いていた場合、
それも一緒にコピーしてしまって予期しない動作が起こったりしますので、
その場合はそれらを削除する必要があります。
(私の場合はid番号が付いていてdelete
でオリジナルも消えました...)
コピーの動きについては以上です。
補足
コピーの話とは関係ありませんが、最後にあるfalse
についてです。
これは該当要素の本来の動きを打ち消してくれるようです。
今回で言えばクリックの対象をlink_to
にしていました。
false
なしだとクリックした時に、一瞬行が表示されて、そして消える。
というような不可解な挙動をしたりします。
これはクリックイベントの処理の後にlink
本来の動きをしたために起こることです。
この動きを打ち消すことで消えることなく無事表示されます。
まとめ
要素をコピーして表示するというのは結構見かける機能な気がします。
今回はただ単に一覧の行をコピーして入れただけですが、
実際には複数のデータを一括で編集するフォームに実装しました。
覚えておけばまたどこかで使えそうです。