simpleUI 项目进行中
快两个月了,我快哭了,一直加班~都没有时间写啊!
在经过多天的思考,阅读了大量的Dojo,YUI源码,终于下定决心,正式启动simpleUI项目。
项目宗旨:基于jQuery建立一套完整的UI,弥补jQuery在某些领域的空白,让其更适合企业级应用程序的开发!
项目计划完成时间:2011.07
项目计划完成组件:
1:基础架构搭建 100%
2:动态加载组件 15%
3:对话框,图片展示组件 100%
4:数据表格组件 70%
5:日期组件
6:图形报表组件
7:表单元素组件(input,select,radio,checkbox,button)100%
8:下拉菜单,右键菜单组件 30%
9:拖放,排序组件
10:JSON模板解析,格式化组件
11:布局组件
最先完成的就是simpleDialog组件,其实这个组件在很久前就已经完工了~~一直在完善,目前放出的这个版本是最新的。
支持所有主流浏览器,当然包括万恶的IE6.0
all source
/** * @author xing * @date 2011-03-19
* @place guangzhou布谷 @version:1.8
*/ (function($){ var ie6 = typeof document.body.style.maxHeight === "undefined"; $.fn.simpleDialog = $.fn.dialog = function(opts){ //return this.each(function(){ var d = new SimpleDialog(this, opts); return d; //}); }; $.close = function(el){ if ($('.xq-dialog').length < 2) { $('.xq-dialog-overlay').remove(); } el = el || $('.xq-dialog'); el.remove(); if (ie6) { $('html,body').removeClass('ie6Fixed'); } }; $.iframe = $.iframeDialog = function(){ var a = arguments, firstArgs = a[0]; a[1] = a[1] || {}; var o = $.extend({}, { iframe: true, iframeUrl: firstArgs }, a[1]); return $().simpleDialog(o); }; /** * 弹出ajax对话框 * @param {string} url * @param {Object} * @param {function} callback * @return {Object} other * @return {jQuery Object} dialog */ //url,object,callback $.ajaxDialog = function(){ var a = arguments, firstArgs = a[0], callback = a.length > 1 ? a[1] : function(){ }; a[2] = a[2] || {}; var o = $.extend({ ajax: true, ajaxUrl: firstArgs, onLoad: callback }, a[2]); return $().simpleDialog(o); }; /** * 弹出警告框 * @param {string} html * @param {function} callback * @param {Object} other * <code> * $.alert('this is a demo'); * </code> * <code> * var callback=function(){}; * $.alert('',callback); * </code> */ $.alert = $.alertDialog = function(html, callback, other){ var sure = function(e){ var el = $(this).parents('.xq-dialog'); $.close(el); if ($.isFunction(callback)) { callback(); } }; var o = $.extend({ buttons: { '确定': sure }, alert: true, title: '温馨提示' }, other); html = $('<div class="xq-dialog-alert"></div>').append(html); return html.simpleDialog(o); }; /** * 弹出确认框 * @param {string} html * @param {function} callback * @param {function} onCancel * @param {Object} other */ $.confirm = $.confirmDialog = function(html, callback, onCancel, other){ var sure = function(){ var el = $(this).parents('.confirm-dialog'); $.close(el); if ($.isFunction(callback)) { callback(); } }; var cancel = function(e){ var el = $(this).parents('.confirm-dialog'); $.close(el); if ($.isFunction(onCancel)) { onCancel(); } }; var o = $.extend({ buttons: { '确定': sure, '取消': cancel }, confirm: true, title: '系统提示' }, other); html = $('<div class="xq-dialog-confirm"></div>').append(html); return html.simpleDialog(o); }; var SimpleDialog = Dialog = function(data, opts){ opts = $.extend({}, { dialogTemplate: '<div class="xq-dialog"><div class="xq-dialog-close"></div><div class="xq-dialog-title"></div>' + '<table class="xq-dialog-table"><tr class="handle"><td class="tl"></td><td class="tc"></td><td class="tr"></td></tr><tr><td class="cl">' + '</td><td class="xq-dialog-wapper"><div class="xq-dialog-content"></div></td><td class="cr"></td></tr>' + '<tr><td class="bl"></td><td class="bc"></td><td class="br"></td></tr></table></div>', title: 'simpleDialog', modal: true, x: null, y: null, buttons: null, id: null, ajax: false, ajaxUrl: null, data: {}, iframe: false, iframeUrl: null, width: null, height: null, drag: true, modal: true, onLoad: function(){ }, onClose: function(){ } }, opts); var d = { container: {}, init: function(){ var s = this, temp; s.container.temp = temp = $(opts.dialogTemplate).clone(); $(document.body).append(temp); if (opts.modal) { s.overlay(); } if (opts.iframe) { var iframe = '<iframe src=' + '"' + opts.iframeUrl + '"' + ' style="border:0" id="xq-dialog-iframe" frameborder=0 onload="reinitIframe()"></iframe>'; $('.xq-dialog-content', temp).append(iframe); } else if (opts.ajax) { var divAjaxLoading = $('<div/>').html('<span>加载中,请等待</span>').addClass('ajaxloading'); var callback = function(){ divAjaxLoading.remove(); //加载完成设置尺寸,防止在加载完成之前执行 s.setPosition(opts.x, opts.y, temp); opts.onLoad(); }; $('.xq-dialog-content', temp).append(divAjaxLoading).load(opts.ajaxUrl, opts.data, callback); } else if (opts.alert) { temp.addClass('alert-dialog'); } else if (opts.confirm) { temp.addClass('confirm-dialog'); } else { //防止将页面中的元素移除 temp.addClass('normal-dialog'); } $('.xq-dialog-wapper', temp).append(s.setBtns(opts.buttons)); $('.xq-dialog-content', temp).append(data); s.setDialogAround(temp); s.setPosition(opts.x, opts.y, temp); return temp; }, setDialogAround: function(el){ var s = this; if (opts.id != null) { el.attr('id', opts.id) } $('.xq-dialog-title', el).html(opts.title); if (opts.width != null) { $('.xq-dialog-content', el).width(opts.width); } if (opts.height != null) { $('.xq-dialog-content', el).height(opts.height); } $('.xq-dialog-close', el).click(function(){ s.closeDialog(); }); }, setPosition: function(x, y, el){ //如果给定了top,left值 if (x && y) { el.css({ top: y, left: x }); } //否则居中显示 else { var DOC = document.documentElement, DOCHEIGHT = DOC.clientHeight, DOCWIDTH = DOC.clientWidth, DOCSCROLLTOP = DOC.scrollTop; el.css({ top: (DOCHEIGHT - el.height()) / 2 < 20 ? 20 : (DOCHEIGHT - el.height()) / 2, left: (DOCWIDTH - el.width()) / 2 }); if (ie6) { el.css({ top: (DOCSCROLLTOP + (DOCHEIGHT - el.height()) / 2) < 20 ? 20 : (DOCSCROLLTOP + (DOCHEIGHT - el.height()) / 2) }); } } }, setBtns: function(buttons){ var buttonBar = $('<div/>').addClass('xq-dialog-btnBar'); if (typeof buttons !== 'object' || buttons == null) { return null; } $.each(buttons, function(name, event){ event = $.isFunction(event) ? event : function(){ alert('你所传递的参数不是有效的函数!') }; var button = $('<div>').addClass('btnAction').append('<span class="text">' + name + '</span>').click(event).appendTo(buttonBar); }); return buttonBar; }, getPageSize: function(){ var DOC = document.documentElement, DOCHEIGHT = DOC.clientHeight, DOCWIDTH = DOC.clientWidth, DOCSCROLLHEIGHT = DOC.scrollHeight, DOCSCROLLWIDTH = DOC.scrollWidth, MAXHEIGHT = Math.max(DOCHEIGHT, DOCSCROLLHEIGHT), MAXWIDTH = Math.max(DOCWIDTH, DOCSCROLLWIDTH); return [MAXHEIGHT, MAXWIDTH]; }, overlay: function(){ var s = this; if ($('.xq-dialog-overlay').length > 0) { return; } s.container.overlay = $('<div/>').addClass('xq-dialog-overlay'); if (ie6) { $('html,body').addClass('ie6Fixed'); } $(document.body).append(s.container.overlay); }, closeDialog: function(){ var s = this; //判断页面中显示dialog的数量,以免存在多个dialog时将遮罩移除 if ($('.xq-dialog').not(':hidden').length < 2) { if (s.container.overlay) { s.container.overlay.remove(); } $('.xq-dialog-overlay').remove();//防止关闭首先弹出的对话框 } if (ie6) { $('html,body').removeClass('ie6Fixed'); } if (s.container.temp.hasClass('normal-dialog') && !opts.remove) { s.container.temp.hide(); } else { s.container.temp.remove(); } if (opts && opts.onClose && $.isFunction(opts.onClose)) { opts.onClose(); } } }; return d.init(); } })(jQuery); //初始设置iframe的大小 function reinitIframe(){ var iframe = document.getElementById("xq-dialog-iframe"); $(iframe).height(100).width(300); try { var bHeight = iframe.contentWindow.document.body.scrollHeight; var dHeight = iframe.contentWindow.document.documentElement.scrollHeight; var BW = iframe.contentWindow.document.body.scrollWidth; var DW = iframe.contentWindow.document.documentElement.scrollWidth; var height = Math.max(bHeight, dHeight); var width = Math.max(BW, DW); $(iframe).height(height).width(width).css('overflow', 'hidden'); var el = $(iframe).parents('.xq-dialog'); $.setPosition(null, null, el); } catch (ex) { } }
调用实例:
简单调用
var dialog=$(‘#content’).dialog();
效果:
配置选项
dialogTemplate:’’,//调用的的对话框显示的模板,更改此选项可以改变外观 title: 'simpleDialog',//对话框显示的名称 modal: true,//是否显示遮罩层 x: null,//对话框显示的水平位置 y: null,//对话框显示的垂直位置 buttons: null,//对话框的构造按钮 id: null,//对话框的ID,配置此选项可以展示多个对话框 ajax: false,//配置使用ajax的方式 ajaxUrl: null,//配置ajax的URL data: {},//发送到页面的数据 iframe: false,//配置使用iframe的方式 iframeUrl: null,//配置iframe的URL width: null,//配置对话框的宽度 height: null,//配置对话框的高度 alert: false,//配置是否显示警告框 confirm: false,//配置是否显示确认框 drag: true,//配置对话框是否可以拖动 modal: true,//配置是否显示遮罩 onLoad: function(){},//页面加载完毕执行的回调 onClose: function(){}//对话框关闭执行的回调
构造按钮方式
var o={ buttons:{ ‘确定’:function(){}, ‘取消’:function(){} } } var dialog=$(‘#content’).dialog();
效果
远程装载ajax页面
var dialog=$.ajaxDialog('content.html');
效果图
API有时间会放出,如果对jquery插件比较熟悉的话,看配置选项就知道怎么用了。
/*==================================4.8 同步更新simpleGrid-1.4==================================*/
目前支持的功能有
拖拽列,
JSON数据解析,
固定列,
多表头,
数据转换,
checkbox,radio
各种情况下的复杂查询~
单字段服务器端排序
所有源码~~
/** * @author xing * @date 2011-03-21 * simpleGrid * @version 1.4 * add multiple header * add fixed colmuns * support convert normal table to simplegrid * @method simpleGrid---->return grid object; * @date 2011-03-26 * 修正滚动时表头和内容无法对齐的Bug * 修正固定高度的列和内容无法对齐的Bug * 添加三个公共的方法~~ * @method reload:重载表格数据 * @method keepGrid:保持所有的查询条件重载表格数据 * @method setSelectedCell:获取选中的行内数据进行操作 * 修正解析JSON格式错误的问题 * @method groupTable * //{opts,colIndex,callback} *@date 03-29 * 增加一个可以让表格饱满的属性 * @method getId,获取选中表格行的ID集合 * @return Array; */ (function($){ $.extend($.expr[':'],{ 'hasColspan':function(a){ return a.colspan>0; } }); $.fn.simpleGrid=$.fn.grid=function(o){ if($(this).data('grid')){ return this; }else{ var that=$(this); var grid=new SimpleGrid(that,o); return this; } }; $.fn.changeGrid=function(o){ var that=$(this); that.next('.simpleGrid').remove(); var grid=new SimpleGrid(that,o); return this; }; //public method,重载表格数据 $.fn.reload=function(){ var that=$(this); if(!that.data('grid')){ return this; }else{ var grid=that.data('grid'); grid.s={}; grid.form={}; grid.hiddenForm={}; grid.getData(); }; }; $.fn.getId=function(){ var that=$(this),grid=that.data('grid'),id=[]; if(!grid){ return this; }else{ var selectedCell=grid.getSelectedCell(); $.each(selectedCell,function(i,n){ id.push(n.data('id')); }) return id; } }; //public method,设置选中的行进行操作 $.fn.setSelectedCell=function(type,callback){ var that=$(this),grid=that.data('grid'); if (!grid) { return this; }else{ var selectedCell=grid.getSelectedCell(); if(type=="del"){ if(selectedCell.length==0){ alert('至少选择一条数据进行操作!'); return this; }else{ callback(selectedCell); return this; } }else{ if(selectedCell.length==0||selectedCell.length>1){ alert('只能选择一条数据进行操作!'); return this; }else{ callback(selectedCell[0]); return this; } } } }; //public method,分组进行相关操作 //带修正 $.fn.groupGrid = function(o,colIndex,fun){ var that=$(this); if(that.data('grid')){ return this; } var show=true; var callbackGroup=function(){ $('.data-table-group-more').unbind('click').click(function(e){ e.stopPropagation(); var id=this.id, that=this; if($(this).data('hasLoad')){ if(show){ $('.data-table-body tr').each(function(){ if($(this).attr('rel')==id){ $(this).hide(); } }); $(that).removeClass('data-table-group-less'); show=false; }else{ $('.data-table-body tr').each(function(){ if($(this).attr('rel')==id){ $(this).show(); } }); $(that).addClass('data-table-group-less'); show=true; } }else{ if($.isFunction(fun)){ fun(this); $(this).addClass('data-table-group-less'); } $(this).data('hasLoad',true); } }); }; ///var grid=that.data('grid'), // o=that.data('config'), var colModel=o.colModel; $.extend(colModel[colIndex],{ format:function(val){ return '<span class="data-table-group-more">+</span>'+'<label>'+val+'</label>'; } }); o.callback.push(callbackGroup); that.grid(o); return this; }; //保持相关参数进行表格的刷新 $.fn.keepGrid=function(){ var that=$(this),grid=that.data('grid'),o=that.data('config'); if(!grid){ return this; }else{ o.currentPage=grid.getCurrentPage(); grid.getData(); } }; $.fn.getThLength=function(){ var that=$(this),grid=that.data('grid'),o=that.data('config'); if(!grid){ return this; }else{ return grid.getThLength(); } }; var Overlay = function(el){ var divLoading; el = $(el); var init = function(){ var width = el.width(); var height = el.height(); var offset = el.offset(); divLoading = $('<div/>').css({ 'background': '#fff', 'opacity': 0.8, 'width': width, 'height': height, top: offset.top, left: offset.left, 'position': 'absolute' }).addClass('data-table-overlay').appendTo(document.body); var spanLoading = $('<div>').addClass('data-table-loading').appendTo(divLoading); var spanWidth = spanLoading.width(), spanHeight = spanLoading.height(); spanLoading.css({ left: (width - spanWidth) / 2, top: (height - spanHeight) / 2 }); }; return { init: init, uninit: function(){ $('.data-table-overlay').remove(); } }; }; var SimpleGrid=function(data,config){ var t=data; //t.hide(); var defaults = { //数据响应的url url: '', /** * 期望返回的数据格式 * html,json,xml */ dataType: 'json', /** * 请求的页码 * */ currentPage: 1, /** * 每页请求的数据量 */ pageSize: 50, /** * 发送到服务器的额外的参数 */ param: {}, pagerShow: 8, // checkboxEvent: false, // radioEvent: false, // pager: '.data-table-footer', /** * 构建工具栏上的按钮,数据应该是以下格式 * //string,function,string * [ * {name:"",event:"",icon:""} * ] */ buttons: {}, // width: [], /**************************************************************************************** * 如果是多表头的情况,colModel应该是下面的格式 * //string,string,boolean,function,number,number,boolean,number(string) * [[ * {display:'',name:'',sortable:'',format:'',rowspan:'',colspan:'',checkbox:false,width:""} * ], * [ * {display:'',name:'',sortable:'',format:'',rowspan:'',colspan:'',checkbox:false,width:""} * ]] * *************************************************************************************** * 如果是单表头的情况,colModel应该是下面的格式 * [{ * display:'',name:'',sortable:'',format:'',rowspan:'',colspan:'',checkbox:false,width:"" * },{ * display:'',name:'',sortable:'',format:'',rowspan:'',colspan:'',checkbox:false.width:"" * }] * 判断是多列还是单列,只需判断其子元素是数组还是对象即可 * **************************************************************************************** * 为了可以转换普通的table到simpleGrid,需要将负责解析的方法与构建表头的方法分离开。 * 而且其中为DOM绑定的事件也应该分离开。 * 为了减少工作量,我们可以将表头构建为带有自定义标记的HTML,然后用负责解析的方法将其转换为simpleGrid * 为了实现多数据源。需要将getData分离 * 添加一个独立的方法,负责向grid中增加数据 */ colModel: [], /** * 如果配置了固定位置的列,其视图应该分开 * 每一个视图都应该有data-table-header,data-table-body,data-table-footer * ************************************************************************************** * 我们应该让右侧的视图overflow:auto * 这样左侧的视图会在右侧视图滚动的时候固定 * 而右侧的视图在上下滚动的时候应该动态改变左侧视图的scrollTop,以便滚动时保持一致 * fixCol的格式与colModel一致 */ fixedCol:[], fix:false, fixParent:false, //scroll: true, simpleSearch: true, simpleSearchKey:[{'name':'name','type':'input'}], complexSearch: false, complexSearchForm: '', hiddenForm: '', pagination:true, pagerStyle: 'line', totalPage: '', fixHeight: 200, colDrag: false, colResize: true, fixWidth:true, header:true, showOrHideCol: true,//待修正 dblclick:function(){ }, callback: function(){ }, onError: function(){ } }; var classConfig = { toolsClass: 'data-table-tools', viewClass:'data-table-views', headerClass: 'data-table-header', bodyClass: 'data-table-body', footerClass: 'data-table-footer', tdHoverClass: 'td-hover-class', trClickClass: 'tr-click-class', oddClass: 'data-table-odd', evenClass: 'data-table-even', highlightClass: 'data-table-hightlight', buttonClass: 'simple-button', simpleSearchDivClass: 'simpleSearchDiv', complexSearchDivClass: 'complexSearchDiv', sortableHoverASCClass: 'sortableHoverASC', sortableHoverDESCClass: 'sortableHoverDESC' }; var o = $.extend({}, defaults, classConfig, config); var grid={ multiple:false, hiddenForm:{}, g:{ tableHeader:[] },//grid存储器 s:{},//排序存储器sortManage d:{ colDrag:false, proxy: $('<div/>').addClass('proxy'), resizeProxy:$('<div/>').addClass('resizeProxy') },//拖放存储器dragManage //初始化函数 init:function(){ var s=this; s.buildGridToolBar(); s.buildGridBody(); s.buildGridPager(); s.parseHeader(); var simpleGrid=$('<div/>').addClass('simpleGrid'); simpleGrid.append(s.g.gridTools).append(s.g.gridBody).append(s.g.gridPager); s.g.simpleGrid=simpleGrid; t.after(simpleGrid); t.empty().hide(); t.grid=grid; t.o=o; s.getData(); }, getSelectedCell:function(){ var s=this,selectedCell=[]; $(':checkbox',s.g.gridView1).each(function(){ if($(this).attr('checked')){ var tr=$(this).parents('tr'); selectedCell.push(tr); } }); return selectedCell; }, getThLength:function(){ return $('.data-table-body tr').eq(0).find('td').length; }, fixAll:function(){ var s=this; var fullPageGrid=function(){ var height=$('table',s.g.gridView2).eq(0).outerHeight(); $('table',s.g.gridView1).eq(0).height(height); var dataView2Width=$('.data-table-body',s.g.gridView2).width(); $('.data-table-header',s.g.gridView2).width(dataView2Width); var pageHeight=document.documentElement.clientHeight; var toolsHeight=0,footerHeight=0; if(o.header){ toolsHeight=s.g.gridTools.height(); } if(o.pagination){ footerHeight=s.g.gridPager.height(); } var headHeight=s.g.tableHeader[0].height(); var parentHeight=s.g.simpleGrid.parent().height(); if(o.fix){ $('.data-table-body',s.g.gridBody).height(pageHeight-toolsHeight-footerHeight-headHeight-20); } if(o.fixParent){ $('.data-table-body',s.g.gridBody).height(parentHeight-toolsHeight-footerHeight-headHeight-20); } //var width=$('.data-table-body table',s.g.gridView2).outerWidth(); //$('.data-table-body',s.g.gridView2).width(width); }; // // fullPageGrid(); // $(window).resize(fullPageGrid); setInterval(fullPageGrid,100); if(o.fixWidth){ var fixWidthFun=function(){ var width=s.g.simpleGrid.width()-45,perWidth=width/s.g.gridWidthTotal; var tr1=$('tr',s.g.gridView1); var cols1=s.getHeaderTh(tr1); $(cols1).each(function(i){ var tw=$(this).find('.th-wapper'); fwidth=parseInt(tw.data('width')*perWidth); tw.width(fwidth); $('.data-table-body tr',s.g.gridView1).each(function(){ $('td',this).eq(i).find('.td-text').width(fwidth); }); }); var tr2=$('tr',s.g.gridView2); var cols=s.getHeaderTh(tr2); $(cols).each(function(i){ var tw=$(this).find('.th-wapper'); fwidth=parseInt(tw.data('width')*perWidth); tw.width(fwidth); $('.data-table-body tr',s.g.gridView2).each(function(){ $('td',this).eq(i).find('.td-text').width(fwidth); }); }); }; fixWidthFun(); $(window).resize(fixWidthFun); } return this; }, tdEvent:function(){ var s=this; $('td',s.g.gridBody).hover(function(){ var index=$(this).attr('index'); $(this).addClass(o.tdHoverClass); $('td[index="'+index+'"]',s.g.gridBody).addClass(o.tdHoverClass); },function(){ var index=$(this).attr('index'); $(this).removeClass(o.tdHoverClass); $('td[index="'+index+'"]',s.g.gridBody).removeClass(o.tdHoverClass); }).click(function(e){ if(e.target.nodeName=="INPUT"){ return; } var index=$(this).attr('index'); var checkbox=$('.data-table-body tr',s.g.gridBody).eq(index).find(':checkbox'); if(checkbox.attr('checked')){ checkbox.attr('checked',''); $('td[index="'+index+'"]',s.g.gridBody).removeClass(o.trClickClass); checkbox.trigger('change'); }else{ checkbox.attr('checked','checked'); $('td[index="'+index+'"]',s.g.gridBody).addClass(o.trClickClass); checkbox.trigger('change'); } }); $('.data-table-body :checkbox',s.g.gridBody).change(function(){ var index=$(this).parents('td').attr('index'); if($(this).attr('checked')){ $('td[index="'+index+'"]',s.g.gridBody).addClass(o.trClickClass); }else{ $('td[index="'+index+'"]',s.g.gridBody).removeClass(o.trClickClass); } }); return s; }, /** * 负责将colModel转换成HTML */ buildTableHeader:function(model){ var gridHeader,s=this; gridHeader = $('<div/>').addClass(o.headerClass).css('position','relative').append('<div class="data-table-header-inner"><table><thead></thead></table></div>'); //css(relative) if(model){ var trs=$('<tr/>'),width=0; $.each(model,function(index,item){ //判断是多表头还是单表头 if($.isArray(item)){ s.multiple=true; var tr=$('<tr/>'); $.each(item,function(i,n){ var th=s.setThElement(n); if(typeof n.width == 'number'){ width+=n.width; } // $(th).attr('col-index',index); tr.append(th); }); $('thead',gridHeader).append(tr); }else{//is object 单表头 if(typeof item.width == 'number'){ width+=item.width; } var th=s.setThElement(item); // $(th).attr('col-index',index); trs.append(th); $('thead',gridHeader).append(trs); } }); s.g.gridWidthTotal=width; } s.g.tableHeader.push(gridHeader); return gridHeader; }, //如果table没有表头将colModel转换成表头 setThElement:function(item){ var s=this; var th=document.createElement('th'); if(item.name){ $(th).attr('name',item.name); } if(item.rowspan){ $(th).attr('rowspan',item.rowspan); } if(item.checkbox){ $(th).append('<div style="width:20px;"><input type="checkbox" name="'+item.name+'"/></div>').attr('type','checkbox'); $(':checkbox',th).change(function(){ var that=$(this); if(that.attr('checked')){ $('.data-table-body :checkbox',s.g.gridBody).attr('checked','checked'); }else{ $('.data-table-body :checkbox',s.g.gridBody).attr('checked',''); } $('.data-table-body :checkbox',s.g.gridBody).change(); }); return th; } if(item.radio){ $(th).append('<div style="width:20px;"></div>').width(20).attr('type','radio'); return th; } if(item.display){ $(th).append('<div class="th-wapper"></div>') $('.th-wapper', th).append('<div class="text">' + item.display + '</div>').append('<span></span>'); } if(item.format){ $(th).data('format',item.format); } if(item.sortable){ $(th).attr('sortable',item.sortable); } if(item.width){ if(o.fixWidth){ $('.th-wapper',th).data('width',item.width); }else{ $('.th-wapper',th).width(item.width); } } if(item.colspan){ $(th).attr('colspan',item.colspan); $(th).attr('colResize','disabled'); $('.th-wapper',th).data('width','auto'); $('.th-wapper',th).width('auto'); //th.colspan=item.colspan } if(item.align){ $(th).attr('tdAlign',item.align); } return th; }, /** * 解析带有自定义标记的HTML * 顺带绑定事件 */ parseHeader:function(){ var s=this,gh=s.g.tableHeader; if(gh){ $.each(gh,function(i,n){ $('th',n).each(function(){ var that=this; if($(that).attr('sortable')){ //$(s.s).extend({ // sortName:that.name, // dir:'asc' //}); $(that).data('order','asc'); $('.text',that).click(function(){ s.w.sort(that); }); } $(that) .mouseover(function(){ if(s.d.colDrag){ s.d.to=this; $(this).addClass('data-table-drag-over'); }else if(!s.d.colResize){ $(this).addClass('data-table-over'); } }) .mouseout(function(){ $(this).removeClass(); }); if(o.colDrag){ $(that).mousedown(function(e){ s.d.colDrag=true; s.w.drag(e,'colDrag'); }); } if(o.colResize){ $('span', that).mousedown(function(e){ if($(that).attr('colresize')=="disabled"){ return; } e.stopPropagation(); s.w.drag(e, 'colResize'); }); } }); }); } }, getHeaderTh:function(tr){ var cols=[],index=0,subIndex=0,totalIndex=0; tr.eq(0).find('th').each(function(i){ if($(this).attr('colspan')>1){ $(this).attr('col-index',index); index++; } }); tr.eq(0).find('th').each(function(){ if($(this).attr('colspan')>1&&$(this).attr('col-index')>-1){ getsubCol($(this)); }else{ cols.push($(this)); } }); function getsubCol(el){ var colIndex=el.attr('col-index'); colspan=el.attr('colspan'); totalIndex=totalIndex*1+colspan*1; for(var i=subIndex;i<totalIndex;i++){ cols.push(tr.eq(1).find('th').eq(i)); } subIndex=subIndex*1+colspan*1; } return cols; }, buildGridToolBar:function(){ var s = this; if(o.header){ var gridTools = $('<div/>').addClass(o.toolsClass); if (o.buttons != null) { $.each(o.buttons, function(i, n){ var divBtn = $('<div/>').addClass(o.buttonClass).append('<span class="simple-button-text">' + n.name + '</span>'); if ($.isFunction(n.event)) { divBtn.click(n.event).hover(function(){ $(this).addClass('simple-button-hover'); },function(){ $(this).removeClass('simple-button-hover'); }); } if(n.disabled){ divBtn.addClass('simple-button-disabled'); // divBtn.unbind(); // var condition = n.condition(); // console.log(condition) //if(condition){ // divBtn.click(n.event); // divBtn.removeClass('simple-button-disabled'); // } } if (n.icon != null) { divBtn.prepend('<span class="simple-button-icon ' + n.icon + '"></span>'); } gridTools.append(divBtn); }); } //简单单字段查询 if (o.simpleSearch) { var divSearch = $('<div/>').addClass('simpleSearchFormDiv'); $.each(o.simpleSearchKey,function(i,n){ if(n.type=="input"){ var input = $('<input/>').attr('name', n.name).addClass('text'); divSearch.append(input); } }); //simpleSearchKey = o.simpleSearchKey || 'name'; var a = $('<a/>').addClass('simpleSearch').html('查询'); divSearch.append(a); a.click(function(){ s.form = $.json(divSearch[0]); s.getData(); }); gridTools.append(divSearch); } if(o.complexSearch){ $('a.query',s.g.simpleGrid).click(function(){ s.form=$.json($(o.complexSearchForm)); s.getData(); }); } s.g.gridTools = gridTools; return gridTools; } }, buildGridBody:function(){ var s=this; s.buildGridView(); //如果配置了colModel if(o.colModel){ var viewThead2=s.buildTableHeader(o.colModel); s.g.gridView2.append(viewThead2); s.g.gridView2.append('<div class="data-table-body"><table><tbody></tbody</table></div>'); if(o.fixCol){ var viewThead1=s.buildTableHeader(o.fixCol); s.g.gridView1.append(viewThead1); s.g.gridView1.append('<div class="data-table-body"><div class="data-table-body-innder"><table><tbody></tbody</table></div></div>'); }else{ s.g.gridView1.width(0).height(0); } } //如果都没有配置从thead里找 else{ if($('thead',t)[0]!=null){ s.g.gridView2.append('<div class="'+o.headerClass+'"></div>') .find('.'+o.footerClass).append($('thead',t)); } else if($('tbody',t)[0!=null]){ s.g.gridView2.append('<div class="data-table-body"></div>') .find('.data-table-body').append($('tbody',t)); } } $('.data-table-body',s.g.gridBody).height(o.fixHeight); $('.data-table-body',s.g.gridView2).scroll(function(){ var scrollTop=this.scrollTop; $('.data-table-body',s.g.gridView1).scrollTop(scrollTop); var scrollLeft=this.scrollLeft; $('.data-table-header',s.g.gridView2).scrollLeft(scrollLeft); var dataTableBodyView2Width=$('.data-table-body table',s.g.gridView2).width(); //$('.data-table-header table',s.g.gridView2).width(dataTableBodyView2Width-36); }); }, buildGridView:function(){ var s=this; var divBody=$('<div/>').addClass('data-table-wapper'); var divView1=$('<div/>').addClass('data-table-view1'); var divView2=$('<div/>').addClass('data-table-view2'); divBody.append(divView1).append(divView2); s.g.gridView1=divView1; s.g.gridView2=divView2; s.g.gridBody=divBody; }, buildGridPager:function(){ if (o.pagination) { var s = this; var p = $('<div/>').addClass(o.footerClass).append('<div class="data-table-pager"></div><div class="data-table-info"></div>'); var first = $('<a/>').addClass('page-first pageA'), prev = $('<a/>').addClass('page-prev pageA'), next = $('<a/>').addClass('page-next pageA'), last = $('<a/>').addClass('page-last pageA'); $('.data-table-pager',p).prepend(first).prepend(prev).append(next).append(last); s.g.gridPager = p; return p; } }, mixData: function(){ var s = this; s.hiddenForm=$.json(o.hiddenForm); var pdata = $.extend({}, { "currentPage": o.currentPage, "pageSize": o.pageSize }, o.param); // if (o.type == 'action') { // pdata = $.extend({}, pdata, { // currentPage: s.getCurrentPage() // }); // } var sdata = $.extend({}, pdata,s.hiddenForm, s.s, s.form); return sdata; }, addData:function(data){ var s=this; s.parseJSON(data); }, getData:function(){ var s = this, data = s.mixData(); $.ajax({ url: o.url, data: data, type: 'post', cache:false, beforeSend: function(){ // if (datacontainer.find('tr').length >= 1) { Overlay(s.g.simpleGrid).init(); //.init(); //} }, // dataType: o.dataType, success: function(datas){ s.addData(datas); Overlay(s.g.simpleGrid).uninit(); s.fixAll().tdEvent(); setTimeout(function(){ if($.isFunction(o.callback)){ o.callback(); }else if($.isArray(o.callback)){ $.each(o.callback,function(i,k){ k(); }); } },200) }, error: function(data){ alert('返回的数据格式不对或者服务器繁忙!'); } }); }, parseJSON:function(data){ var s = this; //待修正 // datacontainer.empty(); $('tbody',s.g.gridBody).empty(); $('.noData').remove(); if (!$.isArray(data)) { data = eval('(' + data + ')'); data=data[0]; } if(data.length<1){ s.g.gridBody.find('.data-table-body').append('<div class="noData"><div>没有任何数据显示!</div></div>'); return false; } var totalPage = data.totalPage, currentPage = data.currentPage, pageSize = data.pageSize, totalCount=data.totalCount, data = data.list; s.g.totalCount=totalCount; var pageInfo=pageSize*(currentPage-1)+1*1; pageInfo2=pageSize*currentPage>totalCount?totalCount:pageSize*currentPage; $('.data-table-info',s.g.gridPager).html('共有'+totalCount+'条数据,当前显示'+pageInfo+'~'+pageInfo2+'条'); $.each(data,function(index,item){ var tr = $('<tr/>').dblclick(o.dblclick); var thView1Tr=$('.data-table-header tr',s.g.gridView1); var cols=s.getHeaderTh(thView1Tr); $(cols).each(function(){ var that = $(this); if(that.attr('type')=="checkbox"){ var td=$('<td/>').html('<div style="width:20px;text-align:center;"><input type="checkbox" name="'+that.attr('name')+'"/></div>').attr('index',index); tr.append(td); } if(that.attr('type')=="radio"){ var td=$('<td/>').html('<div style="width:20px;text-align:center;"><input type="radio" name="'+that.attr('name')+'" class="data-table-radio"/></div>').attr('index',index); tr.append(td); } $.each(item, function(key, value){ if (key=="id"){ tr.data('id',value); } if (that.attr('name') == key) { if ($.isFunction(that.data('format'))) { if(value=='null'){ value=""; } value = that.data('format').call(this, value); } var td = $('<td/>').html('<div class="td-text">' + value + '</div>').attr({ 'name': that.attr('name'), 'index':index, 'align':that.attr('tdalign') }); tr.append(td); } }); }); $('.data-table-body tbody',s.g.gridView1).append(tr); var tr2= $('<tr/>').dblclick(o.dblclick); var thView2Tr=$('.data-table-header tr',s.g.gridView2); var cols2=s.getHeaderTh(thView2Tr); $(cols2).each(function(){ var that = $(this); if(that.attr('type')=="checkbox"){ var td=$('<td/>').html('<div style="width:20px;text-align:center;"><input type="checkbox" name="'+that.attr('name')+'"/></div>').attr('index',index); tr2.append(td); } if(that.attr('type')=="radio"){ var td=$('<td/>').html('<div style="width:20px;text-align:center;"><input type="radio" name="'+that.attr('name')+'" class="data-table-radio"/></div>').attr('index',index); tr2.append(td); } $.each(item, function(key, value){ if (key=="id"){ tr2.data('id',value); } if (that.attr('name') == key) { if ($.isFunction(that.data('format'))) { if(value=='null'){ value=""; } value = that.data('format').call(this, value); } var td = $('<td/>').html('<div class="td-text">' + value + '</div>').attr({ 'name': that.attr('name'), 'index':index, 'align':that.attr('tdalign') }); tr2.append(td); } }); }); $('.data-table-body tbody',s.g.gridView2).append(tr2); }); s.setPageStyle(o.pagerStyle, o.pagerShow, totalPage, currentPage); }, setPageStyle: function(style, pageshow, totalPage, currentPage){ if (style == "click") { // 待修正 } if (style == "line") { line.setLine(totalPage, currentPage, pageshow); } }, getCurrentPage: function(){ return this.g.currentPage; }, w: { drag: function(e, type){ var s = this, d = grid.d,w=grid.w; if (type == 'colDrag') { d.from = $(e.currentTarget)[0]; $(d.from).addClass("drag"); } if (type == 'colResize') { var x = $(e.target).offset().left; // console.log(e.target) d.colLeft = x; d.colWidth = $(e.target).parents('th').width(); d.target = $(e.target).parents('th'); d.colResize = true;//判断是否是拖放的标志 } $(document).mousemove(function(e){ w.dragmove(e, type); }); $(document).mouseup(function(e){ w.dragstop(e, type); }); }, dragmove: function(e, type){ var s = this, d= grid.d, w = grid.w; if (type == "colDrag") { var proxy = d.proxy; //console.log(proxy) proxy.css({ left: e.pageX + 20, top: e.pageY + 10 }).appendTo(document.body).show(); proxy.html($(d.from).html()) } else if (type == "colResize") { $(document.body).css('cursor', 'col-resize'); d.resizeProxy.css({ width:0, 'border-left':'1px solid #cc0000', height:grid.g.gridBody.height(), 'position':'absolute', 'top':0, 'left':e.pageX-grid.g.gridBody.offset().left }).appendTo(grid.g.gridBody).show(); } w.noselect(document.body); }, dragstop: function(e, type){ var s=grid;that=this; // console.log(grid) $(document).unbind('mousemove').unbind('mouseup'); if(type=="colDrag"){ grid.d.proxy.hide(); }else if(type=="colResize"){ $(document.body).css('cursor','default'); grid.d.resizeProxy.hide(); var addWidth=parseInt(e.pageX-grid.d.colLeft); var table2=$('.data-table-body table',s.g.gridView2),table2Width=table2.width(); //console.log(grid.d) //console.log(addWidth) // $('.th-wapper',grid.d.target).width(grid.d.colWidth+addWidth); var thName=grid.d.target.attr('name'); var select='.data-table-body table'; that.setWidth(select,s.g.gridView2,thName,addWidth); // that.setWidth(select,s.g.gridView1,thName,addWidth); // $('td[name="'+thName+'"] .td-text',s.g.gridView2).width(grid.d.target.width()); table2.width(table2Width+addWidth); } }, setWidth:function(select,context,thName,addWidth){ var table=$(select,context),tableWidth=table.width(); $('.th-wapper',grid.d.target).width(grid.d.colWidth+addWidth); $('td[name="'+thName+'"] .td-text').width(grid.d.target.width()); //table.width(tableWidth+addWidth); }, //拖动过程中不选中文字 noselect: function(target){ if (typeof target.onselectstart != "undefined") //IE route target.onselectstart = function(){ return false } else if (typeof target.style.MozUserSelect != "undefined") //Firefox route target.style.MozUserSelect = "none" else //All other route (ie: Opera) target.onmousedown = function(){ return false } //target.style.cursor = "default" }, sort: function(el){ var g = grid,el=$(el); // $('.text', g.g.gridHeader).removeClass(); if (el.data('order') == 'asc') { $.extend(g.s, { sort: el.attr('name'), dir: 'desc' }); el.data('order', 'desc') el.find('.text').removeClass('asc').addClass('desc'); g.getData(); } else { $.extend(g.s, { sort: el.attr('name'), dir: 'asc' }); el.data('order', 'asc') el.find('.text').removeClass('desc').addClass('asc'); g.getData(); } } } }; var line = { setLine: function(totalPage, currentPage, pageshow){ grid.g.currentPage = currentPage; var g = grid,page = $('.data-table-pager',g.g.gridPager); page.empty(); var s = this, displayPage = s.getLimit(pageshow, totalPage, currentPage); // console.log(displayPage) for (var i = displayPage.start; i <= displayPage.end; i++) { var a = $('<a/>').html('<span>' + i + '</span>').addClass('pageA').bind('click', function(){ //wait; //console.log('ccc') o.currentPage = g.g.currentPage = $(this).text(); grid.getData(); }); //当前页 if (i == currentPage) { a.addClass('pageActive'); } page.append(a); } var pageCount = $('<a/>').html('<span>' + currentPage + '/' + totalPage + '</span>').addClass('pageA'); var first = $('<a/>').html('<span>首页</span>').addClass('pageA').data('first', 'first').click(function(){ o.currentPage = g.g.currentPage = 1; grid.getData(); }); var prev = $('<a/>').html('<span>上一页</span>').addClass('pageA').data('prev', 'prev').click(function(){ var currentPage = grid.getCurrentPage(); o.currentPage = g.g.currentPage = currentPage - 1 < 0 ? totalPage : currentPage - 1;//如果当前页为首页,上一页返回到最后一页 grid.getData(); }); var next = $('<a/>').html('<span>下一页</span>').addClass('pageA').data('next', 'next').click(function(){ var currentPage = grid.getCurrentPage(); // console.log(currentPage) o.currentPage = g.g.currentPage = currentPage * 1 + 1 > totalPage ? totalPage : currentPage * 1 + 1;//如果当前页为末页, grid.getData(); }); var last = $('<a/>').html('<span>末页</span>').addClass('pageA').data('last', 'last').click(function(){ o.currentPage = g.g.currentPage = totalPage; grid.getData(); }); page.prepend(prev).prepend(first).prepend(pageCount).append(next).append(last); }, getLimit: function(pageShow, totalPage, start){ // var start = parseInt(o.pager.find('a.pageActive').text()); start = parseInt(start - pageShow / 2) < 0 ? 1 : parseInt(start - pageShow / 2); if (start + o.pageShow > totalPage) { start = totalPage - pageShow < 0 ? 1 : totalPage - pageShow; } var end = (start + pageShow) > totalPage ? totalPage : start + pageShow; return { start: start, end: end } } } grid.init(); t.data('grid',grid); t.data('config',o); }; $.json = function(form){ //判断是否有序列化的东东 if (!$(form).html() || $(form).html() == null || $.trim($(form).html()) == "") { return null; } var formEl = $(form).find('input[type="text"],input[type="hidden"]'); var formselect = $(form).find('select'); var json = "{"; if (formEl.length > 1) { for (var i = 0; i < formEl.length - 1; i++) { var name = formEl.eq(i).attr('name'); var val = "'" + formEl.eq(i).val() + "'"; json += name; json += ":"; json += val; json += ","; } } var lname = formEl.eq(formEl.length - 1).attr('name'); var lval = "'" + formEl.eq(formEl.length - 1).val() + "'"; json += lname; json += ":"; json += lval; if (formselect) { json += ","; if (formselect.length > 1) { for (var i = 0; i < formselect.length - 1; i++) { var name = formselect.eq(i).attr('name'); var val = "'" + formselect.eq(i).val() + "'"; json += name; json += ":"; json += val; json += ","; } var lname = formselect.eq(formselect.length - 1).attr('name'); var lval = "'" + formselect.eq(formselect.length - 1).val() + "'"; json += lname; json += ":"; json += lval; } } json += "}"; var jsonObj = eval("(" + json + ")"); return jsonObj; }; })(jQuery);
关于表格控件,我觉得最重要的就是数据的解析~~其他的功能都是附加的。
数据怎么样才能显示在正确的位置呢~~尤其是多表头的情况,更加棘手~
下面是我的解决方法
只要按照表头顺序去对比数据就可以。关键就是对表头的重排序~
首先观察表格头部的结构,按照顺序遍历,并将其push到新的对象中~当发现有colspan>1(因为默认=1)的表头,找到其子列,并将它们push到新的对象中~
这样得到的新对象便是排好顺序的表头~(这部分代码没有优化!!)
getHeaderTh:function(tr){ var cols=[],index=0,subIndex=0,totalIndex=0; tr.eq(0).find('th').each(function(i){ if($(this).attr('colspan')>1){ $(this).attr('col-index',index); index++; } }); tr.eq(0).find('th').each(function(){ if($(this).attr('colspan')>1&&$(this).attr('col-index')>-1){ getsubCol($(this)); }else{ cols.push($(this)); } }); function getsubCol(el){ var colIndex=el.attr('col-index'); colspan=el.attr('colspan'); totalIndex=totalIndex*1+colspan*1; for(var i=subIndex;i<totalIndex;i++){ cols.push(tr.eq(1).find('th').eq(i)); } subIndex=subIndex*1+colspan*1; } return cols; }
未完待续(。。。)工作了~~