YakovL YakovL - 2 years ago 71
Javascript Question

How to prevent key events from propagating from handsontable after using stopImmediatePropagation?

My final goal is to to automatically add a column to a handsontable when a user presses right, the cursor being in the rightmost column and remove the rightmost column if it's empty when the user moves left; same for rows.

Below is my code that almost works, but there's one problem: if I don't use

Handsontable.Dom.stopImmediatePropagation(event)
, pressing up deletes bottom column and moves selection one column up (which is sort of expected behaviour); but if I use
.stopImmediatePropagation
, pressing up brings me to the right cell (and deletes the bottom row) but also causes scrolling of the page. Isn't
.stopImmediatePropagation
supposed to suppress propagation to the page as well? Is this a bug? Should I use some other method?

Here's a fiddle. My code so far looks like

Handsontable.hooks.add('beforeKeyDown',function(event)
{
var $right = 39, $down = 40, $left = 37, $up = 38,
selected = this.getSelected(),
isEditMode = this.getActiveEditor().isOpened();
if(isEditMode) return;

// calc dimensions
var endColNum = selected ? (selected[3]+1) : null,
colsNum = this.countCols(),
isLastCol = endColNum == colsNum,
endRowNum = selected ? (selected[2]+1) : null,
rowsNum = this.countRows(),
isLastRow = endRowNum == rowsNum,
i, noData, data = this.getData();

// handle arrow keys
if(isLastCol) {
if(event.which == $right)
this.alter('insert_col');
if(event.which == $left) {
noData = true;
for(i = 0; i < rowsNum; i++)
if(data[i][endColNum-1]) // check cells content
noData = false;
if(noData) {
this.alter('remove_col');
Handsontable.Dom.stopImmediatePropagation(event);
}
}
}
if(isLastRow) {
if(event.which == $down)
this.alter('insert_row');
if(event.which == $up) {
noData = true;
for(i = 0; i < colsNum; i++)
if(data[endRowNum-1][i]) // check cells content
noData = false;
if(noData) {
this.alter('remove_row');
Handsontable.Dom.stopImmediatePropagation(event);
}
}
}
},myHandsontable);

Answer Source

So, here's the solution proposed at github: after Handsontable.Dom.stopImmediatePropagation(event); add event.preventDefault() (which I've tried) but don't add any .preventPropagation/.cancelBubble (which I somewhy haven't tried). The noData part now looks like

        if(noData) {
            this.alter('remove_col');
            Handsontable.Dom.stopImmediatePropagation(event);
            // don't scroll the page
            if(event.preventDefault)
                event.preventDefault();
        }

I've made some more changes, though, so if somebody needs a snippet, here it goes:

Handsontable.hooks.add('beforeKeyDown',function(event)
{
    var $right = 39, $down = 40, $left = 37, $up = 38,
        selected = this.getSelected(),
        isEditMode = this.getActiveEditor().isOpened();
    if(isEditMode) return;

    // calc dimensions
    var startRowNum = selected ? (selected[0]+1) : null,
        startColNum = selected ? (selected[1]+1) : null,
        endRowNum   = selected ? (selected[2]+1) : null,
        endColNum   = selected ? (selected[3]+1) : null,
    // endRowNum is not necessarily >= startRowNum, it is where selection /has ended/
        rowsNum = this.countRows(),
        colsNum = this.countCols(),
        isFirstRow  = endRowNum == 0,
        isLastRow   = endRowNum == rowsNum,
        isFirstCol  = endColNum == 0,
        isLastCol   = endColNum == colsNum,
        i, noData, data = this.getData();

    // handle arrow keys
    if(isLastRow) {
        if(event.which == $down)
            this.alter('insert_row');
        if(event.which == $up && !isFirstRow) {
            noData = true;
            for(i = 0; i < colsNum; i++)
                if(data[endRowNum-1][i])
                    noData = false;
            if(noData) {
                this.alter('remove_row');
                Handsontable.Dom.stopImmediatePropagation(event);
                // don't scroll the page
                if(event.preventDefault)
                    event.preventDefault();
            }
        }
    }
    if(isLastCol) {
        if(event.which == $right)
            this.alter('insert_col');
        if(event.which == $left && !isFirstCol) {
            noData = true;
            for(i = 0; i < rowsNum; i++)
                if(data[i][endColNum-1])
                    noData = false;
            if(noData) {
                this.alter('remove_col');
                Handsontable.Dom.stopImmediatePropagation(event);
                // don't scroll the page
                if(event.preventDefault)
                    event.preventDefault();
            }
        }
    }
});
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download