จับแปะ


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 สามารถรับข้อมูลได้

อี


20
ถ้ามีข้อความใน textarea อยู่แล้วและคุณวางและคุณต้องการวางข้อความ?
barfoon

39
ทำงานได้อย่างสมบูรณ์แบบขอบคุณ การหมดเวลาของ 0 ก็ใช้ได้เช่นกัน ฟังก์ชั่นเพียงแค่ต้องการเลื่อนไปที่วงถัดไป
Daniel Lewis

4
เพิ่งอยู่ในสถานการณ์ที่คล้ายคลึงกัน หมดเวลาเนื่องจากกิจกรรมการวางไม่ได้เกิดขึ้นทันที แต่ใช้เวลาสักครู่เพื่อให้สามารถวางเนื้อหาของคลิปบอร์ดได้
James

8
@ user563811: โปรดทราบว่าการหมดเวลาขั้นต่ำอย่างเป็นทางการคือ 4ms ใน HTML5
pimvdb

4
เช่นเดียวกับ sharif บอกว่า 0ms ยังคงวางเหตุการณ์ที่ด้านล่างของสแต็ก
BobRodes

67

คุณสามารถคว้าค่าได้โดยตรงจากเหตุการณ์เหตุการณ์มันค่อนข้างป้านวิธีไปถึงแม้ว่า

กลับเท็จถ้าคุณไม่ต้องการให้มันผ่านไป

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

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

});

2
นี่คือวิธีที่จะไป
DdW

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

4
อย่างไรก็ตามโปรดทราบว่าความต้องการคุณสมบัติ "originalEvent" นั้นจำเป็นเฉพาะในกรณีที่คุณจัดการกับเหตุการณ์ด้วย jQuery คุณสามารถทำได้เพียงแค่e.clipboardData.getData('text')ใช้ JavaScript ธรรมดา
Asier Paz

คำตอบที่ดีที่สุดที่นี่! แต่ - ฉันพบว่ามันแปลกที่การผูกข้อมูลระยะสั้นไม่สามารถใช้งานได้เช่นข้อผิดพลาดถ้าฉันลองทำเช่นนี้: $ (this) .paste (function (e) {... }) ;, แม้ แม้ว่าจะใช้งานได้ในระยะสั้น. on ('คลิก') ฯลฯ
HoldOffHunger

niggle: รหัสไม่มีการปิด paren เห็นได้ชัดว่าการเปลี่ยนแปลงนั้นเล็กเกินไปที่จะอนุญาตให้ฉันแก้ไขเป็นการแก้ไข
Joachim Lous

42

สำหรับความเข้ากันได้ของแพลตฟอร์มข้ามควรจัดการกับอินพุตและเหตุการณ์ onpropertychange:

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

2
โซลูชันที่สวยงามที่ทำงานได้ทั้งการวางและการจับคีย์ - เหตุการณ์ หมายเหตุ:นี่จะทำให้ฟังก์ชันเหตุการณ์เริ่มทำงานสองครั้งด้วยเหตุผลบางอย่างหากคุณเน้นเนื้อหาอินพุตแล้วพิมพ์บางอย่างในIE8 เป็นอย่างน้อย (ไม่สำคัญในหลายกรณี แต่อาจมีความสำคัญมากในบางกรณี)
baacke

เยี่ยมมาก! ฉันไม่รู้เกี่ยวกับอันนี้และมันก็ลงตัวกับความต้องการของฉัน!
Marc Brillault

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')และรู้ว่าองค์ประกอบกำหนดตำแหน่งตัวชี้สำหรับมัน ดูนี่สิ
จาค็อบ

โปรดจำไว้ว่า "สด" ถูกคัดค้าน "on"
NBPalomino

inputสร้างความแตกต่าง :) โดยปกติฉันมีสิ่งเหล่านี้ในเหตุการณ์กล่องข้อความของฉันkeyup keydown paste inputแต่เห็นได้ชัดว่าขึ้นอยู่กับแรงจูงใจของคุณ
Pierre

10

อืม ... ฉันคิดว่าคุณสามารถใช้e.clipboardDataเพื่อจับข้อมูลที่ถูกวาง ถ้ามันไม่ได้เลื่อนออกได้ดูที่นี่

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

