Super Beautiful Bootstrap Rich Text editor Summernote_javascript tips

Source: Internet
Author: User
Tags getmessage sendfile string format log4j

Summernote is a simple, flexible, WYSIWYG (WYSIWYG) editor based on JQuery and Bootstrap constructs. Summernote all major operations support shortcut keys, there is a powerful API that provides a large number of customization options for design (wide, high, effective projects, etc.) and functionality. For the primary scripting language or framework (PHP,RUBY,DJANGO,NODEJS), the project provides an integration example.

Bootstrap Summernote, with its official online introduction is "Super Simple WYSIWYG Editor", but in my opinion, and Bootstrap Chinese official online to provide "BOOTSTRAP-WYSIWYG" to be more simple, More beautiful, better use!

Although I have tried to use bootstrap-wysiwyg before, can refer to bootstrap WYSIWYG Rich text data How to save to MySQL, but afterwards Zhuge Liang's experience told me that Summernote is definitely a better rich text editor, Here to its work team DOT 32 a praise!!!!!

After a day of exploration, Summernote have mastered, then for the wider front-end enthusiasts to provide convenience, I will struggle to introduce summernote, super welfare ah.

First, the official API and source download

工欲善其事 its prerequisite, first of all, the source of summernote and corresponding to the official API to tell everyone is the first task!

Official website (demo and API)

GitHub source Download, note download development version

Second, the effect chart

Effect Figure 1

Effect Figure 2

Effect Figure 3

Iii. content of the lecture

The large direction is the following three contents:

Summernote Page Layout (resource introduction, initial parameters)
Summernote from the local Upload image method (front-end Onimageupload method, back-end Springmvc file Save)
Summernote data submission for form forms

page layouts for ①, summernote

<! DOCTYPE html>  

<! The mark of DOCTYPE HTML>HTML5 is necessary, note must not be <! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en" "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> This doctype, otherwise summernote components show strange, the size of the button layout is inconsistent, here is no longer on the map, but pay attention!"
The bootstrap version number is best for v3.3.5

1, Layout div

<div class= "Summernote" name= "description" placeholder= "Please give a detailed description of the project, so that more people understand your" action= "${ctx}/file" >${ Deal.description}</div>

I'm sure you saw the three attributes I added to the div name, placeholder, action, then let's go into the details of the three properties:

Name, the property name of the data model for the outer form form that provides summernote data, is consistent with the Name property of the input label, and is described later when the form is submitted.

placeholder, very straightforward, for the summernote to provide the initial state of the text description, of course, also need post-processing, Div obviously does not support the placeholder attribute.

Action, for image upload to provide back-end receive address, later in the introduction of the picture upload onimageupload will be used again.
In addition ${deal.description} In fact you do not need too much attention, and textarea of the use of the same, is the simple display of the content after the save.

2, Summernote initialization

