Easyui.datagrid扩展——Ext.grid rowediting风格_ext.grid.plugin.rowediting-程序员宅基地

技术标签: easyui  扩展  JavaScript  

使用过Ext的人都知道,在Ext.grid组件中有个Ext.grid.plugin.RowEditing插件,它会在行编辑状态下,在行的下方出现一组按钮,方便你确定和取消当前行的编辑内容。



有朋友反映看的有点乱,我也懒的再排版了,嫌乱的可以从后向前反着看。最后面给出了完整扩展。


首先我们要达到如下目的:
1、保留easyui.datagrid原有编辑风格
2、增加一个类似Ext.grid的Rowediting编辑风格
3、可以通过一个属性来控制Rowediting编辑风格
4、因为扩展而被使用过的事件,要能保证在datagrid在初始化时设置后,还能正常触发。


下面我们来看看如何在Easyui中实现这个效果。
首先,我们给Easyui.datagrid扩展一个方法叫_registRowEditingHandler,使它能为我们构建Rowediting编辑风格。这个方法名前加了一个“-”表示当作一个私有方法使用,不打算将它公布给调用者使用。当然你也可以通过其他方法来实现,完全按个人习惯。

function _registRowEditingHandler(jq){

    var getEditorButtonsPanelId = function(target){
        return $(target).attr('id')+'_editor_buttons_panel';
    }

    var buildEditorButtonsPanel = function(target){
        var panelId = getEditorButtonsPanelId(target);
        if($('#'+panelId).length > 0) return;

        var panel = $(target).datagrid('getPanel');
        var datagrid_body = $('>div.datagrid-view>div.datagrid-view2>div.datagrid-body', panel);
        datagrid_body.css('position', 'relative');

        var edtBtnPanel = $('<div>', {id: panelId})
            .addClass('dialog-button')
            .appendTo(datagrid_body)
            .css({
                'position': 'absolute',
                'display': 'block',
                'border-bottom': '1px solid #ddd',
                'border-left': '1px solid #ddd',
                'border-right': '1px solid #ddd',
                'left': parseInt(panel.width()/2)-120,
                'z-index': 2013,
                'display': 'none',
                'padding': '4px 5px'
            });

        $('<a href="javascript:void(0)">确定</a>')
            .css('margin-left','0px')
            .linkbutton({iconCls: 'icon-ok'})
            .click(function(){
                var editIndex = $(target).datagrid('getRowIndex', $(target).datagrid('getEditingRow'));
                $(target).datagrid('endEdit', editIndex);
            })
            .appendTo(edtBtnPanel);
        $('<a href="javascript:void(0)">取消</a>')
            .css('margin-left', '6px')
            .linkbutton({iconCls: 'icon-cancel'})
            .click(function(){
                var editIndex = $(target).datagrid('getRowIndex', $(target).datagrid('getEditingRow'));
                $(target).datagrid('cancelEdit', editIndex);
            })
            .appendTo(edtBtnPanel);

    }

    var showEditorButtonsPanel = function(target, index){
        var opts = $.data(target, "datagrid").options;
        var tr = opts.finder.getTr(target, index);
        var position = tr.position();

        var fixPosition = function(){
            var offset = tr.height() * 2 + 10;
            var t = position.top + datagrid_body.scrollTop();

            if((position.top+offset) > datagrid_body.height()){
                return {top: t - offset};
            }else{
                return {top: t};
            }
        }

        var edtBtnPanelId = '#'+getEditorButtonsPanelId(target);
        var panel = $(target).datagrid('getPanel');
        var datagrid_body = $('>div.datagrid-view>div.datagrid-view2>div.datagrid-body', panel);

        $(edtBtnPanelId).css({
            top: fixPosition().top
        }).show();
    }

    var hideEditorButtonsPanel = function(target){
        var edtBtnPanelId = '#'+getEditorButtonsPanelId(target);
        $(edtBtnPanelId).hide();
    }


    jq.each(function(){
        var target = this;
        var opts = $.data(target, "datagrid").options;
        
        var onLoadSuccessCallBack = opts.onLoadSuccess;
        var onBeforeEditCallBack = opts.onBeforeEdit;
        var onAfterEditCallBack = opts.onAfterEdit;
        var onCancelEditCallBack = opts.onCancelEdit;

        $(this).datagrid({
            onLoadSuccess: function(data){
                onLoadSuccessCallBack.call(this, data);
                buildEditorButtonsPanel(this);
            },
            onBeforeEdit: function(index, data){
                showEditorButtonsPanel(target, index);
                onBeforeEditCallBack.call(this, index, data);
            },
            onAfterEdit: function(index, data){
                hideEditorButtonsPanel(target);
                onAfterEditCallBack.call(this, index, data);
            },
            onCancelEdit: function(index, data){
                hideEditorButtonsPanel(target);
                onCancelEditCallBack.call(this, index, data);
            }
        });

    });
}

