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.
Files changed (187) hide show
  1. package/README.md +167 -0
  2. package/dist/agent/authEnDisco.js +56 -0
  3. package/dist/agent/authEnDisco.js.map +1 -0
  4. package/dist/agent/configEnDisco.js +109 -0
  5. package/dist/agent/configEnDisco.js.map +1 -0
  6. package/dist/agent/crearProyecto.js +34 -0
  7. package/dist/agent/crearProyecto.js.map +1 -0
  8. package/dist/agent/entorno.js +124 -0
  9. package/dist/agent/entorno.js.map +1 -0
  10. package/dist/agent/guionizado.js +53 -0
  11. package/dist/agent/guionizado.js.map +1 -0
  12. package/dist/agent/instantanea.js +129 -0
  13. package/dist/agent/instantanea.js.map +1 -0
  14. package/dist/agent/interrupts.js +83 -0
  15. package/dist/agent/interrupts.js.map +1 -0
  16. package/dist/agent/mensajes.js +24 -0
  17. package/dist/agent/mensajes.js.map +1 -0
  18. package/dist/agent/modelos.js +42 -0
  19. package/dist/agent/modelos.js.map +1 -0
  20. package/dist/agent/normalizar.js +20 -0
  21. package/dist/agent/normalizar.js.map +1 -0
  22. package/dist/agent/perfiles.js +103 -0
  23. package/dist/agent/perfiles.js.map +1 -0
  24. package/dist/agent/proyecto.js +107 -0
  25. package/dist/agent/proyecto.js.map +1 -0
  26. package/dist/agent/puente.js +142 -0
  27. package/dist/agent/puente.js.map +1 -0
  28. package/dist/agent/resumenDeTool.js +48 -0
  29. package/dist/agent/resumenDeTool.js.map +1 -0
  30. package/dist/agent/skills.js +65 -0
  31. package/dist/agent/skills.js.map +1 -0
  32. package/dist/agent/textoDeTool.js +113 -0
  33. package/dist/agent/textoDeTool.js.map +1 -0
  34. package/dist/agent/turnoReal.js +173 -0
  35. package/dist/agent/turnoReal.js.map +1 -0
  36. package/dist/agent/verificador.js +65 -0
  37. package/dist/agent/verificador.js.map +1 -0
  38. package/dist/agent/xoneAgent.js +106 -0
  39. package/dist/agent/xoneAgent.js.map +1 -0
  40. package/dist/bin.js +9 -0
  41. package/dist/bin.js.map +1 -0
  42. package/dist/cli/aprobar.js +82 -0
  43. package/dist/cli/aprobar.js.map +1 -0
  44. package/dist/cli/config.js +133 -0
  45. package/dist/cli/config.js.map +1 -0
  46. package/dist/cli/consola.js +346 -0
  47. package/dist/cli/consola.js.map +1 -0
  48. package/dist/cli/describe.js +53 -0
  49. package/dist/cli/describe.js.map +1 -0
  50. package/dist/cli/doctor.js +45 -0
  51. package/dist/cli/doctor.js.map +1 -0
  52. package/dist/cli/main.js +520 -0
  53. package/dist/cli/main.js.map +1 -0
  54. package/dist/cli/markdown.js +90 -0
  55. package/dist/cli/markdown.js.map +1 -0
  56. package/dist/cli/run.js +164 -0
  57. package/dist/cli/run.js.map +1 -0
  58. package/dist/cli/spinner.js +89 -0
  59. package/dist/cli/spinner.js.map +1 -0
  60. package/dist/cli/stdio.js +193 -0
  61. package/dist/cli/stdio.js.map +1 -0
  62. package/dist/cli/tema.js +40 -0
  63. package/dist/cli/tema.js.map +1 -0
  64. package/dist/cli/verify.js +62 -0
  65. package/dist/cli/verify.js.map +1 -0
  66. package/dist/core/bitacora.js +30 -0
  67. package/dist/core/bitacora.js.map +1 -0
  68. package/dist/core/config.js +236 -0
  69. package/dist/core/config.js.map +1 -0
  70. package/dist/core/contextos.js +56 -0
  71. package/dist/core/contextos.js.map +1 -0
  72. package/dist/core/deps.js +51 -0
  73. package/dist/core/deps.js.map +1 -0
  74. package/dist/core/diff.js +79 -0
  75. package/dist/core/diff.js.map +1 -0
  76. package/dist/core/esqueleto.js +366 -0
  77. package/dist/core/esqueleto.js.map +1 -0
  78. package/dist/core/events.js +2 -0
  79. package/dist/core/events.js.map +1 -0
  80. package/dist/core/modelos.js +85 -0
  81. package/dist/core/modelos.js.map +1 -0
  82. package/dist/core/notify.js +106 -0
  83. package/dist/core/notify.js.map +1 -0
  84. package/dist/core/ports.js +114 -0
  85. package/dist/core/ports.js.map +1 -0
  86. package/dist/core/turno.js +127 -0
  87. package/dist/core/turno.js.map +1 -0
  88. package/dist/vendor/hitl.js +103 -0
  89. package/dist/vendor/hitl.js.map +1 -0
  90. package/dist/vendor/skillLoaders/catalog.js +74 -0
  91. package/dist/vendor/skillLoaders/catalog.js.map +1 -0
  92. package/dist/vendor/tokenTracking.js +58 -0
  93. package/dist/vendor/tokenTracking.js.map +1 -0
  94. package/package.json +41 -0
  95. package/skills/xone-debugging/SKILL.md +52 -0
  96. package/skills/xone-debugging/references/faq.md +561 -0
  97. package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
  98. package/skills/xone-development/SKILL.md +105 -0
  99. package/skills/xone-development/references/anti-patrones.md +94 -0
  100. package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
  101. package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
  102. package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
  103. package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
  104. package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
  105. package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
  106. package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
  107. package/skills/xone-development/references/datos/appdata.md +611 -0
  108. package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
  109. package/skills/xone-development/references/datos/http.md +366 -0
  110. package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
  111. package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
  112. package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
  113. package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
  114. package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
  115. package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
  116. package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
  117. package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
  118. package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
  119. package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
  120. package/skills/xone-development/references/indice-completo.md +77 -0
  121. package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
  122. package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
  123. package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
  124. package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
  125. package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
  126. package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
  127. package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
  128. package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
  129. package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
  130. package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
  131. package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
  132. package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
  133. package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
  134. package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
  135. package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
  136. package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
  137. package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
  138. package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
  139. package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
  140. package/skills/xone-development/references/tipos-de-prop.md +28 -0
  141. package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
  142. package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
  143. package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
  144. package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
  145. package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
  146. package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
  147. package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
  148. package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
  149. package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
  150. package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
  151. package/skills/xone-development/references/xml-ui/mapas.md +685 -0
  152. package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
  153. package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
  154. package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
  155. package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
  156. package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
  157. package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
  158. package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
  159. package/skills/xone-plan-builder/SKILL.md +183 -0
  160. package/skills/xone-plan-builder/agents/openai.yaml +5 -0
  161. package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
  162. package/skills/xone-project-generator/SKILL.md +111 -0
  163. package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
  164. package/skills/xone-project-generator/references/colecciones-base.md +16 -0
  165. package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
  166. package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
  167. package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
  168. package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
  169. package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
  170. package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
  171. package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
  172. package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
  173. package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
  174. package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
  175. package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
  176. package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
  177. package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
  178. package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
  179. package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
  180. package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
  181. package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
  182. package/skills/xone-review/SKILL.md +189 -0
  183. package/skills/xone-spec-builder/SKILL.md +235 -0
  184. package/skills/xone-spec-builder/agents/openai.yaml +5 -0
  185. package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
  186. package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
  187. package/skills/xone-spec-builder/references/PLAN-FORMAT.md +120 -0
