I can click on the grid to select a cell
This commit is contained in:
@@ -64,6 +64,70 @@ const combinations = {
|
||||
add_mouse_support('my-element', JSON.stringify(combinations));
|
||||
```
|
||||
|
||||
### Dynamic Values with JavaScript Functions
|
||||
|
||||
You can add dynamic values computed at click time using `hx-vals-extra`. This is useful when combined with a Command (which provides `hx-vals` with `c_id`).
|
||||
|
||||
**Configuration format:**
|
||||
```javascript
|
||||
const combinations = {
|
||||
"click": {
|
||||
"hx-post": "/myfasthtml/commands",
|
||||
"hx-vals": {"c_id": "command_id"}, // Static values from Command
|
||||
"hx-vals-extra": {"js": "getClickData"} // Dynamic values via JS function
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
1. `hx-vals` contains static values (e.g., `c_id` from Command)
|
||||
2. `hx-vals-extra.dict` contains additional static values (merged)
|
||||
3. `hx-vals-extra.js` specifies a function to call for dynamic values (merged)
|
||||
|
||||
**JavaScript function definition:**
|
||||
```javascript
|
||||
// Function receives (event, element, combinationStr)
|
||||
function getClickData(event, element, combination) {
|
||||
return {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
target_id: event.target.id,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The function parameters are optional - use what you need:
|
||||
|
||||
```javascript
|
||||
// Full context
|
||||
function getFullContext(event, element, combination) {
|
||||
return { x: event.clientX, elem: element.id, combo: combination };
|
||||
}
|
||||
|
||||
// Just the event
|
||||
function getPosition(event) {
|
||||
return { x: event.clientX, y: event.clientY };
|
||||
}
|
||||
|
||||
// No parameters needed
|
||||
function getTimestamp() {
|
||||
return { ts: Date.now() };
|
||||
}
|
||||
```
|
||||
|
||||
**Built-in helper function:**
|
||||
```javascript
|
||||
// getCellId() - finds parent with .dt2-cell class and returns its id
|
||||
function getCellId(event) {
|
||||
const cell = event.target.closest('.dt2-cell');
|
||||
if (cell && cell.id) {
|
||||
return { cell_id: cell.id };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### add_mouse_support(elementId, combinationsJson)
|
||||
@@ -150,16 +214,155 @@ The library automatically adds these parameters to every HTMX request:
|
||||
|
||||
## Python Integration
|
||||
|
||||
### Basic Usage
|
||||
### Mouse Class
|
||||
|
||||
The `Mouse` class provides a convenient way to add mouse support to elements.
|
||||
|
||||
```python
|
||||
from myfasthtml.controls.Mouse import Mouse
|
||||
from myfasthtml.core.commands import Command
|
||||
|
||||
# Create mouse support for an element
|
||||
mouse = Mouse(parent_element)
|
||||
|
||||
# Add combinations
|
||||
mouse.add("click", select_command)
|
||||
mouse.add("ctrl+click", toggle_command)
|
||||
mouse.add("right_click", context_menu_command)
|
||||
```
|
||||
|
||||
### Mouse.add() Method
|
||||
|
||||
```python
|
||||
def add(self, sequence: str, command: Command = None, *,
|
||||
hx_post: str = None, hx_get: str = None, hx_put: str = None,
|
||||
hx_delete: str = None, hx_patch: str = None,
|
||||
hx_target: str = None, hx_swap: str = None, hx_vals=None)
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `sequence`: Mouse event sequence (e.g., "click", "ctrl+click", "click right_click")
|
||||
- `command`: Optional Command object for server-side action
|
||||
- `hx_post`, `hx_get`, etc.: HTMX URL parameters (override command)
|
||||
- `hx_target`: HTMX target selector (overrides command)
|
||||
- `hx_swap`: HTMX swap strategy (overrides command)
|
||||
- `hx_vals`: Additional HTMX values - dict or "js:functionName()" for dynamic values
|
||||
|
||||
**Note**:
|
||||
- Named parameters (except `hx_vals`) override the command's parameters.
|
||||
- `hx_vals` is **merged** with command's values (stored in `hx-vals-extra`), preserving `c_id`.
|
||||
|
||||
### Usage Patterns
|
||||
|
||||
**With Command only**:
|
||||
```python
|
||||
mouse.add("click", my_command)
|
||||
```
|
||||
|
||||
**With Command and overrides**:
|
||||
```python
|
||||
# Command provides hx-post, but we override the target
|
||||
mouse.add("ctrl+click", my_command, hx_target="#other-result")
|
||||
```
|
||||
|
||||
**Without Command (direct HTMX)**:
|
||||
```python
|
||||
mouse.add("right_click", hx_post="/context-menu", hx_target="#menu", hx_swap="innerHTML")
|
||||
```
|
||||
|
||||
**With dynamic values**:
|
||||
```python
|
||||
mouse.add("shift+click", my_command, hx_vals="js:getClickPosition()")
|
||||
```
|
||||
|
||||
### Sequences
|
||||
|
||||
```python
|
||||
mouse = Mouse(element)
|
||||
mouse.add("click", single_click_command)
|
||||
mouse.add("click click", double_click_command)
|
||||
mouse.add("click right_click", special_action_command)
|
||||
```
|
||||
|
||||
### Multiple Elements
|
||||
|
||||
```python
|
||||
# Each element gets its own Mouse instance
|
||||
for item in items:
|
||||
mouse = Mouse(item)
|
||||
mouse.add("click", Command("select", "Select item", lambda i=item: select(i)))
|
||||
mouse.add("ctrl+click", Command("toggle", "Toggle item", lambda i=item: toggle(i)))
|
||||
```
|
||||
|
||||
### Dynamic hx-vals with JavaScript
|
||||
|
||||
You can use `"js:functionName()"` to call a client-side JavaScript function that returns additional values to send with the request. The command's `c_id` is preserved.
|
||||
|
||||
**Python**:
|
||||
```python
|
||||
mouse.add("click", my_command, hx_vals="js:getClickContext()")
|
||||
```
|
||||
|
||||
**Generated config** (internally):
|
||||
```json
|
||||
{
|
||||
"hx-post": "/myfasthtml/commands",
|
||||
"hx-vals": {"c_id": "command_id"},
|
||||
"hx-vals-extra": {"js": "getClickContext"}
|
||||
}
|
||||
```
|
||||
|
||||
**JavaScript** (client-side):
|
||||
```javascript
|
||||
// Function receives (event, element, combinationStr)
|
||||
function getClickContext(event, element, combination) {
|
||||
return {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
elementId: element.id,
|
||||
combo: combination
|
||||
};
|
||||
}
|
||||
|
||||
// Simple function - parameters are optional
|
||||
function getTimestamp() {
|
||||
return { ts: Date.now() };
|
||||
}
|
||||
```
|
||||
|
||||
**Values sent to server**:
|
||||
```json
|
||||
{
|
||||
"c_id": "command_id",
|
||||
"x": 150,
|
||||
"y": 200,
|
||||
"elementId": "my-element",
|
||||
"combo": "click",
|
||||
"combination": "click",
|
||||
"has_focus": false,
|
||||
"is_inside": true
|
||||
}
|
||||
```
|
||||
|
||||
You can also pass a static dict:
|
||||
```python
|
||||
mouse.add("click", my_command, hx_vals={"extra_key": "extra_value"})
|
||||
```
|
||||
|
||||
### Low-Level Usage (without Mouse class)
|
||||
|
||||
For advanced use cases, you can generate the JavaScript directly:
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
combinations = {
|
||||
"click": {
|
||||
"hx-post": "/item/select"
|
||||
},
|
||||
"ctrl+click": {
|
||||
"hx-post": "/item/select-multiple",
|
||||
"hx-vals": json.dumps({"mode": "multi"})
|
||||
"hx-vals": {"mode": "multi"}
|
||||
},
|
||||
"right_click": {
|
||||
"hx-post": "/item/context-menu",
|
||||
@@ -168,41 +371,7 @@ combinations = {
|
||||
}
|
||||
}
|
||||
|
||||
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)}')"
|
||||
Script(f"add_mouse_support('{element_id}', '{json.dumps(combinations)}')")
|
||||
```
|
||||
|
||||
## Behavior Details
|
||||
|
||||
Reference in New Issue
Block a user