代码补全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!-- 代码编辑区 -->
<textarea id="editor" placeholder="输入代码,如 console." list="aa"></textarea>
<datalist id="aa">
<option>23</option>
</datalist>
<!-- 补全候选弹窗 -->
<div id="completionList"
style="display: none; position: absolute; border: 1px solid #ccc; background: #fff; z-index: 999;"></div>
<script>
const editor = document.getElementById('editor');
const completionList = document.getElementById('completionList');
// 1. 定义补全词库(示例:JavaScript 常用 API)
const keywordMap = {
"console.": ["log()", "warn()", "error()", "table()"],
"document.": ["getElementById()", "querySelector()", "createElement()"]
};

// 2. 监听输入事件,触发补全检测
editor.addEventListener('input', (e) => {
const cursorPos = editor.selectionStart;
const content = editor.value.substring(0, cursorPos);
// 匹配词库中的触发前缀(如 console.)
const triggerPrefix = Object.keys(keywordMap).find(prefix => content.endsWith(prefix));

if (triggerPrefix) {
showCompletions(keywordMap[triggerPrefix]);
// 定位弹窗到光标下方
const rect = editor.getBoundingClientRect();
console.log(rect)
completionList.style.left = `${rect.left}px`;
completionList.style.top = `${rect.top + rect.height + 5}px`;
} else {
completionList.style.display = 'none'; // 无匹配则隐藏
}
});

// 3. 渲染补全候选列表
function showCompletions(candidates) {
completionList.innerHTML = candidates.map(word => `<div class="item">${word}</div>`).join('');
completionList.style.display = 'block';
// 点击候选词插入到编辑区
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', () => {
const triggerPrefix = Object.keys(keywordMap).find(prefix => editor.value.endsWith(prefix));
editor.value = editor.value.replace(triggerPrefix, triggerPrefix + item.textContent.slice(0, -2));
editor.focus();
completionList.style.display = 'none';
});
});
}

// 4. 点击空白处关闭补全弹窗
document.addEventListener('click', (e) => {
if (![editor, completionList].includes(e.target)) {
completionList.style.display = 'none';
}
});

</script>