JavaScript получает данные буфера обмена при вставке события (кросс-браузер) - PullRequest
271 голосов
/ 01 февраля 2010

Как веб-приложение может обнаружить событие вставки и извлечь данные для вставки?

Я хотел бы удалить содержимое HTML, прежде чем текст будет вставлен в текстовый редактор.

Очистка текста после последующей вставки работает, но проблема в том, что все предыдущее форматирование потеряно. Например, я могу написать предложение в редакторе и сделать его жирным, но когда я вставляю новый текст, все форматирование теряется. Я хочу очистить только текст, который вставлен, и оставить любое предыдущее форматирование без изменений.

В идеале решение должно работать во всех современных браузерах (например, MSIE, Gecko, Chrome и Safari).

Обратите внимание, что MSIE имеет clipboardData.getData(), но я не смог найти аналогичные функции для других браузеров.

Ответы [ 20 ]

4 голосов
/ 13 января 2014

Решение, которое работает для меня, - добавление прослушивателя событий для вставки события, если вы вставляете текстовый ввод. Так как событие вставки происходит до изменения текста во входных данных, внутри моего обработчика при вставке я создаю отложенную функцию, внутри которой я проверяю изменения в моем поле ввода, которые произошли при вставке:

onPaste: function() {
    var oThis = this;
    setTimeout(function() { // Defer until onPaste() is done
        console.log('paste', oThis.input.value);
        // Manipulate pasted input
    }, 1);
}
3 голосов
/ 01 февраля 2010

Первое, что приходит на ум - это программа-обработчик google closure lib http://closure -library.googlecode.com / SVN / багажник / закрытие / GOOG / демки / pastehandler.html

2 голосов
/ 14 октября 2011

Это сработало для меня:

function onPasteMe(currentData, maxLen) {
    // validate max length of pasted text
    var totalCharacterCount = window.clipboardData.getData('Text').length;
}

<input type="text" onPaste="return onPasteMe(this, 50);" />
2 голосов
/ 20 января 2015

Это решение заменяет тег html, оно простое и кросс-браузерное; проверьте этот jsfiddle: http://jsfiddle.net/tomwan/cbp1u2cx/1/, основной код:

var $plainText = $("#plainText");
var $linkOnly = $("#linkOnly");
var $html = $("#html");

$plainText.on('paste', function (e) {
    window.setTimeout(function () {
        $plainText.html(removeAllTags(replaceStyleAttr($plainText.html())));
    }, 0);
});

$linkOnly.on('paste', function (e) {
    window.setTimeout(function () {
        $linkOnly.html(removeTagsExcludeA(replaceStyleAttr($linkOnly.html())));
    }, 0);
});

function replaceStyleAttr (str) {
    return str.replace(/(<[\w\W]*?)(style)([\w\W]*?>)/g, function (a, b, c, d) {
        return b + 'style_replace' + d;
    });
}

function removeTagsExcludeA (str) {
    return str.replace(/<\/?((?!a)(\w+))\s*[\w\W]*?>/g, '');
}

function removeAllTags (str) {
    return str.replace(/<\/?(\w+)\s*[\w\W]*?>/g, '');
}

примечание: вы должны поработать с фильтром xss на обратной стороне, потому что это решение не может фильтровать строки вроде '<< >>'

1 голос
/ 30 декабря 2017

Простое решение:

document.onpaste = function(e) {
    var pasted = e.clipboardData.getData('Text');
    console.log(pasted)
}
1 голос
/ 11 мая 2015
function myFunct( e ){
    e.preventDefault();

    var pastedText = undefined;
    if( window.clipboardData && window.clipboardData.getData ){
    pastedText = window.clipboardData.getData('Text');
} 
else if( e.clipboardData && e.clipboardData.getData ){
    pastedText = e.clipboardData.getData('text/plain');
}

//work with text

}
document.onpaste = myFunct;
1 голос
/ 17 ноября 2013

Вы можете сделать это следующим образом:

используйте этот плагин jQuery для событий до и после вставки:

$.fn.pasteEvents = function( delay ) {
    if (delay == undefined) delay = 20;
    return $(this).each(function() {
        var $el = $(this);
        $el.on("paste", function() {
            $el.trigger("prepaste");
            setTimeout(function() { $el.trigger("postpaste"); }, delay);
        });
    });
};

Теперь вы можете использовать этот плагин;:

$('#txt').on("prepaste", function() { 

    $(this).find("*").each(function(){

        var tmp=new Date.getTime();
        $(this).data("uid",tmp);
    });


}).pasteEvents();

$('#txt').on("postpaste", function() { 


  $(this).find("*").each(function(){

     if(!$(this).data("uid")){
        $(this).removeClass();
          $(this).removeAttr("style id");
      }
    });
}).pasteEvents();

Explaination

Сначала установите uid для всех существующих элементов в качестве атрибута данных.

Затем сравните все узлы события POST PASTE. Таким образом, сравнивая, вы можете идентифицировать только что вставленный, потому что у него будет uid, а затем просто удалить атрибут style / class / id из вновь созданных элементов, чтобы вы могли сохранить старое форматирование.

1 голос
/ 27 декабря 2014

Просто дайте браузеру вставить как обычно в редактируемый div содержимого, а затем после вставки поменяйте местами любые элементы span, используемые для пользовательских стилей текста, с самим текстом. Кажется, это работает нормально в Internet Explorer и других браузерах, которые я пробовал ...

$('[contenteditable]').on('paste', function (e) {
    setTimeout(function () {
        $(e.target).children('span').each(function () {
            $(this).replaceWith($(this).text());
        });
    }, 0);
});

В этом решении предполагается, что вы используете jQuery и что вам не нужно форматировать текст в любом из редактируемых вами div-файлов .

Плюс в том, что это супер просто.

1 голос
/ 19 марта 2014
$('#dom').on('paste',function (e){
    setTimeout(function(){
        console.log(e.currentTarget.value);
    },0);
});
0 голосов
/ 14 сентября 2017

Это существующий код, опубликованный выше, но я обновил его для IE, ошибка заключалась в том, что при выделении и вставке существующего текста выбранный контент не удалялся. Это было исправлено с помощью кода ниже

selRange.deleteContents(); 

См. Полный код ниже

$('[contenteditable]').on('paste', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});
...