微信開發-微信內置瀏覽器的Javascript API

源代碼來自 http://www.baidufe.com/api

/**!
 * 微信內置瀏覽器的Javascript API,功能包括:
 *
 * 一、分享到微信朋友圈
 * 二、分享給微信好友
 * 三、分享到騰訊微博
 * 四、隱藏/顯示右上角的菜單入口
 * 五、隱藏/顯示底部瀏覽器工具欄
 * 六、獲取當前的網絡狀態
 * 七、調起微信客戶端的圖片播放組件
 * 八、關閉公衆平臺Web頁面
 * 九、判斷當前網頁是否在微信內置瀏覽器中打開
 * 十、支持WeixinApi的錯誤監控
 * 十一、發送電子郵件
 * 十二、禁止用戶分享
 *
 */
(function (window) {

    "use strict";

    /**
     * 定義WeixinApi
     */
    var WeixinApi = {
        version: 4.3
    };

    // 將WeixinApi暴露到window下:全局可以使用,對舊版本向下兼容
    window.WeixinApi = WeixinApi;

    /////////////////////////// CommonJS /////////////////////////////////
    if (typeof define === 'function' && (define.amd || define.cmd)) {
        if (define.amd) {
            // AMD 規範,for:requirejs
            define(function () {
                return WeixinApi;
            });
        } else if (define.cmd) {
            // CMD 規範,for:seajs
            define(function (require, exports, module) {
                module.exports = WeixinApi;
            });
        }
    }

    /**
     * 對象簡單繼承,後面的覆蓋前面的,繼承深度:deep=1
     * @private
     */
    var _extend = function () {
        var result = {}, obj, k;
        for (var i = 0, len = arguments.length; i < len; i++) {
            obj = arguments[i];
            if (typeof obj === 'object') {
                for (k in obj) {
                    obj[k] && (result[k] = obj[k]);
                }
            }
        }
        return result;
    };

    /**
     * 內部私有方法,分享用
     * @private
     */
    var _share = function (cmd, data, callbacks) {
        callbacks = callbacks || {};

        // 分享過程當中的一些回調
        var progress = function (resp) {
            switch (true) {
                // 用戶取消
                case /\:cancel$/i.test(resp.err_msg) :
                    callbacks.cancel && callbacks.cancel(resp);
                    break;
                // 發送成功
                case /\:(confirm|ok)$/i.test(resp.err_msg):
                    callbacks.confirm && callbacks.confirm(resp);
                    break;
                // fail 發送失敗
                case /\:fail$/i.test(resp.err_msg) :
                default:
                    callbacks.fail && callbacks.fail(resp);
                    break;
            }
            // 不管成功失敗都會執行的回調
            callbacks.all && callbacks.all(resp);
        };

        // 執行分享,並處理結果
        var handler = function (theData, argv) {

            // 加工一下數據
            if (cmd.menu == 'menu:share:timeline' ||
                (cmd.menu == 'general:share' && argv.shareTo == 'timeline')) {

                var title = theData.title;
                theData.title = theData.desc || title;
                theData.desc = title || theData.desc;
            }

            // 若是是收藏操做,而且在wxCallbacks中配置了favorite爲false,則不執行回調
            if (argv && (argv.shareTo == 'favorite' || argv.scene == 'favorite')) {
                if (callbacks.favorite === false) {
                    WeixinJSBridge.invoke('sendAppMessage', theData, new Function());
                } else {
                    WeixinJSBridge.invoke(cmd.action, theData, progress);
                }
            } else {
                // 新的分享接口,單獨處理
                if (cmd.menu === 'general:share') {
                    if (argv.shareTo === 'timeline') {
                        WeixinJSBridge.invoke('shareTimeline', theData, progress);
                    } else if (argv.shareTo === 'friend') {
                        WeixinJSBridge.invoke('sendAppMessage', theData, progress);
                    } else if (argv.shareTo === 'QQ') {
                        WeixinJSBridge.invoke('shareQQ', theData, progress);
                    } else if (argv.shareTo === 'weibo') {
                        WeixinJSBridge.invoke('shareWeibo', theData, progress);
                    }
                } else {
                    WeixinJSBridge.invoke(cmd.action, theData, progress);
                }
            }
        };

        // 監聽分享操做
        WeixinJSBridge.on(cmd.menu, function (argv) {
            callbacks.dataLoaded = callbacks.dataLoaded || new Function();
            if (callbacks.async && callbacks.ready) {
                WeixinApi["_wx_loadedCb_"] = callbacks.dataLoaded;
                if (WeixinApi["_wx_loadedCb_"].toString().indexOf("_wx_loadedCb_") > 0) {
                    WeixinApi["_wx_loadedCb_"] = new Function();
                }
                callbacks.dataLoaded = function (newData) {
                    callbacks.__cbkCalled = true;
                    var theData = _extend(data, newData);
                    theData.img_url = theData.imgUrl || theData.img_url;
                    delete theData.imgUrl;
                    WeixinApi["_wx_loadedCb_"](theData);
                    handler(theData, argv);
                };
                // 而後就緒
                if (!(argv && (argv.shareTo == 'favorite' || argv.scene == 'favorite') && callbacks.favorite === false)) {
                    callbacks.ready && callbacks.ready(argv, data);
                    // 若是設置了async爲true,可是在ready方法中並無手動調用dataLoaded方法,則自動觸發一次
                    if (!callbacks.__cbkCalled) {
                        callbacks.dataLoaded({});
                        callbacks.__cbkCalled = false;
                    }
                }
            } else {
                // 就緒狀態
                var theData = _extend(data);
                if (!(argv && (argv.shareTo == 'favorite' || argv.scene == 'favorite') && callbacks.favorite === false)) {
                    callbacks.ready && callbacks.ready(argv, theData);
                }
                handler(theData, argv);
            }
        });
    };

    /**
     * 分享到微信朋友圈
     * @param       {Object}    data       待分享的信息
     * @p-config    {String}    appId      公衆平臺的appId(服務號可用)
     * @p-config    {String}    imgUrl     圖片地址
     * @p-config    {String}    link       連接地址
     * @p-config    {String}    desc       描述
     * @p-config    {String}    title      分享的標題
     *
     * @param       {Object}    callbacks  相關回調方法
     * @p-config    {Boolean}   async                   ready方法是否須要異步執行,默認false
     * @p-config    {Function}  ready(argv, data)       就緒狀態
     * @p-config    {Function}  dataLoaded(data)        數據加載完成後調用,async爲true時有用,也能夠爲空
     * @p-config    {Function}  cancel(resp)    取消
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  confirm(resp)   成功
     * @p-config    {Function}  all(resp)       不管成功失敗都會執行的回調
     */
    WeixinApi.shareToTimeline = function (data, callbacks) {
        _share({
            menu: 'menu:share:timeline',
            action: 'shareTimeline'
        }, {
            "appid": data.appId ? data.appId : '',
            "img_url": data.imgUrl,
            "link": data.link,
            "desc": data.desc,
            "title": data.title,
            "img_width": "640",
            "img_height": "640"
        }, callbacks);
    };

    /**
     * 發送給微信上的好友
     * @param       {Object}    data       待分享的信息
     * @p-config    {String}    appId      公衆平臺的appId(服務號可用)
     * @p-config    {String}    imgUrl     圖片地址
     * @p-config    {String}    link       連接地址
     * @p-config    {String}    desc       描述
     * @p-config    {String}    title      分享的標題
     *
     * @param       {Object}    callbacks  相關回調方法
     * @p-config    {Boolean}   async                   ready方法是否須要異步執行,默認false
     * @p-config    {Function}  ready(argv, data)       就緒狀態
     * @p-config    {Function}  dataLoaded(data)        數據加載完成後調用,async爲true時有用,也能夠爲空
     * @p-config    {Function}  cancel(resp)    取消
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  confirm(resp)   成功
     * @p-config    {Function}  all(resp)       不管成功失敗都會執行的回調
     */
    WeixinApi.shareToFriend = function (data, callbacks) {
        _share({
            menu: 'menu:share:appmessage',
            action: 'sendAppMessage'
        }, {
            "appid": data.appId ? data.appId : '',
            "img_url": data.imgUrl,
            "link": data.link,
            "desc": data.desc,
            "title": data.title,
            "img_width": "640",
            "img_height": "640"
        }, callbacks);
    };

    /**
     * 分享到騰訊微博
     * @param       {Object}    data       待分享的信息
     * @p-config    {String}    link       連接地址
     * @p-config    {String}    desc       描述
     *
     * @param       {Object}    callbacks  相關回調方法
     * @p-config    {Boolean}   async                   ready方法是否須要異步執行,默認false
     * @p-config    {Function}  ready(argv, data)       就緒狀態
     * @p-config    {Function}  dataLoaded(data)        數據加載完成後調用,async爲true時有用,也能夠爲空
     * @p-config    {Function}  cancel(resp)    取消
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  confirm(resp)   成功
     * @p-config    {Function}  all(resp)       不管成功失敗都會執行的回調
     */
    WeixinApi.shareToWeibo = function (data, callbacks) {
        _share({
            menu: 'menu:share:weibo',
            action: 'shareWeibo'
        }, {
            "content": data.desc,
            "url": data.link
        }, callbacks);
    };

    /**
     * 新的分享接口
     * @param       {Object}    data       待分享的信息
     * @p-config    {String}    appId      公衆平臺的appId(服務號可用)
     * @p-config    {String}    imgUrl     圖片地址
     * @p-config    {String}    link       連接地址
     * @p-config    {String}    desc       描述
     * @p-config    {String}    title      分享的標題
     *
     * @param       {Object}    callbacks  相關回調方法
     * @p-config    {Boolean}   async                   ready方法是否須要異步執行,默認false
     * @p-config    {Function}  ready(argv, data)       就緒狀態
     * @p-config    {Function}  dataLoaded(data)        數據加載完成後調用,async爲true時有用,也能夠爲空
     * @p-config    {Function}  cancel(resp)    取消
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  confirm(resp)   成功
     * @p-config    {Function}  all(resp)       不管成功失敗都會執行的回調
     */
    WeixinApi.generalShare = function (data, callbacks) {
        _share({
            menu: 'general:share'
        }, {
            "appid": data.appId ? data.appId : '',
            "img_url": data.imgUrl,
            "link": data.link,
            "desc": data.desc,
            "title": data.title,
            "img_width": "640",
            "img_height": "640"
        }, callbacks);
    };

    /**
     * 設置頁面禁止分享:包括朋友圈、好友、騰訊微博、qq
     * @param callback
     */
    WeixinApi.disabledShare = function (callback) {
        callback = callback || function () {
            alert('當前頁面禁止分享!');
        };
        ['menu:share:timeline', 'menu:share:appmessage', 'menu:share:qq',
            'menu:share:weibo', 'general:share'].forEach(function (menu) {
                WeixinJSBridge.on(menu, function () {
                    callback();
                    return false;
                });
            });
    };

    /**
     * 調起微信Native的圖片播放組件。
     * 這裏必須對參數進行強檢測,若是參數不合法,直接會致使微信客戶端crash
     *
     * @param {String} curSrc 當前播放的圖片地址
     * @param {Array} srcList 圖片地址列表
     */
    WeixinApi.imagePreview = function (curSrc, srcList) {
        if (!curSrc || !srcList || srcList.length == 0) {
            return;
        }
        WeixinJSBridge.invoke('imagePreview', {
            'current': curSrc,
            'urls': srcList
        });
    };

    /**
     * 顯示網頁右上角的按鈕
     */
    WeixinApi.showOptionMenu = function () {
        WeixinJSBridge.call('showOptionMenu');
    };


    /**
     * 隱藏網頁右上角的按鈕
     */
    WeixinApi.hideOptionMenu = function () {
        WeixinJSBridge.call('hideOptionMenu');
    };

    /**
     * 顯示底部工具欄
     */
    WeixinApi.showToolbar = function () {
        WeixinJSBridge.call('showToolbar');
    };

    /**
     * 隱藏底部工具欄
     */
    WeixinApi.hideToolbar = function () {
        WeixinJSBridge.call('hideToolbar');
    };

    /**
     * 返回以下幾種類型:
     *
     * network_type:wifi     wifi網絡
     * network_type:edge     非wifi,包含3G/2G
     * network_type:fail     網絡斷開鏈接
     * network_type:wwan     2g或者3g
     *
     * 使用方法:
     * WeixinApi.getNetworkType(function(networkType){
     *
     * });
     *
     * @param callback
     */
    WeixinApi.getNetworkType = function (callback) {
        if (callback && typeof callback == 'function') {
            WeixinJSBridge.invoke('getNetworkType', {}, function (e) {
                // 在這裏拿到e.err_msg,這裏面就包含了全部的網絡類型
                callback(e.err_msg);
            });
        }
    };

    /**
     * 關閉當前微信公衆平臺頁面
     * @param       {Object}    callbacks       回調方法
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  success(resp)   成功
     */
    WeixinApi.closeWindow = function (callbacks) {
        callbacks = callbacks || {};
        WeixinJSBridge.invoke("closeWindow", {}, function (resp) {
            switch (resp.err_msg) {
                // 關閉成功
                case 'close_window:ok':
                    callbacks.success && callbacks.success(resp);
                    break;

                // 關閉失敗
                default :
                    callbacks.fail && callbacks.fail(resp);
                    break;
            }
        });
    };

    /**
     * 當頁面加載完畢後執行,使用方法:
     * WeixinApi.ready(function(Api){
     *     // 從這裏只用Api便是WeixinApi
     * });
     * @param readyCallback
     */
    WeixinApi.ready = function (readyCallback) {

        /**
         * 加一個鉤子,同時解決Android和iOS下的分享問題
         * @private
         */
        var _hook = function () {
            var _WeixinJSBridge = {};
            Object.keys(WeixinJSBridge).forEach(function (key) {
                _WeixinJSBridge[key] = WeixinJSBridge[key];
            });
            Object.keys(WeixinJSBridge).forEach(function (key) {
                if (typeof WeixinJSBridge[key] === 'function') {
                    WeixinJSBridge[key] = function () {
                        try {
                            var args = arguments.length > 0 ? arguments[0] : {},
                                runOn3rd_apis = args.__params ? args.__params.__runOn3rd_apis || [] : [];
                            ['menu:share:timeline', 'menu:share:appmessage', 'menu:share:weibo',
                                'menu:share:qq', 'general:share'].forEach(function (menu) {
                                    runOn3rd_apis.indexOf(menu) === -1 && runOn3rd_apis.push(menu);
                                });
                        } catch (e) {
                        }
                        return _WeixinJSBridge[key].apply(WeixinJSBridge, arguments);
                    };
                }
            });
        };

        if (readyCallback && typeof readyCallback == 'function') {
            var Api = this;
            var wxReadyFunc = function () {
                _hook();
                readyCallback(Api);
            };
            if (typeof window.WeixinJSBridge == "undefined") {
                if (document.addEventListener) {
                    document.addEventListener('WeixinJSBridgeReady', wxReadyFunc, false);
                } else if (document.attachEvent) {
                    document.attachEvent('WeixinJSBridgeReady', wxReadyFunc);
                    document.attachEvent('onWeixinJSBridgeReady', wxReadyFunc);
                }
            } else {
                wxReadyFunc();
            }
        }
    };

    /**
     * 判斷當前網頁是否在微信內置瀏覽器中打開
     */
    WeixinApi.openInWeixin = function () {
        return /MicroMessenger/i.test(navigator.userAgent);
    };

    /**
     * 發送郵件
     * @param       {Object}  data      郵件初始內容
     * @p-config    {String}  subject   郵件標題
     * @p-config    {String}  body      郵件正文
     *
     * @param       {Object}    callbacks       相關回調方法
     * @p-config    {Function}  fail(resp)      失敗
     * @p-config    {Function}  success(resp)   成功
     * @p-config    {Function}  all(resp)       不管成功失敗都會執行的回調
     */
    WeixinApi.sendEmail = function (data, callbacks) {
        callbacks = callbacks || {};
        WeixinJSBridge.invoke("sendEmail", {
            "title": data.subject,
            "content": data.body
        }, function (resp) {
            if (resp.err_msg === 'send_email:sent') {
                callbacks.success && callbacks.success(resp);
            } else {
                callbacks.fail && callbacks.fail(resp);
            }
            callbacks.all && callbacks.all(resp);
        })
    };

    /**
     * 開啓Api的debug模式,好比出了個什麼錯誤,能alert告訴你,而不是一直很苦逼的在想哪兒出問題了
     * @param    {Function}  callback(error) 出錯後的回調,默認是alert
     */
    WeixinApi.enableDebugMode = function (callback) {
        /**
         * @param {String}  errorMessage   錯誤信息
         * @param {String}  scriptURI      出錯的文件
         * @param {Long}    lineNumber     出錯代碼的行號
         * @param {Long}    columnNumber   出錯代碼的列號
         */
        window.onerror = function (errorMessage, scriptURI, lineNumber, columnNumber) {

            // 有callback的狀況下,將錯誤信息傳遞到options.callback中
            if (typeof callback === 'function') {
                callback({
                    message: errorMessage,
                    script: scriptURI,
                    line: lineNumber,
                    column: columnNumber
                });
            } else {
                // 其餘狀況,都以alert方式直接提示錯誤信息
                var msgs = [];
                msgs.push("額,代碼有錯。。。");
                msgs.push("\n錯誤信息:", errorMessage);
                msgs.push("\n出錯文件:", scriptURI);
                msgs.push("\n出錯位置:", lineNumber + '行,' + columnNumber + '列');
                alert(msgs.join(''));
            }
        }
    };

    /**
     * 通用分享,一種簡便的寫法
     * @param wxData
     * @param wxCallbacks
     */
    WeixinApi.share = function (wxData, wxCallbacks) {
        WeixinApi.ready(function (Api) {
            // 用戶點開右上角popup菜單後,點擊分享給好友,會執行下面這個代碼
            Api.shareToFriend(wxData, wxCallbacks);

            // 點擊分享到朋友圈,會執行下面這個代碼
            Api.shareToTimeline(wxData, wxCallbacks);

            // 點擊分享到騰訊微博,會執行下面這個代碼
            Api.shareToWeibo(wxData, wxCallbacks);

            // 分享到各渠道
            Api.generalShare(wxData, wxCallbacks);
        });
    };
})(window);
相關文章
相關標籤/搜索