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

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

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

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

    grid.setCellCustomData(rowIndex, colIndex, "cellsTimepickerValues", 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");
    }
    IncrementalDOM.attr("onkeydown", function (e) {
        e.stopPropagation();
    });
    IncrementalDOM.attr("onchange", function (e) {
        e.stopPropagation();
        var newValue = parseInt(getHHMMFromTime(e.target.value));
        var oldVal = parseInt(grid.getCellCustomData(rowIndex, colIndex, "cellsTimepickerValues"));
        if (isNaN(newValue) || newValue < min || newValue > max || newValue == -1) {
            newValue = oldVal;
        }
        e.target.value = getTimeFromHHMM(newValue);
        grid.setCellCustomData(rowIndex, colIndex, "cellsTimepickerValues", newValue);
        sqGridSendEvent(e, "timepickerUpdated", newValue);
    });

    IncrementalDOM.elementOpenEnd('input');
    var currentElement = IncrementalDOM.currentElement();
    currentElement.value = getTimeFromHHMM(value);
    IncrementalDOM.elementClose('input');

    if (!isDisabled) {
        IncrementalDOM.elementOpenStart('div');
        IncrementalDOM.attr("class", "grid-widget-spinner-plus");
        IncrementalDOM.attr("onclick", function (e) {
            e.stopPropagation();
            var newValue = parseInt(grid.getCellCustomData(rowIndex, colIndex, "cellsTimepickerValues"));
            if (sqGridSpinnerValueCheck(newValue, min, max, step)) {
                newValue = Math.round((newValue + step) * 10000) / 10000;
                currentElement.value = getTimeFromHHMM(newValue);
                grid.setCellCustomData(rowIndex, colIndex, "cellsTimepickerValues", newValue);
                sqGridSendEvent(e, "timepickerUpdated", 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 = parseInt(grid.getCellCustomData(rowIndex, colIndex, "cellsTimepickerValues"));
            if (sqGridSpinnerValueCheck(newValue, min, max, -step)) {
                newValue = Math.round((newValue - step) * 10000) / 10000;
                currentElement.value = getTimeFromHHMM(newValue);
                grid.setCellCustomData(rowIndex, colIndex, "cellsTimepickerValues", newValue);
                sqGridSendEvent(e, "timepickerUpdated", newValue);
            }
        });
        IncrementalDOM.elementOpenEnd('div');
        IncrementalDOM.text("-");
        IncrementalDOM.elementClose('div');
    }

    IncrementalDOM.elementClose('div');

    function getTimeFromHHMM(HHMM) {
        HHMM = parseInt(HHMM);
        var hours = parseInt(HHMM / 100);
        var minutes = parseInt(HHMM % 100);
        var secondsCount = hours * 3600 + minutes * 60;

        var date = new Date(null);
        date.setSeconds(secondsCount);
        return date.toISOString().substr(11, 5);
    }

    function getHHMMFromTime(value) {
        var timeParts = value.split(':');
        if (timeParts.length < 2) {
            return -1;
        }

        return parseInt(timeParts[0]) * 100 + parseInt(timeParts[1]);
    }
}

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

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

function sqGridTimepickerValueGet(grid, rowIndex, colIndex) {
    return grid.getCellWidgetValue(rowIndex, colIndex, "cellsTimepickerValues");
}