diff --git a/src/js/src/main/app.html b/src/js/src/main/app.html index ba73e37..b895e04 100644 --- a/src/js/src/main/app.html +++ b/src/js/src/main/app.html @@ -14,7 +14,7 @@ -
+
-
    -
  • タブ1
  • -
-
-
-

Hello Solitude World

-

This is Solitude

+
+
    +
  • メイン
  • +
+
+
+

Hello Solitude World

+

This is Solitude

+
+
+ +
- - + \ No newline at end of file diff --git a/src/js/src/main/app.js b/src/js/src/main/app.js index 4658228..6c612dc 100644 --- a/src/js/src/main/app.js +++ b/src/js/src/main/app.js @@ -1,30 +1,41 @@ -function main(document) { - webconfig(window); - if ((typeof solitude.style) === 'undefined') { - solitude = readyWeb(); - } - //アプリケーション毎に初期化操作 - initializeSolitudeApps(solitude.apps()) +window.addEventListener('load', main(document)); - query("li.tab").forEach(function (val, index, list) { +function main(document) { + graftSolitude(window); + webconfig(window); + var mysolitude; + if (true || (typeof solitude.style) === 'undefined') { + mysolitude = readyWeb(); + } + + let Que; + const mainOrgan = solitude.newOrgan; + initializeQue(); + + //アプリケーション毎に初期化操作 + initializeSolitudeApps(mysolitude.apps) + + Que("li.tab").list().forEach(function (val, index, _list) { val.addEventListener("click", function () { selectTab(index); }); }) append(location.href); - const leftMenu = query("#left-menu")[0]; - const menuToggle = query("#menu-toggle")[0] + const leftMenu = Que("#left-menu").get(); + const menuToggle = Que("#menu-toggle").get(); menuToggle.addEventListener("click", function () { leftMenu.classList.remove("initial") toggleMenuItem(leftMenu); - query("#left-menu li span").forEach(function (val) { + Que("#left-menu li span").list().forEach(function (val) { toggleMenuItem(val); }) + toggleMenuItem(Que("#main").get()); + }) window.addEventListener("message", (event) => { - const appFrame = query("#main-pane .app-container iframe")[0] + const appFrame = Que("#main-pane .app-container iframe").get() expectedOrigin = appFrame.contentWindow.location.origin if (event.origin != expectedOrigin) { append("failed!") @@ -57,98 +68,136 @@ } function selectTab(index) { - query("li.tab.selected").forEach(function (val) { + let tab, content; + Que("#main-pane li.tab").list().forEach(function (val) { val.classList.remove("selected"); + if(val.dataset.soloAppId == index) { + tab = val; + } }); - query("li.tab")[index].classList.add("selected"); - query("div.main-article.selected").forEach(function (val) { + Que("#main-pane div.main-article").list().forEach(function (val) { val.classList.remove("selected"); + if(val.dataset.soloAppId == index) { + content = val; + } }); - query("div.main-article")[index].classList.add("selected"); + + tab.classList.add("selected"); + content.classList.add("selected"); } - function query(selector) { - return document.querySelectorAll(selector) + function initializeQue() { + //Queはglobalではない。親スコープで宣言済み。 + Que = newQue; + + 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 = query("#logarea")[0].value + let logs = Que("#logarea").get().value logs += kontent + "\n"; - query("#logarea")[0].value = logs; + Que("#logarea").get().value = logs; } /** * solitude web版でのsolitudeオブジェクトの組み立てを行う */ function readyWeb() { - const solitude = buildWebSolitude(); - const apps = window.tmp.solitudeapps; - solitude.apps = () => apps; + //先にwebconfigを起動している前提 + const solitude = window.solitude; + solitude.apps = {}; + Object.assign(solitude.apps, window.tmp.solitudeapps); addProperty(solitude); return solitude; - function buildWebSolitude(global) { + /* + function buildWebSolitude(_global) { const solitude = {}; solitude.write = {} - solitude.write.local = (path, contents) => { append(contents) }; + solitude.write.local = (_path, contents) => { append(contents) }; return solitude; } - + */ function addProperty(app) { //solitude本体を設定しているような表現をしたいための回りくどい書き方 - const solitude = { - get style() { return "web" }, - "write": { - "local": writeLocal, - }, + Object.defineProperty(app, 'style', { + get() { return 'web' } + }); - "read": { - "local": readLocal - } + app.write = {} + app.write.local = writeLocal; + app.read = {}; + app.read.local = readLocal; + return app; - } - - //ここからsolitudeに設定したプロパティをappへうつす - app.write = solitude.write; - app.read = solitude.read; - - for (prop in solitude) { - Object.defineProperty(app, prop, { - get() { return solitude[prop] } - }) - } - - return; - - function writeLocal(path, contents) { + function writeLocal(path, _contents) { solitude.io.fs.download(path, cotents, "text/plain"); } function readLocal(path) { // stringで解決するPromiseを返したい。 - return fetch(path) - .then((response) => { + 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 - }); + }, (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) { @@ -161,128 +210,154 @@ break; case "staticpage": - loadStaticPageApps(name, conf) + app = new StaticPageApp(name, conf); + app.instanceID = ++appInstanceID; + app.load(); break; case "iframe": - loadIframeApps(name, conf); + app = new IframeApp(name, conf); + app.instanceID = ++appInstanceID; + app.load(); + break; + case "batch": + app = new BatchApp(name, conf); + app.instanceID = ++appInstanceID; + app.load(); break; } } - } - - function loadIframeApps(name, conf) { - addNewMenu(name, conf); - const mount = query("#left-menu ol")[0]; - mount.querySelector("li.init").addEventListener("click", function () { - bootIframeApps(name, conf); - }); - mount.querySelector("li.init").classList.remove("init"); - } - - function loadStaticPageApps(name, conf) { - addNewMenu(name, conf); - const mount = query("#left-menu ol")[0]; - mount.querySelector("li.init").addEventListener("click", function () { - bootStaticPageApps(name, conf); - }); - mount.querySelector("li.init").classList.remove("init"); - } - - function bootIframeApps(name, conf) { - addNewTab(name); - addNewContent(name, conf); - } - - function bootStaticPageApps(name, conf) { - addNewTab(name); - addNewStaticPageContent(name, conf); - } - function addNewMenu(name, conf) { - const mount = query("#left-menu ol")[0]; - let menu = query("#app-menu")[0]; - menu = menu.content.cloneNode(true); + //巻き上げを期待しているためclass構文ではない。 + + function IframeApp(name, conf) { + this.name = name; + this.conf = conf; + this.load = loadApp; + this.template = "#app-type-iframe"; + this.callback = iframeCallback; + } - const span = menu.querySelector("span"); - // template では初期状態はexpanded - if (query("#left-menu.shrinked").length > 0) { - const cls = span.classList; - cls.remove("expanded"); - cls.add("shrinked"); + 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 () { + addNewTab(app); + addNewContent(app); + }); + mount.que("li.init").get().classList.remove("init"); + } + + 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) { + /* + タブに対するイベント設定のあたり + val.addEventListener("click", function () { + selectTab(index); + */ + 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); + //mainOrgan.fire("log", "open appID:" + app.instanceID + ", appID:" + app.name, solitude.nerve); + }); + } + + 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()); } - span.textContent = name; - mount.appendChild(menu); - } - function addNewTab(label) { - /* - タブに対するイベント設定のあたり - val.addEventListener("click", function () { - selectTab(index); - */ - const mount = query("#main-tabs")[0]; - let tab = document.querySelector("#app-tab") - tab = tab.content.cloneNode(true); - tab.querySelector("li").textContent = label; - const index = query("li.tab").length - mount.appendChild(tab); + 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); + } - /* - * ・追加したタブのindexの推定のやり方がよくない - * ・イベントの設定コードが重複が気持ち悪い - */ - query("li.tab")[index].addEventListener("click", function () { - selectTab(index); - }) - } - - function addNewContent(name, conf) { - const mount = query("#main-pane")[0]; - let app = query("#app-type-iframe")[0]; - app = app.content.cloneNode(true) - const base = app.querySelector("div.main-article"); - base.classList.remove("undefined") - - const iframe = app.querySelector("div.app-container > iframe"); - iframe.setAttribute("id", name); - iframe.setAttribute("title", name); - iframe.setAttribute("src", conf.src); - - mount.appendChild(base) - } - - function addNewStaticPageContent(name, conf) { - const mount = query("#main-pane")[0]; - let app = query("#app-type-staticpage")[0]; - app = app.content.cloneNode(true) - const base = app.querySelector("div.main-article"); - base.classList.remove("undefined"); - - /* - const staticpage = fetch(conf.src) - .then((res) => { - if(res.ok) { - return res.text(); - } else { - throw new Error(`HTTP error, status = ${res.status}`); - } - }).then((text) => { - const parser = new DOMParser() + 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 = doc.querySelector("div.app-body").cloneNode(true); - base.querySelector("div.app-container").appendChild(content); - mount.appendChild(base) - }); - */ + const content = Que("div.app-body", doc).get().cloneNode(true); + Que("div.app-container", base).get().appendChild(content); - solitude.read.local(conf.src).then((text) => { - const parser = new DOMParser() - const doc = parser.parseFromString(text, "text/html"); - const content = doc.querySelector("div.app-body").cloneNode(true); - base.querySelector("div.app-container").appendChild(content); - mount.appendChild(base) - }) + //文書内の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); + } } } \ No newline at end of file diff --git a/src/js/src/main/css/index.css b/src/js/src/main/css/index.css index ca0127d..d567feb 100644 --- a/src/js/src/main/css/index.css +++ b/src/js/src/main/css/index.css @@ -1,3 +1,8 @@ +html, body { + margin: 0em; + height: 100%; +} + body { color: #ffffff; background-color: #6A91C1; @@ -9,26 +14,38 @@ color:#ffffff; font-size: 1.25em; background-color: #6A91C1; - margin-bottom: 0.25em; + margin-bottom: 0em; margin-left: 0.5em; - height: 2em; + height: 4vh; vertical-align: middle; } #header > p { - margin-top: 0em; - margin-bottom: 0em; + margin: 0em; padding-left: 0.5em; + padding-bottom: 0px;; } #main { + grid-template-columns: 3fr 7fr; white-space:nowrap; overflow-x: scroll; perspective: 3000px; + box-sizing: border-box; + height: 85vh; +} + +#main.expanded { + display: grid; + grid-template-columns: 250px 1fr; +} + +#main.shrinked { + display: grid; + grid-template-columns: 50px 1fr; } #main > div { - display: inline-block; vertical-align: top; margin-right: 0.25em; } @@ -36,12 +53,15 @@ #left-menu { font-size: 1.25em; + height: 100%; min-height: 640px; + max-height: 100%; margin-left: 0.5em; color:#ffffff; background-color: #6A91C1; } +/* #left-menu.expanded.initial li { animation: left-menu-expanding forwards 0s ease 0s normal; } @@ -75,9 +95,10 @@ max-width: 1.5em; } } - +*/ #left-menu ol { padding-left: 0em; + margin: 0px; } #left-menu li:nth-child(1) { @@ -118,8 +139,9 @@ #main-pane { width:100%; - padding-top: 0.75em; - background-color:#6A91C1; + height: inherit; + background-color:#6A91C1; + display: block; } #main-tabs { @@ -157,16 +179,18 @@ div.main-article { display: none; + overflow-y: scroll; } div.main-article.selected { display: inline-block; font-size: 1em; min-width: 300px; - min-height: 640px; + min-height: 480px; width:100%; + height:calc(80vh - 1em); + padding :0em; padding-left : 0.5em; - padding-top :0.5em; color: #000000; background-color: #ffffff; } @@ -180,11 +204,44 @@ #main-pane div.app-container { border: 0.1em solid #516C8D; - height: 640px; + height: 100%; visibility: initial; resize: both; } +#footer { + bottom: 0px; + position: sticky; + height: 10vh; + width: 100%; + padding-left: 50px; + padding-right: 50px; + box-sizing: border-box; +} + +#cli-pane { + border-style: solid; + border-width: 2px; + width: 95%; + height: 100%; + font-size: 16px; + +} + +#cli-pane div.control { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.5em; + margin-bottom: 0.5em; + width: 90%; +} + +#commandline { + width: 100%; + font-size: 16px; +} + + #logarea { display:none; } diff --git a/src/js/src/main/web-conf.js b/src/js/src/main/web-conf.js index 45c481b..eb05d74 100644 --- a/src/js/src/main/web-conf.js +++ b/src/js/src/main/web-conf.js @@ -1,25 +1,65 @@ function webconfig(global) { - global.tmp = global.tmp || {}; - global.tmp.solitudeapps = {}; - loadTo(global.tmp.solitudeapps); + global.tmp = global.tmp || {}; + global.tmp.solitudeapps = {}; + const configurator = createAppConfigurator(global.tmp.solitudeapps); + loadTo(configurator); +} + +function createAppConfigurator(target) { + const app = ((writeback)=> { + const apps = writeback; + let currentApp = {}; + + const result = { + set new(val) { + apps[val] = {}; + currentApp = val; + }, + + set type(val) { + apps[currentApp].type = val; + }, + + set src(val) { + apps[currentApp].src = val; + }, + + get prop() { + return apps[currentApp]; + } + + } + + return result; + })(target); + + return app } -function loadTo(target) { - const apps = target; +function loadTo(app) { + app.new = "main"; + app.type = "mainType"; - const main = {} - main.type = "main"; - apps.main = main; + app.new = "mdeditor"; + app.type = "iframe"; + app.src = "../mdeditor/app.html" - const mdeditor = {}; - mdeditor.type = "iframe"; - mdeditor.src = "../mdeditor/app.html"; - apps.mdeditor = mdeditor; + app.new = "example" + app.type = "staticpage" + app.src = "../example/app.html" + app.prop.loader = fetch; - const example = {}; - example.type = "staticpage"; - example.src = "../example/app.html" - example.loadder = fetch; - apps.example = example; + app.new = "logger"; + app.type = "staticpage"; + app.src = "../simplelog/app.html" + + app.new = "bookmark"; + app.type = "iframe"; + app.src = "../bookmark/app.html" + + app.new = "logData"; + app.type = "batch"; + app.src = "../logData/app.js" + } \ No newline at end of file