jQWidgets Forums

Forum Replies Created

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts

  • EmilioP
    Participant

    Hello Hristo Hristov,
    thanks for trying.
    The error happens to me at least once every 20 refreshes (more or less), both on chrome and on firefox.

    Could you write the ajax function you implemented?


    EmilioP
    Participant

    I forgot to repeat an important thing: the error, even in the example above, occurs with a frequency of 10-15%.
    So it is possible that, to generate the error, it is necessary to reload the page 10-20 times


    EmilioP
    Participant

    Hello Hristo Hristov,
    I took a look at the topic mentioned above, but I don’t think it solves this error.

    Some considerations on the example that I will report below:
    A) if you want to run it you will have to take care of the server side and modify the ENDPOINT variable in the database.js file;
    B) the home page has a list of sections on the left, in the example shown there is only the database section (for simplicity) but in the real version there are more sections that can be visited by the user that modify the right part of the graphical interface;
    C) the example assumes there is a jqwidgets folder inside the same folder where the following files are located

    The example consists of the following 4 files:

    1) index.htm

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1 maximum-scale=1 minimum-scale=1" />
    	
        <title id="Dashboard">TEST</title>
        <meta name="viewport" content="width=device-width, initial-scale=1 maximum-scale=1 minimum-scale=1" />
        <link rel="stylesheet" href="jqwidgets/styles/jqx.base.css" type="text/css" />
        <link rel="stylesheet" href="jqwidgets/styles/jqx.metro.css" type="text/css" />
    
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        
        <script type="text/javascript" src="jqwidgets/jqxcore.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxdata.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxdraw.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxbargauge.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxchart.core.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxscrollbar.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxlistbox.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxdropdownlist.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxlayout.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxribbon.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxdatatable.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxmenu.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxtabs.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxbuttons.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxresponse.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxsplitter.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxpanel.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxprogressbar.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.selection.js"></script> 
        <script type="text/javascript" src="jqwidgets/jqxgrid.grouping.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.filter.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.sort.js"></script> 
        <script type="text/javascript" src="jqwidgets/jqxgrid.pager.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.columnsresize.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxgrid.edit.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxexpander.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxsortable.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxcheckbox.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxlayout.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxwindow.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxinput.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxnotification.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxloader.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxtextarea.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxtooltip.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxtree.js"></script>
        <script type="text/javascript" src="jqwidgets/jqxexpander.js"></script>
    
        <link href="base.css" rel="stylesheet" />
    </head>
    <body>
    
        <div style="visibility:hidden;" id="mainSplitter">
    
            <div class="splitter-panel" id="leftPanel">
                <header class="clearfix">
                    <div class="container">
                        <div class="header-left">
                            <div id="logo" class="suite">
                                <div id="logoName">test</div>
                                <div id="logoVersion">v1.0.0</div>
                            </div>
                        </div>
                        <div class="freeSpace"></div>
                        <div id="listContainer"> 
                            <label for="open">
                                <span class="hidden-desktop"></span>
                            </label>
                            <input type="checkbox" name="" id="open">   
                            <nav>
                                <a href="#" id="1"><p>&emsp;&emsp;Database</p></a>
                            </nav>
                        </div>
                    </div>
                </header>
            </div>
    
            <div class="splitter-panel" id="rightPanel" >
                <!--Database-->
                <div id="database" class="container-fluid">
                    
                    <div id="databaseGridTitle" class="widget-title">Database List</div>
    
                    <div id="databaseButtons">
                        <button id="refreshDatabase">Refresh</button>
                    </div>
    
                    <div id="databaseGrid"></div>
                </div>
            </div>   
        
        </div>
    
        <script type="text/javascript" src="main.js"></script>
        <script type="text/javascript" src="database.js"></script>
    
    </body>
    </html>

    2) main.js

    'use strict';
    
    $(document).ready(function () {
        $('#mainSplitter').jqxSplitter({
            width: '100%',
            height: '100%',
            orientation: 'vertical',
            resizable: false,
            showSplitBar: false,
            panels: [
               { size: 235},
               { size: '87%'}
            ]
        });
        $('#mainSplitter').css('visibility', 'visible');
    
        $('nav a').on('click', function (event) {
            $('nav a').removeClass('active');
            $('#' + event.currentTarget.id).addClass('active');
    	
            $('#database').css('display', 'none');
    
            if (event.currentTarget.id === '1'){
                initDatabaseSection();
                $('#database').css('display', 'block');
            } 
        });
    });

    3) database.js

    'use strict';
    
    // TODO: set the endpoint!
    var ENDPOINT = '****';
    
    var databaseSectionAlreadyInit = false;
    var sourceDatabases = null;
    var rowsDatabaseSelected = new Set();
    
    function initDatabaseSection() {
    	if (!databaseSectionAlreadyInit) {
    		initRefreshDatabase();
    		initDatabaseGrid();
            databaseSectionAlreadyInit = true;
    	}
    	updateDatabaseGrid();
    }
    
    //#region REFRESH BUTTON
    function initRefreshDatabase() {
    	$("#refreshDatabase").jqxButton({ 
    		width: '80', 
    		height: '27',
    		theme: 'metro',
    		disabled: true
    	});
        $("#refreshDatabase").on('click', function (event) {
    		updateDatabaseGrid();
    	});
    }
    //#endregion
    
    //#region DATABASE GRID
    function initDatabaseGrid() {
    	sourceDatabases = {
    		datatype: "array",
    		datafields: [
    			{ name: 'DatabaseSN', map: 'DatabaseUID>DatabaseSN', type: 'string' },
    			{ name: 'DatabaseName', type: 'string' },
    			{ name: 'Description', type: 'string' },
    			{ name: 'CreationTime', type: 'date' },
    			{ name: 'LastItemUpdate', type: 'date' },
    			{ name: 'ModelVersionSN', map: 'ModelUID>ModelVersionSN', type: 'string' },
    			{ name: 'Loaded', type: 'bool' },
    			{ name: 'NoMarkets', map: 'Stats>NoMarkets', type: 'string' },
    			{ name: 'NoCategories', map: 'Stats>NoCategories', type: 'string' },
    			{ name: 'MissingItems', map: 'Stats>MissingItems', type: 'string' }
    		],
    		id: 'DatabaseUID>DatabaseSN',
    		localdata: []
    	};
    	var dataAdapter = new $.jqx.dataAdapter(sourceDatabases);
    
    	// initialize jqxGrid
        $("#databaseGrid").jqxGrid({
    		width: '100%',
    		theme: 'metro',
    		source: dataAdapter,                
    		pageable: true,
    		autoheight: true,
    		sortable: true,
    		altrows: true,
    		enabletooltips: true,
    		editable: true,
    		rowdetails: true, 
    		filterable: true,
    		selectionmode: 'multiplerows',
    		columns: [
    			{ text: 'ID', datafield: 'DatabaseSN', editable: false, width: '24%'}, 
    			{ text: 'Name', datafield: 'DatabaseName', editable: false, width: '8%'},
    			{ text: 'Description', datafield: 'Description', editable: false, width: '14%'}, 
    			{ text: 'Creation time', datafield: 'CreationTime', cellsformat: 'dd/MM/yyyy HH:mm:ss', editable: false, width: '12%'},
    			{ text: 'Last item update', datafield: 'LastItemUpdate', cellsformat: 'dd/MM/yyyy HH:mm:ss', editable: false, width: '12%'},
    			{ text: 'Suite model', datafield: 'ModelVersionSN', editable: false, width: '24%'},
    			{ text: 'Loaded', columntype: 'checkbox', datafield: 'Loaded', filterable: false, sortable: false, width: '6%'}
    		]
    	});
    	$('#databaseGrid').on('rowselect', function (event) {
    		var row = $('#databaseGrid').jqxGrid('getrowdatabyid', event.args.rowindex);
    		rowsDatabaseSelected.add(row.HVerifyDatabaseSN);
    	});
    	$('#databaseGrid').on('rowunselect', function (event) {
    		var row = $('#databaseGrid').jqxGrid('getrowdatabyid', event.args.rowindex);
    		rowsDatabaseSelected.delete(row.HVerifyDatabaseSN);
    	});
    }
    
    function updateDatabaseGrid() {
    	$('#refreshDatabase').jqxButton({disabled: true });
    	$('#databaseGrid').jqxGrid('showloadelement');
    
    	function successfulDatabaseRequest(databases) {
    		var newRowsIDList = [];
    		for (var i = 0; i < databases.length; i++) {
    			var dbID = databases[i].DatabaseUID.HVerifyDatabaseSN;
    			newRowsIDList.push(dbID);
    			databases[i]['Loaded'] = false;
    		}
    
    		var items = $("#databaseGrid").jqxGrid('getrows');
    		var itemsIDList = items.map(({HVerifyDatabaseSN})=>HVerifyDatabaseSN);
    
    		if (!arraysEqual(itemsIDList, newRowsIDList)) {
    			// to update
    			sourceDatabases.localdata = databases;
    			$("#databaseGrid").jqxGrid('updatebounddata');
    			var rows = $("#databaseGrid").jqxGrid('getrows');
    			for (var i = 0; i < rows.length; i++) {
    				var row = rows[i];
    				if (rowsDatabaseSelected.has(row.HVerifyDatabaseSN)) {
    					$('#databaseGrid').jqxGrid('selectrow', row.boundindex);
    				}
    			}
    		} 
    
    		$('#refreshDatabase').jqxButton({disabled: false });
    		$('#databaseGrid').jqxGrid('hideloadelement');
    	}
    
    	function failedlDatabaseRequest(err) {
    		$('#refreshDatabase').jqxButton({disabled: false });
    		$('#databaseGrid').jqxGrid('hideloadelement');
    	}
    
    	restRequest('GET', {}, successfulDatabaseRequest, ENDPOINT, failedlDatabaseRequest);
    }
    //#endregion
    
    //#region UTILS
    function restRequest(type, body, callbackSuccess, endpoint, callbackError) {
        $.ajax({
            url: endpoint,
            type: type,
            contentType: 'application/json',
            data: JSON.stringify(body),
            success: function(data, status, options) {
                callbackSuccess(data);
            },
            error: function (xhr, ajaxOptions, thrownError) {
                callbackError(thrownError);
            }
        });
    }
    
    function arraysEqual(_arr1, _arr2) {
        if (
          !Array.isArray(_arr1)
          || !Array.isArray(_arr2)
          || _arr1.length !== _arr2.length
        ) {
            return false;
        }
        
        const arr1 = _arr1.concat().sort();
        const arr2 = _arr2.concat().sort();
        
        for (let i = 0; i < arr1.length; i++) {
            if (arr1[i] !== arr2[i]) {
                return false;
            }
        }
        
        return true;
    }
    //#endregion

    4) base.css

    html, body
    {
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        margin: 0;
        background-color:#E8E8EC;
        font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
    }
    
    #mainSplitter {
        border:none;
    } 
    
    * {
      margin: 0;
      padding: 0;
      outline: none;
      border: none;
      -webkit-box-sizing: border-box;
    }
    
    *:before,
    *:after {
      -webkit-box-sizing: border-box;
    }
    
    .clearfix {
      *zoom: 1;
    }
    
    .clearfix:before,
    .clearfix:after {
      display: table;
      line-height: 0;
      content: "";
    }
    
    .clearfix:after {
      clear: both;
    }
    
    .container {
      width:100%;
      padding:0;
      margin: 0 auto;
    }
    
    header {
      width: 100%;
      height: auto;
      background: #333;
    }
    
    .header-left {
      position: relative;
      color: white;
    }
    
    .header-right label{
    	position: absolute;
    	top: -5em;
    	right: 4em;
    	cursor: pointer;
    }
    
    .header-right label span:before,
    .header-right label span:after{
    	content: '';
    	position: absolute;
    	width: 2em;
    	height: .5em;
    	top: 4px;
    	left: 0;
    	background: #888D94;
    }
    .header-right label span:after{
    	top: 13px;
    }
    
    #open{
    	display: none;
    }
    
    .hidden-desktop{
    	display: none;
    }
    
    a {
      text-decoration: none !important;
      color: #888D94;
    }
    
    nav a {
      position: relative;
      display: flex;
      align-items: center;
      line-height: 35px;
      width:100%;
      -webkit-transition: all .3s ease;
      padding-bottom:0.3em;
      padding-top:0.3em;
      color: #888D94;
      border-left: 3px solid #333;
    }
    
    nav a p{
        margin-bottom:0;
        margin-top:0;
        font-size:115%;
        font-weight:700;   
        font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    
    nav a span{
        width:20px;
        height:20px;
        margin-bottom:0;
        margin-top:0;
        font-size:140%;
        margin-left:1.8em;
        margin-right:0.9em;
    }
    
    nav a:hover {
        background-color:#333;  
        color:#d9d9d9;
    }
    
    nav a:focus {
      outline: none;
      color: #888D94;
    }
    
    nav {
        background-color:#333;
        text-align:center;
        margin-top: 1em;
    }
    
    .header-right {
        position: relative;
        color: white;
        float: left;
        width: 70%;
    }
    
    #logo {
      text-align: center;
      cursor:pointer;
    }
    
    .suite {
        background-color:#1790d6;
    }
    
    #logo p{
       width:100%;
       height:100%;
       margin:0;
       padding:1em;
       color:white;
       font-weight:bold;
       font-size:200%;
       font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    
    #logo span {
        margin-right:0.4em;
    }
    
    #logoName {
       width:100%;
       height:100%;
       margin:0;
       padding-top:1em;
       color:white;
       font-weight:bold;
       font-size:210%;
       font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    
    #logoVersion {
        width:100%;
        height:100%;
        margin:0;
        padding-top:-1em;
        padding-bottom:2em;
        padding-left:7em;
        color:white;
        font-size:80%;
        font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    
    #leftPanel {
        height:100%;
        padding-left:0;
        padding-right:0;
        background-color:#333;
    }
    
    .active {
        color:white !important;
        background-color:rgb(70, 70, 70);
        border-left: 3px solid white !important;
    }
    
    .freeSpace {
        background-color:#E8E8EC;
        height:160px;
        width:217px;
        position:absolute;
        top:113px;
        z-index:11;
        display:none;
    }
    
    .collapsedListContainer {
        float:none!important;
        top:113px;
    }
    
    #rightPanel {
        background-color:#E8E8EC;
        min-width:646px;
        overflow: hidden;
        position: relative;
        z-index: 0;
    }
    
    .clearfix:after { 
        content: "."; 
        display: block; 
        height: 0; 
        clear: both; 
        visibility: hidden; 
      }
      .clearfix { 
        display: inline-block;  
      }
      * html .clearfix {  
        height: 1%;  
      } /* Hides from IE-mac \*/
      .clearfix {  
        display: block;  
      }
    
      .dataTables_scrollBody
      {
       overflow-x:hidden !important;
       overflow-y:hidden !important;
      }
    
    .widget-title {
        width:100%;
        color:#333;
        font-weight:bold;
        font-size:160%;
        font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
        text-align: center;
    }
    
    /* database section */
    
    #database {
      padding: 26px 26px;
      padding-top: 2.8em;
      height:100%;
      display:none;
    }
    
    #databaseGridTitle {
      margin-top:1em;
    }
    
    #databaseButtons {
      display: flex;
      justify-content: left;
      align-items: center;
      border: none;
      margin-bottom:0.4em;
    }

    EmilioP
    Participant

    Hello Hristo Hristov,
    I also thought it was due to this, but I did some tests and it doesn’t seem like that.

    First I tried to check, before each update call, if the previous grid binding was complete, using the $("#databaseGrid").jqxGrid('isBindingCompleted') method. However, isBindingCompleted always returns true (and thus the previous binding is completed) even when the error occurs.

    Then I tried to call (the first time) the update method using the bindingcomplete event, as follows:

    var sourceDatabases = null;
    var isFirstBinding = true;
    
    function initDatabaseGrid() {
    	sourceDatabases = {
    		datatype: "array",
    		datafields: [
    			{ name: 'DatabaseSN', map: 'DatabaseUID>DatabaseSN', type: 'string' },
    			{ name: 'DatabaseName', type: 'string' },
    			{ name: 'Description', type: 'string' },
    			{ name: 'CreationTime', type: 'date' },
    			{ name: 'LastItemUpdate', type: 'date' },
    			{ name: 'ModelVersionSN', map: 'ModelUID>ModelVersionSN', type: 'string' },
    			{ name: 'Loaded', type: 'bool' },
    			{ name: 'NoMarkets', map: 'Stats>NoMarkets', type: 'string' },
    			{ name: 'NoCategories', map: 'Stats>NoCategories', type: 'string' },
    			{ name: 'MissingItems', map: 'Stats>MissingItems', type: 'string' }
    		],
    		id: 'DatabaseUID>DatabaseSN',
    		localdata: []
    	};
    	var dataAdapter = new $.jqx.dataAdapter(sourceDatabases);
    	
    	$("#databaseGrid").on("bindingcomplete", function (event) {
    		if (isFirstBinding) {
    			isFirstBinding = false;
    			updateDatabaseGrid(newDatabases);
    		}
    	});
    	$("#databaseGrid").jqxGrid({
    		width: '100%',
    		theme: 'metro',
    		source: dataAdapter,                
    		pageable: true,
    		autoheight: true,
    		sortable: true,
    		altrows: true,
    		enabletooltips: true,
    		editable: true,
    		rowdetails: true, 
    		filterable: true,
    		selectionmode: 'multiplerows',
    		columns: [
    			{ text: 'ID', datafield: 'DatabaseSN', editable: false, width: '24%'}, 
    			{ text: 'Name', datafield: 'DatabaseName', editable: false, width: '8%'},
    			{ text: 'Description', datafield: 'Description', editable: false, width: '14%'}, 
    			{ text: 'Creation time', datafield: 'CreationTime', cellsformat: 'dd/MM/yyyy HH:mm:ss', editable: false, width: '12%'},
    			{ text: 'Last item update', datafield: 'LastItemUpdate', cellsformat: 'dd/MM/yyyy HH:mm:ss', editable: false, width: '12%'},
    			{ text: 'Suite model', datafield: 'ModelVersionSN', editable: false, width: '24%'},
    			{ text: 'Loaded', columntype: 'checkbox', datafield: 'Loaded', filterable: false, sortable: false, width: '6%'}
    		]
    	});
    }
    
    function updateDatabaseGrid(newDatabases) {
    	sourceDatabases.localdata = newDatabases;
    	$("#databaseGrid").jqxGrid('updatebounddata');
    }

    Note: the update function in the code above is simplified, actually inside it I have an ajax call to retrieve the new databases to insert into the grid, which if successful executes updatebounddata(point where the error is generated)

    Furthermore, I discovered that, even waiting a few seconds between the initialization of the grid and its first update, the error can still occur, but more rarely (while in a comment above I said that it never occurred waiting few seconds)


    EmilioP
    Participant

    Hi Hristo Hristov, thanks for the reply.
    I’m sure I call the initialization function only once.

    I noticed that, if I let few seconds pass between the initialization and the first update, the error no longer occurs.
    However, it seems strange to me that the error is due to this.
    Any thoughts on this?

Viewing 5 posts - 1 through 5 (of 5 total)