Click here to Skip to main content
Click here to Skip to main content

Flex Like Grid in jQuery/JavaScript

By , 27 Aug 2012
Rate this:
Please Sign up or sign in to vote.

Introduction

Below is the code for creating a grid in jQuery. jQuery uses an HTML table and custom attributes to create grid at run time. Grid has features like sorting, custom item rendering just like in flex. Please note below grid can only be used with AJAX, i.e, you retrieve data collection using AJAX and then binding to the grid.

Using the code 

In the below code I am using LoadData (in AJAX you would be doing this in your call back function) to bind data to my grid. $("#mGrid").ConvertToSmartGrid(GridDP, SmartGridSettings); returns the grid object which is assigned to global variable. On subsequent retrieval of data from server, "refresh" method on sGrid is called. Since I am unable to upload .js files I have include all my code below. Also, make sure you are using jquery library (1.7.2) 

<!DOCTYPE html >
<html>
<head>
    <title>FlexLikeGrid</title>
    
<style type="text/css">
    
body
{
    font-family:Arial;
    font-size:12px;
    color:#000000;
  
}
.Rowgradient 
{
    background-color: #FFFFFF;
    background-image: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#C3CFD6)); /* Saf4+, Chrome */
    background-image: -webkit-linear-gradient(top, #FFFFFF, #C3CFD6); /* Chrome 10+, Saf5.1+, iOS 5+ */
    background-image: -moz-linear-gradient(top, #FFFFFF, #C3CFD6); /* FF3.6 */
    background-image:-ms-linear-gradient(top, #FFFFFF, #C3CFD6); /* IE10 */
    background-image:-o-linear-gradient(top, #FFFFFF, #C3CFD6); /* Opera 11.10+ */
    background-image: linear-gradient(top, #FFFFFF, #C3CFD6);
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,
      startColorstr=#FFFFFF,endColorstr=#C3CFD6); /* GradientType=0 : vertical, 1:horizontal IE6–IE9 */
}  
.GridStyle{
    border:solid 0px #8AABBD;
    table-layout:fixed;
    width:100%;
    text-indent:0.5em;   
}
.GridStyle td
{
    white-space:nowrap;
    overflow:hidden;
    -ms-text-overflow:ellipsis; 
    text-overflow:ellipsis;
    padding:3px 0px 3px 0px;
}
.GridStyle TR.EvenRow
{
    background-color:#FFFFFF;
}
.GridStyle TR.EvenRow:hover
{
    background-color: #FFFFE0;/*#FFFACD;*/
}
.GridStyle TR.OddRow
{
    background-color:#E4E8EB;
}
.GridStyle TR.OddRow:hover
{
    background-color:#FFFFE0; /*#FFFACD;*/
}
.GridStyle TR.GridHeaderStyle
{
    font-weight:bold;
    font-size:11px;
}
.GridStyle TR.GridHeaderStyle td.Sortable
{
    background-image : url("../images/sort.png");
    background-position:right;
    background-repeat:no-repeat;
   
}
.GridStyle TR.GridHeaderStyle td.Sortable:hover
{
    background-color:#C3CFD6;
    color:#444444;
}
button
{
    border: solid 1px silver;
    font-size:11px;
    font-weight:bold;
    background-color:#d8e7fd;
    padding:2px 1px 2px 1px;
    letter-spacing:0.6pt;
    cursor:pointer;
}
button:hover
{
    background-color:#aad1fe;
}
        
input[type='submit']
{
    border: solid 1px silver;
    font-size:11px;
    font-weight:bold;
    background-color:#d8e7fd;
    cursor:pointer;
    letter-spacing:0.6pt;
    padding:2px 1px 2px 1px;
}
        
        
input[type="submit"].FolbsSearch
{
    background-image:url('../images/search.png');
    background-repeat:no-repeat;
    background-position:left center;
    text-indent:1.6em;
    padding:2px 1px 2px 1px;
   
}
input[type="button"].FolbsSearch
{
    background-image:url('../images/search.png');
    background-repeat:no-repeat;
    background-position:left center;
    text-indent:1.6em;
    padding:2px 1px 2px 1px;
   
}
input[type="submit"].FolbsExcelDownload
{
    background-image:url('../images/excel.png');
    background-repeat:no-repeat;
    background-position:left center;
    text-indent:1.6em;
    padding:2px 1px 2px 1px;
          
}
input[type="button"].FolbsExcelDownload
{
    background-image:url('../images/excel.png');
    background-repeat:no-repeat;
    background-position:left center;
    text-indent:1.6em;
    padding:2px 1px 2px 1px;
          
}
input[type="submit"].FolbsNotes
{
    background-image:url('../images/notepad.png');
    background-repeat:no-repeat;
    background-position:left center;
    text-indent:1.6em;
    padding:2px 1px 2px 1px;
          
}
input[type="submit"]:hover
{
    background-color:#aad1fe;
}
        
input[type="button"]
{
    border: solid 1px silver;
    font-size:11px;
    font-weight:bold;
    background-color:#d8e7fd;
    cursor:pointer;
    letter-spacing:0.6pt;
    padding:2px 1px 2px 1px;
}
input[type='button']:hover
{
    background-color:  #aad1fe;
}
        
input[type='text']
{
    border : 1px solid silver;
    background-color:#FFFFFF;
}
input[type='text']:focus
{
    background-color: #ffa;/*#EFEFEF;*/
}
input[type='text']:hover
{
    background-color: #ffa; /*#EFEFEF;*/
}
input[type='text']:disabled
{
    background-color: #EEEEEE; /*#EFEFEF;*/
}
input[type='text']:disabled:hover
{
    background-color: #EEEEEE; /*#EFEFEF;*/
}
input[type='text']
{
    border : 1px solid silver;
    background-color:#FFFFFF;
}
input[type='text']:focus
{
    background-color: #ffa;/*#EFEFEF;*/
}
input[type='text']:hover
{
    background-color: #ffa; /*#EFEFEF;*/
}input[type='password']
{
    border : 1px solid silver;
    background-color:#FFFFFF;
}
input[type='password']:focus
{
    background-color: #ffa;/*#EFEFEF;*/
}
input[type='password']:hover
{
    background-color: #ffa; /*#EFEFEF;*/
}
input[type='checkbox']
{
    
}
a
{
    color:#002EB8;
    text-decoration:underline;
}
a:hover
{
    color:#002EB8;
    text-decoration:none;
}
a:visited
{
    color:#002EB8;
    text-decoration:underline;
}
    </style>
    <script src="Scripts/jquery-1.7.2.js"></script>
<script language="javascript">/********** SIMPLE GRID **********************/
(function ($) {
   
        var SmartGridSettings ;

        $.fn.ConvertToSmartGrid = function (arrData, settings) {
            SmartGridSettings = settings;
            var tgtGrid = this;
            var tgtPrnt = tgtGrid.parent();
            var prntTag = tgtPrnt.prop("tagName");
           
            if (prntTag != "DIV") {
                alert("Grid needs to be inside block element div");
                return;
            }



            var tblWdth; var hdrClss; var evenRowClss; var oddRowClss;
            var tblHt; var showGridLines

            tblWdth = tgtGrid.outerWidth();
            tblHt = tgtGrid.css("height");

            evenRowClss = tgtGrid.attr("evenRowClass");
            oddRowClss = tgtGrid.attr("oddRowClass");
            hdrClss = tgtGrid.attr("headerClass");
            tblClss = tgtGrid.attr("class");
            showGridLines = tgtGrid.attr("showGridLines") == "true" ? true : false;


            hdrClss = typeof (hdrClss) == "undefined" ? "GridHeaderStyle" : "GridHeaderStyle " + hdrClss;
            evenRowClss = typeof (evenRowClss) == "undefined" ? "EvenRow" : evenRowClss;
            oddRowClss = typeof (oddRowClss) == "undefined" ? "OddRow" : oddRowClss;
            tblClss = typeof (tblClss) == "undefined" ? "GridStyle" : "GridStyle " + tblClss;

            var arrTrs = tgtGrid.find('tr');
            var gridTr = arrTrs[0];
            gridTr = $(gridTr);
            var gridTds = gridTr.children(['td']);


            //creating header grid
            var hdrTblTr = document.createElement("tr");
            hdrTblTr = $(hdrTblTr);
            hdrTblTr.addClass(hdrClss);


            var SortData = function(event){
                event.data.JqTBody = $("#_t_b_dy");
                GridHandler.SortTable(event);
                event.stopImmediatePropagation();
            };

            var tdWidth;
            var tdStyle;
            var ntd;
            var srtble;

            
            //creating header row and td
            gridTds.each(function (idx) {
                tdWidth = $(this).attr("width");
                tdStyle = $(this).attr("style");
                ntd = document.createElement("td");
                ntd = $(ntd);
                typeof (tdWidth) != "undefined" ? ntd.attr("width", tdWidth) : "";
                showGridLines == true ? ntd.css("border-right", "solid 1px silver") : "";

                ntd.text($(this).attr("headerText"));
                ntd.css("padding", "3px 0px 3px 0px");
                
                srtble = typeof($(this).attr("Sortable"))
                srtble != "undefined" ? ntd.addClass("Sortable") : "";
                if(srtble != "undefined")
                {
                    var evData =new Object();
                   // evData.jqTBody = ntd.parent().parent();
                    evData.ColIdx = idx;
                    evData.EvenRowClss = evenRowClss;
                    evData.OddRowClss = oddRowClss;
                    ntd.bind("click", evData, SortData);
                }
                  
                hdrTblTr.append(ntd);
            });


            ntd = document.createElement("td");
            $(ntd).attr("width", "16px");
            hdrTblTr.append($(ntd));

            var hdrTbl = document.createElement("table");
            var jhdrTbl = $(hdrTbl);
            jhdrTbl.addClass(tblClss);
           
            
               
            jhdrTbl.attr("cellpadding", "2");
            jhdrTbl.attr("cellspacing", "0");
            jhdrTbl.append(hdrTblTr);


            var hdrDiv = document.createElement("div");
            $(hdrDiv).append(hdrTbl);

            tgtGrid.css("display", "none");


            tgtPrnt.width(tblWdth); // setting parent width to width of grid width

            tgtPrnt.append($(hdrDiv)); // adding header 



            //********starting building grid Rows*************

            var getPropertyValue = function (dataField, data) {
                var retVal;
                var arrDataField;
                arrDataField = dataField.split(".");

                if (arrDataField.length > 1) {
                    for (var x in arrDataField) {
                        data = data[arrDataField[x]];
                    }
                    retVal = data;
                }
                else {
                    retVal = data[dataField];
                }

                return retVal;
            };



            var ctntTbl = document.createElement("table");
            var tbody = document.createElement("tbody");
            $(tbody).attr("id", "_t_b_dy");
            
            ctntTbl = $(ctntTbl);
            ctntTbl.append(tbody);
            ctntTbl.addClass(tblClss);
            ctntTbl.attr("cellpadding", "2");
            ctntTbl.attr("cellspacing", "0");


            var PopulateGridContent = function (arrData) {
                var ctntTr; var data; var propVal; var ctntTd; var lblFn;
                var dataField; var iRend; var thsObj;
                var elem; var rendFn;
                for (var i in arrData) {
                    data = arrData[i];
                    ctntTr = document.createElement("tr");
                    ctntTr = $(ctntTr);
                    i % 2 == 0 ? ctntTr.addClass(oddRowClss) : ctntTr.addClass(evenRowClss);

                    gridTds.each(function (idx) {
                        thsObj = $(this);
                        dataField = thsObj.attr("dataField");
                        propVal = getPropertyValue(dataField, data);

                        ctntTd = document.createElement("td");
                        ctntTd = $(ctntTd)
                        tdWidth = thsObj.attr("width");
                        tdStyle = thsObj.attr("style");
                        typeof (tdWidth) != "undefined" ? ctntTd.attr("width", tdWidth) : "";
                        typeof(tdStyle) != "undefined" ? ctntTd.attr("style", tdStyle) : "";

                        showGridLines == true ? ctntTd.css({
                                                                "border-right" :  "solid 1px silver",
                                                                "border-bottom" :  "solid 1px silver",
                                                                }) : "";
                           
                        rendFn = thsObj.attr("itemRendererFunction");
                        typeof(rendFn) != "undefined" && rendFn != 
                          "" ? window[rendFn](data, ctntTd, idx) : ctntTd.text(propVal);


                        ctntTr.append(ctntTd);
                    });

                    ctntTbl.append(ctntTr);

                  
                }
            };

            PopulateGridContent(arrData);
            var ctntDiv = document.createElement("div");
            ctntDiv = $(ctntDiv);
            ctntDiv.css({
                "height": tblHt,
                "overflow-y": "scroll",
                "overflow-x": "auto"
            });

            ctntDiv.append(ctntTbl);

            tgtPrnt.append(ctntDiv); // adding content

           
            if (settings.ShowPagination) {
                var pgDiv = document.createElement("div");
                pgDiv = $(pgDiv);
                pgDiv.css({
                    "position": "relative",
                    "height": "25px",
                    "border": "solid 0px red"
                });

                tgtPrnt.append(pgDiv);
                if(SmartGridSettings.PaginationType == "AppendToExistingRecord")
                {
                    var spn = document.createElement("span");
                    spn = $(spn);
                    spn.css({
                        "position" : "absolute",
                        "right" : "2px"
                    });

                   spn.append("<label>Total Record: " + 
                     SmartGridSettings.MaxRecord + "</label>" );

                    var ancr = document.createElement("a");
                    ancr = $(ancr);
                    ancr.attr("href", "#");
                    ancr.css("margin-left", "15px");
                    ancr.text("Get Next " + SmartGridSettings.RecordsPerPage + " Records");
                    ancr.bind("click",SmartGridSettings.GetMoreFn);
                    spn.append(ancr);

                    pgDiv.append(spn);  

  
                }
                else
                {
                    pgDiv.GetPaginationUI(SmartGridSettings.MaxRecord, 
                      SmartGridSettings.RecordsPerPage, SmartGridSettings.GetMoreFn, 
                      'dropdown', "0-" + SmartGridSettings.RecordsPerPage);
                }

            }

            tgtPrnt.css("border", "solid 1px silver");


            this.refresh = function (arrData) {
                if(SmartGridSettings.PaginationType != "AppendToExistingRecord")
                {
                    $("#_t_b_dy").empty();
                }
                PopulateGridContent(arrData);
            }

            return this;
        };
    })(jQuery);


//*************** Simple Data Grid Ends********************

var GridHandler = {
    SortByColIdx: null,

    SortDirection: null,

    AscendDataCompareFunction: function (jqTrA, jqTrB) {
        var a = jqTrA.text().toLowerCase();
        var b = jqTrB.text().toLowerCase();

        var aDtMillsec = Date.parse(a)
        if (isNaN(aDtMillsec) == false) {
            a = aDtMillsec;

            b = Date.parse(b);
        }
        if (isNaN(parseInt(a))) {

         

            if (a > b) {
                return -1
            }
            if (a < b) {
                return 1
            }

            return 0;
        }
        else {
            return a - b;
        }
    },

    DescendDataCompareFunction: function (jqTrA, jqTrB) {

     
        var a = jqTrA.text().toLowerCase();
        var b = jqTrB.text().toLowerCase();

        var aDtMillsec = Date.parse(a)
        if (isNaN(aDtMillsec) == false) {
            a = aDtMillsec;

            b = Date.parse(b);
        }
        if (isNaN(parseInt(a))) {
            if (a > b) {
                return 1
            }
            if (a < b) {
                return -1
            }
            return 0;
        }
        else {
            return b - a;
        }
    },

    SortTable: function (event) {
    
        var jqTBody = event.data.JqTBody;
        var colIdx = event.data.ColIdx;

        GridHandler.SortByColIdx = colIdx;

        var arrTrs = jqTBody.find("TR");

        var arrTds = new Array();
        var ntd;
        var len = arrTrs.length;
        
        for (var i = 0; i < len; i++) {
            $(arrTrs[i]).removeAttr("class");
            ntd = $(arrTrs[i]).find("td").get(colIdx);

            $(ntd).attr("idx", i);

            arrTds.push($(ntd));
        }


        if (GridHandler.SortDirection == null || GridHandler.SortDirection == "D") {
            GridHandler.SortDirection = "A"
            arrTds.sort(GridHandler.AscendDataCompareFunction);
        }
        else {
            GridHandler.SortDirection = "D"
            arrTds.sort(GridHandler.DescendDataCompareFunction);
        }

        var oRowCls = event.data.EvenRowClss;
        var eRowClss = event.data.OddRowClss;
        jqTBody.empty();
        
        $(arrTds).each(function (idx) {
            ix = $(this).attr("idx");
            if (idx % 2 == 0) {
                $(arrTrs[ix]).addClass(eRowClss);
            }
            else {
                $(arrTrs[ix]).addClass(oRowCls);

            }
            jqTBody.append(arrTrs[ix]);
        });

    }
};

/********** SIMPLE GRID ENDS **********************/


(function ($) {
    $.fn.GetPaginationUI = function (totalRecCount,
                                    noRecPerPage,
                                    onPageSelectionHandler,
                                    type,
                                    selectedRangeVal) {

        if($.isEmptyObject($("#_pge_div")) == false)
        {
            $("#_pge_div").remove();
        }
        var str = new StringBuilder();
        str.append("<div id='_pge_div' style='position:absolute;top:2px;" +
                            "border:solid 0px red;" +
                            "right:15px;'>");

        str.append("<input type='hidden' name='sRange' id='sRange' value='' />");
        var ctr = Math.ceil(totalRecCount / noRecPerPage);

        var strNum = 0;
        var endNum = noRecPerPage;

        str.append("<span style='margin-right:30px;'><b>Total Records:</b> " + totalRecCount + "</span>");

        str.append("<span style='margin-right:50px'>" +
                "<input type='text' onkeyup=\"PaginationValidation('_recsPerPage')\" 
                id='_recsPerPage' name='_recsPerPage' size='4' style='text-align:right' value='" + 
                noRecPerPage + "' /> <b>records per page</b>" +
               "</span>");

        if (type == "numbers") {
            for (var i = 0; i < ctr; i++) {
                str.append("<span style='margin-left:2px;padding:0px 2px 0px 2px;" +
                                    "text-decoration:underline;" +
                                    "cursor:pointer;" +
                                    "font-weight:bold;" +
                                    "margin-right:4px;" +
                                    "border:solid 1px #999999' onclick='" + 
                                    onPageSelectionHandler + "(" + strNum + "," + 
                                    endNum + ")'>" + (i + 1) + "</span>")
                strNum = endNum;
                endNum = endNum + noRecPerPage;
            }
        }
        else if (type == "dropdown") {
            var rangeval;
            var strSelected = "";

            var selectElem = document.createElement("SELECT");
            $(selectElem).attr("id", "pdwn");




            for (var i = 0; i < ctr; i++) {

                rangeval = strNum.toString() + "-" + endNum.toString();
              
                if (rangeval == selectedRangeVal) {
                    strSelected = " SELECTED ";
                }
                else {
                    strSelected = "";
                }

                $(selectElem).append("<option  " + strSelected + "  value ='" + 
                  rangeval + "'>" + (i + 1) + "</option>");

                strNum = endNum;
                endNum = parseInt(endNum) + parseInt(noRecPerPage);

            }
            str.append("show page ");

            str.append(selectElem.outerHTML);
            str.append(" of " + i);
        }
        str.append("</div>");

        $(this).append(str.toString());
        $("#pdwn").bind("change", onPageSelectionHandler);
        str.clear();
    };
})(jQuery);



function StringBuilder(value)
{
    this.strings = new Array("");
    this.append(value);
}

// Appends the given value to the end of this instance.

StringBuilder.prototype.append = function (value)
{
    if (value)
    {
        this.strings.push(value);
    }
}

// Clears the string buffer

StringBuilder.prototype.clear = function ()
{
    this.strings.length = 1;
}

// Converts this instance to a String.

StringBuilder.prototype.toString = function ()
{
    return this.strings.join("");
    
}</script>
    <script language="javascript" type="text/javascript">
   
    var sGrid;

    function CreateMockData() {
        var GridDP = new Array();
        var obj;
        for (var i = 0; i < 5; i++) {

            obj = new Object();
            obj.Person = {
                FirstName: "First Name" + i,
                Address: {
                    City: "Boston" + i
                }
            };
            obj.LastName = "Last Name " + i;
            obj.Title = "Sr.Software Engg";
            obj.Address1 = "Address1";
            obj.Address2 = "Address2";
            obj.MobilePhone = "555 555 5 55"
            obj.LanPhone = "22 2222 2222";

            GridDP.push(obj);

        };

        return GridDP;
    }

    function LoadData() {

        SmartGridSettings = new Object();
        SmartGridSettings.MaxRecord = 100;
        SmartGridSettings.RecordsPerPage = 10;
        SmartGridSettings.GetMoreFn = GetMoreFunction;
        SmartGridSettings.ShowPagination = true;
        // using AppendToExistingRecord if you want to keep appending
        // record to existing result set when click GetMoreFunction is called
        SmartGridSettings.PaginationType = "";

        var GridDP = CreateMockData();
        sGrid = $("#mGrid").ConvertToSmartGrid(GridDP, SmartGridSettings);
    }


    function MyItemRendererFunction(data,colTd, colIdx){

        if (data.Person.FirstName == "First Name0")
        {
            colTd.append("<input  type='text'style='width:90%;padding:0 0 0 0' value='" + 
                    data.Person["FirstName"] + "' />");
        }
        else{
            colTd.text(data.Person["FirstName"]);
        }
    }

    function GetMoreFunction() {
        var GridDP = new Array();
        var obj;
        for (var i = 0; i < 5; i++) {
            obj = new Object();
            obj.Person = {
                FirstName: "New FirstName" + i,
                Address: {
                    City: "Bangkok" + i
                }
            };
            obj.LastName = "Last Name " + i;
            obj.Title = "CFA";
            obj.Address1 = "Address1";
            obj.Address2 = "Address2";
            obj.MobilePhone = "555 555 5 55"
            obj.LanPhone = "22 2222 2222";

            GridDP.push(obj);

        };

        // call .refresh method if you want to refresh data
        sGrid.refresh(GridDP);
    }


    
    </script>
</head>
<body onload="LoadData()">
     <div id='mgridDiv' style="border:solid 1px silver;">
        <table id = "mGrid"
                            showGridLines = "true" 
                            contentEvenRowClass="EvenRow" 
                            contentOddRowClass = "OddRow"
                            headerClass="Rowgradient"
                            style="width:700px;height:600px;display:none;">     
             <tr>
               
                <td id="fname" 
                    width="120px" 
                    Sortable
                    itemRendererFunction =  "MyItemRendererFunction"
                    headerText = "First Name" 
                    dataField = "Person.FirstName" >
                      
                </td>
                <td  headerText = "City" Sortable
                    labelFunction="TestFunction"    
                    itemRenderer="textbox" 
                    itemRendererEventHandlers="click,OnItemClick;" 
                    dataField = "Person.Address.City">
                 
                </td>

                <td headerText = "Title" 
                    dataField = "Title">
            
                </td>
                <td headerText = "Address1"   
                    dataField = "Address1">
            
                </td>
                <td headerText = "Address2"
                    dataField = "Address2">
            
                </td>
                <td headerText = "Mobile Phone"  
                    dataField = "MobilePhone">
            
                </td>
                <td headerText = "LAN Phone"  
                    dataField = "LanPhone">
            
                </td>
             </tr>                      
        </table>
  </div>
                            
</body>
</html>

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

NewCodePlayer
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web03 | 2.8.140421.2 | Last Updated 27 Aug 2012
Article Copyright 2012 by NewCodePlayer
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid