Tangkap masukan tempel

210

Saya mencari cara untuk membersihkan input yang saya rekatkan ke browser, apakah ini mungkin dilakukan dengan jQuery?

Saya sudah berhasil sampai sejauh ini:

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

Sayangnya perkembangan saya menjadi melengking karena masalah "kecil" ini. Saya benar-benar akan membuat saya kemping bahagia jika seseorang bisa mengarahkan saya ke arah yang benar.

Christoffer Winterkvist
sumber
6
Harap tandai stackoverflow.com/a/1503425/749232 sebagai jawaban untuk penggunaan orang lain yang mengalami masalah yang sama. Itu menyelesaikannya untuk saya.
saji89
2
.live () tidak digunakan lagi pada jquery 1.9, mereka merekomendasikan .on () sebagai gantinya
Sameer Alibhai

Jawaban:

337

OK, hanya bertemu dengan masalah yang sama .. Saya pergi jauh

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

Hanya batas waktu kecil hingga .val () func dapat diisi.

E.

Evgeni Dimov
sumber
20
Bagaimana jika sudah ada teks di textarea dan Anda rekatkan, dan Anda hanya ingin teks yang disisipkan?
barfoon
39
Berfungsi dengan sempurna, terima kasih. Batas waktu 0 berfungsi dengan baik. Fungsi hanya perlu ditunda ke loop berikutnya.
Daniel Lewis
4
Baru saja dalam situasi yang sama. Waktu tunggu habis karena acara tempel tidak langsung, tetapi memerlukan beberapa milidetik untuk menempelkan konten papan klip.
James
8
@ user563811: Perhatikan saja bahwa batas waktu minimum resmi adalah 4 ms dalam HTML5.
pimvdb
4
Seperti kata sharif, 0ms masih menempatkan acara di bagian bawah tumpukan.
BobRodes
67

Anda benar-benar dapat mengambil nilai langsung dari acara tersebut . Ini agak tumpul bagaimana untuk sampai ke sana.

Kembalikan salah jika Anda tidak ingin melewatinya.

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

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

});
Charles Haro
sumber
2
Ini adalah cara untuk pergi
DdW
1
yaitu 11: window.clipboardData.getData ('text')
Wallstrider
4
Namun, perhatikan bahwa kebutuhan properti "originalEvent" hanya diperlukan jika Anda menangani acara dengan jQuery. Anda dapat melakukannya hanya e.clipboardData.getData('text')dalam JavaScript biasa.
Asier Paz
Jawaban terbaik di sini! Tetapi - saya merasa aneh bahwa versi ikatan pendek tidak berfungsi dengan ini, yaitu kesalahan jika saya mencoba ini: $ (this) .paste (function (e) {...}) ;, bahkan meskipun itu berfungsi untuk menyerahkan .on ('klik') singkat, dll.
HoldOffHunger
niggle: kodenya tidak ada paren penutup. Rupanya perubahan terlalu kecil untuk memungkinkan saya memperbaikinya sebagai edit.
Joachim Lous
42

Untuk kompatibilitas lintas platform, harus menangani peristiwa input dan pertukaran properti:

$ (something).bind ("input propertychange", function (e) {
    // check for paste as in example above and
    // do something
})
Xue Liangliang
sumber
2
Solusi indah yang berfungsi sebagai penangkap acara tempel dan kuncian. Catatan: Ini menyebabkan fungsi acara menyala dua kali karena beberapa alasan jika Anda menyorot konten input dan kemudian mengetik sesuatu di setidaknya IE8 (tidak penting dalam banyak kasus, tetapi mungkin sangat penting dalam kasus lain).
baacke
Bagus! Saya tidak tahu tentang yang ini, dan itu sangat sesuai dengan kebutuhan saya!
Marc Brillault
18

Saya semacam memperbaikinya dengan menggunakan kode berikut:

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

Sekarang saya hanya perlu menyimpan lokasi tanda sisipan dan menambahkan ke posisi itu maka saya sudah siap ... saya pikir :)