@@ -0,0 +1,944 @@
1
+ # XOne — Eventos: interacción avanzada, login, sistema y personalizados
2
+
3
+ > Fuente: `xone/v2/xone-help-docs/topics/05-events-patterns-faq.md` §3A–§8. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: §3A drawer y bottom sheet · §4 eventos de login · §5 eventos del sistema (onpushreceived, maintenance, sys-message) · §5A ciclo de aplicación · §5B inactividad · §5D códigos sys-message · §6 réplica · §7 eventos personalizados con ExecuteNode y param · §8 acciones runscript y setval
6
+
7
+ ---
8
+
9
+ ## 3A. Eventos Adicionales de Interaccion
10
+
11
+ ### 3A.1 onlongpress - Pulsacion larga en un prop
12
+
13
+ **Ambito:** property | **Tipo:** atributo
14
+
15
+ Se dispara cuando el usuario mantiene pulsado un control individual (a diferencia de `onlongpressitem` que opera sobre items de lista).
16
+
17
+ ```xml
18
+ <prop name="BTN_OPCIONES" type="B" title="Opciones"
19
+ onlongpress="javascript:mostrarMenu();"/>
20
+ ```
21
+
22
+ ### 3A.2 onlongpressitem - Pulsacion larga en item de lista
23
+
24
+ **Ambito:** property | **Tipo:** atributo
25
+
26
+ Se dispara cuando el usuario mantiene pulsado un item dentro de un content/lista. Recibe la posición del item en `e.position`.
27
+
28
+ ```xml
29
+ <prop name="@miLista" type="Z" contents="miLista"
30
+ onlongpressitem="javascript:mostrarMenu(e.position);"/>
31
+ ```
32
+
33
+ ### 3A.3 oneditoraction - Acción de teclado (Done/Next)
34
+
35
+ **Ambito:** property | **Tipo:** atributo
36
+
37
+ Se dispara cuando el usuario pulsa la tecla Intro, Done o Siguiente en el teclado virtual. Útil para formularios de login o busqueda donde se quiere ejecutar una acción al confirmar.
38
+
39
+ ```xml
40
+ <prop name="MAP_CONTRASENNA" type="X" title="Contraseña"
41
+ oneditoraction="javascript:oneditoraction(self, 0, 'MAP_CONTRASENNA');"/>
42
+ ```
43
+
44
+ ```javascript
45
+ function oneditoraction(obj, action, fieldName) {
46
+ if (fieldName == "MAP_CONTRASENNA") {
47
+ obj.executeNode("doLogin");
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### 3A.4 oncodescanned - Código escaneado (QR/Barcode)
53
+
54
+ **Ambito:** property | **Tipo:** atributo
55
+
56
+ Se dispara cuando se completa el escaneo de un código QR o de barras.
57
+
58
+ ```xml
59
+ <prop name="MAP_SCANNER" type="T"
60
+ oncodescanned="procesarCodigo(e);"/>
61
+ ```
62
+
63
+ ```javascript
64
+ function procesarCodigo(e) {
65
+ self.MAP_CODIGO = e.data; // contenido del código (e.type indica el formato: qr, datamatrix, etc.)
66
+ ui.refresh("MAP_CODIGO");
67
+ ui.showToast("Código leído: " + e.data);
68
+ }
69
+ ```
70
+
71
+ ### 3A.5 ondateselected - Fecha seleccionada en calendario
72
+
73
+ **Ambito:** property (tipo Z con viewmode calendario) | **Tipo:** atributo
74
+
75
+ Se dispara cuando el usuario selecciona una fecha en un control de calendario. Recibe el parámetro `date`.
76
+
77
+ ```xml
78
+ <prop name="MAP_CALENDARIO" type="Z" contents="contentCalendario"
79
+ viewmode="calendarview"
80
+ ondateselected="javascript:onFechaSeleccionada(e);"/>
81
+ ```
82
+
83
+ **Ejemplo real** (del proyecto EspecialCalendario, como nodo):
84
+
85
+ ```xml
86
+ <ondateselected show-wait-dialog="false">
87
+ <action name="runscript">
88
+ <param name="date"/>
89
+ <script language="javascript">
90
+ self.MAP_FECHA = date;
91
+ cargarEventosFecha(date);
92
+ </script>
93
+ </action>
94
+ </ondateselected>
95
+ ```
96
+
97
+ ### 3A.6 onpageselected - Cambio de página (calendario/slideview/tabs)
98
+
99
+ **Ambito:** property (tipo Z con viewmode calendario o slideview) | **Tipo:** atributo
100
+
101
+ Se dispara cuando el usuario cambia de mes/página en un calendario o slideview. Recibe `startDate` y `endDate`.
102
+
103
+ ```xml
104
+ <prop name="MAP_CALENDARIO" type="Z" contents="contentCalendario"
105
+ viewmode="calendarview"
106
+ onpageselected="javascript:onMesCambiado(e);"/>
107
+ ```
108
+
109
+ **Ejemplo real** (del proyecto EspecialCalendario, como nodo):
110
+
111
+ ```xml
112
+ <onpageselected show-wait-dialog="false">
113
+ <action name="runscript">
114
+ <param name="startDate"/>
115
+ <param name="endDate"/>
116
+ <script language="javascript">
117
+ cargarEventosPeriodo(startDate, endDate);
118
+ </script>
119
+ </action>
120
+ </onpageselected>
121
+ ```
122
+
123
+ ### 3A.7 Eventos de mapa
124
+
125
+ Los props con `viewmode="mapview"` u `viewmode="openstreetmap"` soportan estos eventos:
126
+
127
+ | Evento | Descripción | Ejemplo |
128
+ |--------|-------------|---------|
129
+ | `onmapclicked` | Click en el mapa | `onmapclicked="onMapClicked(e);"` |
130
+ | `onmaplongclicked` | Click prolongado en el mapa | `onmaplongclicked="onMapLongClicked(e);"` |
131
+ | `onmarkerdragend` | Fin de arrastrar un marcador | `onmarkerdragend="onMarkerDraggedEnd(e);"` |
132
+ | `onmapready` | El mapa esta listo para usar | `onmapready="onMapReady(e);"` |
133
+ | `onlocationready` | Ubicación GPS lista | `onlocationready="handler(e);"` |
134
+ | `onlocationchanged` | Cambio de ubicación GPS | `onlocationchanged="handler(e);"` |
135
+
136
+ **Ejemplo real** (del proyecto EspecialMapa con OpenStreetMap):
137
+
138
+ ```xml
139
+ <prop name="MAP_MAPA" show-compass="true" show-minimap="true"
140
+ show-scale="true" zoom-to-pois="true"
141
+ visible="1" type="Z"
142
+ contents="ClientesCoord" viewmode="openstreetmap"
143
+ width="100%" height="60%"
144
+ onmapclicked="onMapClicked(e);"
145
+ onmaplongclicked="onMapLongClicked(e);"
146
+ onmarkerdragend="onMarkerDraggedEnd(e);"/>
147
+ ```
148
+
149
+ ### 3A.8 onscroll - Evento de scroll
150
+
151
+ **Ambito:** frame | **Tipo:** atributo
152
+
153
+ Se dispara cuando el usuario hace scroll dentro de un frame con `scroll="true"`. El objeto evento contiene `e.dy` (desplazamiento vertical acumulado).
154
+
155
+ ```xml
156
+ <frame name="frmContenido" width="100%" height="100%"
157
+ scroll="true"
158
+ onscroll="javascript:scrollArrow(e, '2');">
159
+ <!-- contenido scrollable -->
160
+ </frame>
161
+ ```
162
+
163
+ ```javascript
164
+ function scrollArrow(e, miparam) {
165
+ if (e.dy <= 10 && self.MAP_VALORVER == 1) {
166
+ self.MAP_VALORVER = 0;
167
+ ui.getView(self).refresh("frmblotante");
168
+ } else if (e.dy > 10 && self.MAP_VALORVER == 0) {
169
+ self.MAP_VALORVER = 1;
170
+ ui.getView(self).refresh("frmblotante");
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### 3A.9 Eventos del drawer lateral
176
+
177
+ **Ambito:** collection | **Tipo:** atributo
178
+
179
+ Hay cuatro eventos del drawer lateral, todos atributos del nodo `<coll>`. El objeto del evento llega en `e`:
180
+
181
+ | Evento | Cuándo se dispara | Propiedades de `e` |
182
+ |--------|-------------------|--------------------|
183
+ | `ondraweropened` | El drawer queda completamente abierto | `e.id` — id del grupo drawer |
184
+ | `ondrawerclosed` | El drawer queda completamente cerrado | `e.id` |
185
+ | `ondrawerslide` | Durante el deslizamiento (se llama repetidamente) | `e.id`, `e.slideOffset` (de `0.0` cerrado a `1.0` abierto) |
186
+ | `ondrawerstatechanged` | Cambia el estado de arrastre | `e.state`: `"idle"`, `"dragging"`, `"settling"` o `"unknown"` |
187
+
188
+ `e.id` permite distinguir qué drawer cambió cuando hay varios en la misma pantalla. `ondrawerstatechanged` no incluye `e.id`.
189
+
190
+ ```xml
191
+ <coll name="PantallaConDrawer" notab="true"
192
+ ondraweropened="onDrawerOpened(e);"
193
+ ondrawerclosed="onDrawerClosed(e);"
194
+ ondrawerslide="onDrawerSlide(e);"
195
+ ondrawerstatechanged="onDrawerStateChanged(e);">
196
+ <group name="Drawer" id="999"
197
+ width="60%" drawer-orientation="left" bgcolor="#FFFFFF">
198
+ <!-- Contenido del drawer -->
199
+ </group>
200
+ <group name="Contenido" id="1">
201
+ <!-- Contenido principal -->
202
+ </group>
203
+ </coll>
204
+ ```
205
+
206
+ ### 3A.10 onconsolemessage - Mensajes de consola del WebView
207
+
208
+ **Ambito:** property (`type="WEB"`) | **Tipo:** atributo
209
+
210
+ Se dispara con cada mensaje que el WebView reporta a su consola: errores JS, llamadas a `console.log`/`warn`/`error`, etc. Util para capturar fallos del contenido web sin tener que conectar el inspector remoto.
211
+
212
+ ```xml
213
+ <prop name="MAP_WEB" type="WEB" visible="1"
214
+ height="40%"
215
+ title="Página Web"
216
+ onconsolemessage="handleConsole(e);" />
217
+ ```
218
+
219
+ ```javascript
220
+ function handleConsole(e) {
221
+ if (e.messageLevel === "ERROR") {
222
+ ui.msgBox("Nivel: " + e.messageLevel +
223
+ "\nMensaje: " + e.message +
224
+ "\nLinea: " + e.lineNumber +
225
+ "\nFuente: " + e.sourceId, "Error WebView", 0);
226
+ }
227
+ }
228
+ ```
229
+
230
+ **Propiedades del objeto evento (`e`):**
231
+
232
+ | Propiedad | Tipo | Descripción |
233
+ |-----------|------|-------------|
234
+ | `e.target` | string | Nombre del prop que disparo el evento |
235
+ | `e.objItem` | object | Referencia al DataObject que contiene el prop |
236
+ | `e.messageLevel` | string | Nivel del mensaje: `"LOG"`, `"DEBUG"`, `"WARNING"`, `"ERROR"`, `"TIP"` |
237
+ | `e.message` | string | Texto del mensaje |
238
+ | `e.lineNumber` | number | Linea del fuente donde se origino el mensaje |
239
+ | `e.sourceId` | string | URL/identificador del fuente que origino el mensaje |
240
+
241
+ ---
242
+
243
+ ### 3A.11 ontouchdown / ontouchup - Presionar y soltar un botón
244
+
245
+ **Ambito:** property (solo `type="B"`) | **Tipo:** atributo
246
+
247
+ Pareja de eventos táctiles de bajo nivel exclusivos de los botones (`type="B"`):
248
+
249
+ - **`ontouchdown`**: se dispara en el instante en que el dedo toca el botón (al presionar).
250
+ - **`ontouchup`**: se dispara al levantar el dedo o al cancelarse el gesto (al soltar).
251
+
252
+ A diferencia de `onclick` —que solo se dispara una vez completado el tap— estos eventos permiten **distinguir el momento de presionar del de soltar**, lo que habilita interacciones de tipo "mantener pulsado" (por ejemplo, iniciar una grabación mientras se mantiene el botón y detenerla al soltarlo). Su valor es JavaScript inline normal, igual que `onclick`.
253
+
254
+ ```xml
255
+ <prop name="BTN_HABLAR" type="B" title="Mantener para hablar"
256
+ ontouchdown="javascript:iniciarGrabacion();"
257
+ ontouchup="javascript:detenerGrabacion();"/>
258
+ ```
259
+
260
+ **Propiedades del objeto evento (`e`):**
261
+
262
+ | Propiedad | Tipo | Descripción |
263
+ |-----------|------|-------------|
264
+ | `e.target` | string | Nombre del prop (botón) que disparo el evento |
265
+ | `e.objItem` | object | Referencia al DataObject que contiene el prop |
266
+ | `e.x` | number | Coordenada X del toque, relativa al botón (px) |
267
+ | `e.y` | number | Coordenada Y del toque, relativa al botón (px) |
268
+
269
+ **Notas:**
270
+
271
+ - Conviven con `onclick`: si el botón define ambos, `onclick` se sigue disparando al soltar (después de `ontouchup`). Para un botón de tipo "mantener pulsado" lo habitual es no definir `onclick`.
272
+ - El botón debe estar habilitado y ser pulsable (es el caso normal de un botón con fondo). Sobre un botón deshabilitado no se disparan.
273
+
274
+ ---
275
+
276
+ ## 4. Eventos de Login
277
+
278
+ ### 4.1 login-ok
279
+
280
+ **Ambito:** collection (login-coll) | **Tipo:** interno
281
+
282
+ Se dispara cuando el proceso de login es exitoso.
283
+
284
+ ```xml
285
+ <login-ok refresh="false" show-wait-dialog="false">
286
+ <action name="runscript">
287
+ <script language="javascript">
288
+ ui.showToast("Bienvenido!");
289
+ cargarDatosUsuario();
290
+ </script>
291
+ </action>
292
+ </login-ok>
293
+ ```
294
+
295
+ ### 4.2 login-fail
296
+
297
+ **Ambito:** collection (login-coll) | **Tipo:** interno
298
+
299
+ Se dispara cuando el login falla. Permite acceder a la descripción del error.
300
+
301
+ ```xml
302
+ <login-fail>
303
+ <action name="runscript">
304
+ <script language="javascript">
305
+ var error = self.getVariable("##LOGIN_ERRORDESCRIPTION##");
306
+ ui.showToast("Error: " + error);
307
+ </script>
308
+ </action>
309
+ </login-fail>
310
+ ```
311
+
312
+ ### 4.3 onlogon (nivel Empresas)
313
+
314
+ **Ambito:** application (Empresas) | **Tipo:** interno
315
+
316
+ Se dispara cuando el usuario inicia sesión en la aplicación. Se declara en la coleccion `Empresas` dentro de `mappings.xne`.
317
+
318
+ ```xml
319
+ <onlogon>
320
+ <action name="runscript">
321
+ <script language="javascript">
322
+ inicializarAplicacion();
323
+ </script>
324
+ </action>
325
+ </onlogon>
326
+ ```
327
+
328
+ ### 4.4 onlogoff (con replica)
329
+
330
+ **Ambito:** application (Empresas) | **Tipo:** interno
331
+
332
+ Se dispara cuando el usuario cierra sesión. Soporta atributos especiales para gestionar la replica de datos antes de salir.
333
+
334
+ ```xml
335
+ <onlogoff with-replica="true" replica-retry="1" replica-fail-exit="true">
336
+ <action name="runscript">
337
+ <script language="javascript">
338
+ limpiarDatosLocales();
339
+ </script>
340
+ </action>
341
+ </onlogoff>
342
+ ```
343
+
344
+ **Atributos especiales de `onlogoff`:**
345
+
346
+ | Atributo | Tipo | Descripción |
347
+ |----------|------|-------------|
348
+ | `with-replica` | boolean | Ejecutar replica antes de cerrar sesión |
349
+ | `replica-retry` | number | Número de reintentos si la replica falla |
350
+ | `replica-fail-exit` | boolean | Salir igualmente si la replica falla |
351
+
352
+ ---
353
+
354
+ ## 5. Eventos del Sistema
355
+
356
+ ### 5.1 onpushreceived - Notificación push recibida
357
+
358
+ **Ambito:** application (Empresas) | **Tipo:** interno
359
+
360
+ Se dispara cuando la aplicación recibe una notificación push.
361
+
362
+ ```xml
363
+ <onpushreceived>
364
+ <action name="runscript">
365
+ <param name="message"/>
366
+ <script language="javascript">
367
+ ui.showToast("Push recibido: " + message.source);
368
+ procesarNotificacion(message);
369
+ </script>
370
+ </action>
371
+ </onpushreceived>
372
+ ```
373
+
374
+ ### 5.2 onpushnotificationclick - Click en notificación
375
+
376
+ **Ambito:** application (Empresas) | **Tipo:** interno
377
+
378
+ Se dispara cuando el usuario hace click en una notificación push.
379
+
380
+ ```xml
381
+ <onpushnotificationclick>
382
+ <action name="runscript">
383
+ <param name="message"/>
384
+ <script language="javascript">
385
+ if (ui.isInBackground()) {
386
+ ui.returnToForeground();
387
+ }
388
+ abrirDetalle(message.data);
389
+ </script>
390
+ </action>
391
+ </onpushnotificationclick>
392
+ ```
393
+
394
+ ### 5.3 notification - Manejador general
395
+
396
+ **Ambito:** application | **Tipo:** interno
397
+
398
+ Manejador general de notificaciones locales. Recibe parámetros sobre la notificación disparada.
399
+
400
+ ```xml
401
+ <notification refresh="false" show-wait-dialog="false">
402
+ <action name="runscript">
403
+ <param name="id_notificacion"/>
404
+ <param name="sDirectReply"/>
405
+ <param name="parameters"/>
406
+ <script language="javascript">
407
+ procesarNotificacion(id_notificacion, parameters);
408
+ </script>
409
+ </action>
410
+ </notification>
411
+ ```
412
+
413
+ ### 5.4 sys-message - Mensaje del sistema (códigos 1000-1003)
414
+
415
+ **Ambito:** application (Empresas) | **Tipo:** interno
416
+
417
+ Se dispara cuando se recibe un mensaje del sistema, típicamente relacionado con actualizaciones o provisionamiento.
418
+
419
+ ```xml
420
+ <sys-message>
421
+ <action name="runscript">
422
+ <param name="codigo"/>
423
+ <param name="message"/>
424
+ <param name="liveResponse"/>
425
+ <script language="javascript">
426
+ procesarMensajeSistema(codigo, message);
427
+ </script>
428
+ </action>
429
+ </sys-message>
430
+ ```
431
+
432
+ **Ejemplo real** (función `sysMessage` del proyecto wiki):
433
+
434
+ ```javascript
435
+ function sysMessage(codigo, message) {
436
+ var cadena = "";
437
+ switch (codigo) {
438
+ case 1000:
439
+ cadena = " Actualizacion descargandose.";
440
+ break;
441
+ case 1001:
442
+ cadena = " Actualizacion aplicada.";
443
+ break;
444
+ case 1002:
445
+ cadena = " Se han aplicado todas las actualizaciones.";
446
+ break;
447
+ case 1003:
448
+ // Provisionamiento seguro
449
+ ui.msgBox("Se ha programado una actualizacion de base de datos.",
450
+ "Mensaje", 0);
451
+ var bResult = replica.processReplicatorQueue(liveResponse);
452
+ if (bResult) {
453
+ appData.exit();
454
+ } else {
455
+ ui.showToast("Error al procesar la cola de salida");
456
+ }
457
+ break;
458
+ }
459
+ }
460
+ ```
461
+
462
+ **Códigos del sistema:**
463
+
464
+ | Código | Descripción |
465
+ |--------|-------------|
466
+ | 1000 | Actualización descargandose (uno por cada actualización) |
467
+ | 1001 | Actualización aplicada (uno por cada actualización) |
468
+ | 1002 | Todas las actualizaciones aplicadas |
469
+ | 1003 | Provisionamiento seguro - requiere replica y cierre |
470
+
471
+ ### 5.5 maintenance - Tareas programadas (period, frecuency)
472
+
473
+ **Ambito:** application (Empresas) | **Tipo:** contenedor
474
+
475
+ Contenedor para definir tareas periódicas que se ejecutan automáticamente.
476
+
477
+ ```xml
478
+ <maintenance>
479
+ <!-- Tarea cada 10 minutos -->
480
+ <action name="SincronizarDatos" type="runscript"
481
+ period="S" frecuency="600" auto="true" show="false">
482
+ <script language="javascript">
483
+ sincronizarConServidor();
484
+ </script>
485
+ </action>
486
+
487
+ <!-- Replica automática -->
488
+ <action name="Replica" type="replica"
489
+ frecuency="400" period="X" synchronize="true"/>
490
+ </maintenance>
491
+ ```
492
+
493
+ **Atributos de action en maintenance:**
494
+
495
+ | Atributo | Tipo | Descripción | Valores |
496
+ |----------|------|-------------|---------|
497
+ | `name` | string | Nombre identificativo de la tarea | Cualquier texto |
498
+ | `type` | string | Tipo de acción | `runscript`, `replica` |
499
+ | `period` | string | Unidad de tiempo | `S` (segundos), `X` (minutos) |
500
+ | `frecuency` | number | Frecuencia en la unidad especificada | Ej: `600` (cada 600 seg) |
501
+ | `auto` | boolean | Ejecución automática al iniciar | `true`/`false` |
502
+ | `show` | boolean | Mostrar en la interfaz | `true`/`false` |
503
+ | `synchronize` | boolean | Sincronizar al ejecutar | `true`/`false` |
504
+
505
+ **Ejemplo de mantenimiento cada 24 horas:**
506
+
507
+ ```xml
508
+ <maintenance>
509
+ <action name="LimpiezaDiaria" type="runscript"
510
+ period="X" frecuency="1440" auto="true" show="false">
511
+ <script language="javascript">
512
+ // Tareas periodicas de mantenimiento (cada 24h = 1440 min)
513
+ limpiarRegistrosAntiguos();
514
+ compactarBaseDeDatos();
515
+ </script>
516
+ </action>
517
+ </maintenance>
518
+ ```
519
+
520
+ ### 5.6 onrecovery - Recuperación
521
+
522
+ **Ambito:** application | **Tipo:** interno
523
+
524
+ Se dispara cuando la aplicación se recupera de un cierre inesperado o de un estado previo.
525
+
526
+ ```xml
527
+ <onrecovery>
528
+ <action name="runscript">
529
+ <script language="javascript">
530
+ verificarEstadoPendiente();
531
+ </script>
532
+ </action>
533
+ </onrecovery>
534
+ ```
535
+
536
+ ### 5.7 after-recovery-login - Login tras recuperación
537
+
538
+ **Ambito:** application | **Tipo:** interno
539
+
540
+ Se dispara después de que el usuario inicia sesión tras una recuperación de la aplicación (por crash o kill del sistema operativo).
541
+
542
+ ```xml
543
+ <after-recovery-login>
544
+ <action name="runscript">
545
+ <script language="javascript">
546
+ restaurarSesionAnterior();
547
+ </script>
548
+ </action>
549
+ </after-recovery-login>
550
+ ```
551
+
552
+ ---
553
+
554
+ ## 5A. Eventos de Ciclo de Aplicación
555
+
556
+ ### 5A.1 on-app-foreground - App vuelve a primer plano
557
+
558
+ **Ambito:** application (Empresas) | **Tipo:** interno
559
+
560
+ Se dispara cuando la aplicación vuelve al primer plano después de estar en segundo plano. Es el lugar ideal para verificar inactividad y forzar re-login si es necesario.
561
+
562
+ ```xml
563
+ <on-app-foreground>
564
+ <action name="runscript">
565
+ <script language="javascript">
566
+ verificarConexion();
567
+ actualizarDatos();
568
+ </script>
569
+ </action>
570
+ </on-app-foreground>
571
+ ```
572
+
573
+ **Ejemplo real con verificación de inactividad:**
574
+
575
+ ```xml
576
+ <on-app-foreground refresh="false">
577
+ <action name="runscript">
578
+ <script language="javascript">
579
+ var nTime = ui.getInactivityTime();
580
+ if (nTime >= jsconst_oper.tiempoInactividad) {
581
+ var objCrear = new LoginColl_Inactivity();
582
+ ui.openEditView(objCrear);
583
+ }
584
+ </script>
585
+ </action>
586
+ </on-app-foreground>
587
+ ```
588
+
589
+ ### 5A.2 on-app-background - App pasa a segundo plano
590
+
591
+ **Ambito:** application (Empresas) | **Tipo:** interno
592
+
593
+ Se dispara cuando la aplicación pasa a segundo plano (el usuario cambia de app o pulsa Home).
594
+
595
+ ```xml
596
+ <on-app-background>
597
+ <action name="runscript">
598
+ <script language="javascript">
599
+ guardarEstadoActual();
600
+ </script>
601
+ </action>
602
+ </on-app-background>
603
+ ```
604
+
605
+ ---
606
+
607
+ ## 5B. Gestion de Inactividad
608
+
609
+ XOne proporciona funciones JavaScript para gestionar la inactividad del usuario, útiles para forzar re-login por seguridad.
610
+
611
+ ### 5B.1 ui.setInactivityTimer(segundos, acción)
612
+
613
+ Configura un temporizador de inactividad. Cuando el usuario no interactua durante el tiempo especificado, se ejecuta la acción indicada.
614
+
615
+ ```javascript
616
+ ui.setInactivityTimer(300, "verificarSesion"); // 5 minutos
617
+ ```
618
+
619
+ ### 5B.2 ui.getInactivityTime()
620
+
621
+ Obtiene el tiempo en segundos transcurrido desde la última interaccion del usuario.
622
+
623
+ ```javascript
624
+ var tiempo = ui.getInactivityTime();
625
+ if (tiempo > 1800) {
626
+ // Mas de 30 minutos inactivo
627
+ forzarReLogin();
628
+ }
629
+ ```
630
+
631
+ ### 5B.3 ui.removeInactivityTimer()
632
+
633
+ Elimina el temporizador de inactividad activo.
634
+
635
+ ```javascript
636
+ ui.removeInactivityTimer();
637
+ ```
638
+
639
+ ### 5B.4 Patron completo: re-login por inactividad
640
+
641
+ Combinar `on-app-foreground` con `getInactivityTime()` para forzar re-login:
642
+
643
+ ```xml
644
+ <!-- En Empresas (mappings.xne) -->
645
+ <on-app-foreground refresh="false">
646
+ <action name="runscript">
647
+ <script language="javascript">
648
+ var nTime = ui.getInactivityTime();
649
+ if (nTime >= 1800) {
650
+ var objCrear = new LoginColl_Inactivity();
651
+ ui.openEditView(objCrear);
652
+ }
653
+ </script>
654
+ </action>
655
+ </on-app-foreground>
656
+ ```
657
+
658
+ ---
659
+
660
+ ## 5D. Códigos sys-message detallados
661
+
662
+ El evento `sys-message` recibe un parámetro `código` que indica el tipo de mensaje del sistema. Estos son los códigos documentados:
663
+
664
+ | Código | Categoría | Descripción |
665
+ |--------|-----------|-------------|
666
+ | 1000 | Actualización | Actualización descargandose (uno por cada actualización individual) |
667
+ | 1001 | Actualización | Actualización aplicada exitosamente (uno por cada actualización) |
668
+ | 1002 | Actualización | Todas las actualizaciones han sido aplicadas |
669
+ | 1003 | Provisionamiento | Provisionamiento seguro - requiere procesar cola de replica y reiniciar |
670
+
671
+ **Ejemplo completo de manejo de sys-message:**
672
+
673
+ ```javascript
674
+ function sysMessage(codigo, message) {
675
+ var cadena = "";
676
+ switch (codigo) {
677
+ case 1000:
678
+ cadena = "Actualizacion descargandose.";
679
+ ui.showToast(cadena);
680
+ break;
681
+ case 1001:
682
+ cadena = "Actualizacion aplicada.";
683
+ ui.showToast(cadena);
684
+ break;
685
+ case 1002:
686
+ cadena = "Se han aplicado todas las actualizaciones.";
687
+ ui.showToast(cadena);
688
+ break;
689
+ case 1003:
690
+ // Provisionamiento seguro: procesar cola y reiniciar
691
+ ui.msgBox("Se ha programado una actualizacion de base de datos.",
692
+ "Mensaje", 0);
693
+ var bResult = replica.processReplicatorQueue(liveResponse);
694
+ if (bResult) {
695
+ appData.exit();
696
+ } else {
697
+ ui.showToast("Error al procesar la cola de salida");
698
+ }
699
+ break;
700
+ }
701
+ }
702
+ ```
703
+
704
+ > **Nota:** El parámetro `liveResponse` esta disponible como tercer parámetro del evento `sys-message`. Se usa exclusivamente con el código 1003 para el provisionamiento seguro.
705
+
706
+ ---
707
+
708
+ ## 6. Eventos de Replica
709
+
710
+ ### 6.1 replica-ok-{tabla}
711
+
712
+ **Ambito:** application (Empresas) | **Tipo:** interno
713
+
714
+ Se dispara cuando la replica de una tabla especifica es exitosa. El nombre del evento incluye el nombre de la tabla con prefijo.
715
+
716
+ ```xml
717
+ <replica-ok-gen_ot_cabecera>
718
+ <action name="runscript">
719
+ <script language="javascript">
720
+ actualizarListadoOT();
721
+ ui.showToast("OTs sincronizadas");
722
+ </script>
723
+ </action>
724
+ </replica-ok-gen_ot_cabecera>
725
+ ```
726
+
727
+ ---
728
+
729
+ ## 7. Eventos Personalizados (Custom)
730
+
731
+ ### 7.1 Definición de eventos custom
732
+
733
+ Los eventos personalizados se definen como nodos XML con cualquier nombre dentro de la coleccion. Son el mecanismo principal para organizar la lógica de la aplicación en bloques reutilizables.
734
+
735
+ ```xml
736
+ <GuardarFormulario refresh="true" show-wait-dialog="true"
737
+ wait-dialog-text="Guardando...">
738
+ <action name="runscript">
739
+ <script language="javascript">
740
+ validarYGuardar();
741
+ </script>
742
+ </action>
743
+ </GuardarFormulario>
744
+ ```
745
+
746
+ ### 7.2 Invocación con ExecuteNode(nombre)
747
+
748
+ Se invocan desde atributos `method` o `onclick` de un `<prop>`:
749
+
750
+ ```xml
751
+ <prop name="BTN_GUARDAR" type="B"
752
+ method="ExecuteNode(GuardarFormulario)"/>
753
+ ```
754
+
755
+ También se pueden invocar desde JavaScript:
756
+
757
+ ```javascript
758
+ self.executeNode("GuardarFormulario");
759
+ ```
760
+
761
+ ### 7.3 Paso de parámetros ExecuteNode(nombre(param))
762
+
763
+ Se pueden pasar parámetros directamente en la invocación:
764
+
765
+ ```xml
766
+ <prop name="BTN_MENU" type="B"
767
+ method="executenode(CambiarMenu(3))"/>
768
+
769
+ <prop name="BTBUSCAR" type="B"
770
+ method="ExecuteNode(buscar(1))"/>
771
+
772
+ <prop name="BTORDENAR" type="B"
773
+ method="ExecuteNode(buscar(2))"/>
774
+ ```
775
+
776
+ ### 7.4 Usando `<param name="..."/>`
777
+
778
+ Los parámetros se reciben en el evento con nodos `<param>`:
779
+
780
+ ```xml
781
+ <CambiarMenu refresh="true">
782
+ <action name="runscript">
783
+ <param name="opcion"/>
784
+ <script language="javascript">
785
+ cambiarAOpcion(opcion);
786
+ </script>
787
+ </action>
788
+ </CambiarMenu>
789
+ ```
790
+
791
+ **Ejemplo real** (del proyecto EspecialContents - busqueda y ordenacion):
792
+
793
+ ```xml
794
+ <buscar show-wait-dialog="false" refresh="false">
795
+ <action name="runscript">
796
+ <param name="param"/>
797
+ <script language="javascript">
798
+ if (param == "1") {
799
+ if (self.MAP_FILTRO.length == 0) {
800
+ self.getContents("content4").setFilter("");
801
+ } else {
802
+ self.getContents("content4").setFilter(
803
+ "NOMBRE like '%" + self.MAP_FILTRO.toString() + "%' OR "
804
+ + "DIRECCION like '%" + self.MAP_FILTRO.toString() + "%'"
805
+ );
806
+ }
807
+ } else {
808
+ if (self.MAP_ORDEN == "ASC") {
809
+ self.MAP_ORDEN = "DESC";
810
+ self.MAP_BTORDEN = "sortZA.png";
811
+ self.MAP_BTORDENCLICK = "sortZA_click.png";
812
+ } else {
813
+ self.MAP_ORDEN = "ASC";
814
+ self.MAP_BTORDEN = "sortAZ.png";
815
+ self.MAP_BTORDENCLICK = "sortAZ_click.png";
816
+ }
817
+ self.getContents("content4").sort =
818
+ "NOMBRE " + self.MAP_ORDEN.toString();
819
+ }
820
+ self.getContents("content4").unlock();
821
+ self.getContents("content4").loadAll();
822
+ self.getContents("content4").lock();
823
+ ui.getView(self).refresh("@content4,BTORDENAR");
824
+ </script>
825
+ </action>
826
+ </buscar>
827
+ ```
828
+
829
+ **Ejemplo real** (del proyecto EspecialContents - multiples parámetros con checkAll):
830
+
831
+ ```xml
832
+ <checkAll refresh="false">
833
+ <action name="runscript">
834
+ <param name="activo"/>
835
+ <script language="javascript">
836
+ var objContent = self.getContents("ContentDatosFiltroMultiseleccion");
837
+ if (activo == 1) {
838
+ var vres = userMsgBox("OPCIONES",
839
+ "Confirme que desea marcar todos los registros", "2");
840
+ } else {
841
+ var vres = userMsgBox("OPCIONES",
842
+ "Confirme que desea DESmarcar todos los registros", "2");
843
+ }
844
+ if (vres == 1) {
845
+ for (var i = 0; i < objContent.count(); i++) {
846
+ var item = objContent.get(i);
847
+ if (activo == 1) {
848
+ if (item.MAP_SELECTED == 1 && item.REALIZADA == 0) {
849
+ ReportarTareaPendiente2(item);
850
+ item.MAP_SELECTED = 0;
851
+ }
852
+ } else {
853
+ if (item.MAP_SELECTED == 1 && item.REALIZADA == 1) {
854
+ DesregistrarPendiente2(item);
855
+ item.MAP_SELECTED = 0;
856
+ }
857
+ }
858
+ }
859
+ }
860
+ self.executeNode("applyfilter");
861
+ </script>
862
+ </action>
863
+ </checkAll>
864
+ ```
865
+
866
+ ---
867
+
868
+ ## 8. Acciones dentro de Eventos
869
+
870
+ ### 8.1 runscript - Ejecutar JavaScript
871
+
872
+ La acción `runscript` ejecuta un bloque de código JavaScript.
873
+
874
+ ```xml
875
+ <action name="runscript">
876
+ <param name="parametro"/>
877
+ <script language="javascript">
878
+ // Código JavaScript con acceso a 'parametro'
879
+ ui.showToast("Parametro: " + parametro);
880
+ </script>
881
+ </action>
882
+ ```
883
+
884
+ Un evento puede contener multiples acciones `runscript` que se ejecutan en orden:
885
+
886
+ ```xml
887
+ <before-edit>
888
+ <action name="runscript">
889
+ <script language="javascript">
890
+ ui.getView(self).bind("SCVB", "onclick", "testClick");
891
+ </script>
892
+ </action>
893
+ <action name="runscript">
894
+ <script language="javascript">
895
+ self.MAP_GROUP = 1;
896
+ self.MAP_TOTAL_PAGES = 3;
897
+ </script>
898
+ </action>
899
+ </before-edit>
900
+ ```
901
+
902
+ ### 8.2 setval - Establecer valor a campo
903
+
904
+ La acción `setval` asigna un valor a un campo del objeto actual sin necesidad de JavaScript.
905
+
906
+ ```xml
907
+ <action name="setval" field="CAMPO" value="valor"/>
908
+ <action name="setval" field="FECHA" value="##NOW_TIME##"/>
909
+ <action name="setval" field="MAP_IDENTIFICADOR" value="##DEVICEID##"/>
910
+ ```
911
+
912
+ **Ejemplo real** (del proyecto EspecialDatosOnline):
913
+
914
+ ```xml
915
+ <before-edit show-wait-dialog="false">
916
+ <action name="setval" field="MAP_IDENTIFICADOR" value="##DEVICEID##"/>
917
+ <action name="runscript">
918
+ <script language="javascript">
919
+ if (ComprobarConexion() == 1) {
920
+ // continuar...
921
+ }
922
+ </script>
923
+ </action>
924
+ </before-edit>
925
+ ```
926
+
927
+ ### 8.3 Macros en setval: ##NOW_TIME##, ##NOW_DATE##
928
+
929
+ Las macros del sistema se pueden usar como valores en `setval`:
930
+
931
+ | Macro | Descripción | Ejemplo de valor |
932
+ |-------|-------------|------------------|
933
+ | `##NOW_TIME##` | Fecha y hora actual | `2024-01-15 14:30:00` |
934
+ | `##NOW_DATE##` | Fecha actual sin hora | `2024-01-15` |
935
+ | `##USERID##` | ID del usuario logueado | `1` |
936
+ | `##DEVICEID##` | ID único del dispositivo | `abc123def456` |
937
+ | `##MID##` | MID del dispositivo | `device_mid_value` |
938
+ | `##VERSION##` | Versión de la aplicación | `1.0.0` |
939
+ | `##FRAME_VERSION##` | Versión del framework XOne | `4.8.1.33` |
940
+ | `##DEVICE_OS##` | Sistema operativo | `android` o `ios` |
941
+ | `##DEVICE_MODEL##` | Modelo del dispositivo | `Pixel 6` |
942
+
943
+ > **Referencia cruzada:** Para la lista completa de macros del sistema, consultar el tópico 03 sobre la API JavaScript.
944
+