admin管理员组

文章数量:1292123

I have an HTML page. In that page, I'm trying to add a WYSIWYG editor. I've decided to use this one. I have it working in my app. However, I cannot seem to get it styled the way I want. I believe the problem is because I'm using this theme. I'd really like to be able to have the toolbar floating above the control, to the right of the textbox label. At the same time, I'd like to keep the paper look instead of the bulky box.

At this point, I've tried what's in this fiddle. Still, the styling is all wrong. The main code looks like this:

<div class="container">
<div class="form-group label-static is-empty">  
  <div class="row">
    <div class="col-xs-3"><label class="control-label" for="Description">Description</label>  </div>
    <div class="col-xs-9">
      <div id="toolbar" class="pull-right" style="vertical-align:top; margin-top:0; padding-top:0;">[toolbar]</div>
    </div>
  </div>
  <input class="form-control" rows="3" id="Description" name="Description" onfocus="setMode('rich');" onblur="setMode(null);"></div>
</div>

While I'm using the following JavaScript:

$(function () {
  $.material.init();
});

function setMode(name) {
  if (name === 'rich') {
    $('#Description').summernote({ focus: true });  
  } else {
    $('#Description').summernote('destroy');
  }
}

Any help is appreciated. This is really frustrating.

I have an HTML page. In that page, I'm trying to add a WYSIWYG editor. I've decided to use this one. I have it working in my app. However, I cannot seem to get it styled the way I want. I believe the problem is because I'm using this theme. I'd really like to be able to have the toolbar floating above the control, to the right of the textbox label. At the same time, I'd like to keep the paper look instead of the bulky box.

At this point, I've tried what's in this fiddle. Still, the styling is all wrong. The main code looks like this:

<div class="container">
<div class="form-group label-static is-empty">  
  <div class="row">
    <div class="col-xs-3"><label class="control-label" for="Description">Description</label>  </div>
    <div class="col-xs-9">
      <div id="toolbar" class="pull-right" style="vertical-align:top; margin-top:0; padding-top:0;">[toolbar]</div>
    </div>
  </div>
  <input class="form-control" rows="3" id="Description" name="Description" onfocus="setMode('rich');" onblur="setMode(null);"></div>
</div>

While I'm using the following JavaScript:

$(function () {
  $.material.init();
});

function setMode(name) {
  if (name === 'rich') {
    $('#Description').summernote({ focus: true });  
  } else {
    $('#Description').summernote('destroy');
  }
}

Any help is appreciated. This is really frustrating.

Share edited Aug 9, 2016 at 5:56 M.Tanzil 2,0051 gold badge14 silver badges28 bronze badges asked Aug 2, 2016 at 16:50 user70192user70192 14.2k53 gold badges167 silver badges244 bronze badges 9
  • I'm not sure what you're looking for. Your jsfiddle doesn't load summernote because of javascript errors. So I must add: Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – Vince Commented Aug 4, 2016 at 17:53
  • I'm trying to get the fiddle to work as explained in the question. The JavaScript error is odd as it says "setMode is not defined" even though it clearly is. – user70192 Commented Aug 4, 2016 at 19:14
  • 1 @user70192 the js error is because of the jsfiddle loading type. see this updated fiddle – Jaqen H'ghar Commented Aug 4, 2016 at 19:30
  • @JaqenH'ghar - Thanks! Didn't know you could do that in JSFiddle. I've updated the question with the new fiddle. – user70192 Commented Aug 4, 2016 at 20:17
  • Is something like this what you want? jsfiddle/j1hfpqam – Ricky Ruiz Commented Aug 4, 2016 at 23:32
 |  Show 4 more ments

2 Answers 2

Reset to default 8 +250

EDIT:

V2:

I created another version making the label change color when summernote is present as it normally would in material design. Also I added some animations to follow up with material motion.


JSFIDDLE VERSION 2


CODE SNIPPET V2:

$(document).ready(function() {
  $(function() {
    $.material.init();
  });

  var mySummernote = $("#Description"),
    labelStatic = $(".label-static");

  mySummernote
    .on("click", function() {
      setTimeout(function() {
        mySummernote.summernote({
          focus: true
        });
        $('.note-toolbar.panel-heading').appendTo('#toolbar');
        labelStatic.addClass("is-focused");
      }, 250);
    });

  $(document).mouseup(function(el) {
    var summernoteContainer = $("#summernote-container");

    if (!summernoteContainer.is(el.target) && summernoteContainer.has(el.target).length === 0) {
      mySummernote.summernote("destroy");
      $('.note-toolbar.panel-heading').remove();
      labelStatic.removeClass("is-focused");
    }
  });
});
.mytoolbar {
  position: relative;
  top: -30px;
  z-index: 9;
}
@-webkit-keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    transform: none
  }
}
@keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    transform: none
  }
}
#summernote-container .note-editor.note-frame.panel.panel-default {
  animation: fadeInDown .8s;
}
@-webkit-keyframes fadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@keyframes fadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
#summernote-container .note-toolbar.panel-heading {
  opacity: 0;
  animation: fadeIn .8s .8s both;
}
<link href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare./ajax/libs/bootstrap-material-design/0.5.9/css/bootstrap-material-design.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare./ajax/libs/summernote/0.8.1/summernote.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/bootstrap-material-design/0.5.9/js/material.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/summernote/0.8.1/summernote.min.js"></script>

