1. 程式人生 > >百度UEditor呼叫單圖片上傳功能的解決方法

百度UEditor呼叫單圖片上傳功能的解決方法

做了個文章編輯頁面,用了百度的UEditor,文章編輯上傳圖片毫無問題,但是封面圖上傳又開始頭疼了,想呼叫UEditor那個單圖片上傳的按鈕功能,但是js這塊實在沒深入研究過,先放下,找找網上可否有解決方案,方案倒是有,但基本都是出自同一源頭,方法都是再建立一個例項然後隱藏再呼叫的思路,總是覺得不爽,算了照做,但是彈出來是多圖的對話方塊,還有其他問題,這不能忍,必須自己幹!具體如下:

直接定位UEditor的程式碼資料夾找到 ueditor.all.js

因為修改了該檔案,在專案中需要引用ueditor.all.min.js的地方替換成ueditor.all.js

UEditor版本1.4.3.3,定位到行24462(或者直接查詢 simpleupload,即可找到),這是單圖上傳的外掛程式碼,將整個外掛程式碼替換為下面的程式碼

UE.plugin.register('simpleupload', function (){
var me = this,
    isLoaded = false,
    containerBtn;

function initUploadBtn() {
    var w = containerBtn.offsetWidth || 20,
        h = containerBtn.offsetHeight || 20,
        btnIframe = document.createElement('iframe'),
        btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;';

    domUtils.on(btnIframe, 'load', function () {

        var timestrap = (+new Date()).toString(36),
            wrapper,
            btnIframeDoc,
            btnIframeBody;

        btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);
        btnIframeBody = btnIframeDoc.body;
        wrapper = btnIframeDoc.createElement('div');

        wrapper.innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me.getOpt('serverUrl') + '" ' +
        'style="' + btnStyle + '">' +
        '<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '" ' +
        'style="' + btnStyle + '">' +
        '</form>' +
        '<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';

        wrapper.className = 'edui-' + me.options.theme;
        wrapper.id = me.ui.id + '_iframeupload';
        btnIframeBody.style.cssText = btnStyle;
        btnIframeBody.style.width = w + 'px';
        btnIframeBody.style.height = h + 'px';
        btnIframeBody.appendChild(wrapper);

        if (btnIframeBody.parentNode) {
            btnIframeBody.parentNode.style.width = w + 'px';
            btnIframeBody.parentNode.style.height = w + 'px';
        }

        var form = btnIframeDoc.getElementById('edui_form_' + timestrap);
        var input = btnIframeDoc.getElementById('edui_input_' + timestrap);
        var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);

        domUtils.on(input, 'change', function () {
            if (!input.value) return;
            var loadingId = 'loading_' + (+new Date()).toString(36);
            var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';

            var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
            var allowFiles = me.getOpt('imageAllowFiles');

            me.focus();
            me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >');

            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);
                    }
                } catch (er) {
                    showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));
                }
                form.reset();
                domUtils.un(iframe, 'load', callback);
            }
            function showErrorLoader(title) {
                if (loadingId) {
                    var loader = me.document.getElementById(loadingId);
                    loader && domUtils.remove(loader);
                    me.fireEvent('showmessage', {
                        'id': loadingId,
                        'content': title,
                        'type': 'error',
                        'timeout': 4000
                    });
                }
            }

            /* 判斷後端配置是否沒有載入成功 */
            if (!me.getOpt('imageActionName')) {
                errorHandler(me.getLang('autoupload.errorLoadConfig'));
                return;
            }
            // 判斷檔案格式是否錯誤
            var filename = input.value,
                fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
            if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
                showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
                return;
            }

            domUtils.on(iframe, 'load', callback);
            form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
            form.submit();
        });

        var stateTimer;
        me.addListener('selectionchange', function () {
            clearTimeout(stateTimer);
            stateTimer = setTimeout(function () {
                var state = me.queryCommandState('simpleupload');
                if (state == -1) {
                    input.disabled = 'disabled';
                } else {
                    input.disabled = false;
                }
            }, 400);
        });
        isLoaded = true;
    });

    btnIframe.style.cssText = btnStyle;
    containerBtn.appendChild(btnIframe);
    me.fireEvent('simpleupload_ready');         /* TY Added For Extra Custom SimpleUpload */
}
/*============== TY Added For Extra Custom SimpleUpload =================*/
function BindCustomBtn() {
    var w = containerBtn.offsetWidth || 20,
        h = containerBtn.offsetHeight || 20,
        btnIframe = document.createElement('iframe'),
        btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;';

    domUtils.on(btnIframe, 'load', function () {

        var timestrap = (+new Date()).toString(36),
            wrapper,
            btnIframeDoc,
            btnIframeBody;

        btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);
        btnIframeBody = btnIframeDoc.body;
        wrapper = btnIframeDoc.createElement('div');

        wrapper.innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me.getOpt('serverUrl') + '" ' +
        'style="' + btnStyle + '">' +
        '<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '" ' +
        'style="' + btnStyle + '">' +
        '</form>' +
        '<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';

        wrapper.className = 'edui-' + me.options.theme;
        wrapper.id = me.ui.id + '_iframeupload';
        btnIframeBody.style.cssText = btnStyle;
        btnIframeBody.style.width = w + 'px';
        btnIframeBody.style.height = h + 'px';
        btnIframeBody.appendChild(wrapper);

        if (btnIframeBody.parentNode) {
            btnIframeBody.parentNode.style.width = w + 'px';
            btnIframeBody.parentNode.style.height = w + 'px';
        }

        var form = btnIframeDoc.getElementById('edui_form_' + timestrap);
        var input = btnIframeDoc.getElementById('edui_input_' + timestrap);
        var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);

        domUtils.on(input, 'change', function () {
            if (!input.value) return;
            var loadingId = 'loading_' + (+new Date()).toString(36);
            var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';

            var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
            var allowFiles = me.getOpt('imageAllowFiles');

            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) {
                        me.fireEvent('simpleupload_customcomplete', containerBtn.id, link, json.title || '', json.original || '');
                    } else {
                        showErrorLoader && showErrorLoader(json.state);
                    }
                } catch (er) {
                    showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));
                }
                form.reset();
                domUtils.un(iframe, 'load', callback);
            }
            function showErrorLoader(title) {
                if (loadingId) {
                    me.fireEvent('showmessage', {
                        'id': loadingId,
                        'content': title,
                        'type': 'error',
                        'timeout': 4000
                    });
                }
            }

            /* 判斷後端配置是否沒有載入成功 */
            if (!me.getOpt('imageActionName')) {
                errorHandler(me.getLang('autoupload.errorLoadConfig'));
                return;
            }
            // 判斷檔案格式是否錯誤
            var filename = input.value,
                fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
            if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
                showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
                return;
            }

            domUtils.on(iframe, 'load', callback);
            form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
            form.submit();
        });

        var stateTimer;
        me.addListener('selectionchange', function () {
            clearTimeout(stateTimer);
            stateTimer = setTimeout(function () {
                var state = me.queryCommandState('simpleupload');
                if (state == -1) {
                    input.disabled = 'disabled';
                } else {
                    input.disabled = false;
                }
            }, 400);
        });
        isLoaded = true;
    });

    btnIframe.style.cssText = btnStyle;
    containerBtn.appendChild(btnIframe, containerBtn);
}
/*=======================================================================*/