2
เมื่อฉันเรียกใช้งานใน Safari ฉันจะได้ 'undefined' :(
Christoffer Winterkvist

1
clipboardData ถูก sandboxed บนเบราว์เซอร์ส่วนใหญ่ (ช่องโหว่ด้านความปลอดภัยที่ชัดเจน)
podperson

2
Internet Explorer เท่านั้น!
Lodewijk

9

ฟังเหตุการณ์การวางและตั้งค่าฟังเหตุการณ์ keyup บน keyup ให้ดักจับค่าและลบตัวฟังเหตุการณ์ keyup

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

6
นี่เป็นสิ่งที่ดีมาก แต่ไม่ได้ผลสำหรับการวางคลิกขวา
โจเซฟ Ravenwolfe

มันไม่ทำงานสำหรับวางกลางคลิก (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) คุณกำลังรับค่าเต็มขององค์ประกอบ + ค่าคลิปบอร์ด

คุณสามารถทำขั้นตอนพิเศษบางอย่างเพื่อให้ทั้งสองค่าต่างกันก่อนอินพุต & หลังอินพุตหากคุณเป็นจริงหลังจากข้อมูลที่ถูกวางลงในองค์ประกอบอย่างแท้จริงเท่านั้น


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

สิ่งนี้จะใช้ได้กับเหตุการณ์การวางเมาส์


2
นี่คือการใช้งานที่ดีที่สุดของทั้งหมด
Sinan Eldem

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 Costมันจะกลายเป็น1ในกล่องข้อความ

เพื่ออนุญาตเฉพาะค่าลอยฉันใช้รหัสนี้

 //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 และ text เท่านั้น
Mike

@ ไมค์ฉันคัดลอกตัวอย่างโดยตรงจากเอกสารอ้างอิง
davidcondrey

ฉันลองสิ่งนี้ประมาณหนึ่งวัน ข้อความ / html จะไม่ทำงาน ฉันลงเอยด้วยการเพิ่มการหมดเวลาของการหน่วงเวลา 0 และสามารถคว้า html จาก div ที่พวกเขาวางระบบหากใครบางคนมีซอที่ใช้งานได้ซึ่งจะช่วยได้ บางที im เพียงแค่ทำมันผิด ...
ไมค์

3

ดูตัวอย่างนี้: http://www.p2e.dk/diverse/detectPaste.htm

มันจำเป็นติดตามทุกการเปลี่ยนแปลงด้วยเหตุการณ์ oninput แล้วตรวจสอบว่าเป็นการวางโดยการเปรียบเทียบสตริง โอ้และใน IE มีกิจกรรม onpaste ดังนั้น:

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

ดังนั้นจึงเป็นไปไม่ได้ที่จะได้รับข้อความวางเมื่อเหตุการณ์เกิดขึ้น?
Christoffer Winterkvist

ฉันคิดว่าคุณจะต้องจัดการกับมันด้วยตัวเองเช่นเปรียบเทียบก่อนและหลัง มันจะค่อนข้างง่าย แต่ทำไมคุณไม่ตรวจสอบอินพุตทั้งหมดอีกครั้ง ช้า?
Ilya Birman

ฉันแค่คิดว่าเป็นไปได้ที่จะทำ แต่ฉันเดาไม่ได้ตอนนี้ฉันกำลังลองวิธีอื่นโดยการวางมันลงใน textarea แล้วโอนมันไปยังปลายทางสุดท้าย ฉันหวังว่าจะได้ผล
Christoffer Winterkvist

คุณเพียงแค่ต้องค้นหาส่วนการจับคู่สูงสุดในการเริ่มต้นของสองสาย (ก่อนและหลัง) ทุกอย่างตั้งแต่ตรงนี้จนถึงความแตกต่างของความยาวคือข้อความที่วาง
Ilya Birman

@IlyaBirman ไม่ใช่: เช่นข้อความที่วางอาจเป็นการแทนที่บางส่วน (หรือทั้งหมด) ของต้นฉบับ
Jasen

1

วิธีนี้ใช้เนื้อหา jqueries (). 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

สิ่งนี้พิสูจน์แล้วว่าไม่เหมาะสม ค่าของอินพุตไม่ถูกอัพเดตก่อนการเรียกใช้โค้ดภายในฟังก์ชันวางเหตุการณ์ ฉันพยายามเรียกกิจกรรมอื่น ๆ จากภายในฟังก์ชั่นการวางเหตุการณ์ แต่ค่าอินพุตยังไม่ได้รับการปรับปรุงด้วยข้อความที่วางอยู่ภายในฟังก์ชั่นของกิจกรรมใด ๆ นั่นคือเหตุการณ์ทั้งหมดนอกเหนือจากการกดปุ่ม หากคุณเรียกใช้การกดปุ่มจากภายในฟังก์ชั่นการวางเหตุการณ์คุณสามารถฆ่าเชื้อข้อความที่วางจากภายในฟังก์ชั่นการจัดเรียงเหตุการณ์ อย่างนั้น ...

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

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

มีข้อแม้หนึ่งข้ออยู่ที่นี่ ใน Firefox หากคุณรีเซ็ตข้อความอินพุตในทุก ๆ คีย์หากข้อความยาวเกินกว่าพื้นที่ที่สามารถดูได้ที่ความกว้างของอินพุตอนุญาตให้รีเซ็ตค่าในทุก ๆ คีย์คีย์จะทำลายฟังก์ชันการทำงานของเบราว์เซอร์ที่เลื่อนข้อความไปยังตำแหน่งคาเร็ตอัตโนมัติ ท้ายข้อความ แต่ข้อความเลื่อนกลับไปที่จุดเริ่มต้นทำให้เครื่องหมายรูปหมวกไม่อยู่ในมุมมอง


เรียกว่า onpaste ก่อนที่เนื้อหาจะถูกวางระบบคุณต้องใช้เวลาล่าช้าอย่างน้อย 4ms เพื่อสร้างฟังก์ชั่น afterpaste ของคุณเองเพื่อล้างผลลัพธ์ของการวาง
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 (หรือผู้ค้นหาในอนาคต) เข้าใจวิธีการแก้ปัญหาได้จริง ๆ เพียง แต่สนับสนุนการคัดลอก / วางโค้ดที่เข้าใจผิด
ทรอยอัลฟอร์ด

-2

มีข้อแม้หนึ่งข้ออยู่ที่นี่ ใน 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.