从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能

UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。(抄的...)

UEditor是非常好用的富文本web编辑器,而且全中文API和注释,方便学习和使用。特别是图片上传查看及涂鸦功能极为喜欢,但是有很多情况我们并不需要Web编辑器,而只需要图片上传。那么问题来了,提取图片上传哪家强.....

网上有很多图片上传的控件、插件。但都不是那么的完美,有的只有一张图片上传不包含批量上传,有的没有图片查看功能,还有的必须要flash的支持(ios系统就悲剧了),当然还有的不能跨语言,还有上传没有状态显示,当然还有客户体验不是太好, 浏览器兼兼容问题就更多了,在线涂鸦更是少之又少。而UEditor上传图片几乎解决了以上的问题。

废话不多说,走起。

一、从官网(http://ueditor.baidu.com/website/download.html)上下载UEditor选择开发版[1.4.2 .Net 版本],1、因为本人.Net。2、老的版本更稳定,新版本不支持ie8以下版本。关于其他语言的开发其实和.Net一样,主要是思路。

二、按照官网的说明文档(http://fex-team.github.io/ueditor/)把UEditor部署到VS(http://fex-team.github.io/ueditor/#server-net)中,保证UEditor可以正常使用,特别是图片上传功能。本文主要讲解单独提取UEditor图片上传功能,所以对UEditor的使用部署请参考官网(http://ueditor.baidu.com)。图是本人在VS中的目录结构。

三、修改config.json相关配置信息,这个配置主要关于上传以及查看图片的相关配置。

四、修改ueditor.config.js中的toolbars以及serverUrl ,我们只显示多图片单图片以及涂鸦的显示。

// 服务器统一请求接口路径
        , serverUrl: URL + "../../Common/controller.ashx"

        //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的从新定义
        , toolbars: [[ 'insertimage', 'scrawl', 'simpleupload'  ]]

五、我们的主要内容是创建自己的通用提取上传图片的js文件(custom.js)和简单修改UEditor的ueditor.all.js文件。

  1)、我们在页面中添加UEditor显示Div[editor-img]以及我们后面要处理上传完以后处理文件的名称[temp-img-list],还有初始化Ueditor。

 $("body").append(" <div id=\"editor-img\" style=\"display:none\"></div><div id=\"temp-img-list\" style=\"display: none\"></div>");
 var ue = UE.getEditor('editor-img');

   2)、我们可以把div id='editor-img'的display='block'显示,然后我们就可以在页面看到完整的包含图片上传多图片上传以及涂鸦的UEditor了。

   3)、我们在页面Default.aspx中定义一个多图片上传按钮a标签,然后调用uploadImgs()方法,我们要做的就是点击a标签触发UEditor多图片上传按钮,我们查看源码可以到多图片上传按钮的div class 为edui-for-insertimage,如图。然后我们点击a标签就弹出图片上传的窗口了。

function uploadImgs() {
    $(".edui-for-insertimage .edui-button-body")[0].click();
}

 

    

    

    我们这时可以上传图片以及在线查看图片了。然后点击确认。。。。。。我们这时点击确认会发现会把图片加载到UEditor中,这并不是我们想要的,我们已经完成把图片上传到服务器了,现在只要知道我们上传了哪些图片或者查看图片时选择了哪些图片的名称就完成我们所需要的了。

  4)、当点击确认时图片加载到编辑器中,编辑器的内容就会发生变化。我们可以监听编辑器内容的变化然后再获取编辑器中的内容进行分析处理即可获取图片名称。我们查看官方API可以找到contentChange事件(编辑器内容发生改变时会触发该事件),然后监听此事件。由于单个图片上传相比批量上传和涂鸦比较复杂,我们稍后再做详解。

 UE.getEditor('editor-img').addListener('contentChange', function (editor) {
        //获取编辑器中的内容(html 代码)
        var img = UE.getEditor('editor-img').getPlainTxt();
        if (img != "") { 
                //把编辑器中的内容放到临时div中,然后进行获取文件名称。
                $("#temp-img-list").html(img);
                var array = new Array();
                //循环获取文件名称
                $("#temp-img-list img").each(function () {
                    var src = $(this).attr("src");
                    var name = src.replace("/upload/image/", "");
                    array.push(name);
                });
                //清空编辑器中的内容,以便下一次添加图片。
                UE.getEditor('editor-img').execCommand('cleardoc');
                //调用callbackImg获取懂图片名称
                if (typeof callbackImg === "function") {
                    eval("callbackImg('" + array + "')");
                }
            
        }
    });

   5)、我们自定义js方法callbackImg就可以获取到图片名称了

function callbackImg(imgName) {
            var names = imgName.split(",");
            for (var i = 0; i < names.length; i++) {
                $("#show-img-name").append($("<div></div>").html($("<a></a>").html(names[i]).attr("href", "/upload/image/" + names[i] + "").attr("target", "_blank")));
            }
        }

  6)、这样一个完整的批量图片上传查看的功能就完成了。同理我们可以添加涂鸦的功能,其实这这一步涂鸦的功能只要一步即可,自定义一个js方法insertScrawl(),然后调用insertScrawl即可完成涂鸦的功能。

function insertScrawl() {
    $('.edui-for-scrawl .edui-button-body')[0].click();
}

 

  到此为止,我们就完成了批量图片上传和涂鸦功能。