$ (' div.summernote '). each (function () {
var $this = $ (this);
var placeholder = $this. attr ("placeholder") | | '';
var url = $this. attr ("action") | | '';
$this. Summernote ({
lang: ' Zh-cn ',
placeholder:placeholder,
minheight:300,
dialogsfade:true,// Add fade effect on dialogs
dialogsinbody:true,//dialogs can is placed in body, not in
//summernote.
disabledraganddrop:false,//Default false You can disable drag
//And Drop
});

Using jquery to get the summernote on the page and initialize it, let's go over the use of the list of parameters (not the Onimageupload method for uploading pictures).

Lang, specify the language as Simplified Chinese

PLACEHOLDER, Summernote initializes the displayed content.

MinHeight, the minimum height of 300, note that there is no use of height, there is a reason, here a little explanation, not on the map. When using height, if you upload a picture taller than height, Summernote will not automatically adjust the height, and the previous "effect Figure 3" won the winning red area will not be affixed to the picture, and overflow to summernote outside.

Dialogsfade, increase the dynamic effect of sliding slide of pop-up window on Summernote.
Dialogsinbody, this property is also critical, the default is false, the literal meaning is whether the Summernote pop-up box in the body, when set to False, Dialog's style will inherit its upper-level external (such as the previous form-horizontal) container style, then the display is very awkward, this is no longer the image, then set to true, it will not inherit the attributes of the upper-level outside div, from the body.

Disabledraganddrop, set to False bar, sometimes drag will be a little problem, you can practice.

②, summernote upload image from the local method

1, front-end Onimageupload method

If ask Niang the following words: "Onimageupload method how to write?" "Most of the Niang will find you the following answer:

$ (\ '. summernote\ '). Summernote ({
height:300,
onimageupload:function (Files, editor, weleditable) {
SendFile (files[0],editor,weleditable)
;}}); function SendFile (file, editor, weleditable) {
data = new FormData ();
Data.append ("file", file);
url = "Http://localhost/spichlerz/uploads";
$.ajax ({
data:data,
type: "POST",
Url:url,
cache:false,
contenttype:false,
Processdata:false,
success:function (URL) {
editor.insertimage (weleditable, URL);}}
);
</script>

The above resources come from StackOverflow.

But in fact, summernote-develop version of the summernote already do not support this onimageupload writing, so what is the writing now? Refer to Summernote's official website example.

Onimageupload

Override image Upload Handler (default:base64 dataurl on IMG tag). can upload image to server or AWS s3:more
... Onimageupload callback
$ (' #summernote '). Summernote ({
callbacks: {
onimageupload:function (files) {
//Upload image to server and create Imgnode
... $summernote. Summernote (' Insertnode ', imgnode);
}
}
);
Summernote.image.upload
$ (' #summernote '). On (' Summernote.image.upload ', function (we, files) {
//upload Image to server and create Imgnode
... $summernote. Summernote (' Insertnode ', imgnode);
});

So at this time onimageupload the specific wording? (back end is SPRINGMVC):

 callbacks: {//onimageupload parameter for files,summernote support select more than one picture onimageupload:function (files) {var
$files = $ (files); Each of the file $files is traversed by each method. each (function () {var file = this;//FormData, new Form form package, specific to Baidu, but in fact the usage is very simple, the following var data = new for
Mdata ();
Adding files to file, the backend can get to the parameter named "File" Data.append ("file", file); Ajax upload $.ajax ({data:data, type: "POST", action Cache:false on url:url,//Div, contenttype:false, ProcessData: False,//When successful call method, back-end returns JSON data success:function (response) {//Encapsulated eval method, can baidu var json = yunm.jsoneval (response);//console output return
Back to Data Yunm.debug (JSON);
Encapsulation method, mainly displays error message Yunm.ajaxdone (JSON); 
State OK if (json[yunm.keys.statuscode] = = YUNM.statusCode.ok) {//File NOT NULL if (Json[yunm.keys.result]) {//Get background data saved picture full path
var imageUrl = Json[yunm.keys.result].completesavepath;
INSERT into Summernote $this. Summernote (' Insertimage ', IMAGEURL, function ($image) {//TODO, the following can add a new CSS style to the image object, and so on, here Default});
}},//////Ajax request failed with error:YUNM.ajaxError});
}); }
}

The

annotation is added in detail, where the other associated code is posted together for reference only.

Debug:function (msg) {if (this._set.debug) {if (typeof (console)!= "undefined") console.log (msg); else alert (msg); }, Jsoneval:function (data) {try {if ($.type (data) = ' string ') return eval (' + Data + ')]; else return data;} Cat CH (e) {return {}}}, Ajaxerror:function (XHR, ajaxoptions, Thrownerror) {if (Xhr.responsetext) {$.showerr ("<div&
gt; "+ Xhr.responsetext +" </div> "); else {$.showerr ("<div>http Status:" + Xhr.status + "" + Xhr.statustext + "</div>" + "<div>ajaxoptio NS: "+ ajaxoptions + </div>" + "<div>thrownerror:" + thrownerror + "</div>");}, Ajaxdone:functio N (JSON) {if (json[yunm.keys.statuscode] = = YUNM.statusCode.error) {if (json[yunm.keys.message)) {Yunm.debug (json[yunm
. Keys.message]);
$.showerr (Json[yunm.keys.message]); } else if (json[yunm.keys.statuscode] = = YUNM.statusCode.timeout) {yunm.debug (json[yunm.keys.message)); $.showerr ( Json[yunm.keys.message] | | Yunm.msg ("Sessiontimout"), YUNM. Loadlogin); }
},

2, back-end Springmvc file Save

2.1, for SPRINGMVC to increase the configuration of files

<bean id= "Multipartresolver"
class= "Org.springframework.web.multipart.commons.CommonsMultipartResolver" p :d efaultencoding= "UTF-8" >
<property name= "maxuploadsize" value= "1024000000" ></property>
</bean>
<mvc:annotation-driven conversion-service= "Conversionservice"/>
<bean id= " Conversionservice "
class=" Org.springframework.format.support.FormattingConversionServiceFactoryBean ">
<property name= "Converters" >
<list>
<!--use String to Date converts a date in string format directly to the date type--> <bean class= "When the DAO is converted from JSP to controller
" Com.honzh.common.plugin.StringToDateConverter "/>
<!--add converters--> to the data model for type file
<bean class= "com.honzh.common.plugin.CommonsMultipartFileToString"/>
</list>
</property>
</bean>

Here is not to do too much introduction, can refer to my previous written springmvc of the Context-dispatcher.xml, understand the basic controller

2.2, Filecontroller.java

Package Com.honzh.spring.controller;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import Org.apache.log4j.Logger;
Import org.springframework.beans.factory.annotation.Autowired;
Import Org.springframework.stereotype.Controller;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Com.honzh.common.base.UploadFile;
Import Com.honzh.spring.service.FileService; @Controller @RequestMapping (value = "/file") public class Filecontroller extends Basecontroller {private static Logger lo
Gger = Logger.getlogger (Filecontroller.class);
@Autowired private Fileservice Fileservice; @RequestMapping ("") public void Index (HttpServletRequest request, httpservletresponse response) {logger.debug ("Get upload file
..."); try {uploadfile uploadfiles = fileservice.savefile (request); Renderjsondone (response, uploadfiles);} catch (Exception E
{Logger.error (E.getmessage ()); Logger.error (E.getmessage (), E); Renderjsonerror (response, "File upload Failed");} }

2.3, Fileservice.java

Package com.honzh.spring.service;
Import java.io.IOException;
Import Java.util.Iterator;
Import Java.util.Map;
Import Java.util.Random;
Import Javax.servlet.http.HttpServletRequest;
Import Org.apache.commons.io.FileUtils;
Import Org.apache.log4j.Logger;
Import Org.springframework.stereotype.Service;
Import Org.springframework.web.multipart.MultipartFile;
Import Org.springframework.web.multipart.MultipartHttpServletRequest;
Import Com.honzh.common.Variables;
Import Com.honzh.common.base.UploadFile;
Import Com.honzh.common.util.DateUtil; @Service public class Fileservice {private static Logger Logger = Logger.getlogger (fileservice.class); public UploadFile
SaveFile (HttpServletRequest request) throws IOException {logger.debug ("Get upload file ...");
Request Multiparthttpservletrequest Multipartrequest = (multiparthttpservletrequest) to be converted to a file type request;
Gets the corresponding file object map<string, multipartfile> filemap = Multipartrequest.getfilemap (); iterator<string> Fileiterator = multipartrequest.geTfilenames ();
Gets the relative path (http://localhost:8080/file) String Requesturl = Request.getrequesturl () of the project. toString ();
String Prepath = requesturl.substring (0, Requesturl.indexof (variables.ctx)); while (Fileiterator.hasnext ()) {String Filekey = Fileiterator.next (); logger.debug ("File name:" + filekey);//get corresponding file Multipar
Tfile multipartfile = Filemap.get (Filekey); if (Multipartfile.getsize ()!= 0L) {validateimage (multipartfile);//Call SaveImage method Save UploadFile File = SaveImage (Multipa
Rtfile);
File.setprepath (Prepath);
return file;
} return null; Private UploadFile SaveImage (multipartfile image) throws IOException {String originalfilename = Image.getoriginalfilen
Ame ();
Logger.debug ("The original file name is:" + originalfilename);
String ContentType = Image.getcontenttype ();
String type = contenttype.substring (Contenttype.indexof ("/") + 1);
String fileName = dateutil.getcurrentmillstr () + new Random (). Nextint + "." + type; Encapsulates a simple file object that adds several attributes UploadFile file = new UploadFile (Variables.save_directory, FIlename);
File.setcontenttype (ContentType);
Logger.debug ("File Save path:" + file.getsavedirectory ()); The picture is saved by the Org.apache.commons.io.FileUtils writebytearraytofile Fileutils.writebytearraytofile (File.getfile (),
Image.getbytes ());
return file; } private void Validateimage (Multipartfile image) {}}

2.4, Uploadfile.java

Package com.honzh.common.base;
Import Java.io.File;
Import Com.honzh.common.Variables; public class UploadFile {private string savedirectory; private string fileName; private string contentType; private Strin
G Prepath;
Private String Completesavepath;
Private String Relativesavepath; Public UploadFile (String savedirectory, String filesystemname) {this.savedirectory = savedirectory; this.filename = File
SystemName; public string GetFileName () {return FileName:} public string Getsavedirectory () {return savedirectory.} public Strin G getContentType () {return contentType.} public void setContentType (String contentType) {this.contenttype = ContentType
;
Public String Getprepath () {if (Prepath = = null) {return "";}
return prepath; 
} public void Setprepath (String prepath) {this.prepath = Prepath; Setcompletesavepath (Prepath + getrelativesavepath ()); public string Getcompletesavepath () {return completesavepath.} public void Setcompletesavepath (String completesavepath ) {This. Completesavepath = Completesavepath; public string Getrelativesavepath () {return relativesavepath.} public void Setrelativesavepath (string relativesavepat  h) {This.relativesavepath = relativesavepath} public void Setsavedirectory (String savedirectory) {this.savedirectory =
Savedirectory;  public void Setfilename (String fileName) {this.filename = filename;} public File GetFile () {if (getsavedirectory () = = null | | GetFileName () = = null) {return null;} else {Setrelativesavepath (variables.ctx + "/" + Variables.upload + "/" + Getfilen
Ame ());
return new File (getsavedirectory () + "/" + GetFileName ()); }
}
}

The back-end file Save method is also very simple, understand Java students can understand, then for the back end does not use SPRINGMVC students, you can find ways to find.

After the hard introduction of the first two months, we have a dynamic map to see the effect of it!


③. Summernote data submission for form forms

Here, let's review the form of Summernote, which also contains a normal file's input tag, which means that the form also needs to upload a project cover.

<form class= "Form-horizontal required-validate" action= "#" enctype= "Multipart/form-data" method= "POST" onsubmit= " Return Iframecallback (this, pageajaxdone) ">

First look at the properties of the form:

Enctype: "Multipart/form-data", indicating that the form for the file type is saved

The Iframecallback method, which is described in detail later, is mainly to encapsulate form forms with file uploads.

1, Iframecallback

function Iframecallback (form, callback) {Yunm.debug ("with File upload processing"); var $form = $ (form), $iframe = $ ("#callbackframe"); var
data = $form. Data (' Bootstrapvalidator '); if (data) {if (!data.isvalid ()) {return false;}//Rich Text editor $ ("Div.summernote", $form). each (function () {var $this = $ (
this); if (! $this. Summernote (' IsEmpty ')) {var editor = "<input type= ' hidden ' name= '" "+ $this. attr (" name ") +" ' value= ' "+ $th
Is.summernote (' code ') + "'/>";
$form. Append (editor);
else {$.showerr ("Please fill in Project Details"); if ($iframe. Size () = = 0) {$iframe = $ ("<iframe id= ' callbackframe ' name= ' callbackframe ' src= '" About:blank ' style= ') displ
Ay:none ' ></iframe> '). Appendto ("body");
} if (!form.ajax) {$form. Append (' <input type= "hidden" name= "Ajax" value= "1"/> ");} form.target =" Callbackframe "; _iframeresponse ($iframe [0], callback | |
Yunm.ajaxdone); function _iframeresponse (iframe, callback) {var $iframe = $ (iframe), $document = $ (document); $document. Trigger ("Ajaxst
Art "); $iFrame.bind ("Load", function (event) {$iframe. Unbind ("Load"); $document. Trigger ("Ajaxstop"); if (iframe.src = " javascript: '%3chtml%3e%3c/html%3e '; For//Safari IFRAME.SRC = "javascript: '  

Post all the code for your reference, but here we only talk about the following sections:

Rich Text editor
$ ("Div.summernote", $form). each (function () {
var $this = $ (this);
if (! $this. Summernote (' IsEmpty ')) {
var editor = "<input type= ' hidden ' name= '" "+ $this. attr (" name ") +" ' value= ' "+ $this. Summernote (' code ') + "/>";
$form. Append (editor);
else {
$.showerr ("Please fill in the project Details");
return false;
}
});

After you get to the Summernote object $this through the form, pass! $this. Summernote (' IsEmpty ') to determine whether the user is filled with content on the Rich text editor, the guarantee is not empty, when empty, pop-up message.

$this. Summernote (' code ') obtains the HTML content of the Summernote editor and encapsulates it in the input object, name is the name provided by the Div in the previous text for use by the backend.

The rest of the place is not long explained, the details can be referenced bootstrap WYSIWYG Rich text data How to save to MySQL.

What does it look like to save to the database?

<p></p><p> <br></p><p> Hello, interested to join the silent Wang of the group Ah <br></p>

The page effect is:


Well, well, finally finished, did not expect to write so tired, if you have any fresh things, you can also contact me Ah, welcome your guidance!

About bootstrap Rich Text editor Summernote Small series to introduce to everyone here, hope to help everyone! have different opinions welcome to put forward valuable advice, common learning and progress!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.