# Resumen del Script table.js

El script `table.js` define una función principal `initializeTable` que crea y gestiona una tabla HTML dinámica con funcionalidades CRUD, subtablas relacionadas expandibles, selección múltiple y otras características interactivas.

---

## Funcionalidades Principales

### 1. Inicialización y Configuración

- Acepta un ID de tabla, datos iniciales (`data`), esquema de columnas (`schema`) y configuración CRUD (`crudConfig`).
- Permite definir el modo del formulario: `inline`, `modal` u `offcanvas`.
- Procesa el esquema para establecer valores por defecto en `visible`, `editable`, `visible_on_form` y `searchable`.
- Todas las filas de datos llevan la clase CSS `main-row`. Las filas de subtabla llevan `subtable-row`.

### 2. Creación de la Interfaz de Usuario (UI)

- Genera dinámicamente el `<thead>` basado en el esquema.
- Añade botones globales **Agregar** y **Exportar** en la cabecera de la columna de acciones.
- Crea formularios dinámicos (modal o offcanvas de Bootstrap) para agregar o editar filas cuando `formMode` no es `inline`.

### 3. Operaciones CRUD

| Operación | Comportamiento |
|---|---|
| **Agregar** | Fila inline o formulario según `formMode`. Soporta `addByJson` para carga masiva. |
| **Leer** | Renderizado inicial desde `tableData.data`. `getData()` devuelve todas las filas principales. |
| **Actualizar** | Edición inline (inputs en celda) o formulario. `updateRow(i, data)` / `updateRowByObject(i, data)` por API. |
| **Eliminar** | Botón por fila con confirmación. Al eliminar una `main-row` también se elimina su `subtable-row` asociada. |

### 4. Subtablas Relacionadas (filas expandibles)

Cuando se configura `crudConfig.subtable`, cada fila principal muestra un botón chevron en la columna de acciones:

- **`bi-chevron-down`** → subtabla colapsada (estado inicial)
- **`bi-chevron-up`** → subtabla expandida

La carga es **lazy**: el contenido se obtiene solo la primera vez que el usuario expande la fila.

**Opciones de `subtable`:**

| Propiedad | Tipo | Descripción |
|---|---|---|
| `schema` | `Array` | Esquema de columnas de la subtabla (misma estructura que el schema principal). |
| `key` | `string` | Clave del objeto fila que contiene los datos embebidos (array). |
| `fetch` | `Function` | `(rowData) → Promise<Array>`. Llamada AJAX u otra fuente async. Tiene prioridad sobre `key`. |

**Ejemplo con fetch AJAX:**
```javascript
subtable: {
    schema: [
        { key: 'email',  title: 'Email',  type: 'email', visible: true },
        { key: 'status', title: 'Estado', type: 'text',  visible: true },
    ],
    fetch: function(row) {
        return $.ajax({ url: '/ajax/members/get.php', type: 'POST',
                        data: { uuid: row.uuid }, dataType: 'json' });
    }
}
```

**Ejemplo con datos embebidos:**
```javascript
subtable: {
    schema: [ { key: 'name', title: 'Nombre', type: 'text', visible: true } ],
    key: 'members'   // row.members debe ser un array
}
```

### 5. Selección Múltiple

Activada con `multipleSelect: true`. Añade una columna de checkboxes y un "seleccionar todo" en la cabecera. `getSelectedRowsData()` devuelve los datos de las filas marcadas.

### 6. Manejo de Eventos y Callbacks

| Callback | Parámetros | Descripción |
|---|---|---|
| `onAdd` | `(rowData, rowIndex)` | Al confirmar nueva fila. |
| `onUpdate` | `(rowData, rowIndex)` | Al guardar edición. |
| `onDelete` | `(rowData, rowIndex, confirmFn, cancelFn)` | Al pulsar eliminar. Llamar `confirmFn()` para ejecutar el borrado. |
| `onExport` | `(jsonString)` | Al pulsar exportar. Si no se define, descarga el archivo automáticamente. |
| `onEditStart` | `(rowData, rowIndex) → boolean` | Al iniciar edición. Devolver `false` cancela. |
| `onSearch` | `(rowData, $input, rowIndex)` | Al pulsar F2 en un input. |
| `onSelect` | `(rowData, rowIndex)` | Al hacer clic en una fila principal. |
| `onRowPrint` | `(rowData)` | Al pulsar el botón de impresión de fila. |
| `onAddStart` | `()` | Antes de abrir el formulario de nueva fila. |
| `onDraw` | `()` | Tras renderizar todas las filas iniciales. `this` = instancia de tabla. |

Eventos de teclado: **F2** dispara `onSearch`, **Escape** cancela la edición inline o cierra el formulario.

### 7. API Pública (valor de retorno)

```javascript
const tbl = initializeTable('mi-tabla', data, config, callbacks);

tbl.add()                          // Abre formulario / añade fila inline
tbl.export()                       // Exporta datos actuales
tbl.addByJson(data)                // Añade filas desde objeto o array JSON
tbl.cancelInputs()                 // Cancela la edición inline activa
tbl.getData()                      // Array con datos de todas las filas principales
tbl.updateRow(index, data)         // Actualiza celda(s) de una fila por índice
tbl.updateRowByObject(index, data) // Reemplaza valores directamente en el DOM
tbl.deleteRow(index)               // Elimina fila principal y su subtable-row asociada
tbl.fillEditingInputs(data)        // Rellena los inputs del formulario abierto
tbl.triggerOnSelect(index)         // Dispara onSelect manualmente en una fila
tbl.getSelectedRowsData()          // Datos de filas marcadas (requiere multipleSelect)
tbl.clear()                        // Vacía el cuerpo de la tabla
tbl.getSchema()                    // Copia profunda del schema
```

---

## Estructura del Código

- Función principal `initializeTable` que encapsula toda la lógica en un closure.
- Sub-funciones internas: `addSingleRowByJson`, `attachRowEvents`, `openFormDialog`, `buildSubtableHtml`, `renderSubtable`, `cancelEditing`, `getRowData`, `getMainRowIndex`, entre otras.
- Utiliza **jQuery** para manipulación del DOM y eventos.
- Utiliza **Bootstrap 5** para modales y offcanvas.
- Los índices de filas en callbacks (`rowIndex`) se calculan solo entre `main-row`, ignorando `subtable-row`.

---

**En resumen, `table.js` es una librería JavaScript versátil para implementar tablas de datos interactivas con CRUD completo, subtablas relacionadas expandibles, selección múltiple y personalización total mediante esquema y callbacks.**
