SpreadJS 如何自定义公式提示信息 Part I
本帖最后由 KevinChen 于 2020-12-28 18:05 编辑如上图所示,以上两个提示信息是SpreadJS原生实现的,体验上类似Excel的Formula Helper的tip,曾经有很多用Spread JS的朋友希望能够自定义这个Tip,那从本文开始,我就帮咱们尝试分析、实现一下这个需求功能。
注意:
此功能不是SpreadJS产品原生功能。
本文思路仅供参考,请详细阅读文章、源码,并仔细评估后再决定要不要做到产品中。
如遇到问题欢迎交流,但如因此方案不满足需求,版主和技术团队没有完善的义务。
需求分析:
要实现自定制Formula Helper Tips,到底要实现什么?这里建议有此想法的小伙伴,可以先打开一个SpreadJS,输入公式后仔细查看Tips的UI逻辑。我总结了几点,如下所示:
1、能够在光标处根据当前输入内容,自动模糊检索可能的公式条目;
2、当输入公式参数时,会自动判断参数输入的是公式,还是值(或引用),如果是公式,回到1,如果是值(或引用),弹出参数提示以及公式详情;
3、当遇到多层嵌套公式时,Helper Tip会随鼠标点击(光标停留)的位置判断所在位置的公式,并结合1、2的逻辑给出对应的提示信息。
以上3点,是基于UI层面的逻辑拆解,看起来不复杂,但进一步拆解为技术点时会发现,里面有很多难点,比如:
1、怎么获得输入框的光标位置?
2、当光标更改时,如何拆解出对应的公式,并修改Tip的内容给出对应的提示?
3、怎么判断输入、点击、光标变更的事件,如何在合适的时机弹出Helper Tips?
这几个问题都是大坑,我会把这个话题分三个部分,把这些问题一一处理掉。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
一、解决问题3——如何在合适的时机弹出Helper Tips ?
这个问题,如果正面强攻,会非常麻烦,不过好在我们只需要“重写”SpreadJS现有的内容,而不需要自己再造一套轮子。因此我们可以通过MutationObserver监听SpreadJS的弹窗,再修改原有的内容为自定义内容即可。
注:MutationObserver监听是异步的,但它是微任务,优先级高于Dom渲染,不用担心会出现原界面“闪现”的问题。
代码如下:
// 监听host更改,修改func helps内容(依赖SpreadJS自己的逻辑)
function observeChange(formulaHelper){
const targetNode = document.getElementById('ss');
const config = { childList: true };
const callback = function(mutationsList, observer) {
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
if(mutation.addedNodes && mutation.addedNodes.length > 0){
let addedNodes = mutation.addedNodes;
for(let i=0; i<addedNodes.length; i++){
let node = addedNodes;
// gcsj-func-help-popup 是参数提醒
// gcsj-func-ac-popup 是函数提醒
if(node.classList === "gcsj-func-help-popup" || node.classList === "gcsj-func-ac-popup" ){
const nodeObserver = new MutationObserver((mutationsList, observer) => {
mutationsList.forEach((mutationRecord) => {
nodeObserver.disconnect();
// console.log(node);
mutationRecord.target.innerText = formulaHelper.showForCasual(node);
nodeObserver.observe(node, {attributes: true, childList: true});
});
});
nodeObserver.observe(node, {attributes: true, childList: true})
}
}
}
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
return observer;
}
关于其它的问题,请关注后续的Part II和Part III
完整代码参考附件。
页:
[1]