当焦点在另一个输入框时,Handsontable单元格还在对焦(Handsontable cell is focusing, when focus in another input )

问题描述:
当我右键handsontable中的某一个单元格,在右键菜单里面有一项可以弹出对话框,在弹出对话框的时候使用了jquery的focus方法让我对话框中的输入框获取到了焦点,此时光标也在输入框中闪烁,当我敲击键盘输入内容时,居然直接修改了handsontbale单元格的内容。
github上相似的issue
但是当我用鼠标点击对话框的时候,我就可以正常在我的对话框中输入内容,不得不说,这很神奇,也很坑爹。

那么如何解决呢?

被handsontable虐了千百遍的我,再一次打开了handsontable的源码,近3万行的代码,每次打开都是一脸的懵逼。
首先,我用最笨的方法来定位问题所在的地方,在js文件中全局搜索有keydown事件的地方,因为不管怎样,handsontable肯定是监听了keydown事件的。
然后,打上断点,开始测试and调试,当你给handsontable打上断点后,就不难发现当你触发keydown事件的时候,会进入到哪个代码块中。
调试了几遍后,定位到了位于6633行的function onKeyDown(event)中,那么问题来了,这个事件是在哪里绑定的呢?
接着往下找,在6776行的位置,有一个document的keydown绑定,代码如下:

function init() {
    instance.addHook('afterDocumentKeyDown', onKeyDown);
    eventManager.addEventListener(document.documentElement, 'keydown', function(event) {
      instance.runHooks('afterDocumentKeyDown', event);
    });
    function onDblClick(event, coords, elem) {
      if (elem.nodeName == 'TD') {
        _this.openEditor();
        if (activeEditor) {
          activeEditor.enableFullEditMode();
        }
      }
    }
    instance.view.wt.update('onCellDblClick', onDblClick);
    instance.addHook('afterDestroy', function() {
      destroyed = true;
    });
  }

版本不同,可能所在的位置也会有差异,可以直接在js文件中搜索“afterDocumentKeyDown”来定位。

既然找到了,就直接改呗,怎么改呢?这又是个问题,如果直接改了事件监听,你会发现handsontable正常的输入行为也会有问题,那我们在事件触发的时候增加判断逻辑?这样的话,你又会发现handsontable的事件被我们阻止了,但是我们自己对话框的输入事件还是没有,想来想去,还是从源头修改:
既然handsontable监听了document的 keydown事件,那么我们想办法把事件监听迁移到handsontable本身不就行了?

仔细观察上面代码,不难发现,handsontable通过eventManager.addEventListener来绑定事件,我们找到这个方法所在的位置,8730行,修改绑定事件的逻辑:

  addEventListener: function(element, eventName, callback) {
    **if(element.nodeType == 9 || (element.nodeType == 1 && (eventName == "keydown" || eventName == "keyup"))){
        element = this.context.rootElement ? this.context.rootElement : this.context.wtTable.wtRootElement.parentElement;
    }**
    var $__3 = this;
    var context = this.context;
    function callbackProxy(event) {
      if (event.target == void 0 && event.srcElement != void 0) {
        if (event.definePoperty) {
          event.definePoperty('target', {value: event.srcElement});
        } else {
          event.target = event.srcElement;
        }
      }
      if (event.preventDefault == void 0) {
        if (event.definePoperty) {
          event.definePoperty('preventDefault', {value: function() {
              this.returnValue = false;
            }});
        } else {
          event.preventDefault = function() {
            this.returnValue = false;
          };
        }
      }
      event = extendEvent(context, event);
      callback.call(this, event);
    }
    this.context.eventListeners.push({
      element: element,
      event: eventName,
      callback: callback,
      callbackProxy: callbackProxy
    });
    if (window.addEventListener) {
      element.addEventListener(eventName, callbackProxy, false);
    } else {
      element.attachEvent('on' + eventName, callbackProxy);
    }
    Handsontable.countEventManagerListeners++;
    return (function() {
      $__3.removeEventListener(element, eventName, callback);
    });
  }

好了,我们再尝试一下,是不是发现问题已经解决了,perfect!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值