Bắt đầu vào dán


210

Tôi đang tìm cách vệ sinh đầu vào mà tôi dán vào trình duyệt, điều này có thể thực hiện được với jQuery không?

Tôi đã xoay sở để đưa ra điều này cho đến nay:

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

Thật không may, sự phát triển của tôi đã bị đình trệ vì vấn đề "nhỏ" này. Tôi thực sự sẽ làm cho tôi một người cắm trại hạnh phúc nếu ai đó có thể chỉ cho tôi đi đúng hướng.


6
Vui lòng đánh dấu stackoverflow.com/a/1503425/749232 là câu trả lời cho việc sử dụng của những người khác gặp vấn đề tương tự. Điều đó đã giải quyết nó cho tôi.
saji89

2
.live () không được chấp nhận kể từ jquery 1.9, họ đề xuất .on () thay vào đó
Sameer Alibhai

Câu trả lời:


337

OK, chỉ gặp phải vấn đề tương tự .. Tôi đã đi một chặng đường dài

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

Chỉ cần một khoảng thời gian chờ nhỏ cho đến khi .val () func có thể được điền.

E


20
Điều gì sẽ xảy ra nếu đã có văn bản trong textarea và bạn dán, và bạn chỉ muốn văn bản được dán?
barfoon

39
Hoạt động hoàn hảo, cảm ơn. Thời gian chờ là 0 cũng hoạt động. Hàm chỉ cần hoãn lại vòng lặp tiếp theo.
Daniel Lewis

4
Chỉ là trong một tình huống tương tự. Thời gian chờ là có vì sự kiện dán không phải là ngay lập tức, nhưng mất vài mili giây để nội dung clipboard được dán vào.
James

8
@ user563811: Chỉ cần lưu ý rằng thời gian chờ tối thiểu chính thức là 4ms trong HTML5.
pimvdb

4
Giống như sharif nói, 0ms vẫn đặt sự kiện ở dưới cùng của ngăn xếp.
BobRodes

67

Bạn thực sự có thể lấy giá trị trực tiếp từ sự kiện . Nó hơi khó hiểu làm thế nào để có được nó mặc dù.

Trả về false nếu bạn không muốn nó đi qua.

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

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

});

2
Đây là con đường để đi
DdW 20/03/2017

1
tức là 11: window.clipboardData.getData ('văn bản')
Wallstrider

4
Tuy nhiên, lưu ý rằng nhu cầu của thuộc tính "originalEvent" chỉ cần thiết nếu bạn đang xử lý sự kiện với jQuery. Bạn có thể làm chỉ e.clipboardData.getData('text')bằng JavaScript đơn giản.
Asier Paz

Câu trả lời tốt nhất ở đây! Nhưng - tôi thấy thật kỳ lạ khi phiên bản ngắn hạn của ràng buộc không hoạt động với điều này, tức là lỗi nếu tôi thử điều này: $ (this) .paste (function (e) {...});, thậm chí mặc dù nó hoạt động với tay ngắn .on ('click'), v.v.
HoldPackHunger

niggle: mã bị thiếu một paren đóng. Rõ ràng sự thay đổi là quá nhỏ để cho phép tôi sửa nó dưới dạng chỉnh sửa.
Joachim Lous

42

Để tương thích đa nền tảng, cần xử lý các sự kiện oninput và onpropertychange:

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

2
Giải pháp đẹp mà hoạt động như cả dán và keyup sự kiện bắt. Lưu ý: Điều này làm cho chức năng sự kiện để bắn hai lần đối với một số lý do nếu bạn làm nổi bật các nội dung đầu vào và sau đó gõ một cái gì đó trong ít nhất IE8 (không quan trọng trong nhiều trường hợp, nhưng có thể rất quan trọng trong những người khác).
baacke

Đẹp ! Tôi không biết về điều này, và nó hoàn toàn phù hợp với nhu cầu của tôi!
Marc Brillault

18

Tôi sắp xếp nó bằng cách sử dụng đoạn mã sau:

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

Bây giờ tôi chỉ cần lưu trữ vị trí caret và nối vào vị trí đó thì tôi đã sẵn sàng ... Tôi nghĩ :)


