大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ Tab)

一,开篇分析

Hi,大家好!大熊君又和大家见面了,还记得前两篇文章吗。主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是

如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式。那么今天从这篇文章开始,我们就以实例

的方式带着大家由浅入深的开发属于自己的插件库。嘿嘿嘿,废话少说,进入正题。直接上实际效果图:

  

  大家看到了吧,这是一个选项卡插件,在我们日常做那种单页应用("SPA")的时候或许会接触到,就拿今天的例子来说吧,

我们做一个基于BS结构的系统,会有若干模块组成,它们是构建系统的全部组成,通过这个插件我们可以有效地管理我们模块

的体验形式以及用户可交互性,下面就具体分析一下吧。

(二),实例分析

  (1),首先确定这个插件做什么事。下面看一下插件的调用方式,以及配置参数说明。如下代码:

 1 bigbear.ui.createTab($("#tab"),{
 2     buttonText : "添加模块" ,
 3     result : [
 4         {
 5             text : "向导提示" ,
 6             url : "help.html" ,
 7             showClose : "0" ,
 8             status : "1"
 9         } ,
10         {
11             text : "学生信息" ,
12             url : "info.html" ,
13             showClose : "1" ,
14             status : "1"
15         } ,
16         {
17             text : "学生分类" ,
18             url : "category.html" ,
19             showClose : "1" ,
20             status : "1"
21         } ,
22         {
23             text : "大熊君{{bb}}" ,
24             url : "bb.html" ,
25             showClose : "1" ,
26             status : "1"
27         } ,
28         {
29             text : "Beta测试模块" ,
30             url : "test.html" ,
31             showClose : "1" ,
32             status : "1"
33         }
34     ]
35 }) ;

“bigbear.ui.createTab”里面包含两个参数,第一个是dom节点对象,第二个是插件参数选项,"buttonText "代表“Tab“插件中,操作按钮的文字描述。

”result“是一个数组,里面包含的是选项卡项目的属性,包括文字描述,点击选项卡项目时做请求使用的url,”showClose“代表选项卡的选项是否显示关闭按钮。

”status“代表选项的状态,默认为打开状态,可能会有关闭状态,分别表示为:1-打开,0-关闭。

(2),所涉的功能有哪些

通过可选参数,动态生成相关选项条目,如下来个例子:

  

 1 bigbear.ui.createTab($("#tab"),{
 2     buttonText : "添加模块" ,
 3     result : [
 4         {
 5             text : "jQuery源码分析" ,
 6             url : "help.html" ,
 7             showClose : "0" ,
 8             status : "1"
 9         } ,
10         {
11             text : "大熊君{{bb}}}" ,
12             url : "bb.html" ,
13             showClose : "1" ,
14             status : "1"
15         }
16     ]
17 }) ;

效果如下所示:

可自由添加以及删除条目选项,如下效果所示:

  

上图为其中一种情况,无模块的时候,会提示信息。

这是第二种情况,之前删除的可以恢复。

(三),完整代码以供学习,本代码已经过测试,包括目录结构以及相关的文件。

  (1),html

    

 1 <body>
 2         <div class="dxj-ui-hd">
 3             大熊君{{bb}} - DXJ UI ------ Tab
 4         </div>
 5         <div class="dxj-ui-bd">
 6             <div id="tab">
 7                 <div class="title">
 8                     <div class="adder">
 9                         + 添加学生信息
10                     </div>
11                     <div class="items">
12                         <!--<div><span class="del">X</span>欢迎页</div>
13                         <div><span class="del">X</span>用户管理</div>
14                         <div><span class="del">X</span>Bigbear</div>-->
15                     </div>
16                 </div>
17                 <div class="console-panel">
18
19                 </div>
20                 <div class="content">
21                     <!--<div class="c">
22
23                         <div class="input-content"><span>姓名:</span><input type="text" /></div>
24                         <div class="input-content"><span>备注:</span><textarea></textarea></div>
25
26                     </div>    <div class="input-content"><input type="button" value="保存" /></div>
27                     -->
28                 </div>
29             </div>
30         </div>
31     </body>

