diff --git a/frame.js b/frame.js index 062a369e..17c17924 100644 --- a/frame.js +++ b/frame.js @@ -44,9 +44,13 @@ Volcanos(chat.ONENGINE, {_init: function(can, meta, list, cb, target) { can.requ if (cmds[0] == ctx.ACTION && cmds[1] == ice.RUN) { var p = can.onengine.plugin(can, cmds[2]) if (p) { return can.core.CallFunc(p, {can: p.can||panel, msg: msg, arg: cmds.slice(3), cmds: cmds.slice(3), cb: cb}), true } } - var p = can.onengine.plugin(can, cmds[0]), n = 1; if (p) { if (p.meta && p.meta[cmds[1]] && cmds[0] == ctx.ACTION) { n = 3 } else if (p.meta && p.meta[cmds[0]]) { n = 2 } - return can.core.CallFunc(p, {can: p.can||panel, sub: msg._can, msg: msg, arg: cmds.slice(n), cmds: cmds.slice(n), cb: cb}), true - } return false + var p = can.onengine.plugin(can, cmds[0]), n = 1; if (!p) { return false } + var func = p, _can = p.can||panel, _sup = _can + if (p.meta && p.meta[cmds[2]] && cmds[1] == ctx.ACTION) { + n = 3, func = p.meta[cmds[2]], _can = msg._can + } else if (p.meta && p.meta[cmds[1]]) { + n = 2, func = p.meta[cmds[2]], _can = msg._can + } return can.core.CallFunc(func, {sup: _sup, can: _can, sub: msg._can, msg: msg, arg: cmds.slice(n), cmds: cmds.slice(n), cb: cb}), true }, plugin: shy(function(can, name, command) { var _name = can.base.trimPrefix(name, "can.") if (can.base.isUndefined(name) || !can.base.isString(name) || name == _name) { return } @@ -184,7 +188,11 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { }, _output0: function(can, meta, event, cmds, cb, silent) { var msg = can.request(event); if (msg.RunAction(event, can, cmds)) { return } if (msg.Option(ice.MSG_HANDLE) != ice.TRUE && cmds && cmds[0] == ctx.ACTION && meta.feature[cmds[1]]) { var msg = can.request(event, {action: cmds[1]}) - if (can.base.isFunc(meta.feature[cmds[1]])) { return meta.feature[cmds[1]](can, msg, cmds.slice(2)) } + var action = meta.feature[cmds[1]]; if (can.base.isFunc(action)) { + return action.list && action.list.length > 0? can.user.input(event, can, action.list, function(data) { + can.core.CallFunc(action, {can: can, msg: can.request(event, data), arg: cmds.slice(2)}) + }): can.core.CallFunc(action, {can: can, msg: can.request(event), arg: cmds.slice(2)}) + } return can.user.input(event, can, meta.feature[cmds[1]], function(args) { can.Update(can.request(event, {_handle: ice.TRUE}, can.Option()), cmds.slice(0, 2).concat(args), cb) }) } return can.onengine._plugin(event, can, msg, can, cmds, cb) || can.run(event, cmds, cb||function(msg) { if (silent) { return } var _can = can._fields? can.sup: can @@ -307,7 +315,7 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { input: function(can, item, value, target, style) { if ([html.BR, html.HR].indexOf(item.type) > -1) { return can.page.Append(can, target, [item]) } var icon = [] var input = can.page.input(can, can.base.Copy({className: "", type: "", name: ""}, item), value); input.title = can.Conf(can.core.Keys(ctx.FEATURE, chat.TITLE, item.name))||"" - if (item.type == html.SELECT && item.value) { input._init = function(target) { target.value = value||item.value } } + if (item.type == html.SELECT && (value || item.value)) { input._init = function(target) { target.value = value||item.value } } if (item.type == html.TEXT) { input.onkeydown = item.onkeydown||function(event) { can.onkeymap.input(event, can), can.onkeymap.selectOutput(event, can), event.key == lang.ENTER && can.onkeymap.prevent(event) }, icon.push({text: can.page.unicode.delete, className: "icon delete", onclick: function(event) { @@ -406,10 +414,10 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { sub._index = value.index||meta.index, can.base.isFunc(cb) && cb(sub, meta, skip) }, target||can._output, field) }, - _float: function(can, index, args) { + _float: function(can, index, args, cb) { can.onappend.plugin(can, {index: index, args: args, mode: chat.FLOAT}, function(sub) { can.getActionSize(function(left, top, width, height) { sub.onimport.size(sub, sub.ConfHeight(height/2), sub.ConfWidth(width), true) - can.onmotion.move(can, sub._target, {left: left||0, top: (top||0)+height/4}) + can.onmotion.move(can, sub._target, {left: left||0, top: (top||0)+height/4}), can.base.isFunc(cb) && cb(sub) }), sub.onaction.close = function() { can.page.Remove(can, sub._target) } }, can._root._target) }, diff --git a/index.css b/index.css index e2baca31..75325a98 100644 --- a/index.css +++ b/index.css @@ -139,9 +139,9 @@ div.tabs>div:hover span.icon { visibility:visible; } div.tabs>div.select span.icon { visibility:visible; } div.code { position:sticky; left:0; } div.plug { font-style:italic; } -form.option>div.item { position:relative; } -form.option>div.item>span.icon { font-size:20px; position:absolute; top:2px; right:10px; visibility:hidden; } -form.option>div.item:hover>span.icon { visibility:visible; } +div.item.text { position:relative; } +div.item.text>span.icon.delete { font-size:20px; position:absolute; top:2px; right:10px; visibility:hidden; } +div.item.text:hover>span.icon.delete { visibility:visible; } form.option>div.icon { font-size:26px; margin-right:5px; display:none; } form.option>div.icon:hover { background-color:white; } fieldset.story>form.option>div.icon { display:block; } diff --git a/panel/footer.css b/panel/footer.css index 771d0873..befa8410 100644 --- a/panel/footer.css +++ b/panel/footer.css @@ -1,18 +1,14 @@ -fieldset.Footer { font-size:1.1rem; padding:0 5px; clear:both; } -fieldset.Footer>div.output { overflow:auto; } +fieldset.Footer>div.output { font-size:1.1rem; padding:0 5px; } fieldset.Footer>div.output div { padding:5px; height:31px; cursor:pointer; } fieldset.Footer>div.output div:hover { background-color:#2e515f; } fieldset.Footer>div.output div.title { float:left; } fieldset.Footer>div.output div.state { font-family:monospace; float:right; } fieldset.Footer>div.output div.state label { font-size:12px; } fieldset.Footer>div.output div.toast { background-color:darkcyan; float:right; } -fieldset.Footer>div.output div.cmd { padding:0; float:left; position:relative; } -fieldset.Footer>div.output div.cmd span.icon { position:absolute; top:5px; right:10px; } +fieldset.Footer>div.output div.cmd { padding:0; float:left; } fieldset.Footer>div.output div.cmd:hover input[name=cmd] { width:320px; transition:all 0.5s; } fieldset.Footer>div.output input[name=cmd] { margin-left:40px; width:120px; transition:all 1s; } fieldset.Footer>div.output input[name=cmd]:focus { width:320px; transition:all 0.5s; } -fieldset.story.nlog.float tbody tr.warn { color:yellow; } -fieldset.story.nlog.float tbody tr.error { color:red; } .picker { box-shadow:4px 4px 20px 4px #626bd0; } div.view span.keyword { color:#5cadd4; } diff --git a/panel/footer.js b/panel/footer.js index 87a8716a..b1605bc9 100644 --- a/panel/footer.js +++ b/panel/footer.js @@ -1,83 +1,63 @@ (function() { var NTIP = "ntip", NCMD = "ncmd", NLOG = "nlog" -Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { - can.onimport._title(can, msg, target) - can.onimport._state(can, msg, target) - can.onimport._toast(can, msg, target) - can.onimport._command(can, msg, target) +Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.ui = {}, can.db = {} + can.onimport._title(can, msg, target), can.onimport._state(can, msg, target), can.onimport._toast(can, msg, target), can.onimport._command(can, msg, target) }, _title: function(can, msg, target) { can.user.isMobile || can.core.List(msg.result, function(item) { can.page.Append(can, target, [{view: [chat.TITLE, html.DIV, item], title: "联系站长"}]) }) }, _state: function(can, msg, target) { can.core.List(can.base.Obj(can.Conf(chat.STATE)||msg.Option(chat.STATE), [NTIP, NCMD, NLOG]).reverse(), function(item) { - can.page.Append(can, target, [{view: [[chat.STATE], html.DIV, can.Conf(item)], list: [ + can.page.Append(can, target, [{view: [chat.STATE, html.DIV, can.Conf(item)], list: [ {text: [item, html.LABEL]}, {text: [": ", html.LABEL]}, {text: [can.Conf(item)||"", html.SPAN, item]}, ], onclick: function(event) { can.onexport[item](can) }}]) }) }, _toast: function(can, msg, target) { can.toast = can.page.Append(can, target, [{view: chat.TOAST, onclick: function(event) { can.onexport[NTIP](can) }}])._target }, _command: function(can, msg, target) { can.onappend.input(can, {type: html.TEXT, name: ice.CMD, onkeydown: function(event) { can.onkeymap.input(event, can); if (event.key != lang.ENTER) { return } switch (event.target.value) { - case cli.CLOSE: can.cli && can.cli.close(); break - case cli.CLEAR: can.cli && can.cli.close(); break - default: - can.runAction(event, ice.RUN, can.core.Split(event.target.value, ice.SP), function(msg) { can.cli && can.cli.close && can.cli.close(), can["cli"] = {}; var ui = can.onexport.float(can, msg, "cli") - can.getActionSize(function(left) { can.page.style(can, ui._target, html.LEFT, left+10, html.RIGHT, "", html.BOTTOM, can.onexport.height(can)) }) + case cli.CLEAR: + case cli.CLOSE: can.ui.cli && can.ui.cli.close(); break + default: can.ui.cli && can.ui.cli.close(); var list = can.core.Split(event.target.value, ice.SP) + can.onexport._float(can, "cli", list[0], list.slice(1), function(sub) { can.ui.cli.close = function() { can.page.Remove(can, sub._target), delete(can.ui.cli) } + can.getActionSize(function(left) { can.page.style(can, sub._target, html.LEFT, left, html.RIGHT, "") }) }) } }}, "", target, [chat.TITLE]) }, + _data: function(can, name, item) { can[name] = can[name]||can.request(), can[name].Push(item), can.onimport.count(can, name) }, count: function(can, name) { can.page.Select(can, can._output, can.core.Keys(html.SPAN, name), function(item) { item.innerHTML = can.Conf(name, parseInt(can.Conf(name)||"0")+1+"")+"" }) }, toast: function(can, msg, title, content, fileline, time) { can.onimport._data(can, NTIP, {time: time, fileline: fileline, title: title, content: content}), can.page.Modify(can, can.toast, [time, title, content].join(ice.SP)) }, ncmd: function(can, msg, _follow, _cmds) { can.onimport._data(can, NCMD, {time: can.base.Time(), follow: _follow, cmds: _cmds}), can.onimport.nlog(can, NLOG) }, - nlog: function(can, name) { can.page.Select(can, can._output, can.core.Keys(html.SPAN, name), function(item) { item.innerHTML = can.misc._list.length }) }, - _data: function(can, name, item) { can[name] = can[name]||can.request(), can[name].Push(item), can.onimport.count(can, name) }, + nlog: function(can, name) { can.onimport.count(can, name) }, }) Volcanos(chat.ONACTION, {_init: function(can) { if (can.user.isExtension || can.user.mod.isPod) { can.onmotion.hidden(can) } }, onsize: function(can) { can.ConfHeight(can._target.offsetHeight), can.ConfWidth(can._target.offsetWidth) }, onlogin: function(can, msg) { can.run({}, [], function(msg) { can.onmotion.clear(can), can.onimport._init(can, msg, can._output) }) }, ontoast: function(can, msg) { can.core.CallFunc(can.onimport.toast, {can: can, msg: msg}) }, onremote: function(can, msg) { can.core.CallFunc(can.onimport.ncmd, {can: can, msg: msg}) }, + onlayout: function(can, layout) { can.onmotion.toggle(can, can._target, !layout || layout == html.TABS) }, onaction_cmd: function(can) { can.onappend.style(can, html.HIDE) }, - onlayout: function(can, layout) { can.onmotion.toggle(can, can._target, !layout || layout == "tabs") }, oncommand_focus: function(can) { can.page.Select(can, can._output, ["div.cmd", html.INPUT], function(target) { can.onmotion.focus(can, target) }) }, }) Volcanos(chat.ONEXPORT, {height: function(can) { return can._target.offsetHeight }, - float: function(can, msg, name, cb) { if (!can[name]) { return } if (can[name]._target) { return can[name]._target.close() } var ui = can.onappend.field(can, chat.STORY, {name: name}, can._root._target); can[name]._target = ui - can.onappend.style(can, html.FLOAT, ui._target) - ui.close = function() { can.page.Remove(can, ui._target), delete(can[name]._target) }, ui.refresh = function() { ui.close(), can.toast.click() } - can.getActionSize(function(height, width) { can.page.style(can, ui._target, html.RIGHT, 0, html.BOTTOM, can.onexport.height(can)) - can.page.style(can, ui.output, html.MAX_HEIGHT, height-html.ACTION_HEIGHT, html.MAX_WIDTH, width) - }) - can.onappend._action(can, [cli.CLOSE, web.REFRESH, {input: html.TEXT, placeholder: web.FILTER, onkeydown: function(event) { can.onkeymap.input(event, can) - event.key == lang.ENTER && (can.onmotion.tableFilter(can, ui.output, event.target.value), can.onmotion.focus(can, event.target)) - }}], ui.action, ui) - msg && can.onappend.table(can, msg, function(value, key, index, line, list) { - return {text: [value, html.TD], onclick: function(event) { can.base.isFunc(cb) && cb(value, key, index, line, list) }} - }, ui.output), msg && can.onappend.board(can, msg.Result(), ui.output); return ui - }, - ntip: function(can) { can.onexport.float(can, can[NTIP], NTIP, function(value, key, index, line) { can.onappend._float(can, web.CODE_INNER, [ice.USR_VOLCANOS].concat(line.fileline.split(ice.DF))) }) }, - nlog: function(can) { can.onappend._float(can, "can.debug") }, - ncmd: function(can) { can.onexport.float(can, can[NCMD], NCMD, function(value, key, index, line) { - var cmds = can.base.Obj(line.cmds); switch (line.follow) { - case "can.Action": cmds = cmds.slice(2); break - case "can.Search": cmds = cmds.slice(2); break - case "can.Footer": cmds = cmds.slice(2); break - default: return - } - switch (cmds[0]) { - case web.WIKI_WORD: cmds = cmds.slice(5); break - } - can.onappend._float(can, cmds[0], cmds[1] != ctx.ACTION? cmds.slice(1): []) + ntip: function(can) { can.onexport._float(can, NTIP, "can.toast") }, + ncmd: function(can) { can.onexport._float(can, NCMD, "can.debug", [chat.ONREMOTE]) }, + nlog: function(can) { can.onexport._float(can, NLOG, "can.debug") }, + _float: function(can, name, index, args, cb) { can.ui[name]? (can.ui[name].onaction.close(), delete(can.ui[name])): can.onappend._float(can, index, args||[], function(sub) { can.ui[name] = sub + can.page.style(can, sub._target, {left: "", top: "", right: 0, bottom: can.onexport.height(can)}), can.base.isFunc(cb) && cb(sub) }) }, }) Volcanos(chat.ONPLUGIN, { - alert: shy("提示", [wiki.CONTENT], function(can, msg, arg) { arg && arg.length > 0 && can.user.alert(arg[0]) }), - toast: shy("提示", [wiki.CONTENT, wiki.TITLE], function(can, msg, arg) { arg && arg.length > 0 && can.user.toast(can, arg[0], arg[1]), msg.Copy(can[NTIP]), msg.StatusTimeCount() }), + alert: shy("提示", [wiki.CONTENT], function(can, arg) { arg.length > 0 && can.user.alert(arg[0]) }), + toast: shy("提示", { + inputs: shy(function(can, sup, msg, arg) { var list = {}; can.core.List(sup[NTIP][arg[0]], function(item) { if (arg.length > 1 && item.indexOf(arg[1]) == -1) { return } + if (list[item]) { return } list[item] = true; msg.Push(arg[0], item) + }) }), + create: shy([wiki.CONTENT, wiki.TITLE], function(can, content, title) { can.user.toast(can, content, title) }), + }, [html.FILTER, ice.LIST, mdb.CREATE], function(can, msg) { msg.Copy(can[NTIP]), msg.StatusTimeCount() }), debug: shy("网页日志", { "prune": shy("清空", function(can) { while(can.misc._list.pop()) {} can.onmotion.clear(can) }), "w3schools": shy("教程", function(can) { can.user.open("https://www.w3schools.com/colors/colors_names.asp") }), "mozilla": shy("文档", function(can) { can.user.open("https://developer.mozilla.org/en-US/") }), "w3": shy("标准", function(can) { can.user.open("https://www.w3.org/TR/?tag=css") }), }, ["type:select=log,info,warn,error,debug,wss,onremote", "filter", "list", "prune", "w3schools", "mozilla", "w3"], function(can, msg, arg) { can.onmotion.delay(can, function() { var _can = can, can = msg._can - var stat = {} - var ui = can.page.Appends(can, can._output, [{type: html.TABLE, className: html.CONTENT, list: [{type: html.TR, list: [ + var stat = {}; var ui = can.page.Appends(can, can._output, [{type: html.TABLE, className: html.CONTENT, list: [{type: html.TR, list: [ {type: html.TH, inner: mdb.TEXT}, ]}].concat(can.core.List(can.misc._list, function(list) { stat[list[2]] = ((stat[list[2]]||0)+1); return (!arg || !arg[0] || arg[0] == "log" || arg[0] == list[2]) && {type: html.TR, list: [ - {type: html.TD, list: can.core.List(list.slice(0), function(item, index) { var vimer + {type: html.TD, list: can.core.List(list, function(item, index) { var vimer if (index == 1) { var _ls = /(https*:\/\/[^/]+)\/*([^:]+):([0-9]+):([0-9]+)/.exec(list[1]) return {view: [html.ITEM, html.SPAN], list: [{text: ice.SP+can.page.unicode.close+ice.SP}, {text: [(_ls[1] == location.origin? _ls[2].split("?")[0]+ice.DF+_ls[3]: item).split("?")[0], html.SPAN, nfs.PATH], onclick: function(event) { if (can.onexport.record(can, list[1], mdb.LINK, {time: list[0], link: list[1], type: list[2], path: ice.USR_VOLCANOS, file: _ls[2].split("?")[0], line: _ls[3]})) { return } @@ -103,14 +83,12 @@ Volcanos(chat.ONPLUGIN, { localStorage: shy("本地存储", [mdb.NAME, mdb.VALUE, ice.LIST, ice.BACK], function(can, msg, arg) { if (arg.length == 0) { can.core.Item(localStorage, function(name, value) { if (can.base.isFunc(value) || name == "length") { return } msg.Push(mdb.NAME, name).Push(mdb.VALUE, value) - }); return msg.StatusTimeCount() } - if (arg.length > 1) { localStorage.setItem(arg[0], arg[1]) } msg.Echo(localStorage.getItem(arg[0])) + }); return msg.StatusTimeCount() } if (arg.length > 1) { localStorage.setItem(arg[0], arg[1]) } msg.Echo(localStorage.getItem(arg[0])) }), sessionStorage: shy("会话存储", [mdb.NAME, mdb.VALUE, ice.LIST, ice.BACK], function(can, msg, arg) { if (arg.length == 0) { can.core.Item(sessionStorage, function(name, value) { if (can.base.isFunc(value) || name == "length") { return } msg.Push(mdb.NAME, name).Push(mdb.VALUE, value) - }); return msg.StatusTimeCount() } - if (arg.length > 1) { sessionStorage.setItem(arg[0], arg[1]) } msg.Echo(sessionStorage.getItem(arg[0])) + }); return msg.StatusTimeCount() } if (arg.length > 1) { sessionStorage.setItem(arg[0], arg[1]) } msg.Echo(sessionStorage.getItem(arg[0])) }), data: shy("网页数据", [mdb.KEY], function(can, msg, arg) { can.onmotion.delay(can, function() { var can = msg._can if (can.Option(mdb.KEY)) { @@ -131,8 +109,7 @@ Volcanos(chat.ONPLUGIN, { list.push(p.tagName.toLowerCase()+(p.className? ice.PT+p.className.replaceAll(ice.SP, ice.PT).replace(".picker", ""): "")) } can.Option(mdb.KEY, list.reverse().join(ice.SP+ice.GT+ice.SP)) }), - ], true)]) - can.onmotion.delay(can, function() { can.page.Select(can, ui._target, "div.item.head,div.item.body", function(target) { target.click() }) }) + ], true)]); can.onmotion.delay(can, function() { can.page.Select(can, ui._target, "div.item.head,div.item.body", function(target) { target.click() }) }) } }) }), })