资讯专栏INFORMATION COLUMN

summernote编辑器插件使用笔记

printempw / 2704人阅读

摘要:由于需要的编辑器功能比较简单,不需要太多复杂功能,所以选择了一款特别轻量的插件,而且后台操作也很简单。关于图片上传提交按键等回调函数也是在中,详见部分。初始化一个编辑器很简单。

这次项目中需要用到编辑器插件,于是上网查了一下。由于需要的编辑器功能比较简单,不需要太多复杂功能,所以选择了一款特别轻量的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部分。

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

$(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")
@ResponseBody
public 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 = "
" + "" + "" + "
" + "
" + "" + "" + "
" + "
" + "" + "" + "
" + (!options.disableLinkTarget ? "
" + "" + "
" : "" ); var footer = ""; } }

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

"
" + "" + "" + "
" +

那么,我们需要在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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79441.html

相关文章

  • summernote(富文本辑器)将附件与图片上传到自己的服务器(vue项目)

    摘要:将创建好的对象,再插入到编辑器中注意这里不用方法因为他会额外的标签具体查看,另外当选取本地文件的时候,此时的富文本编辑器会失去焦点,插入新的节点的时候,总是从起始点开始插入,而非从当前光标的位置进行插入。 1.上传图片至自己的服务器(这个官方都有例子,重点介绍附件上传)图片上传官方网址 // onChange callback $(#summernote).summernote({ ...

    wqj97 评论0 收藏0
  • summernote(富文本辑器)将附件与图片上传到自己的服务器(vue项目)

    摘要:将创建好的对象,再插入到编辑器中注意这里不用方法因为他会额外的标签具体查看,另外当选取本地文件的时候,此时的富文本编辑器会失去焦点,插入新的节点的时候,总是从起始点开始插入,而非从当前光标的位置进行插入。 1.上传图片至自己的服务器(这个官方都有例子,重点介绍附件上传)图片上传官方网址 // onChange callback $(#summernote).summernote({ ...

    xiaoxiaozi 评论0 收藏0
  • 前端常用插件、工具类库汇总(下)

    摘要:上一篇前端常用插件工具类库汇总上内容摘要动画库滚动库轮播图滚屏弹出框消息通知下拉框级联选择器颜色选择器时间日期处理表单验证分页插件本篇延续上一篇的内容继续给大家带来一系列关于前端插件工具类的内容。 showImg(https://segmentfault.com/img/bVbjsMh?w=900&h=383); 前言 对本文感兴趣可以先加个收藏,也可以转发分享给身边的小伙伴,以后遇到...

    ideaa 评论0 收藏0
  • summernote.js实际运用中遇到的上传图片大小控制及bootstrap模态框嵌套关闭这两个问

    摘要:需求控制编辑框上传的图片不超过。从文件中找到如下图代码位置,选取需要上传的图片,获取图片的大小,将其当做新增参数,给标签新增属性。我的解决方法就是将在中加载出来的模态框中,关闭按钮的属性替换成代码的事件,用来隐藏模态框,如下图所示。 这里先看一下summernote.js模样,如下图,可以添加图片、视频、链接等。showImg(https://segmentfault.com/img/...

    madthumb 评论0 收藏0
  • 代码小记:tinymce使用心得

    摘要:简单使用直接使用可以使用这种方式,方便快捷。但是满足不了大部分人,你们需要的是自定义使用手册传送门速查传送门手脚架提供给看完文档后无从下手的伙伴,这配置够用了。本地化语言包下载传送门语言包下载后放到目录下方可使用。 序 公司后台的编辑器从我刚接触的bootstrap-wysihtml5更新到summernote,后来发现summernote也是巨坑无比(坑:粘贴没有过滤、插件结构最近又...

    GT 评论0 收藏0

发表评论

0条评论

printempw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<