views:

127

answers:

2

I am using jlinq a library for extending linq to json and hence i filter my json data. Consider i have a json data that draws a yui datatable on page load with 100 rows. I am doing a clientside filter which will reduce my json data and i am now redrawing the same datatable. What happens is it works pretty well but with an annoying flickering effect...

I call the below method from onkeyup event of the filter textbox,

function showusersfilter(txt) {
    var jsondata = document.getElementById("ctl00_ContentPlaceHolder1_HfJsonString").value;
    jsondata = jQuery.parseJSON(jsondata);
    var results = jLinq.from(jsondata.Table)
                 .startsWith("name", txt)
                 .select();
    var jsfilter = { "Table": results };

    var myColumnDefs = [
         { key: "userid", label: "UserId", hidden: true },
         { key: "name", label: "Name", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
         { key: "designation", label: "Designation" },
         { key: "phone", label: "Phone" },
         { key: "email", label: "Email" },
         { key: "role", label: "Role", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
         { key: "empId", label: "EmpId" },
         { key: "reportingto", label: "Reporting To", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
         { key: "checkbox", label: "", formatter: "checkbox", width: 20 }
     ];
    var jsonObj = jsfilter;
    var target = "datatable";
    var hfId = "ctl00_ContentPlaceHolder1_HfId";
    generateDatatable(target, jsonObj, myColumnDefs, hfId);
}

My textbox looks

<asp:TextBox ID="TxtUserName" runat="server" CssClass="text_box_height_14_width_150" onkeyup="showusersfilter(this.value);"></asp:TextBox>

and my generatedatatable function,

function generateDatatable(target, jsonObj, myColumnDefs, hfId) {
    var root;
    for (key in jsonObj) {
        root = key; break;
    }
    var rootId = "id";
    if (jsonObj[root].length > 0) {
        for (key in jsonObj[root][0]) {
            rootId = key; break;
        }
    }
    YAHOO.example.DynamicData = function() {
        var myPaginator = new YAHOO.widget.Paginator({
            rowsPerPage: 25,
            template: YAHOO.widget.Paginator.TEMPLATE_ROWS_PER_PAGE,
            rowsPerPageOptions: [10, 25, 50, 100],
            pageLinks: 10
        });

        // DataSource instance 
        var myDataSource = new YAHOO.util.DataSource(jsonObj);
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
        myDataSource.responseSchema = { resultsList: root, fields: new Array() };
        myDataSource.responseSchema.fields[0] = rootId;
        for (var i = 0; i < myColumnDefs.length; i++) {
            myDataSource.responseSchema.fields[i + 1] = myColumnDefs[i].key;
        }
        // DataTable configuration 
        var myConfigs = {
            sortedBy: { key: myDataSource.responseSchema.fields[1], dir: YAHOO.widget.DataTable.CLASS_ASC }, // Sets UI initial sort arrow
            paginator: myPaginator
        };
        // DataTable instance 
        var myDataTable = new YAHOO.widget.DataTable(target, myColumnDefs, myDataSource, myConfigs);
        myDataTable.resizeHack = function()
        { this.getTbodyEl().parentNode.style.width = "100%"; }
        myDataTable.subscribe("rowMouseoverEvent", myDataTable.onEventHighlightRow);
        myDataTable.subscribe("rowMouseoutEvent", myDataTable.onEventUnhighlightRow);
        myDataTable.subscribe("rowClickEvent", myDataTable.onEventSelectRow);
        myDataTable.subscribe("checkboxClickEvent", function(oArgs) {
            var hidObj = document.getElementById(hfId);
            var elCheckbox = oArgs.target;
            var oRecord = this.getRecord(elCheckbox);
            var id = oRecord.getData(rootId);
            if (elCheckbox.checked) {
                if (hidObj.value == "") {
                    hidObj.value = id;
                }
                else {
                    hidObj.value += "," + id;
                }
            }
            else {
                hidObj.value = removeIdFromArray("" + hfId, id);
            }
        });
        myPaginator.subscribe("changeRequest", function() {

            if (document.getElementById(hfId).value != "") {
                if (document.getElementById("ConfirmationPanel").style.display == 'block') {
                    document.getElementById("ConfirmationPanel").style.display = 'none';
                }
                document.getElementById(hfId).value = "";
            }
            return true;
        });
        myDataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
            oPayload.totalRecords = oResponse.meta.totalRecords;
            return oPayload;
        }
        return {
            ds: myDataSource,
            dt: myDataTable
        };
    } ();
}

EDIT:

I even used a delay on the keyup event still the flickering occurs,

var timer;
    function chk_me(){
       clearTimeout(timer);
       timer = setTimeout(function validate(){ showusersfilter(document.getElementById("ctl00_ContentPlaceHolder1_TxtUserName").value);}, 1000);
    }
+1  A: 

The problem could be related to the line:

myDataTable.resizeHack = function()
        { this.getTbodyEl().parentNode.style.width = "100%"; }

Since you are resizing the width of the table, it is reasonable to assume that the table will need to be re-painted on the screen resulting in the flicker.

Alison
@Alison any suggestion to avoid it...
Pandiya Chendur
If you remove the line, does the flicker go away?
Alison
@ALison it didn't get away. Anyother suggestion. But the flicker has been reduced still a small amount of flickering is happening.
Pandiya Chendur
Try commenting out the other lines that change the style of the table. Somewhere in generatedatatable is where the problem is occurring. You'll need to go step by step commenting out code to locate the source.
Alison
+1  A: 

Why do you create a new dataTable each time you filter your data ? You do not need this task. Just supply The filtered data to its dataTable by using sendRequest method of its dataSource

I have create this jsonObject To simulate filtered data

var jsonObject = {
    "root":[
        {id:"5", userid:"1", name:"ar", designation:"1programmer", phone:"15484-8547", email:"[email protected]", role:"1developer", empId:"1789", reportingto:"116"},
        {id:"5", userid:"2", name:"br", designation:"2programmer", phone:"25484-8547", email:"[email protected]", role:"2developer", empId:"2789", reportingto:"216"},
        {id:"5", userid:"3", name:"cr", designation:"3programmer", phone:"35484-8547", email:"[email protected]", role:"3developer", empId:"3789", reportingto:"316"},
        {id:"5", userid:"4", name:"dr", designation:"4programmer", phone:"45484-8547", email:"[email protected]", role:"4developer", empId:"4789", reportingto:"416"},
        {id:"5", userid:"5", name:"er", designation:"5programmer", phone:"55484-8547", email:"[email protected]", role:"5developer", empId:"5789", reportingto:"516"}
    ],
    "another":[
        {id:"5", userid:"5", name:"er", designation:"5programmer", phone:"55484-8547", email:"[email protected]", role:"5developer", empId:"5789", reportingto:"516"},
        {id:"5", userid:"4", name:"dr", designation:"4programmer", phone:"45484-8547", email:"[email protected]", role:"4developer", empId:"4789", reportingto:"416"},
        {id:"5", userid:"3", name:"cr", designation:"3programmer", phone:"35484-8547", email:"[email protected]", role:"3developer", empId:"3789", reportingto:"316"},
        {id:"5", userid:"2", name:"br", designation:"2programmer", phone:"25484-8547", email:"[email protected]", role:"2developer", empId:"2789", reportingto:"216"},
        {id:"5", userid:"1", name:"ar", designation:"1programmer", phone:"15484-8547", email:"[email protected]", role:"1developer", empId:"1789", reportingto:"116"}
    ]
};

When initializing

(function() {
    var Yutil      = YAHOO.util,
        Ywidget    = YAHOO.widget

        DataTable  = Ywidget.DataTable,
        Paginator  = Ywidget.Paginator,
        DataSource = Yutil.DataSource;

    YAHOO.namespace("_3657287"); // QUESTION ID - SEE URL

    var _3657287 = YAHOO._3657287;

    /**
      * paginator
      */
    var paginator = new Paginator({
        rowsPerPage:25,
        template:Paginator.TEMPLATE_ROWS_PER_PAGE,
        rowsPerPageOptions:[10, 25, 50, 100],
        pageLinks:10
    });

    /**
      * dataSource
      *
      * As you have static data, I pass an empty "jsonObject" to its constructor
      */
    var dataSource = new DataSource({root:[]});
    dataSource.responseType = DataSource.TYPE_JSON;
    dataSource.responseSchema = {resultsList:"root", fields:[]};

    var columnSettings = [
        {key:"userid", label:"UserId"},
        {key:"name", label:"Name"},
        {key:"designation", label:"Designation"},
        {key:"phone", label:"Phone"},
        {key:"email", label:"Email"},
        {key:"role", label:"Role"},
        {key:"empId", label:"EmpId"},
        {key:"reportingto", label:"Reporting To"}
    ];

    dataSource.responseSchema.fields[0] = "id";
    for (var i = 0; i < columnSettings.length; i++) {
        dataSource.responseSchema.fields[i + 1] = columnSettings[i].key;
    }

    /**
      * Notice initialLoad equal To false (I suppose your dataTable IS NOT pre-populated)
      */
    var dataTableSettings = {
        paginator:paginator,
        initialLoad:false
    };

    /**
      * dataTable
      *
      * Notice IT IS STORED in the namespace YAHOO._3657287
      */
    _3657287.dataTable = new DataTable("container", columnSettings, dataSource, dataTableSettings);
})();

Now when you want to filter your data, do as follows (Notice sendRequest method)

var i = 0;
YAHOO.util.Event.addListener("reload", "keyup", function(e) {
    YAHOO._3657287.dataTable.getDataSource().sendRequest(null, {
        success:function(request, response, payload) {

            /**
              * initializeTable method clear any data stored by The datatable
              */
            this.initializeTable();

            if(i === 0) {
                this.getRecordSet().setRecords(jsonObject["root"], 0);

                i++;
            } else {
                this.getRecordSet().setRecords(jsonObject["another"], 0);

                i--;
            }

            this.render();
        },
        scope:YAHOO._3657287.dataTable,
        argument:null
    });
});

You can see here. It works fine!

But if the effect appears again (Notice i am just using relevant part - Nor special feature Nor something else) can occurs because

  • keyup Event
  • dataTable rendering

You can set up a variable as follows

var isProcessing = false;

YAHOO.util.Event.addListener("reload", "keyup", function(e) {
    if(isProcessing) {
        return;
    }

    isProcessing = true;

    YAHOO._3657287.dataTable.getDataSource().sendRequest(null, {
        success:function(request, response, payload) {
             // as shown above

             isProcessing = false;
        }
    });
}

See also here and here

Arthur Ronald F D Garcia
@Arthur that worked perfectly..
Pandiya Chendur