Author Topic: Lost Focus after refreshDataAndView  (Read 6084 times)

empy

  • Newbie
  • *
  • Posts: 6
    • View Profile
Lost Focus after refreshDataAndView
« on: April 05, 2017, 01:26:34 pm »
Dears,

I am sitting with a problem for days now, cannot get to solve it on my own, however.
I have a script reading a CSV file and displaying it in pqgrid.

CSV data is displayed in two tables. Whenever to select a row in the top table, the below data and view has to be updated. Basically works fine, but one problem occured:
1: after selecting in the above table,
2: then filtering in the below table,
3: then unselecting in the above table,
4: and then unfiltering the below table
the data gets mixed up.
Once I reselect in the above table, data is correct again.

I can solve the issue with using

Code: [Select]
$("#selector").pqGrid({
filter: function( event, ui ) {
$("#selector").pqGrid.dataModel ={data:filter_data};
$("#selector").pqGrid( "refreshDataAndView" );
}
        });

but as a result, whenever I use the filter in the below table it loses its focus after typing 1 character (using filter listener 'keyup'). Filtering itself then works fine. It also works with listener 'change'. But that is not the intented filtering behaviour.

Can you help me out of my pit? I cannot make it work.

code
Code: [Select]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>roomsys display</title>

<!--jquery import -->
<script src="js/jquery.min.js"></script>

<!--jquery ui import + css -->
<link rel="stylesheet" href="css/jquery-ui.css" />
<script src="js/jquery-ui.min.js"></script>

<!--jquery csv import -->
<script src="js/jquery.csv-0.71.min.js"></script>

<!--paramquery grid import + css-->
<link rel="stylesheet" href="pqgrid/pqgrid.min.css" />
<script type="text/javascript" src="pqgrid/pqgrid.min.js" ></script>

<!--main script organization -->
<script type="text/javascript">

// method that checks that the browser supports the html5 file api
    function browserSupportFileUpload() {
var isCompatible = false;
if (window.File && window.FileReader && window.FileList && window.Blob) {
        isCompatible = true;
        }
return isCompatible;
}

// filter member data according to the selected rooms
function select_members(data_members,first){
var filter_members = [];

// get all selected rows
var selectionArray= $( "#grid_array_rooms" ).pqGrid( "selection",{
type:'row', method:'getSelection'
});

// set array with members, that fits filter criteria
// for all members ...
for (i = 0; i < data_members.length; i++){

// ... and all selected rooms ...
for (j = 0; j < selectionArray.length; j++){

// ... if idents are the same ...
if (data_members[i][5] == " "+selectionArray[j].rowData[0]){

// ... then push data into a new array
filter_members.push(data_members[i]);
}
}

// ... but if nothing is selected and members ident is unknown...
if (selectionArray.length == 0 && data_members[i][5] == " (no room booked) "){

// ... then push all unknown members into that array
filter_members.push(data_members[i]);
}
}

// call function that updates just the data in the already drawn member table
if (first == 1){

// table is already drawn, now just update data according to the new selection of rooms and refresh view. update filterd members in the table
$("#grid_array_members").pqGrid( "option" , "dataModel.data",filter_members );
$("#grid_array_members").pqGrid( "refreshDataAndView" );
}

// call function that draws table with the filtered members initially
if (first == 0){
draw_members(filter_members, data_members);
}
}

