jQueryを使って入力フォームのコピー&ペースト(コピペ)を禁止するようにしたいと思って作業してもぜんぜん思い通りにならなかったが、意外な盲点がそこにあったためだった

パスワード確認入力や電子メールアドレス確認入力などのフォームで、コピー&ペーストを禁止したい場面がある。せっかくの確認のための入力なのに、手入力されずにコピペされてしまうと、もともとの入力が誤っている場合には何の効力も持たなくなってしまう。だから元の入力フォームはコピーさせてもいいけれど(あるいはこちらも禁止したいという要望もあるかもしれない)、確認のための入力欄についてはペースト禁止したい。ウェブでフォームを作っていると、そんな要望は必ずといっていいほど出てくる。jQueryではそれが簡単にできる。


ぶっちゃけていおう。ウェブで情報収集していると、jQueryでの実装方法は複数見つかる。いずれも簡単な方法だし置き換えも容易であるため、おそらく最初に見つけた情報源の通りに実装するか、自分が使いたいと思った実装方法を選ぶかになる可能性がある。

今回紹介するjQueryメソッドだけに限らないが、メソッドには(1)古いjQueryのバージョンからずっと実装されてきて「現在も互換性のために実装されている」メソッドと、(2)より新しいバージョンから実装された「古い実装を置き換えて今後使っていくべき」メソッドがある。ブログや質問サイトなどではいちいち年月日やその時点でのバージョンを確認しない場合がほとんどであろうから、jQueryのバージョンなど特に意識せずに実装を始めてしまうかもしれない。そして実装時点で動いてしまえば「これが正解だな」と思ってしまいがちだ。しかしAPIのドキュメントを改めて手繰って見ると、実はそれが非推奨メソッドであったり、より柔軟なメソッドを使うよう勧められていたりする場合がある。

また古いバージョンだと脆弱性も含まれる場合があるので、なるべく新しいバージョンのjQueryを使う必要があるだろうが、古いバージョンで作成したウェブページのjQueryを単に新バージョンに変更しただけだったり、過去の実装から移植したりした場合に急に動かなくなる、あるいは挙動がおかしくなるという場合が起き得る覚悟はしておくべきだ。jQueryのメソッドは、バージョンに気を配らないと悲しいことになりかねないので注意が必要だろう。

ちなみに、私がいずれの方法で実装した場合も、なぜかどれも失敗に終わった。その理由はとりあえず後回しにして、現時点で問題ない実装を2つだけピックアップしておきたい。

ひとつは、.bind()メソッドを使う方法である。

[javascript]
$(document).ready(function(){
// 個別に指定
$(‘#email_confirm’).bind(‘paste’,function(){
return false; // falseを返して処理を中止させる
}).bind(‘copy’,function(){
return false;
}).bind(‘cut’,function(){
return false;
});

// まとめて指定
$(‘#email_confirm’).bind(‘copy cut paste’,function(e){
e.preventDefault(); // デフォルト動作を回避するpreventDefault()メソッドを呼び出す
});
});
[/javascript]

3~11行目が.bind()メソッドによる指定である。これらはそれぞれfalseを即座に返すことで当該イベント処理を失敗となるようにしている。呼び出し側は戻り値としてfalseを受け取ることによりそれぞれのイベント処理を中断するため、結果としてコピーやカット、ペーストなどが行われなくなるという算段だ。

ただ.bind()メソッドについては、APIリファレンスを見ると最初に注意書きがある。

As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method is used for attaching an event handler directly to elements. Handlers are attached to the currently selected elements in the jQuery object, so those elements must exist at the point the call to .bind() occurs. For more flexible event binding, see the discussion of event delegation in .on() or .delegate().

[誤訳可能性有] jQuery 1.7時点で、.on()メソッドがドキュメントにイベントハンドラを割り当てるための推奨方法である。それ以前のバージョンでは、.bind()メソッドが要素に直接的にイベントハンドラを割り当てる方法として使用されている。ハンドラはjQueryオブジェクト中で現時点で選択されている要素に割り当てられるため、それらの要素は.bind()を呼び出す時点で必ず存在しなければならない。より柔軟なイベントの結びつけのために、.on()メソッドや.delegate()メソッドでイベントの委譲を検討されたい。

ということで、バージョン1.7以降のjQueryを使う場合には、.bind()メソッドより.on()メソッド.delegate()メソッドを利用するほうが望ましいようだ(ただし.delegate()メソッドのドキュメントの注意書きには「.on()メソッドで代替された」と書かれている)。バージョン1.10.1時点では.bind()メソッドは期待通りに動作しているが、今後どう取り扱われるメソッドとなるかは判らない。
ちなみに.live()メソッドというのもあるが、こちらはバージョン1.7以降は非推奨となっており、.on()メソッドや.delegate()メソッドを利用するよう注意書きされている。基本的には、過去のバージョンの互換性のために残されており、イベントハンドラの制御は.on()/.off()メソッドの利用に集約されたとみなしてよいかもしれない。.on()メソッドの書き出しには「イベントハンドラの割り当てに関するすべての機能が提供されている」とある。

[Sponsored Link]


ということで書き直してみるが、基本的にはメソッドを置き換えるだけでよい。

[javascript]
$(document).ready(function(){
// 個別に指定
$(‘#email_confirm’).on(‘paste’,function(){
return false;
}).on(‘copy’,function(){
return false;
}).on(‘cut’,function(){
return false;
});

// まとめて指定
$(‘#email_confirm’).on(‘copy cut paste’,function(e){
e.preventDefault();
});
});
[/javascript]

さて、タイトルと冒頭に書いた「機能しなかった」理由なのだが、実は私のFirefoxには、アドオンでキーバインドを変更するものを入れていたのだ。文字入力の効率化を図ってemacsバインドライクにするようなアドオンを入れていたのだが、コピーペースト含めて最終的にはキー操作がこのアドオンでフックされていたために、jQuery側での制御が無効になってしまった……という感じのオチのようだ。

アドオンのソースを見たわけじゃないので詳細はわからないが、アドオンに制御を奪われて機能しなかったか、アドオンが結果を無視していたか、のいずれかのようだ。アドオンを無効にすると、とたんにjQuery側の制御が有効になった。

ということで、デバッグ時にはこうしたアドオンには要注意であることと、こうしたアドオンを入れているユーザに対してはjQueryでの制御が無効化されてしまう可能性があることには注意したい。

実装例とそのサンプルコードは、以下に示しておきたい。

■コピペを禁止する
http://zura.org/prog/js/bancopypaste/

xWeb制作の現場で使うjQueryデザイン入門[改訂新版] (WEB PROFESSIONAL)現場で役立つjQueryデザインパーツライブラリ実践Webデザイン jQuery+CSSフレームワークでサクサクつくる「動き」と「仕掛け」やさしくはじめるWebデザイナーのためのjQueryの学校10日でおぼえるjQuery入門教室 第2版ラグー チェダーチーズ 454g

コメントを残す

メールアドレスが公開されることはありません。