Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
wiki:2.-desarrollo-app:2.6.-demos-y-ejemplos:b.-ejemplos-codigo-javascript:start [2017/10/30 11:37] – [Botón con Script] patricia | wiki:2.-desarrollo-app:2.6.-demos-y-ejemplos:b.-ejemplos-codigo-javascript:start [2023/10/06 12:08] (actual) – [Obtener nombre de la Colección Actual (activa en ese momento)] ary | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
+ | |||
+ | {{indexmenu_n> | ||
+ | ====== Ejemplos de código Javascript ====== | ||
+ | <WRAP center round important 60%> | ||
+ | Para poder utilizar las funciones **cstr**, **now**, **len**, etc de VBScript, se ha implementado un fichero " | ||
+ | </ | ||
+ | =====Código que recorre una colección completa===== | ||
+ | Código para recorrer una colección registro a registro (Cuando son muchos datos para cargarlos todos en memoria). | ||
+ | <code javascript> | ||
+ | function recorrerColeccion() { | ||
+ | var sMensaje = "Estos son los usuarios:"; | ||
+ | // Variable con la coleccion que se va a utilizar | ||
+ | var mColeccion = appData.getCollection(" | ||
+ | |||
+ | // Guardamos el filtro que tiene la colección actualmente | ||
+ | var filtro=mColeccion.getFilter(); | ||
+ | |||
+ | // Le ponemos un filtro a la colección | ||
+ | mColeccion.setFilter(" | ||
+ | |||
+ | // Variable con la coleccion que se va a utilizar | ||
+ | mColeccion.startBrowse(); | ||
+ | try { | ||
+ | var mObjeto; | ||
+ | while((mObjeto = mColeccion.getCurrentItem()) != undefined) { | ||
+ | sMensaje = sMensaje + " | ||
+ | mColeccion.moveNext(); | ||
+ | } | ||
+ | } catch(ex) { | ||
+ | ui.showToast(" | ||
+ | } finally { | ||
+ | // Cerramos el recordset | ||
+ | mColeccion.endBrowse(); | ||
+ | |||
+ | // Dejamos la colección con el filtro que tenía al principio | ||
+ | mColeccion.setFilter(filtro); | ||
+ | } | ||
+ | return sMensaje; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | =====Recorrer una colección/ | ||
+ | Una colección con pocos datos (Por ejemplo, las filas de detalles de un contents), pueden recorrerse cargando los registros en un array de memoria en lugar de ir recorriendo registro a registro. | ||
+ | |||
+ | <code javascript> | ||
+ | function recorrerContents() | ||
+ | { | ||
+ | // Todas las variables que definamos dentro de una funcion son locales a ésta. | ||
+ | var coll; | ||
+ | var collCount; | ||
+ | var SUM=0; | ||
+ | var i; | ||
+ | var obj; | ||
+ | |||
+ | // (Para hacer referencia al objeto actual se utiliza self, para no interferir con el this de javascript). | ||
+ | self.MAP_TLCABECERAROJO=" | ||
+ | self.MAP_TLCABECERAROJO1=" | ||
+ | |||
+ | collCount=0; | ||
+ | SUM=0; | ||
+ | // Cogemos la coll contents Detalles del objeto actual | ||
+ | coll=self.getContents(" | ||
+ | |||
+ | // Cargamos los registros en memoria y averiguamos el número de registros | ||
+ | coll.loadAll(); | ||
+ | collCount=coll.count(); | ||
+ | |||
+ | // Utilizamos un For para recorrer los registros del contents. | ||
+ | for (i=0; | ||
+ | // Tomamos un registro del content con el indice de dicho registro. | ||
+ | obj=coll.get(i); | ||
+ | SUM=parseFloat(SUM)+parseFloat(obj.IMPORTETOTAL); | ||
+ | } | ||
+ | self.MAP_TLVISITASSIN=" | ||
+ | self.MAP_VISITASSIN=SUM; | ||
+ | |||
+ | // Liberamos la memoria que cargamos con el loadall. | ||
+ | coll.clear(); | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | ===== Obtener un objeto (fila) de una colección, teniendo el valor de un campo de dicho objeto ===== | ||
+ | \\ | ||
+ | <code javascript> | ||
+ | function MarcarIncidencia(idIncid) | ||
+ | { | ||
+ | // Buscamos una incidencia en concreto conociendo el valor de algún campo único (Siempre se busca como cadena). | ||
+ | var collInc = appData.getCollection(" | ||
+ | var objInc = collInc.getObject(vb.cstr(idIncid)); | ||
+ | |||
+ | objInc.CERRADA=1; | ||
+ | objInc.FECHACIERREXONE=vb.now(); | ||
+ | objInc.save(); | ||
+ | | ||
+ | objInc=null; | ||
+ | collInc.clear(); | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | ===== Obtener un objeto (fila) de una colección, utilizando una SQL con más de un campo (FINDOBJECT) ===== | ||
+ | \\ | ||
+ | < | ||
+ | |||
+ | <code javascript> | ||
+ | function ejemploFindObject() { | ||
+ | var nId = 2; | ||
+ | var mObjeto = appData.getCollection(" | ||
+ | if(mObjeto == undefined) { | ||
+ | ui.msgBox(" | ||
+ | } | ||
+ | else { | ||
+ | ui.msgBox(" | ||
+ | |||
+ | // Lo lanzamos en edición | ||
+ | appData.pushValue(mObjeto); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ===== Obtener nombre de la Colección Actual (activa en ese momento) ===== | ||
+ | \\ | ||
+ | <code javascript> | ||
+ | function getCurrentCollName() { | ||
+ | let ventana = ui.getView(); | ||
+ | if (!ventana) { | ||
+ | return ""; | ||
+ | } | ||
+ | let dataObject = ventana.getDataObject(); | ||
+ | if (!dataObject) { | ||
+ | return ""; | ||
+ | } | ||
+ | let ownerCollection = dataObject.getOwnerCollection(); | ||
+ | return ownerCollection.getName(); | ||
+ | } | ||
+ | </ | ||
+ | ===== Crear Registro con Script ===== | ||
+ | \\ | ||
+ | Crear un nuevo registro con script. El script se podrá ejecutar en un **create, insert, delete, botón**...\\ | ||
+ | \\ | ||
+ | <code javascript> | ||
+ | function creaRegistro() { | ||
+ | var cCierre = appData.getCollection(" | ||
+ | var objCierre = cCierre.createObject(); | ||
+ | | ||
+ | cCierre.addItem(objCierre); | ||
+ | | ||
+ | objCierre.NUMINCIDENCIA=self.NUMINCIDENCIA; | ||
+ | objCierre.NUMPROGRESO=self.NUMPROGRESO; | ||
+ | objCierre.CODTECNICO=self.CODTECNICO; | ||
+ | | ||
+ | objCierre.save(); | ||
+ | // Si queremos lanzarlo en edición | ||
+ | appData.pushValue(objCierre); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Nodo para irnos a una colección pasando un parámetro (irColl/ | ||
+ | \\ | ||
+ | Primero tendríamos un botón para llamar a este nodo: | ||
+ | <code xml> | ||
+ | <prop name=" | ||
+ | </ | ||
+ | |||
+ | El código del nodo quedaría: | ||
+ | <code xml> | ||
+ | ' | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | var coll = appData.getCollection(parametro); | ||
+ | var det = coll.createObject(); | ||
+ | // Lo lanzamos en edición | ||
+ | appData.pushValue(det); | ||
+ | |||
+ | //En lugar de poner aqui el código directamente, | ||
+ | // | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <code javascript> | ||
+ | function ircoll(collname){ | ||
+ | var coll = appData.getCollection(collname); | ||
+ | var obj = coll.createObject(); | ||
+ | coll.addItem(obj); | ||
+ | appData.pushValue(obj); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Mostrar mensajes por pantalla ===== | ||
+ | Tenemos varias formas de mostrar un mensaje en pantalla. | ||
+ | |||
+ | |< 95% 30% - >| | ||
+ | ^ Comando | ||
+ | | ui.msgBox(" | ||
+ | Mensaje del framework que necesita respuesta por parte del usuario. | ||
+ | El último parámetro puede ser: | ||
+ | * **0**, que no devuelve ningún valor, únicamente aparece un botón OK. | ||
+ | * **2**, que nos muestra 2 botones: ACEPTAR y CANCELAR que devuelven un 1 ó un 2 respectivamente, | ||
+ | * **4**, que nos muestra 2 botones: SI y NO que devuelven un 6 ó un 7 respectivamente, | ||
+ | </ | ||
+ | | ui.showNotification(1, | ||
+ | | ui.dismissNotification(1); | ||
+ | | ui.showToast(" | ||
+ | \\ | ||
+ | **Ejemplo de código:** | ||
+ | <code xml> | ||
+ | <!-- En este caso vamos a hacer uso del nodo replica-ok, para capturar el evento de cuando recibimos operaciones en la tabla gen_mensajeria --> | ||
+ | < | ||
+ | <action name=" | ||
+ | < | ||
+ | |||
+ | // AppData.UserInterface.MsgBox hace exactamente lo mismo, ui es una abreviatura de AppData.UserInterface. | ||
+ | ui.msgBox(" | ||
+ | |||
+ | // El primer parámetro es el ID por si hay que modificarla luego | ||
+ | ui.showNotification(1, | ||
+ | |||
+ | // Con la siguiente línea cambiaríamos el título y el mensaje de la notificación existente, pues tienen el mismo ID. | ||
+ | // ui.showNotification(1, | ||
+ | |||
+ | // Si queremos quitar la notificación, | ||
+ | // | ||
+ | |||
+ | // Para sacar un mensajito efímero que dura 3 segundos en pantalla. | ||
+ | ui.showToast(" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | ===== Salir de la ventana actual. Nodo onback. ===== | ||
+ | \\ | ||
+ | |||
+ | <code xml> | ||
+ | |||
+ | <!-- En éste caso al nodo que ejecutamos lo hemos llamado " | ||
+ | que el botón de volver atrás físico de android nos ejecute ésta misma acción --> | ||
+ | |||
+ | <onback refresh=" | ||
+ | <action name=" | ||
+ | < | ||
+ | // | ||
+ | //if (st_msg!="" | ||
+ | // | ||
+ | |||
+ | appData.failWithMessage(-11888,"## | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | \\ | ||
+ | ===== Ejecutar alguna acción SIN replicar las operaciones ===== | ||
+ | \\ | ||
+ | Si estamos trabajando offline, por defecto, todo lo que se hace en el framework se va almacenando en la tabla master_replica_queue del dispositivo para posteriormente replicarla al servidor.\\ | ||
+ | Si en algún momento no deseamos que ésto suceda, podemos realizar alguna operación directamente sobre la base de datos del dispositivo sin que se llegue a replicar al servidor. \\ | ||
+ | Este comportamiento es muy utilizado en los mantenimientos sobre la base de datos local del dispositivo para eliminar información que ya no necesitamos (Partes o Pedidos antiguos, etc...).\\ | ||
+ | La metodología es muy simple, se trata de crear una colección que " | ||
+ | |||
+ | <WRAP center round alert 80%>No puede haber 2 nodos **< | ||
+ | |||
+ | <code xml> | ||
+ | <!-- Primero hemos de definir una colección que tenga un atributo connection que apunte directamente a la base de datos local del dispositivo --> | ||
+ | <coll name=" | ||
+ | sql=" | ||
+ | FROM ## | ||
+ | |||
+ | <!-- Esta definición de connection es preferible hacerla en el nodo APP y así otras colecciones puedan hacer uso de ella. --> | ||
+ | < | ||
+ | |||
+ | <group name=" | ||
+ | </ | ||
+ | |||
+ | <!-- En cualquier momento podemos ejecutar un script que nos ejecute las operaciones "al margen" | ||
+ | < | ||
+ | <action name=" | ||
+ | < | ||
+ | | ||
+ | appData.getCollection(" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== MACRO de usuario para cambiar el filtro de una colección ===== | ||
+ | Podemos crear una MACRO de usuario en una colección para sustituir en tiempo real la SQL de una colección, pudiendo llegar a sustituir incluso la SQL de la colección completa. | ||
+ | |||
+ | <code xml> | ||
+ | <coll name=" | ||
+ | sql=" | ||
+ | LEFT JOIN ## | ||
+ | filter=" | ||
+ | |||
+ | <macro name="## | ||
+ | |||
+ | </ | ||
+ | |||
+ | Una vez definida la macro en la colección, posteriormente podemos utilizarla para cambiar el valor de dicha macro y por lo tanto cambiar el SQL.\\ | ||
+ | En éste caso concreto, cambiamos el filtro de una colección cuando cambie el valor de un campo " | ||
+ | <code xml> | ||
+ | < | ||
+ | <field name=" | ||
+ | < | ||
+ | < | ||
+ | collGastos = self.getContents(" | ||
+ | |||
+ | //Aquí cambiamos el valor de la macro que tenemos definida en la colección Gastos. | ||
+ | collGastos.setMacro("## | ||
+ | |||
+ | //Así sería el comando para obtener el valor de una macro. | ||
+ | var Valor=collGastos.getMacro("## | ||
+ | |||
+ | self.executeNode(" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Variables globales o de colección ===== | ||
+ | \\ | ||
+ | Podemos crear variables que tengan ámbito global y así puedan estar disponibles desde cualquier lugar de la aplicación.\\ | ||
+ | \\ | ||
+ | Una opción sería incluir un fichero **.js** en la colección de empresas, donde se definirían con " | ||
+ | \\ | ||
+ | El otro método sería el que se ha utilizado hasta ahora en la plataforma: | ||
+ | |||
+ | <code javascript> | ||
+ | |||
+ | // Para establecer el valor de una variable global: | ||
+ | |||
+ | appData.getCurrentEnterprise().setVariables(" | ||
+ | |||
+ | // Para obtener el valor de una variable global: | ||
+ | |||
+ | vLastPieza=appData.getCurrentEnterprise().getVariables(" | ||
+ | |||
+ | // Para establecer el valor de una variable de la colección " | ||
+ | |||
+ | var mColeccion = appData.getCollection(" | ||
+ | mColeccion.setVariables(" | ||
+ | |||
+ | // Para obtener el valor de una variable de la colección " | ||
+ | |||
+ | var mColeccion = appData.getCollection(" | ||
+ | var sMensaje = mColeccion.getVariables(" | ||
+ | </ | ||
+ | |||
+ | ===== Ir a otra pestaña o group ===== | ||
+ | \\ | ||
+ | <code javascript> | ||
+ | ui.showGroup(self.MAP_PAGINA,"## | ||
+ | </ | ||
+ | |||
+ | ===== Codigo para Crear/ | ||
+ | <code javascript> | ||
+ | //Para poder dar de __ALTA__ un registro en un contents tendríamos que pasarle el ID de la cabecera... | ||
+ | function addContents(coll, | ||
+ | var CollCV = appData.getCollection(coll); | ||
+ | var ObjCV = CollCV.createObject(); | ||
+ | CollCV.addItem(ObjCV); | ||
+ | ObjCV(campoenlace) = self.ID; | ||
+ | |||
+ | appData.pushValue(ObjCV); | ||
+ | } | ||
+ | |||
+ | //A ésta función tenemos que pasarle la referencia al contents y el ID que queremos EDITAR. | ||
+ | function editContents(coll, | ||
+ | var CollCV = appData.getCollection(coll); | ||
+ | var ObjCV = CollCV.findObject(" | ||
+ | if (ObjCV) { | ||
+ | appData.pushValue(ObjCV); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Realmente no borramos el registro físicamente, | ||
+ | //ó podemos ponerle un BAJA=1, para darlo de baja lógica. Posteriormente tendríamos un mantenimiento para | ||
+ | //eliminar éstos registros del dispositivo (Para que no se replique el borrado físico del registro). | ||
+ | function deleteContents(coll, | ||
+ | var result = ui.msgBox(" | ||
+ | if (result == 6) { | ||
+ | var CollCV = appData.getCollection(coll); | ||
+ | var ObjCV = CollCV.findObject(" | ||
+ | if (ObjCV) { | ||
+ | ObjCV.campoenlace = -9999; | ||
+ | ObjCV.save(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | =====Tipos de errores===== | ||
+ | \\ | ||
+ | <code vb> | ||
+ | |||
+ | <script language=" | ||
+ | 'ERROR DISPONIBLE EN TODAS LAS PLATAFORMAS | ||
+ | ' | ||
+ | appdata.failwithmessage -8100," | ||
+ | | ||
+ | ' | ||
+ | ' | ||
+ | appdata.failwithmessage -7500," | ||
+ | | ||
+ | ' | ||
+ | appdata.failwithmessage -666," | ||
+ | | ||
+ | ' | ||
+ | appdata.failwithmessage -11888," | ||
+ | | ||
+ | ' | ||
+ | appdata.failwithmessage -11822," | ||
+ | | ||
+ | ' | ||
+ | appdata.failwithmessage -11811," | ||
+ | | ||
+ | ' | ||
+ | Appdata.FailWithMessage -8100,"## | ||
+ | | ||
+ | 'Esta macro funciona conjuntamente con CGStart (kiosko de PDA). | ||
+ | ' | ||
+ | 'Si el kiosko no está instalado, simplemente se cierra la aplicación. | ||
+ | Appdata.FailWithMessage -8100,"## | ||
+ | | ||
+ | 'Salir de la aplicacion. | ||
+ | Appdata.FailWithMessage -8100,"## | ||
+ | | ||
+ | 'Usado para salir de las ventanas de Nomen y Edit. | ||
+ | Appdata.FailWithMessage -8100,"## | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | \\ | ||
+ | |||
+ | |||
+ | =====Botón con Script===== | ||
+ | \\ | ||
+ | CÓDIGO PARA REALIZAR UN BOTÓN. \\ | ||
+ | \\ | ||
+ | Está formado por **2 nodos**:\\ | ||
+ | \\ | ||
+ | |**Nodo 1** |**Prop de tipo " | ||
+ | |**Nodo 2** |**Nodo en el que se pone el código que se va a ejecutar**| El nombre es definido por el usuario, y como único requisito, es el nombre del nodo, tiene que llamarse igual (mayúsculas-minúsculas) que el nodo al que llama el nodo button en su atributo method.| | ||
+ | \\ | ||
+ | <code xml> | ||
+ | <prop name=" | ||
+ | |||
+ | < | ||
+ | <action name=" | ||
+ | < | ||
+ | var vResult; | ||
+ | vResult =ui.msgBox(" | ||
+ | if (vResult==1) { | ||
+ | //La siguiente sentencia METE las cosas en réplica, como siempre en operaciones atómicas, | ||
+ | //es decir, operaciones que únicamente afectan a un registro cada vez. Si no se desea meter | ||
+ | // | ||
+ | appData.executeSql(" | ||
+ | ui.msgBox(" | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | \\ | ||
+ | ===== Generar UUID ===== | ||
+ | \\ | ||
+ | Generar un UUID con Javascript. | ||
+ | \\ | ||
+ | <code javascript> | ||
+ | function generateUUID() { | ||
+ | var d = new Date().getTime(); | ||
+ | var uuid = ' | ||
+ | var r = (d + Math.random()*16)%16 | 0; | ||
+ | d = Math.floor(d/ | ||
+ | return (c==' | ||
+ | }); | ||
+ | return uuid; | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Obtener la fecha actual ===== | ||
+ | <code javascript> | ||
+ | // Ejemplo de uso: var f=getFecha(" | ||
+ | function getFecha(formato, | ||
+ | { | ||
+ | var sToday = ""; | ||
+ | var today = new Date(); | ||
+ | var dd = today.getDate(); | ||
+ | var mm = today.getMonth()+1; | ||
+ | var yyyy = today.getFullYear(); | ||
+ | |||
+ | if(dd< | ||
+ | dd=' | ||
+ | } | ||
+ | |||
+ | if(mm< | ||
+ | mm=' | ||
+ | } | ||
+ | |||
+ | if (!separador) { | ||
+ | separador="/"; | ||
+ | } | ||
+ | if (formato) { | ||
+ | switch (formato){ | ||
+ | case " | ||
+ | sToday = dd+separador+mm+separador+yyyy; | ||
+ | break; | ||
+ | case " | ||
+ | sToday = mm+separador+dd+separador+yyyy; | ||
+ | break; | ||
+ | case " | ||
+ | sToday = yyyy+separador+mm+separador+dd; | ||
+ | break; | ||
+ | default: | ||
+ | sToday = dd+"/" | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | sToday = dd+"/" | ||
+ | } | ||
+ | return sToday; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | =====Información Queue Dispositivo===== | ||
+ | \\ | ||
+ | COLECCION QUE MUESTRA LA CANTIDAD DE DATOS QUE QUEDAN POR ENVIAR.\\ | ||
+ | \\ | ||
+ | |||
+ | Esta colección se puede complicar todo lo que se quiera, incluso poniendo **Join** con otras tablas, para decir de que tabla faltan los datos | ||
+ | por enviar desde el dispositivo móvil a la central.\\ | ||
+ | \\ | ||
+ | |||
+ | La tabla MASTER_REPLICA_QUEUE, | ||
+ | tabla de sistema, con la cual se enviarán los datos desde el dispositivo móvil al servidor central.\\ | ||
+ | \\ | ||
+ | |||
+ | <code xml> | ||
+ | <coll name=" | ||
+ | sql=" | ||
+ | FROM master_replica_queue" | ||
+ | objname=" | ||
+ | editwidth=" | ||
+ | <group name=" | ||
+ | <prop name=" | ||
+ | </ | ||
+ | </ | ||
+ | \\ | ||
+ | |||
+ | |