方法中用到了另一个easyui.datagrid的扩展方法getEditingRow,作用就是返回当前正被编辑的row。注意这个row不是dom元素,而是用来填充datagrid的数据对象中rows中的一个{}行对象。不理解的自己看Easyui.datagrid的API,不再多做解释。

$.extend($.fn.datagrid.methods, {
    ...... 此处省略其他扩展方法

    getEditingRow: function(jq){
        var datagrid = $.data(jq[0], "datagrid");
        var opts = datagrid.options;
        var data = datagrid.data;
        var editingRow = [];
        opts.finder.getTr(jq[0], "", "allbody").each(function(){
            if($(this).hasClass('datagrid-row-editing')){
                var index = parseInt($(this).attr('datagrid-row-index'));
                editingRow.push(data.rows[index]);
            }
        });

        return editingRow.length>0?editingRow[0]:null;
    }  
});

好了,到目前为止,我们需要的方法都已经构建完成。


接下来,我准备通过一个叫rowediting的属性,来控制这个编辑风格。为了防止与Easyui.datagrid以后扩展的属性冲突,我将其方式到另一个自定义属性customAttr中。以后所有自己扩展的属性都放置到这个属性中。

$.fn.datagrid.defaults.customAttr={
    rowediting: true
}

现在,方法有了,控制属性也有了,那如何将二者关联起来?有人说通过onLoadSuccess事件,有的说再扩展一个方法等等,形式很多。我这里不准备再使用onLoadSuccess事件,因为在构建RowEditing风格的方法中已经使用过这个事件,再用代码就写的太麻烦了。所以这里采用再扩展一个方法的方式,我们将这个方法命名为followCustomHandle。目的是为了处理我所有的自定义属性,目前先用来处理$.fn.datagrid.defaults.customAttr.rowediting属性的解析。

$.extend($.fn.datagrid.methods, {
    followCustomHandle: function(jq){
        return jq.each(function(){
            var opts = $.extend(true, {}, $.fn.datagrid.defaults, $.data(this, 'datagrid').options);
            if(opts.customAttr.rowediting){           
                _registRowEditingHandler(jq);
            } 
        }); 
    }, 
    ......以下省略其它扩展方法 
});

好了,都关联起来了,使用者如何调用?

$('#datagrid').datagrid({
    columns:[[
        {field: 'username', title: 'Name', width: 150, editor: 'text'},
        {field: 'sex', title: 'Sex', width: 50, editor: 'text'},
        {field: 'age', title: 'Age', width: 80, editor: 'numberspinner'},
        {field: 'brithday', title: 'Birthday', width: 100, editor: 'my97'},
        {field: 'registdate', title: 'Regist Date', width: 150, editor: 'datetimebox'},
        {field: 'arrivaltime', title: 'Arrival Time (AT)', width: 110, editor: 'timespinner'}
    ]],
    title: 'Row Editing DataGrid',
    singleSelect: true,
    rownumbers: true,
    height: 250,
    width: 700,
    url: '../datagrid/datagrid_data2.json',
    //customAttr:{
    //    rowediting: false
    //},
    onClickRow: function(index){
        var editingRow = $('#datagrid').datagrid('getEditingRow');
        var editingRowIndex = $('#datagrid').datagrid('getRowIndex', editingRow);
        if(!editingRow){
            $('#datagrid').datagrid('selectRow', index)
                    .datagrid('beginEdit', index);
        }else{
            $('#datagrid').datagrid('selectRow', editingRowIndex);
        }
    }
})
.datagrid('followCustomHandle');

