Положение курсора CKEditor после вставки не редактируемого элемента - PullRequest
8 голосов
/ 18 января 2012

У меня проблемы с разработкой плагинов CKEditor, которые вставляют нередактируемое содержимое в поток текста.Я пытался использовать функции диапазона, но с небольшим успехом, поскольку документация менее звездная.Итак, учитывая некоторый текст, допустим, что плагин вставляет «[[не редактируемый материал]]», а затем при отображении WYSIWYG оборачивает его в промежуток, поэтому его можно стилизовать в цвет:

<p>This is some text[[uneditable stuff here]]</p>

При первой вставке недоступного для редактирования материала мы хотим, чтобы пользователь затем мог продолжать вводить или нажимать клавишу Enter для новой строки.Следующий код (который я получил здесь: Как установить позицию курсора в конец текста в CKEditor? ) работает в Firefox, но (естественно) не в IE9, 8 или 7:

var s = editor.getSelection();
editor.insertElement(e); // element 'e'= a span created earlier
var p = e.getParent();
s.selectElement(p);
var selected_ranges = s.getRanges();
selected_ranges[0].collapse(false);  //  false = to the end of the selected node
s.selectRanges(selected_ranges);  // putting the current selection there

Итак, я хочу, чтобы курсор находился в позиции «^»:

<p>This is some text<span>[[uneditable stuff here]]</span>^</p>

Если новый элемент находится не в конце строки, то послесоздавая его, курсор должен перейти сюда:

<p>This is some text<span>[[uneditable stuff here]]</span>^ with more text after the new element</p>

В FF я могу получить курсор в конце строки, но не в позиции после нового элемента.В IE курсор все еще находится внутри нового SPAN, который я вижу, когда я печатаю, и он все еще в цвете CSS диапазона, а при переключении в представление SOURCE текст исчезает (потому что это не редактируемый диапазон).

Я знаю, что есть метод range.setStartAfter, но не смог заставить его работать даже в FF / Chrome.

У кого-нибудь есть действительно хорошие навыки использования методов диапазона и выбора в CKEditor?Я знаю, я не знаю!

Начинаю думать, что просто использовать editor.insertElement - это неправильно, и я должен узнать о функциях FakeElement (insertBogus?), Которых я не понимаю, еще.Штатные плагины для ссылок и изображений, похоже, не имеют этой проблемы.

Ответы [ 3 ]

7 голосов
/ 09 ноября 2012

Мне пришлось сделать некоторые хитрые вещи, чтобы решить эту проблему, но она все-таки была решена: после создания нередактируемого элемента (диапазон с атрибутом content-editable: false) мне пришлось создать «фиктивный» диапазон с текстом, состоящим изодного пространства.Итак, я вставляю реальный промежуток, а затем манекен.Но только при создании нового элемента.

Так что это идет в разделе «если не имеет дело с редактированием выбранного элемента».Здесь «a» - это экземпляр редактора, «e» - желаемый нередактируемый элемент, «f» - фиктивный интервал.

var e=new CKEDITOR.dom.element('span',a.document);
e.setAttributes({// stuff to create our element});
var f=new CKEDITOR.dom.element('span',a.document);
f.setAttributes({
    'class':'dummyF'
});
f.setText(' '); // that's just one space

// after section dealing with editing a selected item, in "else":
var sel = a.getSelection(); // current cursor position
a.insertElement(e); // the real new element
if(CKEDITOR.env.ie || CKEDITOR.env.webkit){ // IE & Chrome like this way
    f.insertAfter(e);
    sel.selectElement(f);
}
else { //FF likes this way (to ensure cursor stays in the right place)
    f.insertAfter(e);
    var rangeObjForSelection = new CKEDITOR.dom.range( a.document );
    rangeObjForSelection.selectNodeContents( f );
    a.getSelection().selectRanges( [ rangeObjForSelection ] );
}

Я должен признать, что не совсем понимаю,собственный кодЯ попал туда через часы проб и ошибок.О, и мне пришлось добавить правило htmlFilter, чтобы избавиться от оставшихся элементов 'f':

e.addRules({
  // e is the htmlFilter: applied to editor data before/upon output
  elements:{
    span:function(s){ // 's' is any spans found in the editor
        if(s.attributes&&s.attributes['data-cke-myelement']) {
            //stuff to do with my element
        }
        else if(s.attributes['class']=='dummyF') { //CKEDITOR.env.ie&&
            // for dummy spans to deal with "can't type or hit enter after new element" problem
            realtext = new String(s.children[0]['value']);
            realtext.replace(/^&nbsp;/,'');
            s.children[0]['value'] = realtext;
            delete s.name;
        }
    }
  }
});

Я также должен добавить, что не помню, почему мне пришлось заменить «nbsp»лица, прежде чем удалить промежуток.Но это работает.И я не знаю, почему для удаления вы используете «s.name» вместо просто «s».

Надеюсь, это кому-то поможет.

2 голосов
/ 24 декабря 2017

Я столкнулся с той же проблемой, и мне удалось установить курсор до и после моего не редактируемого содержимого (элемента SVG), обернув элемент SVG в <span>&#8203; + element + &#8203;</span>

const eHtml = '<span>&#8203; ' + svgHtml + '&#8203;</span>';  // Wrap element in a span with sorrounding &#8203;
const wrpEl = CKEDITOR.dom.element.createFromHtml(eHtml);
editor.insertElement(wrpEl);
wrpEl.remove(true); // Remove wrapping span leaving children.

Это сработало для меня, теперь я могу получить curesor в начале и в конце в элементе SVG.

0 голосов
/ 21 марта 2018

У меня была похожая проблема с вставкой изображения непосредственно в редактор, изображение стало выделяться, и я не хотел, чтобы оно выбиралось, поэтому мне пришлось отменить выбор изображения и поставить курсор сразу после изображения:

CKEditorObject.on('afterInsertHtml', function (e) {
    setTimeout(function () {
        var range = e.editor.getSelection().getRanges()[0];
        range.collapse();
        e.editor.getSelection().selectRanges( [ range ] );
    }, 1);
});
...