(2),css文件代码

  

  1 .dxj-ui-hd {
  2     padding:0px ;
  3     margin : 0 auto;
  4     margin-top:30px;
  5     width:780px;
  6     height:60px;
  7     line-height: 60px;
  8     background: #3385ff;
  9     color:#fff;
 10     font-family: "微软雅黑" ;
 11     font-size: 28px;
 12     text-align: center;
 13     font-weight:bold;
 14 }
 15 .dxj-ui-bd {
 16     padding:0px ;
 17     margin : 0 auto;
 18     width:778px;
 19     padding-top : 30px ;
 20     padding-bottom : 30px ;
 21     overflow: hidden;
 22     border:1px solid #3385ff;
 23 }
 24 .dxj-ui-bd #tab {
 25     padding:0px ;
 26     margin : 0 auto;
 27     width:720px;
 28     overflow: hidden;
 29 }
 30 .dxj-ui-bd #tab .title {
 31     width:720px;
 32     overflow: hidden;
 33     border-bottom:2px solid #3385ff;
 34 }
 35 .dxj-ui-bd #tab .title .adder {
 36     width:160px;
 37     height:32px;
 38     line-height: 32px;
 39     background: #DC143C;
 40     color:#fff;
 41     font-family: "微软雅黑" ;
 42     font-size: 14px;
 43     text-align: center;
 44     font-weight:bold;
 45     float : left;
 46     cursor:pointer;
 47 }
 48 .dxj-ui-bd #tab .title .items {
 49     height:32px;
 50     margin-left:20px;
 51     width:540px;
 52     overflow: hidden;
 53     float : left;
 54 }
 55 .dxj-ui-bd #tab .title .items div {
 56     padding:0px;
 57     margin-left:10px;
 58     width:96px;
 59     height:32px;
 60     line-height: 32px;
 61     background: #3385ff;
 62     color:#fff;
 63     font-family: arial ;
 64     font-size: 12px;
 65     text-align: center;
 66     position:relative;
 67     float : left;
 68     cursor:pointer;
 69 }
 70 .dxj-ui-bd #tab .title .items div span.del {
 71     width:16px;
 72     height:16px;
 73     line-height: 16px;
 74     display:block;
 75     background: #DC143C;
 76     position:absolute;
 77     right:0 ;
 78     top:0;
 79     cursor:pointer;
 80 }
 81 .dxj-ui-bd #tab .content {
 82     width:716px;
 83     padding-top:30px;
 84     overflow: hidden;
 85     border:2px solid #3385ff;
 86     border-top:0px;
 87     min-height:130px;
 88     text-align:center;
 89 }
 90 .dxj-ui-bd #tab .content table {
 91     margin : 0 auto ;
 92 }
 93 .dxj-ui-bd #tab .content div.c {
 94     padding-top : 20px ;
 95     padding-left:20px;
 96     background:#eee;
 97     height:140px;
 98 }
 99 .dxj-ui-bd #tab .content div.c .input-content {
100     margin-top : 10px ;
101     font-family: arial ;
102     font-size: 12px;
103 }
104 .dxj-ui-bd #tab .console-panel {
105     width:716px;
106     padding-top:20px;
107     padding-bottom:20px;
108     overflow: hidden;
109     border:2px solid #3385ff;
110     border-top:0px;
111     border-bottom:2px solid #3385ff;
112     background:#fff;
113     display:none;
114 }
115 .active {
116     font-weight:bold ;
117 }

