JavaScript插件化开发教程(四)
一,开篇分析
Hi,还记得上一篇文章吗。主要讲述了一个“Tab”插件是如何组织代码以及实现的”,以及过程化设计与面向对象思想设计相结合的方式是
如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式。在从这篇文章中,我们还是以那个“Tab”实例为主,
继续扩展相关功能。嘿嘿嘿,废话少说,进入正题。直接上实际效果图:
大家看到了吧,增加了一个新的功能,如果我们在初始化时,我们的模块配置信息项目的条目数大于我们指定的,那么就会显示在“更多模块”
操作项的隐藏列表中,我们的初始化参数配置也从新做了调整比如多了一个“displayMax”指定初始化时的条目数,还有一个项目属性,“status”
在初始化时也去掉了不需要配置了,在程序中动态生成配置,增加了程序的灵活性,下面就具体分析一下吧。
(二),实例分析
(1),首先确定这个插件做什么事。下面看一下插件的调用方式,以及配置参数说明。如下代码:
{
buttonText:"添加模块",
result:[
{
text:"向导提示",
url:"help.html",
showClose:"0"
},
{
text:"学生信息",
url:"info.html",
showClose:"1"
},
{
text:"学生分类",
url:"category.html",
showClose:"1"
},
{
text:"大熊君{{bb}}",
url:"bb.html",
showClose:"1"
},
{
text:"Beta测试模块",
url:"test.html",
showClose:"1"
},
{
text:"三胖子",
url:"help.html",
showClose:"1"
},
{
text:"四秃子",
url:"help.html",
showClose:"1"
}
],
displayMax:5//最多显示项目
}
“bigbear.ui.createTab”里面包含两个参数,第一个是dom节点对象,第二个是插件参数选项,"buttonText"代表“Tab“插件中,操作按钮的文字描述。
”result“是一个数组,里面包含的是选项卡项目的属性,包括文字描述,点击选项卡项目时做请求使用的url,”showClose“代表选项卡的选项是否显示关闭按钮。
“status”在初始化时也去掉了不需要配置了,在程序中动态生成配置。可能会有关闭状态,分别表示为:1-默认显示,0-关闭状态,2-超过默认的条目数。
(2),功能分步骤介绍
1---,通过可选参数,初始化插件:
$(function(){
bigbear.ui.createTab($("#tab"),{
buttonText:"添加模块",
result:[
{
text:"向导提示",
url:"help.html",
showClose:"0"
},
{
text:"学生信息",
url:"info.html",
showClose:"1"
},
{
text:"学生分类",
url:"category.html",
showClose:"1"
},
{
text:"大熊君{{bb}}",
url:"bb.html",
showClose:"1"
},
{
text:"Beta测试模块",
url:"test.html",
showClose:"1"
},
{
text:"三胖子",
url:"help.html",
showClose:"1"
},
{
text:"四秃子",
url:"help.html",
showClose:"1"
}
],
displayMax:5//最多显示项目
});
});
2---,渲染并且完成时间绑定以及相关的业务逻辑,比如初始化时条目数量验证。
3---,选项卡切换以及数据内容渲染操作。 4---,核心的辅助数据操作方法,不涉及dom。 (三),完整代码以供学习,本代码已经过测试,包括目录结构以及相关的文件。 1,html 2,css 3,bigbear.js (四),最后总结 (1),面向对象的思考方式合理分析功能需求。 (2),以类的方式来组织我们的插件逻辑。 (3),不断重构上面的实例,如何进行合理的重构那?不要设计过度,要游刃有余,推荐的方式是过程化设计与面向对象思想设计相结合。
tabProto.init=function(){
if(this._isEmptyResult()){
this._setContent("暂无任何模块!");
}
varthat=this;
this.getElem().find(".title.adder")
.text("+"+this.getOpts()["buttonText"])
.on("click",function(){
that.getElem().find(".console-panel").slideToggle(function(){
that._renderConsolePanel("0");
});
});
$.each(this.getOpts()["result"],function(i,item){
if(that._isDisplayMax(i+1)){
that._saveOrUpdateStatus(item,"1");
}
else{
that._saveOrUpdateStatus(item,"2");
}
that._render(item);
});
if(!that._isDisplayMax(this.getOpts()["result"].length)){
this.getElem().find(".title.more-mod").fadeIn(function(){
$(this).find(".tag").on("click",function(){
varroot=$(this).next();
root.empty();
$.each(that._getItemListByStatus("2"),function(i,data){
$("<div></div>").text(data["text"])
.on("click",function(){
if(that._getItemListByStatus("1").length<that.getOpts()["displayMax"]){
that.getElem().find(".title.itemsdiv").eq(data["index"]).fadeIn(function(){
that._saveOrUpdateStatus(data,"1");
});
}
else{
alert("不能添加任何模块,目前已经是最大数量!");
}
})
.appendTo(root);
});
root.toggle();
});
});
}
this.getElem().find(".title.itemsdiv")
.eq(0)
.trigger("click");//假定是必须有一项,否则插件意义就不大了!
};
tabProto._setCurrent=function(index){
varitems=this.getElem().find(".title.itemsdiv").removeClass("active");
items.eq(index).addClass("active");
varcontents=this.getElem().find(".content.c").hide();
contents.eq(index).show();
};
item.on("click",function(){
that._setCurrent($(this).index());
that._getContent(data["url"]).done(function(result){
that._setContent(result);
})
.fail(function(){
thrownewError("NetError!");
});
})
tabProto._setContent=function(html){
this.getElem().find(".content").html(html);
};
tabProto._getContent=function(url){
return$.ajax({
url:url
});
};
/*updatetime20151/2615:36*/
tabProto._isDisplayMax=function(size){
vardisplayMax=this.getOpts()["displayMax"]||5;
return(size<=displayMax)?true:false;
};
tabProto._isEmptyResult=function(){
if(!this.getOpts()["result"].length){
returnfalse;
}
returntrue;
};
tabProto._saveOrUpdateStatus=function(item,status){
item["status"]=status;
};
tabProto._getItemListByStatus=function(status){
varlist=[];
varresult=this.getOpts()["result"];
$.each(result,function(i,item){
if(status==item["status"]){
list.push(item);
}
});
returnlist;
};
tabProto._getStatusByIndex=function(index){
varstatus=null;
varresult=this.getOpts()["result"];
$.each(result,function(i,item){
if(index==item["index"]){
status=item["status"];
}
});
returnstatus;
};
<body>
<divclass="dxj-ui-hd">
大熊君{{bb}}-DXJUI------Tab
</div>
<divclass="dxj-ui-bd">
<divid="tab">
<divclass="title">
<divclass="adder">
+添加学生信息
</div>
<divclass="items">
<!--<div><spanclass="del">X</span>欢迎页</div>
<div><spanclass="del">X</span>用户管理</div>
<div><spanclass="del">X</span>Bigbear</div>-->
</div>
<divclass="more-mod">
<divclass="tag">更多模块</div>
<divclass="mods">
</div>
</div>
</div>
<divclass="console-panel">
</div>
<divclass="content">
<!--<divclass="c">
<divclass="input-content"><span>姓名:</span><inputtype="text"/></div>
<divclass="input-content"><span>备注:</span><textarea></textarea></div>
</div> <divclass="input-content"><inputtype="button"value="保存"/></div>
-->
</div>
</div>
</div>
</body>
.dxj-ui-hd{
padding:0px;
margin:0auto;
margin-top:30px;
width:780px;
height:60px;
line-height:60px;
background:#3385ff;
color:#fff;
font-family:"微软雅黑";
font-size:28px;
text-align:center;
font-weight:bold;
}
.dxj-ui-bd{
padding:0px;
margin:0auto;
width:778px;
padding-top:30px;
padding-bottom:30px;
overflow:hidden;
border:1pxsolid#3385ff;
}
.dxj-ui-bd#tab{
padding:0px;
margin:0auto;
width:720px;
overflow:hidden;
position:relative;
}
.dxj-ui-bd#tab.title{
width:720px;
overflow:hidden;
border-bottom:2pxsolid#3385ff;
}
.dxj-ui-bd#tab.title.adder{
width:160px;
height:32px;
line-height:32px;
background:#DC143C;
color:#fff;
font-family:"微软雅黑";
font-size:14px;
text-align:center;
font-weight:bold;
float:left;
cursor:pointer;
}
.dxj-ui-bd#tab.title.more-mod{
overflow:hidden;
border:1pxsolid#DC143C;
width:70px;
position:absolute;
right:0;
margin-right:6px;
display:none;
}
.dxj-ui-bd#tab.title.more-mod.tag{
height:32px;
line-height:32px;
width:70px;
background:#DC143C;
color:#fff;
font-family:arial;
font-size:12px;
text-align:center;
cursor:pointer;
}
.dxj-ui-bd#tab.title.more-mod.mods{
overflow:hidden;
width:70px;
display:none;
}
.dxj-ui-bd#tab.title.more-mod.modsdiv{
height:24px;
line-height:24px;
width:62px;
font-family:arial;
font-size:12px;
cursor:pointer;
padding-left:10px;
}
.dxj-ui-bd#tab.title.items{
height:32px;
width:480px;
overflow:hidden;
float:left;
}
.dxj-ui-bd#tab.title.itemsdiv{
padding:0px;
margin-left:10px;
width:84px;
height:32px;
line-height:32px;
background:#3385ff;
color:#fff;
font-family:arial;
font-size:12px;
text-align:center;
position:relative;
float:left;
cursor:pointer;
}
.dxj-ui-bd#tab.title.itemsdivspan.del{
width:16px;
height:16px;
line-height:16px;
display:block;
background:#DC143C;
position:absolute;
right:0;
top:0;
cursor:pointer;
}
.dxj-ui-bd#tab.content{
width:716px;
padding-top:30px;
overflow:hidden;
border:2pxsolid#3385ff;
border-top:0px;
min-height:130px;
text-align:center;
}
.dxj-ui-bd#tab.contenttable{
margin:0auto;
}
.dxj-ui-bd#tab.contentdiv.c{
padding-top:20px;
padding-left:20px;
background:#eee;
height:140px;
}
.dxj-ui-bd#tab.contentdiv.c.input-content{
margin-top:10px;
font-family:arial;
font-size:12px;
}
.dxj-ui-bd#tab.console-panel{
width:716px;
padding-top:20px;
padding-bottom:20px;
overflow:hidden;
border:2pxsolid#3385ff;
border-top:0px;
border-bottom:2pxsolid#3385ff;
background:#fff;
display:none;
}
.active{
font-weight:bold;
}
(function($){
varwin=window;
varbb=win.bigbear=win.bigbear||{
ui:{}
};
varui=bb.ui={};
varTab=function(elem,opts){
this.elem=elem;
this.opts=opts;
};
vartabProto=Tab.prototype;
/*updatetime20151/2615:36*/
tabProto._isDisplayMax=function(size){
vardisplayMax=this.getOpts()["displayMax"]||5;
return(size<=displayMax)?true:false;
};
tabProto._isEmptyResult=function(){
if(!this.getOpts()["result"].length){
returnfalse;
}
returntrue;
};
tabProto._saveOrUpdateStatus=function(item,status){
item["status"]=status;
};
tabProto._getItemListByStatus=function(status){
varlist=[];
varresult=this.getOpts()["result"];
$.each(result,function(i,item){
if(status==item["status"]){
list.push(item);
}
});
returnlist;
};
tabProto._getStatusByIndex=function(index){
varstatus=null;
varresult=this.getOpts()["result"];
$.each(result,function(i,item){
if(index==item["index"]){
status=item["status"];
}
});
returnstatus;
};
tabProto._renderConsolePanel=function(status){
varthat=this;
varroot=that.getElem().find(".console-panel");
this._resetConsolePanel();
$.each(that._getItemListByStatus(status),function(i,item){
varelem=$("<divstyle="float:left";></div>").appendTo(root);
$("<inputtype="radio"name="addmod"/>")
.data("item",item)
.appendTo(elem);
$("<span></span>").text(item["text"]).appendTo(elem);
});
if(root.find("div").size()){
$("<inputtype="button"value="添加模块"style="margin-left:20px"/>")
.on("click",function(){
vardata=root.find("input[type=radio]:checked").data("item");
if(that._getItemListByStatus("1").length<that.getOpts()["displayMax"]){
that.getElem().find(".title.itemsdiv").eq(data["index"]).fadeIn(function(){
that._saveOrUpdateStatus(data,"1");
})
.trigger("click");
}
else{
that._saveOrUpdateStatus(data,"2");
}
that.getElem().find(".title.adder").trigger("click");
})
.appendTo(root);
}
else{
root.text("暂无任何可添加的项目!");
}
};
/*updatetime20151/2615:36*/
tabProto._setCurrent=function(index){
varitems=this.getElem().find(".title.itemsdiv").removeClass("active");
items.eq(index).addClass("active");
varcontents=this.getElem().find(".content.c").hide();
contents.eq(index).show();
};
tabProto.getElem=function(){
returnthis.elem;
};
tabProto.getOpts=function(){
returnthis.opts;
};
tabProto._resetContent=function(){
this.getElem().find(".content").html("");
};
tabProto._setContent=function(html){
this.getElem().find(".content").html(html);
};
tabProto._getContent=function(url){
return$.ajax({
url:url
});
};
tabProto._deleteItem=function(elem){
varthat=this;
this.getElem().find(".title.itemsdiv")
.eq(elem.index())
.fadeOut(function(){
that._resetContent();
that._saveOrUpdateStatus(elem.data("item"),"0");
that._triggerItem(elem.index()+1);
});
};
tabProto._triggerItem=function(next){
varnextStatus=this._getStatusByIndex(next);
varitems=this.getElem().find(".title.itemsdiv");
next=items.eq(next);
if(next.size()&&"1"==nextStatus){//后继dom节点存在
next.trigger("click");
}
else{
items.eq(0).trigger("click");
}
};
tabProto._resetConsolePanel=function(){
this.getElem().find(".console-panel").empty();
};
tabProto.init=function(){
if(this._isEmptyResult()){
this._setContent("暂无任何模块!");
}
varthat=this;
this.getElem().find(".title.adder")
.text("+"+this.getOpts()["buttonText"])
.on("click",function(){
that.getElem().find(".console-panel").slideToggle(function(){
that._renderConsolePanel("0");
});
});
$.each(this.getOpts()["result"],function(i,item){
if(that._isDisplayMax(i+1)){
that._saveOrUpdateStatus(item,"1");
}
else{
that._saveOrUpdateStatus(item,"2");
}
that._render(item);
});
if(!that._isDisplayMax(this.getOpts()["result"].length)){
this.getElem().find(".title.more-mod").fadeIn(function(){
$(this).find(".tag").on("click",function(){
varroot=$(this).next();
root.empty();
$.each(that._getItemListByStatus("2"),function(i,data){
$("<div></div>").text(data["text"])
.on("click",function(){
if(that._getItemListByStatus("1").length<that.getOpts()["displayMax"]){
that.getElem().find(".title.itemsdiv").eq(data["index"]).fadeIn(function(){
that._saveOrUpdateStatus(data,"1");
});
}
else{
alert("不能添加任何模块,目前已经是最大数量!");
}
})
.appendTo(root);
});
root.toggle();
});
});
}
this.getElem().find(".title.itemsdiv")
.eq(0)
.trigger("click");//假定是必须有一项,否则插件意义就不大了!
};
tabProto._render=function(data){
varthat=this;
varitem=$("<div></div>").text(data["text"]).appendTo(this.getElem().find(".title.items"));
data["index"]=item.index();
item.on("click",function(){
that._setCurrent($(this).index());
that._getContent(data["url"]).done(function(result){
that._setContent(result);
})
.fail(function(){
thrownewError("NetError!");
});
})
.data("item",data);
if("2"==data["status"]){
item.hide();
}
if("1"==data["showClose"]){
$("<spanclass="del">X</span>")
.on("click",function(){
if(win.confirm("是否删除此项?")){
that._deleteItem(item);
returnfalse;//阻止冒泡
}
})
.appendTo(item);
}
};
ui.createTab=function(elem,opts){
vartab=newTab(elem,opts);
tab.init();
returntab;
};
})(jQuery);
相关文章