tinymce富文本编辑器,视频上传后无法预览

  |   3,105 浏览

    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标签。此时我们可以自由的拖拽视频大小尺寸,方便了我们对富文本内容布局,后台我们想要预览视频,点击预览按钮即可。启不美哉-_- 如果有大神有更加优秀的解决方案,欢迎留言交流

    评论

    发表评论

    validate