Drag-n-Drop на элементах contentEditable - PullRequest
14 голосов
/ 09 июня 2010

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

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

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

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

"Уважаемый, обратите внимание ..."

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

"Dear {UserFirstName}, обратите внимание ...".

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

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

Ответы [ 3 ]

6 голосов
/ 15 августа 2011

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

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

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

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

Опять-таки, используя делегирование событий, нужно добавить событие для события «мыши» (событие выпадения) для каждого символа. Теперь можно определить смещение, используя позицию символьного промежутка (смещение) внутри его родителя (обернутый текстовый узел). Теперь можно отменить все переносы, сохранив ссылку на вычисленное смещение и отменив перенос, сохранив ссылку на соответствующий текстовый узел.

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

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

editElement.find("*:not(.text-node)").contents().filter(function(){ 
    return this.nodeType != 1;
}).wrap("<span class=\"text-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 голосов
/ 03 января 2012

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

Установите атрибут «перетаскиваемый» объекта, который вы хотите перетащить, и установите метод «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;
}
1 голос
/ 19 июня 2010

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

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

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