基于MdEditor魔改的markdown编辑器,拓展了图片上传功能

背景

MdEditor是一款非常棒的编辑器,但是在上传图片方面有点美中不足,缺少了本地上传图片到云服务器的功能,如果要日常使用的话还是需要二次开发的,经过一番魔改后可以支持本地图片上传了,本来打算直接引入到项目中的,考虑到编辑器实在太大了,所以就使用了iframe的方式引入,不多BB直接上图。


1.jpg
2.jpg
3.jpg

4.jpg

基于Markdown修改传送门:http://www.mdeditor.com/
拓展后项目源码传送门:https://github.com/LiveJie/simple-markdown

正常使用的话还是需要在editor项目中的html修改一些配置

  
    $(function() {
        window.editor = editormd("min-editor", {
            width  : "100%",
            height : "600px",
            emoji: true,
            updateBefore: updateBefore, //拓展上传文件方法
            theme        : (localStorage.theme) ? localStorage.theme : "dark",
            previewTheme : (localStorage.previewTheme) ? localStorage.previewTheme : "default", 
            editorTheme  : (localStorage.editorTheme) ? localStorage.editorTheme : "pastel-on-dark", 
            path   : "./lib/"
        });
        // 图片上传方法
        function updateBefore(file, callBack) {
            const formData = new FormData()
            formData.append('file', file)
            formData.append('fileName', file.name)
            ajax('post', location.origin+'/api/updateImg', formData, callBack)
        }

        // 简单ajax封装
        function ajax(type, url, data, callBack) {
            var xhr = null;
            if(window.XMLHttpRequest){
                xhr = new XMLHttpRequest();
            } else {
                xhr = new ActiveXObject('Microsoft.XMLHTTP')
            }
            xhr.open(type, url, true);
            xhr.setRequestHeader('token', window._blog_token);
            data && (xhr.send(data));
            // xhr.responseType = "blob";
            xhr.onload = function (e) {
                if (this.status == 200) {
                    let res = JSON.parse(xhr.response)
                    let params = {
                        url: res.data,
                        alt: data.get("fileName"),
                        link: res.data
                    }
                    callBack && callBack(params)
                }
            }
        }
        // 添加监听回应事件
        window.addEventListener('message', function (e) {
            let data = e.data
            //完成事件后响应
            let str = "window_" + data.type
            if(typeof data === 'object') {
                switch(data.type) {
                    case "setToken":
                        window._blog_token = data.blog_token
                        window.parent.postMessage(str,"*");
                        break;
                    case "setValue":
                        window.editor.setValue(data.value)
                        window.parent.postMessage(str,"*");
                    break;
                }
            }else {
                let params = {}
                switch(data) {
                    case "getHTML":
                        params = {
                            type: 'setHtml',
                            data: window.editor.getHTML()
                        }
                        window.parent.postMessage(params,"*");
                    break;
                    case "getValue":
                        params = {
                            type: 'setValue',
                            data: window.editor.getValue()
                        }
                        window.parent.postMessage(params,"*");
                    break;
                }
            }
        });
    });

上面是本人自己用到的图片上传方法使用的时候需要相应的修改,然后需要注意的是callBack方法三个参数需要存在不然可能会报错,也可以再次魔改源码,
下面说下编辑器内嵌的相应事件内嵌的父项目的首页index.html

// 设置iframe需要的token 个人七牛云需要 不需要的不用传
      window._setIframeMessage = function(json) {
        window["_"+json.type] = false
        document.getElementsByTagName('iframe')[0].contentWindow.postMessage(json,"*");
      }

      // 获取编辑器HTML
      window._getEditorHTML = function() {
        document.getElementsByTagName('iframe')[0].contentWindow.postMessage("getHTML","*");
      }

      // 获取编辑器VALUE
      window._getEditorValue = function() {
        document.getElementsByTagName('iframe')[0].contentWindow.postMessage("getValue","*");
      }
      // 捕获反向传播事件
      window.addEventListener('message', function (e) {
        let data = e.data
        if(typeof data === 'object') {
            switch(data.type) {
                case "setHtml":
                    window._editorHtml = data.data
                break;
                case "setValue":
                    window._editorValue = data.data
                break;
            }
          }else {
              switch(data) {
                  case "window_setValue":
                      window._setValue = true
                  break;
                  case "window_setToken":
                      window._setToken = true
                  break;
              }

        }
      })

接着是父项目的具体内嵌页面, 要根据具体情况来调用方法

    mounted () {
        setTimeout(() => {
            let json = {
                type: "setToken",
                blog_token: localStorage.blog_token
            }
            this.getEditorData(json)
        }, 3000)
    },
methods: {
          // 获取获取通讯数据
        getEditorData(json) {
            if (window["_" + json.type]) {
                return
            }
            window._setIframeMessage(json)
            setTimeout(() => {
                this.getEditorData(json)
            }, 100)
        },
}

