window.addEventListener('load', main(document));
function main(document) {
graftSolitude(window);
webconfig(window);
var mysolitude;
if (true || (typeof solitude.style) === 'undefined') {
mysolitude = readyWeb();
}
let Que;
initializeQue();
//アプリケーション毎に初期化操作
initializeSolitudeApps(mysolitude.apps)
Que("li.tab").list().forEach(function (val, index, _list) {
val.addEventListener("click", function () {
selectTab(index);
});
})
append(location.href);
const leftMenu = Que("#left-menu").get();
const menuToggle = Que("#menu-toggle").get();
menuToggle.addEventListener("click", function () {
leftMenu.classList.remove("initial")
toggleMenuItem(leftMenu);
Que("#left-menu li span").list().forEach(function (val) {
toggleMenuItem(val);
})
toggleMenuItem(Que("#main").get());
})
// 以下、宣言
function toggleMenuItem(element) {
if (element.classList.contains("expanded")) {
element.classList.add("shrinked");
element.classList.remove("expanded");
} else {
element.classList.add("expanded");
element.classList.remove("shrinked");
}
}
function selectTab(index) {
let tab, content;
Que("#main-pane li.tab").list().forEach(function (val) {
val.classList.remove("selected");
if (val.dataset.soloAppId == index) {
tab = val;
}
});
Que("#main-pane div.main-article").list().forEach(function (val) {
val.classList.remove("selected");
if (val.dataset.soloAppId == index) {
content = val;
}
});
tab.classList.add("selected");
content.classList.add("selected");
}
function initializeQue() {
//Queはglobalではない。親スコープで宣言済み。
Que = newQue;
Query.prototype = {
get list() {return asList},
get get() {return asNode},
get que() {return reQue},
}
function Query(selector, base) {
if (base instanceof Query) {
this.origin = base.get();
} else {
this.origin = base || document;
}
this.raw = this.origin.querySelectorAll(selector);
/*
this.list = asList;
this.get = asNode;
this.que = reQue;
*/
}
function asList() {
return this.raw;
}
function asNode() {
if (this.raw.length > 0) {
return this.raw[0];
}
}
function newQue(selector, base) {
return new Query(selector, base);
}
function reQue(selector) {
return new Query(selector, this.get())
}
}
function append(kontent) {
let logs = Que("#logarea").get().value
logs += kontent + "\n";
Que("#logarea").get().value = logs;
}
/**
* solitude web版でのsolitudeオブジェクトの組み立てを行う
*/
function readyWeb() {
//先にwebconfigを起動している前提
const solitude = window.solitude;
solitude.apps = {};
Object.assign(solitude.apps, window.tmp.solitudeapps);
addProperty(solitude);
return solitude;
/*
function buildWebSolitude(_global) {
const solitude = {};
solitude.write = {}
solitude.write.local = (_path, contents) => { append(contents) };
return solitude;
}
*/
function addProperty(app) {
//solitude本体を設定しているような表現をしたいための回りくどい書き方
Object.defineProperty(app, 'style', {
get() { return 'web' }
});
app.write = {}
app.write.local = writeLocal;
app.read = {};
app.read.local = readLocal;
return app;
function writeLocal(path, _contents) {
solitude.io.fs.download(path, cotents, "text/plain");
}
function readLocal(path) {
// stringで解決するPromiseを返したい。
return fetch(path).then(
(response) => {
if (response.ok) {
return response.text();
} else {
throw new Error(`HTTP error, status = ${response.status}`);
}
}, (cause) => {
const error = new Error('ファイルのオープンに失敗しました。causeプロパティで原因となったオブジェクトを返します。');
error.cause = cause;
throw error;
}
);
}
}
}
function initializeSolitudeApps(apps) {
appsProto = {
useMenu: true,
useTab: true,
autorun: false,
};
const appFuncs = [IframeApp, StaticPageApp, BatchApp];
appFuncs.forEach(appFunc => {
appFunc.prototype = appsProto;
});
let app;
let appInstanceID = 0;
for (const [name, conf] of Object.entries(apps)) {
const appType = conf.type || "undef";
switch (appType) {
case "main":
case "undef":
app = null;
//do nothing
break;
case "staticpage":
app = new StaticPageApp(name, conf);
break;
case "iframe":
app = new IframeApp(name, conf);
break;
case "batch":
app = new BatchApp(name, conf);
break;
default:
//something wrong;
break;
}
if(app) {
app.instanceID = ++appInstanceID;
app.load();
solitude.log.info("loaded " + name +", instanceID " + app.instanceID )
}
}
//巻き上げを期待しているためclass構文ではない。
function IframeApp(name, conf) {
this.name = name;
this.conf = conf;
this.load = loadApp;
this.template = "#app-type-iframe";
this.callback = iframeCallback;
}
function StaticPageApp(name, conf) {
this.name = name;
this.conf = conf;
this.load = loadApp;
this.template = "#app-type-staticpage";
this.callback = staticpageCallback;
}
function BatchApp(name, conf) {
this.name = name;
this.conf = conf;
this.load = loadBatchApp;
this.template = "#app-type-batch";
this.callback = batchCallback;
}
function loadApp() {
addNewMenu(this.name);
const mount = Que("#left-menu ol");
const app = this;
mount.que("li.init").get().addEventListener("click", function () {
if(isInitialized(app.instanceID)) {
return;
}
addNewTab(app);
addNewContent(app);
solitude.log.info(app.name + " is initialized");
});
mount.que("li.init").get().classList.remove("init");
}
function isInitialized(appInstanceID) {
//アプリのタブが出ているかでロード済みかを判断
let result = false;
Que("#main-tabs li").list().forEach(elem => {
if(appInstanceID == elem.dataset.soloAppId) {
result = true;
}
});
return result;
}
function loadBatchApp() {
addNewContent(this);
}
function addNewMenu(name) {
const mount = Que("#left-menu ol").get();
let menu = Que("#app-menu").get();
menu = menu.content.cloneNode(true);
const span = Que("span", menu).get();
// template では初期状態はexpanded
if (Que("#left-menu.shrinked").list().length > 0) {
const cls = span.classList;
cls.remove("expanded");
cls.add("shrinked");
}
span.textContent = name;
mount.appendChild(menu);
}
function addNewTab(app) {
const mount = Que("#main-tabs").get();
let tab = Que("#app-tab").get()
tab = tab.content.cloneNode(true);
const li = Que("li", tab).get();
li.textContent = app.name;
li.dataset.soloAppId = app.instanceID;
const index = app.instanceID;
mount.appendChild(tab);
li.addEventListener("click", () => {
selectTab(index);
});
}
function addNewContent(app) {
const appNode = (Que(app.template).get()).content.cloneNode(true);
const base = Que("div.main-article", appNode);
base.get().classList.remove("undefined");
base.get().dataset.soloAppId = app.instanceID;
base.que("div.app-container").get().classList.add(app.name);
app.callback(app, base);
const mount = Que("#app-pane").get();
mount.appendChild(base.get());
}
function iframeCallback(app, base) {
const iframe = Que("div.app-container > iframe", base).get();
iframe.setAttribute("id", app.name);
iframe.setAttribute("title", app.name);
iframe.setAttribute("src", app.conf.src);
}
function staticpageCallback(app, base) {
mysolitude.read.local(app.conf.src).then((text) => {
const parser = new DOMParser();
const doc = parser.parseFromString(text, "text/html");
const content = Que("div.app-body", doc).get().cloneNode(true);
Que("div.app-container", base).get().appendChild(content);
//文書内のJavascriptコードを実行する。簡単な実装。
//これだとon.loadイベントとかがキックされなくなってしまう気がする。
const removes = [];
Que("script", content).list().forEach(element => {
const script = document.createElement("script")
script.innerHTML = element.innerHTML;
for (const attr of element.attributes) {
script.setAttribute(attr.name, attr.value);
}
element.before(script)
removes.push(element);
});
for (const script of removes) {
script.remove();
}
});
}
function batchCallback(app, base) {
const content = document.createElement("script")
content.setAttribute("src", app.conf.src);
Que("div.app-container", base).get().appendChild(content);
}
}
}