<div class="container">
  <div class="form-group label-static is-empty" id="summernote-container">
    <div class="row">
      <div class="col-xs-2">
        <label class="control-label" for="Description">Description</label>
      </div>
      <div class="col-xs-10">
        <div id="toolbar" class="mytoolbar"></div>
      </div>
    </div>
    <input class="form-control" rows="3" id="Description" name="Description">
  </div>
</div>


SOLUTION:

First of all, you need to call your functions when document is ready, using:

$("document").ready(function(){
    //Your JS functions here
});

Then remove onfocus and onblur from content.

Following SoC (separation of concerns), we're going to add this logic in our JS file and we are going to use on() jQuery Method instead.

In this case we have the following logic:

$("#summernoteTrigger").on("click", function() {
    //When the user clicks the input stuff here
    //Separate Toolbar from Summernote and show it next to label
});

When the user clicks the input we are going to initialize Summernote and using the focus option:

$(this).summernote({
    focus: true
});

When Summernote is initialized we want the toolbar to be placed beside the label, so we're going to append it to the container of our choice:

 $('.note-toolbar.panel-heading').appendTo('#toolbar');

Another thing we want to do is destroy Summernote if the user stops focusing it. For this we can't use $('#summernoteTrigger').on('summernote.blur', function() {}); because clicking on the toolbar would trigger this callback. Instead we can use the following method:

  $(document).mouseup(function(el) {
    var summernoteContainer = $("#summernote-container");

    if (!summernoteContainer.is(el.target) && summernoteContainer.has(el.target).length === 0) {
      //Add logic here if you want to save what the user typed
      $("#summernoteTrigger").summernote("destroy");
       $('.note-toolbar.panel-heading').remove();
    }
  });
});

Finally we put everything together and add some style if needed.


JSFIDDLE


CODE SNIPPET:

$(document).ready(function() {
  $(function() {
    $.material.init();
  });

  var mySummernote = $("#Description");

  mySummernote
    .on("click", function() {
      $(this).summernote({
        focus: true
      });
      $('.note-toolbar.panel-heading').appendTo('#toolbar');
    });

  $(document).mouseup(function(el) {
    var summernoteContainer = $("#summernote-container");

    if (!summernoteContainer.is(el.target) && summernoteContainer.has(el.target).length === 0) {
      mySummernote.summernote("destroy");
      $('.note-toolbar.panel-heading').remove();
    }
  });
});
.mytoolbar {
  position: relative;
  top: -30px;
  z-index: 9;
}
<link href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare./ajax/libs/bootstrap-material-design/0.5.9/css/bootstrap-material-design.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare./ajax/libs/summernote/0.8.1/summernote.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/bootstrap-material-design/0.5.9/js/material.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/summernote/0.8.1/summernote.min.js"></script>

<div class="container">
  <div class="form-group label-static is-empty" id="summernote-container">
    <div class="row">
      <div class="col-xs-2">
        <label class="control-label" for="Description">Description</label>
      </div>
      <div class="col-xs-10">
        <div id="toolbar" class="mytoolbar"></div>
      </div>
    </div>
    <input class="form-control" rows="3" id="Description" name="Description">
  </div>
</div>

That's my big problem is seperating the toolbar from the text field itself

Summernote has Air mode which is specifically tailored for this situation.

First of all you should know that the trick is split into two easy parts.

First Part:

Air mode will only work with highlighting text, so you should trigger this highlight upon focus (if you want), or else set the css to display:block!important, and of course you can control its position using css, but pay attention that it has an absolute position.

Second Part

When highlighting any text, this will reset the toolbar css, so this solution here, solves it, but will need to modify the summernote source code.

Here is a fiddle that explains the theory, and I will work on a plete Proof of concept when I have time.

$(document).ready(function() {
      $.material.init();
      $('#description').summernote({
        height: 300,
        tabsize: 2,
        airMode: true
      });
    });

本文标签: javascriptStyling Wysiwyg EditorStack Overflow