Как получить точный элемент, отредактированный в contenteditable div? - PullRequest
0 голосов
/ 07 мая 2018

У меня есть contenteditable div с прикрепленным к нему событием keyup. Есть много p тегов, созданных в этом div как пользовательские типы.

$(".pad").keyup(function(e) {
    doSomething();
});

Это событие keyup.

Как я могу определить, какой элемент пользователь отредактировал / создал в contenteditable div?

Я пробовал следующее, но, похоже, это не работает:

$(".pad p").keyup(function(e) {
    doSomething();
});

Цель состоит в том, чтобы иметь что-то вроде этого:

$(".pad").keyup(function(e) {
    theEditedElement = ...;
    $(theEditedElement).css("color","red");
    $(theEditedElement).(...);
});

Мы начинаем с:

<div class="pad" contenteditable="true">
    <p>Some text</p>
</div>

Затем пользователь редактирует:

<div class="pad" contenteditable="true">
    <p>Some text</p>
    <p>Some more text</p>
    <p>Even <b>more</b> text</p>
</div>

Если пользователь решает отредактировать <p>Some more text</p>, то этот конкретный элемент <p> должен быть извлечен.

1 Ответ

0 голосов
/ 07 мая 2018

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

const contentEl = document.querySelector('.pad');
const paras = contentEl.childNodes;

// here, set contenteditable attribute for all paragraphs inside of that div
for (let i = 0; i < paras.length; i++) {
  if (paras[i].nodeType === document.ELEMENT_NODE) {
    paras[i].setAttribute('contenteditable', true);
  }
}

contentEl.addEventListener('keyup', event => {
  // event.target will be the element that you are asking for 
  const theEditedElement = event.target;
  console.log(theEditedElement);
  theEditedElement.style.color = 'red';
});
<div class="pad">
    <p>Some text</p>
    <p>Some more text</p>
    <p>Even <b>more</b> text</p>
</div>

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

Другой вариант - создать наблюдатель мутации и позволить ему обрабатывать изменения в div в случае добавления каких-либо новых абзацев (пусть он устанавливает атрибут contenteditable вновь добавленного абзаца).

const contentEl = document.querySelector('.pad');
const paras = contentEl.childNodes;

for (let i = 0; i < paras.length; i++) {
  if (paras[i].nodeType === document.ELEMENT_NODE) {
    paras[i].setAttribute('contenteditable', true);
  }
}

contentEl.addEventListener('keyup', event => {
  // event.target will be the element that you are asking for 
  const theEditedElement = event.target;
  console.log(theEditedElement);
  theEditedElement.style.color = 'red';
});

// this code here is just to demonstrate the change to the enclosing div
const addNewParagraph = () => {
  const p = document.createElement('p');
  contentEl.appendChild(p);
  p.textContent = 'new paragraph';
};

const btn = document.querySelector('button');
btn.addEventListener('click', addNewParagraph);

// create mutation observer
const config = { childList: true };
const callback = function(mutationList) {
  for (const mutation of mutationList) {
    if (mutation.type === 'childList') {
      console.log('new paragraph has been added');
      // get the added node and set its contenteditable attribute
      mutation.addedNodes[0].setAttribute('contenteditable', true);
    }
  }
}
const observer = new MutationObserver(callback);
observer.observe(contentEl, config);
<button>add new paragraph</button>

<div class="pad">
    <p>Some text</p>
    <p>Some more text</p>
    <p>Even <b>more</b> text</p>
</div>
...