Jodit是国外一款开源的WYSIWYG(What You See Is What You Get, 所见即所得)富文本编辑器,用纯TypeScript写成,功能齐全,风格简约,支持定制。
这是官网地址:https://xdsoft.net/jodit/
本文使用的版本为Jodit-3.5.1,后端接口用php编写javascript
下载源码包,解压php
<link rel="stylesheet" href="build/jodit.css"> <script src="build/jodit.js"></script> <div id="editor"></div> <script> var editor = new Jodit('#editor'); editor.value = '<p>start</p>'; </script>
大部分设置能够在官网的Playground页面下进行交互式定制
经过editor.value能够获取或设置编辑器的内容css
typescript源文件中的默认设置html
Config.prototype.uploader = { url: '', //在html中插入base64编码后的图片,这样会致使html文本大小过大,且可读性下降,通常不用,而是选择设置url将图片上传到服务器上,再在html中插入相应的<img>图片 insertImageAsBase64URI: false, //这里的图片类型好像并无什么用,既不会过滤也不会弹错误框 imagesExtensions: ['jpg', 'png', 'jpeg', 'gif'], //添加请求头 headers: null, //不清楚干啥的,好像没什么用 data: null, //上传文件的参数名 filesVariableName(i: number): string { return `files[${i}]`; }, //不清楚,查了下是 跨域请求是否提供凭据信息(cookie、HTTP认证及客户端SSL证实等) withCredentials: false, //不清楚干啥的,好像没什么用,请求体会有个这个参数,不过是空的 pathVariableName: 'path', format: 'json', method: 'POST', //添加请求体参数 prepareData(this: Uploader, formData: FormData) { return formData; }, //判断是否上传成功 isSuccess(this: Uploader, resp: IUploaderAnswer): boolean { return resp.success; }, //获取返回值信息 getMessage(this: Uploader, resp: IUploaderAnswer) { return resp.data.messages !== undefined && isArray(resp.data.messages) ? resp.data.messages.join(' ') : ''; }, //处理返回值 process(this: Uploader, resp: IUploaderAnswer): IUploaderData { return resp.data; }, //弹出错误消息窗 error(this: Uploader, e: Error) { this.j.e.fire('errorMessage', e.message, 'error', 4000); }, //上传成功时将相应的<img>图片插入html中 defaultHandlerSuccess(this: Uploader, resp: IUploaderData) { const j = this.j || this; if (!isJoditObject(j)) { return; } if (resp.files && resp.files.length) { resp.files.forEach((filename, index: number) => { const [tagName, attr]: string[] = resp.isImages && resp.isImages[index] ? ['img', 'src'] : ['a', 'href']; const elm = j.createInside.element(tagName); elm.setAttribute(attr, resp.baseurl + filename); if (tagName === 'a') { elm.textContent = resp.baseurl + filename; } if (tagName === 'img') { j.s.insertImage( elm as HTMLImageElement, null, j.o.imageDefaultWidth ); } else { j.s.insertNode(elm); } }); } }, //弹出错误消息窗 defaultHandlerError(this: Uploader, e: Error) { this.j.e.fire('errorMessage', e.message); }, //设置请求头中的Content-Type contentType(this: Uploader, requestData: any) { return (this.j.ow as any).FormData !== undefined && typeof requestData !== 'string' ? false : 'application/x-www-form-urlencoded; charset=UTF-8'; } } as IUploaderOptions<Uploader>;
以上几个方法的调用链大概是这样的:
先是prepareData预处理,而后将请求发送给url接口,接口返回json数据,这时先isSuccess判断是否上传成功;
若是上传成功了,调用process处理返回值,接着defaultHandlerSuccess用处理完的返回值向html文本中插入图片;
若是上传失败了,error调用getMessage获取返回值中的错误信息,而后弹出错误消息窗。java
下面开始自定义设置
这里先放一下个人接口的返回值,方便理解代码
上传成功的:typescript
{ "error": false, "msgs": [], "imgs": [ { "url": "Penguins.jpg", "width": 200, "height": 150 }, { "url": "Desert.jpg", "width": 200, "height": 150 } ] }
上传失败的:json
{ "error": true, "msgs": [ "test.pdf: 文件类型不支持", "test.txt.plain: 文件类型不支持" ], "imgs": [] }
而后是uploader的设置:后端
uploader: { url: 'http://localhost/jodit/upload.php', //添加请求头,使用方法: //headers: {"key": "value"} headers: null, data: null, //上传文件的参数名,该方法参数为整数(上传的第几个文件),以支持多份文件的上传,返回值为string filesVariableName: function(i){ return "imgs["+i+"]" }, withCredentials: false, pathVariableName: "path", format: "json", method: "POST", //添加请求体参数,该方法参数为FormData prepareData: function(formData){ //能够在控制台打印出来,能看到支持的方法append, delete... //console.log(formData); formData.append('id', 1) }, //判断是否上传成功,该方法参数为url接口的返回值,返回值为bool isSuccess: function (resp) { return !resp.error; }, //获取返回值信息,该方法参数为url接口的返回值,返回值为string getMessage: function (resp) { return resp.msgs.join('\n'); }, //处理返回值,该方法参数为url接口的返回值,返回值为json //也能够不处理直接返回,或者过滤一下:return {error: resp.error, msgs: resp.msgs, imgs: resp.imgs} process: function (resp) { return resp; }, //上传成功时将相应的<img>图片插入html中,该方法参数为process的返回值 defaultHandlerSuccess: function (resp) { for(var i=0; i<resp.imgs.length; i++) { //insertImage(url: string | HTMLImageElement, styles: [object Object], defaultWidth: [object Object]): void this.s.insertImage(resp.imgs[i]['url'], {width: resp.imgs[i]['width'], height: resp.imgs[i]['height']}); } } }
jodit.html跨域
<!DOCTYPE html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="./jodit-3.5.1/build/jodit.css"> <script src="./jodit-3.5.1/build/jodit.js"></script> <title>Jodit</title> </head> <body> <div id="editor"></div> <script> var editor = new Jodit('#editor', { language: 'zh_cn', //设置错误消息弹窗的显示时间(ms) showMessageErrorTime: 6000, uploader: { url: 'http://localhost/jodit/upload.php', headers: null, data: null, filesVariableName: function(i){ return "imgs["+i+"]" }, withCredentials: false, pathVariableName: "path", format: "json", method: "POST", prepareData: function(formData){ formData.append('id', 1) }, isSuccess: function (resp) { return !resp.error; }, getMessage: function (resp) { return resp.msgs.join('\n'); } process: function (resp) { return resp; }, defaultHandlerSuccess: function (resp) { for(var i=0; i<resp.imgs.length; i++) { this.s.insertImage(resp.imgs[i]['url'], {width: resp.imgs[i]['width'], height: resp.imgs[i]['height']}); } } } }); </script> </body> </html>
upload.php服务器
<?php $ALLOW_TYPE = [ 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/gif' ]; $ALLOW_SIZE = 3 * 1024 * 1024; $error = false; $msgs = array(); $imgs = array(); foreach($_FILES['imgs']['name'] as $i=>$img){ if($_FILES['imgs']['error'][$i] > 0){ $error = true; $msgs[] = $img.': '.$_FILES['imgs']['error'][$i]; continue; } if(!in_array($_FILES['imgs']['type'][$i], $ALLOW_TYPE)){ $error = true; $msgs[] = $img.": 文件类型不支持"; continue; } if($_FILES['imgs']['size'][$i] > $ALLOW_SIZE){ $error = true; $msgs[] = $img.": 图片大小超过3M"; continue; } } if(!$error){ foreach($_FILES['imgs']['name'] as $i=>$img){ move_uploaded_file($_FILES['imgs']['tmp_name'][$i], $img); $imgs[] = [ 'url' => $img, 'width' => 200, 'height' => 150 ]; } } die(json_encode([ 'error' => $error, 'msgs' => array_reverse($msgs), 'imgs' => array_reverse($imgs) ]));
本身作后端的,对js不是很熟,若有错误欢迎指正,也欢迎解答文中疑惑