// draw table with the members for the first time
function draw_members(filter_members, data_members){

// draw filtered members in table with pqgrid
var obj_members = {
filterModel: { on: true, mode: "AND", header: true, type: 'local' },
};
obj_members.width = 1323;
obj_members.height = 300;
obj_members.title = "members";
obj_members.colModel = [{title:"attr1", width:110, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr2", width:120, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr3", width:120, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr4", width:60, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr5", width:65, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr6", width:110, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr7", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr8", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr9", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr10", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr11", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr12", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr13", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr14", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr15", width:139, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr16", width:138, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}}];
obj_members.dataModel = {data:filter_members};

// initialize pqgrid
$("#grid_array_members").pqGrid( obj_members );

// set event listeners for filtering in member area. without it, member data will be shown wrong after filtering and then reselecting rooms
$("#grid_array_members").pqGrid({
filter: function( event, ui ) {
//select_members(data_members, 1);
$("#grid_array_members").pqGrid( "option" , "dataModel.data",filter_members );
$("#grid_array_members").pqGrid( "refreshData" );
}
        });
}

// draw table with the rooms for the first time
function draw_rooms(data_rooms, data_members, initiate){

// if function is called for the first time draw and initiate the table
if (initiate == 0) {

// draw filtered rooms in table with pqgrid
var obj_rooms = {
selectionModel: { type: 'none', subtype:'incr', cbHeader:true, cbAll:true},
filterModel: { on: true, mode: "AND", header: true, type: 'local' },
};
obj_rooms.width = 1323;
obj_rooms.height = 300;
obj_rooms.title = "rooms";
obj_rooms.colModel = [{title:"attr1", width:110, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr2", width:120, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr3", width:120, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr4", width:60, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr5", width:50, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr6", width:70, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr7", width:70, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr8", width:90, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr9", width:50, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr10", width:70, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr11", width:20, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr12", width:100, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},

// is hidden
{title:"attr13", hidden: true, width:50, dataType:"integer", filter: {type: 'textbox', condition: 'equal', listeners: ['keyup']}},
{title:"attr14", width:140, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr15", width:110, dataType:"string", filter: {type: 'textbox', condition: 'contain', listeners: ['keyup']}},
{title:"attr16", width:30, align: "center", type:'checkBoxSelection', resizable: false, sortable:false}];
obj_rooms.dataModel = {data:data_rooms};

// initialize pqgrid
$("#grid_array_rooms").pqGrid( obj_rooms );

// draw members after loading the csv file without anything has to be selected
select_members(data_members, 0);

// set event listeners for select or unselect row or filtering
$("#grid_array_rooms").pqGrid({
rowSelect: function( event, ui ) {
select_members(data_members, 1);
                },
rowUnSelect: function( event, ui ) {
select_members(data_members, 1);
            },

// use it after filter is used in the table and view is refreshed therefore
refresh: function( event, ui ) {
select_members(data_members, 1);
            }
        });
}

// if function is called again, just update the data
if (initiate >= 1) {

// update rooms in already drawn table after loading a new csv
$("#grid_array_rooms").pqGrid( "option" , "dataModel.data",data_rooms );
$("#grid_array_rooms").pqGrid( "refreshDataAndView" );

// draw members after loading a new csv file without anything has to be selected
select_members(data_members, 1);

// set event listeners for select or unselect row or filtering
$("#grid_array_rooms").pqGrid({
rowSelect: function( event, ui ) {
select_members(data_members, 1);
                },
rowUnSelect: function( event, ui ) {
select_members(data_members, 1);
            },

// use it after filter is used in the table and view is refreshed therefore
refresh: function( event, ui ) {
select_members(data_members, 1);
            }
        });
}
}

// main function
$(document).ready(function() {

// define var to determin if it is the first run oder a following run
var initiate = 0;

// the event listener for the file upload
document.getElementById('txtFileUpload').addEventListener('change', upload, false);
   
// method that reads and processes the selected file
function upload(evt) {
if (!browserSupportFileUpload()) {
alert('The File APIs are not fully supported in this browser!');
}
else {
var data = null;
var file = evt.target.files[0];
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event) {
var csvData = event.target.result;
data = $.csv.toArrays(csvData);
if (data && data.length > 0) {

// 1st row has to be empty, 2nd refer to if-clause. then file is rommsys csv export, else abort
if (data[0].length == 1 && data[1] == "attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12, attr13, attr14, attr15"){

// cut two arrays for each members and rooms out of the csv import array
// start in row 3 (it is an array, for this slice_start = 2. this is the 1st row with room data)
var slice_start = 2;
var slice_end = 0;

// filter out rooms
// for each row in main array (begin with row 3, since this is the first room data after empty 1st line and 2nd head line) ...
for (i = 2; i < data.length; i++){

// ... if row is empty after rooms data  ...
if (data[i].length == 1){

// ...then set cut-point for the room data part
slice_end = i;
break;
}
}

// cut array for rooms
var data_rooms = [];
data_rooms = data.slice(slice_start,slice_end);

// set offset: after cut point of rooms there follows an empty row in the csv, followd by headings for the members. jump 2 rows therefore
slice_start = slice_end+2;

// last row is empty. this row has to be cut off
slice_end = data.length-1;

// cut array for members
var data_members = [];
data_members = data.slice(slice_start,slice_end);

// draw rooms
draw_rooms(data_rooms, data_members, initiate);
initiate++;
                }
else {
alert("File format not compatible!");
}
}
else {
alert("No data to import!");
}
};
reader.onerror = function() {
alert('Unable to read ' + file.fileName);
return data;
};
}
}
});
</script>

<style type="text/css">
.fileupload {
padding-bottom: 20px;
width: 665px;
}
.float {
float: left;
}
#grid_array_rooms, #grid_array_members {
margin:auto;
margin-top: 20px;
}
#panel {
width: 1330px;
margin: auto;
}
</style>


</head>

<body>
<div id="panel">
<div id="dvImportSegments" class="fileupload float">
  <fieldset>
    <legend>Upload your CSV File</legend>
    <input type="file" name="File Upload" id="txtFileUpload" accept=".csv" />
  </fieldset>
</div>
<div id="dvImportSegmentsBatch" class="fileupload float">
  <fieldset>
    <legend>Batch Upload with Folder</legend>
    <input type="file" name="File Upload" id="txtFileUploadBatch" accept=".csv" />
  </fieldset>
</div>
</div>
<div id="grid_array_rooms"></div>
<div id="grid_array_members"></div>
</body>
</html>

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #1 on: April 06, 2017, 01:27:00 pm »
Is it possible for you to share a jsfiddle to demonstrate the issue.

Have you used same data in both grids, if yes then it can get messed up. You could deep clone the data array before assigning it to the grids.

empy

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #2 on: April 06, 2017, 04:55:30 pm »
Hi,

thanks for quick response.
Here's a jsfiddle: https://jsfiddle.net/dw0m3bdn/3/
Attached a CSV to test.
EDIT: Please rename rooms.txt to rooms.csv, since I was not allowed to upload CSV directly.


The data is a parsed CSV into array. Afterwards I use it to cut it in two segments, the rooms and the members.
I reload the same data array name into the grid displaying the members, depending in the selection of the rooms in the grid above. Variable name is the same, but content of the array differs, depending on roomm selection. Everytime I reselect a room, members data should be refreshed. Pls see lines 165,168,173, for the function calls. 91 for refreshing it while filter. but that causes the problem.

Quote
You could deep clone the data array before assigning it to the grids.
Different variable name with same content? Or what do you think of?

Thanks alot in advance! Looking forward to hearing from you  :)

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #3 on: April 07, 2017, 05:13:12 pm »
Your attachment doesn't open up.

