Вставить как обычный текст Contenteditable div & textarea (word/excel)

Я хотел бы, чтобы текст вставлялся в редактируемый элемент div, но реагировал как текстовое поле.
Обратите внимание, что я хочу сохранить форматирование, как если бы я вставил его в текстовое поле (из слова, Excel...).
Итак.
1) Вставить текст в contenteditable div
2) Я получаю текст из буфера обмена
3) Я помещаю свое значение из буфера обмена в текстовое поле (не знаю, как??)
4) Получите значение из моего текстового поля и поместите его в мой contenteditable div

Есть предложения?


person Ziggiej    schedule 28.06.2012    source источник
comment
См. stackoverflow.com/questions/2176861/.   -  person Tim Down    schedule 28.06.2012
comment
Проблема не в получении данных, я уже использовал его метод для получения данных из буфера обмена. Но используя данные моего буфера обмена, чтобы вставить их в текстовое поле, есть моя проблема.   -  person Ziggiej    schedule 28.06.2012
comment
Вы можете сделать это, только сфокусировав текстовую область и разрешив браузеру вставлять в нее во время события вставки.   -  person Tim Down    schedule 28.06.2012
comment
Действительно, спасибо за это, в настоящее время я могу заставить его работать с событиями клавиатуры, заглядывая глубже, чтобы найти также решение при вставке событий щелчка.   -  person Ziggiej    schedule 28.06.2012
comment
В некоторых браузерах это просто невозможно. Событие paste слишком поздно для перенаправления фокуса.   -  person Tim Down    schedule 28.06.2012
comment
Я нашел обходной путь: mattbenton.net/2012/01/jquery -plugin-paste-events Но, похоже, он не работает в IE/FF, когда я переключаю внимание на prepaste и postpaste, работает в SAF   -  person Ziggiej    schedule 28.06.2012
comment
Этот плагин все еще использует событие вставки и, к сожалению, ничего не исправляет.   -  person Tim Down    schedule 28.06.2012
comment
нет ли обходного пути, чтобы исправить это?   -  person Ziggiej    schedule 28.06.2012
comment
Не то, чтобы я мог думать. Первое, что JavaScript, запущенный на странице, узнает о вставке из контекстного меню или меню редактирования, — это когда срабатывает событие paste. Некоторые браузеры запускают событие beforepaste, но обычно это бесполезно.   -  person Tim Down    schedule 28.06.2012


Ответы (3)


Я основной разработчик CKEditor, и по стечению обстоятельств последние 4 месяца я работал над поддержкой буфера обмена и сопутствующими вещами :) К сожалению, я не смогу полностью описать вам, как обрабатывается вставка, потому что рассказы об имплементации слишком сложно для меня даже после того, как я сам написал impl: D

Тем не менее, вот несколько советов, которые могут вам помочь:

  1. Не пишите wysiwyg-редактор — используйте существующий. Это займет все ваше время, и все равно ваш редактор будет глючить. Мы и ребята из других... два главных редактора (догадайтесь, почему существует только три) работают над этим годами, и у нас до сих пор есть полные списки ошибок ;).

  2. Если вам действительно нужно написать свой собственный редактор, посетите http://dev.ckeditor.com/browser/CKEditor/trunk/_source/plugins/clipboard/plugin.js — это старый импл, до того, как я его переписал, но он работает везде, где это возможно. Код ужасен... но он может вам помочь.

  3. Вы не сможете обработать все браузеры одним событием paste. Для обработки всех способов вставки мы используем как beforepaste, так и paste.

  4. Есть ряд (огромное количество: D) причуд браузеров, с которыми вам нужно справиться. Я не могу вам их описать, потому что даже спустя несколько недель я не вспомню их всех. Тем не менее, небольшая выдержка из нашей документации может быть вам полезна:

    Команда вставки (используется нестандартной вставкой — например, с нашей панели инструментов)

    * fire 'paste' on editable ('beforepaste' for IE)
    * !canceled && execCommand 'paste'
    * !success && fire 'pasteDialog' on editor
    

    Вставить из собственного контекстного меню и строки меню

    (Fx & Webkits are handled in 'paste' default listner.
    Opera cannot be handled at all because it doesn't fire any events
    Special treatment is needed for IE, for which is this part of doc)
    * listen 'onpaste'
    * cancel native event
    * fire 'beforePaste' on editor
    * !canceled && getClipboardDataByPastebin
    * execIECommand( 'paste' ) -> this fires another 'paste' event, so cancel it
    * fire 'paste' on editor
    * !canceled && fire 'afterPaste' on editor
    

    Остальная часть трюка — в IE мы прослушиваем оба события вставки, в остальных — только paste. Нам нужно предотвратить некоторые события в IE, потому что, поскольку мы прослушиваем оба события, иногда это может привести к двойной обработке. Это самая сложная часть, я думаю.

  5. #P10#
    #P11#
  6. См. http://dev.ckeditor.com/browser/CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js#L120 до строки 123 — это последняя часть задачи — вставка содержимого в выделение.

