原生 JS

原生 JS 讓您可以在 Ninox 腳本中執行 JavaScript 程式碼,並與腳本共用函式與變數。如此一來,原生 JS 就能存取 Ninox 變數,並呼叫本機函式與全域函式。

image.png

限制

在原生 JS 中修改 Ninox 變數,並不會影響該 Ninox 變數。

JavaScript 只會在本機執行。把 JavaScript 加進在伺服器上執行的程式碼中不會有任何效果;同樣地,從在伺服器上執行的程式碼呼叫含有 JavaScript 的全域函式,也不會有任何效果。

哪些程式碼在本機執行、哪些在伺服器上執行,請參見下圖:

image.png

語法

執行

若要告訴 Ninox 您正切換到 JavaScript,必須把程式碼包在 #{ ... }# 之中:

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

別忘了,Ninox 是預先編譯的語言,必須事先知道每個變數與函式的型別。原生 JS 也是如此:您必須指定 JavaScript 程式碼所回傳的型別。原生 JS 預設回傳 text,但您可以在程式碼最開頭以 :[type] 這種寫法指出想回傳的變數型別。

回傳值

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

可用的型別與函式呼叫所使用的相同:textnumberdatedatetimetimetimeintervalappointmentbooleanhtmlcoloriconemailphonelocationfileuser 以及 any

陣列型別

若要回傳陣列,請使用下列語法:

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

記錄型別

若要回傳記錄,請在表格名稱後面加上 nidrid

如果使用 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';

image.png

修改記錄

記錄型別的變數以 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 );

image.png

改用 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 );

Enregistrement de l’écran 2025-03-03 à 11.46.26.gif

呼叫函式

您可以從 JavaScript 呼叫 Ninox 函式。該程序可以是本機或全域的,只要位在該段 JavaScript 程式碼的作用範圍內即可。

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

image.png

若要取得函式的回傳值,同樣必須使用回呼模式(參見上文:非同步執行):

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

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

image.png

如果呼叫該程序之後沒有其他要處理的事,您也可以直接把回呼函式當作參數傳入:

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

image.png

操作記錄與函式

如果您有一份記錄 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;

執行錯誤

如果您的程式碼發生執行錯誤,就會回傳錯誤訊息的文字

image.png