Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling Wysiwyg Editor

Tags:

javascript

css

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.

like image 490
user70192 Avatar asked Aug 02 '16 16:08

user70192


People also ask

What is WYSIWYG style?

In computing, WYSIWYG (/ˈwɪziwɪɡ/ WIZ-ee-wig), an acronym for What You See Is What You Get, is a system in which editing software allows content to be edited in a form that resembles its appearance when printed or displayed as a finished product, such as a printed document, web page, or slide presentation.

What is WYSIWYG editor example?

Microsoft Word is a common example that helps to define a WYSIWYG editor. You have a blank page with some formatting tools that allow you to add and format words, tables, images and so forth.


2 Answers

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.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-material-design/0.5.9/css/bootstrap-material-design.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.1/summernote.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-material-design/0.5.9/js/material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/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.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-material-design/0.5.9/css/bootstrap-material-design.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.1/summernote.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-material-design/0.5.9/js/material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/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>
like image 119
Ricky Avatar answered Oct 27 '22 23:10

Ricky


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 complete Proof of concept when I have time.

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

enter image description here enter image description here

like image 39
ProllyGeek Avatar answered Oct 27 '22 21:10

ProllyGeek