2
votes

I'm trying to make a special menu pop up in Slick Grid when the user holds down the mouse button for some amount of time. The menu has to relate specifically to that column, so I need to somehow retrieve the information from that column. Since the popup will appear during the time the mouse button is held, I can't use an onclick event.

I do have some code I used to make this work for the main body of the grid:

    // Attach the mousedown and mouseup functions to the entire grid
    $(document).ready(function () {
        $("#myGrid").bind("mousedown", function (e, args) {
            var event = e;
            timer = setTimeout(function () { heldMouse(event, args); }, 500);
        })
        .bind("mouseup", function () {
            clearTimeout(timer);
        });
    });

    function heldMouse(e, args) {
            // if header click - 
            // showHeaderContextMenu(e, args)
            // else
            showContextMenu(e);
            mouseHeldDown = false;
    }

    // Displays context menu
    function showContextMenu(e) {
        var cell = grid.getCellFromEvent(e);
        grid.setActiveCell(cell.row, cell.cell);

        $("#slickGridContextMenu")
                  .css("top", e.pageY - 5)
                  .css("left", e.pageX - 5)
                  .show();
    }

(I know args is going to be empty, it's there more as a placeholder than anything else for now)

This works perfectly fine for holding down on the main body, but if I do this on the header, since I no longer have access to getCellFromEvent and the mouse events I've called can't get args from anywhere, I'm unsure how I can get information about the header and which column I'm in. Is there a bit of functionality in Slickgrid that I've overlooked? I didn't notice a mousedown event I could subscribe to.

I had a thought that I could bind separate events to both the header and the body, but I'm not sure if that would still be able to get me the information I need. Looking at the tags, I see two possibilities: slick-header-column, which has an id (slickgrid_192969DealNbr) but I'm not sure how to reliably remove that number (where does it come from?), or slick-column-name, where I can get the html from that tag, but sometimes those names are altered and I'd rather not deal with that unless I absolutely have to. This is what I'm referring to:

<DIV id=slickgrid_192969OrdStartDate_ATG title="" class="ui-state-default slick-header-column" style="WIDTH: 74px">
<SPAN class=slick-column-name>
<SPAN style="COLOR: green">OrdStartDate</SPAN></SPAN><SPAN class=slick-sort-indicator></SPAN>
<DIV class=slick-resizable-handle></DIV></DIV>

Also, I have this:

        grid.onHeaderContextMenu.subscribe(function (e, args) {
            e.preventDefault();
            // args.column - the column information

            showHeaderContextMenu(e, args);
        });

Is there a way perhaps I could trigger this event from the mouse holding methods and receive args with the column name in it? This was just a thought, I'm not really sure how the triggering works with SlickGrid/JQuery, but figured it might be possible.

Thanks for any suggestions!

2

2 Answers

2
votes

Try something like this instead (demo):

$(function () {
    var timer;
    $("#myGrid")
        .bind("mousedown", function (e, args) {
            var event = e; // save event object
            timer = setTimeout(function(){
                doSomething(event, args);
            }, 1000);
        })
        .bind("mouseup mousemove", function () {
            clearTimeout(timer);
        });
});

function doSomething(e, args){
    alert('YAY!');
};

And in case you were wondering why I saved the e (event object), it is because of this (ref):

The event object is valid only for the duration of the event. After it returns you can't expect it to remain unchanged. In fact, the entire native event object (event.originalEvent) cannot be read in IE6/7/8 after the event has passed--it's gone and will throw an error if you try to access it. If you need an unchanging copy of some event data, make one.

1
votes

I got something that works, for now, with the help of Mottie's idea (was not aware of "closest" in jquery). It's not elegant, but so be it.

Here's the structure of one of the column tags:

<DIV id=slickgrid_132593DealNbr title="" class="ui-state-default slick-header-column slick-header-column-sorted" style="WIDTH: 49px">
<SPAN class=slick-column-name>DealNbr</SPAN>
<SPAN class="slick-sort-indicator slick-sort-indicator-asc"></SPAN>
<DIV class=slick-resizable-handle></DIV></DIV>

And here are the calls made to get it.

    $(document).ready(function () {
        $("#myGrid").bind("mousedown", function (e) {
            var event = e;
            timer = setTimeout(function () { heldMouse(event); }, 500);
        })
        .bind("mouseup", function () {
            clearTimeout(timer);
            $("body").one("click", function () { cleanup(); });
        });
    });

    function heldMouse(e) {
        // If the click was not on one of the headers, it won't find this
        if ($(e.target).closest('.slick-header-column').html() != null) {
            var $foundColumnHeader = $(e.target).closest('.slick-header-column');
            // columns being used to populate SlickGrid's columns
            var held_col = columns[$foundColumnHeader.index()];
            showHeaderContextMenu(e, { column: held_col });
        }
        else {
            showContextMenu(e);
        }
        mouseHeldDown = false;
    }

Thanks!