无法为 dgrid 中包含两个 dijit 文本框的自定义编辑器小部件转移焦点

问题描述

我正在构建一个包含几个小的自定义项的时间表输入系统。我的问题是每一天我都需要输入两个十进制值,“小时”和“假日”。我制作了一个可以保存这些数据并通过两个 NumberTextBoxes 输入的自定义小部件,并将这个小部件设置为 dgrid 中该字段的编辑器,它在基本级别上工作。麻烦在于按 Tab 键并将焦点移到“下一个”单元格。

所需的行为是您可以单击一个单元格进行编辑并在“小时”文本框中获得焦点,选项卡应将您带到该编辑器的“假日”文本框,然后选项卡应关闭该编辑器,在下一列,然后重新开始(创建时它会自动聚焦自己的小时文本框)。

这是我为了演示问题而制作的简化版本。

require([
  'dojo/_base/declare','dijit/_WidgetBase','dijit/_TemplatedMixin','dijit/_WidgetsInTemplateMixin','dijit/form/NumberTextBox','dgrid/ondemandGrid','dgrid/Editor','dgrid/Selection','dgrid/Keyboard','dgrid/extensions/DijitRegistry','dstore/Memory','dstore/Trackable','dojo/keys','dojo/on','dojo/domready!'
],function(declare,_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,NumberTextBox,ondemandGrid,Editor,Selection,Keyboard,DijitRegistry,Memory,Trackable,keys,on) {

    /* The custom widget used as the editor */

    var HoursEntry = declare([_WidgetBase,_WidgetsInTemplateMixin],{
        templateString: '<div class="hours-entry">' +
        '    <input class="hours-textBox"' +
        '        data-dojo-type="dijit/form/NumberTextBox"' +
        '        data-dojo-props="constraints: { pattern: \'0.##\' },placeHolder: \'Hours\'"' +
        '        data-dojo-attach-point="hoursTextBox">' +
        '    <input class="holiday-textBox"' +
        '        data-dojo-type="dijit/form/NumberTextBox"' +
        '        data-dojo-props="constraints: { pattern: \'0.##\' },placeHolder: \'Holiday\'"' +
        '        data-dojo-attach-point="holidayTextBox">' +
        '</div>',postCreate: function () {

            var self = this;
            // We want this HoursEntry widget to emit blur,so Editor kNows to tear us down.
            function blurMe(e) {
                // self.emit('blur'); doesn't seem to work despite Editor listening for on('blur')
                // If the focus has moved to either textBox (e.g. tabbing from hours to holiday) then
                // don't emit anything,we want to stay in edit mode for this field.
                // We don't seem to be able to tell during blur if the other control being
                // focussed is within this widget,so pull a timeout trick
                window.setTimeout(function () {
                    // Are either of our textBoxes focussed still?
                    if (!self.hoursTextBox.focused &&
                        !self.holidayTextBox.focused) {
                        // Neither do,so consider us blurred (tears down the editor)
                        self._onBlur();
                self.emit('focus-right');
                    }
                },250);
            }

            this.own(
                this.hoursTextBox.on('blur',blurMe),this.holidayTextBox.on('blur',this.hoursTextBox.on('change',function (val) {
                    var curVal = self.get('value');
                    curVal.hours = val;
                    self.set('value',curVal);
                }),this.holidayTextBox.on('change',function (val) {
                    var curVal = self.get('value');
                    curVal.holiday = val;
                    self.set('value',curVal);
                })
            );

            // Once we have been created (presumably the dgrid field is being edited),// make sure the hours textBox has focus.
            this.hoursTextBox.focus();
            this.inherited(arguments);
        },focus: function () {
            this.hoursTextBox.focus();
        },_setValueAttr: function (val) {
            if (!val) {
                // The data object had no value at all for this field. */
                this._set('value',{ hours: null,holiday: null });
            } else {
                this._set('value',val);
                this.hoursTextBox.set('value',val.hours,false);
                this.holidayTextBox.set('value',val.holiday,false);
            }
        },_getValueAttr: function () {
            return {
                hours: this.hoursTextBox.get('value'),holiday: this.holidayTextBox.get('value')
            };
        }
    });

    var GridType = declare([ondemandGrid,Editor]);
    var StoreType = declare([Memory,Trackable]);

    var store = new StoreType({
        idProperty: 'admin_id',data: [
            {
                admin_id: 1,monday: { hours: 1,holiday: 11 },tuesday: { hours: 2,holiday: 22 },wednesday: { hours: 3,holiday: 33 },thursday: { hours: 4,holiday: 44 },friday: { hours: 5,holiday: 55 },saturday: { hours: 6,holiday: 66 },sunday: { hours: 7,holiday: 77 }
            }
        ]
    });

    function hoursFormatter (val) {
        return !val ? 'null' : (
            (!val.hours ? '<span class="no-value">No hours</span>' : (val.hours + ' hours')) +
                '<br>' +
                (!val.holiday ? '<span class="no-value">No holiday</span>' : (val.holiday + ' holiday'))
            );
    }

    // Create identical grid columns for the dummy data fields we have
    var columns = [];
    [ 'monday','tuesday','wednesday','thursday','friday','saturday','sunday' ].forEach(function (day) {
        columns.push({
            field: day,formatter: hoursFormatter,editor: HoursEntry,editOn: 'dgrid-cellfocusin',autoSave: true
        });
    });

    var grid = new GridType({
        collection: store,columns: columns
    });
    document.body.appendChild(grid.domNode);
    grid.startup();

    // Listen for any of the Editors to tell us we need to move our focus right.
    on(grid.domNode,'focus-right',function (e) {
        console.log('right!');
        Keyboard.moveFocusRight.call(grid,e);
    });

    // This was suggested for older dgrid at https://github.com/SitePen/dgrid/issues/267 back in 2013
    // grid.addKeyHandler(keys.TAB,Keyboard.moveFocusRight);

});
.hours-textBox,.holiday-textBox { width: 100%; }
<script>
window.dojoConfig = {
  parSEOnLoad: false,async: true,packages: [{
      name: 'dstore',location: 'https://cdn.rawgit.com/SitePen/dstore/v1.2.1'
  },{
      name: 'dgrid',location: '//cdn.rawgit.com/SitePen/dgrid/v0.4.2'
  },{
      name: 'xstyle',location:'//cdn.rawgit.com/kriszyp/xstyle/v0.3.3'
  },{
      name: 'put-selector',location: '//cdn.rawgit.com/kriszyp/put-selector/v0.3.6'
  }]
};
</script>
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.12.1/dojo/dojo.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.12.1/dijit/themes/claro/claro.css" />
<style>
    .hours-textBox,.holiday-textBox { width: 100%; }
</style>

<body class="claro">
  <div id="select"></div>
</body>

我可能在两个方面搞砸了:

  • HoursEntry 小部件尝试管理何时对自身调用 '_onBlur',这似乎是告诉 dgrid 该小部件已模糊并且应该拆除的最佳方式。它在它的两个文本框上设置“模糊”处理程序,并在每个文本框中检测它们中的任何一个是否仍然处于焦点状态(即焦点从一个传递到另一个,因此编辑器应该保持不动)。如果两者都不是,它会调用 _onBlur,并发出一个我稍后处理的自定义事件。

  • 在创建 dgrid 的地方,我监听 'focus-right' 事件,并使用 moveFocusRight 函数尝试将焦点向右移动。这似乎获得了所有正确的单元格对象等,但实际上并没有移动它。

自从我打了个结以来,我想我会伸出手来看看是否有更多经验的人可以帮助解决这个问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)