KevinChen 发表于 2020-12-28 17:52:21

SpreadJS 如何自定义公式提示信息 Part II

本帖最后由 KevinChen 于 2020-12-28 18:05 编辑



本文是《SpreadJS 如何自定义公式提示信息》系列的第三篇,第一、二篇请参考:
SpreadJS 如何自定义公式提示信息 Part I
SpreadJS 如何自定义公式提示信息 Part III
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++





二、如何解决获取光标位置?

可能有同学之前在网上搜索过这个问题,但题主确实是没有找到原生的JS事件能够直接监听光标位置的改变。所以这里采用了一些特殊的办法:通过获取“选中区域”的方式,获取到光标所在位置,如果选中区域为0,光标位置就是 selection 的 start == end的位置。

/*
                获取光标焦点位置
                入参:光标HostElement
                返回:光标所在位置(int)
      */
      static getCursortPosition(element) {
          var caretOffset = 0;
          var doc = element.ownerDocument || element.document;
          var win = doc.defaultView || doc.parentWindow;
          var sel;
          if (typeof win.getSelection != "undefined") {//谷歌、火狐
                sel = win.getSelection();
                if (sel.rangeCount > 0) {//选中的区域
                  var range = win.getSelection().getRangeAt(0);
                  var preCaretRange = range.cloneRange();//克隆一个选中区域
                  preCaretRange.selectNodeContents(element);//设置选中区域的节点内容为当前节点
                  preCaretRange.setEnd(range.endContainer, range.endOffset);//重置选中区域的结束位置
                  caretOffset = preCaretRange.toString().length;
                }
          } else if ((sel = doc.selection) && sel.type != "Control") {//IE
                var textRange = sel.createRange();
                var preCaretTextRange = doc.body.createTextRange();
                preCaretTextRange.moveToElementText(element);
                preCaretTextRange.setEndPoint("EndToEnd", textRange);
                caretOffset = preCaretTextRange.text.length;
          }
          return caretOffset;
      }


那么有了上述的方法,我们已经可以获取到输入框的光标位置了,但是在什么时机获取呢?结合Part I 中的分析,当以下两种情况出现时,我们需要更新光标位置:
1、输入框内容发生改变时;
2、鼠标点击对应位置时;
3、键盘的 上、下、左、右方向键被触发时。

本Demo实现其中两个(键盘事件参考鼠标事件自行绑定)
代码如下:

// 鼠标点击获取焦点事件
      sheet.bind(GC.Spread.Sheets.Events.EditStarting, (sender, args) => {
                const editHost = CustomizeFormulaHelper.getInputDom(args.sheet);
                if(editHost){
                        editHost.addEventListener("click", () => {
                              myFormulaHelper.currentCursortPosition = CustomizeFormulaHelper.getCursortPosition(editHost);
                              // console.log(editHost.textContent);
                        });
                }
      });
      // 内容变更获取焦点事件
      sheet.bind(GC.Spread.Sheets.Events.EditChange, (sender, args) => {
                const editHost = CustomizeFormulaHelper.getInputDom(args.sheet);
                if(editHost){
                        myFormulaHelper.currentCursortPosition = CustomizeFormulaHelper.getCursortPosition(editHost);
                        // console.log(editHost.textContent);
                }
      });
      // 复位光标位置
      sheet.bind(GC.Spread.Sheets.Events.EditEnded, (sender, args) => {
                myFormulaHelper = new CustomizeFormulaHelper(args.sheet, fbx);
                observer.disconnect();
                observer = observeChange(myFormulaHelper);
      });


完整Demo请参考附件。

页: [1]
查看完整版本: SpreadJS 如何自定义公式提示信息 Part II