Как использовать встроенный инструмент выбора даты как в форме, так и при редактировании строк в бесплатной jqgrid

Собственный указатель даты в браузере используется для встроенного редактирования строк, как описано в Как использовать input type='date' для столбца даты в jqGrid

Как использовать его для редактирования формы? Я попробовал код ниже:

  • Выбранная строка в сетке
  • Нажата кнопка редактирования на панели инструментов
  • Нажал кнопку сохранения в форме редактирования

После этого дата исчезает из столбца invdate сетки. Также нажатие кнопок следующей и предыдущей записи в форме редактирования приводит к исчезновению invdate.

Как редактировать и отображать дату в форме редактирования с помощью встроенного в браузер средства выбора типа даты html5, если оно поддерживается в браузере?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>https://stackoverflow.com/q/26040738/315935</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="author" content="Oleg Kiriljuk"/>
    <link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css"/>
    <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/css/ui.jqgrid.css"/>
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
    <style type="text/css">
        html, body { font-size: 75%; }
    </style>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    <script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/i18n/grid.locale-en.js"></script>
    <script type="text/javascript">
        $.jgrid = $.jgrid || {};
        $.jgrid.no_legacy_api = true;
        $.jgrid.useJSON = true;
    </script>
    <script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/jquery.jqgrid.src.js"></script>
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
    <script type="text/javascript">
    //<![CDATA[
        /*global $,Modernizr */
        /*jslint browser: true, unparam: true */
        $(function () {
            "use strict";
            var mydata = [
                    { id: "10",  invdate: "", name: "test1",  note: "note1",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "20",  invdate: "2007-10-02", name: "test2",  note: "note2",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" },
                    { id: "30",  invdate: "2007-09-01", name: "test3",  note: "note3",  amount: "400.00", tax: "30.00", closed: false, ship_via: "FE", total: "430.00" },
                    { id: "40",  invdate: "2007-10-04", name: "test4",  note: "note4",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "50",  invdate: "2007-10-31", name: "test5",  note: "note5",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" }
                ],
                $grid = $("#list"),
                initDateEdit = function (elem, options) {
                    // we need get the value before changing the type
                    var orgValue = $(elem).val(), newformat,
                        cm = $(this).jqGrid("getColProp", options.name);

                    $(elem).attr("type", "date");
                    if ((Modernizr && !Modernizr.inputtypes.date) || $(elem).prop("type") !== "date") {
                        // if type="date" is not supported call jQuery UI datepicker
                        $(elem).css({ width: "8em" }).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showButtonPanel: true,
                            showWeek: true
                        });
                    } else {
                        // convert date to ISO
                        if (orgValue !== "") {
                            newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                                cm.formatoptions.newformat :
                                $(this).jqGrid("getGridRes", "formatter.date.newformat");
                            $(elem).val($.jgrid.parseDate.call(this, newformat, orgValue, "Y-m-d"));
                        }
                        // "10em" is better for Chrome and "11em" for Opera 24
                        $(elem).css("width", /OPR/.test(navigator.userAgent) ? "11em" : "10em");
                    }
                },
                myBeforeSaveRow = function (options, rowid) {
                    var $self = $(this), $dates = $("#" + $.jgrid.jqID(rowid)).find("input[type=date]");
                    $dates.each(function () {
                        var $this = $(this), newformat, str,
                            id = $this.attr("id"),
                            colName = id.substr(rowid.length + 1),
                            cm = $self.jqGrid("getColProp", colName);
                        if ((Modernizr && Modernizr.inputtypes.date) || $this.prop("type") === "date") {
                            // convert from iso to newformat
                            str = $this.val();
                            if (str !== "") {
                                newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                                    cm.formatoptions.newformat :
                                    $self.jqGrid("getGridRes", "formatter.date.newformat");
                                str = $.jgrid.parseDate.call($self[0], "Y-m-d", str, newformat);
                            }
                            $this.attr("type", "text");
                            $this.val(str);
                        }
                    });
                },
                initDateSearch = function (elem) {
                    setTimeout(function () {
                        $(elem).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showWeek: true,
                            showButtonPanel: true
                        });
                    }, 50);
                },
                numberTemplate = {formatter: "number", align: "right", sorttype: "number",
                    editrules: {number: true, required: true},
                    searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge", "nu", "nn", "in", "ni"] }};

            $grid.jqGrid({
                datatype: "local",
//loadComplete: function() {
//    $grid.jqGrid('setGridParam', { datatype: 'json' });
//},
                data: mydata,
                colNames: ["Client", "Date", "Closed", "Shipped via", "Notes", "Tax", "Amount", "Total"],
                colModel: [
                    { name: "name", align: "center", editable: true, width: 65, editrules: {required: true} },
                    { name: "invdate", width: 125, align: "center", sorttype: "date",
                        formatter: "date", /*formatoptions: { newformat: "m/d/Y"},*/ editable: true,
                        editoptions: { dataInit: initDateEdit },
                        searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge"], dataInit: initDateSearch } },
                    { name: "closed", width: 70, align: "center", editable: true, formatter: "checkbox",
                        edittype: "checkbox", editoptions: {value: "Yes:No", defaultValue: "Yes"},
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;true:Yes;false:No" } },
                    { name: "ship_via", width: 105, align: "center", editable: true, formatter: "select",
                        edittype: "select", editoptions: { value: "FE:FedEx;TN:TNT;IN:Intim", defaultValue: "IN" },
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;FE:FedEx;TN:TNT;IN:IN" } },
                    { name: "note", width: 60, sortable: false, editable: true, edittype: "textarea" },
                    { name: "tax", width: 52, editable: true, template: numberTemplate },
                    { name: "amount", width: 75, editable: true, template: numberTemplate },
                    { name: "total", width: 60, template: numberTemplate }
                ],
                rowNum: 10,
                rowList: [5, 10, 20],
                iconSet: "fontAwesome",
                pager: "#pager",
                gridview: true,
                autoencode: true,
                ignoreCase: true,
                sortname: "invdate",
                viewrecords: true,
                sortorder: "desc",
                height: "auto",
                rownumbers: true,
                editurl: "clientArray",
//editurl: "http://cdn.jsdelivr.net/test",
        toppager: true,

                onSelectRow: function (rowid) {
                    var $self = $(this),
                        savedRow = $self.jqGrid("getGridParam", "savedRow");
                    if (savedRow.length > 0) {
                        $self.jqGrid("restoreRow", savedRow[0].id);
                    }
                    $self.jqGrid("editRow", rowid, {
                        keys: true,
                        beforeSaveRow: myBeforeSaveRow
                    });
                }
            });

    $.extend(true,$.jgrid.edit, {
        closeAfterAdd: true,
        navkeys: [true,33,34],
        savekey: [true, 13],
        recreateForm: true,
        reloadAfterSubmit: false,
        left: 10,
        top: 15,
        dataheight: '100%',
        width: window.innerWidth - 18
    });



        $grid.jqGrid("navGrid", "#list_toppager", {
edit: true
});

        });
    //]]>
    </script>
</head>
<body>
    <table id="list"><tr><td></td></tr></table>
    <div id="pager"></div>
</body>
</html>

person Andrus    schedule 22.03.2015    source источник


Ответы (1)


Обходной путь, использованный в myBeforeSaveRow, также необходимо реализовать при редактировании форм. Вместо этого я изменил код бесплатного jqGrid, чтобы вам ** вообще не нужно было использовать beforeSaveRow: myBeforeSaveRow. Я поправил код встроенного редактирования и редактирования формы, чтобы он корректно работал при сохранении данных из <input type="date">. Следует быть осторожным и установить значение type в text, если type="date" не поддерживается.

В демо используется текущий код бесплатного jqGrid из GitHub. Я тестировал демо в Chrome 41, Opera 28, где поддерживается <input type="date">. Я тестировал изменения в Safari 5.1.7, Firefox 37 и IE 10. Демонстрация работает и здесь. Он использует следующий модифицированный код initDateEdit:

var initDateEdit = function (elem, options) {
    // we need get the value before changing the type
    var orgValue = $(elem).val(), newformat,
        cm = $(this).jqGrid("getColProp", options.name);

    $(elem).attr("type", "date");
    if ((typeof Modernizr !== "undefined" && !Modernizr.inputtypes.date) || $(elem).prop("type") !== "date") {
        $(elem).attr("type", "text"); // !!! important to make saving works correctly
        $(elem).css({ width: "8em" }).datepicker({
            dateFormat: "mm/dd/yy",
            autoSize: true,
            changeYear: true,
            changeMonth: true,
            showButtonPanel: true,
            showWeek: true
        });
    } else {
        // convert date to ISO
        if (orgValue !== "") {
            newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                cm.formatoptions.newformat :
                $(this).jqGrid("getGridRes", "formatter.date.newformat");
            $(elem).val($.jgrid.parseDate.call(this, newformat, orgValue, "Y-m-d"));
        }
        $(elem).css({width: "11em"});
    }
};

Другой код встроенного редактирования и редактирования формы является стандартным:

    ...
    onSelectRow: function (rowid) {
        var $self = $(this),
            savedRow = $self.jqGrid("getGridParam", "savedRow");
        if (savedRow.length > 0 && savedRow[0].id !== rowid) {
            $self.jqGrid("restoreRow", savedRow[0].id);
        }
        $self.jqGrid("editRow", rowid);
    },
    inlineEditing: {
        keys: true
    }
}).jqGrid("navGrid").jqGrid("inlineNav");

