原生 JS
原生 JS 让您可以在 Ninox 脚本中执行 JavaScript 代码,并与之共享函数和变量。这样,原生 JS 就能访问 Ninox 变量,并调用本地函数和全局函数。

限制
在原生 JS 中修改 Ninox 变量不会影响该 Ninox 变量。
JavaScript 只在本地执行。把 JavaScript 加入在服务器上运行的代码不会产生任何效果。同样地,从服务器上执行的代码中调用包含 JavaScript 的全局函数也不会产生任何效果。
关于哪些代码在本地执行、哪些在服务器上执行,请参见此处:

语法
执行
要告诉 Ninox 您正在切换到 JavaScript,需要把代码包在 #{ ... }# 之中:
#{ alert("hello world") }#;
请记住,Ninox 是一种预编译语言,需要事先知道每个变量和函数的类型。原生 JS 也一样:您必须指定 JavaScript 代码所返回的类型。默认情况下,原生 JS 返回文本,但您可以在代码最开头用 :[type] 的写法指明希望返回的变量类型。
返回值
#{:text return "hello world"}#;
可用的类型与函数调用中使用的类型相同:text、number、date、datetime、time、timeinterval、appointment、boolean、html、color、icon、email、phone、location、file、user 以及 any。
数组类型
要返回数组,请使用以下语法:
#{:number(array) return [1,2,3] }#;
记录类型
要返回记录,请使用表名后跟 nid 或 rid:
如果使用 nid,您必须返回一个文本值数组,其中包含完整的记录标识符,即表标识符 + 记录编号:
#{:nid(customer) return ['A1','A2','A3'] }#
如果使用 rid,则应返回记录编号:
#{:rid(customer) return [1,2,3] }#
对于由多个词组成的表名,不要像在 Ninox 中那样加上 ‘,直接使用表的完整名称即可:
#{:rid(my long name table) return [1,2,3] }#
使用这种写法,原生 JS 返回的变量其行为与 Ninox 代码中的变量相同。也就是说,您可以像使用 select 那样使用以下写法:
(#{:rid(customer) return [1,2,3] }# order by 'Last Name').'First Name';

记录的修改
记录类型的变量以 JSON 格式传递,记录的每个字段对应一个键值对。
var r := first(select Customer);
#{:text return r['First Name'] }#;
此时,变量 r 在 JavaScript 中的内容如下所示:
{
"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"
}
重要提示
代码是在 Mac 应用上还是在网页端执行,会影响 ID 的大小写形式。
为了应对这一点并避免不同平台之间的冲突,ID 会以所有可能的大小写形式重复出现。
在 JavaScript 中修改记录并不会在 Ninox 中更新它。
异步执行
有时,把 Ninox 代码的执行与 JavaScript 同步起来会很有用。
例如在使用定时器时,代码必须在定时器执行完毕之后才结束,这一点很重要。
如果没有这种同步,JavaScript 执行之后的代码会立即运行,可能导致意料之外的行为。
在下面第一个例子中,值 “I don’t know” 会立即返回,alert 函数在问题呈现给用户之前就显示了结果。
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 );

切换到 callback 模式后,Ninox 的 alert 函数只会在 JavaScript 代码调用了回调函数之后才执行,也就是在问题呈现给用户之后。
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 );

函数调用
可以从 JavaScript 调用 Ninox 函数。该过程可以是本地的,也可以是全局的;只要处于该 JavaScript 代码的作用域内即可。
function display( message : text ) do
alert( message );
end;
#{ display('hello world') }#;

要取回函数的返回值,同样必须使用回调模式(参见上文:异步执行):
function add( a : number, b : number ) do
a + b;
end;
#{:number:callback
add( 1, 2, (returnValue) => {
callback( returnValue )
})
}#;

如果调用该过程之后不再需要做其他处理,您可以直接把回调函数作为参数传入:
function add( a : number, b : number ) do
a + b;
end;
#{:number:callback
add( 1, 2, callback )
}#;

操作记录与函数
如果您有一组记录 ID,可以调用一个 Ninox 函数来逐条修改这些记录。为此,只需调用该函数并把 ID 传给它即可。
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;
执行错误
如果您的代码发生执行错误,将返回错误消息文本:

