Подтвердить что ты не робот

Drag-n-Drop для contentEditable элементов

В Интернете есть множество редакторов WYSIWYG, но мне еще предстоит найти ту, которая реализует реализацию drag-n-drop.

Легко создать собственный редактор, но я хочу, чтобы пользователь мог перетаскивать элементы (т.е. токены) из-за пределов редактируемой области и оставлять их по месту их выбора внутри редактируемой области.

Легко вводить html в определенном месте редактируемого элемента, но как определить, где должна быть каретка, когда пользователь перетаскивает DIV над некоторым элементом в области редактирования. Чтобы лучше проиллюстрировать то, что я пытаюсь объяснить, см. Следующий сценарий.

Редактируемая область (либо IFRAME в режиме редактирования, либо DIV с атрибутом contentEditable, установленным в true) уже содержит следующий текст:

"Дорогой, пожалуйста, обратите внимание..."

Теперь пользователь перетаскивает элемент, представляющий некоторый токен из списка элементов, над редактируемой областью, перемещая курсор над текстом, пока каретка не появится перед запятой (,) в тексте, как показано выше. Когда пользователь отпускает кнопку мыши в этом месте, будет добавлен HTML, который может привести к чему-то вроде этого:

"Дорогой {UserFirstName}, пожалуйста, обратите внимание...".

Я не знаю, когда-либо делал что-либо подобное, или, по крайней мере, знал, как это можно сделать с помощью JavaScript.

Любая помощь будет принята с благодарностью.

4b9b3361

Ответ 1

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

Поскольку можно связать события мыши с элементами, а не с текстовыми узлами, можно временно изменить редактируемый элемент. Найдите все элементы и оберните каждый текст node в промежутке, чтобы не нарушить поток текста. Каждому диапазону должно быть присвоено имя класса, чтобы мы могли найти его снова.

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

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

Опять же, используя делегирование событий, нужно добавить событие для события mouse-up (событие drop) для каждого символа. Теперь можно определить смещение, используя положение (смещение) символа в его родительском (обернутый текст - node). Теперь можно отменить все обертывания, сохраняя ссылку на вычисленное смещение и при отмене обертывания, сохраняя ссылку на применимый текст node.

Используя объекты диапазона и выбора браузера, теперь можно установить выбор с помощью вычисленного смещения на соответствующий текст node и ввести требуемый HTML в новый набор (позиция каретки), et viola!

Здесь следует фрагмент с использованием jQuery, который найдет текстовые поля, оберните их:

editElement.find("*:not(.text-node)").contents().filter(function(){ 
    return this.nodeType != 1;
}).wrap("<span class=\"text-node\"/>");

Чтобы найти каждый текст node и обернуть каждый символ, используйте:

editElement.find(".text-node").each(function()
{
    var textnode = $(this), text = textnode.text(), result = [];

    for (var i = 0; i < text.length; i++) result.push(text.substr(i, 1));

    textnode.html("<span class=\"char\">" 
        + result.join("</span><span class=\"char\">") + "</span>");
});

Чтобы отменить упаковку:

editElement.find(".text-node").each(function()
{
    this.parentNode.replaceChild(document.createTextNode($(this).text()), this);
});

Надеемся, что этот подход поможет тем, у кого есть подобные проблемы.

Ответ 2

Если я понимаю, что вы говорите, это просто базовое перетаскивание. Решение ниже должно быть близко к лучшему ответу FIREFOX. Я уверен, что для IE есть разные функции. Для получения дополнительной справки перейдите к http://www.html5rocks.com/en/tutorials/dnd/basics/.

Установите атрибут "draggable" объекта, который вы хотите перетащить, и установите для объекта "ondragstart" метод "dragStartHandler" или независимо от того, что вы вызываете.

// You can set this to 'text/plain' if you don't want to insert HTML content
var internalDNDType = 'text/html';

function dragStartHandler(event) {
  // This is whatever html data you want to insert.
  var textContent = "<b>"+userFirstName+"</b>";

  event.dataTransfer.setData(internalDNDType, textContent);
  event.dataTransfer.effectAllowed = 'copy';
}

function dragEnterHandler(event)
{
  event.preventDefault();
  return false;
}

function dragOverHandler(event)
{
  event.preventDefault();
  return false;
}

function dropHandler(event) {
  event.preventDefault();
  event.stopPropogation();
  return false;
}

Ответ 3

В настоящее время разрабатывается API HTML5, , но, к сожалению, IE его не поддерживает. Edit: Очевидно, что IE действительно поддерживает перетаскивание, но я не очень хорошо знаком с тем, как оно работает. Попробуйте Googling "Перетаскивание IE".

Попробуйте посмотреть эти сайты: