`
dingchao.lonton
  • 浏览: 49688 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

怎么样用扩展的方式来扩展OperaMasksUI的grid

阅读更多

前面我写了一篇文章来扩展OpreaMasksUI的grid的排序功能和显示详情的功能,不清楚的可以看下我博客的另外一篇文章:http://dingchao-lonton.iteye.com/admin/blogs/1345088,但是我修改的时候污染了原来的代码,我觉得这种方式很不好,所以我就用jquery ui的widget factory提供的继承方式来扩展,这样原来的代码可以保持干净;

 

javasscript代码如下:

 

 

/*
 * $Id: om-grid.js,v 1.97 2012/01/04 03:28:04 zhoufazhi Exp $
 * operamasks-ui omGrid @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://ui.operamasks.org/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://ui.operamasks.org/license
 *
 * http://ui.operamasks.org/docs/
 * 
 * Depends:
 *  jquery.ui.widget.js
 *  jquery.ui.core.js
 *  jquery.ui.mouse.js
 *  jquery.ui.resizable.js
 *  om-grid.js
 */ 
/**
     * @name omGridExtend
     * @author ding chao
     * @class 表格组件。扩展自om.omGrid,增加了排序和显示详情功能<br/><br/>
     * <b>示例:</b><br/>
     * <pre>
     * &lt;script type="text/javascript" >
     *   $('#grid').omGridExtend({
	 *			//是否显示详情
	 *			showDetail:true,
	 *			singleSelect:false,
     *          dataSource : 'griddata.do?method=fast',
     *           colModel : [ {header : 'ID', name : 'id', width : 100, align : 'center'}, 
     *                        {header : '地区', name : 'city', width : 120, align : 'center'}, 
     *                        {header : '地址', name : 'address', align : 'center', width : 'autoExpand'} ],
     *				onRowClick:function(index,row){
	 *				
	 *			},
	 *			onRowSelect:function(){
	 *				
	 *			},
	 *			onRowDeselect:function(){
	 *				
	 *			},
	 *			//当详情展开的时候调用的回调
	 *			onDetailExpand:function(rowData,row){
	 *				
	 *			},
	 *			//初始化的时候以哪一个字段排序
	 *			sortName:'address',
	 *			//排序方式
	 *			sortOrder:'desc',
	 *			method:'get',
	 *			onRowCheck:function(index){
	 *				
	 *			}
     *      });
     * &lt;/script>
     * 
     * &lt;table id="mytable"/>
     * </pre>
     * 
     */
;(function($) {
    $.widget('om.omGridExtend',$.om.omGrid, {
        options:/** @lends omGridExtend#*/{
			/**
			  *是否显示详情
			  *@default false
			  *@type Boolean
			  *@example
			  *$('.selector').omGrid({showDetail : false});
			  */
			showDetail:false,
			/**
			  *详情展开的时候是否重新加载
			  *@default true
			  *@type Boolean
			  *@example
			  *$('.selector').omGrid({detailExpandReload : false});
			  */
			detailExpandReload:true,
            /**
			  *详情展开时候的回调函数
			  *@default function(rowData,detailContainer){}
			  *@type Function
			  *@example
			  *$('.selector').omGrid({onDetailExpand : function(rowData,detailContainer){}});
			  */
			onDetailExpand : function(rowData,detailContainer){},
			/**
			  *初始化的时候以哪个字段作为排序字段
			  *@default null
			  *@type String
			  *@example
			  *$('.selector').omGrid({sortName : 'address'});
			  */
			sortName:null,
			/**
			  *排序方式  enmu{"desc","asc"}
			  *@default asc
			  *@type String
			  *@example
			  *$('.selector').omGrid({sortName : 'address'});
			  */
			sortOrder:'asc'
        },
        //private methods
        _create:function(){
			//call super method
			$.om.omGrid.prototype._create.call(this);

            this._bindHeadClickEnvent();
			this._bindDetailEvent();
        },
        _buildTableHead:function(){
            var op=this.options,
                el=this.element,
                grid = el.closest('.om-grid'),
                cms=op.colModel,
                allColsWidth = 0, //colModel的宽度
                indexWidth = 0, //colModel的宽度
                checkboxWidth = 0, //colModel的宽度
                autoExpandColIndex = -1;
                thead=$('<thead></thead');
                tr=$('<tr></tr>').appendTo(thead);
				this.detailColSpan = 0;
			//渲染显示明细列
			if(op.showDetail){
				var cell = $('<th></th>').attr({axis:'detailCol',align:'center'}).addClass('unsort detailCol').append($('<div class="indexheader" style="text-align:center;width:25px;"></div'));
				tr.append(cell);
                indexWidth=25;
				this.detailColSpan++;
			}
            //渲染序号列
            if(op.showIndex){
                var cell=$('<th></th').attr({axis:'indexCol',align:'center'}).addClass('unsort indexCol').append($('<div class="indexheader" style="text-align:center;width:25px;"></div'));
                tr.append(cell);
                indexWidth=25;
				this.detailColSpan++;
            }
            //渲染checkbox列
            if(!op.singleSelect){
                var cell=$('<th></th').attr({axis:'checkboxCol',align:'center'}).addClass('unsort checkboxCol').append($('<div class="checkboxheader" style="text-align:center;width:17px;"><span class="checkbox"/></div'));
                tr.append(cell);
                checkboxWidth=17;
				this.detailColSpan++;
            }
            //渲染colModel各列
            for (var i=0,len=cms.length;i<len;i++) {
                var cm=cms[i],cmWidth = cm.width || 60,cmAlign=cm.align || 'center';
                if(cmWidth == 'autoExpand'){
                    cmWidth = 0;
                    autoExpandColIndex = i;
                }
                var thCell=$('<div></div').html(cm.header).css({'text-align':cmAlign,width:cmWidth});
				if(this.options.sortName && this.options.sortName === cm.name){
					if(this.options.sortOrder === 'asc'){
						thCell.addClass('sasc');
					}else{
						thCell.addClass('sdesc');
					}
				}
                cm.wrap && thCell.addClass('wrap');
                var th=$('<th></th').attr('axis', 'col' + i).addClass('col' + i).append(thCell);
                if(cm.name) {
                    th.attr('abbr', cm.name);
                }
                if(cm.align) {
                    th.attr('align',cm.align);
                }
                //var _div=$('<div></div>').html(cm.header).attr('width', cmWidth);
                allColsWidth += cmWidth;
                tr.append(th);
				this.detailColSpan++;
            }
            //tr.append($('<th></th'));
            el.prepend(thead);
            
            var hDiv = $('<div class="hDiv om-state-default"></div>').append('<div class="hDivBox"><table cellPadding="0" cellSpacing="0"></table></div>');
            el.parent().before(hDiv);
            
                $('table',hDiv).append(thead);
            //修正各列的列宽
            if(autoExpandColIndex != -1){ //说明有某列要自动扩充
                var tableWidth=grid.width()-20,
                    //usableWidth=tableWidth-allColsWidth-indexWidth-checkboxWidth;
                    usableWidth=tableWidth-thead.width();
                    toBeExpandedTh=tr.find('th[axis="col'+autoExpandColIndex+'"] div');
                if(usableWidth<=0){
                    toBeExpandedTh.css('width',60);
                }else{
                    toBeExpandedTh.css('width',usableWidth);
                }
            }else if(op.autoFit){
                //var tableWidth=el.width(),
                 //   usableWidth=tableWidth-indexWidth-checkboxWidth;
                var tableWidth=grid.width()-20,
                    usableWidth=tableWidth-thead.width(),
                    percent=1+usableWidth/allColsWidth,
                    toFixedThs=tr.find('th[axis^="col"] div');
                for (var i=0,len=cms.length;i<len;i++) {
                    var col=toFixedThs.eq(i);
                    col.css('width',parseInt(col.width()*percent));
                }
            }
            this.thead=thead;
            thead = null;
        },
		_bindHeadClickEnvent:function(){
			var self = this,
				op = this.options;
			this.thead.delegate('th:not(.unsort)','click',function(event){
				var abbr = $(this).attr('abbr');
				op.sortName = abbr;
				$('th>div',self.thead).removeClass('sasc').removeClass('sdesc');
				op.sortOrder === 'asc' ? (op.sortOrder = 'desc',$('>div',this).addClass('sdesc')):(op.sortOrder = 'asc',$('>div',this).addClass('sasc'));
				self._populate();
			});
			 
		},
		_renderDatas:function(from,to){
            var self=this,
                el=this.element,
                op=this.options,
                grid=el.closest('.om-grid'),
                gridHeaderCols=$('.hDiv thead tr:first th',grid),
                rows=this.pageData.data.rows,
                colModel=op.colModel,
                rowClasses=op.rowClasses,
                tbody=$('tbody',el).empty(),
                isRowClassesFn= (typeof rowClasses === 'function'),
                pageData = this.pageData,start=(pageData.nowPage-1)*op.limit;
            $.each(rows,function(i, rowData) {
                var rowCls = isRowClassesFn? rowClasses(i,rowData):rowClasses[i % rowClasses.length];
                var tr=$('<tr></tr>').addClass('om-grid-row').addClass(rowCls).attr('rowindex',i);
                var rowValues=self._buildRowCellValues(colModel,rowData,i);
                $(gridHeaderCols).each(function(){
                    var axis = $(this).attr('axis'),wrap=false,html;
					if(axis == 'detailCol'){
						 html = '<span class="detailIcon collapsed"/>';
					}
                    else if(axis == 'indexCol'){
                        html=i+start+1;
                    }else if(axis == 'checkboxCol'){
                        html = '<span class="checkbox"/>';
                    }else{
                        var colIndex=axis.substring(3);
                        html=rowValues[colIndex];
                        if(colModel[colIndex].wrap){
							wrap=true;
						} 
                    }
                    var td = $('<td></td>').attr({align:this.align,abbr:this.abbr}).addClass(axis).append($('<div></div>').html(html).addClass(wrap?'wrap':'').attr({'align':this.align}).width($('div',$(this)).width()));
                    tr.append(td);
                });
                tbody.append(tr);
            });
        },
        //刷新数据
        _populate : function() { // get latest data
            var self=this,
                el = this.element,
                grid = el.closest('.om-grid'),
                op = this.options,
                pageStat = $('.pPageStat', grid);
            if (!op.dataSource) {
                $('.pPageStat', grid).html(op.emptygMsg);
                return false;
            }
            if (this.loading) {
                return true;
            }
            var pageData = this.pageData,
                nowPage = pageData.nowPage || 1,
                loadMask = $('.gBlock',grid);
            //具备加载数据的前提条件了,准备加载
            this.loading = true;
            pageStat.html(op.loadingMsg);
            loadMask.show();
            if ($.browser.opera) {
                $(grid).css('visibility', 'hidden');
            }
            var limit = (op.limit<=0)?100000000:op.limit;
            var param = [ {
                name : 'start',
                value : limit * (nowPage - 1)
            }, {
                name : 'limit',
                value : limit
            }, {
                name : '_time_stamp_',
                value : new Date().getTime()
            } ];
			//push sort options
			if(op.sortName){
				param.push({
					name : 'sortName',
					value : op.sortName 
				});
				param.push({
					name : 'sortOrder',
					value : op.sortOrder
				});
			}
            $.ajax({
                type : op.method,
                url : op.dataSource,
                data : param,
                dataType : 'json',
                success : function(data,textStatus,request) {
                    var onSuccess = op.onSuccess;
                    if (typeof(onSuccess) == 'function') {
                        onSuccess(data,textStatus,request);
                    }
                    self._addData(data);
                    op.onRefresh(nowPage,data.rows);
                    loadMask.hide();
                    self.loading = false;
                },
                error : function(XMLHttpRequest, textStatus, errorThrown) {
                    pageStat.html(op.errorMsg).css('color','red');
                    try {
                        var onError = op.onError;
                        if (typeof(onError) == 'function') {
                            onError(XMLHttpRequest, textStatus, errorThrown);
                        }
                    } catch (e) {
                        // do nothing 
                    } finally {
                        loadMask.hide();
                        self.loading = false;
                        return false;
                    }
                    
                }
            });
        },
        //绑定行选择/行反选/行单击/行双击等事件监听
        _bindSelectAndClickEnvent:function(){
            var self=this;
            //如果有checkbo列则绑定事件
            if(!this.options.singleSelect){ //可以多选
                // 全选/反选,不需要刷新headerChekcbox的选择状态
                $('th.checkboxCol span.checkbox',this.thead).click(function(){
                    var thCheckbox=$(this),trSize=$('tr.om-grid-row',this.tbody).size();
                    if(thCheckbox.hasClass('selected')){ //说明是要全部取消选择
                        thCheckbox.removeClass('selected');
                        for(var i=0;i<trSize;i++){
                            self._rowDeCheck(i);
                        }
                    }else{ //说明是要全选
                        thCheckbox.addClass('selected');
                        for(var i=0;i<trSize;i++){
                            self._rowCheck(i);
                        }
                    }
                });
                //行单击,需要刷新headerChekcbox的选择状态
                this.tbody.delegate('tr.om-grid-row  span.checkbox','click',function(){
                    var row=$(this),index=row.closest('tr',self.tbody).index();
                    if(row.hasClass('selected')){ //已选择
                        self._rowDeCheck(index);
                    }else{
                        self._rowCheck(index);
                    }
                    self._refreshHeaderCheckBox();
                    //self.options.onRowClick(index,self._getRowData(index));
                });
                //行双击
                /*this.tbody.delegate('tr.om-grid-row','dblclick',function(){
                    var row=$(this),index=row.index();
                    if(row.hasClass('om-state-highlight')){ //已选择
                        //do nothing
                    }else{
                        self._rowSelect(index);
                        self._refreshHeaderCheckBox();
                    }
                    self.options.onRowDblClick(index,self._getRowData(index));
                });*/
            }//else{ //不可多选
                //行单击
                this.tbody.delegate('tr.om-grid-row','click',function(event){
					if($(event.target).hasClass('checkbox')||$(event.target).hasClass('detailIcon'))
						return false;
                    var row=$(this),index=row.index();
                    if(row.hasClass('om-state-highlight')){ //已选择
                        // no need to deselect another row and select this row
                    }else{
                        var lastSelectedIndex = $('tr.om-state-highlight',self.tbody).index();
                        (lastSelectedIndex != -1) && self._rowDeSelect(lastSelectedIndex);
                        self._rowSelect(index);
                    }
                    self.options.onRowClick(index,self._getRowData(index));
                });
                
                //行双击,因为双击一定会先触发单击,所以对于单选表格双击时这一行一定是选中的,所以不需要强制双击前选中
                this.tbody.delegate('tr.om-grid-row','dblclick',function(){
                    var index=$(this).index();
                    self.options.onRowDblClick(index,self._getRowData(index));
                });
          //  }
        },
		_bindDetailEvent:function(){
			var self = this;
			this.tbody.delegate('span.detailIcon','click',function(){
				if($(this).hasClass('collapsed')){
					$(this).removeClass('collapsed');
					$(this).addClass('expanded');
					var index = parseInt($(this).parents('tr.om-grid-row').attr('rowindex'));
					self._expand($(this).parents('tr.om-grid-row'),index);
				}else{
					$(this).removeClass('expanded');
					$(this).addClass('collapsed');
					var index = parseInt($(this).parents('tr.om-grid-row').attr('rowindex'));
					self._collapse($(this).parents('tr.om-grid-row'),index);
				}
			});
		},
		//展开
		_expand:function(row,index){
			var rowData = this._getRowData(index);
			var detail = $(row).data('detail');
			if(this.options.detailExpandReload){
				detail = null;
			}
			if(!detail){
				detail = $('<tr class="om-grid-row-detail"><td colspan="'+this.detailColSpan+'"><div class="om-grid-row-detail-wrapper">detail</div></td></tr>').insertAfter($(row)).attr({rowindex:index});
				$(row).data('detail',detail);
				this.options.onDetailExpand(rowData,$('div.om-grid-row-detail-wrapper',detail));
			}else{
				detail.show();
			}
			
		},
		//关闭
		_collapse:function(row,index){
			var rowData = this._getRowData(index);
			var detail = $(row).data('detail');
			if(!detail)
				return;
			if(this.options.detailExpandReload){
				detail.remove();
			}else{
				detail.hide();
			}
		},
        _rowSelect:function(index){
             var el=this.element,
                op=this.options,
                tbody=$('tbody',el),
                tr=$('tr:eq('+index+')',tbody),
                chk=$('td.checkboxCol span.checkbox',tr);
            tr.addClass('om-state-highlight');
            //chk.addClass('selected');
            op.onRowSelect(index,this._getRowData(index));
        },
        _rowDeSelect:function(index){
            var self=this,
                el=this.element,
                op=this.options,
                tbody=$('tbody',el),
                tr=$('tr:eq('+index+')',tbody),
                chk=$('td.checkboxCol span.checkbox',tr);
            tr.removeClass('om-state-highlight');
            //chk.removeClass('selected');
            op.onRowDeselect(index,this._getRowData(index));
        },
		_rowCheck:function(index){
             var el=this.element,
                op=this.options,
                tbody=$('tbody',el),
                tr=$('tr:eq('+index+')',tbody),
                chk=$('td.checkboxCol span.checkbox',tr);
            chk.addClass('selected');
			op.onRowCheck(index,this._getRowData(index));
        },
		_rowDeCheck:function(index){
            var self=this,
                el=this.element,
                op=this.options,
                tbody=$('tbody',el),
                tr=$('tr:eq('+index+')',tbody),
                chk=$('td.checkboxCol span.checkbox',tr);
            chk.removeClass('selected');
        },
        //让列可以改变宽度(index列和checkbox列不可以改变宽度)
        /**
         * 选择行。<b>注意:传入的参数是序号(第一行是0第二行是1)数组(比如[0,1]表示选择第一行和第二行);要想清除所有选择,请使用空数组[]作为参数;只能传入序号数组,如果要做复杂的选择算法,请先在其它地方算好序号数组后后调用此方法;此方法会清除其它选择状态,如选择第1,2行然后setSelections([3])最后结果中只有第3行,如setSelections([3,4]);setSelections([5,6])后只会选择5,6两行</b>。
         * @name omGrid#setSelection
         * @function
         * @param indexes 序号(第一行是0第二行是1)数组。
         * @returns jQuery对象
         * @example
         * //选择表格中第二行、第三行、第五行
         * $('.selector').omGridExtend('setSelection',2);
         * 
         */
        setSelection : function(index){
            var self=this;
            /*if(!$.isArray(indexes)){
                indexes=[indexes];
            }*/
            var selected=this.getSelection();
           /* $(selected).each(function(){
                self._rowDeSelect(this);
            });
            $(indexes).each(function(){
                self._rowSelect(this);
            });*/
			if( selected )
				this._rowDeSelect(selected);
			this._rowSelect( index );
        },
        /**
         * 获取选择的行的行号或行记录。<b>注意:默认返回的是行序号组成的数组(如选择了第2行和第5行则返回[1,4]),如果要返回行记录JSON组成的数组需要传入一个true作为参数</b>。
         * @name omGrid#getSelection
         * @function
         * @param needRecords 参数为true时返回的不是行序号数组而是行记录数组。参数为空或不是true时返回行序号数组。
         * @returns jQuery对象
         * @example
         * var selectedIndexed = $('.selector').omGridExtend('getSelection');
         * var selectedRecords = $('.selector').omGridExtend('getSelection',true);
         * 
         */
        getSelection:function(needRecord){
            //needRecords=true时返回Record[],不设或为false时返回index[]
            var self=this,tr=$('tr.om-state-highlight',this.tbody),result;
            if(needRecord){
                var rows=self.pageData.data.rows;
                if(tr.length == 0){
					result = null;
				}else{
					result = rows[tr.attr('rowindex')];
				}
            }else{
                if(tr.length == 0){
					result = null;
				}else{
					result = tr.attr('rowindex');
				}
            }
            return result;
        },
		 /**
         * 获取选择的行的行号或行记录。<b>注意:默认返回的是行序号组成的数组(如选择了第2行和第5行则返回[1,4]),如果要返回行记录JSON组成的数组需要传入一个true作为参数</b>。
         * @name omGrid#getChecks
         * @function
         * @param needRecords 参数为true时返回的不是行序号数组而是行记录数组。参数为空或不是true时返回行序号数组。
         * @returns jQuery对象
         * @example
         * var selectedIndexed = $('.selector').omGridExtend('getChecks');
         * var selectedRecords = $('.selector').omGridExtend('getChecks',true);
         * 
         */
		getChecks : function(needRecords){
			var self = this , checks = $('span.selected',this.tbody),result = [];
			if(needRecords){
				var rows = this.pageData.data.rows;
				checks.each(function(i){
					var tr = $(this).parents('tr.om-grid-row');
					result[i] = rows[tr.attr('rowindex')];
				});
			}else{
				checks.each(function(i){
					var tr = $(this).parents('tr.om-grid-row');
					result[i] = tr.attr('rowindex');
				});
			}

			return result;
		},
		/**
         * 选择行。<b>注意:传入的参数是序号(第一行是0第二行是1)数组(比如[0,1]表示选择第一行和第二行);要想清除所有选择,请使用空数组[]作为参数;只能传入序号数组,如果要做复杂的选择算法,请先在其它地方算好序号数组后后调用此方法;此方法会清除其它选择状态,如选择第1,2行然后setSelections([3])最后结果中只有第3行,如setSelections([3,4]);setSelections([5,6])后只会选择5,6两行</b>。
         * @name omGrid#setChecks
         * @function
         * @param indexes 序号(第一行是0第二行是1)数组。
         * @returns jQuery对象
         * @example
         * //选择表格中第二行、第三行、第五行
         * $('.selector').omGridExtend('setChecks',[1,2,4]);
         * 
         */
		setChecks : function(indexes){
			var self = this ; 
			if(!$.isArray(indexes)){
                indexes=[indexes];
            }

			$(indexes).each(function(){
				self._rowCheck(this);
			});

		}
    });
})(jQuery);

 使用的时候只要引入这个文件即可,此外还有附件里面的css和image ,附件里面的css和image分别覆盖原来的css和image即可,不然可能图片显示不出来

页面使用时的代码如下:

 

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>基本功能</title>
    <script type="text/javascript" src="../../jquery.js"></script>
    <script src="../../ui/jquery.ui.core.js"></script>
    <script src="../../ui/jquery.ui.widget.js"></script>
    <script src="../../ui/jquery.ui.mouse.js"></script>
    <script src="../../ui/jquery.ui.resizable.js"></script>
    <script type="text/javascript" src="../../ui/om-grid.js"></script>
	<script type="text/javascript" src="../../ui/om-grid-extend.js"></script>
    <link rel="stylesheet" type="text/css" href="../../themes/default/om-all.css" />
    <link rel="stylesheet" type="text/css" href="../common/css/demo.css" />
    <!-- view_source_begin -->
    <script type="text/javascript">
        $(document).ready(function() {
            $('#grid').omGridExtend({
				//是否显示详情
				showDetail:true,
				singleSelect:false,
                dataSource : 'griddata.do?method=fast',
                colModel : [ {header : 'ID', name : 'id', width : 100, align : 'center'}, 
                             {header : '地区', name : 'city', width : 120, align : 'center'}, 
                             {header : '地址', name : 'address', align : 'center', width : 'autoExpand'} ],
				onRowClick:function(index,row){
					
				},
				onRowSelect:function(){
					
				},
				onRowDeselect:function(){
					
				},
				//当详情展开的时候调用的回调
				onDetailExpand:function(rowData,row){
					
				},
				//初始化的时候以哪一个字段排序
				sortName:'address',
				//排序方式
				sortOrder:'desc',
				method:'get',
				onRowCheck:function(index){
					
				}
            });
        });
    </script>
    <!-- view_source_end -->
</head>
<body>
    <!-- view_source_begin -->
    <table id="grid"></table>
    <!-- view_source_end -->
    <input type = "button" id = "get" value ="get" >
    <div id="view-desc">
        设置dataSource和colModel属性,在table元素中渲染表格。
    </div>
</body>
</html>
分享到:
评论
2 楼 mfkvfn 2012-02-02  
1.0之后的版本我们会陆续做一些grid或其它组件的插件(或子类)。

你做的这些功能值得参考。我们正在考虑一种贡献机制,大致是“贡献者自己完成基本功能,然后申请合并到主干,我们进行审核,如果采纳了,就将代码合并进来,由我们进行维护,并在文档显要位置标注贡献者的名字。如果某贡献者多次贡献重要代码,我们将把贡献者加入开发人员组中,与我们开发人员享有同等权利(可以直接提交代码到主干,可以参与Bug修复、测试、发版、文档等工作,可以收到日常工作邮件,可以查看日常内部交流资料等)”。具体细节还在制定中。近期可能会把代码托管到GitHub上,然后采用这种贡献机制。
1 楼 mfkvfn 2012-02-02  
这样做比较好。其实排序功能是比较常见的,之所以我们没把排序做到omGrid中去,是因为我们设计时这个omGrid是一个基础组件,将作为其它grid组件的基类。而有些grid是不可以排序的,比如treeGrid(演示例见http://demo.operamasks.org/bpdemos/index.faces?userdata=treeGrid)、分组统计表格(演示示例见http://demo.operamasks.org/bpdemos/index.faces?userdata=groupSummaryGrid)、统计表格(演示示例见http://demo.operamasks.org/bpdemos/index.faces?userdata=pivotGrid)。所以如果基类有这些功能的话,子类把它去掉不好。

所以设计时基类只有基本功能(所有子类都有的),其它功能由子类(或者插件)来提供。
像你做的可展开表格的效果与http://demo.operamasks.org/bpdemos/index.faces?userdata=expanderGridPlug是一样的。

整个组件的体系与继承机制我们也已经讨论过了,直接的继承并不好,比如A的两个子类A1和A2,A1提供功能1,A2提供功能2,那么如果我同时要A1和A2功能怎么办?再做一个A3同时提供功能1和功能2?那这样功能一多就会产生组合爆炸了。所以我们推荐以插件的机制来做,就类似于《设计模式》中的“Decorator装饰模式”模式这种。

相关推荐

    扩展OperamasksUI的grid的排序和显示detail属性

    这篇博客“扩展OperamasksUI的grid的排序和显示detail属性”显然聚焦于如何增强Operamasks UI框架的功能,特别是其grid组件。Operamasks UI可能是一个用于构建Web应用的开源库,提供了丰富的组件和功能,便于开发者...

    一个基于C# +VS2008实现的PropertyGrid高级扩展控件源码

    开发者可能通过以下几种方式来扩展PropertyGrid: 1. 自定义属性编辑器:默认的PropertyGrid控件使用内置的编辑器来显示和编辑属性值,如TextBox、ComboBox等。通过实现`UITypeEditor`接口,可以创建自定义编辑器,...

    operamasks2.1整合spring、hebernate实现grid增删改查

    然后,Hibernate是一个对象关系映射(Object-Relational Mapping,ORM)框架,它允许开发者用Java对象的方式来操作数据库,降低了数据库操作的复杂性。在这个项目中,Hibernate被用于数据持久化,实现了将业务对象与...

    operamasks整合spring、hibernate实现grid增删改查

    在IT行业中,Web开发是一项核心任务,而"operamasks整合spring、hibernate实现grid增删改查"是常见的Web应用开发实践。这个主题涵盖了多个关键的技术组件,包括OperaMasks、Spring框架和Hibernate持久化层,以及Grid...

    Extjs Grid 扩展实例

    总的来说,"Extjs Grid 扩展实例"是一个全面的教程,涵盖了ExtJS Grid的基础用法和高级扩展技术。通过这个实例,开发者不仅可以学习到如何构建功能完善的表格,还能掌握如何根据业务需求定制Grid,提升Web应用的数据...

    Ext grid 动态添加字段、列扩展

    Ext grid 动态添加字段、列扩展, 如何动态添加或者删除一个grid的列

    angularjs ui-grid datepicker 日期控件

    而“angularjs ui-grid datepicker”则是UI-Grid的一个扩展功能,它为表格中的日期字段提供了集成的日期选择器,提高了用户交互性和数据输入的便利性。下面将详细介绍这个功能及其相关知识点。 1. **AngularJS**: ...

    jquery ui实现的grid

    要使用Grid,首先需要在页面上引入jQuery和jQuery UI的库,然后选择一个表格元素并调用`$.fn.jqueryui.grid()`方法进行初始化。例如: ```javascript $("#myTable").grid({ // 配置选项 }); ``` 3. **配置...

    动态设置显示kendoui grid控件某一列的格式

    至于自定义过滤,Kendo UI Grid提供了`filterable`配置项来定制过滤行为。我们可以为特定列定义一个过滤函数,或者为整个Grid设置全局过滤函数。例如,如果我们希望在日期过滤中加入特定的业务逻辑,如只允许用户...

    使用OOP的方式扩展ExtJS UI组建 - 更新版

    本篇文章将深入探讨如何使用OOP的方式来扩展ExtJS UI组件,并结合更新版的实现方法进行讨论。 首先,理解ExtJS的基础是至关重要的。ExtJS提供了一套完整的组件模型,包括窗口(Window)、面板(Panel)、表格(Grid...

    UltimateGrid V7.3 MFC 扩展表格源代码

    MFC是微软提供的一种C++类库,用于简化Windows API编程,它通过面向对象的方式来封装Windows API,使得开发者能够更高效地构建Windows应用程序。 UltimateGrid73 MFC扩展表格源代码的核心特性包括: 1. **高性能**...

    Kendoui grid多级分组表格展现

    应用kendoui grid实现的多级分组表格展现,里面包含了表格的分组统计以及单表合计功能、还有针对表格的刷新以及子表格刷新功能。此功能是在原有demo版本上改进,增加了很多的个别需求实现,在原来的版本是做不到的。...

    标准kendo ui-grid控件用法

    然后,使用`kendoGrid()`函数来初始化Grid: ```javascript $("#grid").kendoGrid({ dataSource: { /* 数据源配置 */ }, columns: [ /* 列定义 */ ] }); ``` 2. **数据源(DataSource)** Kendo UI Grid的...

    Grid++Report 扩展 报表控件 可扩展 可动态添加

    Grid++Report是一款强大的报表控件,专为开发者设计,提供了高度可扩展性和灵活性,使得在应用程序中创建和管理报表变得更加简单。这款控件的核心特性在于它的动态性,允许用户在运行时修改和添加报表元素,极大地...

    LigerUI之Grid使用详解(一)——显示数据

    本篇文章将详细介绍如何使用LigerUI的Grid组件来显示数据。 首先,我们需要了解Grid的基本结构。在HTML页面中,你需要创建一个div元素作为Grid的容器。例如: ```html &lt;div id="gridContainer"&gt; ``` 接下来,我们...

    Ligerui Grid合并单元格

    Ligerui Grid合并单元格 ,指定列合并单元格,该合并是整列合并

    ligerui+Json_使用LigerUI的Grid和Java的Json实现数据显示

    在本教程中,我们将深入探讨如何结合LigerUI的Grid组件和Java的JSON数据来实现数据显示。Grid是LigerUI中的一个核心组件,用于展示表格数据,支持多种交互功能和自定义样式。 首先,我们需要理解LigerUI的Grid组件...

    asp.net+Ligerui实现grid导出Excel和Word的方法

    本文实例讲述了asp.net+Ligerui实现grid导出Excel和Word的方法。分享给大家供大家参考,具体如下: 下面采用的导EXCEL方法,适合不翻页的grid,而且无需再读一次数据库,对于翻页的grid来说,要导全部,当然后台要再...

    MyTable 是对MvcContrib.UI.Grid的一个扩展控件[C#]

    MyTable 是对MvcContrib.UI.Grid的一个扩展控件.该代码须运行于.net 3.5++. 在原来的基础上进行了一些功能性扩展,主要是从合并行,合并列,以及单行多列,分组补白等.上作了稍许的修改.希望大家喜欢. 因为该表格没有...

    Egrid基于ElementUITable组件封装的高阶表格组件

    Egrid能够无缝地与Element-UI库配合使用,这意味着你可以继续使用Element-UI的其他组件,保持整体设计风格的一致性,而无需担心样式冲突或兼容问题。 5. **性能优化** 针对大数据量场景,Egrid可能已经进行了虚拟...

Global site tag (gtag.js) - Google Analytics