キャッチペースト入力


210

ブラウザに貼り付けた入力をサニタイズする方法を探しています。これはjQueryで実行できますか?

私はこれまでにこれを思いつくことができました:

$(this).live(pasteEventName, function(e) {
 // this is where i would like to sanitize my input
 return false;
}

残念ながら、この「マイナー」な問題のために、私の開発は非常に困難になっています。誰かが私を正しい方向に向けることができれば、私は本当に私を幸せなキャンピングカーにします。


6
stackoverflow.com/a/1503425/749232を、同じ問題が発生している他のユーザーの使用に対する回答としてマークしてください。それで解決しました。
saji89

2
.live()はjquery 1.9で非推奨になり、代わりに.on()を推奨します
Sameer Alibhai

回答:


337

はい、同じ問題にぶつかっただけです。長い道のりを歩き回りました

$('input').on('paste', function () {
  var element = this;
  setTimeout(function () {
    var text = $(element).val();
    // do something with text
  }, 100);
});

.val()funcが入力されるまでのわずかなタイムアウト。

E.


20
textareaに既にテキストがあり、貼り付けて、貼り付けたテキストが欲しかった場合はどうなりますか?
barfoon

39
申し分なく動作します。タイムアウト0も同様に機能します。関数は次のループに延期する必要があるだけです。
Daniel Lewis、

4
ちょうど同じような状況にあった。pasteイベントが即時ではなく、中に貼り付けるクリップボードの内容のために数ミリ秒を要するため、タイムアウトがあります。
ジェームズ

8
@ user563811:HTML5では、公式の最小タイムアウトは4msであることに注意してください。
pimvdb 2012

4
シャリフが言うように、0msはまだイベントをスタックの一番下に置きます。
BobRodes 2012

67

実際にイベントから直接値を取得できます。それを取得する方法は少し鈍いですが。

通過させたくない場合はfalseを返します。

$(this).on('paste', function(e) {

  var pasteData = e.originalEvent.clipboardData.getData('text')

});

2
これが先の方法です
DdW 2017年

1
ie 11:window.clipboardData.getData( 'text')
Wallstrider

4
ただし、「originalEvent」プロパティが必要になるのは、jQueryでイベントを処理している場合のみであることに注意してください。e.clipboardData.getData('text')プレーンなJavaScriptで実行できます。
Asier Paz 2017年

ここでベストアンサー!しかし-バインディングの短縮形がこれで機能しない、つまり、これを試した場合にエラーが発生するのは奇妙なことに気づきました:$(this).paste(function(e){...});、短期手渡し.onのためのその作品ものの(「クリック」)、など。
HoldOffHunger

niggle:コードに閉じ括弧がありません。どうやら変更が小さすぎて編集として修正できないようです。
Joachim Lous

42

クロスプラットフォームの互換性のために、oninputおよびonpropertychangeイベントを処理する必要があります。

$ (something).bind ("input propertychange", function (e) {
    // check for paste as in example above and
    // do something
})

2
貼り付けとキーアップイベントのキャッチの両方として機能する美しいソリューション。注:これにより、入力内容を強調表示して、少なくともIE8に何かを入力する、何らかの理由でイベント関数が2回起動します(多くの場合重要ではないが、他では非常に重要)。
2014年

いいね!私はこれについて知りませんでした、そしてそれは私のニーズに完全に適合します!
Marc Brillault、2016

18

私は次のコードを使用してそれをある程度修正しました:

$("#editor").live('input paste',function(e){
    if(e.target.id == 'editor') {
        $('<textarea></textarea>').attr('id', 'paste').appendTo('#editMode');
        $("#paste").focus();
        setTimeout($(this).paste, 250);
    }
});

今、私はキャレットの場所を保存してその位置に追加する必要があるだけです、それで私はすべて設定されています...


1
キャレットの場所をどのように保存しましたか?
Petah

@Petahどの要素にフォーカスがあるかを確認し.find(':focus')、その要素がキャレットの位置を決定していることを確認できます。参照してくださいこれを
ジェイコブ

「ライブ」は「オン」を支持して廃止されることを覚えておいてください
NBPalomino 2014年

input違いが生じます:)通常、これらはテキストボックスイベントにありますkeyup keydown paste inputが、明らかにあなたの動機が何であるかによって異なります
Pierre

