分享一款自己封装的微信公众号上使用微信API多图片上传的组件【此组件已用于***公众号发帖回帖等等业务】,支持(bbs发帖)输入框任意位置上传,【***俱乐部】公众号发帖回帖功能
核心组件代码:
1.jqwximgupload.js
/*
* @autor:Aaron email:haotking@163.com
* @date:2016-11-05
* @version:1.1.2
* 微信多图片浏览选择图片上传插件
* 插件依赖jquery和微信js-sdk:jweixin-1.0.0.js
*
* <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
* <script type="text/javascript" src="*************jquery.min.js" ></script>
*
* window.jqwx.wxconfigure($id, options)
* $id:点击后弹出图片选择框的html标签的id
* options:扩展对象,
*
* 用法:
* window.jqwx.wxconfigure("uploadButton11",{
* signObject:signObject,
* jsApiList:['chooseImage','previewImage','uploadImage'] ,
* wxdownloadurl:url,
* isInitWx:false,
* wxsigniniturl:"/ump/page/bbsindex/wxJsAuth",
* onBefore:function(){
* },
* onSuccess:function(data,localIds){
* //图片下载成功后需要完成的事情
* },
* onComplete: function(){
* //弹窗关闭的回调,返回触发事件
* }
* });
* 说明:
* wxsigniniturl:本地服务器获取signObject的接口url
* signObject中对象对应微信js-sdk初始化微信sdk时签名对象
* signObject:{
* appid:"", 微信公众号appid *必须
* timestamp:"", 签名的时间戳 *必须
* noncestr:"", 签名的字符串 *必须
* signature:"" 签名 *必须
* }
* jsApiList:为需要用到的微信的js-sdk的接口,默认['chooseImage','previewImage','uploadImage'] *非必须
* wxdownloadurl:选择图片后,图片会自动上传到微信服务器;需要提供企业服务器从微信下载图片的接口的url
* 插件会通过ajax将data: {serverIds:serverIds},作为json格式上传到服务器,serverIds为存储
* 在微信服务器上的所有图片的媒体ID,通过","分割开. *必须
* onBefore:点击传按钮后,先执行的事件; 例如:在图片上传完成之前,禁止用户做其他的一些点击操作 *非必须
* onSuccess:function(data,localIds){}图片上传成功后,由wxdownloadurl对应接口返回来的data数据,将data数据进行一些页面的处理,比如显示上传成功的图片
* localIds对应的是微信选择的所有本地图片对应的id通过","分割开的字符串
* onComplete:上传插件已经调用完成,最后进行的操作
* isInitWx:是否要执行微信Js-sdk的初始化,一个页面只执行一次
*/
(function($,wx){
window['jqwx'] = window['jqwx'] || {};
window['jqwx'].isWeixinInitComplete=(window['jqwx'].isWeixinInitComplete)||false;
initsign=function initsign(url){
var signObject;
var curr_url=location.href.split('#')[0];
$.ajax({
url : url,
type : "Post",
async:false,
data : {
'url':curr_url
},
error : function(msg) {
alert("微信接口加载失败,请重新进入!"+msg);
},
success : function(data) {
signObject=data;
}
});
return signObject;
}
window.jqwx.insertImage =function(contentId,src) {
document.getElementById(contentId).focus();
var selection = window.getSelection ? window.getSelection() : document.selection;
var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0);
if (!window.getSelection) {
range.pasteHTML(src);
range.collapse(false);
range.select();
} else {
range.collapse(false);
var hasR = range.createContextualFragment(src);
var hasLastChild = hasR.lastChild;
while (hasLastChild && hasLastChild.nodeName.toLowerCase() == "br" && hasLastChild.previousSibling && hasLastChild.previousSibling.nodeName.toLowerCase() == "br") {
var e = hasLastChild;
hasLastChild = hasLastChild.previousSibling;
hasR.removeChild(e);
}
//range.insertNode(range.createContextualFragment("<p><br></p>"));
range.insertNode(hasR);
if (hasLastChild) {
range.setEndAfter(hasLastChild);
range.setStartAfter(hasLastChild);
}
selection.removeAllRanges();
selection.addRange(range);
}
}
window.jqwx.addRange=function (o){
var event = window.event || arguments.callee.caller.arguments[0];
//target 就是这个对象
var target = event.srcElement||event.target;
var sel, range;
//var content = $("#"+o)[0].innerHTML;
// $("#bbsContent_div")[0].innerHTML=content+"</br><p> </p>";
document.getElementById(o).focus();
if (window.getSelection) {
range = document.createRange();
sel = window.getSelection();
//if (sel.getRangeAt && sel.rangeCount) {
//range.selectNodeContents(target);
//range.collapse(true);
//range = sel.getRangeAt(0);
//range.deleteContents();
// range = range.cloneRange();
range.setStartAfter(target);
range.collapse(true);
document.getElementById(o).focus();
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
// }
} else if (document.selection && document.selection.type != "Control") {
alert('浏览器不支持');
// IE < 9
//document.selection.createRange().pasteHTML(html);
}
}
window.jqwx.wxconfigure= function($id, options) {
// 微信服务器返回图片ID数组
var localIds = null;
// 上传序号
var idx = 0;
var serverIds='';
var config = $.extend({
//属性
signObject:{
appid:"",
timestamp:"",
noncestr:"",
signature:""
},
size:9,
isInitWx:false,//是否执行微信js-sdk的初始化
jsApiList:[],//用于保存需要微信初始化的接口
isInitSign:true,
wxdownloadurl:"",
wxsigniniturl:"",
debug:false,
//事件
initwinsign: initsign,
onWxready:$.noop,
onBefore: $.noop,//点击确定的按钮回调
//onCancel: $.noop,//点击取消的按钮回调
onSuccess: $.noop,//图片下载成功后需要完成的事情
onComplete: $.noop//弹窗关闭的回调,返回触发事件
}, options);
init();
function hiddenButton(){
wx.hideMenuItems({
menuList: [
'menuItem:openWithSafari', //在Safari中打开
'menuItem:openWithQQBrowser', //在QQ浏览器中打开
'menuItem:copyUrl' //复制链接
]
});
}
function init(){
if((!jqwx.isWeixinInitComplete)&&config.isInitWx){
if(config.isInitSign){
var currSignObject;
if(config.wxsigniniturl!=""){
currSignObject=config.initwinsign(config.wxsigniniturl);
}else{
currSignObject=config.initwinsign();
}
config.signObject=currSignObject;
}
wx.config({
debug: config.debug, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId:config.signObject.appid, // 必填,公众号的唯一标识
timestamp:config.signObject.timestamp, // 必填,生成签名的时间戳
nonceStr: config.signObject.noncestr, // 必填,生成签名的随机串
signature:config.signObject.signature,// 必填,签名,见附录1
jsApiList:config.jsApiList // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
wx.ready(function(){
//设置微信js-sdk初始化已完成
jqwx.isWeixinInitComplete=true;
hiddenButton();
config.onWxready();
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
}
$("#"+$id).click(onChooseClick);
}
function onChooseClick(){
//将参数置为初始化状态
localIds = null;
idx = 0;
serverIds='';
if(jqwx.isWeixinInitComplete){
wx.chooseImage({
count: config.size, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
localIds = res.localIds;//本地图片id数组,下标从0开始
//调用上传递归函数
if(config.wxdownloadurl!=""){
//禁用掉图片按钮和发布按钮
$("#"+$id).attr({"disabled":"disabled"});
config.onBefore();
wxUploadImg(localIds);
//$("#"+$id).removeAttr("disabled");//将按钮可用
//config.onComplete();
}else{
alert("请检查服务器微信图片下载url是否填写正确");
}
}
});
}else{
alert('微信接口正在初始化,请稍后重试!');
}
}
function wxUploadImg(localIds){
wx.uploadImage({//获取图片媒体ID
localId: localIds[idx].toString(), // 需要上传的图片的本地ID
isShowProgressTips: 0, // 默认为1,显示进度提示
success: function (res) {//获取成功
// 上传序号,上传一张 累计 +1
idx++
//存储图片媒体ID,用","号分割
serverIds+=res.serverId+',';
if(idx<localIds.length){//本地图片ID 还没全部获取完图片媒体ID
//调用上传递归函数
wxUploadImg(localIds);
}else{
//上传序号归零
idx=0;
//服务器csrf 验证字符串,如果后端框架没开启csrf,则不需要
//var csrf=$('meta[name="csrf-token"]').attr('content');
var sId=serverIds;
$.ajax({
url: config.wxdownloadurl,//服务器端根据图片媒体ID下载图片处理操作地址
type: 'POST',
async:false,
dataType: 'json',
data: {serverIds:serverIds},
}).done(function(data) {
alert("上传成功");
config.onSuccess(data,localIds,sId);
}).fail(function() {
//console.log("error");
}).always(function() {
//console.log("complete");
$("#"+$id).removeAttr("disabled");//将按钮可用
config.onComplete();
});
serverIds='';
return true;
}
},
fail: function(res){//获取多媒体id失败 返回错误代码
alert("上传失败,msg:"+JSON.stringify(res));
$("#"+$id).removeAttr("disabled");//将按钮可用
config.onComplete();
}
});
}
};
})(jQuery,wx);
2.jqking.main.js(可用于pc端图片任意位置插入jq.addRange、jq.insertImage方法)
(function(jqr_obj) {
var jquery = jqr_obj;
//注册命名空间jKing到window对象上
window['jKing'] = {};
//定义一个jKing函数
var version = "1.0.0";
jq = function(selector) {
// The jKing object is actually just the init constructor 'enhanced'
// Need init if jKing is called (just allow error to be thrown if not included)
return new jq.fn.init(selector);
};
//动态属性方法
jq.fn = jq.prototype = {
// The current version of jKing being used
jKing : version,
constructor : jq,
// Start with an empty selector
selector : "",
// The default length of a jKing object is 0
length : 0,
get : function() {
if (typeof this.selector === "string"
&& this.selector.length > 0) {
if (this.selector.startWith("#")) {
this.element = document.getElementById(this.selector);
return this;
} else if (this.selector.startWith(".")) {
var odiv = document.getElementsByTagName("*");
var a = [];
for ( var i = 0; i < odiv.length; i++) {
if (this.selector == "." + odiv[i].className) {
a[a.length] = odiv[i];
}
}
this.element = a;
return this;
}
}
}
};
//定义静态支持扩展方法
jq.extend = function(namespace, _o1) {
if (!arguments[1]) {
// 开始遍历
for ( var p in arguments[0]) {
// 方法
//console.info(_o1);
//console.info(p);
if (typeof (arguments[0][p]) == "function") {
jq[p] = arguments[0][p];
}
}
} else {
if (namespace && typeof (namespace) === "object") {
// 开始遍历
for ( var p in arguments[1]) {
// 方法
//console.info(_o1);
//console.info(p);
if (typeof (arguments[1][p]) == "function") {
namespace[p] = arguments[1][p];
}
}
}
}
};
jq.extend({//内部使用的方法
"nspace" : function(arr, _obj, i) {
if (i <= arr.length - 1) {
var obj;
if (typeof (_obj[arr[i]]) == "undefined") {
obj = _obj[arr[i]] = {};
} else if (_obj[arr[i]]
&& typeof (_obj[arr[i]]) == "object") {
obj = _obj[arr[i]];
}
//alert(i);
//_obj[arr[i]].b="1";
jq.nspace(arr, obj, i + 1);
} else {
//alert(arr.toString());
//alert(jq.json2str());
return;
}
}
});
jq.ns = function(namespace) {
var nsArray = new Array();
if (namespace && typeof (namespace) === "string") {
nsArray = namespace.split(".");
if (nsArray && nsArray.length > 0) {
jq.nspace(nsArray, jq, 1);
}
} else {
alert("命名空间必须是非空字符串!");
return;
}
}
init = jq.fn.init = function(selector) {
if (!selector) {
return this;
}
if (typeof selector === "string" && selector.length > 0) {
this.selector = selector;
this.length = selector.length;
return this;
}
};
init.prototype = jq.fn;
//动态的load module
jKing.load = function(_o1) {
for ( var p in _o1) {
if (typeof (_o1[p]) == "function") {
window['jKing'][p] = _o1[p];
}
}
};
/*
* addEventListener:监听Dom元素的事件
*
* target:监听对象
* type:监听函数类型,如click,mouseover
* func:监听函数
*/
jq.extend({
"addEventHandler" : function(target, type, callback) {
if (target.addEventListener) {
//监听IE9,谷歌和火狐
target.addEventListener(type, callback, false);
} else if (target.attachEvent) {
target.attachEvent("on" + type, callback);
} else {
target["on" + type] = callback;
}
}
});
/*
* removeEventHandler:移除Dom元素的事件
*
* target:监听对象
* type:监听函数类型,如click,mouseover
* func:监听函数
*/
jq.extend({
"removeEventHandler" : function(target, type, callback) {
if (target.removeEventListener) {
//监听IE9,谷歌和火狐
target.removeEventListener(type, callback, false);
} else if (target.detachEvent) {
target.detachEvent("on" + type, callback);
} else {
delete target["on" + type];
}
}
});
String.prototype.startWith = function(compareStr) {
return this.indexOf(compareStr) == 0;
}
/*停止冒事件*/
jq.stopEvent = function(event) {
var e = event || window.event;
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
};
//Json对象转字符串的方法
jq.json2str = function(obj) {
var s = [];
for ( var i in obj) {
obj[i] = typeof obj[i] == 'string' ? '"' + obj[i] + '"'
: (typeof obj[i] == 'object' ? jq.json2str(obj[i])
: obj[i]);
s.push(i + ':' + obj[i]);
}
return '{' + s.join(',') + '}';
}
//将对象转换成字符串的方法
jq.objConvertStr = function(o) {
if (o == undefined) {
return "";
}
var r = [];
if (typeof o == "string")
return "\""
+ o.replace(/([\"\\])/g, "\\$1")
.replace(/(\n)/g, "\\n")
.replace(/(\r)/g, "\\r")
.replace(/(\t)/g, "\\t") + "\"";
if (typeof o == "object") {
if (!o.sort) {
for ( var i in o)
r.push("\"" + i + "\":" + jq.objConvertStr(o[i]));
if (!!document.all
&& !/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/
.test(o.toString)) {
r.push("toString:" + o.toString.toString());
}
r = "{" + r.join() + "}"
} else {
for ( var i = 0; i < o.length; i++)
r.push(jq.objConvertStr(o[i]))
r = "[" + r.join() + "]";
}
return r;
}
return o.toString().replace(/\"\:/g, '":""');
}
//将from表单序列化
jq.serializeObject = function(formId) {
var form = $("#" + formId);
var o = {};
$.each(form.serializeArray(), function(index) {
if (o[this['name']]) {
o[this['name']] = o[this['name']] + "," + this['value'];
} else {
o[this['name']] = this['value'];
}
});
return o;
};
//将对象填入到表单中
jq.objectToForm = function setValue(obj, formId) {
// 开始遍历
for ( var p in obj) {
// 方法
if (typeof (obj[p]) == "function") {
obj[p]();
} else {
//console.log(document.getElementById("aa").getAttribute("field"));
//console.log($("#aa").attr("value"));
//console.log($("#admin_user_searchForm > #aa").get());
var field = $("#" + formId + " > #field_" + p);
if (field && field.attr("field")) {
field.val(obj[p]);
}
//p 为属性名称,obj[p]为对应属性的值
}
}
};
jq.insertImage =function(contentId,src) {
document.getElementById(contentId).focus();
var selection = window.getSelection ? window.getSelection() : document.selection;
var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0);
if (!window.getSelection) {
range.pasteHTML(src);
range.collapse(false);
range.select();
} else {
range.collapse(false);
var hasR = range.createContextualFragment(src);
var hasLastChild = hasR.lastChild;
while (hasLastChild && hasLastChild.nodeName.toLowerCase() == "br" && hasLastChild.previousSibling && hasLastChild.previousSibling.nodeName.toLowerCase() == "br") {
var e = hasLastChild;
hasLastChild = hasLastChild.previousSibling;
hasR.removeChild(e);
}
//range.insertNode(range.createContextualFragment("<p><br></p>"));
range.insertNode(hasR);
if (hasLastChild) {
range.setEndAfter(hasLastChild);
range.setStartAfter(hasLastChild);
}
selection.removeAllRanges();
selection.addRange(range);
}
}
jq.addRange=function (o){
var event = window.event || arguments.callee.caller.arguments[0];
//target 就是这个对象
var target = event.srcElement||event.target;
var sel, range;
//var content = $("#"+o)[0].innerHTML;
// $("#bbsContent_div")[0].innerHTML=content+"</br><p> </p>";
document.getElementById(o).focus();
if (window.getSelection) {
range = document.createRange();
sel = window.getSelection();
//if (sel.getRangeAt && sel.rangeCount) {
//range.selectNodeContents(target);
//range.collapse(true);
//range = sel.getRangeAt(0);
//range.deleteContents();
// range = range.cloneRange();
range.setStartAfter(target);
range.collapse(true);
document.getElementById(o).focus();
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
// }
} else if (document.selection && document.selection.type != "Control") {
alert('浏览器不支持');
// IE < 9
//document.selection.createRange().pasteHTML(html);
}
}
//把jq函数注册到jKing命名空间中
window['jKing']['$'] = jq;
window['jKing']['jq'] = jquery;
//window['jKing']['load']=jKing.load;
})(jQuery);
效果图如下: