2

Toggle button in jqgrid top toolbar is defined using Oleg answer as

var autoedit;
$("#grid_toppager_left table.navtable tbody tr").append(
    '<td class="ui-pg-button ui-corner-all" >' +
        '<div class="ui-pg-div my-nav-checkbox">' +
        '<input tabindex="-1" type="checkbox" id="AutoEdit" '+(autoedit ? 'checked ' : '')+'/>' +
        '<label title="Toggle autoedit" for="AutoEdit">this text is ignored in toolbar</label></div></td>'
);
$("#AutoEdit").button({
    text: false,
    icons: {primary: "ui-icon-star"}
}).click(function () {
    autoedit = $(this).is(':checked');
});

Answer from how to add standard textbox command to jqgrid context menu is used to autogenerate context menu for grid from toolbar.

In generated context menu for this item only text "this text is ignored in toolbar" appears and selecting it does nothing.

How to make it work or remove this item from context menu?

Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

6

Look at the demo or the same demo with another themes: this and this.

enter image description here

enter image description here

enter image description here

First of all I modified the code of the jquery.contextmenu.js to support jQuery UI Themes. Then I modified the code more, to be able to create context menu more dynamically. In the modified version of jquery.contextmenu.js one can crate menu and the bindings not only in the onContextMenu, but also in onShowMenu. Inside of onContextMenu one can create just the empty menu

<div id="myMenu"><ul></ul></div>

It is important only if one use dynamically switching of the icons of the text of buttons from the navigator bar.

You can download the modified version of the file here.

In the demo I used the last modification of the code from the answer, so the standard context menu can be still used in the grid on selected text or in the enabled input/textarea fields. The context menu of the browser will be displayed in the case:

enter image description here

I modified the code of createContexMenuFromNavigatorButtons function from the answer to the following:

var getSelectedText = function () {
        var text = '';
        if (window.getSelection) {
            text = window.getSelection();
        } else if (document.getSelection) {
            text = document.getSelection();
        } else if (document.selection) {
            text = document.selection.createRange().text;
        }
        return typeof (text) === 'string' ? text : text.toString();
    },
    createContexMenuFromNavigatorButtons = function (grid, pager) {
        var menuId = 'menu_' + grid[0].id, menuUl = $('<ul>'),
            menuDiv = $('<div>').attr('id', menuId);

        menuUl.appendTo(menuDiv);
        menuDiv.appendTo('body');

        grid.contextMenu(menuId, {
            bindings: {}, // the bindings will be created in the onShowMenu
            onContextMenu: function (e) {
                var p = grid[0].p, i, lastSelId, $target = $(e.target),
                    rowId = $target.closest("tr.jqgrow").attr("id"),
                    isInput = $target.is(':text:enabled') ||
                    $target.is('input[type=textarea]:enabled') ||
                    $target.is('textarea:enabled');
                if (rowId && !isInput && getSelectedText() === '') {
                    i = $.inArray(rowId, p.selarrrow);
                    if (p.selrow !== rowId && i < 0) {
                        // prevent the row from be unselected
                        // the implementation is for "multiselect:false" which we use,
                        // but one can easy modify the code for "multiselect:true"
                        grid.jqGrid('setSelection', rowId);
                    } else if (p.multiselect) {
                        // Edit will edit FIRST selected row.
                        // rowId is allready selected, but can be not the last selected.
                        // Se we swap rowId with the first element of the array p.selarrrow
                        lastSelId = p.selarrrow[p.selarrrow.length - 1];
                        if (i !== p.selarrrow.length - 1) {
                            p.selarrrow[p.selarrrow.length - 1] = rowId;
                            p.selarrrow[i] = lastSelId;
                            p.selrow = rowId;
                        }
                    }
                    return true;
                } else {
                    return false; // no contex menu
                }
            },
            onShowMenu: function (e, $menu) {
                var options = this, $menuUl = $menu.find('ul:first').empty();

                $('table.navtable .ui-pg-button', pager).each(function () {
                    var $spanIcon, text, $td, id, $li, $a, button,
                        $div = $(this).children('div.ui-pg-div:first'),
                        gridId = grid[0].id;

                    if ($div.length === 1) {
                        text = $div.text();
                        $td = $div.parent();
                        if (text === '') {
                            text = $td.attr('title');
                        }
                        if (this.id !== '' && text !== '') {
                            id = 'menuitem_' + this.id;
                            if (id.length > gridId.length + 2) {
                                id = id.substr(0, id.length - gridId.length - 1);
                            }
                        } else {
                            // for custom buttons
                            id = $.jgrid.randId();
                        }
                        $li = $('<li>').attr('id', id);
                        $spanIcon = $div.children('span.ui-icon');
                        if ($spanIcon.length > 0) {
                            // standard navGrid button or button added by navButtonAdd
                            $li.append($('<a>')
                                .text(text)
                                .prepend($spanIcon.clone().css({
                                    float: 'left',
                                    marginRight: '0.5em'
                                })));
                            $menuUl.append($li);
                            options.bindings[id] = (function ($button) {
                                return function () { $button.click(); };
                            }($div));
                        } else {
                            button = $div.children("input").data("button");
                            if (button !== undefined) {
                                $a = $('<a>')
                                    .text(button.options.label)
                                    .prepend(
                                        $('<label>').addClass("ui-corner-all").css({
                                            float: 'left',
                                            width: '16px',
                                            borderWidth: '0px',
                                            marginRight: '0.5em'//'4px'
                                        }).append(
                                            $('<span>').addClass("ui-button-icon-primary ui-icon " +
                                                button.options.icons.primary)
                                                .css({
                                                    float: 'left',
                                                    marginRight: '0.5em'
                                                })
                                        )
                                    );
                                $li.append($a);
                                if (button.type === "checkbox" && button.element.is(':checked')) {
                                    $a.find('label:first').addClass("ui-state-active");
                                }
                                $menuUl.append($li);
                                options.bindings[id] = (function ($button, isCheckbox) {
                                    if (isCheckbox) {
                                        return function () {
                                            if ($button.is(':checked')) {
                                                $button.siblings('label').removeClass("ui-state-active");
                                            } else {
                                                $button.siblings('label').addClass("ui-state-active");
                                            }
                                            $button.click();
                                            $button.button("refresh"); // needed for IE7-IE8
                                    };
                                    } else {
                                        return function () { $button.click(); };
                                    }
                                }(button.element, button.type === "checkbox"));
                            }
                        }
                    }
                });
                return $menu;
            }
        });
    },
    autoedit = false;

and fill the check-button in the navigator bar with the code which is changed only a little:

$("#pager_left table.navtable tbody tr").append(
    '<td class="ui-pg-button ui-corner-all">' +
        '<div class="ui-pg-div my-nav-checkbox">' +
        '<input tabindex="-1" type="checkbox" id="AutoEdit" />' +
        '<label title="Checkx caption which should appear as button tooltip"' +
        ' for="AutoEdit">Autoedit</label></div></td>'
);
$("#AutoEdit").button({
    text: false,
    icons: {primary: "ui-icon-mail-closed"}
}).click(function () {
    var iconClass, $this = $(this);
    if (!autoedit) { // $this.is(':checked')) {
        autoedit = true;
        iconClass = "ui-icon-mail-open";
    } else {
        autoedit = false;
        iconClass = "ui-icon-mail-closed";
    }
    $this.button("option", {icons: {primary: iconClass}});
});
createContexMenuFromNavigatorButtons($grid, '#pager');

UPDATED: One more demo which support buttons added by new inlineNav method you can find here. Additionally I included in the demo the function normalizePagers which I use to improve the look of the pager:

enter image description here