For performance reasons pqgrid uses the arrays by reference as are passed to it in the options object. So if you want to share same data array in dataModel.data or colModel across both grids, please use

$.extend(true, [], some_array)

https://api.jquery.com/jquery.extend/

Few more notes:

Quote
//outer selector.
$("#selector").pqGrid({
         filter: function( event, ui ) {
//inner selector.
            $("#selector").pqGrid.dataModel ={data:filter_data};
            $("#selector").pqGrid( "refreshDataAndView" );
            }
           });

I hope outer selector and inner selector inside filter event are different.
and it should be $("#selector2").pqGrid( "option", "dataModel.data", filter_data );
instead of $("#selector").pqGrid.dataModel ={data:filter_data};
« Last Edit: April 07, 2017, 05:19:26 pm by paramquery »

empy

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #4 on: April 07, 2017, 05:57:18 pm »
I dunnot know why attachment cannot be opened. If you save the following into a csv you should be able to test things.
(Beware if the blank lines in line 1 and in last 2 rows.)

Quote

attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12, attr13, attr14, attr15
Room:1a, 2017-05-02 11:00:00, 2017-05-02 11:30:00,  20,  3, b, ct_1,tfr,   5,     02,        0,   0000,  12, Vienna,
Room:22, 2017-05-02 11:00:00, 2017-05-02 11:30:00,  60,  2, bo, ct1,tfr,   6,        0,        8,   0000,  16, Brussels,
Room:2c, 2017-06-04 11:00:00, 2017-06-04 11:30:00,  10,  1, bo, vt2,tfr,   3,      27,       17,   0000,   9, Berlin,
Room:2d, 2017-07-07 11:00:00, 2017-07-07 11:30:00,  10,  1, bo ,       ,   ,  1,        0,        1,   0000,   0, ,
Room:1b, 2017-06-24 11:00:00, 2017-06-24 11:30:00,  15,  2, o, vt1,tfr,   1,       83,        3,   0000,  11, Dublin,
Room:1f, 2017-05-02 11:00:00, 2017-05-02 11:30:00,  40,  2, oob,vtt,tfr,   0,        4,        0,   0000,   8, London,
Room:16, 2017-01-09 11:00:00, 2017-01-09 11:30:00,  40,  3, b, ctt,tfr,   2,        8,        0,   0000,  13, Roma,

