|
|
@@ -0,0 +1,411 @@ |
|
|
|
<!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> |