Параметры beforeSaveRow: myBeforeSaveRow удалены.

person Oleg    schedule 22.03.2015
comment
initDateSearch не использует собственный DatePicker. Как использовать его для поиска также? - person Andrus; 22.03.2015
comment
если Modernizer не включен, этот код вызывает исключение javascript. Как использовать его без модернизатора? - person Andrus; 22.03.2015
comment
нажатие кнопок следующей и предыдущей записи в редактировании формы по-прежнему показывает пустую дату. Если дата пуста, нажатие кнопки «Далее» в редактировании формы также заполняет дату в сетке - person Andrus; 22.03.2015
comment
@Andrus: я не хочу писать здесь полную реализацию <input type="data"> во всех случаях. У вас возник вопрос: как использовать встроенный инструмент выбора даты как в форме, так и в редактировании строк в бесплатном jqGrid. Редактирование формы имело реальную проблему, которая теперь исправлена. Критерий существования Modernizr можно легко изменить на typeof Modernizr !== "undefined". Я включил опцию viewPagerButtons: false в редактирование формы. Если вы хотите, вы можете включить обратный вызов afterclickPgButtons, который правильно заполнит поле редактирования <input type="date">. - person Oleg; 22.03.2015
comment
Я удалил дату в редактировании формы в последней демонстрации и нажал кнопку отправки. Дата 1970 года отображается в сетке вместо пустой даты. - person Andrus; 22.03.2015
comment
@Andrus: Я сделал еще одну небольшую модификацию кода. Теперь можно сохранить пустую дату при редактировании формы, как это возможно и при встроенном редактировании. В демо из ответа используется новый код, и теперь он работает. - person Oleg; 22.03.2015
comment
Если используется начальная загрузка, счетчик увеличения и уменьшения даты появляется в неправильном месте, вне строки в Chrome. Щелчок в счетчике постоянно изменяет значение. Как сделать его совместимым с бутстрапом? - person Andrus; 28.03.2015
comment
@Andrus: Вы можете решить проблему, исправив line-height. Например .ui-jqgrid td input[type=date], input[type=time], input[type=datetime-local], input[type=month] { line-height: normal; }. См. демонстрацию. Я думаю, что лучше опубликовать информацию в новом вопросе, чтобы другие могли найти проблему и решение. - person Oleg; 28.03.2015