10

うーん... 貼り付けたデータをキャッチするのに使えると思いますe.clipboardData。うまくいかない場合は、こちらをご覧ください

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});

2
これをSafariで実行すると、「未定義」になります:(
Christoffer Winterkvist 2009年

1
clipboardDataは、ほとんどのブラウザでサンドボックス化された(明らかにセキュリティホール。)
podperson

2
Internet Explorerのみ!
Lodewijk 2014

9

貼り付けイベントをリッスンし、キーアップイベントリスナーを設定します。keyupで、値をキャプチャし、keyupイベントリスナーを削除します。

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}

6
これは非常に優れていますが、右クリックによる貼り付けでは機能しません。
ジョセフレイブンウルフ2012年

中クリックの貼り付け(X11)では機能しません。キーボードを使用して貼り付けた場合にのみ機能します。
Jasen


6

これはあなたが望むかもしれないものに近づいています。

function sanitize(s) {
  return s.replace(/\bfoo\b/g, "~"); 
};

$(function() {
 $(":text, textarea").bind("input paste", function(e) {
   try {
     clipboardData.setData("text",
       sanitize(clipboardData.getData("text"))
     );
   } catch (e) {
     $(this).val( sanitize( $(this).val() ) );
   }
 });
});

(IE以外のブラウザで)clipboardDataオブジェクトが見つからない場合は、現在、要素の完全な値+クリップボードの値を取得していることに注意してください。

入力前と入力後の2つの値を比較するために、いくつかの追加の手順を実行して、実際に要素に実際に貼り付けられたデータの後にのみ実行できる場合があります。


6
 $('').bind('input propertychange', function() {....});                      

これはマウス貼り付けイベントで機能します。


2
これは、すべての使用法として最適です。
Sinan Eldem 2014年

5

フィールドの元の値とフィールドの変更された値を比較し、その差を貼り付けた値として差し引いてみませんか。これにより、フィールドに既存のテキストがある場合でも、貼り付けられたテキストが正しくキャッチされます。

http://jsfiddle.net/6b7sK/

function text_diff(first, second) {
    var start = 0;
    while (start < first.length && first[start] == second[start]) {
        ++start;
    }
    var end = 0;
    while (first.length - end > start && first[first.length - end - 1] == second[second.length - end - 1]) {
        ++end;
    }
    end = second.length - end;
    return second.substr(start, end - start);
}
$('textarea').bind('paste', function () {
    var self = $(this);
    var orig = self.val();
    setTimeout(function () {
        var pasted = text_diff(orig, $(self).val());
        console.log(pasted);
    });
});

5

このコードは、右クリックから貼り付けるか、直接コピーして貼り付けます

   $('.textbox').on('paste input propertychange', function (e) {
        $(this).val( $(this).val().replace(/[^0-9.]/g, '') );
    })

貼り付けるSection 1: Labour Cost1テキストボックスになります。

float値のみを許可するには、このコードを使用します

 //only decimal
    $('.textbox').keypress(function(e) {
        if(e.which == 46 && $(this).val().indexOf('.') != -1) {
            e.preventDefault();
        } 
       if (e.which == 8 || e.which == 46) {
            return true;
       } else if ( e.which < 48 || e.which > 57) {
            e.preventDefault();
      }
    });

4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

さらに:


text / htmlは無効です。URLとテキストのみです。
マイク

@マイク参照ドキュメントから直接スニペットをコピーしました。
davidcondrey 2016年

私はこれを1日ほど試しました。text / htmlは機能しません。私はタイムアウト0のタイムアウトを追加することになり、貼り付け先のdivからhtmlを取得することができました。多分私はちょうどそれを間違ってやっている...
マイク

3

この例を見てください: http //www.p2e.dk/diverse/detectPaste.htm

それは本質的にoninputイベントですべての変更を追跡し、それが文字列比較による貼り付けかどうかをチェックします。ああ、IEにはオンペーストイベントがあります。そう:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})

したがって、イベントが発生したときにテキストを貼り付けるだけでは不可能ですか?
Christoffer Winterkvist 2009年

まあ、私はあなたがそれを自分で処理しなければならないと思います、例えば、前と後を比較してください。それはかなり簡単でなければなりません。しかし、なぜ入力全体を再検証しないのですか?スロー?
Ilya Birman、

