2月份第一次JS组件,写了几个:TableGrid, Toolbar, LinkButton, Pager,现在发出来。 TableGrid可以包含Toolbar, Pager。 Toolbar可以包含LinkButton。这样就构成了具有工具栏、分页栏的数据表格控件。也就是说,这4个组件可以独立使用,也可以结合使用。通篇只采用一种结构来编写,若能看懂编写规则,往后就可以按照这种模式自定义JS控件了。
1 var fjn=fjn?fjn:{}; 2 (function($,global){ 3 // 确保先加载jQuery.js 4 if($!=jQuery) { 5 throw Error("you must load jQuery.js before this javascript file"); 6 } 7 /* 8 container可以是jQuery对象,jQuery selector, DOM对象 9 1:jQuery 10 2:DOM,jQuery Selector 11 3:Other 12 */ 13 function getRealContainer(container){ 14 var real, 15 containerType=container instanceof jQuery ? 1 : container.nodeType ? 2 : typeof(container)!=‘string‘ ? 3 : $(container)[0] ? 2 : 3 ; 16 switch(containerType){ 17 case 1: 18 real=container; 19 break; 20 case 2: 21 real=$(container); 22 break; 23 case 3: 24 real=null; 25 throw new Error("参数conatiner="+container+"不能代表一个容器!当前对象是:"+this); 26 } 27 return real; 28 }; 29 30 31 function TableGrid(container,options){ 32 if(!(this instanceof TableGrid)) return; 33 this.container=getRealContainer.call(this,container); 34 this._init(options); 35 } 36 37 TableGrid.cssClass={ 38 DEFAULT:"tablegrid", 39 SELECT_All:"selectAll", 40 ROW_CHECK:"rowCheck", 41 EVEN:"even", 42 ODD:"odd", 43 DATA_CELL:"dataCell", 44 HEADER:"header", 45 TR_MOUSEOVER:"mouseover", 46 TR_SELECTED:"selected" 47 }; 48 49 TableGrid.defaultOptions={ 50 title:"TableGrid", 51 checkable:true, 52 columns:[], 53 cls:TableGrid.cssClass.DEFAULT, 54 toolbar:null, 55 pager:null 56 }; 57 58 TableGrid.otherInfo={ 59 bgcolor_onmouseover:"YELLOW" 60 }; 61 62 /** 63 * @param options {Object} 64 * 必要的选项 65 * 66 columns:[{ 67 name:"", // 表格的列名 68 field:""// 69 }] 70 可选项: 71 toolbarCfg:{}//其实是Toolbar的options 72 cls:cssClass 73 style:"" // 也可以使用自定义style,这个优先级高 74 pagerCfg:{}//可以在表格下面加入分页工具 75 */ 76 TableGrid.prototype._init=function(options){ 77 78 this.cfg=$.extend({},TableGrid.defaultOptions,options); 79 // 添加工具条 80 if(this.cfg.toolbarCfg){ 81 this._initToolbar(); 82 } 83 // 检查配置项 84 if(!(this.cfg.columns && this.cfg.columns.length>0)){ 85 new Error("配置项columns必须设置"); 86 } 87 88 this.table=$("<table class=‘"+this.cfg.cls+"‘></table>"); 89 90 // 添加表头 91 var thead=$("<thead></thead>"); 92 var tr=$("<tr></tr>"), 93 td, 94 me=this; 95 // 添加选择框 96 if(this.cfg.checkable){ 97 var checkbox=$("<input type=‘checkbox‘>"); 98 checkbox.click(function(){ 99 if(this.checked){ 100 $("tbody td."+TableGrid.cssClass.ROW_CHECK+" input[type=‘checkbox‘]",me.table).attr("checked","checked"); 101 $("tbody tr", me.table).addClass(TableGrid.cssClass.TR_SELECTED); 102 }else{ 103 $("tbody td."+TableGrid.cssClass.ROW_CHECK+" input[type=‘checkbox‘]",me.table).removeAttr("checked"); 104 $("tbody tr", me.table).removeClass(TableGrid.cssClass.TR_SELECTED); 105 } 106 }); 107 td=$("<th></th>").append(checkbox); 108 tr.append(td); 109 } 110 // 添加表头 111 for(var i=0; i<this.cfg.columns.length; i++){ 112 var style=this.cfg.columns[i].style || ""; 113 td=$("<th class=‘"+TableGrid.cssClass.HEADER+"‘ style=‘"+style+"‘></th>").html(this.cfg.columns[i].name); 114 tr.append(td); 115 } 116 this.container.append(this.table.append(thead.append(tr))); 117 this.table.append("<tbody></tbody>"); 118 119 // 初始化分页工具 120 if(this.cfg.pagerCfg){ 121 this._initPager(); 122 } 123 124 }; 125 126 /** 127 * 128 * @param url 是要访问的资源的URL,可以是一个JSON文件,也可以是action地址 129 * @param params 是异步访问传递的参数 130 * @param filter 暂时没有使用到 131 * @param success 数据加载后的处理 132 */ 133 TableGrid.prototype.load=function(url, params, filter, success){ 134 params=params||{}; 135 if(this.cfg.pagerCfg){ 136 params.pageNumber=this.getPager().getPageNumber(); 137 params.pagesize=this.getPager().getPageSize(); 138 params.recordTotal=this.getPager().getRecordTotal(); 139 } 140 141 // console.log(params); 142 var me=this; 143 $.getJSON(url,params,function(list){ 144 if(list){ 145 var tbody=$("tbody", me.table); 146 tbody.empty(); 147 for(var i=0; i<list.length; i++){ 148 var tr_odd_even=i&1==1?TableGrid.cssClass.EVEN:TableGrid.cssClass.ODD; 149 var tr=$("<tr class=‘"+tr_odd_even+"‘ ></tr>"); 150 151 // 添加选择框 152 if(me.cfg.checkable){ 153 var checkbox=$("<input type=‘checkbox‘>"); 154 td=$("<td class=‘"+TableGrid.cssClass.ROW_CHECK+"‘></td>").append(checkbox); 155 checkbox.click(function(event){ 156 event.stopPropagation(); 157 if(this.checked){ 158 $(this).parent().parent().addClass(TableGrid.cssClass.TR_SELECTED); 159 }else{ 160 $(this).parent().parent().removeClass(TableGrid.cssClass.TR_SELECTED); 161 } 162 }); 163 tr.append(td); 164 165 } 166 167 var obj=list[i], 168 field, // 后台对象的属性 169 value; 170 for(var j=0; j<me.cfg.columns.length; j++){ 171 field=me.cfg.columns[j].field; 172 value=obj[field]; 173 td=$("<td></td>").html(value); 174 175 tr.append(td); 176 } 177 tr.bind({ 178 mouseover:function(){ 179 this.className+=" "+TableGrid.cssClass.TR_MOUSEOVER; 180 }, 181 mouseout:function(){ 182 $(this).removeClass(TableGrid.cssClass.TR_MOUSEOVER); 183 }, 184 click:function(){ 185 if(me.cfg.checkable){ 186 var checkbox=$("td."+TableGrid.cssClass.ROW_CHECK+" input[type=‘checkbox‘]",this); 187 188 if(checkbox[0].checked){ 189 checkbox.removeAttr("checked"); 190 $(this).removeClass(TableGrid.cssClass.TR_SELECTED); 191 }else{ 192 checkbox.attr("checked","checked"); 193 this.className+=" "+TableGrid.cssClass.TR_SELECTED; 194 } 195 } 196 197 } 198 199 }); 200 tbody.append(tr); 201 } 202 } 203 204 if(typeof success==‘function‘) success(); 205 }); 206 207 }; 208 209 TableGrid.prototype._initToolbar=function(){ 210 this.toolbar=new Toolbar(this.container, this.cfg.toolbarCfg); 211 }; 212 213 TableGrid.prototype._initPager=function(){ 214 this.pager=new Pager(this.container, this.cfg.pagerCfg); 215 }; 216 // 获取到表格组件内的中的分页组件 217 TableGrid.prototype.getPager=function(){ 218 return this.pager; 219 } 220 221 // 获取到所有选择项 222 TableGrid.prototype.getSelected=function(){ 223 224 } 225 226 227 228 /*---------------------------------------Toolbar-----------------------------------------*/ 229 function Toolbar(container, options){ 230 if(!(this instanceof Toolbar)) return; 231 this.container=getRealContainer.call(this,container); 232 this._init(options); 233 } 234 235 Toolbar.cssClass={ 236 DEFAULT:"toolbar" 237 }; 238 239 Toolbar.defaultOptions={ 240 buttons:[], 241 cls:Toolbar.cssClass.DEFAULT 242 }; 243 244 /** 245 * @param options 246 * buttons:Array 工具条上的按钮 247 */ 248 Toolbar.prototype._init=function(options){ 249 this.cfg=$.extend({}, Toolbar.defaultOptions, options); 250 this.toolbar=$("<div class=‘"+Toolbar.cssClass.DEFAULT+"‘></div>"); 251 if(this.cfg.buttons){ 252 for(var i=0; i< this.cfg.buttons.length; i++){ 253 new LinkButton(this.toolbar, this.cfg.buttons[i]); 254 } 255 } 256 this.container.append(this.toolbar); 257 }; 258 259 260 /*----------------------------------------LinkButton-------------------------------------*/ 261 262 function LinkButton(container,options){ 263 if(!(this instanceof LinkButton)) return; 264 this.container=getRealContainer.call(this,container); 265 this._init(options); 266 if(this.container){ 267 this.container.append(this.btn); 268 } 269 } 270 271 LinkButton.cssClass={ 272 DEFAULT:"button", 273 SAVE:"btn_save", 274 EDIT:"btn_edit", 275 DELETE:"btn_del" 276 }; 277 278 LinkButton.defaultOptions={ 279 href:"javascript:void(0)", 280 target:"_blank", //是<a>的target属性 281 text:"Button", // 是按钮上的文本 282 cls:LinkButton.cssClass.DEFAULT 283 }; 284 285 /** 286 * @param options 287 * cls:{String} // 按钮的class属性 288 * text:{String}// 按钮上显示的文本 289 * click:{Function}//点击事件处理 290 * href:{String}链接地址,点击事件处理完毕,会将页面链接到指定的URL 291 * target:{String}就是Anchor的target 292 */ 293 LinkButton.prototype._init=function(options){ 294 this.cfg=$.extend({}, LinkButton.defaultOptions, options); 295 var css_class=this.cfg.cls, 296 href=this.cfg.href || LinkButton.defaultOptions.href; 297 this.btn=$("<a class=‘"+css_class+"‘ href=‘"+href+"‘>"+this.cfg.text+"</a>"); 298 if(typeof this.cfg.click ==‘function‘){ 299 this.btn.on("click",this.cfg.click); 300 } 301 }; 302 303 /*------------------------------------Pager----------------------------------------*/ 304 // 每页【xx】条 共X页 【首页】【上一页】【第N页】【下一页】【尾页】 305 function Pager(container, options){ 306 if(!(this instanceof Pager)) return; 307 this.container=getRealContainer.call(this,container); 308 this._init(options); 309 } 310 311 Pager.cssClass={ 312 DEFAULT:"pager", 313 PAGE_SIZE:"pagesize",// 页面大小 314 FIRST:"first",//首页 315 LAST:"last",//尾页 316 PREV:"prev",//上一页 317 NEXT:"next",//下一页 318 PAGE_NUMBER:"pageNumber",//第N页 319 PAGE_RIGHT:"pagerRight", 320 MAX_PAGE:"maxPage", 321 RECORD_TOTAL:"recordTotal", 322 CURRENT_PAGE:"currentPage" 323 }; 324 325 Pager.defaultOptions={ 326 cls:Pager.cssClass.DEFAULT, 327 pageSizeList:[5,10,15,20], 328 handler:{ 329 onSelectPage:function(pageNum, pagesize){}, 330 onPageSizeChanged:function(pagesize){} 331 }, 332 pageNumber:1, // 要请求的页码 333 recordTotal:0, // 总的记录数目 334 maxPage:0, // 最大页码数 335 pagesize:10, // 每页数据行数 336 currentPage:1 // 当前显示的页码 337 }; 338 339 /** 340 * @param options 341 * pageSizeList:[5, 10, 15, 20], 342 * handler:{ 343 * onPageSizeChanged:function(pagesize){}// 参数是页面记录数目 344 * onSelectPage:function(pageNum, pagesize){} 345 * }, 346 * pagesize:10, 347 * recordTotal:10 348 */ 349 Pager.prototype._init=function(options){ 350 this.cfg=$.extend({}, Pager.defaultOptions, options); 351 this.page=$("<div class=‘"+Pager.cssClass.DEFAULT+"‘></div>"); 352 353 // 设置页面记录长度 354 var me=this, 355 pagesizeHTML="<select class=‘"+Pager.cssClass.PAGE_SIZE+"‘ name=‘pagesize‘>"; 356 for(var i=0; i<this.cfg.pageSizeList.length; i++){ 357 var value=parseInt(this.cfg.pageSizeList[i],10); 358 if(value==this.cfg.pagesize){ 359 pagesizeHTML+="<option value=‘"+value+"‘ selected=‘selected‘>"+value+"</option>"; 360 }else{ 361 pagesizeHTML+="<option value=‘"+value+"‘>"+value+"</option>"; 362 } 363 } 364 pagesizeHTML+="</select>"; 365 366 var pagesizeSelect=$(pagesizeHTML).change(function(){ 367 me.cfg.pagesize=parseInt(pagesizeSelect.val(),10); 368 // 执行自定义操作 369 me.cfg.handler.onPageSizeChanged(me.cfg.pagesize); 370 // 更新page数据 371 me._updateSelf(); 372 }); 373 374 375 // 首页,上一页,下一页,尾页 376 var firstSpan=$("<span title=‘首页‘ class=‘"+Pager.cssClass.FIRST+"‘> </span>"), 377 prevSpan=$("<span title=‘上一页‘ class=‘"+Pager.cssClass.PREV+"‘> </span>"), 378 nextSpan=$("<span title=‘下一页‘ class=‘"+Pager.cssClass.NEXT+"‘> </span>"), 379 lastSpan=$("<span title=‘尾页‘ class=‘"+Pager.cssClass.LAST+"‘> </span>"); 380 firstSpan.click(function(){ 381 me.cfg.pageNumber=1; 382 me.cfg.handler.onSelectPage(me.cfg.pageNumber, me.cfg.pagesize); 383 me._updateSelf(); 384 }); 385 prevSpan.click(function(){ 386 if(me.cfg.currentPage>1){ 387 me.cfg.pageNumber=me.cfg.currentPage-1; 388 me.cfg.handler.onSelectPage(me.cfg.pageNumber, me.cfg.pagesize); 389 me.cfg.currentPage-=1; 390 me._updateSelf(); 391 } 392 }); 393 nextSpan.click(function(){ 394 // console.log("当前第"+me.cfg.currentPage+"页"); 395 if(me.cfg.currentPage<me.cfg.maxPage){ 396 me.cfg.pageNumber=me.cfg.currentPage+1; 397 me.cfg.handler.onSelectPage(me.cfg.pageNumber, me.cfg.pagesize); 398 me.cfg.currentPage+=1; 399 me._updateSelf(); 400 } 401 }); 402 lastSpan.click(function(){ 403 me.cfg.pageNumber=me.cfg.maxPage; 404 me.cfg.handler.onSelectPage(me.cfg.pageNumber, me.cfg.pagesize); 405 me.cfg.currentPage=me.cfg.maxPage; 406 me._updateSelf(); 407 }); 408 409 // 第N页 410 var pageNumberSpan=$("<input class=‘"+Pager.cssClass.PAGE_NUMBER+"‘ maxlength=‘3‘>"); 411 pageNumberSpan.change(function(){ 412 var v=parseInt(pageNumberSpan.val(),10); 413 if(v<=0){ 414 v=1; 415 pageNumberSpan.val(v); 416 }else if(v>me.cfg.maxPage){ 417 v=me.cfg.maxPage; 418 pageNumberSpan.val(v); 419 } 420 me.cfg.pageNumber=v; 421 me.cfg.handler.onSelectPage(me.cfg.pageNumber, me.cfg.pagesize); 422 me.cfg.currentPage=me.cfg.maxPage; 423 me._updateSelf(); 424 }); 425 var descDiv="<div class="+Pager.cssClass.PAGE_RIGHT+">共<span class=‘"+Pager.cssClass.RECORD_TOTAL+"‘>"+me.cfg.recordTotal+"</span>条,第<span class=‘"+Pager.cssClass.CURRENT_PAGE+"‘>"+me.cfg.currentPage+"</span>页 共<span class=‘"+Pager.cssClass.MAX_PAGE+"‘>"+me.cfg.maxPage+"</span>页</div>"; 426 this.page.append(pagesizeSelect) 427 .append(firstSpan) 428 .append(prevSpan) 429 .append(pageNumberSpan) 430 .append(nextSpan) 431 .append(lastSpan) 432 .append(descDiv); 433 this.container.append(this.page); 434 435 this._updateSelf(); 436 }; 437 438 Pager.prototype._clac=function(){ 439 if(this.cfg.recordTotal<=0){ 440 this.cfg.pageNumber=1; 441 return; 442 } 443 // 下面是存在记录时的处理: 444 if(this.cfg.pagesize<=0){ 445 this.cfg.pagesize=Pager.defaultOptions.pagesize; 446 } 447 if(this.cfg.pageNumber<=0){ 448 this.cfg.pageNumber==1; 449 } 450 // console.log(this.cfg.recordTotal, this.cfg.pagesize, this.cfg.pageNumber); 451 this.cfg.maxPage=parseInt(this.cfg.recordTotal%this.cfg.pagesize==0?this.cfg.recordTotal/this.cfg.pagesize:(this.cfg.recordTotal/this.cfg.pagesize+1),10); 452 // console.log("maxpage=",this.cfg.maxPage); 453 }, 454 455 /** 456 * 修改页面显示,显示正确的totalRecord, maxPage, currentPage 457 */ 458 Pager.prototype._updateSelf=function(){ 459 this._clac(); 460 $("span."+Pager.cssClass.MAX_PAGE,this.page).html(this.cfg.maxPage); 461 $("span."+Pager.cssClass.RECORD_TOTAL,this.page).html(this.cfg.recordTotal); 462 $("span."+Pager.cssClass.CURRENT_PAGE,this.page).html(this.cfg.currentPage); 463 }; 464 465 /** 466 * 设置总数 467 * @param total 468 */ 469 Pager.prototype.setRecordTotal=function(total){ 470 this.cfg.recordTotal=total; 471 this._updateSelf(); 472 } 473 474 Pager.prototype.getRecordTotal=function(total){ 475 return this.cfg.recordTotal; 476 } 477 478 Pager.prototype.getPageNumber=function(){ 479 return this.cfg.pageNumber; 480 } 481 482 Pager.prototype.getPageSize=function(){ 483 return this.cfg.pagesize; 484 } 485 486 487 488 /*--------------------------------------------------------------------*/ 489 490 $.extend(global,{ 491 getRealContainer:getRealContainer, 492 TableGrid:TableGrid, 493 Toolbar:Toolbar, 494 LinkButton:LinkButton, 495 Pager:Pager 496 }); 497 498 })(jQuery,fjn);
相关CSS,实现JS代码和CSS样式的分离:
1 @CHARSET "UTF-8"; 2 /*-------------------------------TableGrid---------------------------*/ 3 table.TableGrid{ 4 border-collapse: collapse; 5 border: 2px solid #ACE; 6 width: 100%; 7 height: 95%; 8 } 9 10 table.TableGrid thead th{ 11 width:auto; 12 border: 1px solid #ACE; 13 font: ‘宋体‘; 14 font-size:14px; 15 height: 1.5em; 16 color: blue; 17 background: #ACE; 18 border-right: 1px solid #FFF; 19 } 20 21 table.TableGrid tbody tr{ 22 height: 1.2em; 23 } 24 25 table.TableGrid tbody tr.mouseover.even{ 26 background-color: YELLOW; 27 } 28 29 table.TableGrid tbody tr.mouseover{ 30 background-color: YELLOW; 31 } 32 33 table.TableGrid tbody tr.selected{ 34 background-color: YELLOW; 35 } 36 table.TableGrid tbody tr.selected.even{ 37 background-color: YELLOW; 38 } 39 40 table.TableGrid tbody tr.even{ 41 background-color: #beddde; 42 } 43 44 table.TableGrid tbody td{ 45 border: 1px solid #ACE; 46 text-align: right; 47 height: 1.2em; 48 } 49 50 table.TableGrid tbody td.rowCheck{ 51 text-align: center; 52 } 53 54 /*----------------------------------ToolBar LinkButton----------------------------------*/ 55 div.toolbar a.button{ 56 border: 1px solid #ACE; 57 padding: 2px 3px; 58 text-decoration: none; 59 margin: 2px 2px 3px 0; 60 } 61 /*----------------------------------Pager---------------------------------------*/ 62 div.pager div.pagerRight{ 63 display: inline; 64 float: right; 65 } 66 div.pager input.pageNumber{ 67 width:30px; 68 } 69 70 div.pager span{ 71 margin:3px 3px; 72 } 73 div.pager span.first{ 74 background: url(‘../img/pagination_first.gif‘) no-repeat; 75 cursor: pointer; 76 padding: 2px 1px; 77 } 78 div.pager span.prev{ 79 background: url(‘../img/pagination_prev.gif‘) no-repeat; 80 cursor: pointer; 81 padding: 2px 1px; 82 } 83 div.pager span.next{ 84 background: url(‘../img/pagination_next.gif‘) no-repeat; 85 cursor: pointer; 86 padding: 2px 1px; 87 } 88 div.pager span.last{ 89 background: url(‘../img/pagination_last.gif‘) no-repeat; 90 cursor: pointer; 91 padding: 2px 1px; 92 }
自定义JS组件——系列1(TableGrid | Toolbar | LinkButton | Pager),布布扣,bubuko.com