xonecode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -0
- package/dist/agent/authEnDisco.js +56 -0
- package/dist/agent/authEnDisco.js.map +1 -0
- package/dist/agent/configEnDisco.js +109 -0
- package/dist/agent/configEnDisco.js.map +1 -0
- package/dist/agent/crearProyecto.js +34 -0
- package/dist/agent/crearProyecto.js.map +1 -0
- package/dist/agent/entorno.js +124 -0
- package/dist/agent/entorno.js.map +1 -0
- package/dist/agent/guionizado.js +53 -0
- package/dist/agent/guionizado.js.map +1 -0
- package/dist/agent/instantanea.js +129 -0
- package/dist/agent/instantanea.js.map +1 -0
- package/dist/agent/interrupts.js +83 -0
- package/dist/agent/interrupts.js.map +1 -0
- package/dist/agent/mensajes.js +24 -0
- package/dist/agent/mensajes.js.map +1 -0
- package/dist/agent/modelos.js +42 -0
- package/dist/agent/modelos.js.map +1 -0
- package/dist/agent/normalizar.js +20 -0
- package/dist/agent/normalizar.js.map +1 -0
- package/dist/agent/perfiles.js +103 -0
- package/dist/agent/perfiles.js.map +1 -0
- package/dist/agent/proyecto.js +107 -0
- package/dist/agent/proyecto.js.map +1 -0
- package/dist/agent/puente.js +142 -0
- package/dist/agent/puente.js.map +1 -0
- package/dist/agent/resumenDeTool.js +48 -0
- package/dist/agent/resumenDeTool.js.map +1 -0
- package/dist/agent/skills.js +65 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/textoDeTool.js +113 -0
- package/dist/agent/textoDeTool.js.map +1 -0
- package/dist/agent/turnoReal.js +173 -0
- package/dist/agent/turnoReal.js.map +1 -0
- package/dist/agent/verificador.js +65 -0
- package/dist/agent/verificador.js.map +1 -0
- package/dist/agent/xoneAgent.js +106 -0
- package/dist/agent/xoneAgent.js.map +1 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/aprobar.js +82 -0
- package/dist/cli/aprobar.js.map +1 -0
- package/dist/cli/config.js +133 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/consola.js +346 -0
- package/dist/cli/consola.js.map +1 -0
- package/dist/cli/describe.js +53 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/doctor.js +45 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/main.js +520 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/markdown.js +90 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/run.js +164 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/spinner.js +89 -0
- package/dist/cli/spinner.js.map +1 -0
- package/dist/cli/stdio.js +193 -0
- package/dist/cli/stdio.js.map +1 -0
- package/dist/cli/tema.js +40 -0
- package/dist/cli/tema.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/core/bitacora.js +30 -0
- package/dist/core/bitacora.js.map +1 -0
- package/dist/core/config.js +236 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/contextos.js +56 -0
- package/dist/core/contextos.js.map +1 -0
- package/dist/core/deps.js +51 -0
- package/dist/core/deps.js.map +1 -0
- package/dist/core/diff.js +79 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/esqueleto.js +366 -0
- package/dist/core/esqueleto.js.map +1 -0
- package/dist/core/events.js +2 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/modelos.js +85 -0
- package/dist/core/modelos.js.map +1 -0
- package/dist/core/notify.js +106 -0
- package/dist/core/notify.js.map +1 -0
- package/dist/core/ports.js +114 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/turno.js +127 -0
- package/dist/core/turno.js.map +1 -0
- package/dist/vendor/hitl.js +103 -0
- package/dist/vendor/hitl.js.map +1 -0
- package/dist/vendor/skillLoaders/catalog.js +74 -0
- package/dist/vendor/skillLoaders/catalog.js.map +1 -0
- package/dist/vendor/tokenTracking.js +58 -0
- package/dist/vendor/tokenTracking.js.map +1 -0
- package/package.json +41 -0
- package/skills/xone-debugging/SKILL.md +52 -0
- package/skills/xone-debugging/references/faq.md +561 -0
- package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
- package/skills/xone-development/SKILL.md +105 -0
- package/skills/xone-development/references/anti-patrones.md +94 -0
- package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
- package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
- package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
- package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
- package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
- package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
- package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
- package/skills/xone-development/references/datos/appdata.md +611 -0
- package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
- package/skills/xone-development/references/datos/http.md +366 -0
- package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
- package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
- package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
- package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
- package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
- package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
- package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
- package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
- package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
- package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
- package/skills/xone-development/references/indice-completo.md +77 -0
- package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
- package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
- package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
- package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
- package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
- package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
- package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
- package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
- package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
- package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
- package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
- package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
- package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
- package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
- package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
- package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
- package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
- package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
- package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
- package/skills/xone-development/references/tipos-de-prop.md +28 -0
- package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
- package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
- package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
- package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
- package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
- package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
- package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
- package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
- package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
- package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
- package/skills/xone-development/references/xml-ui/mapas.md +685 -0
- package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
- package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
- package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
- package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
- package/skills/xone-plan-builder/SKILL.md +183 -0
- package/skills/xone-plan-builder/agents/openai.yaml +5 -0
- package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
- package/skills/xone-project-generator/SKILL.md +111 -0
- package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
- package/skills/xone-project-generator/references/colecciones-base.md +16 -0
- package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
- package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
- package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
- package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
- package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
- package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
- package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
- package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
- package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
- package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
- package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
- package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
- package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
- package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
- package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
- package/skills/xone-review/SKILL.md +189 -0
- package/skills/xone-spec-builder/SKILL.md +235 -0
- package/skills/xone-spec-builder/agents/openai.yaml +5 -0
- package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
- package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
- package/skills/xone-spec-builder/references/PLAN-FORMAT.md +120 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# XOne — Troubleshooting y glosario
|
|
2
|
+
|
|
3
|
+
> Fuente: `xone/v2/xone-help-docs/topics/05-events-patterns-faq.md` §19–§20. Referencia de la skill; el índice está en [../SKILL.md](../SKILL.md).
|
|
4
|
+
|
|
5
|
+
Contenido: §19 troubleshooting completo por síntoma (incluye 19.14b: load no inicializa pantalla, usar before-edit) · §20 glosario de términos XOne
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 19. Troubleshooting
|
|
10
|
+
|
|
11
|
+
### 19.1 La pantalla no muestra datos
|
|
12
|
+
|
|
13
|
+
**Diagnostico:** Los datos existen en BD pero la pantalla aparece vacia.
|
|
14
|
+
|
|
15
|
+
**Posibles causas y soluciones:**
|
|
16
|
+
|
|
17
|
+
1. **Falta `loadAll()`** - Los contents no cargan automáticamente:
|
|
18
|
+
```javascript
|
|
19
|
+
self.getContents("miContent").loadAll();
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. **Falta `visible="7"` o `visible="4"`** - Los campos no son visibles en el modo actual.
|
|
23
|
+
|
|
24
|
+
3. **El content esta bloqueado** - Desbloquear antes de cargar:
|
|
25
|
+
```javascript
|
|
26
|
+
self.getContents("miContent").unlock();
|
|
27
|
+
self.getContents("miContent").loadAll();
|
|
28
|
+
self.getContents("miContent").lock();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
4. **Falta `ui.refresh()`** - Después de modificar datos, refrescar la vista.
|
|
32
|
+
|
|
33
|
+
### 19.2 El botón no hace nada
|
|
34
|
+
|
|
35
|
+
**Diagnostico:** El botón no responde al toque.
|
|
36
|
+
|
|
37
|
+
**Posibles causas y soluciones:**
|
|
38
|
+
|
|
39
|
+
1. **Falta `visible="1"` o `visible="7"`** - El botón necesita ser visible en modo edición.
|
|
40
|
+
|
|
41
|
+
2. **Error en el atributo `method` o `onclick`** - Verificar sintaxis:
|
|
42
|
+
```xml
|
|
43
|
+
<!-- Correcto -->
|
|
44
|
+
<prop name="btn" type="B" method="ExecuteNode(miNodo)"/>
|
|
45
|
+
<!-- Incorrecto (falta ExecuteNode) -->
|
|
46
|
+
<prop name="btn" type="B" method="miNodo"/>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. **Botón bloqueado por `disableedit`** - Verificar la condición:
|
|
50
|
+
```xml
|
|
51
|
+
<prop name="btn" type="B" disableedit="MAP_ESTADO=0"/>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
4. **Solapamiento con otro elemento** - Un frame flotante puede estar encima.
|
|
55
|
+
|
|
56
|
+
### 19.3 Los estilos no se aplican
|
|
57
|
+
|
|
58
|
+
**Diagnostico:** La clase CSS no tiene efecto.
|
|
59
|
+
|
|
60
|
+
**Posibles causas y soluciones:**
|
|
61
|
+
|
|
62
|
+
1. **Usar unidades incorrectas** - No usar `px`, `em`, `rem`:
|
|
63
|
+
```css
|
|
64
|
+
/* Incorrecto */
|
|
65
|
+
.miClase { width:200px; }
|
|
66
|
+
/* Correcto */
|
|
67
|
+
.miClase { width:200p; }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. **Nombre de clase incorrecto** - Verificar que coincida exactamente.
|
|
71
|
+
|
|
72
|
+
3. **Atributo inline sobreescribe la clase** - Los atributos en el XML tienen prioridad sobre el CSS.
|
|
73
|
+
|
|
74
|
+
4. **Archivo CSS no cargado** - El archivo debe llamarse `default.css` y estar en la raiz del proyecto.
|
|
75
|
+
|
|
76
|
+
### 19.4 La coleccion no carga datos
|
|
77
|
+
|
|
78
|
+
**Diagnostico:** `getCount()` retorna 0 después de `loadAll()`.
|
|
79
|
+
|
|
80
|
+
**Posibles causas y soluciones:**
|
|
81
|
+
|
|
82
|
+
1. **SQL incorrecto** - Verificar la consulta SQL en el atributo `sql` del `<coll>`.
|
|
83
|
+
|
|
84
|
+
2. **Tabla no existe** - Regenerar la base de datos:
|
|
85
|
+
```bash
|
|
86
|
+
xone-db-tools create-db mi_proyecto --overwrite
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
3. **Filtro demasiado restrictivo** - Verificar el `filter` del `<contents>`.
|
|
90
|
+
|
|
91
|
+
4. **Falta prefijo `##PREF##`** en la SQL:
|
|
92
|
+
```xml
|
|
93
|
+
<!-- Correcto -->
|
|
94
|
+
sql="SELECT * FROM ##PREF##MiTabla t1"
|
|
95
|
+
<!-- Incorrecto -->
|
|
96
|
+
sql="SELECT * FROM MiTabla t1"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 19.5 Error de tabla no encontrada
|
|
100
|
+
|
|
101
|
+
**Diagnostico:** Error "no such table" al cargar datos.
|
|
102
|
+
|
|
103
|
+
**Solución:** Regenerar la base de datos. La tabla puede no haberse generado si:
|
|
104
|
+
- La coleccion no tiene `objname` o `updateobj`
|
|
105
|
+
- El archivo `.xne` no fue procesado por el generador
|
|
106
|
+
- El nombre de la tabla no coincide (recordar el prefijo `gen_`)
|
|
107
|
+
|
|
108
|
+
### 19.6 El GPS no funciona
|
|
109
|
+
|
|
110
|
+
**Diagnostico:** Las coordenadas siempre son 0 o null.
|
|
111
|
+
|
|
112
|
+
**Posibles causas y soluciones:**
|
|
113
|
+
|
|
114
|
+
1. **Falta `ui.startGps()`** - Iniciar el GPS antes de pedir coordenadas.
|
|
115
|
+
|
|
116
|
+
2. **Permisos no concedidos** - Verificar con:
|
|
117
|
+
```javascript
|
|
118
|
+
var status = ui.checkGpsStatus();
|
|
119
|
+
if (status == 0 || status == 3) {
|
|
120
|
+
ui.askUserForGpsPermission({
|
|
121
|
+
onEnabled: function() { ui.startGps(); },
|
|
122
|
+
onDenied: function() { ui.showToast("Active el GPS"); }
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
3. **Emulador sin GPS** - Probar en dispositivo físico.
|
|
128
|
+
|
|
129
|
+
### 19.7 La replica falla
|
|
130
|
+
|
|
131
|
+
**Diagnostico:** La sincronización con el servidor no se completa.
|
|
132
|
+
|
|
133
|
+
**Posibles causas:**
|
|
134
|
+
- Sin conexión a internet
|
|
135
|
+
- URL del servidor incorrecta
|
|
136
|
+
- Timeout en la conexión
|
|
137
|
+
- Datos corruptos en la cola de replica
|
|
138
|
+
|
|
139
|
+
**Solución:** Verificar la configuración de replica en `Empresas` y los logs del dispositivo.
|
|
140
|
+
|
|
141
|
+
### 19.8 La imagen no se muestra
|
|
142
|
+
|
|
143
|
+
**Diagnostico:** El espacio de la imagen aparece vacio.
|
|
144
|
+
|
|
145
|
+
**Posibles causas y soluciones:**
|
|
146
|
+
|
|
147
|
+
1. **Archivo no existe** - Verificar que el archivo esta en `icons/` o `files/`.
|
|
148
|
+
|
|
149
|
+
2. **Formato incorrecto** - XOne solo soporta PNG en produccion.
|
|
150
|
+
|
|
151
|
+
3. **Ruta incorrecta** - Usar `##APP##\icons\` para rutas absolutas:
|
|
152
|
+
```xml
|
|
153
|
+
<prop name="img" type="IMG" path="##APP##\icons\mi_icono.png"/>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
4. **El campo esta vacio** - Verificar que el valor del campo contiene el nombre del archivo.
|
|
157
|
+
|
|
158
|
+
### 19.9 El contents esta vacio
|
|
159
|
+
|
|
160
|
+
**Diagnostico:** El área del content se muestra sin items.
|
|
161
|
+
|
|
162
|
+
**Posibles causas y soluciones:**
|
|
163
|
+
|
|
164
|
+
1. **Falta cargar los datos:**
|
|
165
|
+
```javascript
|
|
166
|
+
self.getContents("miContent").loadAll();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
2. **Filtro incorrecto** en el `<contents>`:
|
|
170
|
+
```xml
|
|
171
|
+
<contents name="miContent" src="MiColeccion"
|
|
172
|
+
filter="ID_PADRE=##FLD_MAP_ID##"/>
|
|
173
|
+
```
|
|
174
|
+
Verificar que `MAP_ID` tiene un valor valido.
|
|
175
|
+
|
|
176
|
+
3. **La coleccion fuente (`src`) no existe** - Verificar el nombre.
|
|
177
|
+
|
|
178
|
+
4. **El `<prop type="Z">` no referencia al content correcto:**
|
|
179
|
+
```xml
|
|
180
|
+
<prop name="@miContent" type="Z" contents="miContent"/>
|
|
181
|
+
<contents name="miContent" src="MiColeccion"/>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 19.10 El onchange no se dispara
|
|
185
|
+
|
|
186
|
+
**Diagnostico:** Cambiar un campo no ejecuta el evento onchange.
|
|
187
|
+
|
|
188
|
+
**Posibles causas y soluciones:**
|
|
189
|
+
|
|
190
|
+
1. **Para campos tipo T (texto)**, el `onchange` del nodo se dispara al perder el foco, no en cada tecla. Para tiempo real usar `ontextchanged`:
|
|
191
|
+
```xml
|
|
192
|
+
<prop name="campo" type="T"
|
|
193
|
+
ontextchanged="javascript:miFuncion(e);"/>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
2. **El nombre del campo no coincide** en el `<field>`:
|
|
197
|
+
```xml
|
|
198
|
+
<onchange>
|
|
199
|
+
<field name="MAP_CAMPO"> <!-- Debe coincidir exactamente -->
|
|
200
|
+
<action name="runscript">
|
|
201
|
+
<script language="javascript">
|
|
202
|
+
// Código
|
|
203
|
+
</script>
|
|
204
|
+
</action>
|
|
205
|
+
</field>
|
|
206
|
+
</onchange>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
3. **Usando `onchange` como atributo** con valor incorrecto:
|
|
210
|
+
```xml
|
|
211
|
+
<!-- Correcto -->
|
|
212
|
+
<prop name="campo" type="N" onchange="Refresh"/>
|
|
213
|
+
<prop name="campo" type="N" onchange="refresh(campo1,campo2)"/>
|
|
214
|
+
<prop name="campo" type="N" onchange="ExecuteNode(miNodo)"/>
|
|
215
|
+
|
|
216
|
+
<!-- Incorrecto -->
|
|
217
|
+
<prop name="campo" type="N" onchange="true"/>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 19.11 El refresh no funciona
|
|
221
|
+
|
|
222
|
+
**Diagnostico:** Se cambian datos desde JavaScript pero la pantalla no se actualiza.
|
|
223
|
+
|
|
224
|
+
**Posibles causas y soluciones:**
|
|
225
|
+
|
|
226
|
+
1. **Nombre del campo incorrecto** - Verificar que el nombre pasado a `ui.refresh()` coincida exactamente con el `name` del `<prop>`:
|
|
227
|
+
```javascript
|
|
228
|
+
// Si el campo se llama MAP_NOMBRE (no nombre, no NOMBRE)
|
|
229
|
+
ui.refresh("MAP_NOMBRE");
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
2. **Falta obtener la vista** - En callbacks asincranos, usar `ui.getView(self)`:
|
|
233
|
+
```javascript
|
|
234
|
+
var v = ui.getView(self);
|
|
235
|
+
if (v) {
|
|
236
|
+
v.refresh("MAP_CAMPO");
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
3. **Contexto `self` perdido** - En callbacks de `$http` o eventos diferidos, `self` puede ser null. Guardar referencia antes:
|
|
241
|
+
```javascript
|
|
242
|
+
var miObjeto = self; // Guardar antes del callback
|
|
243
|
+
$http.get(url, request,
|
|
244
|
+
function(sData) {
|
|
245
|
+
miObjeto.MAP_RESULTADO = sData;
|
|
246
|
+
ui.refresh("MAP_RESULTADO");
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 19.12 self es null en callback
|
|
252
|
+
|
|
253
|
+
**Diagnostico:** Al acceder a `self` dentro de un callback, da error porque `self` es null o undefined.
|
|
254
|
+
|
|
255
|
+
**Solución:** Guardar la referencia a `self` en una variable local antes del callback:
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
var contexto = self; // Guardar referencia
|
|
259
|
+
$http.get(url, request,
|
|
260
|
+
function(sData) {
|
|
261
|
+
// contexto funciona, self podria no funcionar aqui
|
|
262
|
+
contexto.MAP_DATO = JSON.parse(sData).valor;
|
|
263
|
+
ui.refresh("MAP_DATO");
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 19.13 Coleccion vacia después de loadAll
|
|
269
|
+
|
|
270
|
+
**Diagnostico:** `coll.count()` retorna 0 después de llamar a `loadAll()`.
|
|
271
|
+
|
|
272
|
+
**Posibles causas y soluciones:**
|
|
273
|
+
|
|
274
|
+
1. **Filtro activo demasiado restrictivo** - Verificar y limpiar el filtro:
|
|
275
|
+
```javascript
|
|
276
|
+
coll.setFilter(""); // Limpiar filtro
|
|
277
|
+
coll.loadAll();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
2. **Falta usar startBrowse/endBrowse** para colecciones accedidas externamente:
|
|
281
|
+
```javascript
|
|
282
|
+
var coll = appData.getCollection("MiColeccion");
|
|
283
|
+
try {
|
|
284
|
+
coll.startBrowse();
|
|
285
|
+
coll.loadAll();
|
|
286
|
+
var count = coll.count();
|
|
287
|
+
// ... usar datos ...
|
|
288
|
+
} finally {
|
|
289
|
+
coll.endBrowse();
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
3. **La tabla no existe** en la base de datos. Regenerar con `xone-db-tools create-db`, o inspeccionarla con `xone-db-tools describe-table <db> <tabla> --json` —que devuelve las columnas con su tipo— y consultar el contenido con `xone-db-tools execute-sql <db> "SELECT …" --json`. **Sobre una copia**: `execute-sql` ejecuta lo que le pases y muta el fichero. Detalle de ambos en `xone-review`.
|
|
294
|
+
|
|
295
|
+
### 19.14 lock/unlock no funciona
|
|
296
|
+
|
|
297
|
+
**Diagnostico:** Se obtiene error al intentar modificar una coleccion bloqueada.
|
|
298
|
+
|
|
299
|
+
**Solución:** Verificar que se usa el patron try/finally correctamente:
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// INCORRECTO - si hay error, nunca se ejecuta lock()
|
|
303
|
+
coll.unlock();
|
|
304
|
+
var obj = coll.createObject();
|
|
305
|
+
coll.addItem(obj);
|
|
306
|
+
obj.save();
|
|
307
|
+
coll.lock();
|
|
308
|
+
|
|
309
|
+
// CORRECTO - lock() siempre se ejecuta en finally
|
|
310
|
+
try {
|
|
311
|
+
coll.unlock();
|
|
312
|
+
var obj = coll.createObject();
|
|
313
|
+
coll.addItem(obj);
|
|
314
|
+
obj.save();
|
|
315
|
+
} finally {
|
|
316
|
+
coll.lock();
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 19.15 Evento no se dispara
|
|
321
|
+
|
|
322
|
+
**Diagnostico:** Un evento definido en XML no se ejecuta.
|
|
323
|
+
|
|
324
|
+
**Posibles causas y soluciones:**
|
|
325
|
+
|
|
326
|
+
1. **Nombre del evento incorrecto** - Los nombres de evento son case-sensitive. Verificar que coincida exactamente con el nodo XML.
|
|
327
|
+
|
|
328
|
+
2. **Atributo `refresh` impide ver el efecto** - Si el evento modifica datos pero `refresh="false"`, la UI no se actualiza:
|
|
329
|
+
```xml
|
|
330
|
+
<!-- Probar con refresh="true" para diagnosticar -->
|
|
331
|
+
<miEvento refresh="true" show-wait-dialog="false">
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
3. **El `method` no usa ExecuteNode** correctamente:
|
|
335
|
+
```xml
|
|
336
|
+
<!-- Incorrecto -->
|
|
337
|
+
<prop name="btn" type="B" method="miNodo"/>
|
|
338
|
+
<!-- Correcto -->
|
|
339
|
+
<prop name="btn" type="B" method="ExecuteNode(miNodo)"/>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
4. **Error JavaScript silencioso** - Agregar `show-wait-dialog="true"` temporalmente para ver errores.
|
|
343
|
+
|
|
344
|
+
### 19.16 Campos MAP_ no se guardan
|
|
345
|
+
|
|
346
|
+
**Diagnostico:** Los campos con prefijo `MAP_` pierden su valor al cerrar y volver a abrir la pantalla.
|
|
347
|
+
|
|
348
|
+
**Explicacion:** Los campos `MAP_` son **transitorios** (campos calculados/virtuales). No se persisten en la base de datos. Solo existen en memoria mientras el objeto esta cargado.
|
|
349
|
+
|
|
350
|
+
**Solución:** Si necesitas persistir el dato, usa un campo sin prefijo `MAP_` que tenga su correspondiente columna en la tabla de la base de datos.
|
|
351
|
+
|
|
352
|
+
### 19.17 Error -8100
|
|
353
|
+
|
|
354
|
+
**Diagnostico:** Al intentar guardar un objeto, se obtiene el error `-8100`.
|
|
355
|
+
|
|
356
|
+
**Causa:** Campos obligatorios no completados. El framework valida que todos los campos marcados como obligatorios (`mandatory="true"` o equivalente) tengan valor.
|
|
357
|
+
|
|
358
|
+
**Solución:** Verificar que todos los campos obligatorios tienen un valor antes de llamar a `save()`.
|
|
359
|
+
|
|
360
|
+
### 19.18 Cerrar pantalla / cerrar app desde JavaScript
|
|
361
|
+
|
|
362
|
+
**Forma correcta:**
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
// Cerrar pantalla actual (vuelve a la anterior)
|
|
366
|
+
ui.getView(self).exit();
|
|
367
|
+
|
|
368
|
+
// Cerrar toda la aplicación
|
|
369
|
+
appData.exit();
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Nota sobre código heredado:** En proyectos antiguos puede aparecer el patrón `appData.failWithMessage(-11888, "##EXIT##")` para cerrar la pantalla. Sigue funcionando (el código `-11888` con `##EXIT##` es interpretado por el framework como una orden de cierre, no como un error real), pero la forma preferida es `ui.getView(self).exit()`.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## 20. Glosario de Terminos XOne
|
|
377
|
+
|
|
378
|
+
| Termino | Descripción |
|
|
379
|
+
|---------|-------------|
|
|
380
|
+
| **action** | Bloque de ejecución dentro de un evento. Puede ser `runscript` (JavaScript) o `setval` (asignacion). |
|
|
381
|
+
| **appData** | Objeto global JavaScript para acceder a datos de la aplicación, colecciones y configuración. |
|
|
382
|
+
| **before-edit** | Evento de ciclo de vida que se ejecuta antes de entrar en modo edición. El más usado para inicialización. |
|
|
383
|
+
| **bind** | Método de `ui.getView()` para asignar eventos a controles por script en lugar de por atributo XML. |
|
|
384
|
+
| **coll** | Nodo raiz XML que define una coleccion. Puede representar una tabla de BD, una pantalla o un formulario. |
|
|
385
|
+
| **contents** | Nodo XML que define una relación padre-hijo entre colecciones, para embeber listas dentro de formularios. |
|
|
386
|
+
| **create** | Evento de ciclo de vida que se ejecuta al crear un nuevo objeto. |
|
|
387
|
+
| **CSS (XOne)** | Sistema de estilos propietario similar a CSS web pero con atributos y unidades propios (`p`, `%`). |
|
|
388
|
+
| **DataObject** | Objeto que representa un registro de datos en XOne. Se accede via `self` en scripts. |
|
|
389
|
+
| **disablevisible** | Atributo XML que condiciona la visibilidad de un elemento según el valor de un campo. |
|
|
390
|
+
| **Empresas** | Coleccion obligatoria en `mappings.xne`. Representa la configuración global de la aplicación. |
|
|
391
|
+
| **ExecuteNode** | Función para invocar un evento personalizado desde `method` o `onclick`. |
|
|
392
|
+
| **frame** | Contenedor visual XML para agrupar propiedades y otros frames en el layout. |
|
|
393
|
+
| **functions.js** | Archivo JavaScript global cuyas funciones están disponibles en todos los scripts del proyecto. |
|
|
394
|
+
| **gestion.db** | Archivo de base de datos SQLite local generado en la carpeta `bd/`. |
|
|
395
|
+
| **group** | Nodo XML que agrupa elementos. Se usa para pestanas, secciones y el header/footer fijo. |
|
|
396
|
+
| **group-swipe** | Atributo de `<coll>` que habilita la navegación entre grupos deslizando horizontalmente. |
|
|
397
|
+
| **loadAll()** | Método de coleccion que carga todos los registros desde la base de datos. |
|
|
398
|
+
| **lock/unlock** | Patron obligatorio para modificar contenidos de una coleccion o content. |
|
|
399
|
+
| **maintenance** | Nodo en `Empresas` para definir tareas programadas periódicas (replica, sincronización). |
|
|
400
|
+
| **MAP_** | Prefijo convencional para campos calculados/temporales que no se persisten en BD. |
|
|
401
|
+
| **mapcol** | Atributo para vincular un campo con una coleccion de datos (combo/selector). |
|
|
402
|
+
| **mappings.xne** | Archivo XML que contiene las colecciones `Empresas` y `Usuarios`. |
|
|
403
|
+
| **method** | Atributo de `<prop>` para vincular un botón con un evento custom via `ExecuteNode()`. |
|
|
404
|
+
| **notab** | Atributo de `<coll>` que oculta las pestanas de navegación. |
|
|
405
|
+
| **onback** | Evento que se dispara al presionar el botón de retroceso del dispositivo. |
|
|
406
|
+
| **onchange** | Evento que se dispara cuando cambia el valor de una propiedad. Como nodo permite `<field>`. |
|
|
407
|
+
| **onclick** | Atributo de evento que ejecuta JavaScript al hacer click/tap en un elemento. |
|
|
408
|
+
| **ontextchanged** | Atributo de evento que se dispara en tiempo real al escribir en un campo de texto. |
|
|
409
|
+
| **postonchange** | Atributo que ejecuta una acción después de un cambio de valor, en un segundo paso. |
|
|
410
|
+
| **prop** | Nodo XML que define una propiedad (campo de datos o control de UI). |
|
|
411
|
+
| **recyclerview** | ViewMode recomendado para listas con reciclaje de vistas, mejorando rendimiento. |
|
|
412
|
+
| **refresh** | Función/atributo para actualizar la interfaz de usuario después de cambiar datos. |
|
|
413
|
+
| **replica** | Sistema de sincronización bidireccional entre el dispositivo y el servidor. |
|
|
414
|
+
| **ROWID** | Campo interno de la plataforma (existe a nivel BD en toda coll persistida como GUID hex de 32 caracteres). NO se declara como `<prop>` ni se incluye en el SELECT del `sql=`. XOne lo gestiona automáticamente. |
|
|
415
|
+
| **runscript** | Tipo de acción dentro de un evento que ejecuta código JavaScript. |
|
|
416
|
+
| **self** | Objeto global JavaScript que referencia al DataObject actual en el contexto del script. |
|
|
417
|
+
| **setval** | Tipo de acción dentro de un evento que asigna un valor a un campo sin JavaScript. |
|
|
418
|
+
| **special** | Atributo de `<coll>`: el framework NO gestiona automáticamente los datos de esa coleccion — no ejecuta su `sql=` contra la BD ni contra su conexión. De ahí sus dos usos: una pantalla de puro UI (menú, buscador, coll base para `inherits`) y una coleccion que se llena desde script (por ejemplo con `addItem` tras llamar a una API) para pintarla en un `<contents>` o buscar sobre ella. **No confundir con `<entry-point>`**, que es el nodo de `app.xml` que dice qué coleccion se abre al entrar; esa coll suele ser `special`, pero son cosas distintas. Síntoma típico: `special` junto a `sql` da pantalla vacía, porque el `sql` no se ejecuta. |
|
|
419
|
+
| **sql** | Atributo de `<coll>` con la consulta SQL para cargar datos de la tabla. |
|
|
420
|
+
| **type** | Atributo de `<prop>` que define el tipo de dato/control (T, N, B, D, IMG, PH, Z, etc.). |
|
|
421
|
+
| **ui** | Objeto global JavaScript para interfaz de usuario: dialogos, navegación, GPS, camara. |
|
|
422
|
+
| **Usuarios** | Coleccion obligatoria en `mappings.xne` para la gestion de usuarios de la aplicación. |
|
|
423
|
+
| **viewmode** | Atributo de `<prop type="Z">` que define como se visualiza un content (recyclerview, mapview, etc.). |
|
|
424
|
+
| **visible** | Atributo bitmask (0-7) que controla en que modos se muestra una propiedad. |
|
|
425
|
+
| **xne** | Extensión de los archivos XML de XOne que definen colecciones y pantallas. |
|
|
426
|
+
| **##FLD_CAMPO##** | Macro que referencia el valor de un campo en filtros SQL de contents. |
|
|
427
|
+
| **##NOW_TIME##** | Macro del sistema que retorna la fecha y hora actual. |
|
|
428
|
+
| **##PREF##** | Macro que se reemplaza por el prefijo de tabla configurado (típicamente `gen_`). |
|
|
429
|
+
| **##USERID##** | Macro del sistema que retorna el ID del usuario logueado. |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xone-development
|
|
3
|
+
description: "Desarrollo XOne: XML .xne, JS del runtime, CSS, datos, dispositivo, fundamentos. UI/.xne: colecciones, props/tipos, groups, frames, contents, asfilter, combos mapcol/mapfld, mapas, kanban, chips, Lottie en IMG, layouts, inherits, include-layout, eventos XML, permisos. JS y functions.js: self, selfDataColl, ui, appData, err, user, getControl, métodos de controles, singletons, creables, lock/unlock, startBrowse/endBrowse, objeto ai. CSS: default.css, clases, selectores coll/prop:TYPE/group/frame, unidades p/%, colores #AARRGGBB, extends/@extend, :root/var(), calc(), @import, temas light/dark, animaciones. Datos: SQL ##PREF##, SqlManager, macros, $http TLS/pinning/mTLS, futures, OAuth2, crypto. Dispositivo: GPS, cámara, foto/vídeo, QR/barcode, scanDocument, OCR recognizeText, firma DR, biometría, Bluetooth, impresión, NFC, DNI electrónico. Fundamentos: app.xml, app.ini, mappings.xne, bd/icons/files/fonts, macros, códigos de error, Splash→Login→EntradaApp→Menu, convenciones de nombres."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XOne — Desarrollo (XML, JavaScript, CSS, datos y dispositivo)
|
|
7
|
+
Estas son las reglas que aplican a cualquier trabajo sobre un proyecto XOne, sea XML, JavaScript o CSS. **No afirmes nada que no esté en las referencias de esta skill o de las especializadas.** Si una API, atributo o comportamiento no aparece, dilo y pide el dato; no lo deduzcas por analogía con la web ni con otros frameworks.
|
|
8
|
+
|
|
9
|
+
## Referencias
|
|
10
|
+
|
|
11
|
+
**Este `SKILL.md` es la referencia CORTA y lleva solo las reglas duras.** Una lectura por
|
|
12
|
+
omisión trae **100 líneas** (`DEFAULT_READ_LIMIT` de deepagents) y este fichero tenía 395, así
|
|
13
|
+
que el índice y los anti-patrones no se leían salvo que el modelo pidiera `limit=1000` — lo
|
|
14
|
+
hacía la mitad de las veces (dorado con control, 2026-08-24). Ahora todo lo consultable vive
|
|
15
|
+
al lado, y cada fichero cabe entero:
|
|
16
|
+
|
|
17
|
+
| Qué buscas | Dónde |
|
|
18
|
+
|---|---|
|
|
19
|
+
| **El índice COMPLETO** de las 55 referencias, por familia | [references/indice-completo.md](references/indice-completo.md) |
|
|
20
|
+
| **Tipos de `prop` válidos** (la tabla) | [references/tipos-de-prop.md](references/tipos-de-prop.md) |
|
|
21
|
+
| **Anti-patrones**: lo que NO hay que hacer, con el porqué | [references/anti-patrones.md](references/anti-patrones.md) |
|
|
22
|
+
| Resumen de la capa XML y de la capa CSS | [references/resumen-xml-y-css.md](references/resumen-xml-y-css.md) |
|
|
23
|
+
| Resumen de JavaScript, datos e integración y dispositivo | [references/resumen-js-datos-dispositivo.md](references/resumen-js-datos-dispositivo.md) |
|
|
24
|
+
|
|
25
|
+
Las cinco familias del detalle están en `references/`: `fundamentos/`, `xml-ui/`,
|
|
26
|
+
`javascript/`, `css/`, `datos/` y `dispositivo/`.
|
|
27
|
+
|
|
28
|
+
## Siempre
|
|
29
|
+
|
|
30
|
+
1. **Consulta la referencia antes de responder.** Cada área tiene su fichero; están indexados abajo y en las skills especializadas.
|
|
31
|
+
2. **La fuente es el `.xne`.** Los ficheros `.xml` de colecciones y pantallas son artefactos generados automáticamente por XOneStudio a partir de los `.xne`: no se leen, no se editan, no se consultan. La única excepción es `app.xml`, que sí es fuente. Si conviven `.xne` y `.xml`, trabaja solo sobre los `.xne`.
|
|
32
|
+
3. **`progid` es opcional.** Sin él, la coll es un objeto de datos genérico (equivalente a `ASData.CASBasicDataObj`). Solo **Empresas** (`ASGestion.CASEmpresa`) y **Usuarios** (`ASGestion.CASUser`) requieren el suyo para activar su lógica de negocio. No inventes progids. **Conflicto conocido sin resolver:** `xone-simulator` lo marca como error (`COLL_MISSING_PROGID`) pese a ser opcional según lo anterior. No resuelvas la discrepancia por tu cuenta: repórtala y deja la decisión al desarrollador.
|
|
33
|
+
4. **Encoding coherente en los `.xne`.** El motor respeta el `encoding` declarado en el prólogo y asume UTF-8 si falta. UTF-8 e iso-8859-15 son válidos; lo que corrompe tildes y eñes es declarar uno y guardar en otro.
|
|
34
|
+
5. **`ID` y `ROWID` los gestiona la plataforma.** No hace falta declararlos como `<prop>` (es válido pero redundante). En el `sql=` de la coll, `ID` sí se rescata en el SELECT; `ROWID` no es necesario.
|
|
35
|
+
6. **Inicializa con el evento correcto:** `<before-edit>` al abrir para editar, `<create>` la primera vez. `<load>` se dispara **por cada DataObject** al cargar desde la BD (startBrowse, loadAll, `<contents>`) y no se recomienda por rendimiento.
|
|
36
|
+
7. **Los nombres son únicos y case-sensitive.** Ver la sección de unicidad más abajo.
|
|
37
|
+
|
|
38
|
+
## Nunca
|
|
39
|
+
|
|
40
|
+
1. **No inventes** atributos XML, funciones JavaScript ni propiedades CSS que no estén en las referencias. XOne ignora silenciosamente los atributos desconocidos, así que un invento no da error: da un bug silencioso.
|
|
41
|
+
2. **No uses APIs del DOM.** No existen: `document`, `window`, `localStorage`, `sessionStorage`, `XMLHttpRequest`, `navigator`, `history`.
|
|
42
|
+
3. **No uses VBScript.** Está descontinuado en XOne aunque alguna referencia histórica lo mencione. La única opción válida es `<script language="javascript">`; si encuentras un ejemplo en VBScript, tradúcelo antes de proponerlo.
|
|
43
|
+
4. **No mezcles patrones de React, Angular, Vue** ni de ningún framework web.
|
|
44
|
+
5. **No repitas nombres de nodos dentro de la misma colección.**
|
|
45
|
+
6. **No uses `<load>`** para inicializar una pantalla: produce bugs silenciosos.
|
|
46
|
+
|
|
47
|
+
## Sintaxis JavaScript que soporta el motor
|
|
48
|
+
|
|
49
|
+
**Sí:** `let`, `const`, arrow functions, destructuring, `class` (con `extends`, `super`, `static`, getters/setters, computed keys, field declarations y generator methods con `*`), `Promise` (ES2024 completo: `all`, `allSettled`, `race`, `any`, `withResolvers`, `.then`, `.catch`, `.finally`), generadores con `yield` (runtime estilo SpiderMonkey legacy: `.next()` devuelve el valor directo y `StopIteration`; no `for...of` sobre generadores), `for...of` sobre arrays y strings, `Symbol`, typed arrays.
|
|
50
|
+
|
|
51
|
+
**No, a nivel de sintaxis:** template literals `` `${x}` ``, `async`/`await`, spread/rest, parámetros por defecto, optional chaining `?.`, nullish coalescing `??`, computed keys en object literals (sí en cuerpo de clase), campos privados `#name`, bloques `static`.
|
|
52
|
+
|
|
53
|
+
**Sí existen con implementación custom de XOne** (semántica compatible con WHATWG): `fetch(input, init?)` con limitaciones (no admite `Request` como primer argumento, ni body `FormData`/`Blob`/`ReadableStream`, ni cancelación real en vuelo), `setTimeout`/`clearTimeout`/`setInterval`/`clearInterval`/`queueMicrotask`, `URL`/`URLSearchParams`, `Headers`, `AbortController`/`AbortSignal`, `Response`, `EventTarget`, `TextEncoder`/`TextDecoder`, `console` completo (`log`, `info`, `debug`, `warn`, `error`, `trace`, `assert`, `group`, `time`, `table`… con formato `%s`/`%d`/`%j`), `performance.now()`, `atob`/`btoa`, `structuredClone`, `DOMParser`/`XMLSerializer`, `globalThis`.
|
|
54
|
+
|
|
55
|
+
Aun existiendo, lo idiomático en XOne es `$http` en vez de `fetch`, y `ui.executeActionAfterDelay` en vez de `setTimeout`.
|
|
56
|
+
|
|
57
|
+
## Unicidad y nombres
|
|
58
|
+
|
|
59
|
+
- El ámbito de unicidad es la **`<coll>` entera**, no el `<group>` ni el `<frame>`: no puede haber dos `<prop>`, dos `<group>`, dos `<frame>` ni dos eventos con el mismo `name` en ninguna parte de la misma coll, aunque estén en grupos distintos. El `name` se publica a nivel de coll (los `collprops`) y se volvería ambiguo.
|
|
60
|
+
- Dos `<coll>` distintas **sí** pueden tener contenido idéntico, siempre que su propio `name` sea distinto. Dos colls con el mismo `name` en el proyecto no son válidas.
|
|
61
|
+
- El atributo `name` es **case-sensitive**, y eso aplica a todas las referencias cruzadas: `self.MiNombre`, `mapcol`, `linkedto`, `inherits`, `<field name="...">`, `getControl("...")`, `ui.openEditView("...")`, `appData.getCollection("...")`.
|
|
62
|
+
- En cada `<group>`, `id` es obligatorio y único dentro de la coll. Convención habitual: `1`, `2`, `3`… para grupos normales, `999` para HEADER fijo y `0` para FOOTER fijo.
|
|
63
|
+
- Prefijo `MAP_`: significa que el prop **no es columna de la tabla de `objname`**, así que el framework lo excluye de INSERT y UPDATE. Lo llevan los alias de JOIN (`c.NOMBRE AS MAP_NOMBRECLIENTE`), la descripción visible de un combo con `linkedto`, y los props puramente visuales (labels, botones, totales, estados de UI). **El fallo es simétrico**: ponérselo a una columna real pierde el dato al guardar; omitirlo en un alias o en la descripción de un combo da error SQL al actualizar una columna inexistente. Detalle en [convenciones](references/fundamentos/navegacion-convenciones-y-primer-proyecto.md).
|
|
64
|
+
|
|
65
|
+
## Visibilidad
|
|
66
|
+
|
|
67
|
+
Bitmask de 4 bits: `1` edición · `2` lista · `4` content · `8` combo. Cualquier combinación es válida.
|
|
68
|
+
|
|
69
|
+
| Valor | Contextos |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `0` | Ninguno: campo interno, solo para lógica |
|
|
72
|
+
| `1` | Solo formulario de edición |
|
|
73
|
+
| `2` | Solo lista |
|
|
74
|
+
| `3` | Edición + lista |
|
|
75
|
+
| `4` | Solo content (lista embebida) |
|
|
76
|
+
| `7` | Edición + lista + content — **el más habitual** |
|
|
77
|
+
| `8` | Solo combo |
|
|
78
|
+
| `15` | Todos |
|
|
79
|
+
|
|
80
|
+
`visible` es **estático**: no se cambia en runtime, ni por script ni por eventos. Para visibilidad condicional se usa `disablevisible="CAMPO=valor"`, que sí es dinámico.
|
|
81
|
+
|
|
82
|
+
## Ciclo de vida y eventos
|
|
83
|
+
|
|
84
|
+
| Necesito | Evento |
|
|
85
|
+
|---|---|
|
|
86
|
+
| Inicializar la primera vez | `<create>` |
|
|
87
|
+
| Inicializar al abrir para editar | `<before-edit>` |
|
|
88
|
+
| Ejecutar tras entrar en edición | `<after-edit>` |
|
|
89
|
+
| Reaccionar a cada ítem al cargar una colección (no recomendado) | `<load>` |
|
|
90
|
+
| Cambio de campo | `<onchange>` + `<field name="CAMPO">` |
|
|
91
|
+
| Botón atrás | `<onback>` |
|
|
92
|
+
|
|
93
|
+
No existen `<unload>`, `<ondelete>`, `<beforedelete>` ni `<afterdelete>`. Para borrado hay `<delete>` con hijos `<rule>`, que es un bloque de reglas, no un evento antes/después. Solo puede haber un `<before-edit>` por coll.
|
|
94
|
+
|
|
95
|
+
- **No uses `<load>` para inicializar pantallas**: se dispara por cada DataObject cargado. `xone-simulator` lo marca como `ANTIPATTERN_LOAD_EVENT`.
|
|
96
|
+
- Solo un `<before-edit>` por coll (`ANTIPATTERN_MULTIPLE_BEFORE_EDIT`).
|
|
97
|
+
- En un botón, `onclick` **o** `method="ExecuteNode(...)"`, nunca ambos. Para lógica compleja, `ExecuteNode` y un nodo aparte.
|
|
98
|
+
- `onchange="refresh"` o `onchange="refresh(MAP_CAMPO)"`; `refresh255` es notación legacy de PDA.
|
|
99
|
+
|
|
100
|
+
El **catálogo de eventos** (cuándo dispara cada uno, con qué parámetros) vive con el XML, porque los eventos se declaran en el XML: [eventos de ciclo de vida e interacción](references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md) (`create`, `before-edit`, `after-edit`, `load`, `onclick`, `onchange`, `selecteditem`, `onlongpressitem`, `onback`) y [eventos de sistema, login y personalizados](references/xml-ui/eventos-sistema-login-y-personalizados.md) (drawer, bottom sheet, login, `onpushreceived`, `maintenance`, `sys-message` y sus códigos, ciclo de aplicación, `ExecuteNode` y acciones).
|
|
101
|
+
|
|
102
|
+
## JavaScript embebido en `.xne`
|
|
103
|
+
|
|
104
|
+
Para JS no trivial, la forma preferida es declarar la función en un `.js` externo (`functions.js` u otro incluido) y llamarla desde el XML con `miFuncion();`, escribiendo el JS normal, sin entidades ni CDATA. Para snippets cortos inline: dentro de un nodo `<script>` valen tanto entidades XML (`<`, `>`, `&`) como `<![CDATA[…]]>`; dentro de un atributo (`onclick=`, `disablevisible=`) **solo entidades**, porque CDATA no es válido en atributos XML.
|
|
105
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Anti-patrones
|
|
2
|
+
|
|
3
|
+
> Referencia de `xone-development`. Sale del `SKILL.md` para que las reglas
|
|
4
|
+
> duras quepan en una lectura por omisión (100 líneas).
|
|
5
|
+
|
|
6
|
+
## Anti-patrones
|
|
7
|
+
|
|
8
|
+
### XML
|
|
9
|
+
| Incorrecto | Correcto |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `<prop type="C">` (combo) | `type="T"` + `mapcol` + `mapfld` |
|
|
12
|
+
| `<prop type="M">` (mapa) | `type="Z" viewmode="mapview"` |
|
|
13
|
+
| `<prop type="A">` (autocomplete) | `type="T"` + `mapcol` + `mapfld` + `linkedfield` |
|
|
14
|
+
| `<prop type="IMG" readonly="false">` (firma obsoleta) | `<prop type="DR">` |
|
|
15
|
+
| `<prop type="L" labelwidth="0" title="X">` | `<prop type="L" title="X" label-align="center">` — con `labelwidth="0"` el título se pinta en un ancho de cero |
|
|
16
|
+
| `<prop type="L" title="...">` esperando que muestre el valor que actualiza el JS | `<prop type="L">` **sin `title`**: el label usa el valor del campo como fallback |
|
|
17
|
+
| `newline="false"` en el primer elemento de un frame | Solo en el segundo y siguientes |
|
|
18
|
+
| `<prop name="PASSWORD" type="X">` en Usuarios | `<prop name="PWD" type="X">` — el framework lo lee literalmente |
|
|
19
|
+
| `<prop name="ID_EMPRESA">` en Usuarios | `<prop name="IDEMPRESA">` — sin guion bajo |
|
|
20
|
+
| Dos `<group id="1">` en la misma coll | `id` único por coll |
|
|
21
|
+
| Dos `<prop name="X">` en la misma coll, aunque estén en grupos distintos | `name` único en la coll entera |
|
|
22
|
+
| `special="true"` junto con `sql` | Son excluyentes |
|
|
23
|
+
| Contents sin prefijo `@` | `contents="@MiContent"` |
|
|
24
|
+
| `loadall="true"` en tablas grandes | Carga bajo demanda |
|
|
25
|
+
| Mezclar `onclick` y `method` en un botón | Uno u otro |
|
|
26
|
+
|
|
27
|
+
### JavaScript: APIs y patrones
|
|
28
|
+
| Incorrecto | Correcto |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `self("CAMPO")` | `self.CAMPO`, `self["CAMPO"]` o `self.getValue("CAMPO")` |
|
|
31
|
+
| `self.lock()` / `self.unlock()` | Son de la colección: `self.getContents("X").unlock()` |
|
|
32
|
+
| `coll.macro("##N##", v)` | `coll.setMacro("##N##", v)` / `getMacro` |
|
|
33
|
+
| `setMacro` sin declarar la macro en el XML | Declarar `<macro name="##N##" value="..." default="true" />` en la coll |
|
|
34
|
+
| `deviceInfo.getMobileNetworkSignalStrengh()` | `getMobileNetworkSignalStrength()` (sin el typo) |
|
|
35
|
+
| `ui.executeActionAfterDelay("X", 2000)` creyendo que son ms | El segundo parámetro va en **segundos**: `("X", 2)` |
|
|
36
|
+
| Encadenar `executeActionAfterDelay` como `setInterval` | `control.startChronometer({fromDate, dateFormat})` |
|
|
37
|
+
| `ui.startChronometer({...})` | Es del control: `getControl("MAP_T").startChronometer({...})` |
|
|
38
|
+
| `ui.setFieldPropertyValue(...)` / `ui.getFieldPropertyValue(...)` | Son de `self`. Y el cambio no repinta solo: llama a `ui.refresh(prop)` después |
|
|
39
|
+
| `self.X` dentro de un callback asíncrono | Guardar `var miSelf = self;` antes |
|
|
40
|
+
| `startBrowse()` sin `endBrowse()` en `finally` | `try { … } finally { coll.endBrowse(); }` |
|
|
41
|
+
| `appData.executeSql("… WHERE ID=" + id)` | `sqlManager.doRawQuery("… WHERE ID=?", id)` |
|
|
42
|
+
| `ui.setBlur(...)` / `ui.setSaturation(...)` | No son de `ui` ni de XOne: los expone la **vista nativa** que hay debajo. Se llaman sobre el frame o el control — `ui.getView(self)["mi_frame"].setBlur(8)`. Ver [métodos nativos de la vista](references/javascript/metodos-nativos-de-la-vista.md) |
|
|
43
|
+
| `GpsCollection` como colección built-in | La declara el proyecto con connector GPS |
|
|
44
|
+
| Variantes de `setCircularReveal` (Show/Hide, setXY, growAndShrink) | Solo existe `setCircularReveal(cx, cy, bReveal)` |
|
|
45
|
+
|
|
46
|
+
### JavaScript: creación de objetos
|
|
47
|
+
| Incorrecto | Correcto |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `appData.createObject("XOneFileManager")` | `new FileManager()` |
|
|
50
|
+
| `appData.createObject("Http")` | Singleton `$http` |
|
|
51
|
+
| `appData.createObject("Crypto")` / `new Crypto()` | Singleton `crypto` |
|
|
52
|
+
| `appData.createObject("DeviceInfo")` / `new DeviceInfo()` | Singleton `deviceInfo` |
|
|
53
|
+
| `appData.createObject("SystemSettings")` / `new SystemSettings()` | Singleton `systemSettings` |
|
|
54
|
+
| `appData.createObject("XOneClipboard")` | Singleton `clipboard` |
|
|
55
|
+
| `appData.createObject("XOneBiometricsManager")` | Singleton `biometricsManager` |
|
|
56
|
+
| `appData.createObject("ScriptSensorManager")` | Singleton `sensorManager` |
|
|
57
|
+
| `appData.createObject("XOnePackageManager")` | Singleton `packageManager` |
|
|
58
|
+
| `appData.createObject("XOneWifiManager")` | `new WifiManager()` |
|
|
59
|
+
| `appData.createObject("ScriptOauth2")` | `new OAuth2()` |
|
|
60
|
+
| `appData.createObject("WebWorker")` | `new Worker()` |
|
|
61
|
+
| `appData.createObject("XOneSocket")` / `XOneWebSocket` / `XOneDebugTools` | `new Socket()` / `new WebSocket()` / `new DebugTools()` |
|
|
62
|
+
| `appData.createObject("Encoder")` | `new EncodingUtils()` — «Encoder» no existe |
|
|
63
|
+
| `new Packages.com.xone.android.script.runtimeobjects.IniParser()` | `new IniParser()` |
|
|
64
|
+
|
|
65
|
+
### CSS
|
|
66
|
+
| Incorrecto | Correcto |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `font-size: 14px` | `fontsize: 14` |
|
|
69
|
+
| `bg-color: #FFF` | `bgcolor: #FFFFFF` |
|
|
70
|
+
| `#00000080` (alpha al final) | `#80000000` (ARGB) |
|
|
71
|
+
| `margin: 10p` | `tmargin: 10p; bmargin: 10p; …` |
|
|
72
|
+
| `div.header { }` | `.header { }` |
|
|
73
|
+
| Duplicar atributos entre clases | `extends: .base;` y sobrescribir |
|
|
74
|
+
| `display: none` | `visible` (bitmask) |
|
|
75
|
+
| `box-shadow` | `elevation` + `shadow-color` |
|
|
76
|
+
|
|
77
|
+
### Datos
|
|
78
|
+
| Incorrecto | Correcto |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `gen_` literal en XML o SQL portable | `##PREF##` |
|
|
81
|
+
| SQL concatenado con entrada externa | Parámetros `?` |
|
|
82
|
+
| Cursor o conexión sin cerrar | `finally` |
|
|
83
|
+
| `allowUnsafeCertificates: true` en producción | Verificación TLS |
|
|
84
|
+
| Token en claro en logs o macros | Cifrado, limpieza y sin logging |
|
|
85
|
+
|
|
86
|
+
### Dispositivo
|
|
87
|
+
| Incorrecto | Correcto |
|
|
88
|
+
|---|---|
|
|
89
|
+
| Leer GPS sin iniciarlo ni pedir permiso | `startGps` + `checkGpsStatus` + permiso |
|
|
90
|
+
| Aceptar cualquier coordenada | `STATUS == 1` y longitud válida |
|
|
91
|
+
| `fingerprintManager` en código nuevo | `biometricsManager` |
|
|
92
|
+
| Bloquear la UI esperando | `ui.executeActionAfterDelay` |
|
|
93
|
+
| Dejar conexiones abiertas | `disconnect`/`close` al salir |
|
|
94
|
+
| Asumir que el simulador tiene datos de hardware | Configurar `mock/device.json` |
|