How you can see the contextmenu includes only enabled buttons from the navigator bar.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thank you. Great. If context menu if opened at bottom in browser window, it is rendered out of browser. It is not visible and accessible. How to force it to be rendered inside browser so it is visible and accessible. Can jquery postition widget used of other idea ? – Andrus Dec 14 '11 at 17:51
  • 1
    @Andrus: the current implementation of `contexmenu` use `pageX` and `pageY` properties of the event object as the absolute position in the web browser window. the event is accessible in `onShowMenu` callback as the first parameter. If you would change the `e.pageX` and `e.pageY` properties to 0 for example the contexmenu will be shown exactly in the top left corner of the browser window. This way can be used to solve the problem which you described. – Oleg Dec 14 '11 at 23:14
  • Thank you. How to force menu to open near the clicked place so that that most of menu is always visible (and vertical scrollbar appears if there is large number of items) ? – Andrus Dec 15 '11 at 08:56
  • I added separate queston about this – Andrus Dec 15 '11 at 09:04
  • This context menu shows inline navigator buttons as active if they are not active in jqgrid toolbar. How to fix this ? – Andrus Dec 15 '11 at 19:25
  • 1
    @Andrus: I made one more demo. See UPDATED part of my answer. – Oleg Dec 16 '11 at 10:57
  • Thank you. In new demo, If Edit is selected from context menu and after that Save or Cancel is selected from context menu, row remains in edit mode. How to fix this ? – Andrus Dec 16 '11 at 19:11
  • 1
    @Andrus: I can't reproduce the problem which you describe. I know some other problems, but all in `inlineNav` method only. For example you select row and click "edit" button then you select another row and click "Save" or "Cancel" button. The row still in editing. The same problem exist independent how one click the buttons: directly or trigger the button from the context menu. – Oleg Dec 16 '11 at 19:33
  • the issue your described is probably the problem. I posted it as separate question in http://stackoverflow.com/questions/8545042/how-to-synchronize-jqgrid-inline-navigator-and-formatter-actions-buttons-and-end . Btw. Have you looked to http://stackoverflow.com/questions/8495573/how-to-show-html-in-textarea-as-formatted-in-jqgrid-view-window issue? – Andrus Dec 17 '11 at 13:26
  • If toolbar contains large number of buttons and context menu is opened at bottom, it selections are not accessible. How to add vertical toolbar to context menu to make all items accessible or any other solution ? Can context menu rendered upwards like standard browser context menu and if items does not fit style="overflow-y: auto" used? – Andrus Dec 17 '11 at 13:30
  • In free jgrid this code will not generate context menu. Maybe top level toolbar structure change breaks this code. – Andrus Mar 17 '15 at 08:25
  • @Andrus: One should just change the selectors `table.navtable tbody tr` and the icons itself. I use close method in projects which I created for my customers and all works good. – Oleg Mar 17 '15 at 08:29
  • Toolbar has inline-block style layout from answer in http://stackoverflow.com/questions/29041956/how-to-place-pager-to-end-of-top-of-toolbar-in-free-jqgrid is used. Will this work with this layout also ? Is there some sample ? – Andrus Mar 17 '15 at 19:25
  • @Andrus: I looked in my sources and could see that I use small modification of [jquery.contextmenu-ui.js](https://github.com/OlegKi/jqGrid-plugins/blob/master/jquery.contextmenu-ui.js) which **works with jQuery UI till 1.10.X, but it looks not so good for the current jQuery UI 1.11.X**. I though to adjust the `jquery.contextmenu-ui.js` to support jQuery UI 1.11.X, but I have currently no time for it: I use still 1.10.4 in customer projects. If you have an interest I could share my code, but you should open better new question where I'll post the code. – Oleg Mar 17 '15 at 20:45
  • @Andrus: I fixed the code and can share it with other. If you have an interest you need just open new question. I'll post the details of implementation in my answer. – Oleg Mar 22 '15 at 18:12