Jodit富文本编辑器的基本使用(图片上传)

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

相关文章
相关标签/搜索