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不是很熟,若有錯誤歡迎指正,也歡迎解答文中疑惑