ao_module.js 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  1. /*
  2. ArOZ Online Module API wrapper
  3. This script is used for wrapping all the API that can be called by the ArOZ Online Module under VDI mode.
  4. For faster development, please include this script into your module and call through this script.
  5. Or otherwise, you can call directly to the ArOZ Online System via GET / POST request.
  6. <!> Warning! This script require jQuery to work.
  7. Although some functions might not require jquery, it is still recommended. You can include the jquery file from
  8. AOR/script/jquery.min.js
  9. Toby Chui @ IMUS Laboratory, All Right Reserved
  10. */
  11. //Check if current module is called in Virtal Desktop Mode
  12. var ao_module_virtualDesktop = !(!parent.isFunctionBar);
  13. //Get the current windowID if in Virtual Desktop Mode, return false if VDI is not detected
  14. var ao_module_windowID = false;
  15. var ao_module_parentID = false;
  16. var ao_module_callback = false;
  17. var ao_root = null;
  18. if (ao_module_virtualDesktop)ao_module_windowID = $(window.frameElement).parent().attr("id");
  19. if (ao_module_virtualDesktop)ao_module_parentID = $(window.frameElement).parent().find(".floatWindow").attr("puid");
  20. if (ao_module_virtualDesktop)ao_module_callback = $(window.frameElement).parent().find(".floatWindow").attr("callback");
  21. if (ao_module_virtualDesktop)ao_module_parentURL = $(window.frameElement).parent().find("iframe").attr("src");
  22. //Try to access the aoRoot by parsing the script including function
  23. $("script").each(function(){
  24. if (this.hasAttribute("src") && $(this).attr("src").includes("ao_module.js")){
  25. var tmp = $(this).attr("src");
  26. tmp = tmp.split("script/ao_module.js");
  27. ao_root = tmp[0];
  28. }
  29. });
  30. //Set the current FloatWindow with specified icon
  31. function ao_module_setWindowIcon(icon){
  32. if (ao_module_virtualDesktop){
  33. parent.setWindowIcon(ao_module_windowID + "",icon);
  34. return true;
  35. }
  36. return false;
  37. }
  38. //Set the current FloatWindow with specified title tag
  39. function ao_module_setWindowTitle(title){
  40. if (ao_module_virtualDesktop){
  41. parent.changeWindowTitle(ao_module_windowID + "",title);
  42. return true;
  43. }
  44. window.title = title;
  45. return false;
  46. }
  47. //Set the current FloatWindow to GlassEffect Window (Cannot switch back to origianl mode)
  48. function ao_module_setGlassEffectMode(){
  49. if (ao_module_virtualDesktop){
  50. parent.setGlassEffectMode(ao_module_windowID + "");
  51. return true;
  52. }
  53. return false;
  54. }
  55. //Set the current FloatWindow to Fixed Size Window (Non-resizable), default Resizable
  56. function ao_module_setFixedWindowSize(){
  57. if (ao_module_virtualDesktop){
  58. parent.setWindowFixedSize(ao_module_windowID + "");
  59. return true;
  60. }
  61. return false;
  62. }
  63. //Set the current FloatWindow size (width, height)
  64. //Cache: Should the function bar system cache the window size of this window so that the white preload window will not be shown
  65. //Exact: Should the url be exact (including .php?...) or be not exact (Only remember url till .php script filename)
  66. function ao_module_setWindowSize(w,h,cache=false,exact=false){
  67. if (ao_module_virtualDesktop){
  68. parent.setWindowPreferdSize(ao_module_windowID + "",w,h);
  69. if (cache){
  70. //Cache the window size for this base url and the white window will not be shown next time.
  71. parent.cacheWindowSize(ao_module_parentURL,w,h,exact);
  72. }
  73. return true;
  74. }
  75. return false;
  76. }
  77. //Close the current window
  78. function ao_module_close(){
  79. if (ao_module_virtualDesktop){
  80. parent.closeWindow(ao_module_windowID);
  81. return true;
  82. }
  83. return false;
  84. }
  85. //Get the windows that is running the given module name and return an id list for floatWindow
  86. function ao_module_getProcessID(modulename){
  87. if (ao_module_virtualDesktop){
  88. return parent.getWindowFromModule(modulename);
  89. }
  90. return false;
  91. }
  92. //Hide all control element of this float window.
  93. function ao_module_hideAllControls(){
  94. if (ao_module_virtualDesktop){
  95. parent.hideAllControlElements(ao_module_windowID);
  96. return true;
  97. }
  98. return false;
  99. }
  100. //Crashed
  101. function ao_module_declareCrash(crashmsg){
  102. return false;
  103. }
  104. //Initiate Translation
  105. /*
  106. ArOZ Online Localization and Translation Services
  107. This enable to translation on a given page with the given language or the default language.
  108. To use translation, you will need to include "localtext" in the class field of the DOM element and an attribute "localtext" that point to the classname of the translation.
  109. Example:
  110. (in HTML file)
  111. <span class="localtext" localtext="index/menu/title">Default Text</span>
  112. (in localization file)
  113. "index/menu/title":"ArOZ Onlineβ",
  114. //Results --> <span>ArOZ Onlineβ</span>
  115. Set overscan to true if you want to allow all elements with "localtext" attribute to be translated without class specified "localtext"
  116. Example:
  117. <span localtext="index/menu/title">Default Text</span>
  118. */
  119. function ao_module_initLocalTranslation(overscan = false, lang = null){
  120. if (ao_root === null){
  121. return;
  122. }
  123. if (lang === null){
  124. //Use default lang
  125. lang = localStorage.getItem("aosystem.localize");
  126. if (lang === undefined || lang === "" || lang === null){
  127. lang = "";
  128. }
  129. }
  130. //Load the given language
  131. $.get(ao_root + "SystemAOB/system/lang/" + lang + ".json",function(data){
  132. window.arozTranslationKey = data;
  133. if (overscan){
  134. $("*").each(function(){
  135. if (this.hasAttribute("localtext")){
  136. var thisKey = $(this).attr("localtext");
  137. var localtext = window.arozTranslationKey.keys[thisKey];
  138. $(this).text(localtext);
  139. }
  140. });
  141. }else{
  142. $(".localtext").each(function(){
  143. if (this.hasAttribute("localtext")){
  144. var thisKey = $(this).attr("localtext");
  145. var localtext = window.arozTranslationKey.keys[thisKey];
  146. $(this).text(localtext);
  147. }
  148. });
  149. }
  150. });
  151. }
  152. function ao_module_setLocal(lang){
  153. localStorage.setItem("aosystem.localize",lang);
  154. }
  155. //Open file selector
  156. /**
  157. File Explorer powered by ArOZ Online File System
  158. To pop up a file selector and return an object of files, you can call the following function with the given variable.
  159. Usage: ao_module_openFileSelector({uid},{call back function name in String},{window Width},{windowHeight},{allowMultipleFiles},{selectMode});
  160. For example, this is a function which FFmpeg Factory calls to the file selector
  161. var uid = ao_module_utils.getRandomUID();
  162. ao_module_openFileSelector(uid,"addFileFromSelector",undefined,undefined,true);
  163. This will allow the file selector get files (as selectMode default value is "file") and allow multiple selections
  164. The selectMode option provide modes for file / folder / mix / new, where mix means user can select both files and folders and new means create new file.
  165. The allowMultiple means if the user can select multiple files. True for allow and false for disallow multi selections.
  166. To catch the callback of the selector, you can put the following script into your callBack function (In this case, 'addFileFromSelector')
  167. function addFileFromSelector(fileData){
  168. result = JSON.parse(fileData);
  169. for (var i=0; i < result.length; i++){
  170. var filename = result[i].filename;
  171. var filepath = result[i].filepath;
  172. //DO SOMETHING HERE
  173. }
  174. }
  175. Example call to create a new file with default filename "dummy.txt"
  176. var uid = ao_module_utils.getRandomUID();
  177. ao_module_openFileSelector(uid,"addFileFromSelector",undefined,undefined,true,"new","dummy.txt",false);
  178. REMINDER
  179. If you call this function in default mode, please use the "ao_module_openFileSelectorTab" and pass in the relative location of AOR (Root of ArOZ) as the first variable.
  180. You will also need to handle the listen of change in the uid in localStorage for cross tab communication
  181. **/
  182. function ao_module_openFileSelector(uid,callBackFunctionName, windowWidth = 1080, windowHeight = 645, allowMultiple = false, selectMode = "file", newfname = "newfile.txt", umf = true){
  183. //selectMode: file / folder / mix
  184. //allowMultiple: true / false
  185. if (allowMultiple){
  186. allowMultiple = "true";
  187. }else{
  188. allowMultiple = "false";
  189. }
  190. if (umf){
  191. umf = "true";
  192. }else{
  193. umf = "false";
  194. }
  195. if (ao_module_virtualDesktop){
  196. //Launch inside VDI
  197. if (selectMode == "new"){
  198. ao_module_newfw("SystemAOB/functions/file_system/fileSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode + "&useUMF=" + umf + "&newfn=" + newfname,"Starting file selector","spinner",uid,windowWidth,windowHeight,ao_module_getLeft() + 30,ao_module_getTop() + 30,undefined,undefined,ao_module_windowID,callBackFunctionName);
  199. }else{
  200. ao_module_newfw("SystemAOB/functions/file_system/fileSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode,"Starting file selector","spinner",uid,windowWidth,windowHeight,ao_module_getLeft() + 30,ao_module_getTop() + 30,undefined,undefined,ao_module_windowID,callBackFunctionName);
  201. }
  202. return true;
  203. }else{
  204. return false;
  205. }
  206. }
  207. //Request file selection OUTSIDE OF VDI MODE (REQUIRE localStorage)
  208. /**
  209. This function can be used to call the file selector in non-VDI mode.
  210. The following example shows the method of calling, similar to that in VDI mode.
  211. Assume we have a module at AOR/Dummy/index.php, the script running in that module has an aor = ../
  212. var uid = ao_module_utils.getRandomUID();
  213. ao_module_openFileSelectorTab(uid,"../",true,"file",fileProcesser);
  214. //fileProcessor will catch the file selection
  215. function fileProcesser(fileData){
  216. result = JSON.parse(fileData);
  217. for (var i=0; i < result.length; i++){
  218. var filename = result[i].filename;
  219. var filepath = result[i].filepath;
  220. //DO SOMETHING HERE
  221. }
  222. }
  223. **/
  224. var ao_module_fileSelectorCallBack,ao_module_fileSelectorWindowObject,ao_module_fileSelectorReplyObject,ao_module_fileSelectorFileAwait;
  225. function ao_module_openFileSelectorTab(uid, aor,allowMultiple = false, selectMode = "file",callBack=console.log, newfname = "newfile.txt", umf = true){
  226. //selectMode: file / folder / mix
  227. //allowMultiple: true / false
  228. if (allowMultiple){
  229. allowMultiple = "true";
  230. }else{
  231. allowMultiple = "false";
  232. }
  233. if (aor.slice(-1) != "/"){
  234. aor = aor + "/";
  235. }
  236. if (umf){
  237. umf = "true";
  238. }else{
  239. umf = "false";
  240. }
  241. ao_module_fileSelectorReplyObject = uid;
  242. ao_module_fileSelectorCallBack = callBack;
  243. if (selectMode == "new"){
  244. var windowObject = window.open(aor + "/SystemAOB/functions/file_system/fileSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode + "&puid=" + uid + "&useUMF=" + umf + "&newfn=" + newfname);
  245. }else{
  246. var windowObject = window.open(aor + "/SystemAOB/functions/file_system/fileSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode + "&puid=" + uid);
  247. }
  248. ao_module_fileSelectorWindowObject = windowObject;
  249. ao_module_fileSelectorFileAwait = setInterval(ao_module_listenFileSelectionInput,5000);
  250. return windowObject;
  251. }
  252. //Cross-tab File Selector Listener for File Selector Callback purpose. This is not a usable function. Do not touch this function.
  253. function ao_module_listenFileSelectionInput(){
  254. var ao_module_fileSelectorReturnedFiles = ao_module_readTmp(ao_module_fileSelectorReplyObject);
  255. if (ao_module_fileSelectorReturnedFiles == false && ao_module_fileSelectorReturnedFiles.length === undefined){
  256. }else{
  257. //File found! Closing all selection windows and load the files
  258. clearInterval(ao_module_fileSelectorFileAwait);
  259. if (ao_module_fileSelectorReturnedFiles.length == 0){
  260. //Cancel selection
  261. ao_module_fileSelectorCallBack(JSON.stringify([]));
  262. }else{
  263. ao_module_fileSelectorWindowObject.close();
  264. ao_module_removeTmp(ao_module_fileSelectorReplyObject);
  265. ao_module_fileSelectorReplyObject = undefined;
  266. ao_module_fileSelectorCallBack(JSON.stringify(ao_module_fileSelectorReturnedFiles));
  267. }
  268. }
  269. }
  270. //Open an ArOZ Online Path with the given targetPath from ArOZ Online Root
  271. /**
  272. For example, if you want to open the folder:
  273. "AOR/Audio/uploads/"
  274. Then you can call this function as follow:
  275. ao_module_openPath("Audio/uploads");
  276. **/
  277. function ao_module_openPath(targetPath, windowWidth = 1080, windowHeight = 580,posx = undefined,posy = undefined,resizable = true,glassEffect = true){
  278. if (ao_module_virtualDesktop){
  279. var uid = Date.now();
  280. parent.newEmbededWindow("SystemAOB/functions/file_system/index.php?controlLv=2&subdir=" + targetPath, "Loading", "folder open outline",uid,windowWidth,windowHeight,posx,posy,resizable,glassEffect);
  281. return uid;
  282. }
  283. return false;
  284. }
  285. //Open an ArOZ Online File with the given targetPath and filename (display name) from ArOZ Online Root
  286. /**
  287. For example, if you want to open the file:
  288. "AOR/Desktop/files/admin/helloworld.txt"
  289. Then you can call this function as follow:
  290. ao_module_openFile("Desktop/files/admin/helloworld.txt","helloworld.txt");
  291. The targetpath can be something different from the filename (display name). For example, an encoded file with path:
  292. "Desktop/files/TC/inithe38090e5b08fe9878ee5b48ee4babae38091546f75686f754d4144202d20546f75686f752026204e69746f72692047657420446f776e2120282b6c797269632920e380904844e38091205b373230705d.mp4"
  293. can be opened with filename
  294. "【小野崎人】TouhouMAD - Touhou %26 Nitori Get Down! (+lyric) 【HD】 [720p].mp4" with the following command:
  295. ao_module_openFile("Desktop/files/TC/inithe38090e5b08fe9878ee5b48ee4babae38091546f75686f754d4144202d20546f75686f752026204e69746f72692047657420446f776e2120282b6c797269632920e380904844e38091205b373230705d.mp4","【小野崎人】TouhouMAD - Touhou %26 Nitori Get Down! (+lyric) 【HD】 [720p].mp4");
  296. **/
  297. function ao_module_openFile(targetPath,filename){
  298. if (ao_module_virtualDesktop){
  299. parent.newEmbededWindow("SystemAOB/functions/file_system/index.php?controlLv=2&mode=file&dir=" + targetPath + "&filename=" + filename, filename, "file outline","fileOpenMiddleWare",0,0,-10,-10);
  300. return true;
  301. }
  302. return false;
  303. }
  304. //Open a FloatWindow
  305. /**
  306. Example 1: opening the Memo index with the following code:
  307. ao_module_newfw('Memo/index.php','Memo','sticky note outline','memoEmbedded',475,700);
  308. Example 2: opening the Memo index with minimal parameter:
  309. ao_module_newfw('Memo/index.php','Memo','sticky note outline','memoEmbedded');
  310. Example 3: opening a sub-module and tell the sub-module the parent's window id that is not yourself:
  311. ao_module_newfw('Memo/index.php','Memo','sticky note outline','memoEmbedded',undefined,undefined,undefined,undefined,undefined,undefined,"someoneElseUID");
  312. Example 4: opening a sub-module and ask for a callback: (Default parentUID is set to this module's WindowID and hence, the call back will be called to this content window)
  313. ao_module_newfw('Memo/index.php','Memo','sticky note outline','memoEmbedded',undefined,undefined,undefined,undefined,undefined,undefined,undefined,"callBackFunctionName");
  314. Reminder:
  315. - If you open multiple windows with the same UID, the previous one will be overwritten and reload to the latest page.
  316. - windowname parameter must not contain chars that cannot be put inside an id field (e.g. "&", "." etc)
  317. - For a list of icons, please reference https://tocas-ui.com/elements/icon/
  318. **/
  319. function ao_module_newfw(src,windowname,icon,uid,sizex = undefined,sizey = undefined,posx = undefined,posy = undefined,fixsize = undefined,glassEffect = undefined,parentUID=null, callbackFunct=null){
  320. if (parentUID === null){
  321. parentUID = ao_module_windowID;
  322. }
  323. if (ao_module_virtualDesktop){
  324. parent.newEmbededWindow(src,windowname,icon,uid,sizex,sizey,posx,posy,fixsize,glassEffect,parentUID,callbackFunct);
  325. return true;
  326. }
  327. return false;
  328. }
  329. //Launch a module using FloatWindow.php
  330. //Pass in the module folder name as the input. Example: ao_module_launchModule("Audio");
  331. //Please make sure the module support legacy FloatWindow.php launch method before calling.
  332. function ao_module_launchModule(moduleName){
  333. if (ao_module_virtualDesktop){
  334. parent.LaunchFloatWindowFromModule(moduleName,true);
  335. return true;
  336. }else{
  337. return false;
  338. }
  339. }
  340. //Request fullscreen access from VDI module
  341. function ao_module_fullScreen(){
  342. if (ao_module_virtualDesktop){
  343. parent.openFullscreen();
  344. return true;
  345. }
  346. return false;
  347. }
  348. //Get the basic information of the floatWindows (including the width, height, left and top value)
  349. function ao_module_getWidth(){
  350. if (ao_module_virtualDesktop){
  351. return parent.document.getElementById(ao_module_windowID).offsetWidth;
  352. }else{
  353. return -1;
  354. }
  355. }
  356. function ao_module_getHeight(){
  357. if (ao_module_virtualDesktop){
  358. return parent.document.getElementById(ao_module_windowID).offsetHeight;
  359. }else{
  360. return -1;
  361. }
  362. }
  363. function ao_module_getLeft(){
  364. if (ao_module_virtualDesktop){
  365. return parent.document.getElementById(ao_module_windowID).getBoundingClientRect().left;
  366. }else{
  367. return -1;
  368. }
  369. }
  370. function ao_module_getTop(){
  371. if (ao_module_virtualDesktop){
  372. return parent.document.getElementById(ao_module_windowID).getBoundingClientRect().top;
  373. }else{
  374. return -1;
  375. }
  376. }
  377. //Showing msgbox at the notification side bar
  378. /**
  379. For example, the most basic use of this command will be:
  380. ao_module_msgbox("This is a demo message from the aroz online module.","Hello World");
  381. You can add more object to the message including HTML tags in msg and title, and redirection path for opening the target etc.
  382. If auto close = false, the side bar will not get hidden after 4 seconds.
  383. **/
  384. function ao_module_msgbox(warningMsg,title="",redirectpath="",autoclose=true){
  385. if (ao_module_virtualDesktop){
  386. parent.msgbox(warningMsg,title,redirectpath,autoclose);
  387. return true;
  388. }
  389. return false;
  390. }
  391. //Focus this floatWindow and bring it to the front
  392. /**
  393. This function bring the current floatWindow content to the front of all FloatWindows.
  394. Please use this only in urgent / warning information. This might bring interuption to user's operation and making them unhappy :(
  395. **/
  396. function ao_module_focus(){
  397. if (ao_module_virtualDesktop){
  398. parent.focusFloatWindow(ao_module_windowID);
  399. return true;
  400. }else{
  401. return false;
  402. }
  403. }
  404. //Return the object in which the main interface iframe (The most backgound iframe. Mostly Desktop when you are using VDI mode. But you can change it if required).
  405. function ao_module_callToInterface(){
  406. return parent.callToInterface();
  407. }
  408. //Cross iFrame communication pipeline
  409. /**
  410. This function can send data to parent callback function if necessary.
  411. Data has to be an data object
  412. Given the following condition
  413. parentID: test
  414. callback: setBackgroundColor
  415. with a function named setBackgroundColor(data) in the parent window (iframe)
  416. Then you can use the following example to send data to the parent frame
  417. Example: ao_module_parentCallback({color:"white"});
  418. The returned value will be the data object in stringify JSON.
  419. To get the original value of the data received by another window:
  420. function setBackgroundColor(data){
  421. object = (JSON.parse(data));
  422. console.log(object.color);
  423. }
  424. Console output:
  425. >>white
  426. **/
  427. function ao_module_parentCallback(data){
  428. if (ao_module_virtualDesktop && ao_module_parentID !== undefined && ao_module_callback !== undefined){
  429. data = JSON.stringify(data);
  430. var ao_module_parentTarget = parent.getWindowObjectFromID(ao_module_parentID);
  431. if (ao_module_parentTarget !== null){
  432. ao_module_parentTarget.eval(ao_module_callback + "('" + data + "')");
  433. return true;
  434. }else{
  435. return false;
  436. }
  437. }else{
  438. return false;
  439. }
  440. }
  441. /**
  442. REMINDER
  443. When your module require save and loading data from localStorage, we recommend using the naming method as follow.
  444. [ModuleName]_[Username]_[Properties].
  445. For example, you are developing a new "MusicMixer" Module and want to store the "songList" properties for user "Admin". Then the recommended localStorage syntax will be:
  446. MusicMixer_Admin_songList
  447. Example:
  448. ao_module_getStorage("MusicMixer","Admin","songList");
  449. ao_module_saveStorage("MusicMixer","Admin","songList","{some JSON string here}");
  450. **/
  451. //Load something from localStorage with given tag
  452. function ao_module_getStorage(moduleName,itemname){
  453. moduleName = moduleName.split("_").join("-");
  454. username = ao_module_utils.getUserName().split("_").join("-");
  455. itemname = itemname.split("_").join("-");
  456. return localStorage.getItem(moduleName + "_" + username + "_" + itemname);
  457. }
  458. //Save something into localStoarge with give tag and value
  459. function ao_module_saveStorage(moduleName,itemname,value){
  460. moduleName = moduleName.split("_").join("-");
  461. username = ao_module_utils.getUserName().split("_").join("-");
  462. itemname = itemname.split("_").join("-");
  463. localStorage.setItem(moduleName + "_" + username + "_" + itemname, value);
  464. return true;
  465. }
  466. //Write something to tmp, which can be used as callback or anything that is not important
  467. //The value can also be an object
  468. function ao_module_writeTmp(uid,value){
  469. uid = "tmp_" + uid;
  470. localStorage.setItem(uid,JSON.stringify(value));
  471. }
  472. function ao_module_readTmp(uid){
  473. uid = "tmp_" + uid;
  474. var value = localStorage.getItem(uid);
  475. if (value == null || value == "null"){
  476. return false;
  477. }
  478. return JSON.parse(value);
  479. }
  480. function ao_module_removeTmp(uid){
  481. uid = "tmp_" + uid;
  482. if (ao_module_readTmp(uid) == false){
  483. localStorage.removeItem(uid);
  484. }
  485. }
  486. //Check if the storage exists on this browser or not
  487. function ao_module_checkStorage(id){
  488. if (typeof(Storage) !== "undefined") {
  489. return true;
  490. } else {
  491. return false;
  492. }
  493. }
  494. /*
  495. ArOZ Online Cluster Services Functions
  496. These functions are desgined for powering the cluster services of the ArOZ Cluster System.
  497. These 3 functions provide a GUI for user to select a desired parallel processing host / clusters.
  498. To use this in Tab Mode (Non-VDI mode), use the ao_module_openClusterSelectorTab() function instead.
  499. ao_module_openClusterSelector()
  500. Example Usage: (Node Selection)
  501. function openClusterSelect(){
  502. var uid = ao_module_utils.getRandomUID();
  503. if (ao_module_virtualDesktop){
  504. ao_module_openClusterSelector(uid,"clusterProcess");
  505. }else{
  506. ao_module_openClusterSelectorTab(uid,"../",undefined,undefined,clusterProcess);
  507. }
  508. }
  509. or (Disk Selection)
  510. function openClusterDriveSelect(){
  511. var uid = ao_module_utils.getRandomUID();
  512. if (ao_module_virtualDesktop){
  513. ao_module_openClusterSelector(uid,"diskProcess",undefined,undefined,undefined,"disk");
  514. }else{
  515. ao_module_openClusterSelectorTab(uid,"../",undefined,"disk",diskProcess);
  516. }
  517. }
  518. Example return functions:
  519. function diskProcess(diskInfo){
  520. result = JSON.parse(diskInfo);
  521. for (var i=0; i < result.length; i++){
  522. var diskID = result[i].diskID;
  523. //Do something here
  524. }
  525. }
  526. function clusterProcess(clusterData){
  527. $("#reply").html("");
  528. result = JSON.parse(clusterData);
  529. for (var i=0; i < result.length; i++){
  530. var clusterIP = result[i].hostIP;
  531. var clusterUUID = result[i].hostUUID;
  532. var online = result[i].hostOnline;
  533. //Do something here
  534. }
  535. }
  536. */
  537. var ao_module_clusterSelectorCallBack,ao_module_clusterSelectorWindowObject,ao_module_clusterSelectorReplyObject,ao_module_clusterSelectorFileAwait;
  538. function ao_module_openClusterSelector(uid,callBackFunctionName, windowWidth = 1080, windowHeight = 645, allowMultiple = false, selectMode = "node"){
  539. //selectMode: node / disk
  540. //allowMultiple: true / false
  541. if (allowMultiple){
  542. allowMultiple = "true";
  543. }else{
  544. allowMultiple = "false";
  545. }
  546. if (ao_module_virtualDesktop){
  547. //Launch inside VDI
  548. ao_module_newfw("SystemAOB/functions/cluster/clusterSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode,"Starting cluster selector","spinner",uid,windowWidth,windowHeight,ao_module_getLeft() + 30,ao_module_getTop() + 30,undefined,undefined,ao_module_windowID,callBackFunctionName);
  549. return true;
  550. }else{
  551. return false;
  552. }
  553. }
  554. function ao_module_openClusterSelectorTab(uid, aor,allowMultiple = false, selectMode = "node",callBack=console.log){
  555. //selectMode: node / disk
  556. //allowMultiple: true / false
  557. if (allowMultiple){
  558. allowMultiple = "true";
  559. }else{
  560. allowMultiple = "false";
  561. }
  562. if (aor.slice(-1) != "/"){
  563. aor = aor + "/";
  564. }
  565. ao_module_clusterSelectorReplyObject = uid;
  566. ao_module_clusterSelectorCallBack = callBack;
  567. var windowObject = window.open(aor + "/SystemAOB/functions/cluster/clusterSelector.php?allowMultiple=" + allowMultiple + "&selectMode=" + selectMode + "&puid=" + uid);
  568. ao_module_clusterSelectorWindowObject = windowObject;
  569. ao_module_clusterSelectorFileAwait = setInterval(ao_module_listenClusterSelectionInput,5000);
  570. return windowObject;
  571. }
  572. //Cross-tab File Selector Listener for File Selector Callback purpose. This is not a usable function. Do not touch this function.
  573. function ao_module_listenClusterSelectionInput(){
  574. var ao_module_clusterSelectorReturnedFiles = ao_module_readTmp(ao_module_clusterSelectorReplyObject);
  575. if (ao_module_clusterSelectorReturnedFiles == false && ao_module_clusterSelectorReturnedFiles.length === undefined){
  576. }else{
  577. //File found! Closing all selection windows and load the files
  578. clearInterval(ao_module_clusterSelectorFileAwait);
  579. if (ao_module_clusterSelectorReturnedFiles.length == 0){
  580. //Cancel selection
  581. ao_module_clusterSelectorCallBack(JSON.stringify([]));
  582. }else{
  583. ao_module_clusterSelectorWindowObject.close();
  584. ao_module_removeTmp(ao_module_clusterSelectorReplyObject);
  585. ao_module_clusterSelectorReplyObject = undefined;
  586. ao_module_clusterSelectorCallBack(JSON.stringify(ao_module_clusterSelectorReturnedFiles));
  587. }
  588. }
  589. }
  590. /*
  591. ArOZ Online Module Input Method Editor / Extension
  592. These functions for designed for custom input method.
  593. Please refer to the implementation comments listed below.
  594. */
  595. class ao_module_inputs{
  596. //Define this module window as an Input Method
  597. /*
  598. //The following function should be defined at the first line of Javascript of your input method for handling the key events
  599. //THESE SECTIONS OF CODE ARE FOR WEBAPP THAT IS DESIGNED TO BE A INPUT METHOD ONLY
  600. ao_module_inputs.defineInputMethod(function(e) {
  601. //Your code here, e is the event handler which should be passed through to this iframe by the typing target window
  602. });
  603. //You can also undefined the Input Method (Optional) on beforeUnload
  604. ao_module_inputs.undefineInputMethod();
  605. */
  606. static defineInputMethod(keyHandlerFunct){
  607. parent.window.inputMethod = ao_module_windowID;
  608. window.keyHandler = keyHandlerFunct;
  609. }
  610. //Undefined this module window as an Input Method
  611. static undefineInputMethod(){
  612. parent.window.inputMethod = undefined;
  613. window.keyHandler = undefined;
  614. }
  615. //Allow module to hook functions from local script to stdIn for Input Method bypass
  616. /*
  617. //THESE SECTION OF CODE IS DESIGN FOR MODULE THAT RECEIVE INPUT FROM INPUT METHODS
  618. //Assume you have an input field that is going to filled in by string returned by the input method.
  619. //Then, you can first hook the StdIn of your WebAPP as follow.
  620. ao_module_inputs.hookStdIn(function(text){
  621. //text variable is the string that the user typed via the IME
  622. $("#input").append(text);
  623. });
  624. //Next, you need to hand the key input event to the input method.
  625. document.addEventListener("keydown", ao_module_inputs.hookKeyHandler, false);
  626. */
  627. static hookStdIn(localFunction){
  628. //Check if any input method is hooked. If yes, allow hooking
  629. if (parent.window.inputMethod != undefined){
  630. window.stdIn = localFunction;
  631. }else{
  632. return false;
  633. }
  634. }
  635. //Do not include the following function into your code. This is used for callback purpose only.
  636. static hookKeyHandler(event){
  637. if (parent.window.inputMethod != undefined){
  638. var InputMethod = parent.window.document.getElementById(parent.window.inputMethod);
  639. if ($(InputMethod).length == 0){
  640. //Input method no longer exists
  641. return false;
  642. }
  643. $(InputMethod).find("iframe")[0].contentWindow.keyHandler(event);
  644. }else{
  645. return false;
  646. }
  647. }
  648. //Sent output text to the current focused Windows
  649. /*
  650. //This function send text (or character) to the focused windows's hookStdIn defined function
  651. //THIS FUNCTION IS FOR WEBAPP THAT IS DESIGNED FOR BEING AN INPUT METHOD ONLY
  652. ao_module_inputs.stdOut(text);
  653. */
  654. static stdOut(text){
  655. var targetWindow = parent.focusedWindow;
  656. if ($(targetWindow).parent().attr("id") == ao_module_windowID){
  657. //This is this windows. Ignore the StdOut
  658. return;
  659. }
  660. targetWindow = $(targetWindow).parent().find("iframe")[0];
  661. if (targetWindow.contentWindow != null && typeof targetWindow.contentWindow.stdIn != undefined && targetWindow.contentWindow.stdIn != undefined){
  662. //This module allow stdIn Hooking, send it text!
  663. targetWindow.contentWindow.stdIn(text);
  664. }else{
  665. //This module do not allow hooking to input methods
  666. return false;
  667. }
  668. }
  669. }
  670. /**
  671. ArOZ Online Module Functions for WebSocket Communication
  672. The default port for ArOZ Online Websocket Server is 8000.
  673. This function is not usable if you don't have a valid websocket setup.
  674. ao_module_ws.init(aor, modulename(nospace), server, channel, JWTtoken, onopen, onmessage, onclose, onerror); //Initialize conenction to aobws
  675. ao_module_ws.send(conn, object); //Send an object through aobws
  676. ao_module_ws.sendToUser(conn, username, object); //Send object to a certain username
  677. ao_module_ws.sendToUUID(conn, uuid, object); //Send object to a connection UUID
  678. ao_module_ws.parse(aor, modulename, msg, callback); //Internal parse engine. Advanced developer only.
  679. Points to be noted:
  680. After initiation, two commands will be sent automatically:
  681. /login module_name(aka channel, No Space) token --> return 202 Accepted if succeed
  682. /chkuuid --> return UUID of this client connection
  683. afterward, you can access the connection object itself using
  684. window.aobws
  685. or you can also get the UUID of the connection by getting
  686. window.aobwsUUID
  687. **/
  688. class ao_module_ws{
  689. //Initialize the websocket connection to aobws. Given server address, channel, token and other important event handlers
  690. /*
  691. //Here is an example on how to use the init function and set event handlers
  692. var conn = ao_module_ws.init("../","Dummy"
  693. "ws://192.168.0.107:8000/ws",
  694. "channel",
  695. "{JWT-token here, leave empty for auto assign. See System Settings > ArOZ Cluster > ShadowJWT}",
  696. function(){
  697. //Failed callback on auth fail
  698. console.log("Auth failed.");
  699. },
  700. function(data){
  701. //Onopen function
  702. console.log("Connection opened");
  703. },
  704. function(data){
  705. //Onmessage function
  706. console.log(data);
  707. }, function(data){
  708. //On close function
  709. console.log("Connection Closed");
  710. },function(data){
  711. //On error function
  712. console.log("Oops something went wrong.")
  713. });
  714. //On message will return an object with 4 keys:
  715. connUUID: sender UUID of this piece of message
  716. data: Data in the form of Javascript Object
  717. sender: The username / owner of the sender token
  718. type: Message type. (broadcast / utell / tell)
  719. */
  720. static init(aor, modulename, server, channel, JWTtoken="", failCallback, onopen, onmessage, onclose, onerror){
  721. //server example: "ws://192.168.0.107:8000/ws"
  722. //Replace any space in channel with URL elements
  723. channel = encodeURI(channel);
  724. //Check if jwttoken exists. If not, lead to the authentication interface
  725. if (JWTtoken == ""){
  726. //Check if this module already has a token. If yes, load from it.
  727. $.ajax({
  728. url: aor + "SystemAOB/system/jwt/getToken.php?module=" + modulename,
  729. success: function(data) {
  730. if (data == ""){
  731. //No token is generated for this module.
  732. //Generate a new token with given GUI
  733. var authUI = aor + "SystemAOB/system/jwt/request.php?module=" + modulename;
  734. window.wsAuthFailedCallback = failCallback;
  735. window.previouswsInitRecord = [aor, modulename, server, channel, JWTtoken, failCallback, onopen, onmessage, onclose, onerror];
  736. $("body").append('<div id="system_jwtauth_ui_dimmer" class="ts active dimmer"></div>');
  737. $("body").append('<div id="system_jwtauth_ui_iframe" onClick="ao_module_ws.fadeOutWSAuthUI();" style="z-index:999; width:100%; height:100%; position:fixed;left:0px;top:0px;" align="center"><iframe style="z-index:999; width:560px; height:760px;overflow:hidden;" src="' + authUI + '"></iframe></div>');
  738. return;
  739. }else{
  740. //Token found. Use this as token
  741. JWTtoken = data;
  742. var conn = new WebSocket(server);
  743. conn.onopen = function (evt){
  744. //Connection opened. Register this user with the given channel and token
  745. conn.send("/login " + channel + " " + JWTtoken);
  746. conn.send("/chkuuid");
  747. onopen(evt);
  748. };
  749. conn.onclose = function (evt) {
  750. onclose(evt);
  751. };
  752. conn.onmessage = function (evt) {
  753. ao_module_ws.parse(aor, modulename, evt,onmessage);
  754. };
  755. conn.ononerror = function(evt){
  756. onerror(evt);
  757. }
  758. window.aobws = conn;
  759. }
  760. }
  761. });
  762. }else{
  763. var conn = new WebSocket(server);
  764. conn.onopen = function (evt){
  765. //Connection opened. Register this user with the given channel and token
  766. conn.send("/login " + channel + " " + JWTtoken);
  767. console.log("/login " + channel + " " + JWTtoken);
  768. onopen(evt);
  769. };
  770. conn.onclose = function (evt) {
  771. onclose(evt);
  772. };
  773. conn.onmessage = function (evt) {
  774. console.log(evt);
  775. ao_module_ws.parse(evt,onmessage);
  776. };
  777. conn.ononerror = function(evt){
  778. onerror(evt);
  779. }
  780. window.aobws = conn;
  781. }
  782. }
  783. //Send (broadcast) an object to everyone including yourself
  784. /*
  785. Example usage:
  786. var dataToBeSent = {"name":"Tester", "age":13};
  787. ao_module_ws.send(conn,dataToBeSent);
  788. */
  789. static send(conn, object){
  790. conn.send(ao_module_utils.objectToAttr(object));
  791. }
  792. //Send (tell) an object to a given username in the same channel except yourself
  793. /*
  794. Example usage:
  795. var dataToBeSent = {"name":"Tester", "age":13};
  796. var targetUser = "user";
  797. ao_module_ws.sendToUser(conn, targetUser, dataToBeSent);
  798. */
  799. static sendToUser(conn, username, object){
  800. conn.send("/tell " + username + " " + ao_module_utils.objectToAttr(object));
  801. }
  802. //Send (utell) an ibject to a given client with UUID in the same channel
  803. static sendToUUID(conn, uuid, object){
  804. conn.send("/utell " + uuid + " " + ao_module_utils.objectToAttr(object));
  805. }
  806. static fadeOutWSAuthUI(){
  807. window.wsAuthFailedCallback();
  808. $("#system_jwtauth_ui_dimmer").fadeOut('fast',function(){
  809. $(this).remove();
  810. });
  811. $("#system_jwtauth_ui_iframe").fadeOut('fast',function(){
  812. $(this).remove();
  813. });
  814. }
  815. //Parse the raw input from aobws to readable format.
  816. //This section should have been included in the init() process which will parse the input data first before handing out to onmessage handler.
  817. static parse(aor, modulename, msg, callback){
  818. var data = msg.data;
  819. var JSONvalid = false;
  820. if (/^[\],:{}\s]*$/.test(data.replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
  821. JSONvalid = true;
  822. }
  823. if (!JSONvalid){
  824. //Datapack corrupted. Ignore it.
  825. return;
  826. }
  827. data = JSON.parse(data);
  828. //Check if the data is command response.
  829. if (data.type == "resp"){
  830. //Check if it is login failed. If yes, clear up the token and redo authentication
  831. if (data.command == "login" && data.data == "401 Unauthorized"){
  832. //This token is no longer usable.
  833. console.log("Warning! Token is dead. Removing token and performing re-authentication process.");
  834. $.get(aor + "SystemAOB/system/jwt/getToken.php?clearModule=" + modulename,function(data){
  835. window.location.reload();
  836. });
  837. }else if (data.command == "chkuuid" && data.data != "401 Unauthorized"){
  838. //Client connection UUID received.
  839. window.aobwsUUID = data.data;
  840. }
  841. //No need to do further parsing
  842. callback(data);
  843. return;
  844. }
  845. //This is a communication msgpackage. Parse it
  846. var sendType = data.type;
  847. var sender = data.sender;
  848. var connectionUUID = data.connUUID;
  849. var message = ao_module_utils.attrToObject(data.data);
  850. callback({
  851. "type": sendType,
  852. "sender": sender,
  853. "connUUID": connectionUUID,
  854. "data": message
  855. });
  856. }
  857. }
  858. /**
  859. ArOZ Online Module File System Operation API
  860. This API is provided for handling backstage file operation via PHP + Golang file system execution system (aka fsexec).
  861. See fsexec documentation for more information.
  862. ao_module_fs.isFile(source); //Check if a give path is file.
  863. ao_module_fs.unlink(source); //Remove the given file.
  864. ao_module_fs.move(source, target, callback); //Move a file / folder to a target location. Path can be either start from File Explorer Relative or AOR Relative.
  865. ao_module_fs.rename(source, target, callback); //Same as move
  866. ao_module_fs.copy(source, target, callback); //Copy a file / folder to a target location. Path can be either start from File Explorer Relative or AOR Relative.
  867. **/
  868. class ao_module_fs{
  869. static unlink(source, callback = null, overrideConfirm = false){
  870. if (!ao_module_virtualDesktop){
  871. return false;
  872. }
  873. if (!overrideConfirm){
  874. if (!confirm("The module with ID " + ao_module_windowID + " request to remove file " + source + ". Confirm Delete?")){
  875. return;
  876. }
  877. }
  878. parent.$.get( "SystemAOB/functions/file_system/delete.php?filename=" + source, function(data) {
  879. console.log(data);
  880. callback(data);
  881. });
  882. }
  883. static rename(source,target, callback = null){
  884. //Alias both renname and move
  885. ao_module_fs.move(source,target, callback);
  886. }
  887. static isFile(source){
  888. var isFile = false;
  889. if (source.split(".").length > 1){
  890. isFile = true;
  891. }
  892. return isFile;
  893. }
  894. static move(source, target, callback = null){
  895. if (!ao_module_virtualDesktop){
  896. return false;
  897. }
  898. //Check if the source is a file or folder by checking if it has a file extension
  899. var sourceIsFile = ao_module_fs.isFile(source);
  900. if (sourceIsFile){
  901. //Move file
  902. parent.$.get("SystemAOB/functions/file_system/fsexec.php?opr=move&from=" + source + "&target=" + target, function(data) {
  903. if (!data.includes("ERROR")){
  904. ao_module_fs.createFileOprListener([data],"move",source, target);
  905. }else{
  906. console.log("[" + ao_module_windowID + "] " + data);
  907. }
  908. callback(data);
  909. });
  910. }else{
  911. //Move folder
  912. parent.$.get("SystemAOB/functions/file_system/fsexec.php?opr=move_folder&from=" + source + "&target=" + target, function(data) {
  913. if (!data.includes("ERROR")){
  914. ao_module_fs.createFileOprListener([data],"move",source, target);
  915. }else{
  916. console.log("[" + ao_module_windowID + "] " + data);
  917. }
  918. callback(data);
  919. });
  920. }
  921. }
  922. static copy(source, target, callback = null){
  923. if (!ao_module_virtualDesktop){
  924. return false;
  925. }
  926. var sourceIsFile = ao_module_fs.isFile(source);
  927. if (sourceIsFile){
  928. //Copy File
  929. parent.$.get("SystemAOB/functions/file_system/fsexec.php?opr=copy&from=" + source + "&target=" + target, function(data) {
  930. if (!data.includes("ERROR")){
  931. console.log(data);
  932. ao_module_fs.createFileOprListener([data],"copy",source, target);
  933. }else{
  934. console.log("[" + ao_module_windowID + "] " + data);
  935. }
  936. callback(data);
  937. });
  938. }else{
  939. //Cp[y Folder
  940. parent.$.get("SystemAOB/functions/file_system/fsexec.php?opr=copy_folder&from=" + source + "&target=" + target, function(data) {
  941. if (!data.includes("ERROR")){
  942. ao_module_fs.createFileOprListener([data],"copy",source, target);
  943. }else{
  944. console.log("[" + ao_module_windowID + "] " + data);
  945. }
  946. callback(data);
  947. });
  948. }
  949. }
  950. }
  951. /**
  952. ArOZ Online Module Utils for quick deploy of ArOZ Online WebApps
  953. ao_module_utils.objectToAttr(object); //object to DOM attr
  954. ao_module_utils.attrToObject(attr); //DOM attr to Object
  955. ao_module_utils.getRandomUID(); //Get random UUID from timestamp
  956. ao_module_utils.getIconFromExt(ext); //Get icon tag from file extension
  957. **/
  958. class ao_module_utils{
  959. //Two simple functions for converting any Javascript object into string that can be put into the attr value of an DOM object
  960. static objectToAttr(object){
  961. return encodeURIComponent(JSON.stringify(object));
  962. }
  963. static attrToObject(attr){
  964. return JSON.parse(decodeURIComponent(attr));
  965. }
  966. //Get the current username from localStorage
  967. //Warning! This value might not be accurate as the user might change this by themself. If you want to ensure their username, use PHP $_SESSION['login'] instead.
  968. static getUserName(){
  969. return localStorage.getItem("ArOZusername");
  970. }
  971. //Get a random id for a new floatWindow, use with var uid = ao_module_utils.getRandomUID();
  972. static getRandomUID(){
  973. return new Date().getTime();
  974. }
  975. //Get the icon of a file with given extension (ext), use with ao_module_utils.getIconFromExt("ext");
  976. static getIconFromExt(ext){
  977. var ext = ext.toLowerCase().trim();
  978. var iconList={
  979. md:"file text outline",
  980. txt:"file text outline",
  981. pdf:"file pdf outline",
  982. doc:"file word outline",
  983. docx:"file word outline",
  984. odt:"file word outline",
  985. xlsx:"file excel outline",
  986. ods:"file excel outline",
  987. ppt:"file powerpoint outline",
  988. pptx:"file powerpoint outline",
  989. odp:"file powerpoint outline",
  990. jpg:"file image outline",
  991. png:"file image outline",
  992. jpeg:"file image outline",
  993. gif:"file image outline",
  994. odg:"file image outline",
  995. psd:"file image outline",
  996. zip:"file archive outline",
  997. '7z':"file archive outline",
  998. rar:"file archive outline",
  999. tar:"file archive outline",
  1000. mp3:"file audio outline",
  1001. m4a:"file audio outline",
  1002. flac:"file audio outline",
  1003. wav:"file audio outline",
  1004. aac:"file audio outline",
  1005. mp4:"file video outline",
  1006. webm:"file video outline",
  1007. php:"file code outline",
  1008. html:"file code outline",
  1009. htm:"file code outline",
  1010. js:"file code outline",
  1011. css:"file code outline",
  1012. xml:"file code outline",
  1013. json:"file code outline",
  1014. csv:"file code outline",
  1015. odf:"file code outline",
  1016. bmp:"file image outline",
  1017. rtf:"file text outline",
  1018. wmv:"file video outline",
  1019. mkv:"file video outline",
  1020. ogg:"file audio outline",
  1021. stl:"cube",
  1022. obj:"cube",
  1023. "3ds":"cube",
  1024. fbx:"cube",
  1025. collada:"cube",
  1026. step:"cube",
  1027. iges:"cube",
  1028. gcode:"cube",
  1029. shortcut:"external square",
  1030. opus:"file audio outline",
  1031. apscene:"cubes"
  1032. };
  1033. var icon = "";
  1034. if (ext == ""){
  1035. icon = "folder outline";
  1036. }else{
  1037. icon = iconList[ext];
  1038. if (icon == undefined){
  1039. icon = "file outline"
  1040. }
  1041. }
  1042. return icon;
  1043. }
  1044. }
  1045. class ao_module_codec{
  1046. //Decode umfilename into standard filename in utf-8, which umfilename usually start with "inith"
  1047. //Example: ao_module_codec.decodeUmFilename(umfilename_here);
  1048. static decodeUmFilename(umfilename){
  1049. if (umfilename.includes("inith")){
  1050. var data = umfilename.split(".");
  1051. if (data.length == 1){
  1052. //This is a filename without extension
  1053. data = data[0].replace("inith","");
  1054. var decodedname = ao_module_codec.decode_utf8(ao_module_codec.hex2bin(data));
  1055. if (decodedname != "false"){
  1056. //This is a umfilename
  1057. return decodedname;
  1058. }else{
  1059. //This is not a umfilename
  1060. return umfilename;
  1061. }
  1062. }else{
  1063. //This is a filename with extension
  1064. var extension = data.pop();
  1065. var filename = data[0];
  1066. filename = filename.replace("inith",""); //Javascript replace only remove the first instances (i.e. the first inith in filename)
  1067. var decodedname = ao_module_codec.decode_utf8(ao_module_codec.hex2bin(filename));
  1068. if (decodedname != "false"){
  1069. //This is a umfilename
  1070. return decodedname + "." + extension;
  1071. }else{
  1072. //This is not a umfilename
  1073. return umfilename;
  1074. }
  1075. }
  1076. }else{
  1077. //This is not umfilename as it doesn't have the inith prefix
  1078. return umfilename;
  1079. }
  1080. }
  1081. //Encode filename to UMfilename
  1082. //Example: ao_module_codec.encodeUMFilename("test.stl");
  1083. static encodeUMFilename(filename){
  1084. if (filename.substring(0,5) != "inith"){
  1085. //Check if the filename include extension.
  1086. if (filename.includes(".")){
  1087. //Filename with extension. pop it out first.
  1088. var info = filename.split(".");
  1089. var ext = info.pop();
  1090. var filenameOnly = info.join(".");
  1091. var encodedFilename = "inith" + ao_module_codec.decode_utf8(ao_module_codec.bin2hex(filenameOnly)) + "." + ext;
  1092. return encodedFilename;
  1093. }else{
  1094. //Filename with no extension. Convert the whole name into UMfilename
  1095. var encodedFilename = "inith" + ao_module_codec.decode_utf8(ao_module_codec.bin2hex(filename));
  1096. return encodedFilename;
  1097. }
  1098. }else{
  1099. //This is already a UMfilename. return the raw filename.
  1100. return filename;
  1101. }
  1102. }
  1103. //Decode hexFoldername into standard foldername in utf-8, return the original name if it is not a hex foldername
  1104. //Example: ao_module_codec.decodeHexFoldername(hexFolderName_here);
  1105. static decodeHexFoldername(folderName, prefix=true){
  1106. var decodedFoldername = ao_module_codec.decode_utf8(ao_module_codec.hex2bin(folderName));
  1107. if (decodedFoldername == "false"){
  1108. //This is not a hex encoded foldername
  1109. decodedFoldername = folderName;
  1110. }else{
  1111. //This is a hex encoded foldername
  1112. if (prefix){
  1113. decodedFoldername = "*" + decodedFoldername;
  1114. }else{
  1115. decodedFoldername =decodedFoldername;
  1116. }
  1117. }
  1118. return decodedFoldername;
  1119. }
  1120. //Encode foldername into hexfoldername
  1121. //Example: ao_module_codec.encodeHexFoldername("test");
  1122. static encodeHexFoldername(folderName){
  1123. var encodedFilename = "";
  1124. if (ao_module_codec.decodeHexFoldername(folderName) == folderName){
  1125. //This is not hex foldername. Encode it
  1126. encodedFilename = ao_module_codec.decode_utf8(ao_module_codec.bin2hex(folderName));
  1127. }else{
  1128. //This folder name already encoded. Return the original value
  1129. encodedFilename = folderName;
  1130. }
  1131. return encodedFilename;
  1132. }
  1133. static hex2bin(s){
  1134. var ret = []
  1135. var i = 0
  1136. var l
  1137. s += ''
  1138. for (l = s.length; i < l; i += 2) {
  1139. var c = parseInt(s.substr(i, 1), 16)
  1140. var k = parseInt(s.substr(i + 1, 1), 16)
  1141. if (isNaN(c) || isNaN(k)) return false
  1142. ret.push((c << 4) | k)
  1143. }
  1144. return String.fromCharCode.apply(String, ret)
  1145. }
  1146. static bin2hex(s){
  1147. var i
  1148. var l
  1149. var o = ''
  1150. var n
  1151. s += ''
  1152. for (i = 0, l = s.length; i < l; i++) {
  1153. n = s.charCodeAt(i)
  1154. .toString(16)
  1155. o += n.length < 2 ? '0' + n : n
  1156. }
  1157. return o
  1158. }
  1159. static decode_utf8(s) {
  1160. return decodeURIComponent(escape(s));
  1161. }
  1162. }
  1163. /**
  1164. Screenshot related functions
  1165. This function make use of the html2canvas JavaScript library. For license and author, please refer to the html2canvas.js head section.
  1166. target value are used to defined the operation after the screenshot.
  1167. default / newWindow --> Open screenshot in new window
  1168. dataurl --> return data url of the image as string
  1169. canvas --> return the canvas object
  1170. **/
  1171. //Updates Removed Screenshot feature due to waste of resources
  1172. /**
  1173. //Take a screenshot from module body
  1174. function ao_html2canvas_screenshot(target="newWindow",callback){
  1175. if (typeof html2canvas != undefined){
  1176. html2canvas(document.body).then(function(canvas) {
  1177. if (target == "newWindow"){
  1178. window.open(canvas.toDataURL("image/png"), '_blank');
  1179. return true;
  1180. }else if (target == "dataurl"){
  1181. callback(canvas.toDataURL("image/png"));
  1182. }else if (target == "canvas"){
  1183. callback(canvas);
  1184. }else{
  1185. window.open(canvas.toDataURL("image/png"), '_blank');
  1186. return true;
  1187. }
  1188. });
  1189. }else{
  1190. return false;
  1191. }
  1192. }
  1193. function ao_html2canvas_getPreview(w,h){
  1194. if (typeof html2canvas != undefined){
  1195. html2canvas(document.body,{width: w,height: h}).then(function(canvas) {
  1196. parent.updatePreview(canvas);
  1197. });
  1198. }else{
  1199. return false;
  1200. }
  1201. }
  1202. **/