I am trying to create a few draggable elements (tokens) that can be dragged around inside a contenteditable div. It seems that everything is working except that... after I drag one element and drop it, I cannot drag it again. It seems that I cannot bind to it's dragstart event again.
Any idea why this happens and how can i fix it?
Here's a link to my fiddle: http://jsfiddle.net/gXScu/1/
HTML:
<div id="editor" contenteditable="true">
Testime siinkohal seda, et kuidas<br />
on võimalik asja testida.
<span class="draggable" draggable="true" contenteditable="false">Token</span>
</div>
<span class="draggable" draggable="true" contenteditable="false">Token 2</span>
Javascript (jQuery)
var bindDraggables = function() {
console.log('binding draggables', $('.draggable').length);
$('.draggable').off('dragstart').on('dragstart', function(e) {
if (!e.target.id)
e.target.id = (new Date()).getTime();
e.originalEvent.dataTransfer.setData('text/html', e.target.outerHTML);
console.log('started dragging');
$(e.target).addClass('dragged');
}).on('click', function() {
console.log('there was a click');
});
}
$('#editor').on('dragover', function (e) {
e.preventDefault();
return false;
});
$('#editor').on('drop', function(e) {
e.preventDefault();
var e = e.originalEvent;
var content = e.dataTransfer.getData('text/html');
var range = null;
if (document.caretRangeFromPoint) { // Chrome
range = document.caretRangeFromPoint(e.clientX, e.clientY);
}
else if (e.rangeParent) { // Firefox
range = document.createRange();
range.setStart(e.rangeParent, e.rangeOffset);
}
console.log('range', range)
var sel = window.getSelection();
sel.removeAllRanges(); sel.addRange(range);
$('#editor').get(0).focus(); // essential
document.execCommand('insertHTML',false, content);
//$('#editor').append(content);
sel.removeAllRanges();
bindDraggables();
console.log($('[dragged="dragged"]').length);
$('.dragged').remove();
});
bindDraggables();
CSS:
#editor {
border: 2px solid red;
padding: 5px;
}
.draggable {
display: inline-block;
padding: 3px;
background: yellow;
cursor: move !important;
}
Apparently Chrome has a bug (not a surprise -
contenteditable
is the most buggy feature in all browsers). Your code works perfectly fine on Firefox, but for some reason element inserted into editable withinsertHTML
command cannot be dragged any more.I tried few hacks, but only one worked - inserting other element and then replacing it.
So instead:
Use something like this:
You can try this here: http://jsfiddle.net/gXScu/5/. I also corrected wrong order of this:
I also tried a few hacks but none of them seems to work. I was inspecting HTML and I found that in your example the newly inserted content don't have any contenteditable attribute assigned and when I assigned to it manually then it started working fine.
Here is my code http://jsfiddle.net/gXScu/8/
I just added this line
$('.draggable').attr("contenteditable", false);
inbindDraggables
method.I agree with Reinmar explanation over contenteditable.