(3),Js代码如下:

  

  1 $(function(){
  2     bigbear.ui.createTab($("#tab"),{
  3         buttonText : "添加模块" ,
  4         result : [
  5             {
  6                 text : "向导提示" ,
  7                 url : "help.html" ,
  8                 showClose : "0" ,
  9                 status : "1"
 10             } ,
 11             {
 12                 text : "学生信息" ,
 13                 url : "info.html" ,
 14                 showClose : "1" ,
 15                 status : "1"
 16             } ,
 17             {
 18                 text : "学生分类" ,
 19                 url : "category.html" ,
 20                 showClose : "1" ,
 21                 status : "1"
 22             } ,
 23             {
 24                 text : "大熊君{{bb}}" ,
 25                 url : "bb.html" ,
 26                 showClose : "1" ,
 27                 status : "1"
 28             } ,
 29             {
 30                 text : "Beta测试模块" ,
 31                 url : "test.html" ,
 32                 showClose : "1" ,
 33                 status : "1"
 34             }
 35         ]
 36     }) ;
 37 }) ;
 38 (function($){
 39     var win = window ;
 40     var bb = win.bigbear = win.bigbear || {
 41         ui : {}
 42     } ;
 43     var ui = bb.ui = {} ;
 44     var Tab = function(elem,opts){
 45         this.elem = elem ;
 46         this.opts = opts ;
 47     } ;
 48     var tabProto = Tab.prototype ;
 49     tabProto._deleteItem = function(item){
 50         var that = this ;
 51         this.getElem().find(".title .items div")
 52         .eq(item["index"])
 53         .fadeOut(function(){
 54             that._resetContent() ;
 55             that._updateStatus(item) ;
 56             that._triggerItem(item["index"] + 1) ;
 57             that.getElem().find(".title .adder").trigger("click") ;
 58         }) ;
 59     } ;
 60     tabProto._triggerItem = function(next){
 61         var nextStatus = this._getStatus(next) ;
 62         var items = this.getElem().find(".title .items div") ;
 63         next = items.eq(next) ;
 64         if(next.size() && "1" == nextStatus){ //后继dom节点存在
 65             next.trigger("click") ;
 66         }
 67         else{
 68             items.eq(0).trigger("click") ;
 69         }
 70     } ;
 71     tabProto._getStatus = function(index){
 72         var status = "" ;
 73         $.each(this.getOpts()["result"],function(i,item){
 74             if(index == item["index"]){
 75                 status += item["status"] ;
 76                 return false ;
 77             }
 78         }) ;
 79         return status ;
 80     } ;
 81     tabProto._updateStatus = function(item){
 82         var status = item["status"] ;
 83         item["status"] = ("1" == status) ? "0" : "1" ;
 84     } ;
 85     tabProto.init = function(){
 86         var that = this ;
 87         this.getElem().find(".title .adder")
 88         .text("+" + this.getOpts()["buttonText"])
 89         .on("click",function(){
 90             that._toggleConsolePanel(function(){
 91                 var root = that.getElem().find(".console-panel").empty() ;
 92                 $.each(that.getOpts()["result"],function(i,item){
 93                     if("0" == item["status"]){
 94                         var elem = $("<div style=‘float:left‘;></div>")
 95                         .data("item",item)
 96                         .appendTo(root) ;
 97                         $("<input type=‘radio‘ name=‘addmod‘ />").appendTo(elem) ;
 98                         $("<span></span>").text(item["text"]).appendTo(elem) ;
 99                     }
100                 }) ;
101                 if(root.find("div").size()){
102                     $("<input type=‘button‘ value=‘添加模块‘ style=‘margin-left:20px‘/>")
103                     .on("click",function(){
104                         var data = root.find("input[type=radio]:checked").parent().data("item") ;
105                         that._updateStatus(data) ;
106                         that.getElem().find(".title .items div").eq(data["index"]).fadeIn().trigger("click") ;
107                         that.getElem().find(".title .adder").trigger("click") ;
108                     })
109                     .appendTo(root) ;
110                 }
111                 else{
112                     root.text("暂无任何可添加的项目!") ;
113                 }
114             }) ;
115         }) ;
116         $.each(this.getOpts()["result"],function(i,item){
117             item["index"] = i ;
118             that._render(item) ;
119         }) ;
120         this.getElem().find(".title .items div")
121         .eq(0)
122         .trigger("click") ; // 假定是必须有一项,否则插件意义就不大了!
123     } ;
124     tabProto._toggleConsolePanel = function(callback){
125         this.getElem().find(".console-panel").slideToggle(function(){
126             $.isFunction(callback) && callback() ;
127         }) ;
128     } ;
129     tabProto._resetContent = function(){
130         this.getElem().find(".content").html("") ;
131     } ;
132     tabProto._setContent = function(html){
133         this.getElem().find(".content").html(html) ;
134     } ;
135     tabProto._getContent = function(url){
136         return $.ajax({
137             url : url
138         }) ;
139     } ;
140     tabProto._render = function(data){
141         var that = this ;
142         var item = $("<div></div>")
143         .text(data["text"])
144         .on("click",function(){
145             that._setCurrent(data["index"]) ;
146             that._getContent(data["url"]).done(function(result){
147                 that._setContent(result) ;
148             })
149             .fail(function(){
150                 throw new Error("Net Error !") ;
151             });
152         })
153         .appendTo(this.getElem().find(".title .items")) ;
154         if("1" == data["showClose"]){
155             $("<span class=‘del‘>X</span>")
156             .on("click",function(){
157                 if(win.confirm("是否删除此项?")){
158                     that._deleteItem(data) ;
159                     return false ; // 阻止冒泡
160                 }
161             })
162             .appendTo(item) ;
163         }
164     } ;
165     tabProto._setCurrent = function(index){
166         var items = this.getElem().find(".title .items div").removeClass("active") ;
167         items.eq(index).addClass("active") ;
168         var contents = this.getElem().find(".content .c").hide() ;
169         contents.eq(index).show() ;
170     } ;
171     tabProto.getElem = function(){
172         return this.elem ;
173     } ;
174     tabProto.getOpts = function(){
175         return this.opts ;
176     } ;
177     ui.createTab = function(elem,opts){
178         var tab = new Tab(elem,opts) ;
179         tab.init() ;
180         return tab ;
181     } ;
182 })(jQuery) ;

