Как восстановить позицию каретки после CKEDITOR.inline в обработчике события onclick - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь инициализировать экземпляры CKEditor в событии onclick.Но у меня есть проблема, когда я просто нажимаю на него, когда это просто div (contenteitrable), и моя каретка будет на том месте, где я щелкнул.Но когда функция CKEditor.inline выполняет свою работу, она перемещает курсор в начало контейнера.Я хочу сохранить позицию каретки, которая была до CKEditor.inline, и установить ее после.

Я пробовал решения, такие как window.getSelection (). Anchor ... пробовал различные функции, которые позволяют нам сохранять позицию каретки и восстанавливать, но это не имеет никакого эффекта.Может быть, есть какой-то способ получить anchorNode / anchorOffset / selectionStart и установить их в CKEditor с помощью его собственных команд?

<div id="editor">
  <p>Hello my name is ...</p>
  <p>I am from ...</p>
  <p>London is the capital of Great Britain</p>
</div>
const editor = document.getElementById('editor');
  let isActivated = false;
  let isContenteditable = false;

  editor.onmouseenter = function(e) {
    if (!isContenteditable) {
      isContenteditable = true;
      editor.setAttribute('contenteditable', true);
    }
  };

  editor.onclick = function(e) {    
    if (!isActivated) {
      isActivated = true;
      const cke = CKEDITOR.inline('editor');

      cke.on('instanceReady', () => {
         // trying to set caret here
      });
    }
  }

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

использовать https://cdn.ckeditor.com/4.11.4/standard/ckeditor.js

PLAYGROUND - ошибка воспроизведения https://codepen.io/medinsky/pen/zQpBJQ?editors=1010

1 Ответ

0 голосов
/ 22 мая 2019

Нашли обходной путь, но, похоже, это не очень хорошо.

Есть еще идеи?

https://codepen.io/medinsky/pen/Gaymxb?editors=0010

const isInRange = (position, start, end) => position >= start && position <= end;

function setCaretPosition(el, sPos) {
  let charIndex = 0;
  const range = document.createRange();
  range.setStart(el, 0);
  range.collapse(true);
  const nodeStack = [el];
  let node,
    foundStart = false,
    stop = false;

  while (!stop && (node = nodeStack.pop())) {
    if (node.nodeType === Node.TEXT_NODE) {
      const nextCharIndex = charIndex + node.length;
      if (!foundStart && isInRange(sPos, charIndex, nextCharIndex)) {
        range.setStart(node, sPos - charIndex);
        foundStart = true;
      }
      if (foundStart && isInRange(sPos, charIndex, nextCharIndex)) {
        range.setEnd(node, sPos - charIndex);
        stop = true;
      }
      charIndex = nextCharIndex;
    } else {
      let i = node.childNodes.length;
      while (i--) {
        nodeStack.push(node.childNodes[i]);
      }
    }
  }
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
}

const editor = document.getElementById('editor');
let isActivated = false;

editor.onclick = function(e) {

  if (!isActivated) {
    editor.setAttribute('contenteditable', true);

    const {anchorNode, anchorOffset} = window.getSelection();
    if (anchorNode && anchorOffset) {
       anchorNode.parentElement.setAttribute('data-bookmark', anchorOffset.toString());
    }

    isActivated = true;
    const cke = CKEDITOR.inline('editor', {
      extraAllowedContent: "*[data-bookmark]"
    });

    cke.on('instanceReady', () => {
      const bookmarkElement = cke.container.$.querySelector('[data-bookmark]');

      if (bookmarkElement) {
        const bookmarkOffset = bookmarkElement.dataset.bookmark;

        if (bookmarkOffset) {
          bookmarkElement.removeAttribute('data-bookmark');
          setCaretPosition(bookmarkElement, bookmarkOffset);
        }
      }
    });

  }
}
...