tinymce富文本编辑器,视频上传后无法预览
tinymce富文本编辑器,最大的特点是开源(好用的插件是收费的-_-!),插件是按需加载,界面UI友好简洁易用。
今天我们来聊一聊该编辑器最受关注的视频上传功能。这款编辑器默认的视频上传是无法上传本地视频的,只能使用在线的url插入视频。
当然想要实现本地上传也是非常简单的。我们只需要在编辑器初始化的参数里面传入file_picker_callback回调方法并且自定义上传逻辑,代码如下:
file_picker_callback: function(){
//创建一个隐藏的type=file的文件选择input
let input = document.createElement('input');
let url = "";
input.setAttribute('type', 'file');
if (meta.filetype === 'image'){
url = baseUrl + 'cbeditor/uploadImg'
input.setAttribute('accept', 'image/jpeg,image/gif,image/jpg,image/png')
}else if (meta.filetype === 'media'){
url = baseUrl + 'cbeditor/uploadMedia'
input.setAttribute('accept', 'video/*')
}else if (meta.filetype === 'file'){
url = baseUrl + 'cbeditor/uploadFile'
}
input.onchange = function(){
let file = this.files[0];//只选取第一个文件。如果要选取全部,后面注意做修改
comp.editorUploadFile(cb, url, file)
}
//触发点击
input.click();
},
images_upload_handler: function(blobInfo, success, failure) {
let xhr = new XMLHttpRequest()
xhr.open('POST', "视频上传的远程接口url")
xhr.withCredentials = true
let formData = new FormData()
formData.append('file', blobInfo.blob())
xhr.send(formData)
}
解决视频本地上传并不难,网上资料一坨,总有一款适合你。但是我们要讲的是视频上传后,在编辑器内容中是无法预览我们上传的视频的。上传视频成功后,在编辑区会是一个img标签代替了我们的视频。此时网上又有攻略说有个属性media_live_embeds配置为true时。就可以实现视频预览。不要激动。这个配置我保证100%无效。可以看源码,这个配置只对iframe的内嵌方式有效。本地上传的视频洗洗睡吧。
此时积极百度的同学们可能又找到第二种解决方法:自定义video_template_callback回调方法,此方法就是用来自定义处理视频上传后的回显逻辑。恭喜你。此方法是有效的。上传视频后在编辑区是可以直接预览播放的。但是小问题又来了。这里的width是100%。上传后。是无法再次编辑拖拽调整视频尺寸的。
video_template_callback: function(data) {
data.width = "100%";
data.height = "auto";
return `<p>
<span class="mce-preview-object mce-object-video" contenteditable="false"
data-mce-object="video" data-mce-p-allowfullscreen="allowfullscreen"
data-mce-p-frameborder="no" data-mce-p-scrolling="no"
data-mce-p-src=${data.source1}
data-mce-p-width=${data.width}
data-mce-p-height=${data.height}
data-mce-p-controls="controls" data-mce-html="%20">
<video width=${data.width} height=${data.height} controls="controls">
<source src=${data.source1} type=${data.source1mime}></source>
</video>
</span>
</p>`;
}
事情到这里还没有结束。现在只是在编辑器中插入视频时可以预览了。但是我们在后台管理系统中。通常新增一条记录。肯定也可以修改这条记录。那么数据回显问题又来了。修改记录时。此时编辑器要从数据库中加载富文本数据。这时可不会触发上传视频操作。也就是上面这个回调方法是没有用了。数据回显时依然是一个img标签静静的躺在那里。-_-!!!如果客户端你也是用这个编辑器去渲染数据的。那就真的洗洗睡了。视频直接是img标签,根本无法播放。
好了,事到如今。我在这里总结一下。如果想用tinymce富文本编辑器做后端数据维护,客户端也用编辑器做数据渲染展示的业务需求时。方案如下:
1、后台新增和修改操作时,我们直接不做预览。(舍掉预览,我们能收益一个自由调整视频尺寸的功能)。如果实在想预览看一下视频有没有问题。编辑器自带了预览插件,点击预览按钮,我们进入预览模式就可以看到视频了。这也算是一种折中方案,各有优缺点。看你取舍了。
2、如果前端也是用的此编辑器去渲染数据的。我们不可能要求客户去点击预览按钮才去看视频。显然很不友好。但是渲染出来的又是一个img,视频无法播放。此时解决该问题,我们就需要修改Media插件的源代码了。我们修改他的渲染逻辑。基本思路就是当他渲染video节点时。我们把他的img标签强行换成video标签。src和controls属性什么的都填充好即可。
具体实施步骤如下,可以无视tinymce版本。原理都一样,不管哪个版本照改不误,无非就是修改的代码所在行数不一样:
1、找到函数:placeHolderConverter位置
在函数外部定义一个视频src的变量,例如:var videoSrc = "";
在if(node.name === 'script'){...}后面增加以下代码片断,目的就是获取视频的src临时保存到刚刚声明的变量中去。方便后面替换img时填充video的src属性:
if(node.name === 'video'){
if(node.attributes['map'] && node.attributes['map'].src){
videoSrc = node.attributes['map'].src
}else{
for(var ii=0;ii<node.attributes.length;ii++){
if(node.attributes[ii].name == "src"){
videoSrc = node.map.node.attributes[ii].value
}
}
}
if(node.firstChild && node.firstChild.value){
var elel=node.firstChild && $(node.firstChild.value)
videoSrc = elel.attr('src')
}
}
2、找到函数:createPlaceholderNode位置
此函数就是渲染节点的。看源码是不是发现里面是一个img标签。此时我们把他修改成video标签。并且把下面的src属性修改成我们刚刚临时保存的变量,以及增加controls属性
完整代码如下(注意里面的Settings.mediaIsPreview方法是我自定义的。这个参数是我用来控制是否打开这个开关。因为后台编辑数据里我们不需要他解析。我们就可以通过这个参数去关闭这个预览。前台需要直接渲染时才打开这个开关。):
var createPlaceholderNode = function (editor, node) {
var placeHolder;
var name = node.name;
var videoFlag = Settings.mediaIsPreview(editor) && name === 'video'
placeHolder = new global$8(videoFlag ? 'video' : 'img', 1);
placeHolder.shortEnded = true;
retainAttributesAndInnerHtml(editor, node, placeHolder);
placeHolder.attr({
'width': node.attr('width') || '300',
'height': node.attr('height') || (name === 'audio' ? '30' : '150'),
'style': node.attr('style'),
'src': videoFlag ? videoSrc || global$1.transparentSrc : global$1.transparentSrc,
'controls': videoFlag ? 'controls' : null,
'data-mce-object': name,
'class': 'mce-object mce-object-' + name
});
videoSrc = ""
return placeHolder;
};
至此我们为tinymce编辑器自定义了一个开关参数。当我们打开了开关时,编辑器加载视频时就会把他渲染成video标签而不是img标签,客户端可以正常的预览视频。当我们在后台编辑内容时,我们把开关关闭。编辑器就回到了渲染成img标签。此时我们可以自由的拖拽视频大小尺寸,方便了我们对富文本内容布局,后台我们想要预览视频,点击预览按钮即可。启不美哉-_- 如果有大神有更加优秀的解决方案,欢迎留言交流