Christoffer Winterkvist
sumber
1
Bagaimana Anda menyimpan lokasi tanda sisipan?
Petah
@ Petah Anda dapat memeriksa elemen mana yang memiliki fokus .find(':focus'), dan mengetahui bahwa elemen menentukan lokasi tanda sisipan untuknya. Lihat ini .
Jacob
Ingatlah bahwa "live" sudah tidak digunakan lagi karena "on"
NBPalomino
inputmembuat perbedaan :) Saya biasanya memiliki ini di acara kotak teks saya keyup keydown paste inputtetapi jelas tergantung apa motif Anda
Pierre
10

Hmm ... aku pikir Anda bisa menggunakan e.clipboardDatauntuk menangkap data yang disisipkan. Jika tidak berhasil, lihat di sini .

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});
moff
sumber
2
Ketika saya menjalankan ini di Safari saya mendapatkan 'tidak terdefinisi' :(
Christoffer Winterkvist
1
clipboardData di-sandbox di sebagian besar browser (lubang keamanan yang jelas.)
podperson
2
Hanya Internet Explorer!
Lodewijk
9

Dengarkan acara tempel dan atur pendengar acara keyup. Pada keyup, ambil nilainya dan hapus pendengar acara keyup.

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}
Eric
sumber
6
Ini sangat bagus, tetapi tidak berfungsi untuk menempelkan klik kanan.
Joseph Ravenwolfe
juga tidak berfungsi untuk menempelkan klik tengah (X11) hanya berfungsi jika mereka menggunakan keyboard untuk menempel.
Jasen
7
$("#textboxid").on('input propertychange', function () {
    //perform operation
        });

Ini akan bekerja dengan baik.

Rajat Jain
sumber
6

Ini semakin dekat dengan apa yang Anda inginkan.

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() ) );
   }
 });
});

Harap dicatat bahwa ketika objek clipboardData tidak ditemukan (di browser selain IE), Anda saat ini mendapatkan nilai penuh elemen + nilai clipboard'ed.

Anda mungkin dapat melakukan beberapa langkah tambahan untuk membedakan kedua nilai, sebelum input & setelah input, jika Anda benar-benar hanya setelah data apa yang benar-benar ditempelkan ke dalam elemen.

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

Ini akan berfungsi untuk acara tempel mouse.

Abhiram
sumber
2
Ini adalah penggunaan terbaik dari semua.
Sinan Eldem
5

Bagaimana dengan membandingkan nilai asli bidang dan nilai bidang yang diubah dan mengurangi perbedaan sebagai nilai yang ditempelkan? Ini menangkap teks yang disisipkan dengan benar bahkan jika ada teks yang ada di lapangan.

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);
    });
});
Alo Sarv
sumber
5

Kode ini berfungsi untuk saya, tempel dari klik kanan atau salin tempel langsung

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

Ketika saya tempel Section 1: Labour Costitu menjadi 1dalam kotak teks.

Untuk mengizinkan hanya nilai float, saya menggunakan kode ini

 //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();
      }
    });
RN Kushwaha
sumber
4
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/html') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/html'));
        e.preventDefault();

        ...
    }
});

Lebih lanjut:

davidcondrey
sumber
teks / html tidak valid, hanya url dan teks.
Mike
@ Mike Saya menyalin cuplikan langsung dari dokumentasi yang direferensikan.
davidcondrey
Saya mencoba ini selama sekitar satu hari. teks / html tidak akan pernah berfungsi. Saya akhirnya menambahkan batas waktu 0 keterlambatan dan dapat mengambil html dari div tempat mereka menempel. Jika seseorang memiliki biola yang bisa membantu. Mungkin aku salah melakukannya ...
Mike
3

Lihat contoh ini: http://www.p2e.dk/diverse/detectPaste.htm

