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,704 @@
1
+ # XOne — Eventos: sistema, ciclo de vida e interacción
2
+
3
+ > Fuente: `xone/v2/xone-help-docs/topics/05-events-patterns-faq.md` §1–§3. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: §1 cómo funciona el sistema de eventos · §2 eventos de ciclo de vida (create, before-edit, after-edit, load) · §3 eventos de interacción (onclick, onchange, selecteditem, onlongpressitem, onback)
6
+
7
+ ---
8
+
9
+ ## 1. Sistema de Eventos en XOne
10
+
11
+ ### 1.1 Como funciona el sistema de eventos
12
+
13
+ XOne utiliza un sistema de eventos declarativo en XML. Los eventos se definen como nodos dentro de una coleccion (`<coll>`) y contienen acciones que se ejecutan cuando el evento se dispara.
14
+
15
+ El flujo básico es:
16
+
17
+ ```
18
+ Evento disparado --> Nodo XML del evento --> Accion(es) --> Script JavaScript
19
+ ```
20
+
21
+ Las acciones principales dentro de un evento son:
22
+
23
+ - **`runscript`** - Ejecuta código JavaScript
24
+ - **`setval`** - Establece un valor en un campo
25
+
26
+ Ejemplo básico de un evento con acción:
27
+
28
+ ```xml
29
+ <create refresh="true" show-wait-dialog="false">
30
+ <action name="setval" field="FECHA" value="##NOW_TIME##"/>
31
+ <action name="runscript">
32
+ <script language="javascript">
33
+ inicializarFormulario();
34
+ </script>
35
+ </action>
36
+ </create>
37
+ ```
38
+
39
+ > **Referencia cruzada:** Para la estructura XML de los nodos de eventos, consultar el tópico 02 sobre estructura XML.
40
+
41
+ ### 1.2 Ambitos de eventos
42
+
43
+ Los eventos en XOne operan en cuatro ambitos distintos:
44
+
45
+ | Ambito | Descripción | Donde se declara | Ejemplos |
46
+ |--------|-------------|------------------|----------|
47
+ | **application** | Nivel de aplicación completa | Coleccion `Empresas` en `mappings.xne` | `onlogon`, `maintenance`, `onpushreceived`, `sys-message` |
48
+ | **collection** | Nivel de coleccion | Dentro del nodo `<coll>` | `selecteditem`, `onlongpressitem`, `login-ok`, `login-fail` |
49
+ | **object** | Nivel de objeto individual | Dentro del nodo `<coll>` | `create`, `load`, `before-edit`, `after-edit`, `onback`, `onrefresh` |
50
+ | **property** | Nivel de propiedad/campo | Como atributo en `<prop>` | `onclick`, `onchange`, `ontextchanged`, `onfocuschanged` |
51
+
52
+ ### 1.3 Atributos comunes de eventos
53
+
54
+ Todos los nodos de evento soportan los siguientes atributos de configuración:
55
+
56
+ | Atributo | Tipo | Descripción | Valor por defecto |
57
+ |----------|------|-------------|-------------------|
58
+ | `refresh` | boolean | Refrescar la UI después de ejecutar el evento | `true` |
59
+ | `show-wait-dialog` | boolean | Mostrar un dialogo de espera mientras se ejecuta | `true` |
60
+ | `wait-dialog-text` | string | Texto personalizado del dialogo de espera | (vacio) |
61
+
62
+ Ejemplo con todos los atributos:
63
+
64
+ ```xml
65
+ <GuardarDatos refresh="true" show-wait-dialog="true" wait-dialog-text="Guardando...">
66
+ <action name="runscript">
67
+ <script language="javascript">
68
+ guardarFormulario();
69
+ </script>
70
+ </action>
71
+ </GuardarDatos>
72
+ ```
73
+
74
+ **Buena práctica:** Establece `refresh="false"` y `show-wait-dialog="false"` en eventos que no modifican la UI para evitar parpadeos innecesarios.
75
+
76
+ ---
77
+
78
+ ## 2. Eventos de Ciclo de Vida
79
+
80
+ ### 2.1 create - Al crear objeto nuevo
81
+
82
+ **Ambito:** object | **Tipo:** interno
83
+
84
+ Se dispara una única vez cuando se crea un nuevo objeto en la coleccion. Es ideal para inicializar valores por defecto.
85
+
86
+ ```xml
87
+ <create refresh="true" show-wait-dialog="false">
88
+ <action name="setval" field="FECHA" value="##NOW_TIME##"/>
89
+ <action name="runscript">
90
+ <script language="javascript">
91
+ inicializarFormulario();
92
+ </script>
93
+ </action>
94
+ </create>
95
+ ```
96
+
97
+ **Ejemplo real** (del proyecto EspecialCalendario):
98
+
99
+ ```xml
100
+ <create>
101
+ <action name="runscript">
102
+ <script language="javascript">
103
+ self.MAP_CTN_TITLE_FECHA = "FECHA";
104
+ self.MAP_CTN_TITLE_TIPO = "TIPO";
105
+ self.MAP_CTN_TITLE_DESCRIPCION = "DESCRIPCION";
106
+ </script>
107
+ </action>
108
+ </create>
109
+ ```
110
+
111
+ **Ejemplo real** (del proyecto ContentCoordenadasGPS, con `setval` y `mapval`):
112
+
113
+ ```xml
114
+ <create>
115
+ <action name="setval" field="FECHA" value="##NOW_TIME##"/>
116
+ <action name="mapval" field="USUARIO" coll="Usuarios"
117
+ mapfld="ID" mapvalue="##USERID##" targetfld="LOGIN"/>
118
+ </create>
119
+ ```
120
+
121
+ ### 2.2 load - Al cargar cada DataObject
122
+
123
+ **Ambito:** object | **Tipo:** interno
124
+
125
+ Se dispara **por cada DataObject** al cargarse desde la base de datos (en `loadAll()`, `startBrowse()` o cuando se hidrata un item de `<contents>`). Se ejecuta después de `create` si el objeto es nuevo.
126
+
127
+ > **NUNCA usar `<load>` para inicializar una pantalla** — usar `<before-edit>`. En una pantalla `special="true"` sin coleccion de datos, `<load>` no se dispara nunca; en pantallas con coleccion, se dispara una vez por cada item cargado y penaliza rendimiento.
128
+
129
+ ### 2.3 before-edit - Antes de entrar en edición
130
+
131
+ **Ambito:** object | **Tipo:** interno
132
+
133
+ Se dispara antes de que la vista entre en modo edición. Es el evento más utilizado para preparar la pantalla, inicializar variables MAP y configurar contents.
134
+
135
+ ```xml
136
+ <before-edit refresh="false" show-wait-dialog="false">
137
+ <action name="runscript">
138
+ <script language="javascript">
139
+ self.MAP_USER = self.getOwnerCollection().getVariable("##LOGIN_LASTUSER##");
140
+ </script>
141
+ </action>
142
+ </before-edit>
143
+ ```
144
+
145
+ **Ejemplo real** (del proyecto EspecialContents):
146
+
147
+ ```xml
148
+ <before-edit refresh="true">
149
+ <action name="runscript">
150
+ <script language="javascript">
151
+ self.MAP_GROUP = 1;
152
+ self.MAP_TOTAL_PAGES = 5;
153
+ self.MAP_ORDEN = "ASC";
154
+ self.MAP_BTORDEN = "sortAZ.png";
155
+ self.MAP_BTORDENCLICK = "sortAZ_click.png";
156
+ self.getContents("content4").sort = "NOMBRE ASC";
157
+ self.getContents("content4").loadAll();
158
+ self.getContents("content4").lock();
159
+
160
+ self.getContents("content1").clear();
161
+ self.getContents("content1").lock();
162
+
163
+ ui.startGps();
164
+ self.MAP_NOMBRESEL = "";
165
+ </script>
166
+ </action>
167
+ </before-edit>
168
+ ```
169
+
170
+ **Ejemplo real** (del proyecto EspecialEventos, con `bind` para eventos por script):
171
+
172
+ ```xml
173
+ <before-edit>
174
+ <action name="runscript">
175
+ <script language="javascript">
176
+ var v = ui.getView(self);
177
+ v.bind("MAP_ONTEXTCHANGED", "ontextchanged", eventoOnTextChanged);
178
+ v.bind("MAP_ONFOCUSCHANGED01", "onfocuschanged", eventoOnFocusChanged);
179
+
180
+ v.bind("SCJAVA", "onclick",
181
+ {title:'valor desde fuera', msg:'LLamada inline'},
182
+ function(e) {
183
+ ui.msgBox(e.target + ":" + e.data.msg, e.data.title, 0);
184
+ });
185
+
186
+ v.bind("SCJAVA1", "onclick", "EspecialcollTest1", jstestClick);
187
+ </script>
188
+ </action>
189
+ </before-edit>
190
+ ```
191
+
192
+ ### 2.4 after-edit - Después de entrar en edición
193
+
194
+ **Ambito:** object | **Tipo:** interno
195
+
196
+ Se dispara después de que la vista ha entrado en modo edición y se ha pintado la interfaz. Útil para operaciones que requieren que la UI ya este renderizada.
197
+
198
+ ```xml
199
+ <after-edit show-wait-dialog="false" refresh="false">
200
+ <action name="runscript">
201
+ <script language="javascript">
202
+ if (appData.getGlobalMacro("##DEVICE_OS##") == "android")
203
+ requestIgnoreBatteryOptimizations();
204
+ </script>
205
+ </action>
206
+ </after-edit>
207
+ ```
208
+
209
+ **Ejemplo real** (del proyecto EspecialChat):
210
+
211
+ ```xml
212
+ <after-edit show-wait-dialog="false" refresh="false">
213
+ <action name="runscript">
214
+ <script language="javascript">
215
+ lockContents(["Chat", "nUsuarios", "Chatear"]);
216
+ </script>
217
+ </action>
218
+ </after-edit>
219
+ ```
220
+
221
+ ### 2.5 Orden de ejecución de lifecycle
222
+
223
+ El orden de ejecución de los eventos de ciclo de vida es:
224
+
225
+ **Para un objeto nuevo:**
226
+ 1. `create` - Se inicializa el objeto
227
+ 2. `before-edit` - Se prepara la vista
228
+ 3. (Se pinta la interfaz)
229
+ 4. `after-edit` - La vista esta renderizada
230
+
231
+ **Para un objeto existente:**
232
+ 1. `load` - Se carga desde BD
233
+ 2. `before-edit` - Se prepara la vista
234
+ 3. (Se pinta la interfaz)
235
+ 4. `after-edit` - La vista esta renderizada
236
+
237
+ **Al salir:**
238
+ 1. `onback` - El usuario pulsa atrás
239
+
240
+ ---
241
+
242
+ ## 3. Eventos de Interaccion
243
+
244
+ ### 3.1 onclick (atributo) - Click/tap en elemento
245
+
246
+ **Ambito:** property | **Tipo:** atributo
247
+
248
+ Se dispara cuando el usuario hace click o tap en un elemento. Se declara como atributo en el nodo `<prop>`.
249
+
250
+ ```xml
251
+ <prop type="B" name="BTN_LOGIN" title="Login"
252
+ onclick="doLogin();"/>
253
+
254
+ <prop name="BTN_ACCION" type="B"
255
+ onclick="self.MAP_QR=1; ui.refresh('frmCamera'); ui.sleep(0.1);"/>
256
+ ```
257
+
258
+ **Ejemplo real** (del proyecto EspecialEventos, llamada inline con parámetros):
259
+
260
+ ```xml
261
+ <prop name="ATTJAVA" title="No abre coleccion"
262
+ onclick="javascript:(function(e, data) {
263
+ ui.msgBox(e.target + ':' + data.msg, data.title, 0);
264
+ })(e, {title:'valor desde fuera', msg:'LLamada inline'});"
265
+ type="B" visible="1" width="300p" height="150p"
266
+ labelwidth="1" bgcolor="#666666" forecolor="#F2F2F2"/>
267
+ ```
268
+
269
+ **Ejemplo real** (del proyecto EspecialEventos, llamada a función con datos):
270
+
271
+ ```xml
272
+ <prop name="ATTJAVA1" title="Abrir coleccion 1"
273
+ onclick="javascript:jstestClickNode(e, 'EspecialcollTest1');"
274
+ type="B" visible="1" width="300p" height="150p"/>
275
+
276
+ <prop name="ATTJAVA2" title="Abrir coleccion 2"
277
+ onclick="javascript:jstestClickNode(e, {
278
+ title:'valor desde fuera',
279
+ msg:'Abre un nuevo objeto',
280
+ collName: 'EspecialcollTest2'
281
+ });"
282
+ type="B" visible="1" width="300p" height="150p"/>
283
+ ```
284
+
285
+ ### 3.2 onchange (nodo y atributo) - Cambio de valor
286
+
287
+ **Ambito:** property/object | **Tipo:** interno/atributo
288
+
289
+ Se dispara cuando cambia el valor de una propiedad. Puede usarse de dos formas:
290
+
291
+ **Como nodo `<onchange>` con campos `<field>` especificos:**
292
+
293
+ ```xml
294
+ <onchange show-wait-dialog="false" refresh="false">
295
+ <field name="MAP_TIPO">
296
+ <action name="runscript">
297
+ <script language="javascript">
298
+ actualizarPorTipo();
299
+ </script>
300
+ </action>
301
+ </field>
302
+ </onchange>
303
+ ```
304
+
305
+ **Ejemplo real** (del proyecto EspecialMacros, con multiples campos):
306
+
307
+ ```xml
308
+ <onchange>
309
+ <field name="MAP_TIPO">
310
+ <action name="runscript">
311
+ <script language="javascript">
312
+ var coll = self.getContents("content1");
313
+ if (self.TIPO == "TODOS") {
314
+ coll.setMacro("##TIPO##", "1=1");
315
+ } else {
316
+ coll.setMacro("##TIPO##", "FILTRO='" + self.TIPO.toString() + "'");
317
+ }
318
+ ui.refresh();
319
+ </script>
320
+ </action>
321
+ </field>
322
+ <field name="MAP_TIPO1">
323
+ <action name="runscript">
324
+ <script language="javascript">
325
+ var coll = self.getContents("content2");
326
+ if (self.TIPO1 == "TODOS") {
327
+ coll.setMacro("##TIPO##",
328
+ "SELECT ID,TITULO,FILTRO FROM GEN_CONTROLES");
329
+ } else {
330
+ coll.setMacro("##TIPO##",
331
+ "SELECT ID,TITULO,FILTRO FROM GEN_CONTROLES WHERE FILTRO='"
332
+ + self.TIPO1.toString() + "'");
333
+ }
334
+ ui.refresh();
335
+ </script>
336
+ </action>
337
+ </field>
338
+ </onchange>
339
+ ```
340
+
341
+ **Ejemplo real** (del proyecto EspecialChat, escuchando cambios en foto y adjunto):
342
+
343
+ ```xml
344
+ <onchange>
345
+ <field name="MAP_FOTO">
346
+ <action name="runscript">
347
+ <script language="javascript">
348
+ AccionesChatEspecial('enviar');
349
+ </script>
350
+ </action>
351
+ </field>
352
+ <field name="MAP_ADJUNTO">
353
+ <action name="runscript">
354
+ <script language="javascript">
355
+ AccionesChatEspecial('adjuntoguardar', e);
356
+ </script>
357
+ </action>
358
+ </field>
359
+ </onchange>
360
+ ```
361
+
362
+ **Como atributo en `<prop>` (forma simplificada):**
363
+
364
+ ```xml
365
+ <prop name="CANTIDAD" type="N" onchange="Refresh"/>
366
+ <prop name="MAP_TEXT" type="T" onchange="ExecuteNode(oldvalue)"/>
367
+ <prop name="Calendario" type="Z" onchange="refresh" postonchange="refresh"/>
368
+ ```
369
+
370
+ El valor `"Refresh"` o `"refresh"` hace un refresco automático de la pantalla. También puede usarse `"refresh(campo1,campo2)"` para refrescar campos especificos.
371
+
372
+ #### onvaluechanged (atributo) — Cambio de valor en la capa de datos
373
+
374
+ `onvaluechanged` se dispara cuando el valor de un campo cambia. Tiene dos características que lo distinguen:
375
+
376
+ 1. **Su valor es JavaScript inline normal** (igual que `onclick`): escribes directamente el código a ejecutar.
377
+ 2. **Se dispara desde la capa de datos**, así que salta siempre que el valor del campo cambie de verdad, **aunque no haya ninguna ventana abierta** (cambios provocados por scripts de fondo, réplica, tareas programadas, etc.).
378
+
379
+ Recibe un objeto de evento `e` con estas propiedades:
380
+
381
+ | Propiedad | Descripción |
382
+ |-----------|-------------|
383
+ | `e.value` | Nuevo valor del campo (después del cambio) |
384
+ | `e.oldValue` | Valor que tenía el campo antes del cambio |
385
+ | `e.target` | Nombre del campo que ha cambiado |
386
+ | `e.objItem` | Objeto de datos sobre el que se ha producido el cambio |
387
+ | `e.data` | Dato libre asociado al binding (normalmente vacío) |
388
+
389
+ ```xml
390
+ <!-- Recalcular un total al cambiar la cantidad, haya o no pantalla abierta -->
391
+ <prop name="CANTIDAD" type="N" visible="1"
392
+ onvaluechanged="self.TOTAL = e.value * self.PRECIO;" />
393
+
394
+ <!-- Registrar el cambio en una auditoría -->
395
+ <prop name="ESTADO" type="T" visible="1"
396
+ onvaluechanged="registrarCambio(e.target, e.oldValue, e.value);" />
397
+ ```
398
+
399
+ También se puede registrar dinámicamente desde JavaScript:
400
+
401
+ ```javascript
402
+ self.bind("CANTIDAD", "onvaluechanged", function (e) {
403
+ self.TOTAL = e.value * self.PRECIO;
404
+ });
405
+ ```
406
+
407
+ **Solo JavaScript.** Se dispara únicamente cuando el valor cambia de verdad (reasignar el mismo valor no lo dispara) y nunca durante la carga del objeto desde la base de datos.
408
+
409
+ Es ideal para lógica que debe ejecutarse siempre que el dato cambie (recalcular campos, `Save()`, auditoría, sincronización), haya o no una pantalla abierta.
410
+
411
+ ### 3.3 selecteditem - Selección en lista
412
+
413
+ **Ambito:** collection | **Tipo:** interno
414
+
415
+ Se dispara cuando el usuario selecciona un item de una lista o content.
416
+
417
+ ```xml
418
+ <selecteditem refresh="false" show-wait-dialog="false">
419
+ <action name="runscript">
420
+ <script language="javascript">
421
+ onSelectedItem(self);
422
+ </script>
423
+ </action>
424
+ </selecteditem>
425
+ ```
426
+
427
+ > **Referencia cruzada:** Para ver como se implementa la selección en listas con contents, ver el tópico 02 sobre estructura XML y el patron maestro-detalle en la sección 10.2.
428
+
429
+ ### 3.4 onlongpressitem - Pulsacion larga
430
+
431
+ **Ambito:** collection | **Tipo:** interno
432
+
433
+ Se dispara cuando el usuario hace una pulsacion larga sobre un item de una lista.
434
+
435
+ ```xml
436
+ <onlongpressitem refresh="false" show-wait-dialog="false">
437
+ <action name="runscript">
438
+ <script language="javascript">
439
+ mostrarMenuContextual(self);
440
+ </script>
441
+ </action>
442
+ </onlongpressitem>
443
+ ```
444
+
445
+ ### 3.5 onback - Botón retroceso
446
+
447
+ **Ambito:** object | **Tipo:** interno
448
+
449
+ Se dispara cuando el usuario presiona el botón de retroceso del dispositivo. Permite controlar la navegación hacia atrás.
450
+
451
+ ```xml
452
+ <onback refresh="false" show-wait-dialog="false">
453
+ <action name="runscript">
454
+ <script language="javascript">
455
+ if (hayDatosSinGuardar()) {
456
+ confirmarSalida();
457
+ } else {
458
+ ui.closeApp();
459
+ }
460
+ </script>
461
+ </action>
462
+ </onback>
463
+ ```
464
+
465
+ **Ejemplo real** (patron estándar en todos los proyectos del wiki):
466
+
467
+ ```xml
468
+ <onback show-wait-dialog="false">
469
+ <action name="runscript">
470
+ <script language="javascript">
471
+ ui.getView(self).exit();
472
+ </script>
473
+ </action>
474
+ </onback>
475
+ ```
476
+
477
+ **Ejemplo real** (del proyecto UseCars - EntradaApp, con confirmacion):
478
+
479
+ ```xml
480
+ <onback>
481
+ <script>
482
+ if (confirmar("¿Desea salir de la aplicación?", "Salir")) {
483
+ appData.exit();
484
+ }
485
+ </script>
486
+ </onback>
487
+ ```
488
+
489
+ **Ejemplo real** (del proyecto EspecialChat, lógica condicional):
490
+
491
+ ```xml
492
+ <onback show-wait-dialog="false" refresh="false">
493
+ <action name="runscript">
494
+ <script language="javascript">
495
+ salir();
496
+ </script>
497
+ </action>
498
+ </onback>
499
+ ```
500
+
501
+ ### 3.6 onrefresh - Al refrescar vista
502
+
503
+ **Ambito:** object | **Tipo:** interno
504
+
505
+ Se dispara cuando se refresca la vista del objeto.
506
+
507
+ ```xml
508
+ <onrefresh>
509
+ <action name="runscript">
510
+ <script language="javascript">
511
+ actualizarContadores();
512
+ </script>
513
+ </action>
514
+ </onrefresh>
515
+ ```
516
+
517
+ ### 3.7 postonchange (atributo) - Post-cambio
518
+
519
+ **Ambito:** property | **Tipo:** atributo
520
+
521
+ Se ejecuta después de que cambia el valor de una propiedad. A diferencia de `onchange`, se ejecuta en un segundo paso, permitiendo realizar acciones de post-procesamiento como refrescar la UI o ejecutar otro nodo.
522
+
523
+ ```xml
524
+ <prop name="FOTO" type="IMG"
525
+ method="executenode(HacerFoto)"
526
+ postonchange="actualizarGaleria();"/>
527
+
528
+ <prop name="BNew" type="B" img="nuevo.png"
529
+ method="ExecuteNode(nuevo)"
530
+ postonchange="refresh"/>
531
+
532
+ <prop name="EGECUTARYREFRES" type="B"
533
+ method="executeNode(pulsaronchange('EspecialColeccionDePegaOnchange'))"
534
+ postonchange="ExecuteNode(postpulsaronchange)"/>
535
+ ```
536
+
537
+ ### 3.8 ontextchanged - Cambio de texto en tiempo real
538
+
539
+ **Ambito:** property | **Tipo:** atributo
540
+
541
+ Se dispara cada vez que el usuario escribe o borra un carácter en un campo de texto. Recibe un objeto evento con información sobre el cambio.
542
+
543
+ ```xml
544
+ <prop name="MAP_ONTEXTCHANGED" title="onTextChanged" type="T"
545
+ ontextchanged="javascript:eventoOnTextChanged(e);"/>
546
+ ```
547
+
548
+ **Ejemplo real** (del proyecto EspecialEventos - la función receptora en JS):
549
+
550
+ ```javascript
551
+ function eventoOnTextChanged(evento) {
552
+ self["MAP_DESCRIPCIONEVENTO"] = "onTextChanged! target: " + evento.target
553
+ + "\nObjItem: " + evento.objItem
554
+ + "\nTecla pulsada: " + evento.keyPressed
555
+ + "\noldText: " + evento.oldText
556
+ + "\nnewText: " + evento.newText;
557
+ ui.getView(self).refresh("MAP_DESCRIPCIONEVENTO");
558
+ }
559
+ ```
560
+
561
+ **Ejemplo real** (del proyecto EspecialContents, filtrado en tiempo real):
562
+
563
+ ```xml
564
+ <prop name="MAP_BUSCAR_TEXT"
565
+ ontextchanged="javascript:FiltraMarcados(e);"
566
+ labelwidth="0" text-border="true" type="T"
567
+ width="98%" height="60p" tooltip="Texto a buscar"/>
568
+ ```
569
+
570
+ ```javascript
571
+ function FiltraMarcados(e) {
572
+ self.MAP_BUSCAR_TEXT = e.newText;
573
+ self.executeNode("applyfilter");
574
+ }
575
+ ```
576
+
577
+ **Propiedades del objeto evento (`e`):**
578
+
579
+ | Propiedad | Tipo | Descripción |
580
+ |-----------|------|-------------|
581
+ | `e.target` | string | Nombre del campo que disparo el evento |
582
+ | `e.objItem` | object | Referencia al objeto que contiene el campo |
583
+ | `e.keyPressed` | string | Tecla pulsada |
584
+ | `e.oldText` | string | Texto anterior al cambio |
585
+ | `e.newText` | string | Texto nuevo después del cambio |
586
+
587
+ ### 3.9 onfocuschanged - Cambio de foco
588
+
589
+ **Ambito:** property | **Tipo:** atributo
590
+
591
+ Se dispara cuando un campo gana o pierde el foco.
592
+
593
+ ```xml
594
+ <prop name="MAP_ONFOCUSCHANGED01"
595
+ onfocuschanged="javascript:eventoOnFocusChanged(e);"
596
+ title="Evento onFocus" type="T"/>
597
+ ```
598
+
599
+ **Ejemplo real** (del proyecto EspecialEventos):
600
+
601
+ ```javascript
602
+ function eventoOnFocusChanged(evento) {
603
+ self.MAP_DESCRIPCIONEVENTO = "onFocusChanged! target: " + evento.target
604
+ + "\nObjItem: " + evento.objItem
605
+ + "\nTiene foco: " + evento.isFocused;
606
+ ui.getView(self).refresh("MAP_DESCRIPCIONEVENTO");
607
+ }
608
+ ```
609
+
610
+ **Ejemplo real** (del proyecto EspecialChat, en campo de texto del chat):
611
+
612
+ ```xml
613
+ <prop name="MAP_TITLE"
614
+ onfocuschanged="javascript:AccionesChatEspecial('foco', e);"
615
+ ontextchanged="javascript:AccionesChatEspecial('textoChange', e);"
616
+ type="T" visible="1" width="424p" height="80p"/>
617
+ ```
618
+
619
+ **Propiedades del objeto evento (`e`):**
620
+
621
+ | Propiedad | Tipo | Descripción |
622
+ |-----------|------|-------------|
623
+ | `e.target` | string | Nombre del campo |
624
+ | `e.objItem` | object | Referencia al objeto |
625
+ | `e.isFocused` | boolean | `true` si gano el foco, `false` si lo perdio |
626
+
627
+ ### 3.10 onscroll - Al hacer scroll
628
+
629
+ **Ambito:** frame | **Tipo:** atributo
630
+
631
+ Se dispara cuando el usuario hace scroll dentro de un frame con `scroll="true"`.
632
+
633
+ ```xml
634
+ <frame name="atttop" align="top" height="100%" width="100%"
635
+ scroll="true"
636
+ onscroll="javascript:scrollArrow(e, '2');">
637
+ <!-- contenido -->
638
+ </frame>
639
+ ```
640
+
641
+ **Ejemplo real** (del proyecto EspecialEventos, mostrar/ocultar flecha de scroll):
642
+
643
+ ```javascript
644
+ function scrollArrow(e, miparam) {
645
+ if (miparam == 1) {
646
+ if (e.dy <= 10 && self.MAP_VALORVER == 1) {
647
+ self.MAP_VALORVER = 0;
648
+ ui.getView(self).refresh("frmblotante");
649
+ } else if (e.dy > 10 && self.MAP_VALORVER == 0) {
650
+ self.MAP_VALORVER = 1;
651
+ ui.getView(self).refresh("frmblotante");
652
+ }
653
+ }
654
+ }
655
+ ```
656
+
657
+ **También se puede usar `bind` en `before-edit` para asignar el evento por script:**
658
+
659
+ ```javascript
660
+ v.bind("sctop", "onscroll", function(e) {
661
+ if (e.dy <= 10 && self.MAP_SCSHOWOVERSCROLL == 1) {
662
+ self.MAP_SCSHOWOVERSCROLL = 0;
663
+ ui.getView(self).refresh("scfroverscroll");
664
+ } else if (e.dy > 10 && self.MAP_SCSHOWOVERSCROLL == 0) {
665
+ self.MAP_SCSHOWOVERSCROLL = 1;
666
+ ui.getView(self).refresh("scfroverscroll");
667
+ }
668
+ });
669
+ ```
670
+
671
+ **Propiedades del objeto evento (`e`):**
672
+
673
+ | Propiedad | Tipo | Descripción |
674
+ |-----------|------|-------------|
675
+ | `e.dy` | number | Desplazamiento vertical acumulado |
676
+
677
+ ### 3.11 onfocus (grupo) - Al enfocar un grupo
678
+
679
+ **Ambito:** group | **Tipo:** atributo
680
+
681
+ Se dispara cuando un grupo (pestana) recibe el foco, típicamente al cambiar de tab con `group-swipe="true"`.
682
+
683
+ ```xml
684
+ <group name="Group1" id="1" onfocus="ExecuteNode(onfocusgrupo(1))">
685
+ <!-- contenido -->
686
+ </group>
687
+ <group name="Group2" id="2" onfocus="ExecuteNode(onfocusgrupo(2))">
688
+ <!-- contenido -->
689
+ </group>
690
+ ```
691
+
692
+ **Ejemplo real** (nodo custom asociado, presente en todos los proyectos del wiki):
693
+
694
+ ```xml
695
+ <onfocusgrupo show-wait-dialog="false">
696
+ <action name="runscript">
697
+ <param name="index"/>
698
+ <script language="javascript">
699
+ self.MAP_GROUP = index;
700
+ </script>
701
+ </action>
702
+ </onfocusgrupo>
703
+ ```
704
+