1
Làm thế nào bạn lưu trữ vị trí caret?
Petah

@Petah Bạn có thể kiểm tra phần tử nào có tiêu điểm .find(':focus')và biết phần tử đó xác định vị trí dấu mũ cho nó. Xem này .
Jacob

Hãy nhớ rằng "trực tiếp" không được dùng để "bật"
NBPalomino

inputlàm cho sự khác biệt :) Tôi thường có những điều này trong các sự kiện trong hộp văn bản của mình keyup keydown paste inputnhưng rõ ràng phụ thuộc vào động cơ của bạn là gì
Pierre

10

Hmm ... Tôi nghĩ rằng bạn có thể sử dụng e.clipboardDatađể bắt dữ liệu được dán. Nếu nó không pan ra, hãy xem ở đây .

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

2
Khi tôi chạy này trong Safari tôi nhận được 'không xác định' :(
Christoffer Winterkvist

1
clipboardData được sandbox trên hầu hết các trình duyệt (lỗ hổng bảo mật rõ ràng.)
podperson

2
Chỉ có Internet Explorer!
Lodewijk

9

Nghe sự kiện dán và thiết lập trình nghe sự kiện keyup. Trên keyup, nắm bắt giá trị và loại bỏ trình nghe sự kiện keyup.

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

6
Điều này là rất tốt, nhưng nó không hoạt động để dán nhấp chuột phải.
Joseph Ravenwolfe

Nó không hoạt động để dán nhấp chuột giữa (X11) nó chỉ hoạt động nếu họ sử dụng bàn phím để dán.
Jasen

7
$("#textboxid").on('input propertychange', function () {
    //perform operation
        });

Nó sẽ hoạt động tốt.


6

Điều này đang tiến gần hơn đến những gì bạn có thể muốn.

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

Xin lưu ý rằng khi không tìm thấy đối tượng clipboardData (trên các trình duyệt khác IE), bạn hiện đang nhận được giá trị đầy đủ của phần tử + giá trị của bảng tạm.

Bạn có thể có thể thực hiện một số bước bổ sung để khác biệt hai giá trị, trước đầu vào & sau đầu vào, nếu bạn thực sự chỉ sau khi dữ liệu thực sự được dán vào thành phần.


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

Điều này sẽ làm việc cho sự kiện dán chuột.


2
Đây là cách sử dụng tốt nhất của tất cả.
Sinan Eldem

5

Làm thế nào về việc so sánh giá trị ban đầu của trường và giá trị thay đổi của trường và khấu trừ chênh lệch như giá trị dán? Điều này bắt văn bản được dán chính xác ngay cả khi có văn bản hiện có trong trường.

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

Mã này đang hoạt động đối với tôi hoặc dán từ nhấp chuột phải hoặc dán sao chép trực tiếp

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

Khi tôi dán Section 1: Labour Costnó trở thành 1trong hộp văn bản.

Để chỉ cho phép giá trị float tôi sử dụng mã này

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

        ...
    }
});

Thêm nữa:


văn bản / html không hợp lệ, chỉ có url và văn bản.
Mike

@Mike Tôi đã sao chép đoạn mã trực tiếp từ tài liệu được tham chiếu.
davidcondrey

Tôi đã thử điều này trong khoảng một ngày. văn bản / html sẽ không bao giờ hoạt động. Cuối cùng tôi đã thêm thời gian chờ là 0 và có thể lấy html từ div nơi họ đang dán. Nếu ai đó có một câu đố làm việc có thể giúp ích. Có lẽ tôi chỉ đang làm sai ...
Mike

3

Xem ví dụ này: http://www.p2e.dk/diverse/detectPaste.htmlm

Nó cần thiết theo dõi mọi thay đổi với sự kiện oninput và sau đó kiểm tra xem đó có phải là dán bằng cách so sánh chuỗi hay không. Ồ, và trong IE có một sự kiện onpaste. Vì thế:

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

Vì vậy, không thể chỉ có được văn bản dán khi sự kiện xảy ra?
Christoffer Winterkvist

