summernote编辑器插件使用

来源:互联网 发布:coc女王升级数据2017 编辑:程序博客网 时间:2024/06/03 18:35

这次项目中需要用到编辑器插件,于是上网查了一下。由于需要的编辑器功能比较简单,不需要太多复杂功能,所以选择了一款特别轻量的summernote插件,而且后台操作也很简单。
官网:http://summernote.org/
github地址:https://github.com/summernote...

先来看一下官网的截图


麻雀虽小五脏俱全。完全可以满足编辑器的需要。

按照官网链接下载下来的是


我们需要使用的是在dist文件夹内


其中font主要是编辑器内的图标显示,lang是各种语言,css则是样式。我们主要来看一下summernote.js。

summernote.js

定义

 $.fn.extend({    summernote: function () {      var type = $.type(list.head(arguments));      var isExternalAPICalled = type === 'string';      var hasInitOptions = type === 'object';      var options = hasInitOptions ? list.head(arguments) : {};      options = $.extend({}, $.summernote.options, options);      options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]);      this.each(function (idx, note) {        var $note = $(note);        if (!$note.data('summernote')) {          var context = new Context($note, options);          $note.data('summernote', context);          $note.data('summernote').triggerEvent('init', context.layoutInfo);        }      });      var $note = this.first();      if ($note.length) {        var context = $note.data('summernote');        if (isExternalAPICalled) {          return context.invoke.apply(context, list.from(arguments));        } else if (options.focus) {          context.invoke('editor.focus');        }      }      return this;    }  });

这就是初始化summernote时执行的函数。

$.extend(object) 可以理解为JQuery 添加一个静态方法。$.fn.extend(object) 可以理解为JQuery实例添加一个方法。

默认的options如下

