2010-06-09 2 views
14

В Интернете есть множество редакторов WYSIWYG, но я еще не нашел тот, который реализует какую-то форму реализации drag-n-drop.Drag-n-Drop на contentEditable элементы

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

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

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

«Дорогой, пожалуйста, принять к сведению ....»

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

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

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

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

ответ

6

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

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

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

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

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

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

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

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); 
}); 

Надежда этот подход помогает тем, имеющих аналогичные проблемы

+1

Возможно, не требуется применять делегированное событие mouseup в символьных пробелах, как упомянуто выше, можно использовать свойство исходного события droppable event, чтобы определить, действительно ли перетаскиваемый был отброшен для символьного интервала. Просто FYI .... – Raybiez

1

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

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

+0

Мой коллега нашел решение, именно для него я задал вопрос. Я скоро отправлю решение здесь – Raybiez

+0

Увы, его решение на самом деле не применимо. Охота вернулась ... grrr – Raybiez

+0

@Raybiez Возможно, вы могли бы отредактировать свой вопрос, чтобы добавить решение, которое не сработало? Это также будет иметь побочный эффект, чтобы вернуть этот вопрос на первую страницу. – Na7coldwater

2

Если я понимаю, что вы говорите, то это просто базовое перетаскивание. Решение ниже должно быть близко к лучшему ответу 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; 
} 
+0

Спасибо за ответ, однако это зависит от HTML5, и приложение должно было поддерживать старые браузеры. Для нового обновленного приложения без поддержки браузера, основанного на устаревших версиях, этот подход лучше всего подходит. – Raybiez

Смежные вопросы