return {
    bindEvents:{
        'ready': function() {
            //設定loading的樣式
            utils.cssRule('loading',
                '.loadingclass{display:inline-block;cursor:default;background: url(\''
                + this.options.themePath
                + this.options.theme +'/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
                '.loaderrorclass{display:inline-block;cursor:default;background: url(\''
                + this.options.themePath
                + this.options.theme +'/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
                '}',
                this.document);
        },
        /* 初始化簡單上傳按鈕 */
        'simpleuploadbtnready': function(type, container) {
            containerBtn = container;
            me.afterConfigReady(initUploadBtn);
        },
        /*============== TY Added For Extra Custom SimpleUpload =================*/
        'simpleupload_custominit': function (type,container) {
            containerBtn = container;
            BindCustomBtn();
        }
        /*=======================================================================*/
    },
    outputRule: function(root){
        utils.each(root.getNodesByTagName('img'),function(n){
            if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
                n.parentNode.removeChild(n);
            }
        });
    },
    commands: {
        'simpleupload': {
            queryCommandState: function () {
                return isLoaded ? 0:-1;
            }
        }
    }
}
});

外掛新增了3個訊息,simpleupload_ready、simpleupload_custominit和simpleupload_customcomplete,和新增了一個BindCustomBtn()函式和對應響應訊息simpleupload_custominit的處理函式.

simpleupload_ready訊息是UEditor初始化繫結單圖上傳按鈕完成發出的訊息,響應這個訊息開始繫結自己的單圖上傳按鈕

simpleupload_custominit訊息是通知UEditor呼叫BindCustomBtn()繫結自定義的按鈕

simpleupload_customcomplete訊息是自定義按鈕上傳圖片完成後會出發的訊息,會帶來上傳的結果包括id(自定義按鈕)、link、title、alt引數。

id引數就是自定義按鈕的id,這個可以用來區分是哪個自定義按鈕上傳完畢出發的,也就是說可以支援多個自定義按鈕獨立單圖上傳。

下面是頁面實現一個自定義上傳按鈕(區域)的程式碼

頁面部分Html程式碼(Div作為自定義按鈕)

<div id="upload-cover" style="width: 45px; height: 30px; margin-left: 60px; border: 1px solid #808080">
<img id="cover-img" src="" width="45" height="30" style="position: absolute" />
                </div>

頁面js程式碼

//UEditor And CustomSimpleUpload Init
        var ue = UE.getEditor('content');
        ue.addListener('simpleupload_ready', function (types) {
            var btnUpload = document.getElementById('upload-cover');
            ue.fireEvent('simpleupload_custominit', btnUpload);
        });
        ue.addListener('simpleupload_customcomplete', function (types, id, link, title, alt) {
            document.getElementById('cover-img').src = link;
            document.getElementById('cover').value = link;//賦值表單的一個隱藏input
        });

以上程式碼基本上就解決呼叫單圖上傳的問題,有個問題需要注意下,原單圖的外掛是在上傳點選按鈕(區域)上覆蓋了一層同樣大小的透明按鈕,上傳點選按鈕的動作觸發的其實是這個透明按鈕,
自定義按鈕按照上面js程式碼繫結訊息後,觸發方式不變,所以如果點選無效的話,那應該是透明按鈕沒有重疊到你自己的自定義按鈕上。在外掛程式碼的函式BindCustomBtn()中,找到

filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;

把透明改為不透明,自己調整下按鈕位置,和自己的自定義按鈕重疊就OK了。

最終完成效果是這樣的:

1、上傳封面圖片前

上傳前

2、上傳中

上傳中

3、上傳完成

這裡寫圖片描述