No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

index.html 14KB

hace 5 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <!DOCTYPE html>
  2. <html>
  3. <meta charset="utf-8">
  4. <head>
  5. <style>
  6. table
  7. {
  8. border-collapse: collapse;
  9. }
  10. table, th, td
  11. {
  12. border: 1px solid #aaa;
  13. padding: 0.5em;
  14. margin-top: 0.5em;
  15. margin-bottom: 0.5em;
  16. }
  17. .error
  18. {
  19. color: red;
  20. }
  21. .section
  22. {
  23. text-align: center;
  24. font-weight: bold;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <table>
  30. <tr>
  31. <td colspan="2" class="section">
  32. <a href="http://opengamestudio.org/lfsa">Local file system access</a>
  33. </td>
  34. </tr>
  35. <tr>
  36. <td>Path:</td>
  37. <td id="lfsaPath">Updating...</td>
  38. </tr>
  39. <tr>
  40. <td colspan="2" class="section">
  41. Configuration
  42. <button type="button" onclick="window.pskovTool.saveCfg()">Save</button>
  43. </td>
  44. </tr>
  45. <tr>
  46. <td>Input directory:</td>
  47. <td><input id="input"></input>
  48. </tr>
  49. <tr>
  50. <td>News item template:</td>
  51. <td><input id="item"></input>
  52. </tr>
  53. <tr>
  54. <td>News preview template:</td>
  55. <td><input id="preview"></input>
  56. </tr>
  57. <tr>
  58. <td>Index template:</td>
  59. <td><input id="index"></input>
  60. </tr>
  61. <tr>
  62. <td>Output directory:</td>
  63. <td><input id="output"></input>
  64. </tr>
  65. <tr>
  66. <td colspan="2" class="section">Log</td>
  67. </tr>
  68. <tr>
  69. <td id="log" colspan="2"></td>
  70. </tr>
  71. </table>
  72. <script type="text/javascript">
  73. <!-- LFSA.js -->
  74. // LFSA class to communicate with local-file-system-access instance.
  75. function LFSA()
  76. {
  77. this.host = "http://127.0.0.1";
  78. this.port = 8000;
  79. }
  80. LFSA.prototype.get = function(url, successCallback, failureCallback)
  81. {
  82. var req = new XMLHttpRequest();
  83. req.addEventListener(
  84. "load",
  85. function()
  86. {
  87. //console.log("get.successCallback.responseText: '" + this.responseText + "'");
  88. successCallback(this.responseText);
  89. }
  90. );
  91. req.addEventListener(
  92. "error",
  93. function()
  94. {
  95. failureCallback();
  96. }
  97. );
  98. req.addEventListener(
  99. "abort",
  100. function()
  101. {
  102. failureCallback();
  103. }
  104. );
  105. const prefix = this.host + ":" + this.port;
  106. const addr = prefix + url;
  107. //console.log("GET addr: '" + addr + "'");
  108. req.open("GET", addr);
  109. req.send();
  110. }
  111. LFSA.prototype.requestPath = function(successCallback, failureCallback)
  112. {
  113. this.get("/path", successCallback, failureCallback);
  114. }
  115. LFSA.prototype.post = function(url, data, successCallback, failureCallback)
  116. {
  117. var req = new XMLHttpRequest();
  118. req.addEventListener(
  119. "load",
  120. function()
  121. {
  122. console.log("POST.successCallback.responseText: '" + this.responseText + "'");
  123. successCallback(this.responseText);
  124. }
  125. );
  126. req.addEventListener(
  127. "error",
  128. function()
  129. {
  130. failureCallback();
  131. }
  132. );
  133. req.addEventListener(
  134. "abort",
  135. function()
  136. {
  137. failureCallback();
  138. }
  139. );
  140. const prefix = this.host + ":" + this.port;
  141. const addr = prefix + url;
  142. console.log("POST addr: '" + addr + "'");
  143. req.open("POST", addr);
  144. req.send(data);
  145. }
  146. LFSA.prototype.requestFileList = function(dir, successCallback, failureCallback)
  147. {
  148. this.post(
  149. "/list",
  150. dir,
  151. function(response)
  152. {
  153. var json = JSON.parse(response);
  154. successCallback(json);
  155. },
  156. failureCallback
  157. );
  158. }
  159. LFSA.prototype.requestFile = function(path, successCallback, failureCallback)
  160. {
  161. this.post(
  162. "/read",
  163. path,
  164. successCallback,
  165. failureCallback
  166. );
  167. }
  168. LFSA.prototype.saveFile = function(path, contents, successCallback, failureCallback)
  169. {
  170. var data = {};
  171. data["path"] = path;
  172. data["contents"] = btoa(contents);
  173. var datastr = JSON.stringify(data);
  174. this.post(
  175. "/write",
  176. datastr,
  177. successCallback,
  178. failureCallback
  179. );
  180. }
  181. <!-- Reusable -->
  182. function fileExists(fileName, fileList)
  183. {
  184. for (var id in fileList)
  185. {
  186. var file = fileList[id];
  187. if (file.path === fileName)
  188. {
  189. return true;
  190. }
  191. }
  192. return false;
  193. }
  194. // Topic: Create GUID / UUID in JavaScript?
  195. // Source: https://stackoverflow.com/a/2117523
  196. function generateUUID()
  197. {
  198. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
  199. /[xy]/g,
  200. function(c)
  201. {
  202. var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
  203. return v.toString(16);
  204. }
  205. );
  206. }
  207. function LOG(message)
  208. {
  209. var log = document.getElementById("log");
  210. var now = new Date();
  211. log.innerHTML += now.toISOString() + " " + message + "<br>";
  212. }
  213. function parseINI(contents)
  214. {
  215. var cfg = { };
  216. var lines = contents.split(/\r\n|\r|\n/);
  217. for (var id in lines)
  218. {
  219. var line = lines[id];
  220. var keyAndValue = line.split(/=/);
  221. if (keyAndValue.length == 2)
  222. {
  223. var key = keyAndValue[0].trim();
  224. var value = keyAndValue[1].trim();
  225. cfg[key] = value;
  226. }
  227. }
  228. return cfg;
  229. }
  230. // ReporterSubscription class.
  231. function ReporterSubscription(id, callback, reporter)
  232. {
  233. this.id = id;
  234. this.callback = callback;
  235. this.reporter = reporter;
  236. }
  237. // Reporter class.
  238. function Reporter(name)
  239. {
  240. this.name =
  241. (typeof name !== "undefined") ?
  242. name :
  243. "";
  244. this.subscriptions = [];
  245. }
  246. Reporter.prototype.report = function()
  247. {
  248. for (var id in this.subscriptions)
  249. {
  250. var subscription = this.subscriptions[id];
  251. subscription.callback();
  252. }
  253. }
  254. Reporter.prototype.subscribe = function(callback)
  255. {
  256. var id = generateUUID();
  257. var subscription = new ReporterSubscription(id, callback, this);
  258. this.subscriptions.push(subscription);
  259. return subscription;
  260. }
  261. <!-- Tool.js -->
  262. // Tool class.
  263. function Tool()
  264. {
  265. this.lfsa = new LFSA();
  266. this.cfgExists = false;
  267. this.cfgExistsChanged = new Reporter();
  268. this.cfg = {};
  269. this.cfgChanged = new Reporter();
  270. this.cfgSaved = new Reporter();
  271. }
  272. // Tool's startup sequence.
  273. Tool.prototype.run = function()
  274. {
  275. var self = this;
  276. this.refreshLFSAPath();
  277. this.checkCfgExistence();
  278. this.cfgExistsChanged.subscribe(function(){
  279. LOG("cfgExistsChanged. cfgExists: '" + self.cfgExists + "'");
  280. });
  281. this.cfgExistsChanged.subscribe(function(){
  282. self.readCfg();
  283. });
  284. this.cfgChanged.subscribe(function(){
  285. LOG("cfgChanged. cfg: '" + self.cfg + "'");
  286. });
  287. this.cfgChanged.subscribe(function(){
  288. self.displayCfg();
  289. });
  290. this.cfgSaved.subscribe(function(){
  291. self.readCfg();
  292. });
  293. }
  294. Tool.prototype.refreshLFSAPath = function()
  295. {
  296. var lfsaPath = document.getElementById("lfsaPath");
  297. var success = function(response)
  298. {
  299. lfsaPath.innerHTML = response;
  300. }
  301. var failure = function()
  302. {
  303. lfsaPath.innerHTML = "<span class='error'>Error</span>";
  304. }
  305. this.lfsa.requestPath(success, failure);
  306. }
  307. Tool.prototype.checkCfgExistence = function()
  308. {
  309. var self = this;
  310. var success = function(fileList)
  311. {
  312. var cfgExists = fileExists("cfg", fileList);
  313. if (!cfgExists)
  314. {
  315. LOG("ERROR `cfg` file does not exist");
  316. return;
  317. }
  318. // Report.
  319. self.cfgExists = true;
  320. self.cfgExistsChanged.report();
  321. }
  322. var failure = function()
  323. {
  324. LOG("ERROR Could not check if `cfg` exists");
  325. }
  326. this.lfsa.requestFileList("", success, failure);
  327. }
  328. Tool.prototype.readCfg = function()
  329. {
  330. var self = this;
  331. var success = function(contents)
  332. {
  333. self.cfg = parseINI(contents);
  334. self.cfgChanged.report();
  335. }
  336. var failure = function()
  337. {
  338. LOG("ERROR Could not read `cfg` file");
  339. }
  340. this.lfsa.requestFile("cfg", success, failure);
  341. }
  342. Tool.prototype.displayCfg = function()
  343. {
  344. var input = document.getElementById("input");
  345. input.value = this.cfg["input"];
  346. var item = document.getElementById("item");
  347. item.value = this.cfg["item"];
  348. var preview = document.getElementById("preview");
  349. preview.value = this.cfg["preview"];
  350. var index = document.getElementById("index");
  351. index.value = this.cfg["index"];
  352. var output = document.getElementById("output");
  353. output.value = this.cfg["output"];
  354. }
  355. Tool.prototype.saveCfg = function()
  356. {
  357. // Compose cfg file to save.
  358. var cfgFile = "";
  359. var input = document.getElementById("input");
  360. cfgFile += "input = " + input.value + "\n";
  361. var item = document.getElementById("item");
  362. cfgFile += "item = " + item.value + "\n";
  363. var preview = document.getElementById("preview");
  364. cfgFile += "preview = " + preview.value + "\n";
  365. var index = document.getElementById("index");
  366. cfgFile += "index = " + index.value + "\n";
  367. var output = document.getElementById("output");
  368. cfgFile += "output = " + output.value + "\n";
  369. // Save file.
  370. var self = this;
  371. var success = function()
  372. {
  373. self.cfgSaved.report();
  374. }
  375. var failure = function()
  376. {
  377. LOG("ERROR Could not save `cfg` file");
  378. }
  379. this.lfsa.saveFile("cfg", cfgFile, success, failure);
  380. }
  381. <!-- Startup -->
  382. window.pskovTool = new Tool();
  383. window.pskovTool.run()
  384. </script>
  385. </body>
  386. </html>