Chà, tôi đoán bạn sẽ phải tự mình giải quyết nó, thích, so sánh trước và sau. Nó phải khá dễ dàng. Nhưng tại sao bạn không xác nhận lại toàn bộ đầu vào? Chậm?
Ilya Birman

Tôi chỉ nghĩ rằng điều đó là có thể làm được nhưng tôi đoán là không, Hiện tại tôi đang thử một phương pháp khác bằng cách dán nó vào một vùng văn bản và sau đó chuyển nó đến đích cuối cùng. Tôi hy vọng điều đó sẽ làm việc.
Christoffer Winterkvist

Bạn chỉ cần tìm đoạn phù hợp tối đa ở đầu hai chuỗi (trước và sau). Tất cả mọi thứ từ đó và cho đến sự khác biệt độ dài là văn bản dán.
Ilya Birman

@IlyaBirman không phải vậy: vd: văn bản được dán có thể thay thế một phần (hoặc tất cả) bản gốc
Jasen

1

Phương pháp này sử dụng nội dung jqueries (). Unrap ().

  1. Đầu tiên, phát hiện sự kiện dán
  2. Thêm một lớp duy nhất vào các thẻ đã có trong phần tử mà chúng ta đang dán.
  3. Sau khi hết thời gian, hãy quét qua tất cả các thẻ hủy ghép nội dung không có lớp mà bạn đã đặt trước đó. Lưu ý: Phương pháp này không xóa các thẻ tự đóng như
    Xem ví dụ bên dưới.

    //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);

Chắc chắn là câu trả lời hay nhất, ngắn nhất và tự nói từng thấy !!! Cảm ơn bạn rất nhiều, bạn đã thực hiện ngày của tôi;)
lập trình viên web

0

Điều này tỏ ra khá ảo tưởng. Giá trị của đầu vào không được cập nhật trước khi thực thi mã bên trong chức năng dán sự kiện. Tôi đã thử gọi các sự kiện khác từ bên trong chức năng dán sự kiện nhưng giá trị đầu vào vẫn không được cập nhật với văn bản được dán bên trong chức năng của bất kỳ sự kiện nào. Đó là tất cả các sự kiện ngoài keyup. Nếu bạn gọi keyup từ bên trong chức năng sự kiện dán, bạn có thể vệ sinh văn bản đã dán từ bên trong chức năng sự kiện keyup. như vậy ...

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

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

Có một cảnh báo ở đây. Trong Firefox, nếu bạn đặt lại văn bản đầu vào trên mỗi lần gõ phím, nếu văn bản dài hơn vùng có thể xem được cho phép bởi chiều rộng đầu vào, thì việc đặt lại giá trị trên mỗi lần khóa sẽ phá vỡ chức năng trình duyệt tự động cuộn văn bản đến vị trí dấu mũ ở cuối văn bản. Thay vào đó, văn bản cuộn trở lại từ đầu để lại dấu mũ.


onpaste được gọi trước khi nội dung được dán vào. Bạn cần độ trễ theo thời gian ít nhất là 4ms để tạo chức năng dư vị của riêng bạn, để rửa kết quả dán.
DragonLord

-1

Tập lệnh để loại bỏ các ký tự đặc biệt khỏi tất cả các trường với lớp 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
Bạn có thể vui lòng thêm một mô tả về vệ sinh có liên quan và tại sao nó có thể giúp giải quyết vấn đề của người gửi? Đơn giản chỉ cần cung cấp một khối mã không thực sự giúp OP (hoặc người tìm kiếm trong tương lai) hiểu cách giải quyết vấn đề - nó chỉ khuyến khích sao chép / dán mã bị hiểu nhầm.
Troy Alford

-2

Có một cảnh báo ở đây. Trong Firefox, nếu bạn đặt lại văn bản đầu vào trên mỗi lần gõ phím, nếu văn bản dài hơn vùng có thể xem được cho phép bởi chiều rộng đầu vào, thì việc đặt lại giá trị trên mỗi lần khóa sẽ phá vỡ chức năng trình duyệt tự động cuộn văn bản đến vị trí dấu mũ ở cuối văn bản. Thay vào đó, văn bản cuộn trở lại từ đầu để lại dấu mũ.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.