# Mouse Support - Documentation

## Overview

The mouse support library provides keyboard-like binding capabilities for mouse actions. It supports simple clicks, modified clicks (with Ctrl/Shift/Alt), and sequences of clicks with smart timeout logic.

## Features

### Supported Mouse Actions

**Basic Actions**:
- `click` - Left click
- `right_click` (or `rclick`) - Right click (contextmenu)

**Modified Actions**:
- `ctrl+click` (or `ctrl+rclick`) - Ctrl+Click (or Cmd+Click on Mac)
- `shift+click` (or `shift+rclick`) - Shift+Click
- `alt+click` (or `alt+rclick`) - Alt+Click
- `ctrl+shift+click` - Multiple modifiers
- Any combination of modifiers

**Sequences**:
- `click right_click` (or `click rclick`) - Click then right-click within 500ms
- `click click` - Double click sequence
- `ctrl+click click` - Ctrl+click then normal click
- Any sequence of actions

**Note**: `rclick` is an alias for `right_click` and can be used interchangeably.

### Smart Timeout Logic

Same as keyboard support:
- If **any element** has a longer sequence possible, **all matching elements wait**
- Timeout is 500ms between actions
- Immediate trigger if no longer sequences exist

### Multiple Element Support

Multiple elements can listen to the same mouse action and all will trigger simultaneously.

## Configuration Format

Uses HTMX configuration objects (same as keyboard support):

```javascript
const combinations = {
  "click": {
    "hx-post": "/handle-click",
    "hx-target": "#result"
  },
  "ctrl+click": {
    "hx-post": "/handle-ctrl-click",
    "hx-swap": "innerHTML"
  },
  "rclick": {  // Alias for right_click
    "hx-post": "/context-menu"
  },
  "click rclick": {  // Can use rclick in sequences too
    "hx-post": "/sequence-action",
    "hx-vals": {"type": "sequence"}
  }
};

add_mouse_support('my-element', JSON.stringify(combinations));
```

## API Reference

### add_mouse_support(elementId, combinationsJson)

Adds mouse support to an element.

**Parameters**:
- `elementId` (string): ID of the HTML element
- `combinationsJson` (string): JSON string of combinations with HTMX configs

**Returns**: void

**Example**:
```javascript
add_mouse_support('button1', JSON.stringify({
  "click": {"hx-post": "/click"},
  "ctrl+click": {"hx-post": "/ctrl-click"}
}));
```

### remove_mouse_support(elementId)

Removes mouse support from an element.

**Parameters**:
- `elementId` (string): ID of the HTML element

**Returns**: void

**Side effects**:
- If last element: detaches global event listeners and cleans up all state

**Example**:
```javascript
remove_mouse_support('button1');
```

## Automatic Parameters

The library automatically adds these parameters to every HTMX request:
- `combination` - The mouse combination that triggered the action (e.g., "ctrl+click")
- `has_focus` - Boolean indicating if the element had focus when clicked
- `is_inside` - Boolean indicating if the click was inside the element
  - For `click`: `true` if clicked inside element, `false` if clicked outside
  - For `right_click`: always `true` (only triggers when clicking on element)
- `has_focus` - Boolean indicating if the element had focus when the action triggered
- `clicked_inside` - Boolean indicating if the click was inside the element or outside

### Parameter Details

**`has_focus`**: 
- `true` if the registered element currently has focus
- `false` otherwise
- Useful for knowing if the element was the active element

**`clicked_inside`**:
- For `click` actions: `true` if clicked on/inside the element, `false` if clicked outside
- For `right_click` actions: always `true` (since right-click only triggers on the element)
- Useful for "click outside to close" logic

**Example values sent**:
```javascript
// User clicks inside a modal
{
  combination: "click",
  has_focus: true,
  clicked_inside: true
}

// User clicks outside the modal (modal still gets triggered because click is global)
{
  combination: "click",
  has_focus: false,
  clicked_inside: false  // Perfect for closing the modal!
}

// User right-clicks on an item
{
  combination: "right_click",
  has_focus: false,
  clicked_inside: true  // Always true for right_click
}
```

## Python Integration

### Basic Usage

```python
combinations = {
    "click": {
        "hx-post": "/item/select"
    },
    "ctrl+click": {
        "hx-post": "/item/select-multiple",
        "hx-vals": json.dumps({"mode": "multi"})
    },
    "right_click": {
        "hx-post": "/item/context-menu",
        "hx-target": "#context-menu",
        "hx-swap": "innerHTML"
    }
}

f"add_mouse_support('{element_id}', '{json.dumps(combinations)}')"
```

### Sequences

```python
combinations = {
    "click": {
        "hx-post": "/single-click"
    },
    "click click": {
        "hx-post": "/double-click-sequence"
    },
    "click right_click": {
        "hx-post": "/click-then-right-click"
    }
}
```

### Multiple Elements

```python
# Item 1
item1_combinations = {
    "click": {"hx-post": f"/item/1/select"},
    "ctrl+click": {"hx-post": f"/item/1/toggle"}
}
f"add_mouse_support('item-1', '{json.dumps(item1_combinations)}')"

# Item 2
item2_combinations = {
    "click": {"hx-post": f"/item/2/select"},
    "ctrl+click": {"hx-post": f"/item/2/toggle"}
}
f"add_mouse_support('item-2', '{json.dumps(item2_combinations)}')"
```

## Behavior Details

### Click vs Right-Click Behavior

**IMPORTANT**: The library handles `click` and `right_click` differently:

**`click` (global detection)**:
- Triggers for ALL registered elements, regardless of where you click
- Useful for "click outside to close" functionality (modals, dropdowns, popups)
- Example: Modal registered with `click` → clicking anywhere on the page triggers the modal's click action

