function sqGridSpinner(grid, rowIndex, colIndex, row, params) {
    var value = 0;
    var min = 0;
    var max = 100000;
    var step = 1;
    if ("value" in params) {
        value = parseFloat(params["value"]);
    }
    if ("min" in params) {
        min = parseFloat(params["min"]);
    }
    if ("max" in params) {
        max = parseFloat(params["max"]);
    }
    if ("step" in params) {
        step = parseFloat(params["step"]);
    }

    var isDisabled = false;
    if (row.disabled) {
        isDisabled = true;
    }
    if (grid.getCellCustomData(rowIndex, colIndex, "cellsDisabled")) {
        isDisabled = true;
    }

    var customValue = grid.getCellCustomData(rowIndex, colIndex, "cellsSpinnerValues");
    if (customValue != null) {
        value = customValue;
    } else {
        grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", value);
    }

    if (value < min) {
        value = min;
    }
    if (value > max) {
        value = max;
    }

    grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", value);

    IncrementalDOM.elementOpenStart('div');
    IncrementalDOM.attr("class", "grid-widget-spinner");
    IncrementalDOM.attr("onmousedown", function (e) {
        e.stopPropagation();
    });
    IncrementalDOM.elementOpenEnd('div');

    IncrementalDOM.elementOpenStart('input');
    IncrementalDOM.attr("class", "grid-widget-spinner-input");
    IncrementalDOM.attr("type", "text");
    IncrementalDOM.attr("value", value);
    if (isDisabled) {
        IncrementalDOM.attr("disabled", "disabled");
    }
    var prevValue = value;
    IncrementalDOM.attr("onkeydown", function (e) {
        e.stopPropagation();
    });
    IncrementalDOM.attr("onchange", function (e) {
        e.stopPropagation();
        var newValue = parseFloat(e.target.value);
        if (isNaN(newValue) || newValue < min || newValue > max) {
            newValue = prevValue;
        } else {
            prevValue = newValue;
        }
        e.target.value = newValue;
        grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", newValue);
        sqGridSendEvent(e, "spinnerUpdated", newValue);
    });

    IncrementalDOM.elementOpenEnd('input');
    var currentElement = IncrementalDOM.currentElement();
    currentElement.value = value;
    /*     (function (currentElement, prevValue, min, max, rowIndex, colIndex) {
            currentElement.onchange = function (e) {
                e.stopPropagation();
                console.error("chnged 2");
                var newValue = parseFloat(e.target.value);
                if (isNaN(newValue) || newValue < min || newValue > max) {
                    newValue = prevValue;
                } else {
                    prevValue = newValue;
                }
                e.target.value = newValue;
                grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", newValue);
                sqGridSendEvent(e, "spinnerUpdated", newValue);
            }
        })(currentElement, prevValue, min, max, rowIndex, colIndex); */
    IncrementalDOM.elementClose('input');

    if (!isDisabled) {
        IncrementalDOM.elementOpenStart('div');
        IncrementalDOM.attr("class", "grid-widget-spinner-plus");
        IncrementalDOM.attr("onclick", function (e) {
            e.stopPropagation();
            var newValue = parseFloat(currentElement.value);
            if (sqGridSpinnerValueCheck(newValue, min, max, step)) {
                newValue = Math.round((newValue + step) * 10000) / 10000;
                currentElement.value = newValue;
                grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", newValue);
                sqGridSendEvent(e, "spinnerUpdated", newValue);
            }
        });
        IncrementalDOM.elementOpenEnd('div');
        IncrementalDOM.text("+");
        IncrementalDOM.elementClose('div');

        IncrementalDOM.elementOpenStart('div');
        IncrementalDOM.attr("class", "grid-widget-spinner-minus");
        IncrementalDOM.attr("onclick", function (e) {
            e.stopPropagation();
            var newValue = parseFloat(currentElement.value);
            if (sqGridSpinnerValueCheck(newValue, min, max, -step)) {
                newValue = Math.round((newValue - step) * 10000) / 10000;
                currentElement.value = newValue;
                grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", newValue);
                sqGridSendEvent(e, "spinnerUpdated", newValue);
            }
        });
        IncrementalDOM.elementOpenEnd('div');
        IncrementalDOM.text("-");
        IncrementalDOM.elementClose('div');
    }

    IncrementalDOM.elementClose('div');
}

function sqGridSpinnerValueCheck(value, min, max, step) {
    if (value + step >= min && value + step <= max) {
        return true;
    }
    return false;
}

function sqGridSpinnerValueSet(grid, rowIndex, colIndex, newValue, disableBodyRedraw) {
    grid.setCellCustomData(rowIndex, colIndex, "cellsSpinnerValues", newValue);
    if (!disableBodyRedraw) {
        grid.bodyRedraw();
    }
}

function sqGridSpinnerValueGet(grid, rowIndex, colIndex) {
    return grid.getCellWidgetValue(rowIndex, colIndex, "cellsSpinnerValues");
}