魔改编辑器的核心拓展文件update-img.js

/**
 * @description editor图片拓展上传插件
 * @author jie
 * @export
 * @param {*} 
 * @returns 
 */

;
(function () {
    var factory = function () {
        let _this = this
        this.Message = null;
        this.fileList = [];
        let imgWrapperDom = document.getElementById("extend-img-dialog-wrapper")
        // 插件初始化
        this.init = function () {
            this.Message = new Message()
            let updateDom = document.createElement("div")
            updateDom.setAttribute("id", "update-wrapper")
            updateDom.className = "update-wrapper"
            updateDom.innerHTML = `
            
Click or drag file to this area to upload
Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files
确认
取消
`; imgWrapperDom.appendChild(updateDom); //监听input上传图片 let fileDom = document.getElementById('input-file'); fileDom.onchange = function(e) { e.preventDefault(); let fileList = e.target.files if(fileList.length > 5) { _this.Message.error("图片最多只能选择5张!") }else { for(let item of fileList) { if(!item.type.match("image")) { _this.Message.error("请上传正确格式的图片!") return false } let sign = new Date().getTime() item.sign = sign _this.fileList.push(item) var read = new FileReader(); read.readAsDataURL(item); read.onload = function (e) { addFileList(this.result, item.name, sign) } } } } //图片拖拽上传 let box = document.getElementById('update-wrapper'); box.ondragover = function (e){ e.preventDefault(); } // 拖拽图片 box.ondrop = function (e){ e.preventDefault(); var files = e.dataTransfer.files;//获取到第一个上传的文件对象 for(let file of files) { if(!file.type.match("image")) { _this.Message.error("请上传正确格式的图片!") return false } _this.fileList.push(file) var fr=new FileReader();//实例FileReader对象 fr.readAsDataURL(file);//把上传的文件对象转换成url fr.onload=function (e){ addFileList(this.result, file.name) } } } }() function Message() { this.success = function(msg = "", duration = 3) { let className = "message active success" this.showThis(msg, duration, className) } this.wraning = function(msg = "", duration = 3) { let className = "message active wraning" this.showThis(msg, duration, className) } this.error = function(msg = "", duration = 3) { let className = "message active error" this.showThis(msg, duration, className) } this.showThis = function(msg, duration, className) { if(!msg) { return Error("msg is null") } let divDom = document.createElement("div") divDom.innerText = msg divDom.className = "message"; imgWrapperDom.appendChild(divDom) setTimeout(function(){ divDom.className = className || "message" },50) setTimeout(function(){ imgWrapperDom.removeChild(divDom) }, duration * 1000) } } this.getFileList = function () { return this.fileList } this.hide = function () { this.reset(); imgWrapperDom.style.display = 'none'; } this.confirm = function () { if(!window._updateBefore) { _this.Message.error("updateBefore function is not setting!") return } if(!this.fileList.length) { _this.Message.error("上传图片不能为空!") } for(let item of this.fileList) { window._updateBefore(item, function(params) { dialog.setFileUrl(params) }) } this.reset() imgWrapperDom.style.display = 'none'; } this.reset = function() { this.fileList = []; let fileListDom = document.getElementsByClassName("file-list-wrapper")[0] fileListDom.innerHTML = ''; } this.show = function () { this.fileList = []; imgWrapperDom.style.display = 'block'; } //加载进度条 this.speedProgress = function (e) { const lastLinearDom = e.children[e.children.length - 1] let w = ~~lastLinearDom.style.width.replace("%", "") if(w >= 100) { lastLinearDom.style.width = ''; }else { let randomNum = Math.floor(Math.random()*10) if((w + randomNum) >= 100) { lastLinearDom.style.width = ''; }else { lastLinearDom.style.width = w + randomNum + '%'; setTimeout(function(){ speedProgress(e) },100) } } } //添加图片文件 this.addFileList = function(url, name, sign) { let fileListDom = document.getElementsByClassName("file-list-wrapper")[0] if(fileListDom.children.length >= 5) { this.Message.error("图片最多只能选择5张!") return } let html = `
${name}
` let divDom = document.createElement("div") divDom.className = "list" divDom.innerHTML = html; fileListDom.appendChild(divDom) } //点击删除元素 this.deleteDom = function(e) { e.parentNode.remove(e) _this.fileList.forEach(function(item, index) { if(item.sign == e.attributes[1].value) { _this.fileList.splice(index) return; } }) console.log(_this.fileList) } // 模拟点击上上传图片 this.selectFile = function() { var fileDom = document.getElementById('input-file'); fileDom.click() } }; if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { module.exports = factory; } else if ((typeof define === "function")) { if(define.amd) { define(null, function() { factory() }); }else { define(function() { factory(); }); } } else { factory(); } })();

到这里就介绍的差不多了,希望可以帮助到有需要的人

你可能感兴趣的:(基于MdEditor魔改的markdown编辑器,拓展了图片上传功能)