Ini penting melacak setiap perubahan dengan peristiwa input dan kemudian memeriksa apakah itu tempel dengan perbandingan string. Oh, dan di IE ada acara onpaste. Begitu:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})
Ilya Birman
sumber
Jadi tidak mungkin hanya mendapatkan teks tempel ketika acara terjadi?
Christoffer Winterkvist
Yah, saya kira Anda harus menghadapinya sendiri, seperti, membandingkan sebelum dan sesudah. Itu harus agak mudah. Tetapi mengapa Anda tidak memvalidasi ulang seluruh input? Lambat?
Ilya Birman
Saya hanya berpikir itu mungkin dilakukan tetapi saya kira tidak, Saat ini saya sedang mencoba metode lain dengan menempelkannya ke dalam textarea dan kemudian mentransfernya ke tujuan akhirnya. Saya berharap itu akan berhasil.
Christoffer Winterkvist
Anda hanya perlu menemukan fragmen pencocokan maksimum di awal dua string (sebelum dan sesudah). Segala sesuatu dari sana dan hingga perbedaan panjangnya adalah teks yang ditempel.
Ilya Birman
@IlyaBirman tidak bukan: misalnya teks yang disisipkan dapat menggantikan bagian (atau semua) dari yang asli
Jasen
1

Metode ini menggunakan konten jqueries (). Unwrap ().

  1. Pertama, deteksi acara tempel
  2. Tambahkan kelas unik ke tag yang sudah ada di elemen tempat kami menempelkan.
  3. Setelah batas waktu tertentu, pindai semua konten yang membuka tag yang tidak memiliki kelas yang Anda atur sebelumnya. Catatan: Metode ini tidak menghapus tag penutup sendiri seperti
    Lihat contoh di bawah ini.

    //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);
Shadrack B. Orina
sumber
Pasti jawaban terbaik, terpendek dan berbicara sendiri yang pernah dilihat !!! Terima kasih banyak, kamu membuat hariku;)
webprogrammer
0

Ini terbukti sangat ilusi. Nilai input tidak diperbarui sebelum eksekusi kode di dalam fungsi tempel acara. Saya mencoba memanggil acara lain dari dalam fungsi tempel acara, tetapi nilai input masih belum diperbarui dengan teks yang disisipkan di dalam fungsi acara apa pun. Itu semua peristiwa terlepas dari keyup. Jika Anda memanggil keyup dari dalam fungsi tempel acara, Anda dapat membersihkan teks yang disisipkan dari dalam fungsi event keyup. seperti itu ...

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

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

Ada satu peringatan di sini. Di Firefox, jika Anda mengatur ulang teks input pada setiap keyup, jika teks lebih panjang dari area yang dapat dilihat yang diizinkan oleh lebar input, maka mengatur ulang nilai pada setiap keyup akan merusak fungsionalitas browser yang secara otomatis menggulirkan teks ke posisi caret di akhir teks. Alih-alih, teks bergulir kembali ke awal meninggalkan tanda sisipan.


sumber
onpaste dipanggil sebelum konten disisipkan masuk. Anda perlu waktu tunda setidaknya 4ms untuk membuat fungsi afterpaste Anda sendiri, untuk mencuci hasil paste.
DragonLord
-1

Skrip untuk menghapus karakter khusus dari semua bidang dengan kelas 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");
    }
}
Alex si juru masak
sumber
2
Bisakah Anda menambahkan deskripsi sanitasi yang relevan dan mengapa itu dapat membantu menyelesaikan masalah poster? Cukup dengan menyediakan blok kode tidak benar-benar membantu OP (atau pencari masa depan) memahami bagaimana menyelesaikan masalah - itu hanya mendorong penyalinan / menempelkan kode yang disalahpahami.
Troy Alford
-2

Ada satu peringatan di sini. Di Firefox, jika Anda mengatur ulang teks input pada setiap keyup, jika teks lebih panjang dari area yang dapat dilihat yang diizinkan oleh lebar input, maka mengatur ulang nilai pada setiap keyup akan merusak fungsionalitas browser yang secara otomatis menggulirkan teks ke posisi caret di akhir teks. Alih-alih, teks bergulir kembali ke awal meninggalkan tanda sisipan.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
lordcheeto
sumber