diff --git a/Merger.js b/Merger.js index 6eea33a..199fca4 100644 --- a/Merger.js +++ b/Merger.js @@ -1,5 +1,5 @@ /* - * Merger UI V0.3 t144567 + * Merger UI V0.3 * Copyright 2016 XWolfOVerride@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy of this @@ -22,27 +22,29 @@ var merger = new function () { - /** - * merger system variables - */ - var sys = { - _type: "system", - icon: "data:image/gif;base64,R0lGODlhIAAgAOMAAP///zOZ/47N8FxqpgAAAMzM/7+/v9nu+QBjpAA9hP///////////////////////yH5BAEKAA8ALAAAAAAgACAAAATq8MlJH7k16y3JEQXGjZVXBGBIkKQpoEIqsuVRxHAsr3Rn6zndjuYCCo8F1ahoPCJDG2bTKbTxKNIpVWAbXH03atDZ9ZYKh49zXC0M3l/LKZA+Bthc99uMnd/rLzhBZXtxBH53dGpAKISFZ4mJCIpHjo99kQGTiWmdbgkJe3AGmJKZdwUPem+ghQavHX6bpyABoqyhBK+wh3ezpwGrtwMJurtymsCRwsPGpHK/ysyizhME0dLDo7DWBMqZ017HFQYX36jN4xrl3tnU6hzswMLVPfLLrtw9EvfB28/7KMhzUy9gBnYFDa6DtyECADs=", - ver: "0.3", - color: { - frame: "teal", - client: "white", - // frame:"orange", - framecontrast: "white", - text: "black", - windowtitle: "black", - selection: "lightskyblue", - }, - icons: {} - }; + //=== Merger System Configuration + //============================================================================================= + var core, // Core object (initialized below) + sys = { // Configuration + _type: "system", + icon: "data:image/gif;base64,R0lGODlhIAAgAOMAAP///zOZ/47N8FxqpgAAAMzM/7+/v9nu+QBjpAA9hP///////////////////////yH5BAEKAA8ALAAAAAAgACAAAATq8MlJH7k16y3JEQXGjZVXBGBIkKQpoEIqsuVRxHAsr3Rn6zndjuYCCo8F1ahoPCJDG2bTKbTxKNIpVWAbXH03atDZ9ZYKh49zXC0M3l/LKZA+Bthc99uMnd/rLzhBZXtxBH53dGpAKISFZ4mJCIpHjo99kQGTiWmdbgkJe3AGmJKZdwUPem+ghQavHX6bpyABoqyhBK+wh3ezpwGrtwMJurtymsCRwsPGpHK/ysyizhME0dLDo7DWBMqZ017HFQYX36jN4xrl3tnU6hzswMLVPfLLrtw9EvfB28/7KMhzUy9gBnYFDa6DtyECADs=", + ver: "0.3", + color: { + frame: "teal", //"orange" + client: "white", + framecontrast: "white", + text: "black", + windowtitle: "black", + selection: "lightskyblue", + }, + icons: {}, + }; + + //=== Merger Core Framework + //============================================================================================= /** - * merge method the root of all merger framework + * Merge method the root of all merger framework */ if (!Object.prototype.merge) Object.defineProperty(Object.prototype, "merge", { @@ -56,25 +58,329 @@ } }); - var ui = { - app: {}, - w: {}, - menu: {}, - }; - /** - * Toolbar clock logic + * Merger Core */ - function clockTick() { - var now = new Date(), h = now.getHours(), m = now.getMinutes(); - if (h < 10) - h = "0" + h; - if (m < 10) - m = "0" + m; - ui.menu.time.innerText = h + ":" + m; + function MergerCore() { + var apps = {}, initialized = false, selectedApp, dsk, menu, menuToShow, menuCurrent; + + /** Return desktop element */ + function getDesktop() { + if (!dsk) { + dsk = this.mkTag("div"); + dsk.setAttribute("id", "Merger::Desktop"); + dsk.style.merge({ + position: "absolute", + zIndex: 510, + top: 0, + left: 0, + width: "100%", + height: "100%", + fontFamily: "Verdana", + fontSize: "10px", + overflow: "hidden", + backgroundColor: "rgba(128,128,128,0.3)", + }); + dsk.addEventListener("mousemove", function (e) { + if (DragNDrop.dragging()) + DragNDrop.update(e.clientX, e.clientY); + }); + dsk.addEventListener("click", function (e) { + if (menuCurrent) + menuCurrent.close(true); + if (menuToShow) + menuToShow.popup(); + }); + } + return dsk; + } + + /** Return menu element */ + function getMenu() { + if (!menu) { + menu = core.mkTag("div"); + menu.setAttribute("id", "Merger::Menu"); + getDesktop().appendChild(menu); + menu.style.merge({ + position: "absolute", + zIndex: 512, + top: 0, + left: 0, + width: "100%", + height: "21px", + padding: "0px 5px 0px 0px", + backgroundColor: "white", + borderBottom: "1px solid " + sys.color.frame, + boxSizing: "border-box", + }); + menu.sysMenu = merger.ui.menuItem("sysMenu", { + icon: sys.icon, + style: { + float: "left", + padding: "2px 7px 2px 12px", + fontFamily: "Arial", + fontSize: "14px", + lineHeight: "16px", + backgroundColor: sys.color.frame, + color: "white", + }, + onmouseenter: function () { + this.style.backgroundColor = ""; + this.style.color = sys.color.windowtitle; + }, + onmouseleave: function () { + this.style.backgroundColor = sys.color.frame; + this.style.color = sys.color.framecontrast; + }, + parentControl: sys, + }); + menu.client = core.mkTag("div"); + menu.client.style.merge({ + padding: "0 0 0 1px", + float: "left", + fontFamily: "Arial", + fontSize: "14px", + lineHeight: "16px", + }); + menu.time = core.mkTag("div"); + menu.time.style.merge({ + float: "right", + fontFamily: "Arial", + fontSize: "14px", + lineHeight: "16px", + padding: "2px 4px 2px 4px", + color: sys.framecolor, + }); + menu.appendChild(menu.sysMenu); + menu.appendChild(menu.client); + menu.appendChild(menu.time); + menu.style.merge({ + userSelect: "none", + }) + + /** Update clock */ + function clockTick() { + var now = new Date(), h = now.getHours(), m = now.getMinutes(); + if (h < 10) + h = "0" + h; + if (m < 10) + m = "0" + m; + menu.time.innerText = h + ":" + m; + } + + clockTick(); + setInterval(clockTick, 60000); + } + return menu; + } + + /** Open desktop */ + function enterDesktop() { + if (!selectedApp) { + switchApplication(); + } + document.body.appendChild(getDesktop()); + } + + /** Close desktop */ + function leaveDesktop() { + var desktop = getDesktop(); + if (document.body.contains(desktop)) + document.body.removeChild(desktop); + } + + /** Create application */ + function createApplication(id, def) { + if (apps[id]) + throw new Error("Application '" + id + "' already exists"); + var a = new MergerApplication(id), windows = def.windows, menu = def.menu, i; + apps[id] = a; + delete (def.windows); + delete (def.menu); + a.merge(def); + if (windows) + for (i = 0; i < windows.length; i++) + a.addWindow(windows[i]); + if (menu) + for (i = 0; i < menu.length; i++) { + var m = menu[i]; + a.menu[m.getId()] = m; + m.application = m.parentControl = a; + m.style.display = "inline-block"; + m._root = true; + } + if (a.onLoad) + a.onLoad(); + return a; + + } + + /** Switch to application */ + function switchApplication(a) { + var i, m, ax, menu = getMenu(); + if (!a) + if (sys.selectedApp && a == sys.selectedApp) + a = sys.selectedApp; + else + if (Object.keys(apps).length > 0) + a = apps[Object.keys(apps)[0]]; + else return false; + if (typeof a === "string") { + a = app[a] + if (!a) + return false; + } + sys.selectedApp = a; + menu.sysMenu.setIcon(a.icon ? a.icon : sys.icon); + menu.sysMenu.setText(a.title ? a.title : a.id); + menu.sysMenu.items = []; + menu.sysMenu.items.push( + m = merger.ui.menuItem("sys_about", { + icon: core.getHelpIcon(), + text: "About " + a.title, + enabled: a.onAbout, + onClick: function () { + if (a.onAbout) + a.onAbout(); + } + }) + ); + m.parentControl = menu.sysMenu; + menu.sysMenu.items.push(m = menuSeparator("sys_applications_separator")); + m.parentControl = menu.sysMenu; + for (i in apps) { + ax = apps[i]; + menu.sysMenu.items.push( + m = merger.ui.menuItem("sys_app_" + i, { + icon: ax.icon ? ax.icon : sys.icon, + text: ax.title, + _app: ax, + onClick: function () { + switchApplication(this._app); + } + }) + ); + m.parentControl = menu.sysMenu; + } + while (menu.client.lastChild) + menu.client.removeChild(menu.client.lastChild); + for (i in a.menu) + menu.client.appendChild(a.menu[i]); + } + + /** Focus application */ + function focusApplication(app) { + enterDesktop(); + return switchApplication(app); + } + + /** Show menu */ + function showMenu(menu) { + menuToShow = menu; + } + + /** Set menu as current one */ + function setCurrentMenu(menu) { + menuCurrent = menu; + } + + /** Check if menu is marked as current */ + function menu_isCurrent(menu) { + return menuCurrent = menu; + } + + this.merge({ + enterDesktop: enterDesktop, + getDesktop: getDesktop, + leaveDesktop: leaveDesktop, + app: { + create: createApplication, + switch: switchApplication, + focus: focusApplication, + }, + menu: { + showMenu: showMenu, + setCurrent: setCurrentMenu, + isCurrent: menu_isCurrent, + } + }) } - // ---- Tools + /** + * Tool for creating tags + */ + MergerCore.prototype.mkTag = function (tag) { + return document.createElement(tag); + } + + /** + * Tool to merge control definition preserving style + */ + MergerCore.prototype.mkDefinition = function (a, b) { + if (a.style) + b.style = a.style.merge(b.style); + return a.merge(b); + } + + /** + * Create a standard SVG icon + */ + MergerCore.prototype.mkIcon = function (color, text) { + return "data:image/svg+xml;utf8," + text + ""; + } + + /** + * Return current configured help icon + */ + MergerCore.prototype.getHelpIcon = function () { + return sys.icons.help ? sys.icons.help : this.mkIcon(sys.color.frame, '?'); + } + + core = new MergerCore(); + + //=== Merger Application Framework + //============================================================================================= + + /** Merger application base definition */ + function MergerApplication(id, def) { + this.merge({ + _type: "app", + getId: function () { + return id; + }, + title: id, + windows: {}, + menu: {}, + }); + } + + /** Show application */ + MergerApplication.prototype.show = function () { + core.enterDesktop(); + core.app.focus(this.getId()); + if (this.onEnter) + this.onEnter(); + } + + /** Add window to applicaiton */ + MergerApplication.prototype.addWindow = function (win) { + this.windows[win.getId()] = win; + win.application = win.parentControl = this; + win.setAttribute("id", this.getId() + "::" + win.getId()); + if (win.getVisible()) + core.getDesktop().appendChild(win); + } + + /** Remove window from applicaiton */ + MergerApplication.prototype.removeWindow = function (win) { + if (!this.windows[win.getId()]) + return; + delete this.windows[win.getId()]; + core.getDesktop().removeChild(win); + } + + //=== Tools + //============================================================================================= /** * Tool for trigger creation @@ -104,58 +410,11 @@ controller.check(); } - // ---- UI implementation - // ---------------------- - - /** - * Tool for creating tags - */ - function mkTag(tag) { - return document.createElement(tag); - } - - /** - * Tool for injecting CSS rules - */ - function mkCSS(css) { - style = mkTag('style'); - if (style.styleSheet) - style.styleSheet.cssText = css; - else - style.appendChild(document.createTextNode(css)); - document.getElementsByTagName('head')[0].appendChild(style); - } - - /** - * Function to merge control definition preserving style - */ - function mkDefinition(a, b) { - if (a.style) - b.style = a.style.merge(b.style); - return a.merge(b); - } - - /** - * Create a standard SVG icon - */ - function mkIcon(color, text) { - return "data:image/svg+xml;utf8," + text + ""; - } - - /** - * Return current configured help icon - */ - function getHelpIcon() { - return sys.icons.help ? sys.icons.help : mkIcon(sys.color.frame, '?'); - } - /** * Drag'N'Drop system */ - var DragNDrop = new (function () { var item, point; - this.merge({ drag: function (i, x, y) { if (item) @@ -181,95 +440,15 @@ }); })(); - /** - * Open merger desktop. - * The first time finish the basic layout creation - */ - function openDesktop() { - if (!ui.dsk.merger_init) { - ui.dsk.merger_init = true; - ui.dsk.onmousemove = function (e) { - if (DragNDrop.dragging()) - DragNDrop.update(e.clientX, e.clientY); - } - ui.dsk.onclick = function (e) { - if (ui.menu.current) { - ui.menu.current.close(true); - delete (ui.menu.current); - } - if (ui.menu.showMenu) { - ui.menu.showMenu.popup(); - delete (ui.menu.showMenu); - } - } - ui.menu.style.merge({ - position: "absolute", - zIndex: 512, - top: 0, - left: 0, - width: "100%", - height: "21px", - padding: "0px 5px 0px 0px", - backgroundColor: "white", - borderBottom: "1px solid " + sys.color.frame, - boxSizing: "border-box", - }); - ui.menu.sysMenu = merger.ui.menuItem("sysMenu", { - icon: sys.icon, - style: { - float: "left", - padding: "2px 7px 2px 12px", - fontFamily: "Arial", - fontSize: "14px", - lineHeight: "16px", - backgroundColor: sys.color.frame, - color: "white", - }, - onmouseenter: function () { - this.style.backgroundColor = ""; - this.style.color = sys.color.windowtitle; - }, - onmouseleave: function () { - this.style.backgroundColor = sys.color.frame; - this.style.color = sys.color.framecontrast; - }, - parentControl: sys, - }); - ui.menu.client = mkTag("div"); - ui.menu.client.style.merge({ - padding: "0 0 0 1px", - float: "left", - fontFamily: "Arial", - fontSize: "14px", - lineHeight: "16px", - }); - ui.menu.time = mkTag("div"); - ui.menu.time.style.merge({ - float: "right", - fontFamily: "Arial", - fontSize: "14px", - lineHeight: "16px", - padding: "2px 4px 2px 4px", - color: sys.framecolor, - }); - ui.menu.appendChild(ui.menu.sysMenu); - ui.menu.appendChild(ui.menu.client); - ui.menu.appendChild(ui.menu.time); - ui.menu.style.merge({ - userSelect: "none", - }) - clockTick(); - setInterval(clockTick, 60000); - } - document.body.appendChild(ui.dsk); - } + //=== Control Tool Kit (MTK) + //============================================================================================= /** * Base control creation */ function control(type, id, def, c) { if (!c) - c = mkTag("div"); + c = core.mkTag("div"); c.setAttribute("merger_type", type); c.setAttribute("id", id); c.setAttribute("name", id); @@ -356,7 +535,7 @@ this[key] = o.d; } } - c.merge(mkDefinition({ + c.merge(core.mkDefinition({ style: { position: "absolute", }, @@ -371,7 +550,7 @@ * Menu Item control creation */ function menuItem(id, def) { - var client, dirty = true, icon, openMark, textElement, m = control("menu", id, mkDefinition({ + var client, dirty = true, icon, openMark, textElement, m = control("menu", id, core.mkDefinition({ style: { position: "", padding: "2px 9px 2px 9px", @@ -385,7 +564,7 @@ setIcon: function (src) { if (src) { if (!icon) { - this.appendChild(icon = mkTag("img")); + this.appendChild(icon = core.mkTag("img")); icon.style.merge({ width: "16px", height: "16px", @@ -399,7 +578,7 @@ }, showMoreMark: function () { if (!openMark) { - this.appendChild(openMark = mkTag("div")); + this.appendChild(openMark = core.mkTag("div")); openMark.style.merge({ float: "right", padding: "0 0 0 5px", @@ -425,7 +604,7 @@ fontSize: "14px", } }); - ui.dsk.appendChild(client); + core.getDesktop().appendChild(client); } var bounds = this.getBoundingClientRect(); if (this.parentControl._type == "menu") @@ -448,14 +627,14 @@ m.showMoreMark(); client.appendChild(m); } - ui.menu.current = this; + core.menu.setCurrent(this); client.show(); }, close: function (all) { if (client) client.hide(); - if (ui.menu.current == this) - ui.menu.current = null; + if (core.menu.isCurrent(this)) + core.menu.setCurrent(null); if (all && this.parentControl._type == "menu") this.parentControl.close(all); }, @@ -469,7 +648,7 @@ }, onclick: function () { if (this.items) - ui.menu.showMenu = this; + core.menu.showMenu(this); else if (this.onClick) this.onClick.apply(this, arguments); } @@ -587,7 +766,7 @@ }); def.content = [wt, wc]; // Window root - w = control("window", id, mkDefinition({ + w = control("window", id, core.mkDefinition({ width: dw + 10, height: dh + 30, setTitle: function (title) { @@ -613,8 +792,6 @@ this.hide(); }, }, def)); - ui.dsk.appendChild(w); - ui.w[id] = w; w.client = w.content.client; w.titlebar = w.content.titlebar; w.content = w.client.content; @@ -625,11 +802,11 @@ * Picture control creation */ function picture(id, def) { - var c = control("picture", id, mkDefinition({ + var c = control("picture", id, core.mkDefinition({ setSrc: function (src) { this.src = src; } - }, def), mkTag("img")); + }, def), core.mkTag("img")); return c; } @@ -637,7 +814,7 @@ * Label control creation */ function label(id, def) { - var c = control("label", id, mkDefinition({ + var c = control("label", id, core.mkDefinition({ setText: function (text) { this.innerText = text; } @@ -651,7 +828,7 @@ * TextBox control creation */ function textbox(id, def) { - var c = control("textbox", id, mkDefinition({ + var c = control("textbox", id, core.mkDefinition({ setText: function (value) { this.value = value; }, @@ -667,7 +844,7 @@ * Button control creation */ function button(id, def) { - var c = control("button", id, mkDefinition({ + var c = control("button", id, core.mkDefinition({ setText: function (text) { this.innerText = text; }, @@ -696,7 +873,7 @@ color: sys.color.framecontrast, }) }, - }, def), mkTag("button")); + }, def), core.mkTag("button")); c.setText(def.text); c.addEventListener("click", function () { if (this.onClick) @@ -715,133 +892,17 @@ } /** - * Component path getter - */ - function get(id) { - return ui.w[id]; - } - - // ---- Kernel implementation - // -------------------------- - - function kSwitchApp(app) { - var i, m, a; - ui.menu.sysMenu.setIcon(app.icon ? app.icon : sys.icon); - ui.menu.sysMenu.setText(app.title ? app.title : app.id); - ui.menu.sysMenu.items = []; - if (app.onAbout) { - ui.menu.sysMenu.items.push( - m = merger.ui.menuItem("sys_about" + i, { - icon: getHelpIcon(), - text: "About " + app.title, - onClick: function () { - app.onAbout(); - } - }) - ); - m.parentControl = ui.menu.sysMenu; - ui.menu.sysMenu.items.push(m = menuSeparator("sys_sep1")); - m.parentControl = ui.menu.sysMenu; - } - for (i in ui.app) { - a = ui.app[i]; - ui.menu.sysMenu.items.push( - m = merger.ui.menuItem("sys_app_" + i, { - icon: a.icon ? a.icon : sys.icon, - text: a.title, - _app: a, - onClick: function () { - kSwitchApp(this._app); - } - }) - ); - m.parentControl = ui.menu.sysMenu; - } - while (ui.menu.client.lastChild) - ui.menu.client.removeChild(ui.menu.client.lastChild); - for (i in app.menu) - ui.menu.client.appendChild(app.menu[i]); - } - - /** - * Application creation - */ - function app(id, def) { - if (ui.app[id]) - throw new Error("Application '" + id + "' already exists"); - var a = { - _type: "app", - getId: function () { - return id; - }, - title: id, - windows: {}, - menu: {}, - onLoad: function () { - - }, - show: function () { - openDesktop(); - if (this.mainWindow) - this.mainWindow.show(); - }, - focus: function () { - this.show(); - kSwitchApp(this); - if (this.mainWindow) - this.mainWindow.focus(); - if (this.onEnter) - this.onEnter(); - } - }, windows = def.windows, menu = def.menu, i; - ui.app[id] = a; - delete (def.windows); - delete (def.menu); - a.merge(def); - if (windows) - for (i = 0; i < windows.length; i++) { - var win = windows[i]; - a.windows[win.getId()] = win; - win.application = win.parentControl = a; - } - if (menu) - for (i = 0; i < menu.length; i++) { - var m = menu[i]; - a.menu[m.getId()] = m; - m.application = m.parentControl = a; - m.style.display = "inline-block"; - m._root = true; - } - // Drop MainWindow feature - if (a.mainWindow) - a.mainWindow = a.windows[a.mainWindow]; - if (a.onLoad) - a.onLoad(); - return a; - } - - function enter() { - openDesktop(); - } - - function leave() { - if (document.body.contains(ui.dsk)) - document.body.removeChild(ui.dsk); - } - - /** - * merger API + * Merger API */ // -- Kernel this.merge({ - app: app, - enter: enter, - leave: leave, + app: core.app.create, + enter: core.enterDesktop, + leave: core.leaveDesktop, version: sys.ver, // -- UI ui: { window: window, - get: get, list: list, label: label, textbox: textbox, @@ -851,37 +912,13 @@ menuSeparator: menuSeparator, }, media: { - createIcon: mkIcon, + createIcon: core.mkIcon, }, conf: { color: sys.color, icon: sys.icons, } }); - - /** - * Initializes merger subsystem - */ - function kInit() { - ui.dsk = mkTag("div"); - ui.dsk.id = "Merger::Desktop"; - ui.dsk.style.merge({ - position: "absolute", - zIndex: 510, - top: 0, - left: 0, - width: "100%", - height: "100%", - fontFamily: "Verdana", - fontSize: "10px", - overflow: "hidden", - backgroundColor: "rgba(128,128,128,0.3)", - }); - ui.menu = mkTag("div"); - ui.dsk.appendChild(ui.menu); - } - - kInit(); } /** @@ -889,5 +926,4 @@ */ merger.app("merger", { title: "Merger Sample Application (Kill)" - }); diff --git a/WebInquirer.html b/WebInquirer.html index 66f04f3..f1b54ec 100644 --- a/WebInquirer.html +++ b/WebInquirer.html @@ -34,25 +34,28 @@ rimg.style.display = isiz === 0 ? "none" : ""; } -
-
-
-

-
-
-
-
- -

- +
+
+

+
+

+

+
+
+
+
+ +

+ \ No newline at end of file