六、通读代码其实发现批量图片上传和涂鸦就是简单的模拟按钮调用,然后上传完图片或者选择完图片然后点击确认回调处理编辑器中的内容获取文件名称。但是单独上传图片会有一定的复杂度。

  1)、我们用UEditor上传单个图片时会发现在编辑器中会有个等待的图片,当图片上传完毕以后会把等待图片换成我们上传的图片。

  

  上传中...

  

  上传完成以后。

   2)、那么问题又来了,问题一,我们原来是监听编辑器中文本变化,然后获取其中的图片提取名称,这时我们获取的是等待的图片而不是我们真正上传的图片。问题二,这时上传并没有状态显示,如果图片过大或者网速不是很好的情况下,导致用户体验不是很好。

    解决这些问题我们首先要找到图片刚开始上传和上传完毕的事件,还有要判断编辑器中的图片是否是等待的图片,反之就是我们上传的图片。

      1)、查找源码我们可以在ueditor.all.js中找到上传开始和上传完成的事件,分别在24379行和24390行,在ueditor.all.js中分别调用js方法preUploadSingleImg()和uploadSingleImgCallback()。

      2)、ueditor.all.js中修改代码(1,2,3行,23,24,25行)

       if (typeof preUploadSingleImg === "function") {
                preUploadSingleImg();
            }
            function callback() { 
                try{
                    var link, json, loader,
                        body = (iframe.contentDocument || iframe.contentWindow.document).body,
                        result = body.innerText || body.textContent || '';
                    json = (new Function("return " + result))();
                    link = me.options.imageUrlPrefix + json.url;
                    if(json.state == 'SUCCESS' && json.url) {
                        loader = me.document.getElementById(loadingId);
                        loader.setAttribute('src', link);
                        loader.setAttribute('_src', link);
                        loader.setAttribute('title', json.title || '');
                        loader.setAttribute('alt', json.original || '');
                        loader.removeAttribute('id');
                        domUtils.removeClasses(loader, 'loadingclass');
                    } else {
                        showErrorLoader && showErrorLoader(json.state);
                    }
                    //单独提取上传回调函数。
                    if (typeof uploadSingleImgCallback === 'function') {
                        uploadSingleImgCallback();
                    }

     3)、在自定义js custom.js中添加方法

//单传图片开始上传,显示等待。
function preUploadSingleImg() {
    if ($("#loading").length > 0) {
        $("#loading").html("<img src='/Scripts/ueditor/loading.gif'>");;
    }

}

//单传图片回调,隐藏等待图片
function uploadSingleImgCallback() { 
    if ($("#loading").length > 0) {
        $("#loading").empty();
    }
}

     4)、最后要做的就是在页面上添加一个空的div id='loading'

     5)、这样我们就解决了单独图片上传状态的问题,但是还有一个获取编辑器中上传图片的问题,这时要做两步,

        1)、在custom.js中修改代码,编辑器内容改变事件中contentChange 判断是否是等待图片,如果是等待图片我们不做任何的处理即可。修改代码为

UE.getEditor('editor-img').addListener('contentChange', function (editor) {
        //获取编辑器中的内容(html 代码)
        var img = UE.getEditor('editor-img').getPlainTxt();
        if (img != "") {
            //判断是否是单图片上传,如果是单传不做任何处理,等待回调函数再次调用。
            if (img.indexOf("loadingclass") == -1) {
                //把编辑器中的内容放到临时div中,然后进行获取文件名称。
                $("#temp-img-list").html(img);
                var array = new Array();
                //循环获取文件名称
                $("#temp-img-list img").each(function () {
                    var src = $(this).attr("src");
                    var name = src.replace("/upload/image/", "");
                    array.push(name);
                });
                //清空编辑器中的内容,以便下一次添加图片。
                UE.getEditor('editor-img').execCommand('cleardoc');
                //调用callbackImg获取懂图片名称
                if (typeof callbackImg === "function") {
                    eval("callbackImg('" + array + "')");
                }
            }
        }
    });

         2)、我们在上传完事件中清空编辑器中的内容,然后编辑器又会调用 contentChange 事件,由于上传完毕以后编辑器中不是等待的图片而是我们真正上传的图片,这时只要按照多图片上传获取图片名称即可。修改方法uploadSingleImgCallback为

//单传图片回调,然后清理内容,在清理内容会自动调用contentChange事件,然后再获取上传文件的文件名。
function uploadSingleImgCallback() {
    UE.getEditor('editor-img').execCommand('cleardoc');
    if ($("#loading").length > 0) {
        $("#loading").empty();
    }
}

    6)、最后我自定义一个按钮调用方法uploadImg()即可弹出窗口选择图片,然后选择图片点击确定即可上传到服务器并获取到文件名称。

function uploadImg() {
    $(".edui-for-simpleupload input").click();
}

     

总结:我们选择就从UEditor中提取了多图片单图片上传以及涂鸦的功能。关于其他语言,逻辑一样的,只要更换不同的服务端代码即可。

以下为动画演示

 

谢谢观赏...

 

Github:https://github.com/Emrys5/UeditorFileUpload

 

    

    

 

 

 

 

 

posted @ 2014-10-22 18:48  Emrys5  阅读(16994)  评论(143编辑  收藏  举报