jQWidgets Forums

jQuery UI Widgets Forums Grid getrowdata sometime returns undefined

This topic contains 1 reply, has 2 voices, and was last updated by  Hristo 8 years, 7 months ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
  • getrowdata sometime returns undefined #87944

    phaefele
    Participant

    Hi,

    I have an issue in my method get_selected_algo_ids() – it looks up the selected rows and then tries to get the row data using getrowdata. The grid is a multiplerowsadvanced grid. The problem is that about 25% of the time, I get undefined when I call getrowdata. This especially happens if I select two non-contiguous rows, and right-click to bring up my context menu when get_selected_algo_ids() / getrowdata is called.

    Also of note is that I call updatebounddata every few seconds via a separate timer.

    Any ideas on what is wrong.

    Many thanks,
    Paul

    Here is my code:

    `<!DOCTYPE html>
    <html>
    <head>

    <title>Backtest Results: Paul Development</title>
    <meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
    <!– Bootstrap –>
    <link href=”//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css” rel=”stylesheet”>
    <link rel=”stylesheet” href=”/static/jqwidgets/styles/jqx.base.css” type=”text/css” />
    <link href=”/static/jqwidgets/styles/jqx.bootstrap.css” rel=”stylesheet”>
    <link rel=”stylesheet” href=”/static/jqwidgets/styles/irwin.css” type=”text/css” />
    <link rel=”stylesheet” href=”/static/css/irwin.css” type=”text/css” />

    </head>
    <body>

    <script src=”//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js”></script>
    <script src=”//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxcore.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdata.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxbuttons.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxscrollbar.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxmenu.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxlistbox.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdropdownlist.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.selection.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.columnsresize.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.filter.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.sort.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.pager.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.grouping.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxwindow.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxinput.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.storage.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdata.export.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.export.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.aggregates.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxgrid.edit.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxsplitter.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdraw.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxchart.core.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxtabs.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxcheckbox.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxtree.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdatetimeinput.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxcalendar.js”></script>
    <script type=”text/javascript” src=”/static/scripts/utils.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxdraw.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxchart.rangeselector.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxnumberinput.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxslider.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxprogressbar.js”></script>
    <script type=”text/javascript” src=”/static/jqwidgets/jqxtabs.js”></script>
    <script>
    $(document).ready(function () {
    // Set the browser ID into the title
    var browser_id = getCookie(‘browser_id’);
    if (browser_id && browser_id.length > 0) {
    $(‘#browser_id_field’).text(” (“+browser_id+”)”);
    }
    });
    </script>
    <script>
    (function(i,s,o,g,r,a,m){i[‘GoogleAnalyticsObject’]=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,’script’,’//www.google-analytics.com/analytics.js’,’ga’);

    ga(‘create’, ‘UA-BLANKEDOUT-1’, ‘auto’);
    ga(‘send’, ‘pageview’);
    </script>

    <script type=”text/javascript”>

    $(document).ready(function () {

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Grid Context Menu incl dynamic External Analysis
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    var context_menu_X = -1;
    var context_menu_Y = -1;
    var context_menu_data = -1;

    // Icons from: http://www.flaticon.com/packs/font-awesome
    var BASE_MENU_DATA = [ {“id”: “1”, “parentid”: “-1”, “label”: “Create Comparison Notebook”},
    {“id”: “2”, “parentid”: “-1”, “label”: “Create Comparison Spreadsheet”},
    {“id”: “3”, “parentid”: “-1”, “label”: “Create Backtest Detail Report”},
    {“id”: “4”, “parentid”: “-1”, “label”: “Show Return Graph”},
    {“id”: “5”, “parentid”: “-1”, “label”: “Show Return Graph Incl Benchmark”},
    {“id”: “6”, “parentid”: “-1”, “label”: “Show MTM Graph”},
    {“id”: “7”, “parentid”: “-1”, “label”: “Show MTM Graph Less Benchmark”},
    {“id”: “8”, “parentid”: “-1”, “label”: “Show Backtest Performance”},
    {“id”: “prev_analysis_submenu”, “parentid”: “-1”, “subMenuWidth”: ‘400px’, “label”: “Previous Analysis”},
    {“id”: “trade_analysis_submenu”, “parentid”: “-1”, “subMenuWidth”: ‘400px’, “label”: “Trade Analysis”}];

    // Returns the select list of algo ids
    function get_selected_algo_ids() {
    var _row_index_list = $(“#runGrid”).jqxGrid(‘getselectedrowindexes’);
    var algo_id_list = [];
    for (i=0; i < _row_index_list.length; i++) {
    var run = $(“#runGrid”).jqxGrid(‘getrowdata’, _row_index_list[i]);
    if (run) {
    algo_id_list.push(run.id);
    }
    }
    return algo_id_list
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Run set data spreadsheet / grid
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    var browser_id = getCookie(‘browser_id’);
    var data_url = ‘/rundata/none’;
    if (browser_id && browser_id.length > 0) {
    data_url = “/rundata/”+ browser_id;
    }

    var source =
    {
    datatype: “json”,
    datafields: [
    { name: ‘id’, type: ‘int’ },
    { name: ‘run_id’, type: ‘int’ },
    { name: ‘run_start’, type: ‘date’ },
    { name: ‘start_date’, type: ‘date’ },
    { name: ‘end_date’, type: ‘date’ },
    { name: ‘run_type’, type: ‘string’ },
    { name: ‘class_name’, type: ‘string’ },
    { name: ‘symbols’, type: ‘string’ },
    { name: ‘config’, type: ‘string’ },
    { name: ‘performance’, type: ‘string’ },
    { name: ‘code_version’, type: ‘string’ },
    { name: ‘code’, type: ‘string’ },
    { name: ‘delete_date’, type: ‘date’, format: ‘yyyy-MM-dd’ },
    { name: ‘comments’, type: ‘string’ },
    { name: ‘google_file_ids’, type: ‘string’ }
    ],
    id: ‘id’,
    url: data_url
    };
    var dataAdapter = new $.jqx.dataAdapter(source);
    $(“#runGrid”).jqxGrid(
    {
    width: ‘100%’,
    height: ‘100%’,
    source: dataAdapter,
    columnsresize: true,
    theme: “irwin”,
    sortable: “true”,
    showstatusbar: true,
    showfilterrow: true,
    filterable: true,
    autoshowloadelement: false,
    enabletooltips: true,
    editable: true,
    columns: [
    { text: ‘AlgoID’, datafield: ‘id’, width: 60, editable: false},
    { text: ‘Run Date’, datafield: ‘run_start’, width: 100, cellsformat: ‘dd-MMM HH:MM’, editable: false },
    { text: ‘Start Date’, datafield: ‘start_date’, width: 100, cellsformat: ‘dd-MMM-yyyy’, editable: false },
    { text: ‘End Date’, datafield: ‘end_date’, width: 100, cellsformat: ‘dd-MMM-yyyy’, editable: false },
    { text: ‘Run Type’, datafield: ‘run_type’, width: 80, editable: false },
    { text: ‘Class Name’, datafield: ‘class_name’, width: 150, editable: false },
    { text: ‘Symbols’, datafield: ‘symbols’, width: 200, editable: false },
    { text: ‘Performance’, datafield: ‘performance’, width: 200, editable: false },
    { text: ‘Config’, datafield: ‘config’, width: 500, editable: false },
    { text: ‘Comments’, datafield: ‘comments’, width: 300, columntype: ‘textbox’, editable: true },
    { text: ‘Delete Date’, datafield: ‘delete_date’, width: 100, cellsformat: ‘dd-MMM-yyyy’, columntype: ‘datetimeinput’, editable: true },
    { text: ‘Git Version’, datafield: ‘code_version’, width: 140, editable: false },
    { text: ‘RunID’, datafield: ‘run_id’, width: 60, editable: false }
    ]
    });

    $(“#runGrid”).jqxGrid({selectionmode: ‘multiplerowsadvanced’});

    // disable the default browser’s context menu.
    $(“#runGrid”).on(‘contextmenu’, function (e) { return false; });

    // Handle context menu clicks
    $(“#context_menu_div”).on(‘itemclick’, function (event) {

    if ($.trim($(args).text()).indexOf(“Create Comparison”) >= 0) {
    $(‘body’).css(‘cursor’, ‘wait’);
    algo_id_list = get_selected_algo_ids()
    // Construct a string of the ids to compare
    $(“#report_algo_id_list”).val(algo_id_list.join(‘,’));
    if ($.trim($(args).text()).indexOf(“Notebook”) >= 0) {
    $(“#report_output_type”).val(‘notebook’);
    } else {
    $(“#report_output_type”).val(‘comparison_report’);
    }
    $(“#algo_report_form”).submit();
    }
    else if ($.trim($(args).text()).indexOf(“Create Backtest Detail Report”) >= 0) {
    $(‘body’).css(‘cursor’, ‘wait’);
    algo_id_list = get_selected_algo_ids()
    // Construct a string of the ids to compare
    $(“#report_algo_id_list”).val(algo_id_list.join(‘,’));
    $(“#report_output_type”).val(‘run_report’);
    $(“#algo_report_form”).submit();
    }
    else if ($.trim($(args).text()).indexOf(“Show Backtest Performance”) >= 0) {
    algo_id_list = get_selected_algo_ids();
    link = ‘/generic_algo_result/backtest_performance_result/’ + algo_id_list.join(‘+’);
    window.open(link);
    }
    else if ($.trim($(args).text()).indexOf(“Graph”) >= 0) {
    // Create a link the a comparison chart
    algo_id_list = get_selected_algo_ids();
    var link = ‘/backtest_chart/return/’;
    if ($.trim($(args).text()).indexOf(“Less”) >= 0) {
    link = ‘/backtest_chart/diff/’;
    }
    else if ($.trim($(args).text()).indexOf(“MTM”) >= 0) {
    var link = ‘/backtest_chart/mtm/’;
    }
    if ($.trim($(args).text()).indexOf(“Benchmark”) >= 0) {
    link = link + ‘B+’;
    }
    link = link + algo_id_list.join(‘+’);

    window.open(link);
    }
    else if ($.trim($(args).text()) == “Keep Run Forever”) {
    // This is one of the comparison objects
    algo_id_list = get_selected_algo_ids()
    $.post(‘/keep_runs_forever’, {data: JSON.stringify(algo_id_list.join(‘,’))});
    // Refresh the grid so we can see the far ahead delete date
    $(“#runGrid”).jqxGrid(‘updatebounddata’, ‘cells’);
    }
    else if ($.trim($(args).text()) == “Schedule Deletion”) {
    // This is one of the comparison objects
    algo_id_list = get_selected_algo_ids()
    $.post(‘/schedule_deletion’, {data: JSON.stringify(algo_id_list.join(‘,’))});
    // Refresh the grid so we can see the new delete date
    $(“#runGrid”).jqxGrid(‘updatebounddata’, ‘cells’);
    } else {
    // This is one of the comparison objects
    var id = event.args.id;
    for (var i=0; i < context_menu_data.length; i++) {
    if (id == context_menu_data[i].id) {
    var link = context_menu_data[i].link;
    window.open(link);
    break;
    }
    }
    }
    });

    var stop_update_on_edit = 0;

    $(“#runGrid”).bind(‘cellbeginedit’, function (event) {
    stop_update_on_edit = 1;
    });

    $(“#runGrid”).on(‘cellendedit’, function (event) {
    var args = event.args;
    var algo_id = args.row[‘id’];
    var field = args.datafield;
    var new_value = args.value;
    if (field == ‘delete_date’) {
    new_value = new_value.toISOString().slice(0,10).replace(/-/g,””); // Turn into YYYYMMDD
    }

    $.post(‘/update_algo_data’, {data: JSON.stringify(algo_id.toString() + ‘,’ + field + ‘,’ + new_value.toString())});

    stop_update_on_edit = 0;
    })

    // Build the context menu based on the right-click
    $(“#runGrid”).on(‘rowclick’, function (event) {
    if (event.args.rightclick) {
    $(“#runGrid”).jqxGrid(‘selectrow’, event.args.rowindex);

    // Store where we want the context menu to come up
    var scrollTop = $(window).scrollTop();
    var scrollLeft = $(window).scrollLeft();
    context_menu_X = parseInt(event.args.originalEvent.clientX) + 5 + scrollLeft;
    context_menu_Y = parseInt(event.args.originalEvent.clientY) + 5 + scrollTop;

    var algo_id_list = get_selected_algo_ids();
    if (algo_id_list != ”) {
    $.post(‘/dynamic_context_menu’, {data: JSON.stringify(algo_id_list)},
    function(data, status) {

    var ea_list = [];
    if (status == ‘success’) {
    ea_list = JSON.parse(data);
    }

    context_menu_data = BASE_MENU_DATA.slice(); // copy the list
    var start_index = context_menu_data.length + 1;
    var max_len = -1;
    for (var i = 0; i < ea_list.length; i++) {
    var icon = ”;
    if (ea_list[i][2] == ‘gspread’ || ea_list[i][2] == ‘gdata’) {
    icon = ‘spreadsheet_16.png’;
    } else if (ea_list[i][2] == ‘notebook’) {
    icon = ‘ipython_notebook_16.png’;
    } else {
    icon = ‘bar_chart_16.png’;
    }
    var label = “” + ea_list[i][1];
    var menu_len = ea_list[i][1].length;
    if (menu_len > max_len) {
    max_len = menu_len;
    }

    var parentid = ”;
    if (ea_list[i][0] == ‘ExternalAnalysis’) {
    parentid = ‘prev_analysis_submenu’;
    } else if (ea_list[i][0] == ‘TradeAnalysis’) {
    parentid = ‘trade_analysis_submenu’;
    }
    context_menu_data.push({“id”: start_index + i, “parentid”: parentid, “label”: label, “link”: ea_list[i][3]});
    }
    // Add remaining menu items
    context_menu_data.push({“id”: ‘menuSeparator’, “parentid”: “-1”, “label”: “”});
    context_menu_data.push({“id”: start_index + ea_list.length, “parentid”: “-1”, “label”: “Keep Run Forever”});
    context_menu_data.push({“id”: start_index + ea_list.length + 1, “parentid”: “-1”, “label”: “Schedule Deletion”});

    // Make the sub menu length correct
    max_len = Math.min(600, max_len);
    context_menu_data[1][“subMenuWidth”] = (max_len * 9 + 20).toString() + “px”;

    var source = { datatype: “json”, datafields: [ { name: ‘id’ }, { name: ‘parentid’ }, { name: ‘label’ }, { name: ‘subMenuWidth’ } ],
    id: ‘id’, localdata: context_menu_data
    };
    // create data adapter and perform Data Binding.
    var dataAdapter = new $.jqx.dataAdapter(source);
    dataAdapter.dataBind();

    // Create the menu
    var records = dataAdapter.getRecordsHierarchy(‘id’, ‘parentid’, ‘items’);
    cm = $(‘#context_menu_div’).jqxMenu({ source: records, height: (BASE_MENU_DATA.length + 3) * 24, width: ‘300px’, autoOpenPopup: false, mode: ‘popup’ });

    // Open the menu now it is created
    cm.jqxMenu(‘open’, context_menu_X, context_menu_Y);

    $(“li[id=’menuSeparator’]”).attr(“class”,”jqx-menu-item-separator jqx-rc-all”); // From http://www.jqwidgets.com/community/topic/separator-inside-source-based-jqmenu/#post-62736

    // Disable the previous run menu item if there are none.
    if (ea_list.length == 0) {
    $(“#context_menu_div”).jqxMenu(‘disable’, “prev_analysis_submenu”, true);
    }
    });
    } else {
    var error=1; // Have this so we can at least not show the menu if we can’t get the IDs
    }
    return false;
    }
    });

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Refresh the grids every 5 seconds
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    setInterval(function () {
    if (stop_update_on_edit == 0) {
    $(“#runGrid”).jqxGrid(‘updatebounddata’, ‘cells’);
    }
    }, 15000);

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Code to show the new Notebook URL as a popup. When we want to show the popup,
    // compare_algos_notebook_url is set and so window.open is in Javascript
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    // If the compare notebook url has been specified (done on algo_report_form POST), open a window for it.
    window.open(“http://localhost:5002/notebooks/Compare%20Runs%20-%205163.ipynb”); // Open the compare algo url if supplied

    });
    </script>

    <div id=”help_modal_popup” class=”modal fade” tabindex=”-1″ role=”dialog”>
    <div class=”modal-dialog” style=”width: 1024px; height: 768px;”>
    <div class=”modal-content”>
    <div class=”modal-body”>

    </div>
    </div>
    </div>
    </div>

    <!– This makes the body take up the whole frame. Not sure why putting this in the style block does not work.
    See http://www.jqwidgets.com/fluid-layout-with-fixed-header-and-footer/ –>
    <style type=”text/css”>
    html, body {
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px;
    overflow: hidden;
    }
    </style>

    <table style=”border-collapse: separate; border-spacing:0; background-repeat: no-repeat;” width=”100%” background=”/static/images/vol_surface_wide.png”>
    <tr width=”100%” >
    <td width=’4%’ align=”left”></td>
    <td width=”6%” align=”left” valign=”middle”><h2 style=”color:black”><b>Irwin</b></h2></td>
    <td width=”60%” align=”left” valign=”left”><span style=”font-size:1.9em; color:DimGray”>Backtest Results: Paul Development</span><span style=”font-size:0.7em” id=’browser_id_field’></span></td>

    <td width=”6px” align=”right”></td>
    <td width=”140px” align=”right”>
    <button type=”button” class=”btn btn-sm btn-block btn-primary” style=”margin-top:1em” onclick=”location.href=’/backtest_algo_list’;”>Algo List</button>
    </td>

    <td width=”6px” align=”right”></td>
    <td width=”80px” align=”right”>
    <button type=”button” class=”btn btn-sm btn-block btn-primary” style=”margin-top:1em” data-toggle=”modal” data-target=”#help_modal_popup”>Help</button>
    </td>
    <td width=”3px” align=”right”></td>
    </tr></table>

    <div id=’jqxWidget’ style=”position: absolute; box-sizing:border-box; -moz-box-sizing:border-box; padding-top: 0px; padding-bottom: 60px; width: 100%; height: 100%;”>
    <div id=”runGrid”></div>
    </div>
    <div id=’context_menu_div’>
    </div>
    <div style=”overflow: hidden;”>
    <form method=”POST” id=”algo_report_form” style=”display: none;”>
    <label for=”report_algo_id_list”>report_algo_id_list</label> <input id=”report_algo_id_list” name=”report_algo_id_list” type=”text” value=””>
    <label for=”report_output_type”>report_output_type</label> <input id=”report_output_type” name=”report_output_type” type=”text” value=””>
    <input id=”algo_report_submit” name=”algo_report_submit” type=”submit” value=”algo_report_submit”>
    </form>
    </div>

    </body>
    </html>

    getrowdata sometime returns undefined #87994

    Hristo
    Participant

    Hello phaefele,

    We could not spend a time to create/check (private) project.
    This is one big data source code and it is difficult to check.
    If we focus on the described issue you could try to use this algo_id_list.push(run.uid); instead of algo_id_list.push(run.id);
    Hope this helps.

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com

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

You must be logged in to reply to this topic.