JavaScript nativo

JavaScript nativo permite ejecutar código JavaScript dentro de un script de Ninox y compartir funciones y variables con él. Así, JavaScript nativo puede acceder a las variables de Ninox y llamar tanto a funciones locales como globales.

imagen.png

Limitaciones

Modificar una variable de Ninox en NativeJS no afecta a la variable de Ninox.

JavaScript solo se ejecuta localmente. Añadir JavaScript a código que se ejecuta en el servidor no tiene ningún efecto. Del mismo modo, llamar desde código ejecutado en el servidor a una función global que contiene JavaScript tampoco tiene efecto.

Vea aquí qué códigos se ejecutan localmente y cuáles en el servidor:

imagen.png

Sintaxis

Ejecución

Para indicar a Ninox que pasa a JavaScript, hay que encerrar el código entre #{ ... }#:

#{ alert("hello world") }#;

Recuerde que Ninox es un lenguaje precompilado que necesita conocer de antemano el tipo de cada variable y de cada función. Lo mismo ocurre con JavaScript nativo: debe indicar el tipo devuelto por el código JavaScript. De forma predeterminada, JavaScript nativo devuelve texto, pero puede indicar el tipo de variable que desea devolver especificándolo justo al principio del código con la notación :[type].

Valor devuelto

#{:text return "hello world"}#;

Los tipos posibles son los mismos que se usan en las llamadas a funciones: text, number, date, datetime, time, timeinterval, appointment, boolean, html, color, icon, email, phone, location, file, user y any.

Tipos de tabla (array)

Para devolver un array, use la sintaxis siguiente:

#{:number(array) return [1,2,3] }#;

Tipos de registro

Para devolver registros, use el nombre de la tabla seguido de nid o rid:

Si usa nid, debe devolver un array de valores de texto con el identificador completo del registro, que incluye el identificador de la tabla + el número de registro:

#{:nid(customer) return ['A1','A2','A3'] }#

Si usa rid, debe devolver el número de registro:

#{:rid(customer) return [1,2,3] }#

Para nombres de tabla compuestos, no añada como en Ninox: use simplemente el nombre completo de la tabla:

#{:rid(my long name table) return [1,2,3] }#

Con esta sintaxis, JavaScript nativo devuelve variables que se comportan igual que el código de Ninox. Es decir, puede usar la sintaxis siguiente como si se tratara de un select:

(#{:rid(customer) return [1,2,3] }# order by 'Last Name').'First Name';

imagen.png

Modificación de registros

Las variables de tipo registro se pasan en formato JSON, con un par clave-valor por cada campo del registro.

var r := first(select Customer);
#{:text return r['First Name'] }#;

Aquí, el contenido de la variable r en JavaScript es el siguiente:

{
 "Created on": 1648910817206,
 "Id": "A1",
 "Last modified": 1714817525840,
 "Modified by": "7zBqhAKXxfQAPmH7Y",
 "First Name": "Sofia",
 "Last Name": "Young",
 "Company": "Kollwitz GmbH",
 "Postal Code": "12345",
 "City": "New Jersey",
 "Address": "11,South Commerce Street",
 "Email": "sofi@kollwitz-gmbh.com",
 "Customer No": "K0001",
 "Title": "2",
 "Invoices": [
  1,
  16,
  17
 ],
 "Photo": "shutterstock_307218608.jpg",
 "Category": "1",
 "Position": "Marketing head",
 "Checked": true,
 "ID": "A1",
 "id": "A1"
}

Importante

Según se ejecute el código en la aplicación de Mac o en la web, el ID puede llevar mayúsculas o minúsculas distintas.
Para resolverlo y evitar conflictos entre plataformas, el ID se repite con todas las variantes posibles de mayúsculas y minúsculas.

Modificar el registro en JavaScript no lo actualiza en Ninox.

Ejecución asíncrona

A veces resulta útil sincronizar la ejecución del código de Ninox con la de JavaScript.
Por ejemplo, al usar un temporizador, es importante que el código solo termine después de que el temporizador haya terminado de ejecutarse.
Sin esa sincronización, el código posterior a la ejecución de JavaScript se ejecutaría de inmediato, lo que podría provocar comportamientos inesperados.

En este primer caso, el valor «I don't know» se devuelve de inmediato, y la función alert muestra el resultado antes de que la pregunta llegue siquiera a presentarse al usuario.

var r:= #{:text
   setTimeout( () => {
      if (confirm("Are you ok ?"))
        return "of course";
      else
        return "Never !";
   }, 2000);
  return "I don't know";
}#;
alert( "Your answer is : "+r );

imagen.png

Al pasar al modo callback, la función alert de Ninox se ejecuta solo después de que el código JavaScript haya llamado a la función de retorno, es decir, después de haber presentado la pregunta al usuario.

var r:= #{:text:callback
   setTimeout( () => {
      if (confirm("Are you ok ?"))
         callback( "of course" );
      else
        callback( "Never !" );
   }, 2000);
   return "I don't know";
}#;
alert( "Your answer is : "+r );

Grabación de pantalla 2025-03-03 a las 11.46.26.gif

Llamada a funciones

Se puede llamar a funciones de Ninox desde JavaScript. El procedimiento puede ser local o global; basta con que esté dentro del ámbito del código JavaScript.

function display( message : text ) do
    alert( message );
end;
#{ display('hello world') }#;

imagen.png

Para recuperar el valor devuelto por una función, hay que usar de nuevo el modo callback (véase más arriba: Ejecución asíncrona):

function add( a : number, b : number ) do
    a + b;
end;

#{:number:callback
   add( 1, 2, (returnValue) => {
     callback( returnValue )
   })
}#;

imagen.png

Si no tiene ningún tratamiento pendiente después de llamar al procedimiento, puede pasar directamente la función de retorno como parámetro:

function add( a : number, b : number ) do
    a + b;
end;
#{:number:callback
   add( 1, 2, callback )
}#;

imagen.png

Manipular registros y funciones

Si dispone de una lista de identificadores de registro, puede llamar a una función de Ninox para modificar cada registro uno a uno. Para ello, basta con llamar a la función pasándole el identificador.

function setCustomerChecked( id : text, checked : boolean ) do
   var n := number(replacex(id, "\D",""));
   var rec := record( Customer, n );
   rec.Checked := checked;
end;
var c := select Customer;
var isChecked := not first(c).Checked;
#{
   c.forEach( v => { setCustomerChecked( v, isChecked ) } );
}#;
c.checked;

Errores de ejecución

Si se produce un error de ejecución en su código, se devolverá el texto del mensaje de error:

imagen.png