0

I'm looking for a way to add hot keys for top level toolbar buttons:

  • Add
  • Edit
  • View

I tried code below which worked in earlier versions.

In free jqgrid every F4 click adds new icon on submit and cancel button. After that pressing Cancel button causes javascript exception:

    Uncaught TypeError: Cannot read property 'a' of undefined Line 15011 Column 19
TypeError: Cannot read property 'a' of undefined    at Object.$.jqm.close (http://localhost:52216/admin/Scripts/jqgrid-4.8.0/js/jquery.jqgrid.src.js:15011:19)   
 at HTMLDivElement.<anonymous> (http://localhost:52216/admin/Scripts/jqgrid-4.8.0/js/jquery.jqgrid.src.js:14936:78)   
 at Function.jQuery.extend.each (http://localhost:52216/admin/Scripts/jquery-1.11.2.js:384:23)    at jQuery.fn.jQuery.each (http://localhost:52216/admin/Scripts/jquery-1.11.2.js:136:17)    at $.fn.jqmHide (http://localhost:52216/admin/Scripts/jqgrid-4.8.0/js/jquery.jqgrid.src.js:14936:53) 
   at $.extend.hideModal (http://localhost:52216/admin/Scripts/jqgrid-4.8.0/js/jquery.jqgrid.src.js:6263:43)  
  at Object.$.extend.complete (http://localhost:52216/admin/Scripts/jqgrid-4.8.0/js/jquery.jqgrid.src.js:9703:32)  
  at fire (http://localhost:52216/admin/Scripts/jquery-1.11.2.js:3143:30) 
   at Object.self.fireWith (http://localhost:52216/admin/Scripts/jquery-1.11.2.js:3255:7)
    at done (http://localhost:52216/admin/Scripts/jquery-1.11.2.js:9324:21)

Add and view hotkeys have same issue if they are implemented. Search button does not disable grid. Only search button hotkey implemented is this way works in free jqgrid also.

How to fix this ? It looks like hotkeys needs to be disabled if edit or view window is active.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>http://stackoverflow.com/q/26040738/315935</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="author" content="Oleg Kiriljuk"/>
    <link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css"/>
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
    <!--<link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/css/ui.jqgrid.css"/>-->
    <link rel="stylesheet" type="text/css" href="http://rawgit.com/free-jqgrid/jqGrid/master/css/ui.jqgrid.css"/>
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"/>
    <style type="text/css">
        html, body { font-size: 75%; }
        .ui-jqgrid td input[type=date], input[type=time], input[type=datetime-local], input[type=month] {
            line-height: normal;
        }
    </style>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    <!--<script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/i18n/grid.locale-en.js"></script>-->
    <script type="text/javascript" src="http://rawgit.com/free-jqgrid/jqGrid/master/js/i18n/grid.locale-en.js"></script>
    <script type="text/javascript">
        $.jgrid = $.jgrid || {};
        $.jgrid.no_legacy_api = true;
        $.jgrid.useJSON = true;
    </script>
    <!--<script src="../jqGrid/js/jquery.jqGrid.src.js"></script>-->
    <!--<script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/jquery.jqgrid.src.js"></script>-->
    <script type="text/javascript" src="http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js"></script>
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
    <script type="text/javascript">
    //<![CDATA[
        /*global $,Modernizr */
        /*jslint browser: true, unparam: true */
        $(function () {
            "use strict";
            var mydata = [
                    { id: "10",  invdate: "2007-10-01", name: "test1",  note: "note1",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "20",  invdate: "2007-10-02", name: "test2",  note: "note2",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" },
                    { id: "30",  invdate: "2007-09-01", name: "test3",  note: "note3",  amount: "400.00", tax: "30.00", closed: false, ship_via: "FE", total: "430.00" },
                    { id: "40",  invdate: "2007-10-04", name: "test4",  note: "note4",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "50",  invdate: "2007-10-31", name: "test5",  note: "note5",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" },
                    { id: "60",  invdate: "2007-09-06", name: "test6",  note: "note6",  amount: "400.00", tax: "30.00", closed: false, ship_via: "FE", total: "430.00" },
                    { id: "70",  invdate: "2007-10-04", name: "test7",  note: "note7",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "80",  invdate: "2007-10-03", name: "test8",  note: "note8",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" },
                    { id: "90",  invdate: "2007-09-01", name: "test9",  note: "note9",  amount: "400.00", tax: "30.00", closed: false, ship_via: "TN", total: "430.00" },
                    { id: "100", invdate: "2007-09-08", name: "test10", note: "note10", amount: "500.00", tax: "30.00", closed: true,  ship_via: "TN", total: "530.00" },
                    { id: "110", invdate: "2007-09-08", name: "test11", note: "note11", amount: "500.00", tax: "30.00", closed: false, ship_via: "FE", total: "530.00" },
                    { id: "120", invdate: "2007-09-10", name: "test12", note: "note12", amount: "500.00", tax: "30.00", closed: false, ship_via: "FE", total: "530.00" }
                ],
                $grid = $("#list"),
                initDateEdit = function (elem, options) {
                    // we need get the value before changing the type
                    var orgValue = $(elem).val(), newformat,
                        cm = $(this).jqGrid("getColProp", options.name);

                    $(elem).attr("type", "date");
                    if ((typeof Modernizr !== "undefined" && !Modernizr.inputtypes.date) || $(elem).prop("type") !== "date") {
                        $(elem).attr("type", "text"); // !!! important to make saving works correctly
                        $(elem).css({ width: "8em" }).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showButtonPanel: true,
                            showWeek: true
                        });
                    } else {
                        // convert date to ISO
                        if (orgValue !== "") {
                            newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                                cm.formatoptions.newformat :
                                $(this).jqGrid("getGridRes", "formatter.date.newformat");
                            $(elem).val($.jgrid.parseDate.call(this, newformat, orgValue, "Y-m-d"));
                        }
                        $(elem).css({width: "11em"});
                    }
                },
                initDateSearch = function (elem) {
                    setTimeout(function () {
                        $(elem).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showWeek: true,
                            showButtonPanel: true
                        });
                    }, 50);
                },
                numberTemplate = {formatter: "number", align: "right", sorttype: "number",
                    editrules: {number: true, required: true},
                    searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge", "nu", "nn", "in", "ni"] }};

            $grid.jqGrid({
                datatype: "local",
                data: mydata,
                colNames: ["Client", "Date", "Closed", "Shipped via", "Notes", "Tax", "Amount", "Total"],
                colModel: [
                    { name: "name", align: "center", editable: true, width: 65, editrules: {required: true} },
                    { name: "invdate", width: 125, align: "center", sorttype: "date",
                        formatter: "date", /*formatoptions: { newformat: "m/d/Y"},*/ editable: true,
                        editoptions: { dataInit: initDateEdit },
                        searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge"], dataInit: initDateSearch } },
                    { name: "closed", width: 70, align: "center", editable: true, formatter: "checkbox",
                        edittype: "checkbox", editoptions: {value: "Yes:No", defaultValue: "Yes"},
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;true:Yes;false:No" } },
                    { name: "ship_via", width: 105, align: "center", editable: true, formatter: "select",
                        edittype: "select", editoptions: { value: "FE:FedEx;TN:TNT;IN:Intim", defaultValue: "IN" },
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;FE:FedEx;TN:TNT;IN:IN" } },
                    { name: "note", width: 60, sortable: false, editable: true, edittype: "textarea" },
                    { name: "tax", width: 52, editable: true, template: numberTemplate },
                    { name: "amount", width: 75, editable: true, template: numberTemplate },
                    { name: "total", width: 60, template: numberTemplate }
                ],
                rowNum: 10,
                rowList: [5, 10, 20],
            toppager: true,

                iconSet: "fontAwesome",
                pager: "#pager",
                gridview: true,
                autoencode: true,
                ignoreCase: true,
                sortname: "invdate",
                viewrecords: true,
                sortorder: "desc",
                height: "auto",
                rownumbers: true,
                editurl: "clientArray",
                onSelectRow: function (rowid) {
                    var $self = $(this),
                        savedRow = $self.jqGrid("getGridParam", "savedRow");
                    if (savedRow.length > 0) {
                        $self.jqGrid("restoreRow", savedRow[0].id);
                    }
                    $self.jqGrid("editRow", rowid);
                },
                inlineEditing: {
                    keys: true
                },
                formEditing: {
                    viewPagerButtons: false
                }
            }).jqGrid("navGrid").jqGrid("inlineNav");


var htmlKeydown = function (evt) {
    if (!evt.ctrlKey && !evt.altKey) {
        switch (evt.keyCode) {
            case 115: $("#edit_list_top").click(); return false;
           }
}
};


$("html").keydown(function (evt) {
    return htmlKeydown(evt);
});

        });
    //]]>
    </script>
</head>
<body>
<div id="outerDiv" style="margin:5px;">
    <table id="list"><tr><td></td></tr></table>
    <div id="pager"></div>
</div>
</body>
</html>
Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

1

It seems to me that you need just replace the code

switch (evt.keyCode) {
    case 115: $("#edit_list_top").click(); return false;
}

to

var idSelector = $.jgrid.jqID($grid[0].id);
switch (evt.keyCode) {
    case 115:
        if ($("#editmod" + idSelector).length === 0) {
            $("#edit_" + idSelector + "_top").click();
        }
        return false;
}

So I suggest that you test whether the Add/Edit dialog already exist before simulation the click on Edit button of the navigator toolbar.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thank you. It worked. For add button I used `if ($("#editmod" + idSelector).length === 0) { $("#add_" + idSelector + "_top").click(); }` hope this is OK? – Andrus Mar 29 '15 at 18:55
  • @Andrus: Yes of cause. What I mean is: you should simulation the click on an navigator bar only if the corresponding dialog in not already opened. During closing it will be destroyed in free jqGrid, so the test for existence of the dialog is easy. – Oleg Mar 29 '15 at 19:23
  • This is global keydown handler. If jqgrid does not exist in page, it causes javascript exception. How to add check for jqgrid existence in page ? – Andrus Mar 30 '15 at 11:59
  • 1
    @Andrus: The code which you posted have an explicit `id` name of the grid: `list`. I don't understand how exactly you make it **global**. In general you can search for `$("table.ui-jqgrid-btable")` for example to get all existing grids of the page. The `id` attribute of the elements in the jQuery set are the ids of the grid. Moreover it's unclear **where exactly you JavaScript an exception**. Probably you can verify the the button exist (`$("#add_" + idSelector + "_top").length > 0`) before to execute `click()`? – Oleg Mar 30 '15 at 12:11
  • keydown handler is placed to site.cshtml file and is executed also if there is no grid defined in page. Assiging to idSelector causes exception so this check is too late. I changed code to `var idSelector = null; if ( $("table.ui-jqgrid-btable").length>0) { idSelector = $.jgrid.jqID($grid[0].id); } ` and check to `if (idSelector!== null && $("#editmod" + idSelector).length === 0)` . Is this OK ? – Andrus Mar 30 '15 at 13:20
  • @Andrus: Yes, it looks OK for me. You should still the test the solution in your environment. The code uses for example the first grid in `$("#editmod" + idSelector)`. It can be that you use subgrid scenario or to have multiple grids on the page. I would recommend you to make the loop to find the first grid which have Edit navigator button and use the button in the case. You can use `$("table.ui-jqgrid-btable").each` for example and use `return false` inside of `each` to break the enumeration. – Oleg Mar 30 '15 at 13:32