412 lines
14 KiB
HTML
412 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<meta charset="utf-8">
|
|
<head>
|
|
<style>
|
|
table
|
|
{
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
table, th, td
|
|
{
|
|
border: 1px solid #aaa;
|
|
padding: 0.5em;
|
|
margin-top: 0.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
.error
|
|
{
|
|
color: red;
|
|
}
|
|
|
|
.section
|
|
{
|
|
text-align: center;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<table>
|
|
<tr>
|
|
<td colspan="2" class="section">
|
|
<a href="http://opengamestudio.org/lfsa">Local file system access</a>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Path:</td>
|
|
<td id="lfsaPath">Updating...</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2" class="section">
|
|
Configuration
|
|
<button type="button" onclick="window.pskovTool.saveCfg()">Save</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Input directory:</td>
|
|
<td><input id="input"></input>
|
|
</tr>
|
|
<tr>
|
|
<td>News item template:</td>
|
|
<td><input id="item"></input>
|
|
</tr>
|
|
<tr>
|
|
<td>News preview template:</td>
|
|
<td><input id="preview"></input>
|
|
</tr>
|
|
<tr>
|
|
<td>Index template:</td>
|
|
<td><input id="index"></input>
|
|
</tr>
|
|
<tr>
|
|
<td>Output directory:</td>
|
|
<td><input id="output"></input>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2" class="section">Log</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="log" colspan="2"></td>
|
|
</tr>
|
|
</table>
|
|
<script type="text/javascript">
|
|
<!-- LFSA.js -->
|
|
// LFSA class to communicate with local-file-system-access instance.
|
|
function LFSA()
|
|
{
|
|
this.host = "http://127.0.0.1";
|
|
this.port = 8000;
|
|
}
|
|
LFSA.prototype.get = function(url, successCallback, failureCallback)
|
|
{
|
|
var req = new XMLHttpRequest();
|
|
req.addEventListener(
|
|
"load",
|
|
function()
|
|
{
|
|
//console.log("get.successCallback.responseText: '" + this.responseText + "'");
|
|
successCallback(this.responseText);
|
|
}
|
|
);
|
|
req.addEventListener(
|
|
"error",
|
|
function()
|
|
{
|
|
failureCallback();
|
|
}
|
|
);
|
|
req.addEventListener(
|
|
"abort",
|
|
function()
|
|
{
|
|
failureCallback();
|
|
}
|
|
);
|
|
|
|
const prefix = this.host + ":" + this.port;
|
|
const addr = prefix + url;
|
|
//console.log("GET addr: '" + addr + "'");
|
|
req.open("GET", addr);
|
|
req.send();
|
|
}
|
|
LFSA.prototype.requestPath = function(successCallback, failureCallback)
|
|
{
|
|
this.get("/path", successCallback, failureCallback);
|
|
}
|
|
LFSA.prototype.post = function(url, data, successCallback, failureCallback)
|
|
{
|
|
var req = new XMLHttpRequest();
|
|
req.addEventListener(
|
|
"load",
|
|
function()
|
|
{
|
|
console.log("POST.successCallback.responseText: '" + this.responseText + "'");
|
|
successCallback(this.responseText);
|
|
}
|
|
);
|
|
req.addEventListener(
|
|
"error",
|
|
function()
|
|
{
|
|
failureCallback();
|
|
}
|
|
);
|
|
req.addEventListener(
|
|
"abort",
|
|
function()
|
|
{
|
|
failureCallback();
|
|
}
|
|
);
|
|
|
|
const prefix = this.host + ":" + this.port;
|
|
const addr = prefix + url;
|
|
console.log("POST addr: '" + addr + "'");
|
|
req.open("POST", addr);
|
|
req.send(data);
|
|
}
|
|
LFSA.prototype.requestFileList = function(dir, successCallback, failureCallback)
|
|
{
|
|
this.post(
|
|
"/list",
|
|
dir,
|
|
function(response)
|
|
{
|
|
var json = JSON.parse(response);
|
|
successCallback(json);
|
|
},
|
|
failureCallback
|
|
);
|
|
}
|
|
LFSA.prototype.requestFile = function(path, successCallback, failureCallback)
|
|
{
|
|
this.post(
|
|
"/read",
|
|
path,
|
|
successCallback,
|
|
failureCallback
|
|
);
|
|
}
|
|
LFSA.prototype.saveFile = function(path, contents, successCallback, failureCallback)
|
|
{
|
|
var data = {};
|
|
data["path"] = path;
|
|
data["contents"] = btoa(contents);
|
|
var datastr = JSON.stringify(data);
|
|
|
|
this.post(
|
|
"/write",
|
|
datastr,
|
|
successCallback,
|
|
failureCallback
|
|
);
|
|
}
|
|
|
|
<!-- Reusable -->
|
|
function fileExists(fileName, fileList)
|
|
{
|
|
for (var id in fileList)
|
|
{
|
|
var file = fileList[id];
|
|
if (file.path === fileName)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
// Topic: Create GUID / UUID in JavaScript?
|
|
// Source: https://stackoverflow.com/a/2117523
|
|
function generateUUID()
|
|
{
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
|
|
/[xy]/g,
|
|
function(c)
|
|
{
|
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
return v.toString(16);
|
|
}
|
|
);
|
|
}
|
|
function LOG(message)
|
|
{
|
|
var log = document.getElementById("log");
|
|
var now = new Date();
|
|
log.innerHTML += now.toISOString() + " " + message + "<br>";
|
|
}
|
|
function parseINI(contents)
|
|
{
|
|
var cfg = { };
|
|
var lines = contents.split(/\r\n|\r|\n/);
|
|
for (var id in lines)
|
|
{
|
|
var line = lines[id];
|
|
var keyAndValue = line.split(/=/);
|
|
if (keyAndValue.length == 2)
|
|
{
|
|
var key = keyAndValue[0].trim();
|
|
var value = keyAndValue[1].trim();
|
|
cfg[key] = value;
|
|
}
|
|
}
|
|
|
|
return cfg;
|
|
}
|
|
// ReporterSubscription class.
|
|
|
|
function ReporterSubscription(id, callback, reporter)
|
|
{
|
|
this.id = id;
|
|
this.callback = callback;
|
|
this.reporter = reporter;
|
|
}
|
|
|
|
// Reporter class.
|
|
|
|
function Reporter(name)
|
|
{
|
|
this.name =
|
|
(typeof name !== "undefined") ?
|
|
name :
|
|
"";
|
|
this.subscriptions = [];
|
|
}
|
|
|
|
Reporter.prototype.report = function()
|
|
{
|
|
for (var id in this.subscriptions)
|
|
{
|
|
var subscription = this.subscriptions[id];
|
|
subscription.callback();
|
|
}
|
|
}
|
|
|
|
Reporter.prototype.subscribe = function(callback)
|
|
{
|
|
var id = generateUUID();
|
|
var subscription = new ReporterSubscription(id, callback, this);
|
|
this.subscriptions.push(subscription);
|
|
return subscription;
|
|
}
|
|
|
|
<!-- Tool.js -->
|
|
// Tool class.
|
|
function Tool()
|
|
{
|
|
this.lfsa = new LFSA();
|
|
this.cfgExists = false;
|
|
this.cfgExistsChanged = new Reporter();
|
|
this.cfg = {};
|
|
this.cfgChanged = new Reporter();
|
|
this.cfgSaved = new Reporter();
|
|
}
|
|
// Tool's startup sequence.
|
|
Tool.prototype.run = function()
|
|
{
|
|
var self = this;
|
|
this.refreshLFSAPath();
|
|
this.checkCfgExistence();
|
|
this.cfgExistsChanged.subscribe(function(){
|
|
LOG("cfgExistsChanged. cfgExists: '" + self.cfgExists + "'");
|
|
});
|
|
this.cfgExistsChanged.subscribe(function(){
|
|
self.readCfg();
|
|
});
|
|
this.cfgChanged.subscribe(function(){
|
|
LOG("cfgChanged. cfg: '" + self.cfg + "'");
|
|
});
|
|
this.cfgChanged.subscribe(function(){
|
|
self.displayCfg();
|
|
});
|
|
this.cfgSaved.subscribe(function(){
|
|
self.readCfg();
|
|
});
|
|
}
|
|
Tool.prototype.refreshLFSAPath = function()
|
|
{
|
|
var lfsaPath = document.getElementById("lfsaPath");
|
|
|
|
var success = function(response)
|
|
{
|
|
lfsaPath.innerHTML = response;
|
|
}
|
|
var failure = function()
|
|
{
|
|
lfsaPath.innerHTML = "<span class='error'>Error</span>";
|
|
}
|
|
|
|
this.lfsa.requestPath(success, failure);
|
|
}
|
|
Tool.prototype.checkCfgExistence = function()
|
|
{
|
|
var self = this;
|
|
|
|
var success = function(fileList)
|
|
{
|
|
var cfgExists = fileExists("cfg", fileList);
|
|
if (!cfgExists)
|
|
{
|
|
LOG("ERROR `cfg` file does not exist");
|
|
return;
|
|
}
|
|
|
|
// Report.
|
|
self.cfgExists = true;
|
|
self.cfgExistsChanged.report();
|
|
}
|
|
var failure = function()
|
|
{
|
|
LOG("ERROR Could not check if `cfg` exists");
|
|
}
|
|
|
|
this.lfsa.requestFileList("", success, failure);
|
|
}
|
|
Tool.prototype.readCfg = function()
|
|
{
|
|
var self = this;
|
|
|
|
var success = function(contents)
|
|
{
|
|
self.cfg = parseINI(contents);
|
|
self.cfgChanged.report();
|
|
}
|
|
var failure = function()
|
|
{
|
|
LOG("ERROR Could not read `cfg` file");
|
|
}
|
|
|
|
this.lfsa.requestFile("cfg", success, failure);
|
|
}
|
|
Tool.prototype.displayCfg = function()
|
|
{
|
|
var input = document.getElementById("input");
|
|
input.value = this.cfg["input"];
|
|
var item = document.getElementById("item");
|
|
item.value = this.cfg["item"];
|
|
var preview = document.getElementById("preview");
|
|
preview.value = this.cfg["preview"];
|
|
var index = document.getElementById("index");
|
|
index.value = this.cfg["index"];
|
|
var output = document.getElementById("output");
|
|
output.value = this.cfg["output"];
|
|
}
|
|
Tool.prototype.saveCfg = function()
|
|
{
|
|
// Compose cfg file to save.
|
|
var cfgFile = "";
|
|
var input = document.getElementById("input");
|
|
cfgFile += "input = " + input.value + "\n";
|
|
var item = document.getElementById("item");
|
|
cfgFile += "item = " + item.value + "\n";
|
|
var preview = document.getElementById("preview");
|
|
cfgFile += "preview = " + preview.value + "\n";
|
|
var index = document.getElementById("index");
|
|
cfgFile += "index = " + index.value + "\n";
|
|
var output = document.getElementById("output");
|
|
cfgFile += "output = " + output.value + "\n";
|
|
|
|
// Save file.
|
|
var self = this;
|
|
|
|
var success = function()
|
|
{
|
|
self.cfgSaved.report();
|
|
}
|
|
var failure = function()
|
|
{
|
|
LOG("ERROR Could not save `cfg` file");
|
|
}
|
|
|
|
this.lfsa.saveFile("cfg", cfgFile, success, failure);
|
|
}
|
|
|
|
<!-- Startup -->
|
|
window.pskovTool = new Tool();
|
|
window.pskovTool.run()
|
|
</script>
|
|
</body>
|
|
</html>
|