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.
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.
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.
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>
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
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With