person Reinmar    schedule 02.07.2012
comment
@Привет ! Есть ли шанс, что вы знаете, почему ссылка, отображаемая в iframe, не активна? Но они работают, если щелкнуть правой кнопкой мыши -> открыть в новом окне. Это было бы прекрасно. Ваш продукт, кстати, отличный! - person Ced; 07.09.2015

Текущее решение отлично работает в IE/SAF/FF, но все же мне нужно исправить «не» события клавиатуры при вставке щелчком мыши... Текущее решение для событий «вставки» клавиатуры:

$(document).ready(function() {
    bind_paste_textarea();      
});


function bind_paste_textarea(){
    var activeOnPaste = null;
    $("#mypastediv").keydown(function(e){
        var code = e.which || e.keyCode;
        if((code == 86)){
            activeOnPaste = $(this);
            $("#mytextarea").val("").focus();
        }
    });
    $("#mytextarea").keyup(function(){
        if(activeOnPaste != null){
            $(activeOnPaste).focus();
            activeOnPaste = null;
        }
    });
}

<h2>DIV</h2>
<div id="mypastediv" contenteditable="true" style="width: 400px; height: 400px; border: 1px solid orange;">

</div>
<h2>TEXTAREA</h2>
<textarea id="mytextarea" style="width: 400px; height: 400px; border: 1px solid red;"></textarea>
person Ziggiej    schedule 28.06.2012

Я добился этого, используя библиотеку rangy для сохранения и восстановления выбора.

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

HTML

<div><div id="editor"contenteditable="true" type="text"></div><div>

JavaScript

var inputArea = $element.find('#editor');
var debounceInterval = 200;

function highlightExcessCharacters() {
    // Bookmark selection so we can restore it later
    var sel = rangy.getSelection();
    var savedSel = sel.saveCharacterRanges(editor);

    // Strip HTML
    // Prevent images etc being pasted into textbox
    inputArea.text(inputArea[0].innerText);

    // Restore the selection
    sel.restoreCharacterRanges(editor, savedSel);
}

// Event to handle checking of text changes
var handleEditorChangeEvent = (function () {

    var timer;

    // Function to run after timer passed
    function debouncer() {
        if (timer) {
            timer = null;
        }
        highlightExcessCharacters();
    }

    return function () {
        if (timer) {
            $timeout.cancel(timer);
        }
        // Pass the text area we want monitored for exess characters into debouncer here
        timer = $timeout(debouncer, debounceInterval);
    };
})();

function listen(target, eventName, listener) {
    if (target.addEventListener) {
        target.addEventListener(eventName, listener, false);
    } else if (target.attachEvent) {
        target.attachEvent("on" + eventName, listener);
    }
}

// Start up library which allows saving of text selections
// This is useful for when you are doing anything that might destroy the original selection
rangy.init();
var editor = inputArea[0];

// Set up debounced event handlers
var editEvents = ["input", "keydown", "keypress", "keyup", "cut", "copy", "paste"];
for (var i = 0, eventName; eventName = editEvents[i++];) {
    listen(editor, eventName, handleEditorChangeEvent);
}
person Amicable    schedule 29.06.2015