**`right_click` (element-specific detection)**:
- Triggers ONLY when you right-click on (or inside) the registered element
- Right-clicking outside the element does nothing and shows browser's context menu
- This preserves normal browser behavior while adding custom actions on your elements

**Example use case**:
```javascript
// Modal that closes when clicking anywhere
add_mouse_support('modal', JSON.stringify({
  "click": {"hx-post": "/close-modal"}  // Triggers even if you click outside modal
}));

// Context menu that only appears on element
add_mouse_support('item', JSON.stringify({
  "right_click": {"hx-post": "/item-menu"}  // Only triggers when right-clicking the item
}));
```

### Modifier Keys (Cross-Platform)

- **Windows/Linux**: `ctrl+click` uses Ctrl key
- **Mac**: `ctrl+click` uses Cmd (⌘) key OR Ctrl key
- This follows standard web conventions for cross-platform compatibility

### Input Context Protection

Mouse actions are **disabled** when clicking in input fields:
- `<input>` elements
- `<textarea>` elements  
- Any `contenteditable` element

This ensures normal text selection and interaction works in forms.

### Right-Click Menu

The contextmenu (right-click menu) is prevented with `preventDefault()` when:
- A `right_click` action is configured for the element
- The element is NOT an input/textarea/contenteditable

### Event Bubbling

The library checks if the click target OR any parent element is registered:
```html
<div id="container">
  <button>Click me</button>
</div>
```
If `container` is registered, clicking the button will trigger the container's actions.

## Examples

### Using Aliases

You can use `rclick` instead of `right_click` anywhere:

```javascript
// These are equivalent
const config1 = {
  "right_click": {"hx-post": "/menu"}
};

const config2 = {
  "rclick": {"hx-post": "/menu"}  // Shorter alias
};

// Works in sequences too
const config3 = {
  "click rclick": {"hx-post": "/sequence"}
};

// Works with modifiers
const config4 = {
  "ctrl+rclick": {"hx-post": "/ctrl-right-click"}
};
```

### Context Menu

```javascript
const combinations = {
  "right_click": {
    "hx-post": "/show-context-menu",
    "hx-target": "#menu",
    "hx-swap": "innerHTML"
  }
};
```

### Close Modal/Popup on Click Outside

Since `click` is detected globally (anywhere on the page), it's perfect for "click outside to close":

```javascript
// Modal element
const modalCombinations = {
  "click": {
    "hx-post": "/close-modal",
    "hx-target": "#modal",
    "hx-swap": "outerHTML"
  }
};
add_mouse_support('modal', JSON.stringify(modalCombinations));

// Now clicking ANYWHERE on the page will trigger the handler
// Your backend receives:
// - clicked_inside: true (if clicked on modal) → maybe keep it open
// - clicked_inside: false (if clicked outside) → close it!
```

**Backend example (Python/Flask)**:
```python
@app.route('/close-modal', methods=['POST'])
def close_modal():
    clicked_inside = request.form.get('clicked_inside') == 'true'
    
    if clicked_inside:
        # User clicked inside the modal - keep it open
        return render_template('modal_content.html')
    else:
        # User clicked outside - close the modal
        return ''  # Empty response removes the modal
```

**Note**: The click handler on the modal element will trigger for all clicks on the page, not just clicks on the modal itself. Use the `clicked_inside` parameter to determine the appropriate action.

### Multi-Select List

```javascript
const combinations = {
  "click": {
    "hx-post": "/select-item",
    "hx-vals": {"mode": "single"}
  },
  "ctrl+click": {
    "hx-post": "/select-item",
    "hx-vals": {"mode": "toggle"}
  },
  "shift+click": {
    "hx-post": "/select-range",
    "hx-vals": {"mode": "range"}
  }
};
```

### Interactive Canvas/Drawing

```javascript
const combinations = {
  "click": {
    "hx-post": "/draw-point"
  },
  "ctrl+click": {
    "hx-post": "/draw-special"
  },
  "click click": {
    "hx-post": "/confirm-action"
  }
};
```

### Drag-and-Drop Alternative

```javascript
const combinations = {
  "click": {
    "hx-post": "/select-source"
  },
  "click click": {
    "hx-post": "/set-destination"
  }
};
```

## Troubleshooting

### Clicks not detected

- Verify the element exists and has the correct ID
- Check browser console for errors
- Ensure HTMX is loaded before mouse_support.js

### Right-click menu still appears

- Check if element is in input context (input/textarea)
- Verify the combination is configured correctly
- Check browser console for configuration errors

### Sequences not working

- Ensure clicks happen within 500ms timeout
- Check if longer sequences exist (causes waiting)
- Verify the combination string format (space-separated)

## Technical Details

### Architecture

- **Global listeners** on `document` for `click` and `contextmenu` events
- **Tree-based matching** using prefix trees (same as keyboard support)
- **Single timeout** for all elements (sequence-based, not element-based)
- **Independent from keyboard support** (separate registry and timeouts)

### Performance

- Single event listener regardless of number of elements
- O(n) matching where n is sequence length
- Efficient memory usage with automatic cleanup

### Browser Compatibility

- Modern browsers (ES6+ required)
- Chrome, Firefox, Safari, Edge
- Requires HTMX library

## Notes

- Timeout value is the same as keyboard support (500ms) but in separate variable
- Can be used independently or alongside keyboard support
- Does not interfere with normal mouse behavior in inputs
- Element must exist in DOM when `add_mouse_support()` is called
- **Alias**: `rclick` can be used interchangeably with `right_click` for shorter syntax