zoukankan      html  css  js  c++  java
  • 用Jquery Widgets Factory写自己的表格控件——AFGrid(支持增、删、改)

    一,Jquery Widget Factory介绍

    官网地址

    Demo:http://jqueryui.com/widget/ 

    API:http://api.jqueryui.com/jQuery.widget/

    常见的用jquery写UI插件有两种方式:1)对JQuery自身的扩展插件,形如$.extend(方法名字:function(参数){方法体})。2)对Jquery对象的拓展,形如(function ($) {$.fn.方法名 = function(参数){方法体}})(jQuery);以上两种方式编写的插件大都是无状态的,即和外部的交互时机仅限于调用它的时候,如$(ele).val(value),但是一些复杂的UI插件却要求是有状态的,有生命周期的,从在DOM中被创建到销毁的整个过程中都要和外部有交互,Jquery Widget factory 是创建有状态的插件的唯一途径。

    二,我用Widget写表格的需求介绍

    在公司的BSS系统中用户在填写表单一些明细的数据的时候要求

    1)单元格可以编辑

    2)可以插入新行

    3)可以删除任意行

    4)可以多选

    5)可以实时统计数值型列的合计

    6)支持和页面其它的DOM元素的联动

    7)可以导入Excel

    8)整个表格的操作过程页面不能刷新(最重要的需求

    大致形状如此:

    三,我用Jquery Widget的实现

    $.widget("ui.AFGrid", {
        options: {
            Title: "",//表格头
            HeadRow: "",//表格头html模板
            InsertRow: "",//插入行html模板
            TotalRow: "",//合计行html模板
            DataSource: "",//数据源
            ArrayDelimiter: ";",//数据行分隔符
            FieldDelimiter: "#",//数据列分隔符
            IsReadOnly: false,//是否只读
            IsAdd: false,//在为插件对象重新指定数据源时该选项用于指示是否清空表格中原有的数据,true不清空,false清空
            /*call backs*/
            Change: null, //编辑表格后blur事件触发的方法,参数(jquery对象){calculateRow:合计行Tr,contentBody明细表格Tbody,currentRow:当前行Tr}
            Validate: null, //编辑表格后blur事件触发的方法(此方法首先触发,返回true时,随后触发Change方法),参数(jquery对象){currentRow:当前行Tr}
            InsertRowCalculate: null, //点击插入新行click事件触发的方法,参数(jquery对象){insertRow:插入行Tr}
            TableCalculate: null//明细表格计算,参数(jquery对象){calculateRow:合计行Tr,contentBody明细表格Tbody}
        },
        _create: function () {
            $this = this;
            this.trTitleEle = $("<tr id='tr_Title' align='center' class='theme'></tr>").appendTo(this.element);
            this.trSelectEle = $("<tr id='tr_Select'></tr>").appendTo(this.element);
            this.trContentEle = $("<tr id='tr_Content'></tr>").appendTo(this.element);
            this.trEditEle = $("<tr id='tr_Edit'></tr>").appendTo(this.element);
            //trTitle
            this.trTitleTdEle = $("<td colspan='9999'>" + this.options.Title + "</td>").appendTo(this.trTitleEle);
            //trSelect
            this.trSelectTdEle = $("<td colspan='9999'></td>").appendTo(this.trSelectEle);
            if (this.options.IsReadOnly) {
                this.trSelectTdEle.hide();
            }
            if (!this.options.IsReadOnly) {
                this.trSelectA_AllEle = $("<a href='#'>全选</a>").appendTo(this.trSelectTdEle);
                this.trSelectA_ExceptEle = $("<a href='#'>反选</a>").appendTo(this.trSelectTdEle);
                this.trSelectA_DelEle = $("<a href='#'>删除</a>").appendTo(this.trSelectTdEle);
                //全选
                this._on(this.trSelectA_AllEle, { "click": function (event) { this.trContentTdTableBodyEle.find("input[type='checkbox']").prop("checked", true); } });
                //反选
                this._on(this.trSelectA_ExceptEle, { "click": function (event) {
                    this.trContentTdTableBodyEle.find("input[type='checkbox']").each(function (i, n) {
                        if ($(n).prop("checked")) { $(n).prop("checked", false); } else { $(n).prop("checked", true); }
                    });
                }
                });
                //删除
                this._on(this.trSelectA_DelEle, { "click": function (event) {
                    this.trContentTdTableBodyEle.find("input[type = 'checkbox']").each(function (i, n) {
                        if ($(n).prop("checked")) {
                            $(n).parent().parent().remove();
                        }
                    });
                    this._trigger("TableCalculate", null, { calculateRow: this.TotalRowEle, contentBody: this.trContentTdTableBodyEle });
                }
                });
            }
            //trEdit
            this.trEditTdEle = $("<td></td>").appendTo(this.trEditEle);
            this.trEditTdTableEle = $("<table width='100%' border='1'></table>").appendTo(this.trEditTdEle);
            this.TotalRowEle = $(this.options.TotalRow).appendTo(this.trEditTdTableEle);
            this.InsertRowEle = $(this.options.InsertRow).appendTo(this.trEditTdTableEle);
            var insertTdTotal = this.InsertRowEle.find("td").length - 1;
            this.importRowEle = $("<tr></tr>").appendTo(this.trEditTdTableEle);
            $("<td><a href='#'>导入</a></td><td colspan='" + insertTdTotal + "'><input type='file'/><a href='#'>下载模版</a></td>").appendTo(this.importRowEle);
            this.InsertRowEle.find("input[type='text'][class='thousandSeparator']").on("blur", function (event) {
                if ($(event.target).val() !== "") {
                    addThousandSeparator($(event.target));
                    if ($this._trigger("Validate", event, { currentRow: $this.InsertRowEle }) !== false) {
                        $this._trigger("InsertRowCalculate", event, { insertRow: $this.InsertRowEle });
                    }
                    $(event.target).css("borderColor", "");
                }
                else {
                    $(event.target).css("borderColor", "Red");
                    event.preventDefault();
                }
            });
            if (this.options.IsReadOnly) {
                this.InsertRowEle.hide();
            }
            if (!this.options.IsReadOnly) {
                //插入
                this._on(this.InsertRowEle.find("a").first(), { "click": function (event) {
                    if (this._trigger("Validate", event, { currentRow: this.InsertRowEle }) !== false) {
                        if (this._trigger("InsertRowCalculate", event, { insertRow: this.InsertRowEle }) !== false) {
                            var $tempTr = $(this.options.InsertRow);
                            $tempTr.find("input[type='text']").on("blur", function (event) {
                                if ($(event.target).val() !== "") {
                                    if ($(event.target).attr("class") === "thousandSeparator") {
                                        addThousandSeparator($(event.target));
                                    }
                                    $this._trigger("Change", event, { calculateRow: $this.TotalRowEle, contentBody: $this.trContentTdTableBodyEle, currentRow: $(event.target).parent().parent() });
                                    $(event.target).css("borderColor", "");
                                }
                                else {
                                    $(event.target).css("borderColor", "Red");
                                    event.preventDefault();
                                }
                            });
                            $tempTr.find("select").on("change", function (event) {
                                if ($(event.target).val() !== "0") {
                                    $this._trigger("Change", event, { calculateRow: $this.TotalRowEle, contentBody: $this.trContentTdTableBodyEle, currentRow: $(event.target).parent().parent() });
                                    $(event.target).css("borderColor", "");
                                }
                                else {
                                    $(event.target).css("borderColor", "Red");
                                    event.preventDefault();
                                }
                            });
    
                            $tempTr.find("td:first-child").html("<input type='checkbox'/>");
                            this.InsertRowEle.find("td").each(function (index, ele) {
                                if (index > 0) {
                                    $tempTr.find("td:eq(" + index + ")").children().first().val($(ele).children().first().val());
                                }
                            });
                            $tempTr.appendTo(this.trContentTdTableBodyEle);
                            this._trigger("TableCalculate", null, { calculateRow: this.TotalRowEle, contentBody: this.trContentTdTableBodyEle });
                        }
                    }
                }
                });
            }
            //trContent
            this.trContentTdEle = $("<td></td>").appendTo(this.trContentEle);
            this.trContentTdTableEle = $("<table width='100%' border='1'></table>").appendTo(this.trContentTdEle);
            this.trContentTdTableHeadEle = $("<thead></thead>").appendTo(this.trContentTdTableEle);
            this.trContentTdTableBodyEle = $("<tbody></tbody>").appendTo(this.trContentTdTableEle);
            this.trContentTdTableHeadRowEle = $(this.options.HeadRow).appendTo(this.trContentTdTableHeadEle);
            this.setContent();
        },
        _refresh: function () {
            if (this.options.IsReadOnly) {
                this.trSelectTdEle.hide();
                this.InsertRowEle.hide();
            }
            else {
                this.trSelectTdEle.show();
                this.InsertRowEle.show();
            }
            this.setContent();
        },
        _setOptions: function () {
            this._superApply(arguments);
            this._refresh();
        },
        _setOption: function (key, value) {
            this._super(key, value);
        },
        setContent: function () {
            $this = this;
            if (this.options.DataSource.length > 0) {
                if (!this.options.IsAdd) {
                    this.trContentTdTableBodyEle.empty();
                }
                var arrTr = this.options.DataSource.split(this.options.ArrayDelimiter);
                for (var tr in arrTr) {
                    if (arrTr[tr].length > 0) {
                        var $tempTr = $(this.options.InsertRow);
                        $tempTr.find("input[type='text']").on("blur", function (event) {
                            if ($(event.target).val() !== "") {
                                if ($(event.target).attr("class") === "thousandSeparator") {
                                    addThousandSeparator($(event.target));
                                }
                                $this._trigger("Change", event, { calculateRow: $this.TotalRowEle, contentBody: $this.trContentTdTableBodyEle, currentRow: $(event.target).parent().parent() });
                                $(event.target).css("borderColor", "");
                            }
                            else {
                                $(event.target).css("borderColor", "Red");
                                event.preventDefault();
                            }
                        });
    
                        $tempTr.find("select").on("change", function (event) {
                            if ($(event.target).val() !== "0") {
                                $this._trigger("Change", event, { calculateRow: $this.TotalRowEle, contentBody: $this.trContentTdTableBodyEle, currentRow: $(event.target).parent().parent() });
                                $(event.target).css("borderColor", "");
                            }
                            else {
                                $(event.target).css("borderColor", "Red");
                                event.preventDefault();
                            }
                        });
                        $tempTr.find("td:first-child").html("<input type='checkbox'/>");
                        if (this.options.IsReadOnly) {
                            $tempTr.find("td:first-child").html("");
                        }
                        var con = arrTr[tr].split(this.options.FieldDelimiter);
                        for (var i = 1; i <= con.length; i++) {
                            var $element = $tempTr.find("td:eq(" + i + ")").children().first();
                            $element.val(con[i - 1]);
                            if ($element.attr("class") === "thousandSeparator") {
                                $element.val(getValueWithThousandSeparator(con[i - 1]));
                            }
                            if (this.options.IsReadOnly) {
                                $element.attr("disabled", "disabled");
                                if ($element.attr("class") === "Wdate") {
                                    $element.unbind();
                                }
                            }
                        }
                        $tempTr.appendTo(this.trContentTdTableBodyEle);
                    }
                }
                this._trigger("TableCalculate", null, { calculateRow: this.TotalRowEle, contentBody: this.trContentTdTableBodyEle });
            }
        }
    });
    View Code

    四,调用方式

    首先,在页面中指定一个table标签,<table id="test_tb" width="100%"></table>,然后

     var test = $("#test_tb").AFGrid({
                    IsReadOnly: false,
                    TotalRow: "<tr><td width='10%'></td><td width='22.5%'></td><td width='22.5%' align='right'>合计金额</td><td  align='left'><label id='lbl_RecordsTotal'></label></td><td width='22.5%'></td></tr>",
                    InsertRow: "<tr><td width='10%'><a href='#' >插入项</a></td><td width='22.5%'><input type='text' style=' 100%' /></td><td width='22.5%'><input type='text' class='Wdate' onclick='WdatePicker()' style=' 100%' /></td><td  width='22.5%'><input type='text' style=' 100%' onkeydown='onlydigital()' class='thousandSeparator'/></td><td width='22.5%'><select style=' 100%'><option value='1'>正常</option><option value='2'>退票</option></select></td></tr>",
                    DataSource: $("#<%=hf_test.ClientID %>").val(),
                    HeadRow: "<tr><th width='10%'></th><th width='22.5%'>发票编号</th><th width='22.5%'>开具时间</th><th width='22.5%'>发票金额</th><th width='22.5%'>状态</th><tr>",
                    Title: "执行记录",
                    Change: function (event, data) {
                        if (ValidateTb(event, data)) {
                            CalculateTb(event, data);
                        }
                    },
                    Validate: function (event, data) {
                        ValidateTb(event, data);
                    },
                    InsertRowCalculate: function (event, data) {
    
                    },
                    TableCalculate: function (event, data) {
                        CalculateTb(event, data);
                    }
                });

    效果如图:

    随后可以通过改变IsReadOnly选项控制表格的可编辑性,可以重新指定数据源DataSource并结合IsAdd选项的设置为通过ajax获取的数据动态的添加或者刷新到表格上,代码详见https://files.cnblogs.com/afutureBoss/AFWidget.rar

  • 相关阅读:
    使用fiddler对手机APP进行抓包
    接口测试xml格式转换成json
    python datetime笔记
    python time模块详解
    python time相关操作
    2013流行Python项目汇总
    大象的崛起!Hadoop七年发展风雨录
    利用Mahout实现在Hadoop上运行K-Means算法
    20个开源项目托管站点推荐
    有用的国外开源项目网址
  • 原文地址:https://www.cnblogs.com/afutureBoss/p/3673222.html
Copyright © 2011-2022 走看看