我的开源框架之TAB控件

需求

(1)支持iframe、html、json格式的tab内容远程请求

(2)支持动态添加tab

(3)支持远程加载完成监听,支持tab激活事件监听

(4)支持reload tab内容【如果是远程加载】

(5)支持邮件菜单【未实现】

实现图例

客户代码

 1 <body>
 2     <div id="text">
 3         <h3>无题</h3>
 4         <p>月落湖面两清影,</p>
 5         <p>岸柳丝丝弄轻盈。</p> 
 6         <p>此番凉意写不出,</p> 
 7         <p>难画秋月一片晴。</p> </div>
 8     <div style="padding-left:100px; padding-bottom:12px;">
 9         <div id="tabContainer" style="width:800px;height:260px">
10             <div title="静态html"  closable="true" >项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1项目1</div>
11             <div title="iframe加载" isiframe="true" url="/innerpage.html" iconcls="icon-edit" closable="true">
12             </div>
13             <div title="远程HTML加载"  dataType="html" url="/content.html" iconcls="icon-save" closable="true">
14             </div>
15         </div>
16     </div>
17     <script type="text/javascript">       
18         var tabs;
19         $(function () {
20             tabs = $("#tabContainer").tabs({
21                 items: [{
22                     title: '远程加载JSON数据',
23                     closable: false,
24                     iconcls: 'icon-print',
25                     actived: true,// 激活状态                   
26                     url: 'testServer/jsonQuestTest.ashx',//如果不配置采用公用 $.fn.tabs.defaults里的配置
27                     dataType: 'json'// //如果不配置采用公用 $.fn.tabs.defaults里的配置 
28                 },{
29                     title: '文本测试',
30                     closable: false,
31                     iconcls: 'icon-back',
32                     actived: false,// 激活状态                   
33                     content: $("#text") //'<a>我是测试内容.....................</a>'// 可以是文本,可以是$("#id")对象                    
34                 }],
35                 onLoadSuccess: function (title, context) {
36                     console.log(title + "加载完成");                    
37                     if (title == "远程加载JSON数据" || title == "动态添加tab") {
38                        context.target.html(JSON.stringify(context.data));
39                     }
40                 },
41                 activedHandler: function (tilte,context) {
42                     console.log("actived=" + tilte);
43                 },
44                 closedHandler: function (title) {
45                     console.log("closed=" + title);
46                 }
47             });
48         });
49         function addTab() {
50             tabs.tabs("addTabs", {
51                 title: '动态添加tab',
52                 closable: true,
53                 iconcls: 'icon-back',
54                 actived: false,// 激活状态                   
55                 //content: '<a>我是动态tab内容</a>'
56                 url: 'testServer/jsonQuestTest.ashx',//如果不配置采用公用 $.fn.tabs.defaults里的配置
57                 dataType: 'json',// //如果不配置采用公用 $.fn.tabs.defaults里的配置 
58                 onLoadSuccess: function (title, context) {
59                     context.target.html(title+"loadsucc;我自己注册的事件 "+JSON.stringify(context.data));
60                 }
61             });
62         }
63         function getSelectedTab() {
64            var res =  tabs.tabs("getSelectedTab");
65            alert(res.titleObj.attr("title"));
66         }
67         function reload() {
68             var itemsopt = $("#itemsopt").children("option[selected]");
69             tabs.tabs("reLoadTab", itemsopt.val());
70             if (tabs.tabs("isExist", itemsopt.val())) {
71                 console.log(itemsopt.val()+"exist");
72             } else {
73                 console.log(itemsopt.val() + "no exist");
74             }
75             
76         }
77     </script>
78 </body>