(四),最后总结

  (1),面向对象的思考方式合理分析功能需求。

  (2),以类的方式来组织我们的插件逻辑。

  (3),不断重构上面的实例,如何进行合理的重构那?不要设计过度,要游刃有余,推荐的方式是过程化设计与面向对象思想设计相结合。

   (4),思考一下上面例子中,选项卡中的选项是否可以独立成单独的类那?比如“Item”,那么“Tab”类如何修改那?带着问题去思考吧。。。

                   哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)                       

时间: 2024-08-24 10:17:18

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ Tab)的相关文章

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ Tab功能扩展完结版)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得上一篇文章吗.主要讲述了一个“Tab”插件是如何组织代码以及实现的”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.在从这篇文章中,我们还是以那个“Tab”实例为主, 继续扩展相关功能.嘿嘿嘿,废话少说,进入正题.直接上实际效果图: 大家看到了吧,增加了一个新的功能,如果我们在初始化时,我们的模块配置信息项目的条目数大于我们指定的,那么

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得前两篇文章吗.主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.那么今天从这篇文章开始,我们就以实例 的方式带着大家由浅入深的开发属于自己的插件库.嘿嘿嘿,废话少说,进入正题.直接上实际效果图: 大家看到了吧,这是一个下拉菜单插件,在我们日常开发中,系统提供的可能有时让我们觉得不是很美观并且功

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector重构完结版)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得上一篇文章吗.主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.那么今天这篇文章我们说点什么那?嘿嘿嘿 .我们接着上篇文章对不足的地方进行重构,以深入浅出的方式来逐步分析,让大家有一个循序渐进提高的过程.废话少说,进入正题.让我们先来回顾一下之前的 Js部分的代码,如下: 1 function

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ProcessBar)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得前两篇文章吗.主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.那么今天从这篇文章开始,我们就以实例 的方式带着大家由浅入深的开发属于自己的插件库.嘿嘿嘿,废话少说,进入正题.直接上实际效果图: 大家看到了吧,这是一个进度条插件,在我们日常开发中,有时我们会有一个装载数据的进度提示,如果无任何

大熊君JavaScript插件化开发------(第一季)

一,开篇分析 Hi,大家!大熊君又来了,今天这系列文章主要是说说如何开发基于“JavaScript”的插件式开发,我想很多人对”插件“这个词并不陌生, 有的人可能叫“组件”或“部件”,这不重要,关键是看如何设计,如何做一个全方位的考量,这是本文的重点阐述的概念.我想大家对 “jQuery插件的方式”有一定的了解,我们结合这个话题一起讨论一下,最终给出相关的实现方案,来不断提高自己的谁能力.   二,进入插件正题 一般来说,jQuery插件的开发分为两种:一种是挂在jQuery命名空间下的全局函数

Asp.Net MVC 插件化开发简化方案

Web 管理系统可以庞大到不可想像的地方,如果想就在一个 Asp.Net MVC 项目中完成开发,这个工程将会变得非常庞大,协作起来也会比较困难.为了解决这个问题,Asp.Net MVC 引入了 Areas 的概念,将模块划分到 Area 中去--然而 Area 仍然是主项目的一部分,多人协作的时候仍然很容易造成 .csproj 项目文件的冲突. 对于这类系统,比较好的解决办法是采用 SOA 的方式,把一个大的 Web 系统划分成若干微服务,通过一个含授权中心的 Web 集散框架组织起来.不过这

Android插件化开发---运行未安装apk中的Service

如果你还不知道什么叫插件化开发,那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从整体角度分析了一下Android插件化开发的几个难点与动态加载没有被安装的apk中的Activity和资源的方法.其实一般的插件开发主要也就是加载个Activity,读取一些资源图片之类的.但是总有遇到特殊情况的时候,比如加载Service. 要动态加载Service,有两种思路:一是通过NDK的形式,将Service通过C++运行起来(这种方法我没有尝试,只听群里的朋友说实现

Android 使用动态加载框架DL进行插件化开发

如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456    (来自时之沙的csdn博客) 概述: 随着应用的不断迭代,应用的体积不断增大,项目越来越臃肿,冗余增加.项目新功能的添加,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,只能紧急发布补丁版本,强制用户进行更新.结果频繁的更新,反而容易降低用户使用黏性.或者是公司业务的不断发展,同系的应用越来越多,传统方式需要通过用户量最大的主项目进行引导下载并安装. 怎么办?参考浏览器-插件开发模式: 一.

Android插件化开发,初入殿堂

好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架CJFrameForAndroid. 好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架CJFrameForAndroid. 背景交代 首先,你需要知道什么是插件化开发.就拿最常见的QQ来说,在第三个界面动态那里有个管理,点开后可以选择很多的增植功能,这里腾讯只放了一些网页应用,那么如果未来想加入一个打飞机游戏,要怎么做?让用户重新安装吗,这就是插件化开发所解决的问题. 用一句话来概括插