私はそれが可能だと思っていましたが、そうではないと思います。今、私はそれをテキストエリアに貼り付け、それを最終的な宛先に転送することで別の方法を試しています。それがうまくいくことを願っています。
Christoffer Winterkvist 2009年

2つの文字列の先頭(前後)で最大の一致するフラグメントを見つける必要があります。そこから長さの違いまでのすべてが貼り付けられたテキストです。
Ilya Birman

@IlyaBirmanいいえ、そうではありません。たとえば、貼り付けられたテキストが元のテキストの一部(またはすべて)を置き換える可能性があります
Jasen

1

このメソッドは、jqueryのcontent()。unwrap()を使用します。

  1. まず、貼り付けイベントを検出します
  2. 貼り付け先の要素に既にあるタグに一意のクラスを追加します。
  3. 所定のタイムアウトの後、以前に設定したクラスを持たないすべてのコンテンツアンラップタグをスキャンします。注:このメソッドは
    、次の例を参照してください。

    //find all children .find('*') and add the class .within .addClass("within") to all tags
    $('#answer_text').find('*').each(function () {
    $(this).addClass("within");
    });
    setTimeout(function() {
    $('#answer_text').find('*').each(function () {
        //if the current child does not have the specified class unwrap its contents
        $(this).not(".within").contents().unwrap();
    });
    }, 0);

間違いなく、これまでに見た中で最高の、最も短く、自己話す答え!!! どうもありがとう、あなたは私の一日を作りました;)
webprogrammer

0

これはかなり幻想であることがわかりました。入力の値は、pasteイベント関数内のコードの実行前に更新されません。イベントの貼り付け関数内から他のイベントを呼び出してみましたが、イベントの関数内に貼り付けられたテキストで入力値がまだ更新されていません。キーアップ以外のすべてのイベントです。貼り付けイベント関数内からkeyupを呼び出すと、keyupイベント関数内から貼り付けられたテキストをサニタイズできます。そのようです...

$(':input').live
(
    'input paste',
    function(e)
    {
        $(this).keyup();
    }
);

$(':input').live
(
    'keyup',
    function(e)
    {
        // sanitize pasted text here
    }
);

ここには注意点が1つあります。Firefoxでは、キーアップごとに入力テキストをリセットすると、テキストが入力幅で許可されている表示可能領域よりも長い場合、キーアップごとに値をリセットすると、テキストを自動でキャレット位置にスクロールするブラウザ機能が無効になりますテキストの終わり。代わりに、テキストが最初にスクロールして戻り、キャレットが見えなくなります。


onpasteは、コンテンツが貼り付けられる前に呼び出されます。独自のafterpaste関数を作成して貼り付けの結果を洗浄するには、少なくとも4msの時間遅延が必要です。
DragonLord、

-1

クラスportlet-form-input-fieldを持つすべてのフィールドから特殊文字を削除するスクリプト:

// Remove special chars from input field on paste
jQuery('.portlet-form-input-field').bind('paste', function(e) {
    var textInput = jQuery(this);
    setTimeout(function() {
        textInput.val(replaceSingleEndOfLineCharactersInString(textInput.val()));
    }, 200);
});

function replaceSingleEndOfLineCharactersInString(value) {
    <%
        // deal with end-of-line characters (\n or \r\n) that will affect string length calculation,
        // also remove all non-printable control characters that can cause XML validation errors
    %>
    if (value != "") {
        value = value.replace(/(\x00|\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F)/gm,'');
        return value = value.replace(/(\r\n|\n|\r)/gm,'##').replace(/(\#\#)/gm,"\r\n");
    }
}

2
関連するサニタイズの説明と、ポスターの問題の解決に役立つ理由を追加していただけませんか?コードブロックを提供するだけでは、OP(または将来の検索者)が問題を解決する方法を理解するのに実際には役立ちません。誤解されたコードのコピー/貼り付けを促すだけです。
Troy Alford

-2

ここには注意点が1つあります。Firefoxでは、キーアップごとに入力テキストをリセットすると、テキストが入力幅で許可されている表示可能領域よりも長い場合、キーアップごとに値をリセットすると、テキストを自動でキャレット位置にスクロールするブラウザ機能が無効になりますテキストの終わり。代わりに、テキストが最初にスクロールして戻り、キャレットが見えなくなります。

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.