你可以将上段JavaScript代码放入到这里调用。

<script type="text/javascript">
    $(function(){
         //上段的JavaScript代码扔到这里。为啥?jquery基础,不解释。
    })
</script>

效果:


图2


图3


下面给出完整扩展

jquery.easyui.datagrid.extend.js

(function($){
    function _registRowEditingHandler(jq){

        var getEditorButtonsPanelId = function(target){
            return $(target).attr('id')+'_editor_buttons_panel';
        }

        var buildEditorButtonsPanel = function(target){
            var panelId = getEditorButtonsPanelId(target);
            if($('#'+panelId).length > 0) return;

            var panel = $(target).datagrid('getPanel');
            var datagrid_body = $('>div.datagrid-view>div.datagrid-view2>div.datagrid-body', panel);
            datagrid_body.css('position', 'relative');

            var edtBtnPanel = $('<div>', {id: panelId})
                .addClass('dialog-button')
                .appendTo(datagrid_body)
                .css({
                    'position': 'absolute',
                    'display': 'block',
                    'border-bottom': '1px solid #ddd',
                    'border-left': '1px solid #ddd',
                    'border-right': '1px solid #ddd',
                    'left': parseInt(panel.width()/2)-120,
                    'z-index': 2013,
                    'display': 'none',
                    'padding': '4px 5px'
                });

            $('<a href="javascript:void(0)">确定</a>')
                .css('margin-left','0px')
                .linkbutton({iconCls: 'icon-ok'})
                .click(function(){
                    var editIndex = $(target).datagrid('getRowIndex', $(target).datagrid('getEditingRow'));
                    $(target).datagrid('endEdit', editIndex);
                })
                .appendTo(edtBtnPanel);
            $('<a href="javascript:void(0)">取消</a>')
                .css('margin-left', '6px')
                .linkbutton({iconCls: 'icon-cancel'})
                .click(function(){
                    var editIndex = $(target).datagrid('getRowIndex', $(target).datagrid('getEditingRow'));
                    $(target).datagrid('cancelEdit', editIndex);
                })
                .appendTo(edtBtnPanel);

        }

        var showEditorButtonsPanel = function(target, index){
            var opts = $.data(target, "datagrid").options;
            var tr = opts.finder.getTr(target, index);
            var position = tr.position();

            var fixPosition = function(){
                var offset = tr.height() * 2 + 10;
                var t = position.top + datagrid_body.scrollTop();

                if((position.top+offset) > datagrid_body.height()){
                    return {top: t - offset};
                }else{
                    return {top: t};
                }
            }

            var edtBtnPanelId = '#'+getEditorButtonsPanelId(target);
            var panel = $(target).datagrid('getPanel');
            var datagrid_body = $('>div.datagrid-view>div.datagrid-view2>div.datagrid-body', panel);

            $(edtBtnPanelId).css({
                top: fixPosition().top
            }).show();
        }

        var hideEditorButtonsPanel = function(target){
            var edtBtnPanelId = '#'+getEditorButtonsPanelId(target);
            $(edtBtnPanelId).hide();
        }


        jq.each(function(){
            var target = this;
            var opts = $.data(target, "datagrid").options;
            
            var onLoadSuccessCallBack = opts.onLoadSuccess;
            var onBeforeEditCallBack = opts.onBeforeEdit;
            var onAfterEditCallBack = opts.onAfterEdit;
            var onCancelEditCallBack = opts.onCancelEdit;

            $(this).datagrid({
                onLoadSuccess: function(data){
                    onLoadSuccessCallBack.call(this, data);
                    buildEditorButtonsPanel(this);
                },
                onBeforeEdit: function(index, data){
                    showEditorButtonsPanel(target, index);
                    onBeforeEditCallBack.call(this, index, data);
                },
                onAfterEdit: function(index, data){
                    hideEditorButtonsPanel(target);
                    onAfterEditCallBack.call(this, index, data);
                },
                onCancelEdit: function(index, data){
                    hideEditorButtonsPanel(target);
                    onCancelEditCallBack.call(this, data);
                }
            });

        });
    }

    $.fn.datagrid.defaults.customAttr={
        rowediting: true
    }

    $.extend($.fn.datagrid.methods, {
        followCustomHandle: function(jq){
            return jq.each(function(){
                var opts = $.extend(true, {}, $.fn.datagrid.defaults, $.data(this, 'datagrid').options);
                if(opts.customAttr.rowediting){
                    _registRowEditingHandler(jq);
                }
            });
        },
        getEditingRow: function(jq){
            var datagrid = $.data(jq[0], "datagrid");
            var opts = datagrid.options;
            var data = datagrid.data;
            var editingRow = [];
            opts.finder.getTr(jq[0], "", "allbody").each(function(){
                if($(this).hasClass('datagrid-row-editing')){
                    var index = parseInt($(this).attr('datagrid-row-index'));
                    editingRow.push(data.rows[index]);
                }
            });

            return editingRow.length>0?editingRow[0]:null;
        }  
    });

})(jQuery)