attr1, attr2, attr3, attr4, attr5, attr6, attr7
Mike, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   0,        0, (not booked) ,
Susan, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   0,      0, Room:22, Room:1b
Fred, 2017-06-04 11:00:00, 2017-06-04 11:30:00,  3,      0, Room:1a,
Robert, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   8,       0, (not booked) ,
Francis, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   3,       0, Room:16, Room:1b
Ana, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   0,        0, (not booked) ,
Stephen, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   6,        0, Room:2c,
Al, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   4,        0, Room:1f,
Maria, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   2,       0, (not booked) ,
Medow, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   1,        0, Room:16,
Peter, 2017-05-02 11:00:00, 2017-06-04 11:30:00,   2,        0, Room:1f,
Paul, 2017-05-02 11:00:00, 2017-06-04 11:30:00,  0,       0, Room:2d,



inner and outer selector are the same in my example. without it, is wrong after filter event.
I am gonna testing it with the extend method.

In the meanwhile, perhaps you could try it with the csv above. If you have more tips for me.
Main problem is that I only need to use the filter-thing because data isnt shown correctly.

I also tried it with .pqGrid( "option", "dataModel.data", filter_data ); but it did not make a difference.
« Last Edit: April 07, 2017, 06:03:56 pm by empy »

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #5 on: April 11, 2017, 08:43:44 pm »
setting new data and calling refreshDataAndView in filter event causes loss of focus in the header filter because refreshDataAndView refreshes the whole grid including header.

So you should avoid that.

Now your original problem of filtered data not showing correctly.

When data is filtered, filtered out rows are stored as dataModel.dataUF. If new data is set for the grid, it gets mixed up with dataUF.

When you set new data for grid while it's already in filtered state, you should either remove the filter or clear dataModel.dataUF. This should fix your original problem.

empy

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #6 on: April 13, 2017, 11:33:10 am »
trying a method with dataUF then. sounds promising. I will see how it works, give me some time please...

empy

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Lost Focus after refreshDataAndView
« Reply #7 on: April 19, 2017, 01:40:34 am »
I could not get things to work in the intended behaviour with dataUF. All I did is not what I needed.

After further thoughts I came up the idea of just setting the focus back to the last focused element (where my cursor lost focus before refreshDataAndView). That works. Very smooth in Google Browser, with a minimum delay in Internet Explorer.

Thank you anyways. However, dataUF made me understand what happens after refresh much better. Thank you.

Code: [Select]
// find out name of the active filter input field (identical to column)
var readname = document.activeElement.getAttribute("name");

// find all elements, what have same name as filter input field. (active node list of all fitting elements). position 3 it is the desired field
var setname = document.getElementsByName(readname)[3];

// set an unique identifier in order to identify for the workaround in order to focus
setname.setAttribute("id", "search-id-"+readname);

// set focus and cursor to last position (from stackoverflow http://stackoverflow.com/questions/637287/how-can-you-move-the-cursor-to-the-last-position-of-a-textarea-in-javascript
var v = $("#search-id-"+readname).val();
$( "#search-id-"+readname ).focus().val("").val(v);