options: {  modules: {    'editor': Editor,    'clipboard': Clipboard,    'dropzone': Dropzone,    'codeview': Codeview,    'statusbar': Statusbar,    'fullscreen': Fullscreen,    'handle': Handle,    // FIXME: HintPopover must be front of autolink    //  - Script error about range when Enter key is pressed on hint popover    'hintPopover': HintPopover,    'autoLink': AutoLink,    'autoSync': AutoSync,    'placeholder': Placeholder,    'buttons': Buttons,    'toolbar': Toolbar,    'linkDialog': LinkDialog,    'linkPopover': LinkPopover,    'imageDialog': ImageDialog,    'imagePopover': ImagePopover,    'videoDialog': VideoDialog,    'helpDialog': HelpDialog,    'airPopover': AirPopover  },  buttons: {},    lang: 'zh-CN',  // toolbar工具栏默认  toolbar: [    ['style', ['style']],    ['font', ['bold', 'underline', 'clear']],    ['fontname', ['fontname']],    ['color', ['color']],    ['para', ['ul', 'ol', 'paragraph']],    ['table', ['table']],    ['insert', ['link', 'picture', 'video']],    ['view', ['fullscreen', 'codeview', 'help']]  ],  // popover  popover: {    image: [      ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],      ['float', ['floatLeft', 'floatRight', 'floatNone']],      ['remove', ['removeMedia']]    ],    link: [      ['link', ['linkDialogShow', 'unlink']]    ],    air: [      ['color', ['color']],      ['font', ['bold', 'underline', 'clear']],      ['para', ['ul', 'paragraph']],      ['table', ['table']],      ['insert', ['link', 'picture']]    ]  },  // air mode: inline editor  airMode: false,  width: null,  height: null,  focus: false,  tabSize: 4,  styleWithSpan: false,  shortcuts: true,  textareaAutoSync: true,  direction: null,  styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],  fontNames: [    'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',    'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',    'Tahoma', 'Times New Roman', 'Verdana'  ],  fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],  // pallete colors(n x n)  colors: [    ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],    ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],    ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],    ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],    ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],    ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],    ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],    ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']  ],  lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],  tableClassName: 'table table-bordered',  insertTableMaxSize: {    col: 10,    row: 10  },  dialogsInBody: false,  dialogsFade: false,  maximumImageFileSize: null,  callbacks: {    onInit: null,//初始化回调函数    onFocus: null,//聚集    onBlur: null,//失去焦点    onEnter: null,//回车键的回调函数    onKeyup: null,    onKeydown: null,    onSubmit: null,//提交时回调函数    onImageUpload: null,//这就是上传图片的回调函数    onImageUploadError: null//上传图片出错  },  codemirror: {    mode: 'text/html',    htmlMode: true,    lineNumbers: true  },  keyMap: {    pc: {      'ENTER': 'insertParagraph',      'CTRL+Z': 'undo',      'CTRL+Y': 'redo',      'TAB': 'tab',      'SHIFT+TAB': 'untab',      'CTRL+B': 'bold',      'CTRL+I': 'italic',      'CTRL+U': 'underline',      'CTRL+SHIFT+S': 'strikethrough',      'CTRL+BACKSLASH': 'removeFormat',      'CTRL+SHIFT+L': 'justifyLeft',      'CTRL+SHIFT+E': 'justifyCenter',      'CTRL+SHIFT+R': 'justifyRight',      'CTRL+SHIFT+J': 'justifyFull',      'CTRL+SHIFT+NUM7': 'insertUnorderedList',      'CTRL+SHIFT+NUM8': 'insertOrderedList',      'CTRL+LEFTBRACKET': 'outdent',      'CTRL+RIGHTBRACKET': 'indent',      'CTRL+NUM0': 'formatPara',      'CTRL+NUM1': 'formatH1',      'CTRL+NUM2': 'formatH2',      'CTRL+NUM3': 'formatH3',      'CTRL+NUM4': 'formatH4',      'CTRL+NUM5': 'formatH5',      'CTRL+NUM6': 'formatH6',      'CTRL+ENTER': 'insertHorizontalRule',      'CTRL+K': 'linkDialog.show'    },    mac: {      'ENTER': 'insertParagraph',      'CMD+Z': 'undo',      'CMD+SHIFT+Z': 'redo',      'TAB': 'tab',      'SHIFT+TAB': 'untab',      'CMD+B': 'bold',      'CMD+I': 'italic',      'CMD+U': 'underline',      'CMD+SHIFT+S': 'strikethrough',      'CMD+BACKSLASH': 'removeFormat',      'CMD+SHIFT+L': 'justifyLeft',      'CMD+SHIFT+E': 'justifyCenter',      'CMD+SHIFT+R': 'justifyRight',      'CMD+SHIFT+J': 'justifyFull',      'CMD+SHIFT+NUM7': 'insertUnorderedList',      'CMD+SHIFT+NUM8': 'insertOrderedList',      'CMD+LEFTBRACKET': 'outdent',      'CMD+RIGHTBRACKET': 'indent',      'CMD+NUM0': 'formatPara',      'CMD+NUM1': 'formatH1',      'CMD+NUM2': 'formatH2',      'CMD+NUM3': 'formatH3',      'CMD+NUM4': 'formatH4',      'CMD+NUM5': 'formatH5',      'CMD+NUM6': 'formatH6',      'CMD+ENTER': 'insertHorizontalRule',      'CMD+K': 'linkDialog.show'    }  },  icons: {    'align': 'icon-align',    'alignCenter': 'icon-align-center',    'alignJustify': 'icon-align-justify',    'alignLeft': 'icon-align-left',    'alignRight': 'icon-align-right',    'indent': 'icon-indent-right',    'outdent': 'icon-indent-left',    'arrowsAlt': 'icon-resize-full',    'bold': 'icon-bold',    'caret': 'icon-caret-down',    'circle': 'icon-circle',    'close': 'icon-close',    'code': 'icon-code',    'eraser': 'icon-eraser',    'font': 'icon-font',    'frame': 'icon-frame',    'italic': 'icon-italic',    'link': 'icon-link',    'unlink': 'icon-chain-broken',    'magic': 'icon-magic',    'menuCheck': 'icon-check',    'minus': 'icon-minus',    'orderedlist': 'icon-list-ol',    'pencil': 'icon-pencil',    'picture': 'icon-picture',    'question': 'icon-question',    'redo': 'icon-redo',    'square': 'icon-square',    'strikethrough': 'icon-strikethrough',    'subscript': 'icon-subscript',    'superscript': 'icon-superscript',    'table': 'icon-table',    'textHeight': 'icon-text-height',    'trash': 'icon-trash',    'underline': 'icon-underline',    'undo': 'icon-undo',    'unorderedlist': 'icon-list-ul',    'video': 'icon-facetime-video'  }}

关于编辑器需要的工具栏toolbar具体属性可查看官网summernote-toolbar属性

更改工具栏图标

由于项目中我是直接使用fontawesome,所以我没有再引入summernote.font,直接在options中的icons中修改。但比较麻烦,不知道有什么更好的方法,求指导。

关于图片上传、提交、按键等回调函数也是在options中,详见callbacks部分。

初始化一个编辑器很简单。只需要定义

<div class="summernote" id="myid"></div> $(function () {    $('.summernote').summernote();    //或者    $('#myid').summernote();});

设置placeholder:

$('.summernote').summernote({        placeholder:'请输入文章内容',        ...    });

设置toolbar,

$('.summernote').summernote({        toolbar:[            ['style',['bold','italic','underline','clear']],            ['fontsize',['fontsize']],            ['para',['ul','ol','paragraph']],            ['color',['color']]        ],        ...    });

更改图片上传的方式

需要提及的是,summernote默认的图片上传方式为base64方式。若需要修改,看以下代码。【一定要注意:onImageUpload方法修改时要放在callbacks内配置,否则没用】

$('#myid').summernote({    callbacks:{        onImageUpload: function(files, editor, $editable) {            UploadFiles(files,insertImg);        }    },    ...});function insertImg(){    for(i in imageUrl){        $('.summernote').summernote('editor.insertImage',imageUrl[i]);    }}function UploadFiles(files,func){//这里files是因为我设置了可上传多张图片,所以需要依次添加到formData中    var formData = new FormData();    for(f in files){        formData.append("file", files[f]);    }    $.ajax({        data: formData,        type: "POST",        url: "/uploadMultipleFile",        cache: false,        contentType: false,        processData: false,        success: function(imageUrl) {            func(imageUrl);             },        error: function() {            console.log("uploadError");        }    })}

我们项目的后台是用spring+springMVC实现的。后台图片上传代码如下:

@RequestMapping(value = "/uploadMultipleFile", method = RequestMethod.POST, produces = "application/json;charset=utf8")@ResponseBodypublic String uploadMultipleFileHandler(@RequestParam("file") MultipartFile[] files, HttpServletRequest request) throws IOException {    return     UploadUtil.uploadImage(request.getServletContext().getRealPath("/"), files);}//UploadUtil.java中uploadImage方法如下 public static String uploadImage(String serverPath, MultipartFile[] files) {    try {        String uploadPath = serverPath + getImageRelativePath();        String images = "{}";        //如果不存在目录,创建一个目录        isDirectory(uploadPath);        if (files != null && files.length > 0) {            for (int i = 0; i < files.length; i++) {                MultipartFile file = files[i];                //save file                if (!file.isEmpty()) {                    String savePath = getImageRelativePath() + file.getOriginalFilename();//数据库保存的图片路径                    images = JSONUtil.addProperty(images, String.valueOf(i), savePath);                    save(file, uploadPath);                }            }        }        return images;    } catch (Exception e) {        e.printStackTrace();        return "{}";    }}

设置编辑器中的值:

$('#myid').summernote('code',content);

需要注意的是,content是html代码,可能存在引号嵌套的问题导致报错,记得将引号进行转义。
后台处理-java代码:

content = content.replaceAll("'","\\\\'");content = content.replaceAll("\"", "\\\\\"");

获取编辑器中的值:

var content = $('.summernote').summernote('code');

上传附件

这次项目需要使用附件,但发现summernote貌似没有附件功能,于是自己研究了一下代码,根据项目的需求,在link链接部分进行了修改。
效果如下:


首先,我们先看link按钮所绑定的事件。

context.memo('button.link', function () {        return ui.button({          contents: ui.icon(options.icons.link),          tooltip: lang.link.link,          click: context.createInvokeHandler('linkDialog.show')        }).render();      });

由上面的代码可以发现click事件为:linkDialog.show,那么我们再来看一下linkDialog

var LinkDialog = function (context) {    ...    this.initialize = function () {//初始化        ...        var body = '<div class="form-group">' +               '<label>' + lang.link.textToDisplay + '</label>' +               '<input class="note-link-text form-control" type="text" />' +             '</div>' +              '<div class="form-group">' +              '<label>' + lang.link.attachment + '</label>' +              '<input class="note-link-attachment form-control" type="file" />' +              '</div>' +             '<div class="form-group">' +               '<label>' + lang.link.url + '</label>' +               '<input class="note-link-url form-control" type="text" value="http://" />' +             '</div>' +             (!options.disableLinkTarget ?               '<div class="checkbox">' +                 '<label>' + '<input type="checkbox" checked> ' + lang.link.openInNewWindow + '</label>' +               '</div>' : ''             );        var footer = '<button href="#" class="btn btn-primary note-link-btn disabled" disabled>' + lang.link.insert + '</button>';          }}

可以看到,点击链接按钮出现的弹框样式就在LinkDialoginitialize方法中的body,所以我在中间添加了一个input上传附件的部分。

'<div class="form-group">' +'<label>' + lang.link.attachment + '</label>' +'<input class="note-link-attachment form-control" type="file" />' +'</div>' +

那么,我们需要在lang.link属性中,新增一个attachment附件属性。


除此之外,在中文的转换部分summernote-zh-CN.min.js中,添加linkattachment: '添加附件'

好了,那么我们接下来需要处理的问题是上传文件后的处理。

this.showLinkDialog = function (linkInfo) {    return $.Deferred(function (deferred) {        ...        //上传文件的输入框        $linkAttachment = self.$dialog.find('.note-link-attachment'),                ui.onDialogShown(self.$dialog, function () {            ...            //对于输入框的事件绑定            $linkAttachment.on('change', function() {                UploadFiles($linkAttachment.val(),function(url){                    $linkUrl.val(url);//将上传后的URL赋值到linkUrl的输入框中                });            });        }    }}

UploadFiles与上述修改上传图片的形式一样。

如果这篇文章对您有帮助,欢迎点赞。如果有疏漏,欢迎指正。
本文地址:http://lsxj615.com/2016/08/10...

原创粉丝点击