Search code examples
jquerydrag-and-dropsummernote

Drag and drop external element to summernote editor with custom styling


I've been headbanging myself all mornign on trying to do this.

What I have

  • I have a div on the page with a list of resources (with a specific #id)
  • another div with an editable summernote instance

What I want to create

  1. Be able to drag a resource from the list into the summernote editor (maybe use jquery UI to make it prettier ?)
  2. That once you put the resource into the editor, it's automatically styled in a certain/custom way (e.g. with button-info style and with specific #id of the resource)
  3. That once the element is in the editor, we cannot edit the text from that element (so we cannot change the title of the resource) but instead be able to drag the whole element anywhere else in the editor (like you would with an image).

Here's the basic fiddle with all the basic code needed :

// when edit
$('.edit').on('click', function() {
  var target = $(this).attr('target');




  $(this).parent().find('.save').show();
  $(this).parent().find('.edit').hide();
  $('#module_descr').summernote({
    height: 300,
    toolbar: [
      ['img', ['picture']],
      ['style', ['style', 'addclass', 'clear']],
      ['fontstyle', ['bold', 'italic', 'ul', 'ol', 'link', 'paragraph']],
      ['fontstyleextra', ['strikethrough', 'underline', 'hr', 'color', 'superscript', 'subscript']]


    ]
  });
});

// when saving title or description
$('.save').on('click', function() {


  $('#module_descr').summernote('destroy');
  $(this).parent().find('.save').hide();
  $(this).parent().find('.edit').show();



});
.save {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.0/summernote.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.0/summernote.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />

<div class="col-md-6">
  <div class="panel panel-default">
    <div class="panel-heading">Ressources</div>
    <div class="panel-body" style="max-height:200px;overflow:auto;">
      <div class="list-group modules" id="ressourcesList">

        <a href="#" class="list-group-item" id="1"> Resource 1
					</a>

        <a href="#" class="list-group-item" id="2"> Resource 2
					</a>

        <a href="#" class="list-group-item" id="3"> Another Resource
					</a>


      </div>

    </div>
  </div>

  <div class="row" id="module_info">
    <div class="panel panel-info">
      <div class="panel-heading">
        <div class="row">
          <div class="col-md-9 title_descr"></div>
          <div class="col-md-3 text-right">
            <button type="button" class="btn btn-info btn-sm edit" target="module_descr">Edit</button>
            <button type="button" class="btn btn-success btn-sm save" target="module_descr" style="display:none">Save</button>
          </div>
        </div>
      </div>
      <div class="panel-body" id="module_descr" module_id="">

      </div>
    </div>
  </div>

I tried searching on google any possibleI would really appreciate any help with this,

Best Regards,

Xogno


Solution

  • Posting the answer in case it might help someone.

    With the help of my brother, I found a way to do exactly what I want. It turns out that with the option to create a custom button for summernote, the button doesn't need to be in the editor specifically. You can add any content to the edito using a "node".

    The code in the fiddle is the basic code to make it work, but here are the features :

    • there's a button with "add resource" which will add the resource to the editor (extracting the #id of the resource) - it will add a collapsible
    • you cannot edit the collapsible (so that the user doesn't mess everything up) , thanks to "contentEditable=false"
    • once you save de text, you can move the collapsible around thanks to the move icon - made possible with Jquery Sortable.

       // when edit
      
        $('.edit').on('click', function() { var target = $(this).attr('target');  $(this).parent().find('.save').show();
        $(this).parent().find('.edit').hide();
        $('#module_descr').summernote({
        disableDragAndDrop: true,
          height: 300,
          toolbar: [
            ['img', ['picture']],
            ['style', ['style', 'addclass', 'clear']],
            ['fontstyle', ['bold', 'italic', 'ul', 'ol', 'link', 'paragraph']],
            ['fontstyleextra', ['strikethrough', 'underline', 'hr', 'color', 'superscript', 'subscript']]
              ]
            });
          });
      
      
      $('.addResource').on('click', function() {
          var resourceId = $(this).parent().attr('id');
        console.log($('#3'));
        console.log($('#item2'));
      
        mydiv = $('<div><p>test paragraph</p></div>');
        console.log("I created a div : ", mydiv);
        var node = document.createElement('div');
        //node.textContent = "This is a DIV node\nAgain some text</br>";
      
        node.innerHTML = '<div class="col-md-12 resourceadded"><span class="handle button glyphicon glyphicon-move"></span><button class="btn btn-info " contenteditable="false" data-toggle="collapse" data-target="#demo_'+ resourceId + '">Collapsible '+ resourceId + '</button><div contenteditable="false" id="demo_'+ resourceId + '" class="collapse">Lorem ipsum dolor text....</div><br/><br/></div>';
      
        node.setAttribute("class", "test");
      
      
        // @param {Node} node
        $('#module_descr').summernote('insertNode', node);
          $('#module_info').find('.save').show();
        $('#module_info').find('.edit').hide();
      });
      
      // when saving title or description
      $('.save').on('click', function() {
      
      
        $('#module_descr').summernote('destroy');
        $(this).parent().find('.save').hide();
        $(this).parent().find('.edit').show();
      
      
      
      
      });
      
      
      
      
      $("#module_descr").sortable({
           placeholder: 'slide-placeholder',
          axis: "y",
          revert: 150,
          start: function(e, ui){
      
              placeholderHeight = ui.item.outerHeight();
              ui.placeholder.height(placeholderHeight + 15);
              $('<div class="slide-placeholder-animator" data-height="' + placeholderHeight + '"></div>').insertAfter(ui.placeholder);
      
          },
          change: function(event, ui) {
      
              ui.placeholder.stop().height(0).animate({
                  height: ui.item.outerHeight() + 15
              }, 300);
      
              placeholderAnimatorHeight = parseInt($(".slide-placeholder-animator").attr("data-height"));
      
              $(".slide-placeholder-animator").stop().height(placeholderAnimatorHeight + 15).animate({
                  height: 0
              }, 300, function() {
                  $(this).remove();
                  placeholderHeight = ui.item.outerHeight();
                  $('<div class="slide-placeholder-animator" data-height="' + placeholderHeight + '"></div>').insertAfter(ui.placeholder);
              });
      
          },
          stop: function(e, ui) {
              $(this).append('<br/><br/>');
              $(".slide-placeholder-animator").remove();
      
          },
      });
      

    Here's the fiddle to see the code in action : https://jsfiddle.net/Ltw7dsqr/5/

    One way to improve it would be to make the collapsible movable IN the editor, but I don't know how to make that possible.