编写仓促,有Bug的地方自己修改修改。因为简单,应该很容易看懂,所以没写多少注释。



升级后的代码,请访问我的jquery.easyui.1.3.3扩展库






版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zjh527/article/details/8985174

智能推荐

SimpleFOC(五)—— 双电机控制_loop222-程序员宅基地

文章浏览阅读7.4k次,点赞2次,收藏37次。目录一、硬件说明1、硬件清单2、硬件连接二、程序演示三、其他控制模式1、速度模式2、速度和力矩混合模式 一、硬件说明1、硬件清单序号名称数量1Arduino UNO12simpleFOCShield V2.0.323带磁编码器的云台电机2412V电源15方口USB线1如下图所示: 2、硬件连接  ⑴、驱动板背面跳线  两个驱动板,一个接9、5、6、8,另一个接3、10、11、7。  ⑵、编码器连接  Arduin_loop222

Linux高级IO-程序员宅基地

文章浏览阅读1k次,点赞16次,收藏20次。IO主要分为两步:第一步是等,即等待IO条件就绪。第二步是拷贝,也就是当IO条件就绪后将数据拷贝到内存或外设。任何IO的过程,都包含“等”和“拷贝”这两个步骤,但在实际的应用场景中“等”消耗的时间往往比“拷贝”消耗的时间多,因此要让IO变得高效,最核心的办法就是尽量减少“等”的时间。

python websocket-http实现fastapi-sse_sse_starlette flask-程序员宅基地

文章浏览阅读1.6k次。实现目的:因为项目从flask迁移到fastapi上,导致flask-sse无法使用期间尝试了很多websocket相关库如:starlette.websocketssse_starlette.sse import EventSourceResponse等期间踩了无数坑后来发现了websocket-client库第一步 搭建简单的fastapi 服务from fastapi import FastAPI, Requestfrom client_web import_sse_starlette flask

Am335x 应用层之SPI操作_spi_ioc_message-程序员宅基地

文章浏览阅读1w次。我们先来看一下SPI的时序图,下面的内容转自http://blog.chinaunix.net/uid-8307196-id-2032955.htmlSPI接口有四种不同的数据传输时序,取决于CPOL和CPHL这两位的组合。图1中表现了这四种时序,时序与CPOL、CPHL的关系也可以从图中看出。图1CPOL是用来决定SCK时钟信号空闲时的电平,CPOL=0,空闲_spi_ioc_message

时序预测 | MATLAB实现基于LSTM-AdaBoost长短期记忆网络结合AdaBoost时间序列预测 替换数据可以直接使用,注释清楚,适合新手_adaboost能集成lstm-程序员宅基地

