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

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

Какие-либо предложения?

3 ответа

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

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

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

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

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

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

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

    * 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. Обратите внимание, что я хочу сохранить форматирование так, как я бы вставил его в текстовую область (от word, excel...).

    Какие части форматирования вы хотите сохранить? Textarea сохранит только базовые - блоки форматирования.

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

Текущее решение прекрасно работает в 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>

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

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

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);
}
Другие вопросы по тегам