javascriptjquerydomcontenteditablecontent-editor

drag and drop between lines or paragraphs in contenteditable


I am trying to drag and drop content in my contenteditable area.

<div contenteditable="true">
<p>some multiline paragraph
   paragraph</p>
<p>another multiline 
   paragraph</p>
<div class="draggable">DRAGGABLE</div>
</div>

Html with the same structure as above with more content is at http://jsfiddle.net/BQg7L/1

What I want is that I should be able to drag and drop the '.draggable' element into the paragraph <p> tags. And here is the detail. The drop should work as either of the following ways.

  1. The draggable needs to be DROPPED only between lines of the paragraph and when dropped, it should split the paragraph into two paragraphs at the point of dropping. And the dropped element should be between these two paragraphs.
  2. Or, draggable should be dropped only at the end of the paragraph (i.e., after the closing </p> tag) no matter where inside the paragraph it is dropped.

Any help is appreciated. The jsfiddle has only the question and no javascript code as I dont have any idea to start with. I will update the jsfiddle with js as I get some directions.


Solution

  • Here is the HTML code:

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
    <div class="drop_area" contenteditable="true">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut eget luctus enim. Nunc varius bibendum accumsan. Donec pretium mi eget risus auctor, nec pulvinar libero blandit. Aenean feugiat dolor sit amet nisi sagittis mattis. Praesent lacus metus, aliquam vehicula enim eu, fringilla sollicitudin est.</p>
        <p>Cras ut turpis at diam auctor euismod. Maecenas in mauris erat. Maecenas sit amet tellus a augue dignissim fringilla. Proin auctor et quam sed tincidunt. Vivamus vehicula est id ligula lacinia, ac euismod dolor porta. </p>
        <p class="test_row" style="visibility: hidden"></p>
        <p class="new_row" style="visibility: hidden"></p>
        <!-- the below div should be draggable and can be dropped between lines in the above paragraphs. On drop, the paragraph should be split into two paragraphs and the div should be between these paragraphs -->
        <div class="draggable">DRAGGABLE</div>
    </div>
    

    and the JS code:

    $(document).ready(function(){
        $.each($( ".drop_area p" ), function(){
            var rows = parseInt($(this).height())/parseInt($(this).css('line-height'));
            var arr_words = $(this).text().split(' ');
            $('.new_row').html('');
            $.each(arr_words, function(){
                $('.test_row').text($('.test_row').text() + ' ' + this);
    
                if(parseInt($('.test_row').height())>parseInt($(".drop_area p").css('line-height'))){
    
                    $('.new_row').html($('.new_row').html() + '<span style="height: 1px; width: 100%;display: block"></span> ' + this);
                   $('.test_row').text('')
                }
                else $('.new_row').html($('.new_row').html() + ' ' + this);
            })
            $(this).html($('.new_row').html())
        })
        $( ".draggable" ).draggable({
                    appendTo: 'body',
                    cursorAt: { top: 0, left: 30 },
                    revert: 'invariant',
                    helper: 'clone'
                });
            $( ".drop_area p span" ).droppable({
            activeClass: "ui-state-default",
            hoverClass: "ui-state-hover",
            accept: ":not(.ui-sortable-helper)",
            over: function(event, ui) {
                   $(this).css('height','10px');
             },
            out: function(event, ui) {
                $(this).css('height','1px');
            },
            drop: function( event, ui ) {
             $(this).replaceWith('</p><p>')
    
    
            }
        })
    })
    

    You can also check the result here