文章浏览阅读858次,点赞18次,收藏21次。在金融市场、气象预测、股票走势等领域,时间序列预测一直是一个重要的问题。随着人工智能和机器学习的发展,越来越多的方法被应用于时间序列预测中。本文将介绍一种基于长短期记忆网络(LSTM)结合AdaBoost的时间序列预测方法。长短期记忆网络是一种特殊的循环神经网络,它在处理时间序列数据时表现出色。LSTM网络能够学习长期依赖关系,对于时间序列数据中的趋势和周期性变化有着较好的表现。然而,单独的LSTM网络可能无法充分捕捉时间序列数据中的复杂特征,因此需要结合其他方法进行预测。_adaboost能集成lstm

一文弄懂神经网络中的反向传播法——BackPropagation_神经元模型 反向传播-程序员宅基地

文章浏览阅读307次,点赞2次,收藏2次。最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进行补充,但是补充的又是错的,难怪觉得有问题。反向传播法其实是神经网络的基础了,但是很多人在学的时候总是会遇到一些问题,或者看到大篇的公式觉得好像很难就退缩了,其实不难,就是一个链式求导法则反复用。如果不想看公式,可以直接把数值带进去,实际的计算一下,体会一下这个过程之后再来推导公式,这样就会觉得很容易了。 _神经元模型 反向传播

随便推点

代码大全2(读书笔记10)_把一段代码放入一个命名恰当的子程序内,是说-程序员宅基地

文章浏览阅读418次。109、为未来的变化做准备  如果你预计到某个程序会被修改,你可以把预计要被改动的部分放到单独的类里,同其他部分隔离开,这是个好主意。之后你就可以只修改这个类或用新的类来取代它,而不会影响到程序的其余部分了。 110、子程序优点一-----------降低复杂度  创建子程序的一个最重要的原因,就是为了降低程序的复杂度。可能通过创建子程序来隐藏一些信息,这样你就不必再考虑这些信息了_把一段代码放入一个命名恰当的子程序内,是说

CAM 和 Grad-CAM 实现_guided_model-程序员宅基地

文章浏览阅读1.5w次,点赞9次,收藏66次。https://bindog.github.io/blog/2018/02/10/model-explanation/推荐这个博客,感觉原理讲的比较清楚。代码: 代码参考链接:https://github.com/jacobgil/keras-grad-cam 对其中有问题的地方进行了更改。from keras.applications.vgg16 import ( V..._guided_model

C# wince5.0下的插入、删除、更新源码_c#wince源码-程序员宅基地

文章浏览阅读1k次。using System;using System.Collections.Generic;using System.Text;using System.Data.SqlServerCe;using System.IO;using System.Collections;using System.Data;using System.Drawing;using System.Windo_c#wince源码

算法导论第三版 10.1-6习题答案_算法导论15.3-6答案-程序员宅基地

文章浏览阅读436次。10.1-6答案:设定两个栈为s1和s2,那么s1用来ENQUEUE(),s2用来DEQUEUE(),当然s1需要用来为DEQUEUE()操作作过渡,流程如下:(1)首先将入队元素1,2,3依次放进栈s1。此时s1元素从低到高为1,2,3,s2中暂时无元素。(2)然后依次将1,2,3从s1中弹出并且放入s2中。此时s1栈空,s2中元素从低到高依次为3,2,1(3)若此时进行还需要ENQU..._算法导论15.3-6答案

java编译提示错误_javac编译提示错误需要为 class、interface 或 enum-程序员宅基地

文章浏览阅读1k次。HelloWorld.java:1: 需要为 class、interface 或 enum锘缝ublic class HelloWorld{^1 错误这个错误出现的原因主要是在中文操作系统中,使用一贯的“javac HelloWorld.java”方式编译UTF-8(带BOM)编码的.java源文件,在没有指定编码参数(encoding)的情况下,默认是使用GBK编码。当编译器用GBK编码来编译U..._d:\jdkcode>javac helloworld.java helloworld.java:1: 错误: 需要 class、interf

spring security 集成cas单点登录核心配置及相关java代码_cas登录核心代码-程序员宅基地

文章浏览阅读3.1k次。最近项目中需要集成单点登录,所以最近研究了下,同时也在前面的章介绍了cas服务端的搭建,接下来security 集成cas 亲测可行,网上也是有很多不完整的代码,免得误导大家1.web.xml配置 kun-web contextConfigLocation classpath:webApplication.xml,classpath:application_cas登录核心代码