组件代码

  1 /**************************************************************
  2 *作者:hjwen
  3 *电邮:hjwen88@126.com
  4 *版本:1.0
  5 *版权许可:中国通用开源许可协议V1.0
  6 *说明:myui组件tabs组件
  7 ***************************************************************/
  8 (function ($) {
  9     /******
 10     *渲染目标:renderHtml为构建html结构的函数,init初始化会调用
 11     *******/
 12     var contentPadding = 6;
 13     var showTitleItem = null;
 14     var showContentItem = null;
 15     var itemTitleContainer, itemContentContainer, existItems;
 16     var headerWith = 0;
 17     var itemsWidth = 0;
 18     var leftMoreBtn = null, rightMoreBtn = null;
 19     function renderHtml(target, opts) {
 20         itemContentContainer = target;
 21         var panel = target.panel({ expandable: false, maximizable: false, closeable: false, expanded: false });
 22         var titleWrap = target.prev("div");
 23         headerWith = titleWrap.width();
 24         var panelTitle = titleWrap.children(".panel-tilte");
 25         itemTitleContainer = $("<ul class=\"tabsul\"></ul>").appendTo(panelTitle);
 26         target.css({ "overflow": "hidden", "padding": "0px" });
 27         existItems.css({ "width": target.width() - contentPadding * 2 + "px", "height": target.height() - contentPadding * 2 + "px", "margin": "0px", "padding": contentPadding + "px", "overflow": "auto" }).hide();
 28         createTabs(opts.items);
 29         existItems = null;
 30     };
 31     /**********私有方法开始********************/
 32     function createTabs(items) {
 33         $.each(items, function (i, item) {
 34             createTab(item, i);
 35         });
 36         showContentItem.show();
 37         showTitleItem.attr("actived", "true").children("a").addClass("tabs_selected").css("border-bottom", "1px solid #FFFFFF");        
 38     }
 39     function createTab(item, index) {
 40         //创建tab标题项
 41         var a_tag = "<a href='javascript:void(0)'>";
 42         if (item.iconcls != '')
 43             a_tag = a_tag + "<span class='item_title_ioc " + item.iconcls + "'></span>";
 44         if (item.closable)
 45             a_tag = a_tag + "<span class='item_title_text'>" + item.title + "</span><span  for=" + index + " class='item_title_close' ></span></a>";
 46         else
 47             a_tag = a_tag + "<span class='item_title_text'>" + item.title + "</span></a>";
 48         var itemTitleLi = $("<li contextmenu=\"" + item.contextMenu + "\" datatype=\"" + item.dataType + "\" url=\"" + item.url + "\" isiframe=\"" + item.isiframe + "\" title=\"" + item.title + "\" closable=\"" + item.closable + "\" actived=\"" + item.actived + "\" for=" + index + ">" + a_tag + "</li>").appendTo(itemTitleContainer);
 49         itemTitleLi.bind({
 50             "click": function () {
 51                 var $this = $(this);
 52                 if ($this.attr("actived") == "true")
 53                     return;
 54                 var idx = $this.attr("for");
 55                 showContentItem.hide();
 56                 showTitleItem.attr("actived", "false").children("a").removeClass("tabs_selected").css("border-bottom", "1px solid #99BBE8");
 57                 $.each(itemContentContainer.children("div"), function (j, obj) {
 58                     var $obj = $(obj);
 59                     if (j == parseInt(idx)) {
 60                         $this.attr("actived", "true").children("a").addClass("tabs_selected").css("border-bottom", "1px solid #FFFFFF");
 61                         showContentItem = $obj.show();
 62                         showTitleItem = $this;
 63                     }
 64                 });
 65                 if (item.activedHandler != null) {
 66                     item.activedHandler(showTitleItem.attr("title"), { titleObj: showTitleItem, conetentObj: showContentItem });
 67                 }
 68             }            
 69         });
 70         //如果可以关闭
 71         if (item.closable) {
 72             itemTitleLi.children("a").children(".item_title_close").bind({
 73                 click: function () {
 74                     var allIts = itemContentContainer.children("div");
 75                     var $t = $(this);
 76                     var foridx = parseInt($t.attr("for"));
 77                     var removeContent = null;
 78                     for (var k = 0, len = allIts.length; k < len; ++k) {
 79                         if (foridx == k) {
 80                             removeContent = $(allIts[k]);
 81                             break;
 82                         }
 83                     };
 84                     //如果关闭的是激活的tab,则需要调整激活的tab
 85                     var showIdx = 0;
 86                     var titleLi = $t.parent("a").parent("li");
 87                     if (titleLi.attr("actived") == "true") {
 88                         var showIt = titleLi.prev("li");
 89                         showIdx = foridx - 1;
 90                         if (showIt.length == 0) {
 91                             showIt = titleLi.next("li");
 92                             showIdx = foridx + 1;
 93                         }
 94                         showTitleItem = showIt;
 95                         showTitleItem.attr("actived", "true").children("a").addClass("tabs_selected").css("border-bottom", "1px solid #FFFFFF");
 96                         //激活对应的内容div
 97                         for (var k = 0, len = allIts.length; k < len; ++k) {
 98                             if (showIdx == k) {
 99                                 $(allIts[k]).show();
100                                 break;
101                             }
102                         };
103                     }
104                     //修改删除项目后面所有li项的for属性
105                     var nextAll = titleLi.nextAll();
106                     if (nextAll.length > 0) {
107                         setTimeout(function () {
108                             $.each(nextAll, function (j, obj) {
109                                 var $obj = $(obj);
110                                 var curFor = parseInt($obj.attr("for"));
111                                 var newFor = curFor - 1;
112                                 $obj.attr("for", newFor);
113                                 $obj.children("a").children(".item_title_close").attr("for", newFor);
114                             });
115                         }, 0);
116                     }
117                     var title = titleLi.attr("title");
118                     itemsWidth = itemsWidth - titleLi.outerWidth()-11;
119                     titleLi.remove();
120                     removeContent.remove();
121                     showMoreBtn();
122                     if (item.closedHandler != null)
123                         item.closedHandler(title);
124                 },
125                 mouseover: function () {
126                     $(this).css("background-color", "#8DE2B3");
127                 },
128                 mouseout: function () {
129                     $(this).attr("style", "");
130                 }
131             });
132         }
133         var contentDiv;
134         if (item.exist) {//已经存在的不用再创建内容div
135             contentDiv = $(existItems[index]);
136         } else {
137             contentDiv = $("<div></div>").appendTo(itemContentContainer).css({ "width": itemContentContainer.width() - contentPadding * 2 + "px", "height": itemContentContainer.height() - contentPadding * 2 + "px", "margin": "0px", "padding": contentPadding + "px", "overflow": "auto" }).hide();;
138         }
139         if (item.content != "") {//优先取content
140             if ($.isPlainObject(item.content)) {
141                 item.content.remove().appendTo(contentDiv);
142             } else {
143                 contentDiv.html(item.content);
144             }
145         } else {
146             //是否有url 远程加载
147             if (item.url != "") {
148                 load(contentDiv, item,false);
149             }
150         }
151         if (index == 0) {//默认第一个为激活状态
152             showTitleItem = itemTitleLi;
153             showContentItem = contentDiv;
154         }
155         if (item.actived) {
156             showTitleItem = itemTitleLi;
157             showContentItem = contentDiv;
158         }
159         itemsWidth = itemsWidth + itemTitleLi.outerWidth()+11;       
160         showMoreBtn();
161     };
162     function load(target,item,isReload) {
163         if (item.isiframe) {
164             target.css({ "overflow": "hidden", "padding": "0", "width": target.width() + contentPadding * 2 + "px", "height": target.height() + contentPadding * 2 + "px" });
165             var loading = $("<div class='loading icon-loading'>正在加载......</div>").appendTo(target);
166             var iframe;
167             if (isReload) {
168                 iframe = target.children("iframe")[0];
169                 iframe.contentWindow.location.reload();
170             } else {
171                 iframe = $("<iframe title='" + item.title + "' frameborder='0' style='overflow:visible' scrolling='auto' width='100%' height='100%' src='" + item.url + "' ></iframe>").appendTo(target);
172                 iframe.load(function () {
173                     loading.remove();
174                     if (item.onLoadSuccess != null)
175                         item.onLoadSuccess($(this).attr('title'), target);
176                 });
177             }        
178         } else {
179             if (item.dataType == "json") {
180                 var ajaxopt = {
181                     url: item.url,
182                     loadingContainer: target,
183                     returnParams: true,
184                     params: { title: encodeURIComponent(item.title) }
185                 };
186                 if (item.onLoadSuccess != null)
187                     ajaxopt.okdeal = function (data, extParams) {
188                         item.onLoadSuccess(decodeURIComponent(extParams.title), { data: data, target: target });
189                     };
190                 $.myui.ajaxRequest(ajaxopt);
191             } else {
192                 var settings = { url: item.url, extParam: item.title };
193                 if (item.onLoadSuccess != null)
194                     settings.loaded = function (t, extParam) {
195                         item.onLoadSuccess(extParam, t);
196                     };
197                 $.myui.objectLoadContect({
198                     target: target,
199                     settings: settings
200                 });
201             }
202         }
203     };
204     function showMoreBtn() {
205         if (itemsWidth > headerWith) {
206             itemTitleContainer.css("padding-left","9px");
207             if (leftMoreBtn == null) {
208                 var headerWrap = itemTitleContainer.parent("div").parent("div");
209                 leftMoreBtn = $("<a class='leftMoreBtn'></a>").appendTo(headerWrap);
210                 rightMoreBtn = $("<a class='rightMoreBtn'></a>").appendTo(headerWrap);
211                 leftMoreBtn.bind('click', function () {
212                     var position = itemTitleContainer.position();
213                     if (position.left < 9) {
214                         var pos = position.left +80;
215                         itemTitleContainer.animate({ left: pos },500);
216                     }
217                 });
218                 rightMoreBtn.bind('click', function () {
219                     var position = itemTitleContainer.position();
220                     var pos = position.left -80;                 
221                     itemTitleContainer.animate({ left: pos},500);
222                 });
223             } else {
224                 leftMoreBtn.show();
225                 rightMoreBtn.show();
226             }
227             var diff = itemsWidth - headerWith;           
228             itemTitleContainer.animate({ left: -diff }, 500);
229         } else {            
230             if (leftMoreBtn != null) {
231                 itemTitleContainer.css("padding-left", "0px");
232                 leftMoreBtn.hide();
233                 rightMoreBtn.hide();
234                 var position = itemTitleContainer.position();
235                 if (position.left < 0) {
236                     itemTitleContainer.animate({ left: 0 }, 500);
237                 }
238             }
239         }
240     }
241     /**********私有方法结束*******************/
242     /*****************************************************************************
243     *对外的函数统一封装到methods中
244     *调用方式:$.pluginInstance.pluginName("methodName",params) 
245     ******************************************************************************/
246     var methods = {
247         init: function (options) {
248             return this.each(function () {
249                 var $this = $(this);
250                 var settings
251                 if (typeof options == 'undefined')
252                     settings = $.fn.tabs.defaults;
253                 else
254                     settings = $.extend({}, $.fn.tabs.defaults, options);
255                 var newItemArr = [];
256                 existItems = $this.children("div");//已经存在的item项
257                 if (existItems.length > 0) {
258                     $.each(existItems, function (i, it) {
259                         var $it = $(it);
260                         newItemArr.push({
261                             title: $it.attr("title"),
262                             content: '',
263                             contextMenu: false,
264                             closable: $it.attr("closable") == "true" ? true : false,
265                             iconcls: $it.attr("iconcls") == undefined ? "" : $it.attr("iconcls"),
266                             actived: $it.attr("actived") == "true" ? true : false,// 激活状态
267                             isiframe: $it.attr("isiframe") == "true" ? true : false,//如果不配置采用公用 $.fn.tabs.defaults里的配置
268                             url: $it.attr("url") == undefined ? "" : $it.attr("url"),//如果不配置采用公用 $.fn.tabs.defaults里的配置
269                             dataType: $it.attr("dataType") == undefined ? "json" : $it.attr("dataType"),  //如果不配置采用公用 $.fn.tabs.defaults里的配置
270                             exist: true, //
271                             onLoadSuccess: settings.onLoadSuccess,//fn(tabtitle,resdata)
272                             activedHandler: settings.activedHandler,//fn(tabtitle,context)
273                             closedHandler: settings.closedHandler //fn(tabtitle) tab被关闭时触发
274                         });
275                     });
276                 }
277                 //合并每一个tab项的默认设置
278                 $.each(settings.items, function (i, item) {
279                     var newIt = $.extend({}, $.fn.tabs.itemdefaults, item);
280                     newIt.exist = false;
281                     if (typeof newIt.onLoadSuccess!='function')
282                         newIt.onLoadSuccess = settings.onLoadSuccess;//fn(tabtitle,resdata)
283                     if (typeof newIt.activedHandler != 'function')
284                         newIt.activedHandler = settings.activedHandler;//fn(tabtitle,context)
285                     if (typeof newIt.closedHandler != 'function')
286                         newIt.closedHandler = settings.closedHandler; //fn(tabtitle) tab被关闭时触发
287                     newItemArr.push(newIt);
288                 });
289                 settings.items = newItemArr;
290                 //创建ui布局
291                 renderHtml($this, settings);
292                 if ($.myui.isDebug) {
293                     $.myui.log("jQuery.tabs init finish......");
294                 }
295                 $this.data('settings', settings);
296             });
297         },
298         destroy: function (options) {
299             return $(this).each(function () {
300                 var $this = $(this);
301                 $this.removeData('settings');
302             });
303         },
304         /***
305         *opt={
306             title: 'tab标题',
307             closable: false,
308             iconcls: '',
309             actived: false,// 激活状态
310             isiframe: false,//如果不配置采用公用 $.fn.tabs.defaults里的配置
311             url: '',//如果不配置采用公用 $.fn.tabs.defaults里的配置
312             content: '',//内容默认为空,如果该属性有值,则优先默认采用这个,即使设置url也不会去远程加载数据,content可以是html对象,也可以是文本
313             dataType: 'json',// //如果不配置采用公用 $.fn.tabs.defaults里的配置
314             contextMenu: false //右键菜单未实现
315         }
316         ***/
317         addTabs: function (opts) {
318             var newOpt = $.extend({}, $.fn.tabs.itemdefaults, opts);
319             newOpt.actived = true;            
320             return $(this).each(function () {
321                 var $this = $(this);
322                 var settings = $this.data('settings');
323                 if (showContentItem != null)
324                     showContentItem.hide();
325                 if (showTitleItem != null)
326                     showTitleItem.attr("actived", "false").children("a").removeClass("tabs_selected").css("border-bottom", "1px solid #99BBE8");
327                 itemContentContainer = $this;
328                 var index = $this.children("div").length;
329                 if (typeof newOpt.onLoadSuccess != 'function')
330                     newOpt.onLoadSuccess = settings.onLoadSuccess;//fn(tabtitle,resdata)
331                 if (typeof newOpt.activedHandler != 'function')
332                     newOpt.activedHandler = settings.activedHandler;//fn(tabtitle,context)
333                 if (typeof newOpt.closedHandler != 'function')
334                     newOpt.closedHandler = settings.closedHandler; //fn(tabtitle) tab被关闭时触发
335                 createTab(newOpt, index);
336                 showContentItem.show();
337                 showTitleItem.attr("actived", "true").children("a").addClass("tabs_selected").css("border-bottom", "1px solid #FFFFFF");
338             });
339         },
340         /**
341         * 获取选中的tab,返回值{titleObj:...,contentObj:...}
342         ***/
343         getSelectedTab: function () {
344             return { titleObj: showTitleItem, contentObj: showContentItem };
345         },
346         /***
347         *重新加载某个tab,以title为标准
348         ****/
349         reLoadTab: function (title) {
350             var $this = $(this);
351             var titlelis = $this.prev().children(".panel-tilte").children("ul").children();
352             var forIdx = -1;
353             var url = '';
354             var isIframe = false;
355             var dataType = "html";
356             var currShowTitle = null;
357             for (var i = 0, len = titlelis.length; i < len; ++i) {
358                 var $li = $(titlelis[i]);
359                 if ($li.attr("title") == title && $li.attr("url") != undefined && $li.attr("url")!='') {
360                     forIdx = i;
361                     url = $li.attr("url");
362                     if ($li.attr("isiframe") != undefined) {
363                         isIframe = $li.attr("isiframe") == 'true';
364                     }
365                     if ($li.attr("datatype") != undefined) {
366                         dataType = $li.attr("datatype");
367                     }
368                     currShowTitle = $li;
369                     break;
370                 }
371             }
372             if (forIdx != -1) {
373                 var childs = $this.children();
374                 var updateContent = null;
375                 for (var i = 0, len = childs.length; i < len;++i){
376                     if (i == forIdx) {
377                         updateContent = $(childs[i]);
378                     }
379                 }
380                 if (updateContent != null) {
381                     var opts = $this.data('settings');
382                     var it;
383                     for (var j = 0, len = opts.items.length; j < len;++j){
384                         if (forIdx == j)
385                             it = opts.items[j];
386                     }
387                     if (showTitleItem.attr("title") != title) {                     
388                         showContentItem.hide();                    
389                         showTitleItem.attr("actived", "false").children("a").removeClass("tabs_selected").css("border-bottom", "1px solid #99BBE8");
390                         showContentItem= updateContent.show();
391                         showTitleItem = currShowTitle.attr("actived", "true");
392                         showTitleItem.children("a").addClass("tabs_selected").css("border-bottom", "1px solid #FFFFFF");
393                     }               
394                     load(updateContent, it, true);
395                 }
396             }
397             return $this;
398         },
399         /****
400         * 判断某个tab是否存在
401         ****/
402         isExist: function (title) {
403             var $this = $(this);
404             var titlelis = $this.prev().children(".panel-tilte").children("ul").children();
405             var forIdx = -1;          
406             for (var i = 0, len = titlelis.length; i < len; ++i) {
407                 var $li = $(titlelis[i]);
408                 if ($li.attr("title") == title && $li.attr("url") != undefined && $li.attr("url") != '') {
409                     forIdx = i; 
410                     break;
411                 }
412             }
413             if (forIdx > -1)
414                 return true;
415             else
416                 return false;
417         }        
418     };
419     /********************
420     *组件的构造函数
421     *********************/
422     $.fn.tabs = function () {
423         var method = arguments[0];
424         if (methods[method]) {
425             method = methods[method];
426             arguments = Array.prototype.slice.call(arguments, 1);
427         } else if (typeof (method) == 'object' || !method) {
428             if ($.myui.isDebug) {
429                 $.myui.log("jQuery.tabs init.....");
430             }
431             method = methods.init;
432         } else {
433             $.error('Method ' + method + ' does not exist on jQuery.tabs');
434             return this;
435         }
436         return method.apply(this, arguments);
437     };
438     /********************
439     *组件的默认配置值
440     *options={
441         items: [], //tab项配置,对应$.fn.tabs.itemdefaults
442         isiframe: false,// 是否嵌入iframe,嵌入iframe 需要与url配合使用,即采用url加载远程页面时【dataType=html】才起作用
443         url: '',
444         dataType: 'json',// json/html 远程加载时的数据格式
445         onLoadSuccess: null,//fn(tabtitle,resdata)
446         activedHandler: null,//fn(tabtitle,context)
447         closedHandler: null //fn(tabtitle) tab被关闭时触发
448     }
449     *********************/
450     $.fn.tabs.defaults = {
451         items: [], //tab项配置,对应$.fn.tabs.itemdefaults
452         isiframe: false,// 是否嵌入iframe,嵌入iframe 需要与url配合使用,即采用url加载远程页面时【dataType=html】才起作用
453         url: '',
454         dataType: 'json',// json/html 远程加载时的数据格式
455         onLoadSuccess: null,//fn(tabtitle,resdata)
456         activedHandler: null,//fn(tabtitle)
457         closedHandler: null //fn(tabtitle) tab被关闭时触发
458     };
459     /***
460     *每一个tab项目的默认配置
461     ****/
462     $.fn.tabs.itemdefaults = {
463         title: 'tab标题',
464         closable: false,
465         iconcls: '',
466         actived: false,// 激活状态
467         isiframe: false,//如果不配置采用公用 $.fn.tabs.defaults里的配置
468         url: '',//如果不配置采用公用 $.fn.tabs.defaults里的配置
469         content: '',//内容默认为空,如果该属性有值,则优先默认采用这个,即使设置url也不会去远程加载数据,content可以是html对象,也可以是文本
470         dataType: 'json',// //如果不配置采用公用 $.fn.tabs.defaults里的配置 
471         contextMenu: false //右键菜单未实现
472     }
473 })(jQuery);

 

posted @ 2014-08-09 15:55  hjwen  Views(2421)  Comments(4Edit  收藏  举报