实现可编辑Div按下{键弹出字段选择列表的问题求助
Fixing the Interactive Field Picker for Your Editable Div
Hey Stacy, let's get that field picker working right! The issue you're hitting is that your current code is inserting the entire list of options directly into the editable div instead of creating a selectable dropdown. Here's a step-by-step solution to build an interactive picker that pops up when users press {:
Core Approach
We'll:
- Intercept the
{keypress to stop it from being inserted directly - Show a custom dropdown menu near the user's cursor
- Let users click a field (like
First_Name) to insert it into the div - Hide the menu once a selection is made (or if the user clicks elsewhere)
Full Code Example
HTML
First, set up your editable div and a hidden dropdown container:
<div id="editableDiv" contenteditable="true" placeholder="Type here... Press { to insert fields}"></div> <ul id="fieldPicker" class="field-picker"> <li data-field="First_Name">First_Name</li> <li data-field="Last_Name">Last_Name</li> <li data-field="Email">Email</li> </ul>
CSS
Style the dropdown to look clean and position it absolutely:
#editableDiv { width: 80%; min-height: 150px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 16px; } .field-picker { display: none; position: absolute; list-style: none; margin: 0; padding: 8px 0; background: white; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); z-index: 100; } .field-picker li { padding: 6px 16px; cursor: pointer; } .field-picker li:hover { background: #f0f0f0; }
JavaScript
Add the logic to handle keypress, show the picker, and insert fields:
const editableDiv = document.getElementById('editableDiv'); const fieldPicker = document.getElementById('fieldPicker'); const fieldOptions = fieldPicker.querySelectorAll('li'); // Intercept { keypress editableDiv.addEventListener('keydown', (e) => { if (e.key === '{') { e.preventDefault(); // Stop { from being inserted directly // Get cursor position to place the picker const selection = window.getSelection(); const range = selection.getRangeAt(0); const rect = range.getBoundingClientRect(); // Position the picker near the cursor fieldPicker.style.display = 'block'; fieldPicker.style.left = `${rect.left + window.scrollX}px`; fieldPicker.style.top = `${rect.bottom + window.scrollY}px`; // Focus the picker for keyboard navigation (optional) fieldPicker.focus(); } }); // Insert selected field into the div fieldOptions.forEach(option => { option.addEventListener('click', () => { const fieldText = `{${option.dataset.field}}`; // Wrap field in {} if needed // Insert text at cursor position document.execCommand('insertText', false, fieldText); // Hide the picker fieldPicker.style.display = 'none'; // Return focus to the editable div editableDiv.focus(); }); }); // Hide picker when clicking outside document.addEventListener('click', (e) => { if (!editableDiv.contains(e.target) && !fieldPicker.contains(e.target)) { fieldPicker.style.display = 'none'; } });
Key Details Explained
- Prevent Default Behavior:
e.preventDefault()stops the raw{from being added to the div, so we can replace it with our picker. - Cursor Positioning: Using
getBoundingClientRect()ensures the dropdown pops up right where the user is typing, which feels intuitive. - Inserting Text:
document.execCommand('insertText')handles inserting the selected field at the current cursor position reliably (works in all modern browsers). - Outside Click Close: Makes sure the picker disappears if the user clicks elsewhere, avoiding clutter.
With this setup, users will see a clean, interactive dropdown when they press {—no more entire lists getting dumped into the text!
内容的提问来源于stack exchange,提问作者Stacy Thompson
相关产品推荐
相关产品推荐

