# Example Walkthrough: Multiple Duplicates Rendering
## Example Input
```
Text: "ذهبو الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى"
```
## Step 1: Backend Analysis
When this text is sent to `/api/analyze`, the backend returns:
```json
{
"original": "ذهبو الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى",
"corrected": "ذهبوا الى المدرسة ثم ذهبوا الى البيت ثم ذهبوا مرة اخرى",
"suggestions": [
{
"start": 0,
"end": 4,
"original": "ذهبو",
"correction": "ذهبوا",
"type": "spelling"
},
{
"start": 20,
"end": 24,
"original": "ذهبو",
"correction": "ذهبوا",
"type": "spelling"
},
{
"start": 38,
"end": 42,
"original": "ذهبو",
"correction": "ذهبوا",
"type": "spelling"
}
],
"status": "success"
}
```
## Step 2: Offset Verification
Character positions in the text:
```
Position: 0 5 10 15 20 25 30 35 40 45 50
Text: ذ ــ ـ م ذ ــ ـ ب ذ ــ ى
ذهبو الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى
^^^^ ^^^^ ^^^^
0-4 20-24 38-42
```
## Step 3: Renderer Processing
### 3a. Sort Suggestions (already sorted)
```javascript
sorted = [
{start: 0, end: 4, ...}, // First occurrence
{start: 20, end: 24, ...}, // Second occurrence
{start: 38, end: 42, ...} // Third occurrence
]
```
### 3b. Create Segments
The text is split into segments at suggestion boundaries:
```javascript
segments = [
{type: 'suggestion', text: 'ذهبو', suggestion: {...}}, // [0:4]
{type: 'text', text: ' الى المدرسة ثم '}, // [4:20]
{type: 'suggestion', text: 'ذهبو', suggestion: {...}}, // [20:24]
{type: 'text', text: ' الى البيت ثم '}, // [24:38]
{type: 'suggestion', text: 'ذهبو', suggestion: {...}}, // [38:42]
{type: 'text', text: ' مرة اخرى'} // [42:51]
]
```
### 3c. Render Each Segment
**Segment 1** (suggestion):
```html
ذهبو
```
**Segment 2** (text): `" الى المدرسة ثم "`
**Segment 3** (suggestion):
```html
ذهبو
```
**Segment 4** (text): `" الى البيت ثم "`
**Segment 5** (suggestion):
```html
ذهبو
```
**Segment 6** (text): `" مرة اخرى"`
## Step 4: Final Rendered Output
Complete HTML:
```html
ذهبو الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى
```
Visual representation:
```
[ذهبو] الى المدرسة ثم [ذهبو] الى البيت ثم [ذهبو] مرة اخرى
(red) (red) (red)
```
## Step 5: User Interaction
### User clicks on first "ذهبو" (red underline)
1. Click event fired on ``
2. Tooltip appears showing:
- Error type: "خطأ إملائي"
- Correction: "ذهبوا"
3. User can click to apply correction
### When user applies correction:
**Before**:
```
ذهبو الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى
```
**After** (1st corrected):
```
ذهبوا الى المدرسة ثم ذهبو الى البيت ثم ذهبو مرة اخرى
```
**Key**: Only the clicked occurrence changes. The other two remain.
**Important**:
- ✅ Cursor position is preserved
- ✅ Selection is preserved
- ✅ Text is re-analyzed immediately
- ✅ New highlights appear with updated offsets
## Advantages Over Old System
### Old System (replace-based)
```javascript
// Try to find and replace first occurrence
text.replace("ذهبو", "ذهبوا")
// Result: ALL occurrences get replaced (or just first depending on regex)
// Problem: Can't target specific occurrence
// Problem: Duplicate words fail silently
```
### New System (offset-based)
```javascript
// Render all occurrences with specific offsets
render({
text: "ذهبو الى ... ذهبو الى ... ذهبو مرة",
suggestions: [
{start: 0, end: 4, ...}, // Exact position 1
{start: 20, end: 24, ...}, // Exact position 2
{start: 38, end: 42, ...} // Exact position 3
]
})
// Result: 3 independent spans, each clickable/correctable
// Advantage: Precise, no ambiguity, no silent failures
```
## Code Flow Diagram
```
User Text Input
↓
┌─────────────────────────────────┐
│ saveSelection() from selection.js│
│ Stores: {selectionStart, end} │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ analyzeText() from editor.js │
│ Calls: POST /api/analyze │
└────────────────┬────────────────┘
↓
API Response
{original, corrected,
suggestions with offsets}
↓
┌─────────────────────────────────┐
│ render() from renderer.js │
│ Input: text + suggestions[] │
│ - Sort by offset │
│ - Create segments │
│ - Escape HTML │
│ - Generate spans with metadata │
│ Output: Safe HTML string │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ setEditorHTML() from selection.js│
│ Updates DOM │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ restoreSelection() from selection│
│ Restores {selectionStart, end} │
│ Cursor back where it was! │
└──────────────────────────────────┘
```
## Per-Occurrence Data
Each `` carries its own suggestion:
**Span 1**:
- `data-suggestion-id="0"` - First in suggestions array
- `data-original="ذهبو"`
- `data-correction="ذهبوا"`
- Spans characters [0:4]
**Span 2**:
- `data-suggestion-id="1"` - Second in suggestions array
- `data-original="ذهبو"` (same original, different position)
- `data-correction="ذهبوا"` (same correction)
- Spans characters [20:24]
**Span 3**:
- `data-suggestion-id="2"` - Third in suggestions array
- `data-original="ذهبو"` (same original, different position)
- `data-correction="ذهبوا"` (same correction)
- Spans characters [38:42]
**Result**: No confusion. Each occurrence is independent.
---
## Summary
✅ **All 3 occurrences are highlighted**
✅ **Each is independently identifiable**
✅ **User can click any one to see/apply correction**
✅ **Cursor/selection preserved through re-renders**
✅ **XSS-safe (all user content escaped)**
✅ **No regex or string replacement needed**