Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a div contenteditable and draggable

<div contenteditable="true" id="d">
<span>Text to edit</span>
</div>

$("#d").draggable();

I can only drag this div but how can i edit it (like on doubleclick editable property become active and on click dragging become active)?

like image 629
Gaurav Avatar asked Apr 25 '12 13:04

Gaurav


4 Answers

I find the follow behaviour much more intuitiv and smoothly (no double click needed).

Version 1 (best) http://jsfiddle.net/k1d9ftyu/

d.onmousedown = e => {
    d.contentEditable = false
}

d.ondragstart = e => {
    e.dataTransfer.setData('text', "XXX");
}

d.ondragend = () => {
    d.contentEditable = true
}

d.onmouseup = e => {
    d.contentEditable = true
    if (document.caretRangeFromPoint)
        range = document.caretRangeFromPoint(e.clientX, e.clientY)
    else {   // firefox
        var sel = window.getSelection()
        sel.collapse(e.rangeParent, e.rangeOffset)
    }
}
#d {
    background-color: #cfc;
    width: 200px;
}

#d[contenteditable=false] {
    cursor: grab;
}
<div contenteditable=true>
The green child div is contenteditable by default (as well as the parent div). The caret can run through both divs.
<div id="d" draggable=true contenteditable=true>Mousedown sets contenteditable=false, the div can be dragged. If not dragged after click, it becomes again contenteditable.</div>
The caret is positioned according to the last click.
</div>

Version 2

Similar as version 1, but uses mouseenter and needs a second click to position the caret correctly: http://jsfiddle.net/z8aojdg6

Version 3
Original version with contenteditable=false by default. Due to the focus() call the caret is placed at the line end. Thus a second click is needed to re-position the caret (it might be improved with usage of selection and range).

d.onmouseup = () => {
  d.contentEditable = true
  d.focus()
}

d.onblur = () => {
  d.contentEditable = false
}
#d {
    background-color: #ccc;
    width: 130px;
    height: 90px;
}
#d:focus {
    outline: 2px solid blue;
}
<div id="d" draggable=true contenteditable=false>
  Edit me when focussed. Drag me when inactive.</div>

Demo: http://jsfiddle.net/rz28c0xe

like image 72
Friedrich Avatar answered Nov 15 '22 10:11

Friedrich


$("#d").draggable()
  .click(function() {
    $(this).draggable({ disabled: false });
}).dblclick(function() {
    $(this).draggable({ disabled: true });
});
​​

DEMO

like image 37
Okan Kocyigit Avatar answered Nov 15 '22 09:11

Okan Kocyigit


$("#d")
.draggable()
.click(function(){
    if ( $(this).is('.ui-draggable-dragging') ) {
        return;
    }
    $(this).draggable( "option", "disabled", true );
    $(this).attr('contenteditable','true');
})
.blur(function(){
    $(this).draggable( 'option', 'disabled', false);
    $(this).attr('contenteditable','false');
});

This is the DEMO : http://jsfiddle.net/UH9UE/222/.

like image 9
ETY001 Avatar answered Nov 15 '22 10:11

ETY001


Another option is to pass the .draggable({ handle: "handleDiv" }) which allows you to keep draggable on all the time as well as allowing contenteditable editing. Just make your draggable div with two divs inside: the handle, and your contenteditable div.

API documentation

like image 6
Richard Avatar answered Nov 15 '22 08:11

Richard