diff --git a/const.js b/const.js index 40813724..42d99726 100644 --- a/const.js +++ b/const.js @@ -259,6 +259,7 @@ var code = { } var wiki = { DRAW: "draw", WORD: "word", PORTAL: "portal", + FEEL: "feel", TITLE: "title", BRIEF: "brief", REFER: "refer", SPARK: "spark", SHELL: "shell", ORDER: "order", TABLE: "table", CHART: "chart", IMAGE: "image", VIDEO: "video", FIELD: "field", LOCAL: "local", PARSE: "parse", @@ -467,6 +468,8 @@ var icon = { expire: "bi bi-clock-history", name: "bi bi-sort-alpha-down", + time: "bi bi-clock-history", + size: "bi bi-calculator", sess: "bi bi-telephone-forward", path: "bi bi-folder2", file: "bi bi-file-earmark-text", line: "bi bi-sort-numeric-down", start: "bi bi-play-circle", stop: "bi bi-stop-circle", diff --git a/frame.js b/frame.js index 64adb09d..3ca5c296 100644 --- a/frame.js +++ b/frame.js @@ -266,11 +266,12 @@ Volcanos(chat.ONAPPEND, { }}) } can.core.List(list, function(item) { + item.value = can.sup && can.sup.onexport.session && can.sup.onexport.session(can.sup, "action:"+item.name||item[0]) || item.value can.base.isUndefined(item) || can.onappend.input(can, item == ""? /* 1.空白 */ {type: html.BR}: can.base.isString(item)? /* 2.按键 */ {type: html.BUTTON, name: item, value: can.user.trans(can, item, meta._trans), onclick: function(event) { run(event, item) - }}: item.length > 0? /* 3.列表 */ {type: html.SELECT, name: item[0], values: item.slice(1), onchange: function(event) { can.misc.Event(event, can, function(msg) { - var button = event.target.value; can.onexport.session && can.onexport.session(can, "action:"+item[0], button) + }}: item.length > 0? /* 3.列表 */ {type: html.SELECT, name: item[0], value: item.value, values: item.slice(1), onchange: function(event) { can.misc.Event(event, can, function(msg) { + var button = event.target.value; can.onexport.session && can.onexport.session(can, "action:"+(item.name||item[0]), button) can.onaction._select && can.onaction._select(event, can, item[0], button) meta[item[0]]? can.core.CallFunc(meta[item[0]], [event, can, item[0], button]): meta[button]? can.core.CallFunc(meta[button], [event, can, button]): can.Action(item[0], button) @@ -1150,7 +1151,12 @@ Volcanos(chat.ONMOTION, { can.user.toast(can, "filter out "+count+" lines") }, 300) }, - cacheClear: function(can, key) { delete(can._cache_data[key]) + cacheClear: function(can, key) { + if (!key) { + delete(can._cache_data), delete(can._output._cache) + return + } + delete(can._cache_data[key]) can.core.List(arguments, function(target, index) { index > 1 && target && target._cache && delete(target._cache[key]) }) }, cache: function(can, next) { var list = can.base.getValid(can.base.Obj(can.core.List(arguments).slice(2)), [can._output]) diff --git a/index.css b/index.css index de411e52..4e8e279c 100644 --- a/index.css +++ b/index.css @@ -232,7 +232,7 @@ div.project div.item.filter>input { padding:0 25px; width:100% !important; } div.project div.item.search { padding:0; width:100%; } div.project div.item.search>input { padding:0 25px; width:100%; } div.project div.item img { height:var(--action-height); width:var(--action-height); } -div.project div.item img { margin:0; } +div.project div.item img { margin:0; flex-shrink:0; } div.project div.item>div.name { padding:0 var(--input-padding); } div.project div.item>div.icon { position:absolute; right:var(--input-padding); } div.project div.item>div.icon:hover { background-color:var(--hover-bg-color); } @@ -992,7 +992,7 @@ fieldset.Action>div.output>fieldset.ssh.cloud.profile:hover { box-shadow:none; } fieldset.Action>div.output>fieldset.ssh.cloud.profile>div.output { background-color:transparent; } fieldset.Action:not(.horizon):not(.grid)>fieldset.plugin>form.option>div.item.text.path>input { width:var(--project-width); } body:not(.debug) fieldset.plugin.can._notfound { display:none; } -body:not(.cmd) fieldset.Action>div.output>fieldset.plugin>legend { border-top:var(--item-notice); border-top-left-radius:0; margin-right:var(--legend-margin); } +body:not(.cmd) fieldset.Action>div.output>fieldset.plugin>legend { border-top:var(--box-notice3); border-top-left-radius:0; margin-right:var(--legend-margin); } body:not(.cmd) fieldset.Action>div.output>fieldset.plugin>legend:not(:hover) { background-color:var(--output-bg-color); } body:not(.dark) fieldset.draw.trends div.output svg { background-color:#1b5b738c; } body.width6 fieldset.plugin.word>form.option>div.item.text>input { width:var(--project-width); } diff --git a/lib/base.js b/lib/base.js index de1e57a2..009eb2bb 100644 --- a/lib/base.js +++ b/lib/base.js @@ -35,7 +35,9 @@ Volcanos("base", { } return to === from }, - Ext: function(path) { return path.split("?")[0].split(nfs.PS).pop().split(nfs.PT).pop().toLowerCase() }, + Ext: function(path) { + return (path||"").split("?")[0].split("#")[0].split("/").pop().split(".").pop().toLowerCase() + }, Dir: function(path) { return path.endsWith(nfs.PS)? path: path.slice(0, path.lastIndexOf(nfs.PS)+1) }, Path: function(path) { var res = "", arg = arguments; for (var i = 0; i < arg.length; i++) { if (!arg[i]) { continue } diff --git a/lib/misc.js b/lib/misc.js index 64433e80..d45bc5ad 100644 --- a/lib/misc.js +++ b/lib/misc.js @@ -73,6 +73,28 @@ Volcanos("misc", { res._option && (msg._option = res._option) && res._option.forEach(function(key) { res[key] && (msg[key] = res[key]) }) return msg }, + Sort: function(key, swap) { var n = msg.Length() + key = key||msg.append[0], swap = swap||function(i, j) { return msg[key][i] > msg[key][j] } + switch (swap) { + case "str": swap = function(i, j) { return msg[key][i] > msg[key][j] }; break + case "str_r": swap = function(i, j) { return msg[key][i] < msg[key][j] }; break + case "int": swap = function(i, j) { return can.base.ParseSize(msg[key][i]) > can.base.ParseSize(msg[key][j]) }; break + case "int_r": swap = function(i, j) { return can.base.ParseSize(msg[key][i]) < can.base.ParseSize(msg[key][j]) }; break + } + for (var i = 0; i < n-1; i++) { + for (var j = i+1; j < n; j++) { var _swap = swap(i, j) + if (_swap === true) { + can.core.List(msg.append, function(k) { + var temp = msg[k][i]; msg[k][i] = msg[k][j], msg[k][j] = temp + }) + } else if (_swap === false) { + continue + } else { + + } + } + } + }, Push: function(key, value, detail) { if (can.base.isObject(key)) { can.core.List(value||msg.append||can.base.Obj(msg.Option(ice.MSG_FIELDS))||can.core.Item(key), function(item) { detail? msg.Push(mdb.KEY, item).Push(mdb.VALUE, key[item]||""): msg.Push(item, key[item]||"") @@ -278,6 +300,9 @@ Volcanos("misc", { return dir+file+(ext? nfs.PT+ext: "") }, isDebug: function(can) { return can.misc.Search(can, log.DEBUG) == ice.TRUE }, + isImage: function(can, path) { return can.base.isIn(can.base.Ext(path), "png", "jpg", "jpeg") }, + isVideo: function(can, path) { return can.base.isIn(can.base.Ext(path), "mp4", "m4v", "mov", "webm") }, + isAudio: function(can, path) { return can.base.isIn(can.base.Ext(path), "mp3") }, Search: function(can, key, value) { var args = this.ParseURL(can, location.href) if (can.base.isUndefined(key)) { return args } else if (can.base.isObject(key)) { can.core.Item(key, function(k, v) { v === ""? delete(args[k]): (args[k] = v) }) @@ -292,10 +317,9 @@ Volcanos("misc", { SearchHash: function(can) { var hash = location.hash if (arguments.length > 1) { hash = can.core.List(arguments, function(item) { - if (can.base.isArray(item)) { - return item.join(nfs.DF) - } - return can.base.replaceAll(item, ":", "%3A") }).slice(1).join(nfs.DF) + if (can.base.isArray(item)) { return item.join(nfs.DF) } + return can.base.replaceAll(item, ":", "%3A") + }).slice(1).join(nfs.DF) if (can.isCmdMode() || can._name == "River" || can._name == "Action") { location.hash = hash } } return can.core.List(can.core.Split(can.base.trimPrefix(location.hash, "#"), nfs.DF)||[], function(item) { return decodeURIComponent(item) }) @@ -313,10 +337,6 @@ Volcanos("misc", { } can.base.isUndefined(value) || set(key, value) var val = (new RegExp(key+"=([^;]*);?")).exec(document.cookie); return val && val.length > 1? val[1]: "" }, - localStorage: function(can, key, value) { - if (can.base.isUndefined(key)) { var res = {}; can.core.Item(localStorage, function(name, value) { can.base.isFunc(value) || name == "length" || (res[name] = value) }); return res } - if (!can.base.isUndefined(value)) { if (value === "") { return localStorage.removeItem(key) } localStorage.setItem(key, value) } return can.base.Obj(localStorage.getItem(key)) - }, sessionStorage: function(can, key, value) { if (can.base.isUndefined(key)) { var res = {}; can.core.Item(sessionStorage, function(name, value) { can.base.isFunc(value) || name == "length" || (res[name] = value) }); return res } if (can.base.isArray(key)) { key = key.join(":") } @@ -324,17 +344,17 @@ Volcanos("misc", { if (value === "") { return sessionStorage.removeItem(key) } sessionStorage.setItem(key, value) } return can.base.Obj(sessionStorage.getItem(key))||sessionStorage.getItem(key) }, - Log: function() { - var args = this._args("", arguments) + localStorage: function(can, key, value) { + if (can.base.isUndefined(key)) { var res = {}; can.core.Item(localStorage, function(name, value) { can.base.isFunc(value) || name == "length" || (res[name] = value) }); return res } + if (!can.base.isUndefined(value)) { if (value === "") { return localStorage.removeItem(key) } localStorage.setItem(key, value) } return can.base.Obj(localStorage.getItem(key)) + }, + Log: function() { var args = this._args("", arguments) if (arguments[0].indexOf && arguments[0].indexOf("on") == 0) { args[1] = this.FileLine((arguments[0] == "onremote"? 1: 1)+this._skip) } for (var i in arguments) { var arg = arguments[i]; if (arg && arg.Option && arg.Option("log.caller")) { args[1] = arg.Option("log.caller") } } console.log.apply(console, args), this._signal(args) }, Info: function() { var args = this._args(log.INFO, arguments); console.info.apply(console, args), this._signal(args) }, - Warn: function() { - var args = this._args(log.WARN, arguments); console.warn.apply(console, args), this._signal(args); - // debugger - }, + Warn: function() { var args = this._args(log.WARN, arguments); console.warn.apply(console, args), this._signal(args); }, Error: function() { var args = this._args(log.ERROR, arguments); args.push(lex.NL, this._stacks().slice(1).join(lex.NL)), console.error.apply(console, args), this._signal(args); debugger }, Debug: function() { var args = this._args(log.DEBUG, arguments); args.push(lex.NL, this._stacks().slice(1, 4).join(lex.NL)), console.debug.apply(console, args), this._signal(args) }, Trace: function() { var output = false @@ -355,22 +375,21 @@ Volcanos("misc", { }, _stacks: function(n, s) { var list = ((s||(new Error())).stack||"").split(lex.NL).slice(typeof n == "undefined"? 2: n) for (var i = 0; i < list.length; i++) { var ls = list[i].trim().split(lex.SP) - list[i] = ls.pop().trim(); if (list[i][0] == "(") { list[i] = list[i].slice(1, -1) } - list[i] = " "+list[i]; if (ls.length > 1) { list[i] += " "+ls.pop() } - list[i] = list[i].replace(/\?[^:]+/, "").replace(location.origin, "") - } return list - }, _stack: function() { return ((new Error()).stack||"").split(lex.NL).slice(2) }, - _time: function() { var now = new Date() - var hour = now.getHours(); hour < 10 && (hour = "0"+hour) - var minute = now.getMinutes(); minute < 10 && (minute = "0"+minute) - var second = now.getSeconds(); second < 10 && (second = "0"+second) - var mill = now.getMilliseconds(); mill < 10 && (mill = "00"+mill) || mill < 100 && (mill = "0"+mill) - return [hour, minute, second].join(nfs.DF)+nfs.PT+mill - }, - _args: function(level, arg) { var args = [this._time(), this.FileLine(this._skip+1, 3)].concat(level? [level]: []) - for (var i in arg) { arg[i] != undefined && args.push(arg[i]) } return args - }, - _signal: function(args) { this._list.push(args) }, _list: [], _skip: navigator && navigator.userAgent.indexOf("Chrome") > -1? 3: 3, - }) - - + list[i] = ls.pop().trim() + if (list[i][0] == "(") { list[i] = list[i].slice(1, -1) } // ")" + list[i] = " "+list[i]; if (ls.length > 1) { list[i] += " "+ls.pop() } + list[i] = list[i].replace(/\?[^:]+/, "").replace(location.origin, "") + } return list + }, _stack: function() { return ((new Error()).stack||"").split(lex.NL).slice(2) }, + _time: function() { var now = new Date() + var hour = now.getHours(); hour < 10 && (hour = "0"+hour) + var minute = now.getMinutes(); minute < 10 && (minute = "0"+minute) + var second = now.getSeconds(); second < 10 && (second = "0"+second) + var mill = now.getMilliseconds(); mill < 10 && (mill = "00"+mill) || mill < 100 && (mill = "0"+mill) + return [hour, minute, second].join(nfs.DF)+nfs.PT+mill + }, + _args: function(level, arg) { var args = [this._time(), this.FileLine(this._skip+1, 3)].concat(level? [level]: []) + for (var i in arg) { arg[i] != undefined && args.push(arg[i]) } return args + }, + _signal: function(args) { this._list.push(args) }, _list: [], _skip: navigator && navigator.userAgent.indexOf("Chrome") > -1? 3: 3, +}) diff --git a/lib/page.js b/lib/page.js index 30576e15..5c6a1038 100644 --- a/lib/page.js +++ b/lib/page.js @@ -273,21 +273,22 @@ Volcanos("page", { ], Color: function(text) { if (typeof text != code.STRING) { return "" } text = text.replace(/\\n/g, "
") if (text.indexOf(ice.HTTP) == 0 && text.length > 10) { var ls = text.split(lex.SP); text = ""+decodeURI(ls[0])+""+ls.slice(1).join(lex.SP) } - if (text.indexOf("export ctx_dev=") == 0 && text.length > 10) { return "
"+""+text+""+"
" } - if (text.indexOf("\033\[") == -1) { return text } - text = text.replace(/\033\[41m/g, "") - text = text.replace(/\033\[31m/g, "") - text = text.replace(/\033\[32m/g, "") - text = text.replace(/\033\[33m/g, "") - text = text.replace(/\033\[34m/g, "") - text = text.replace(/\033\[36m/g, "") - text = text.replace(/\033\[37m/g, "") - text = text.replace(/\033\[34;1m/g, "") - text = text.replace(/\033\[37;1m/g, "") - text = text.replace(/\033\[1m/g, "") - text = text.replace(/\033\[0m/g, "") - text = text.replace(/\033\[m/g, "") - return text + if (text.indexOf("export ctx_dev=") == 0 && text.length > 10) { + return "
"+""+text+""+"
" + } if (text.indexOf("\033\[") == -1) { return text } + text = text.replace(/\033\[41m/g, "") + text = text.replace(/\033\[31m/g, "") + text = text.replace(/\033\[32m/g, "") + text = text.replace(/\033\[33m/g, "") + text = text.replace(/\033\[34m/g, "") + text = text.replace(/\033\[36m/g, "") + text = text.replace(/\033\[37m/g, "") + text = text.replace(/\033\[34;1m/g, "") + text = text.replace(/\033\[37;1m/g, "") + text = text.replace(/\033\[1m/g, "") + text = text.replace(/\033\[0m/g, "") + text = text.replace(/\033\[m/g, "") + return text // } }, Keys: function() { var list = []; /* FS SP GT PT */ for (var i = 0; i < arguments.length; i++) { var v = arguments[i]; if (typeof v == code.OBJECT) { for (var j = 0; j < v.length; j++) { if (typeof v[j] == code.OBJECT) { @@ -363,127 +364,134 @@ Volcanos("page", { favor: "\u2606", help: "\u2753", }, - inputs: function(can, list, type) { var _list = []; for (var i = 0; i < list.length; i++) { switch (list[i]) { - case "": _list.push(""); break - case ice.AUTO: - _list.push({type: html.BUTTON, name: ice.LIST}) - _list.push({type: html.BUTTON, name: ice.BACK}) - break - case web.FILTER: - _list.push({type: html.TEXT, name: web.FILTER, icon: icon.search}) - break - case mdb.PAGE: - _list.push({type: html.TEXT, name: mdb.OFFEND, value: can._msg.Option(mdb.OFFEND)}) - _list.push({type: html.TEXT, name: mdb.LIMIT, value: can._msg.Option(mdb.LIMIT), _init: function(target) { - can.onappend.figure(can, {action: "key", run: function(event, cmds, cb) { - var msg = can.request(event) - msg.Push(cmds[1], "10") - msg.Push(cmds[1], "30") - msg.Push(cmds[1], "50") - msg.Push(cmds[1], "100") - cb(msg) - }}, target, function() { can.Update() }) - }}) - _list.push(mdb.NEXT, mdb.PREV) - break - default: - (function() { var item = can.core.SplitInput(list[i], type||html.BUTTON) - if (item.type == html.SELECT) { item._init = function(target) { target.value = item.value||item.values[0], target.onchange = function(event) { can.misc.Event(event, can, function(msg) { - can.run(event) - }) } } } item.action && (function() { item._init = function(target) { - can.onappend.figure(can, item, target, function() { can.Update({}, ) }) - } })() - _list.push(item), type = item.type - })() -} } return _list }, -input: function(can, item, value) { var input = {type: html.INPUT, name: item.name, data: item, style: item.style||{}, dataset: {}, _init: item._init} - item.value == ice.AUTO && (item.value = "", item.action = ice.AUTO), item.action == ice.AUTO && (input.dataset.action = ice.AUTO) - switch (item.type = item.type||html.TEXT) { - case html.SELECT: input.type = html.SELECT, item.className||can.page.ClassList.add(can, item, ctx.ARGS) - item.values = can.base.isString(item.values)? can.core.Split(item.values): item.values - if (!item.values && item.value) { item.values = can.core.Split(item.value), item.value = item.values[0] } - if (item.values.slice(1).indexOf(item.values[0]) > -1) { item.value = item.value||item.values[0], item.values = item.values.slice(1) } - item.value = value||item.value, input.list = item.values.map(function(value) { - return {type: html.OPTION, value: value, inner: can.user.trans(can, value, null, html.VALUE)} - }); break - case html.TEXTAREA: input.type = html.TEXTAREA // no break - case html.USERNAME: // no break - case html.PASSWORD: // no break - case html.TEXT: - case html.FILTER: - item.className||can.page.ClassList.add(can, item, ctx.ARGS), item.name = item.name||item.type, item.value = value||item.value||""; - item.placeholder = item.placeholder||item.name - break - case html.UPLOAD: item.type = html.FILE, input.name = html.UPLOAD; break - case html.BUTTON: item.value = item.value||item.name||mdb.LIST; break - } return input -}, -icons: function(can, name, space) { if (!name) { return } - if (can.base.contains(name, ".ico", ".png", ".jpg")) { return {img: can.misc.Resource(can, (name.indexOf(nfs.PS) == -1? nfs.USR_ICONS: "")+name, space)} } - // if (can.page.unicode[name]) { return {text: [can.page.unicode[name], "", "icon"]} } - if (name == mdb.DELETE) { return {icon: "bi bi-trash"} } - if (can.base.beginWith(name, "bi ")) { return {icon: name} } - var _icon = can.base.getValid(can.Conf("_icons."+name), can.Conf("_trans.icons."+name), can.core.Value(can.onaction, ["_trans.icons."+name]), icon[name]) - if (_icon) { return {icon: _icon} } -}, -requireChina: function(can, title, list, name, path) { - can.onappend.plugin(can, {title: title, display: "/plugin/story/china.js", style: html.FLOAT, height: can.ConfHeight(), width: can.ConfHeight()}, function(sub) { - sub.run = function(event, cmds, cb) { var msg = can.request(event, {title: title, name: name, path: path}) - can.core.List(list, function(item) { msg.Push(mdb.NAME, item.name), msg.Push(mdb.VALUE, item.value) }), cb(msg) - can.onmotion.resize(can, sub._target, function(height, width) { sub.onimport.size(sub, height, width, true) }) + inputs: function(can, list, type) { + var _list = []; for (var i = 0; i < list.length; i++) { + switch (list[i]) { + case "": _list.push(""); break + case ice.AUTO: + _list.push({type: html.BUTTON, name: ice.LIST}) + _list.push({type: html.BUTTON, name: ice.BACK}) + break + case web.FILTER: + _list.push({type: html.TEXT, name: web.FILTER, icon: icon.search}) + break + case mdb.PAGE: + _list.push({type: html.TEXT, name: mdb.OFFEND, value: can._msg.Option(mdb.OFFEND)}) + _list.push({type: html.TEXT, name: mdb.LIMIT, value: can._msg.Option(mdb.LIMIT), _init: function(target) { + can.onappend.figure(can, {action: "key", run: function(event, cmds, cb) { + var msg = can.request(event) + msg.Push(cmds[1], "10") + msg.Push(cmds[1], "30") + msg.Push(cmds[1], "50") + msg.Push(cmds[1], "100") + cb(msg) + }}, target, function() { can.Update() }) + }}) + _list.push(mdb.NEXT, mdb.PREV) + break + default: (function() { var item = can.core.SplitInput(list[i], type||html.BUTTON) + if (item.type == html.SELECT) { + item._init = function(target) { target.value = item.value||item.values[0] + target.onchange = function(event) { can.misc.Event(event, can, function(msg) { can.run(event) }) } + } + } + item.action && (function() { item._init = function(target) { + can.onappend.figure(can, item, target, function() { can.Update({}, ) }) + } })() + _list.push(item), type = item.type + })() + } } - }) -}, -requireModules: function(can, libs, cb, cbs) { if (!libs || libs.length == 0) { return cb && cb() } - for (var i = 0; i < libs.length; i++) { if (libs[i].indexOf(nfs.PS) == 0 || libs[i].indexOf(ice.HTTP) == 0) { continue } - if (libs[i].indexOf(nfs._CSS) == -1 && libs[i].indexOf(nfs._JS) == -1) { libs[i] = libs[i]+"/lib/"+libs[i]+nfs._JS } - libs[i] = nfs.M+libs[i] - } can.require(libs, cb, cbs) -}, -requireDraw: function(can, cb) { can.require([chat.PLUGIN_LOCAL+"wiki/draw.js", chat.PLUGIN_LOCAL+"wiki/draw/path.js"], function() { - can.onimport._last_init(can, can.request()), can.onappend.style(can, wiki.DRAW, can._fields), cb() -}, function(can, mod, sub) { mod == chat.ONIMPORT && (can[mod]._last_init = sub._init) }) }, -drawText: function(can, text, size, margin, fonts) { text = text.slice(0, 1), size = size||80, margin = margin == undefined? 10: margin - var colors = ["rgb(239,150,26)", 'rgb(255,58,201)', "rgb(111,75,255)", "rgb(36,174,34)", "rgb(80,80,80)"] - var canvas = can.page.Create(can, html.CANVAS, {width: size, height: size}), ctx = canvas.getContext("2d") - ctx.fillStyle = colors[Math.floor(Math.random()*(colors.length))], ctx.fillRect(margin, margin, size-2*margin, size-2*margin) - ctx.fillStyle = cli.WHITE, ctx.font = (fonts||can.base.Min(size/text.length-30, 16))+"px Arial", ctx.textAlign = "center", ctx.textBaseline = "middle", ctx.fillText(text, size/2, size/2) - return canvas.toDataURL(html.IMAGE_PNG, 1) -}, -position: function(event, target) { var p = target.getBoundingClientRect(); return {x: event.clientX - p.x, y: event.clientY - p.y} }, -getquery: function(can, target) { - var list = []; for (var p = target; p; p = p.parentNode) { - if (can.page.tagis(p, "body")) { list.pop(); break } - list.push(can.core.Keys(p.tagName.toLowerCase(), can.core.List(p.classList).join(".")), ">") - if (can.page.tagis(p, html.FIELDSET)) { - if (can.page.tagis(p, "fieldset.web.chat.tutor")) { return "" } - list.pop(); break + return _list + }, + input: function(can, item, value) { var input = {type: html.INPUT, name: item.name, data: item, style: item.style||{}, dataset: {}, _init: item._init} + item.value == ice.AUTO && (item.value = "", item.action = ice.AUTO), item.action == ice.AUTO && (input.dataset.action = ice.AUTO) + switch (item.type = item.type||html.TEXT) { + case html.SELECT: input.type = html.SELECT, item.className||can.page.ClassList.add(can, item, ctx.ARGS) + item.values = can.base.isString(item.values)? can.core.Split(item.values): item.values + if (!item.values && item.value) { item.values = can.core.Split(item.value), item.value = item.values[0] } + if (item.values.slice(1).indexOf(item.values[0]) > -1) { item.value = item.value||item.values[0], item.values = item.values.slice(1) } + item.value = value||item.value, input.list = item.values.map(function(value) { + return {type: html.OPTION, value: value, inner: can.user.trans(can, value, null, html.VALUE)} + }); break + case html.TEXTAREA: input.type = html.TEXTAREA // no break + case html.USERNAME: // no break + case html.PASSWORD: // no break + case html.TEXT: + case html.FILTER: + item.className||can.page.ClassList.add(can, item, ctx.ARGS), item.name = item.name||item.type, item.value = value||item.value||""; + item.placeholder = item.placeholder||item.name + break + case html.UPLOAD: item.type = html.FILE, input.name = html.UPLOAD; break + case html.BUTTON: item.value = item.value||item.name||mdb.LIST; break + } return input + }, + icons: function(can, name, space) { if (!name) { return } + if (can.base.contains(name, "/") && can.misc.isImage(can, name)) { return {img: can.misc.Resource(can, name, space)} } + // if (can.page.unicode[name]) { return {text: [can.page.unicode[name], "", "icon"]} } + if (can.base.beginWith(name, "bi ")) { return {icon: name} } + if (name == mdb.DELETE) { return {icon: "bi bi-trash"} } + var _icon = can.base.getValid(can.Conf("_icons."+name), can.Conf("_trans.icons."+name), can.core.Value(can.onaction, ["_trans.icons."+name]), icon[name]) + if (_icon) { return {icon: _icon} } + }, + requireChina: function(can, title, list, name, path) { + can.onappend.plugin(can, {title: title, display: "/plugin/story/china.js", style: html.FLOAT, height: can.ConfHeight(), width: can.ConfHeight()}, function(sub) { + sub.run = function(event, cmds, cb) { var msg = can.request(event, {title: title, name: name, path: path}) + can.core.List(list, function(item) { msg.Push(mdb.NAME, item.name), msg.Push(mdb.VALUE, item.value) }), cb(msg) + can.onmotion.resize(can, sub._target, function(height, width) { sub.onimport.size(sub, height, width, true) }) + } + }) + }, + requireModules: function(can, libs, cb, cbs) { if (!libs || libs.length == 0) { return cb && cb() } + for (var i = 0; i < libs.length; i++) { if (libs[i].indexOf(nfs.PS) == 0 || libs[i].indexOf(ice.HTTP) == 0) { continue } + if (libs[i].indexOf(nfs._CSS) == -1 && libs[i].indexOf(nfs._JS) == -1) { libs[i] = libs[i]+"/lib/"+libs[i]+nfs._JS } + libs[i] = nfs.M+libs[i] + } can.require(libs, cb, cbs) + }, + requireDraw: function(can, cb) { can.require([chat.PLUGIN_LOCAL+"wiki/draw.js", chat.PLUGIN_LOCAL+"wiki/draw/path.js"], function() { + can.onimport._last_init(can, can.request()), can.onappend.style(can, wiki.DRAW, can._fields), cb() + }, function(can, mod, sub) { mod == chat.ONIMPORT && (can[mod]._last_init = sub._init) }) }, + drawText: function(can, text, size, margin, fonts) { text = text.slice(0, 1), size = size||80, margin = margin == undefined? 10: margin + var colors = ["rgb(239,150,26)", 'rgb(255,58,201)', "rgb(111,75,255)", "rgb(36,174,34)", "rgb(80,80,80)"] + var canvas = can.page.Create(can, html.CANVAS, {width: size, height: size}), ctx = canvas.getContext("2d") + ctx.fillStyle = colors[Math.floor(Math.random()*(colors.length))], ctx.fillRect(margin, margin, size-2*margin, size-2*margin) + ctx.fillStyle = cli.WHITE, ctx.font = (fonts||can.base.Min(size/text.length-30, 16))+"px Arial", ctx.textAlign = "center", ctx.textBaseline = "middle", ctx.fillText(text, size/2, size/2) + return canvas.toDataURL(html.IMAGE_PNG, 1) + }, + position: function(event, target) { var p = target.getBoundingClientRect(); return {x: event.clientX - p.x, y: event.clientY - p.y} }, + getquery: function(can, target) { + var list = []; for (var p = target; p; p = p.parentNode) { + if (can.page.tagis(p, "body")) { list.pop(); break } + list.push(can.core.Keys(p.tagName.toLowerCase(), can.core.List(p.classList).join(".")), ">") + if (can.page.tagis(p, html.FIELDSET)) { + if (can.page.tagis(p, "fieldset.web.chat.tutor")) { return "" } + list.pop(); break + } } - } - return list.reverse().join("") -}, -theme: function(cb) { var themeMedia = window.matchMedia("(prefers-color-scheme: dark)") - cb && themeMedia.addListener(function(event) { cb(event.matches? html.DARK: html.LIGHT) }) - cb && cb(themeMedia.matches? html.DARK: html.LIGHT) - return themeMedia.matches? html.DARK: html.LIGHT -}, -parseAction: function(can, value) { var action = [] - can.page.Select(can, can.page.Create(can, html.DIV, value.action), html.INPUT, function(target) { - action.push(target.name), target.name != target.value && can.user.trans(can, kit.Dict(target.name, target.value)) - }) - return action -}, -buttonStyle: function(can, name) { - return can.core.Value(can.onaction, ["_trans", "style", name])||(can.base.isIn(name, mdb.CREATE, mdb.INSERT, mdb.IMPORT, nfs.CLONE, cli.START, ctx.RUN, web.UPLOAD, web.CONFIRM, aaa.LOGIN, code.AUTOGEN, "sso", "add", "pull", "push", "commit", "preview", "auto-preview", ice.APP)? html.NOTICE: - can.base.isIn(name, mdb.REMOVE, mdb.DELETE, mdb.PRUNES, mdb.PRUNE, nfs.TRASH, cli.RESTART, cli.STOP, cli.CLOSE, cli.REBOOT, web.CANCEL, code.UPGRADE, "del", "drop", "access", "kill", "prockill")? html.DANGER: "") -}, -exportValue: function(can, msg, target) { target = target||can._output - msg.OptionDefault(ice.MSG_THEME, can.getHeaderTheme()) - msg.OptionDefault(ice.MSG_BG, can.page.styleValue(can, "--plugin-bg-color", target)) - msg.OptionDefault(ice.MSG_FG, can.page.styleValue(can, "--plugin-fg-color", target)) - can.user.info.language && msg.OptionDefault(ice.MSG_LANGUAGE, can.user.info.language) - return msg -}, -styleValue: function(can, key, target) { const styles = getComputedStyle(target||document.body); return styles.getPropertyValue(key) }, -styleValueInt: function(can, key, target) { return parseInt(can.base.trimSuffix(can.page.styleValue(can, key, target), "px")) } + return list.reverse().join("") + }, + theme: function(cb) { var themeMedia = window.matchMedia("(prefers-color-scheme: dark)") + cb && themeMedia.addListener(function(event) { cb(event.matches? html.DARK: html.LIGHT) }) + cb && cb(themeMedia.matches? html.DARK: html.LIGHT) + return themeMedia.matches? html.DARK: html.LIGHT + }, + parseAction: function(can, value) { var action = [] + can.page.Select(can, can.page.Create(can, html.DIV, value.action), html.INPUT, function(target) { + action.push(target.name), target.name != target.value && can.user.trans(can, kit.Dict(target.name, target.value)) + }) + return action + }, + buttonStyle: function(can, name) { + return can.core.Value(can.onaction, ["_trans", "style", name])||(can.base.isIn(name, mdb.CREATE, mdb.INSERT, mdb.IMPORT, nfs.CLONE, cli.START, ctx.RUN, web.UPLOAD, web.CONFIRM, aaa.LOGIN, code.AUTOGEN, "sso", "add", "pull", "push", "commit", "preview", "auto-preview", ice.APP)? html.NOTICE: + can.base.isIn(name, mdb.REMOVE, mdb.DELETE, mdb.PRUNES, mdb.PRUNE, nfs.TRASH, cli.RESTART, cli.STOP, cli.CLOSE, cli.REBOOT, web.CANCEL, code.UPGRADE, "del", "drop", "access", "kill", "prockill")? html.DANGER: "") + }, + exportValue: function(can, msg, target) { target = target||can._output + msg.OptionDefault(ice.MSG_THEME, can.getHeaderTheme()) + msg.OptionDefault(ice.MSG_BG, can.page.styleValue(can, "--plugin-bg-color", target)) + msg.OptionDefault(ice.MSG_FG, can.page.styleValue(can, "--plugin-fg-color", target)) + can.user.info.language && msg.OptionDefault(ice.MSG_LANGUAGE, can.user.info.language) + return msg + }, + styleValue: function(can, key, target) { const styles = getComputedStyle(target||document.body); return styles.getPropertyValue(key) }, + styleValueInt: function(can, key, target) { return parseInt(can.base.trimSuffix(can.page.styleValue(can, key, target), "px")) } }) diff --git a/lib/user.js b/lib/user.js index 5b377808..dd4face6 100644 --- a/lib/user.js +++ b/lib/user.js @@ -174,7 +174,8 @@ Volcanos("user", { var _style = can.page.buttonStyle(can, item) return { view: [[html.ITEM, item, _style]], - list: [can.page.icons(can, item), {text: [can.user.trans(can, item, trans), "", "name"]}], + // list: [can.page.icons(can, item), {text: [can.user.trans(can, item, trans), "", "name"]}], + list: [{text: [can.user.trans(can, item, trans), "", "name"]}], onclick: function(event) { click(event, item, index) }, onmouseenter: function(event) { remove_sub(carte) }, } @@ -184,7 +185,7 @@ Volcanos("user", { can.onimport && can.onimport[item[0]]? can.onimport[item[0]](can, button, event): click(event, button, index) }, carte, trans); carte._sub = sub } return {view: html.ITEM, list: [ - can.page.icons(can, item[0]), + // can.page.icons(can, item[0]), {text: [can.user.trans(can, item[0], trans), "", "name"]}, {text: [lex.SP+can.page.unicode.next, "", [html.ICON, "next"]]} ], onmouseenter: subs, onclick: subs} diff --git a/plugin/input.js b/plugin/input.js index e844fdfe..d689a6a5 100644 --- a/plugin/input.js +++ b/plugin/input.js @@ -2,7 +2,10 @@ Volcanos(chat.ONACTION, { run: function(event, can) { can.run(can.request(event, {_method: http.POST})) }, refresh: function(event, can) { can.run(can.request(event, {_method: http.GET})) }, list: function(event, can) { can.sup.isSimpleMode() || can.run(can.request(event, {_toast: event.isTrusted? ice.PROCESS: "" , _method: http.GET})) }, back: function(event, can) { can.sup.onimport.back(event, can.sup) }, onclick: function(event, can) { can.Conf(mdb.TYPE) == html.BUTTON && can.run(event, [ctx.ACTION, can.Conf(mdb.NAME)].concat(can.sup.Input())), can.onkeymap.prevent(event) }, - onchange: function(event, can) { can.Conf(mdb.TYPE) == html.SELECT && can.run(event) }, + onchange: function(event, can) { if (can.Conf(mdb.TYPE) != html.SELECT) { return } + can.sup.onexport.session && can.sup.onexport.session(can.sup, "action:"+can.Conf(mdb.NAME), event.target.value) + can.run(event) + }, onkeydown: function(event, can) { can.onkeymap.input(event, can, event.target); if (can.Conf(mdb.TYPE) == html.TEXTAREA && !event.ctrlKey) { return } if (event.key == code.ENTER) { return can.onkeymap.prevent(event), can.run(event), can.onmotion.focus(can, event.target) } if (!event.ctrlKey) { return } switch (event.key) { diff --git a/plugin/local/wiki/feel.css b/plugin/local/wiki/feel.css index 699445cb..019eeaaa 100644 --- a/plugin/local/wiki/feel.css +++ b/plugin/local/wiki/feel.css @@ -1,30 +1,34 @@ -// fieldset.feel>form.option div.item.file input { width:var(--project-width); } -fieldset.feel:not(.cmd)>form.option div.item.file { display:none; } -fieldset.feel>div.output>div.project div.item span.name { flex-grow:1; overflow:hidden; } -fieldset.feel>div.output>div.project div.item span.progress { color:var(--notice-bg-color); margin-left:10px; } -fieldset.feel>div.output>div.project div.item span.size { color:var(--disable-fg-color); font-size:var(--status-font-size); margin-left:10px; } -fieldset.feel>div.output>div.layout>div.display { position:relative; overflow:hidden; } +fieldset.feel:not(.cmd)>form.option>div.item.file { display:none; } +body.mobile fieldset.feel>form.option>div.item.file { display:none; } +fieldset.feel>div.output>div.project>div.item.select { border-width:3px; } +fieldset.feel>div.output>div.project>div.item>img { padding:5px; } +fieldset.feel>div.output>div.project>div.item>span.name { flex-grow:1; overflow:hidden; } +fieldset.feel>div.output>div.project>div.item>span.progress { color:var(--notice-bg-color); margin-left:10px; } +fieldset.feel>div.output>div.project>div.item>span.size { color:var(--disable-fg-color); font-size:var(--status-font-size); margin-left:10px; } +fieldset.feel>div.output>div.layout>div.display { overflow:hidden; position:relative; } fieldset.feel>div.output>div.layout>div.display:not(.hide) { height:100px; display:flex; justify-content:center; align-items:center; gap:10px; } -fieldset.feel>div.output>div.layout>div.display>.select { border:var(--box-notice); } -fieldset.feel>div.output>div.layout>div.display>img { height:98px; width:100px; object-fit:cover; } -fieldset.feel>div.output>div.layout>div.display>video { height:98px; width:100px; object-fit:cover; } -fieldset.feel>div.output>div.layout>div.display>div.audio { word-break:break-all; height:100%; width:100px; display:flex; align-items:center; } +fieldset.feel>div.output>div.layout>div.display>.select { border:var(--box-notice); border-width:3px; } +fieldset.feel>div.output>div.layout>div.display>img { height:100px; width:100px; object-fit:cover; } +fieldset.feel>div.output>div.layout>div.display>video { height:100px; width:100px; object-fit:cover; } +fieldset.feel>div.output>div.layout>div.display>div.audio { word-break:break-all; height:100px; width:100px; display:flex; align-items:center; } fieldset.feel>div.output>div.layout>div.display>div.audio:not(.select) { border:var(--box-border); } +fieldset.feel>div.output>div.layout>div.display>div.audio img.cover { height:94px; width:94px; position:absolute; } +fieldset.feel>div.output>div.layout>div.display>div.audio span.name { z-index:5; } fieldset.feel>div.output>div.layout>div.display>img:hover { cursor:pointer; } fieldset.feel>div.output>div.layout>div.display>video:hover { cursor:pointer; } -fieldset.feel>div.output>div.layout>div.display>div.audio:hover { background-color:var(--hover-bg-color); cursor:pointer; } +fieldset.feel>div.output>div.layout>div.display>div.audio:hover { cursor:pointer; } fieldset.feel>div.output>div.layout>div.display>div.toggle { font-size:32px; padding:5px; padding-top:32px; height:100px; position:absolute; } fieldset.feel>div.output>div.layout>div.display>div.toggle.prev { left:0; } fieldset.feel>div.output>div.layout>div.display>div.toggle.next { right:0; } -fieldset.feel>div.output>div.layout>div.layout>div.content { overflow:hidden; padding:0; } -fieldset.feel>div.output>div.layout>div.layout>div.content>img { object-fit:scale-down; cursor:pointer; } -fieldset.feel>div.output>div.layout>div.layout>div.content>img { height:100%; width:100%; } +fieldset.feel>div.output>div.layout>div.layout>div.content { padding:0; overflow:hidden; } +fieldset.feel>div.output>div.layout>div.layout>div.content>img { height:100%; width:100%; object-fit:scale-down; cursor:pointer; } fieldset.feel>div.output>div.layout>div.layout>div.content>video { height:100%; width:100%; } fieldset.feel>div.output>div.layout>div.layout>div.content>div.audio { height:100%; width: 100%; display:flex; flex-direction:column; justify-content:center; align-items:center; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.audio img.cover { height:calc(100% - 120px); } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.audio span.name { padding:10px; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.progress { background-color:var(--notice-bg-color); height:3px; position:absolute; bottom:2px; } fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle { font-size:32px; padding:5px; padding-top:32px; height:100px; top:40%; z-index:5; } fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle.next { right:0; } fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle.prev { left:0; } -fieldset.feel>div.output>div.layout>div.layout>div.content>div.progress { background-color:var(--notice-bg-color); height:3px; position:absolute; bottom:2px; } -// body:not(.mobile) fieldset.feel>div.output>div.layout>div.layout>div.content:not(:hover)>div.toggle { display:none; } -// body:not(.mobile) fieldset.feel>div.output>div.layout>div.display:not(:hover)>div.toggle { display:none; } -// body.mobile fieldset.feel>div.output>div.project { overflow-x:hidden; } +div.toggle { -webkit-user-select:none; } +img { -webkit-user-select:none; } \ No newline at end of file diff --git a/plugin/local/wiki/feel.js b/plugin/local/wiki/feel.js index 8b919a35..3f920c2d 100644 --- a/plugin/local/wiki/feel.js +++ b/plugin/local/wiki/feel.js @@ -1,39 +1,46 @@ Volcanos(chat.ONIMPORT, { - _init: function(can, msg, cb) { - can.ui = can.onappend.layout(can), can.onimport._project(can, msg) - cb && cb(msg), can.onimport.page(can, can.db.list, can.db.begin = 0) + _init: function(can, msg, cb) { can.onappend.style(can, wiki.FEEL) + can.user.isMobile && (can.onaction.list = ["upload"]) + can.ui = can.onappend.layout(can), cb && cb(msg) + if (can.Action("sort") != mdb.TIME) { + can.onaction.sort({}, can, "sort", can.Action("sort")) + } else { + can.onimport._project(can, msg) + } + can.onimport.page(can, can.db.list, can.db.begin = 0) can.onmotion.toggle(can, can.ui.display, true), can.onimport.layout(can) }, _project: function(can, msg) { can.db.list = [], can.db.dir_root = msg.Option(nfs.DIR_ROOT) msg.Table(function(item) { item.name = can.base.trimPrefix(item.path, can.Option(nfs.PATH)) + can.base.endWith(item.path, "/") && (item.nick = [{img: can.misc.Resource(can, "usr/icons/dir.png")}, {text: [item.name, "", mdb.NAME]}]) can.base.endWith(item.path, nfs.PS)? can.onimport.item(can, item, function(event) { can.Option(nfs.PATH, item.path) && can.Update(event) }): can.db.list.push(item) }) - can.core.List(can.db.list, function(item, index) { var last = can.onexport.progress(can, "p."+can.onimport._file(can, item.path)) - item.nick = [{text: [item.name, "", mdb.NAME]}, last && {text: [last, "", "progress"]}, {text: [item.size, "", nfs.SIZE]}] + can.core.List(can.db.list, function(item, index) { var last = can.onexport.progress(can, "p."+item.path) + item.nick = [item.cover? {img: can.misc.Resource(can, item.cover)}: + can.misc.isImage(can, item.path)? {img: can.misc.Resource(can, item.path)}: + can.misc.isVideo(can, item.path)? {img: can.misc.Resource(can, "usr/icons/QuickTime Player.png")}: + can.misc.isAudio(can, item.path)? {img: can.misc.Resource(can, "usr/icons/Music.png")}: null, + {text: [item.name, "", mdb.NAME]}, last && {text: [last, "", "progress"]}, {text: [item.size, "", nfs.SIZE]}, + ] item._hash = item.path, item._title = item.path.split("/").pop() - var target = can.onimport.item(can, item, function(event, item, show, target) { can.onimport._content(can, item, index, target) }); item._target = target + item._target = can.onimport.item(can, item, function(event, item, show, target) { can.onimport._content(can, item, index, target) }) }) }, - _content: function(can, item, index, target) { var progress - can.Option(nfs.FILE, can.base.trimPrefix(item.path, can.Option(nfs.PATH))) - if (can.onexport.progress(can, "p."+item._path) == "100%") { - can.onexport.progress(can, "p."+item._path, ""), can.onexport.progress(can, item._path, 0) - } - if (!can.onmotion.cache(can, function() { return item.path }, can.ui.content)) { - item._cb = function(event) { can.ui.video = event.target, can.Status(item), can.onexport.storage(can, "last", item.path) - var p = parseInt(event.target.currentTime*100/event.target.duration); item.nick[1] = {text: [p+"%", "", "progress"]}, can.page.Appends(can, target, item.nick) - if (!progress) { progress = can.page.Append(can, can.ui.content, ["progress"])._target } - can.page.style(can, progress, html.WIDTH, can.ui.content.offsetWidth*p/100) + _content: function(can, item, index, target) { can.Option(nfs.FILE, item.name), can.Status(item) + if (can.onexport.progress(can, "p."+item.path) == "100%") { can.onexport.progress(can, "p."+item.path, ""), can.onexport.progress(can, item.path, "") } + if (!can.onmotion.cache(can, function() { return item.path }, can.ui.content)) { var progress + item._cb = function(event) { can.ui.video = event.target + var p = parseInt(event.target.currentTime*100/event.target.duration) + can.page.Select(can, target, "span.progress", function(target) { target.innerText = p+"%" }) + if (!progress) { progress = can.page.Append(can, can.ui.content, ["progress"])._target } can.page.style(can, progress, html.WIDTH, can.ui.content.offsetWidth*p/100) } var _target = can.onimport.file(can, item.path, item, index, can.ui.content, true); _target.focus() - // _target.onclick = function() { can.page.tagis(_target, html.IMG) && can.ondetail._init(can, index) } can.onappend._toggle(can, can.ui.content, function() { - index == 0? can.user.toast(can, "已经是第一页了"): target.previousSibling.click() + target.previousSibling? target.previousSibling.click(): can.user.toast(can, "已经是第一页了") }, function() { - try { target.nextSibling.click() } catch (e) { can.user.toast(can, "已经是最后一页了") } + target.nextSibling? target.nextSibling.click(): can.user.toast(can, "已经是最后一页了") }) } - can.Status(item) if (index < can.db.begin || index >= can.db.begin+can.db.limit) { can.onimport.page(can, can.db.list, can.db.begin = index-index%can.db.limit) } can.onmotion.select(can, can.ui.display, "*", item._display) @@ -43,58 +50,57 @@ Volcanos(chat.ONIMPORT, { }, file: function(can, path, item, index, target, auto) { item._path = path = can.onimport._file(can, path) var cb = can.onfigure[can.base.Ext(path)]||can.onfigure[wiki.IMAGE] - return cb && can.page.Append(can, target||can.ui.display, [cb(can, path, item, index, auto)])._target + return cb && can.page.Append(can, target||can.ui.display, [cb(can, item, auto)])._target }, page: function(can, list, begin) { can.onmotion.clear(can, can.ui.display) - begin = parseInt(begin||can.db.begin||0), can.db.limit = (parseInt(can.ui.display.offsetWidth/110)||5)-1 - for (var i = begin; i < begin+can.db.limit; i++) { - if (list && list[i]) { - list[i]._display = can.onimport.file(can, list[i].path, list[i], i) - } - } + begin = parseInt(begin||can.db.begin||0), can.db.limit = can.base.Min((parseInt(can.ui.display.offsetWidth/110)||5)-1, 3) + for (var i = begin; i < begin+can.db.limit; i++) { if (list && list[i]) { list[i]._display = can.onimport.file(can, list[i].path, list[i], i) } } can.onappend._toggle(can, can.ui.display, function(event) { can.onaction.prev(event, can) }, function(event) { can.onaction.next(event, can) }) can.Status({begin: begin, limit: can.db.limit, total: list.length}) }, }, [""]) Volcanos(chat.ONFIGURE, { - png: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, - jpg: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, - jpeg: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, - image: function(can, path, item, index) { return {img: path, onclick: function(event) { item._target.click() }} }, - audio: function(can, path, item, index, auto) { - var meta = can.onfigure.video(can, path, item, index, auto); meta.type = html.AUDIO; - return {view: html.AUDIO, list: [{text: item.name}, meta], onclick: meta.onclick} - }, - video: function(can, path, item, index, auto) { - var cb = item._cb||function cb(event) {} - var init, last = can.onexport.progress(can, path)||0 - // preload: auto? "auto": "metadata", - return {type: html.VIDEO, data: {src: path, controls: auto? "controls": "", autoplay: auto, playbackRate: 1}, + png: function(can, item) { return can.onfigure.image(can, item) }, + jpg: function(can, item) { return can.onfigure.image(can, item) }, + jpeg: function(can, item) { return can.onfigure.image(can, item) }, + image: function(can, item) { return {img: item._path, onclick: function(event) { item._target.click() }} }, + video: function(can, item, auto) { var init, last = can.onexport.progress(can, item.path)||0 + return {type: html.VIDEO, data: {src: item._path, controls: auto, autoplay: auto}, onclick: function(event) { item._target.click(), can.onkeymap.prevent(event) }, onratechange: function(event) { can.onexport.storage(can, "rate", event.target.playbackRate) }, onvolumechange: function(event) { can.onexport.storage(can, "volume", event.target.volume) }, onloadedmetadata: function(event) { - event.target.volume = can.onexport.storage(can, "volume")||1 + event.target.volume = can.onexport.storage(can, "volume")||0.5 event.target.playbackRate = can.onexport.storage(can, "rate")||1 }, - ontimeupdate: function(event) { if (event.target.currentTime == 0) { return } cb(event) + ontimeupdate: function(event) { if (event.target.currentTime == 0) { return } item._cb && item._cb(event) can.Status("position", can.onexport.position(can, event.target.currentTime-1, event.target.duration)) - can.onexport.progress(can, "p."+path, parseInt(event.target.currentTime*100/event.target.duration)+"%") - can.onexport.progress(can, path, event.target.currentTime) + can.onexport.progress(can, "p."+item.path, parseInt(event.target.currentTime*100/event.target.duration)+"%") + can.onexport.progress(can, item.path, event.target.currentTime) if (!init) { init = true, event.target.currentTime = last } }, onended: function(event) { var next = item._target.nextSibling - if (next) { can.onmotion.delay(can, function() { next.click() }, 3000), can.user.toast(can, "3s 后即将播放下一个", "", 3000) } + next && can.onmotion.delay(can, function() { next.click() }, 300) }, } }, - webm: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, - mov: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, - m4v: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, - mp4: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, - mp3: function(can, path, item, index, auto) { return can.onfigure.audio(can, path, item, index, auto) }, + audio: function(can, item, auto) { var meta = can.onfigure.video(can, item, auto); meta.type = html.AUDIO + return {view: html.AUDIO, list: [{img: can.misc.Resource(can, item.cover, can.ConfSpace()), className: "cover"}, {text: [item.name, "", mdb.NAME]}, meta], onclick: meta.onclick} + }, + webm: function(can, item, auto) { return can.onfigure.video(can, item, auto) }, + mov: function(can, item, auto) { return can.onfigure.video(can, item, auto) }, + m4v: function(can, item, auto) { return can.onfigure.video(can, item, auto) }, + mp4: function(can, item, auto) { return can.onfigure.video(can, item, auto) }, + mp3: function(can, item, auto) { return can.onfigure.audio(can, item, auto) }, }) Volcanos(chat.ONACTION, { + _trans: { + "fullscreen": "全屏", + icons: { + "fullscreen": "bi bi-fullscreen", + }, + }, + list: ["upload", "record1", "record2", "fullscreen", ["sort", "time", "path", "size"]], record0: function(event, can, name, cb) { can.user.input(event, can, [{name: nfs.FILE, value: name}], function(list) { var height = window.innerHeight navigator.mediaDevices.getDisplayMedia({video: {height: height}}).then(function(stream) { can.core.Next([3, 2, 1], function(item, next) { can.user.toast(can, item + "s 后开始截图"), can.onmotion.delay(can, next, 1000) }, function() { can.user.toast(can, "现在开始截图") @@ -119,30 +125,17 @@ Volcanos(chat.ONACTION, { var show = can.onmotion.toggle(can, can.ui.project); can.onmotion.toggle(can, can.ui.display, show), can.onimport.layout(can) can.page.ClassList.set(can, can.ui.content, html.FLOAT, !show) }, + sort: function(event, can, button, value) { + switch (value) { + case mdb.TIME: can._msg.Sort(value, "str_r"); break + case nfs.PATH: can._msg.Sort(value, "str"); break + case nfs.SIZE: can._msg.Sort(value, "int_r"); break + } + can.onmotion.clear(can, can.ui.project), can.ui.filter = can.onappend.filter(can, can.ui.project), can.onimport._project(can, can._msg) + }, prev: function(event, can) { if (can.db.begin > 0) { can.db.begin -= can.db.limit, can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是第一页了") } }, next: function(event, can) { if (can.db.begin + can.db.limit < can.db.list.length) { can.db.begin += can.db.limit, can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是最后一页了") } }, }) -Volcanos(chat.ONDETAIL, {list: ["关闭", "上一个", "下一个", "设置头像", "设置背景", "复制链接", "下载", "删除"], - _init: function(can, index) { - can.onappend._init(can, {type: "story feel play float"}, [], function(sub) { can.sub = sub, sub._legend.innerHTML = can._legend.innerHTML, sub._legend.onclick = can._legend.onclick, can.onappend.style(can, html.FLEX, sub._output) - can.getActionSize(function(msg, left, top, width, height) { sub.onappend._action(can, can.ondetail.list, sub._action, can.ondetail), sub.onappend._status(sub, ["begin", nfs.FILE]) - sub.page.style(sub, sub._target, {left: left||0, top: top||0}), sub.page.style(sub, sub._output, html.HEIGHT, height-2*html.ACTION_HEIGHT, html.WIDTH, width) - can.order = index, can.show = function(order) { path = can.onimport._file(can, can.db.list[order].path); var cb = can.onfigure[can.base.Ext(path)]||can.onfigure[wiki.IMAGE] - sub.page.Appends(sub, sub._output, [can.base.Copy(cb(can, path, index), {height: "", style: kit.Dict(html.MAX_WIDTH, width, html.MAX_HEIGHT, height-2*html.ACTION_HEIGHT)})]) - sub.Status(cli.BEGIN, order+1+nfs.PS+can.db.list.length), sub.Status(nfs.FILE, path) - }, can.show(can.order) - }), sub.run = function(can, cmds, cb) { can.run(can, cmds, cb, true) } - }, can._root._target) - }, - "关闭": function(event, can) { can.page.Remove(can, can.sub._target) }, - "上一个": function(event, can) { can.order > 0? can.show(--can.order): can.user.toast(can, "已经是第一张啦!") }, - "下一个": function(event, can) { can.order < can.db.list.length-1? can.show(++can.order): can.user.toast(can, "已经是最后一张啦!") }, - "设置头像": function(event, can) { can.setHeader(aaa.AVATAR, can.onimport._file(can, can.db.list[can.order].path)) }, - "设置背景": function(event, can) { can.setHeader(aaa.BACKGROUND, can.onimport._file(can, can.db.list[can.order].path)) }, - "复制链接": function(event, can) { can.onmotion.share(event, can, [], [web.LINK, can.user.copy(event, can, can.misc.MergeURL(can, {_path: can.onimport._file(can, can.db.list[can.order].path)}, true)) ]) }, - "下载": function(event, can) { can.user.download(can, path = can.onimport._file(can, can.db.list[can.order].path)) }, - "删除": function(event, can) { can.runAction(event, nfs.TRASH, [can.db.list[can.order].path], function(msg) { can.user.toastSuccess(can, "删除成功") }, true) }, -}) Volcanos(chat.ONEXPORT, {list: [cli.BEGIN, mdb.LIMIT, mdb.TOTAL, mdb.NAME, nfs.SIZE, mdb.TIME, "position"], progress: function(can, path, time) { return can.onexport.storage(can, path.split("?")[0], time) }, position: function(can, index, total) { total = total || can.max; return parseInt((index+1)*100/total)+"%"+" = "+(parseInt(index)+1)+nfs.PS+parseInt(total) }, @@ -150,7 +143,7 @@ Volcanos(chat.ONEXPORT, {list: [cli.BEGIN, mdb.LIMIT, mdb.TOTAL, mdb.NAME, nfs.S Volcanos(chat.ONKEYMAP, { _mode: { plugin: { - Escape: function(event, can) { can.onaction.full(event, can) }, + Escape: function(event, can) { can.onaction.fullscreen(event, can) }, ArrowLeft: function(event, can) { can.ui.video.currentTime -= 15 }, ArrowRight: function(event, can) { can.ui.video.currentTime += 15 }, ArrowDown: function(event, can) { try { can.user.toast(can, "volume: "+parseInt((can.ui.video.volume -= 0.1)*100)) } catch (e) {} }, diff --git a/plugin/state.js b/plugin/state.js index bea6b5df..11d90390 100644 --- a/plugin/state.js +++ b/plugin/state.js @@ -344,7 +344,7 @@ Volcanos(chat.ONEXPORT, { return can.misc.sessionStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), key, location.pathname], value) }, storage: function(can, key, value) { if (value) { value = JSON.stringify(value) } - return can.misc.localStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), key, location.pathname], value) + return can.misc.localStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), key], value) }, hash: function(can, hash) { can.misc.SearchHash(can, hash), can.onexport.storage(can, "hash", hash) @@ -352,9 +352,7 @@ Volcanos(chat.ONEXPORT, { }, title: function(can, title) { if (!can.isCmdMode()) { return } var list = []; function push(p) { p && list.indexOf(p) == -1 && list.push(p) } - if (!can.base.isIn(can.ConfIndex(), web.PORTAL)) { - push(can.user.trans(can, can.ConfIndex(), can.Conf("help"))) - } + if (!can.base.isIn(can.ConfIndex(), web.PORTAL)) { push(can.user.trans(can, can.ConfIndex(), can.Conf("help"))) } can.core.List(arguments, function(title, index) { index > 0 && push(title) }), push(can.ConfSpace()||can.misc.Search(can, ice.POD)) can.user.title(list.join(" ")) }, diff --git a/plugin/table.js b/plugin/table.js index eec61393..26ead735 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -130,214 +130,215 @@ Volcanos(chat.ONIMPORT, { ].concat( can.onimport._nick(can, item), item._label||[], [ - item.action && {icon: "bi bi-three-dots", onclick: function(event) { can.onimport._menu(event, can, item, cbs) }}, - ]), _init: function(target) { target._item = item, item._item = target, can.ui[item.path] = target - item._select && can.onmotion.delay(can, function() { target.click() }) - }, onclick: function(event) { - can.db.value = item, can.onexport.hash(can, item._hash), can.onexport.title(can, item._title) - cb(event) - }, oncontextmenu: function(event) { - can.onimport._menu(event, can, item, cbs) - }} - }, - item: function(can, item, cb, cbs, _target) { - return can.page.Append(can, _target||can.ui.project||can._output, [can.onimport._item(can, item, function(event) { var target = event.currentTarget - can.onmotion.select(can, target.parentNode, html.DIV_ITEM, target) - can.onengine.signal(can, "onproject", can.request(event, {type: "item", query: can.page.getquery(can, can._fields)+","+item.path})) - var show = target._list && can.onmotion.toggle(can, target._list); if (show === false) { return } cb(event, item, show, target) - }, cbs)])._target - }, - _itemselect: function(can, target) { - can.page.Select(can, can.ui.project, html.DIV_ITEM, function(target) { can.page.ClassList.del(can, target, html.SELECT) }) - for (var p = target; p; p = p.parentNode.previousElementSibling) { can.page.ClassList.add(can, p, html.SELECT), can.onmotion.toggle(can, p.nextSibling, true) } - }, - itemlist: function(can, list, cb, cbs, target) { if (!list || list.length == 0) { return } - if (!target) { return can.core.List(list, function(value) { can.onimport.item(can, value, cb, cbs) }) } - if (!target._list) { target._list = can.page.insertBefore(can, [html.LIST], target.nextSibling, target.parentNode) } - return can.page.Append(can, target._list, can.core.List(list, function(item) { - return can.onimport._item(can, item, function(event) { var target = event.currentTarget - if (target._list && target._list.childElementCount > 0 && target._list && can.onmotion.toggle(can, target._list) == false) { return } - can.onimport._itemselect(can, target), cb && cb(event, item, target._list && true, target) - }, cbs) - })), target._list - }, - tree: function(can, list, cb, cbs, target, node, field, split) { node = node||{"": target||can.ui.project||can._output}, field = field||nfs.PATH, split = split||nfs.PS - can.core.List(list, function(item) { var key = item[field]; key && can.core.List(key.split(split), function(value, index, array) { if (!value) { return } - var last = array.slice(0, index).join(split), name = array.slice(0, index+1).join(split); if (node[name]) { return } - last && node[last] && can.page.Select(can, node[last].previousSibling, "div.expand", function(target) { target.innerHTML == "" && (target.innerHTML = can.page.unicode.closes) }) - item.expand = item.expand||item._select||(can.db.hash && (can.db.hash[0] == key)) - item._hash = item._hash||item.hash||item.zone||item.path||item.name - item._title = item._title||item.name||item.path||item.path||item.hash - var ui = can.page.Append(can, node[last], [{view: html.ITEM, list: [ - {view: [[html.EXPAND], html.DIV, (index==array.length-1? "": can.page.unicode.closes)]}, - {view: [mdb.NAME], list: [{text: [value, "", html.NAME]}].concat(item._label||[])}, - item.action && {view: [mdb.ICON], list: [{icon: "bi bi-three-dots", onclick: function(event) { can.onimport._menu(event, can, item, cbs) }}]}, - ], onclick: function(event) { var target = event.currentTarget - if (index < array.length-1 && !can.page.ClassList.set(can, ui[html.EXPAND], cli.OPEN, !can.page.ClassList.neg(can, node[name], html.HIDE))) { return } + item.action && {icon: "bi bi-three-dots", onclick: function(event) { can.onimport._menu(event, can, item, cbs) }}, + ]), _init: function(target) { target._item = item, item._item = target, can.ui[item.path] = target + item._select && can.onmotion.delay(can, function() { target.click() }) + }, onclick: function(event) { can.db.value = item, can.onexport.hash(can, item._hash), can.onexport.title(can, item._title) - can.onimport._itemselect(can, target), can.base.isFunc(cb) && cb(event, item, ui.item) - node[key] && can.page.ClassList.add(can, node[key].previousSibling, html.SELECT) - if (node[name].childElementCount == 2) { can.onmotion.delay(can, function() { node[name].firstChild.click() }) } + cb(event) }, oncontextmenu: function(event) { can.onimport._menu(event, can, item, cbs) - }, _init: item._init}, {view: [[html.LIST, html.HIDE]]}]); node[name] = ui.list, item.expand && ui.item.click() - }) }); return node - }, - tabs: function(can, list, cb, cbs, action) { action = action||can.ui.tabs||can._action; return can.page.Append(can, action, can.core.List(list, function(tabs) { if (typeof tabs == code.STRING) { tabs = {name: tabs} } - function close(target) { - if (can.page.ClassList.has(can, target, html.SELECT)) { - var next = can.page.tagis(target.nextSibling, html.DIV_TABS)? target.nextSibling: can.page.tagis(target.previousSibling, html.DIV_TABS)? target.previousSibling: null - if (!next) { return true } next && next.click() - } can.page.Remove(can, target), can.onexport.tabs && can.onexport.tabs(can) - } - return {view: [[html.TABS, tabs.type, tabs.role, tabs.status]], title: tabs.title||tabs.text, list: [ - can.onimport._icons(can, tabs), can.onimport._nick(can, tabs), {icon: mdb.DELETE, onclick: function(event) { tabs._target._close(), can.onkeymap.prevent(event) }}, - ], onclick: function(event) { - can.onmotion.delay(can, function() { can.onmotion.scrollIntoView(can, tabs._target) }) - if (can.page.ClassList.has(can, tabs._target, html.SELECT)) { return } - can.onmotion.select(can, action, html.DIV_TABS, tabs._target), can.base.isFunc(cb) && cb(event, tabs) - }, oncontextmenu: function(event) { var target = tabs._target, _action = can.page.parseAction(can, tabs) - var menu = tabs._menu||shy(function(event, button) { can.Update(event, [ctx.ACTION, button]) }) - can.user.carte(event, can, kit.Dict( - "Close", function(event) { target._close() }, - "Close Other", function(event) { target.click(), can.page.SelectChild(can, action, html.DIV_TABS, function(target) { target == tabs._target || target._close() }) }, - "Rename Tabs", function(event) { can.user.input(event, can, [mdb.NAME], function(list) { - can.page.SelectOne(can, target, html.SPAN, function(target) { can.page.Modify(can, target, list[0]||tabs.name) }) - }) }, menu.meta - ), ["Close", "Close Other", "Rename Tabs", ""].concat(can.base.getValid(menu.list, can.core.Item(menu.meta)), _action), function(event, button, meta) { - (meta[button]||menu)(can.request(event, tabs), button, meta) - }) - }, _init: function(target) { - action == can._action && can.page.Select(can, can._action, "div.item._space.state", function(space) { can.page.insertBefore(can, target, space) }) - target._item = tabs, tabs._target = target, target._close = function() { close(target) || cbs && cbs(tabs) }, target.click() - can.page.Modify(can, target, {draggable: true, - ondragstart: function(event) { action._drop = function(before) { before.parentNode == action && action.insertBefore(target, before), can.onexport.tabs(can) } }, - ondragover: function(event) { event.preventDefault(), action._drop(event.target) }, - }) - }} - }))._target }, - tabsCache: function(can, value, target, cb) { if (value._tabs) { return value._tabs.click() } - value._tabs = can.onimport.tabs(can, [value], function() { can.page.isSelect(target) || can.onmotion.delay(can, function() { target.click() }) - can.page.SelectOne(can, can._status, html.LEGEND) || can.onmotion.cache(can, function() { return value._hash }, can._status) - if (can.onmotion.cache(can, function() { return value._hash }, can.ui.content, can.ui.profile, can.ui.display)) { return can.onimport.layout(can) } - can.Status(value); if (can.base.isFunc(cb)) { return cb() } var msg = cb - if (msg.Append(ctx.INDEX)) { msg.Table(function(value, index) { - index == 0 && can.onappend.plugin(can, value, function(sub) { can.db.value._content_plugin = sub, can.onimport.layout(can) }, can.ui.content) - index == 1 && can.onappend.plugin(can, value, function(sub) { - can.onmotion.toggle(can, can.ui.display, true) - can.db.value._display_plugin = sub, can.onimport.layout(can) }, can.ui.display) - index == 2 && can.onappend.plugin(can, value, function(sub) { - can.onmotion.toggle(can, can.ui.profile, true) - can.db.value._profile_plugin = sub, can.onimport.layout(can) }, can.ui.profile) - can.onmotion.delay(can, function() { can.onimport.layout(can) }) - can.onmotion.delay(can, function() { can.onimport.layout(can) }, 100) - can.onmotion.delay(can, function() { can.onimport.layout(can) }, 300) - }) } else { can.onappend.table(can, msg), can.onappend.board(can, msg) } - }, function() { delete(value._tabs), can.onmotion.cacheClear(can, value._hash, can.ui.content, can.ui.profile, can.ui.display) }) - }, - tool: function(can, list, cb, target, status) { target = target||can._status, status = status||can._status - var height = can.base.Max(html.PLUG_HEIGHT, can.ConfHeight()-3*html.ACTION_HEIGHT, 240), width = can.base.Max(html.PLUG_WIDTH, can.ConfWidth()-(can.user.isMobile? 0: html.PROJECT_WIDTH)) - can.core.Next(list.reverse(), function(meta, next) { can.base.isString(meta) && (meta = {index: meta}), meta.mode = html.FLOAT - can.onimport.plug(can, meta, function(sub) { - sub.onexport.output = function() { - can.page.style(can, sub._output, html.MAX_HEIGHT, "", html.HEIGHT, "", html.WIDTH, "", html.MAX_WIDTH, "") - sub.onimport.size(sub, height, width, false), can.onmotion.delay(can, function() { sub.onimport.size(sub, height, width, false) }) - }, sub.onimport.size(sub, height, width, false) - can.page.Append(can, sub._legend,[{text: [can.page.unicode.remove, "", mdb.REMOVE], onclick: function(event) { - can.page.Remove(can, sub._target), can.page.Remove(can, sub._legend), can.onexport.tool(can), can.onkeymap.prevent(event) - }}]), sub._legend._target = sub._target, sub._legend._meta = {index: meta.index} - status.appendChild(sub._legend), sub._legend.oncontextmenu = sub._legend.onclick, sub._legend.onclick = function(event) { can.misc.Event(event, can, function(msg) { - if (can.page.SelectOne(can, status, "legend.select", function(target) { - can.onmotion.hidden(can, target._target), can.page.ClassList.del(can, target, html.SELECT); return target }) == sub._legend) { return } - can.onmotion.select(can, status, html.LEGEND, sub._legend), can.onmotion.toggle(can, sub._target, true) - can.onmotion.select(can, target, html.FIELDSET_PLUG, sub._target) - sub.onimport.size(sub, sub.ConfHeight(), sub.ConfWidth(), false) - if (sub._delay_init || meta.msg) { sub._delay_init = false, meta.msg = false, (sub._inputs && sub._inputs.list || sub._inputs && sub._inputs.refresh) && sub.Update() } - }) }, sub._delay_init = true, sub.select = function(show) { - if (show && can.page.ClassList.has(can, sub._legend, html.SELECT)) { return sub } - return sub._legend.click(), sub - }, can.onmotion.hidden(can, sub._target) - sub.hidden = function() { can.onmotion.hidden(can, sub._target), can.page.ClassList.del(can, sub._legend, html.SELECT) } - sub.onaction._close = function() { can.page.Remove(can, sub._target), can.page.Remove(can, sub._legend), can.onexport.tool(can) } - sub.onaction.close = function() { sub.select() }, can.base.isFunc(cb) && cb(sub), can.onexport.tool(can) - next() - }, target) - }) - }, - plug: function(can, meta, cb, target, field) { if (!meta || !meta.index) { return } - meta.type = meta.type||html.PLUG, meta.name = meta.index, can.onappend.plugin(can, meta, function(sub) { sub.sup = can - sub.onaction.close = function() { can.onmotion.hidden(can, target) }, can.base.isFunc(cb) && cb(sub) - }, target, field) - }, -}) -Volcanos(chat.ONLAYOUT, { - _init: function(can, height, width) { can.core.CallFunc([can.onimport, html.LAYOUT], {can: can, height: height, width: width}) }, - zone: function(can, height, width) { can.onlayout._init(can, height, width) }, - result: function(can, height, width) { can.onlayout._init(can, height, width) }, - simple: function(can, height, width) { can.onlayout._init(can, height, width) }, - output: function(can, height, width) { can.onlayout._init(can, height, width) }, - float: function(can, height, width) { can.onlayout._init(can, height, width) }, - full: function(can, height, width) { can.onlayout._init(can, height, width) }, - cmd: function(can, height, width) { can.onlayout._init(can, height, width) }, -}) -Volcanos(chat.ONEXPORT, { - title: function(can, title) { can.sup.onexport.title.apply(can.sup.onexport, [can.sup].concat(can.core.List(arguments).slice(1))) }, - action_value: function(can, key, def) { var value = can.Action(key); return can.base.isIn(value, ice.AUTO, key, undefined)? def: value }, - tabs: function(can) {}, - tool: function(can) { can.misc.sessionStorage(can, [can.ConfIndex(), "tool"], JSON.stringify(can.page.Select(can, can._status, html.LEGEND, function(target) { return target._meta }))) }, - hash: function(can, hash) { hash = typeof hash == code.STRING? hash.split(":").concat(can.core.List(arguments).slice(2)||[]): hash || can.core.Item(can.Option(), function(key, value) { return value||"" }) - return can.sup.onexport.hash(can.sup, hash) - }, - session: function(can, key, value) { return can.sup.onexport.session(can.sup, key, value) }, - storage: function(can, key, value) { return can.sup.onexport.storage(can.sup, key, value) }, - table: function(can) { var msg = can._msg; if (msg.Length() == 0) { return } var res = [msg.append && msg.append.join(mdb.FS)] - msg.Table(function(line, index, array) { res.push(can.core.Item(line, function(key, value) { return value }).join(ice.FS)) }) - return res.join(lex.NL) - }, - board: function(can) { var msg = can._msg; return msg.Result() }, -}) -Volcanos(chat.ONACTION, { - onkeydown: function(event, can) { - if (can.onkeymap.selectCtrlN(event, can, can.ui.tabs||can._action, html.DIV_TABS)) { return } - can.onkeymap._parse(event, can) - }, -}) -Volcanos(chat.ONKEYMAP, { - escape: function(event, can) {}, enter: function(event, can) {}, - ctrln: function(event, can) { can.onkeymap.selectCtrlN(event, can, can._action, html.DIV_TABS) }, - space: function(event, can) { can.ui.filter && (can.ui.filter.focus(), can.onkeymap.prevent(event)) }, - tabx: function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { target._close() }) }, - tabs: function(event, can) {}, - _mode: { - plugin: { - Escape: shy("清理屏幕", function(event, can) { can.onkeymap.escape(event, can) }), - Enter: shy("执行操作", function(event, can) { can.onkeymap.enter(event, can) }), - " ": shy("搜索项目", function(event, can) { can.onkeymap.space(event, can) }), - f: shy("搜索项目", function(event, can) { can.ui.filter && (can.ui.filter.focus(), can.onkeymap.prevent(event)) }), - a: shy("展示项目", function(event, can) { can.ui.project && (can.onmotion.toggle(can, can.ui.project), can.onimport.layout(can)) }), - v: shy("展示预览", function(event, can) { can.ui.profile && (can.onmotion.toggle(can, can.ui.profile), can.onimport.layout(can)) }), - r: shy("展示输出", function(event, can) { can.ui.display && (can.onmotion.toggle(can, can.ui.display), can.onimport.layout(can)) }), - p: shy("添加插件", function(event, can) { can.sup.onaction["添加工具"](event, can.sup) }), - t: shy("添加标签", function(event, can) { can.onkeymap.tabs(event, can) }), - x: shy("添加标签", function(event, can) { can.onkeymap.tabx(event, can) }), - l: shy("打开右边标签", function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { - var next = target.nextSibling; next && can.page.ClassList.has(can, next, html.TABS) && next.click() - }) }), - h: shy("打开左边标签", function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { - var prev = target.previousSibling; prev && can.page.ClassList.has(can, prev, html.TABS) && prev.click() - }) }), + }} }, - }, _engine: {}, -}) -Volcanos(chat.ONINPUTS, { - _nameicon: function(event, can, msg, target, name) { - can.page.Appends(can, can._output, msg.Table(function(value) { - return {view: html.ITEM, list: [{img: can.misc.Resource(can, value.icons)}, - {view: html.CONTAINER, list: [{view: [html.TITLE, "", value[name]||value[mdb.NAME]]}, - can.onappend.label(can, value, {version: icon.version, time: icon.compile}), - ]}, - ], onclick: function(event) { can.showIcons(value[name]||value[mdb.NAME], value.icons) }} - })) - }, - dream: function(event, can, msg, target, name) { can.sup.sub.oninputs._nameicon(event, can, msg, target, name) }, -}) + item: function(can, item, cb, cbs, _target) { + return can.page.Append(can, _target||can.ui.project||can._output, [can.onimport._item(can, item, function(event) { var target = event.currentTarget + can.onmotion.select(can, target.parentNode, html.DIV_ITEM, target) + can.onengine.signal(can, "onproject", can.request(event, {type: "item", query: can.page.getquery(can, can._fields)+","+item.path})) + var show = target._list && can.onmotion.toggle(can, target._list); if (show === false) { return } cb(event, item, show, target) + }, cbs)])._target + }, + _itemselect: function(can, target) { + can.page.Select(can, can.ui.project, html.DIV_ITEM, function(target) { can.page.ClassList.del(can, target, html.SELECT) }) + for (var p = target; p; p = p.parentNode.previousElementSibling) { can.page.ClassList.add(can, p, html.SELECT), can.onmotion.toggle(can, p.nextSibling, true) } + }, + itemlist: function(can, list, cb, cbs, target) { if (!list || list.length == 0) { return } + if (!target) { return can.core.List(list, function(value) { can.onimport.item(can, value, cb, cbs) }) } + if (!target._list) { target._list = can.page.insertBefore(can, [html.LIST], target.nextSibling, target.parentNode) } + return can.page.Append(can, target._list, can.core.List(list, function(item) { + return can.onimport._item(can, item, function(event) { var target = event.currentTarget + if (target._list && target._list.childElementCount > 0 && target._list && can.onmotion.toggle(can, target._list) == false) { return } + can.onimport._itemselect(can, target), cb && cb(event, item, target._list && true, target) + }, cbs) + })), target._list + }, + tree: function(can, list, cb, cbs, target, node, field, split) { node = node||{"": target||can.ui.project||can._output}, field = field||nfs.PATH, split = split||nfs.PS + can.core.List(list, function(item) { var key = item[field]; key && can.core.List(key.split(split), function(value, index, array) { if (!value) { return } + var last = array.slice(0, index).join(split), name = array.slice(0, index+1).join(split); if (node[name]) { return } + last && node[last] && can.page.Select(can, node[last].previousSibling, "div.expand", function(target) { target.innerHTML == "" && (target.innerHTML = can.page.unicode.closes) }) + item.expand = item.expand||item._select||(can.db.hash && (can.db.hash[0] == key)) + item._hash = item._hash||item.hash||item.zone||item.path||item.name + item._title = item._title||item.name||item.path||item.path||item.hash + var ui = can.page.Append(can, node[last], [{view: html.ITEM, list: [ + {view: [[html.EXPAND], html.DIV, (index==array.length-1? "": can.page.unicode.closes)]}, + {view: [mdb.NAME], list: [{text: [value, "", html.NAME]}].concat(item._label||[])}, + item.action && {view: [mdb.ICON], list: [{icon: "bi bi-three-dots", onclick: function(event) { can.onimport._menu(event, can, item, cbs) }}]}, + ], onclick: function(event) { var target = event.currentTarget + if (index < array.length-1 && !can.page.ClassList.set(can, ui[html.EXPAND], cli.OPEN, !can.page.ClassList.neg(can, node[name], html.HIDE))) { return } + can.db.value = item, can.onexport.hash(can, item._hash), can.onexport.title(can, item._title) + can.onimport._itemselect(can, target), can.base.isFunc(cb) && cb(event, item, ui.item) + node[key] && can.page.ClassList.add(can, node[key].previousSibling, html.SELECT) + if (node[name].childElementCount == 2) { can.onmotion.delay(can, function() { node[name].firstChild.click() }) } + }, oncontextmenu: function(event) { + can.onimport._menu(event, can, item, cbs) + }, _init: item._init}, {view: [[html.LIST, html.HIDE]]}]); node[name] = ui.list, item.expand && ui.item.click() + }) }); return node + }, + tabs: function(can, list, cb, cbs, action) { action = action||can.ui.tabs||can._action; return can.page.Append(can, action, can.core.List(list, function(tabs) { if (typeof tabs == code.STRING) { tabs = {name: tabs} } + function close(target) { + if (can.page.ClassList.has(can, target, html.SELECT)) { + var next = can.page.tagis(target.nextSibling, html.DIV_TABS)? target.nextSibling: can.page.tagis(target.previousSibling, html.DIV_TABS)? target.previousSibling: null + if (!next) { return true } next && next.click() + } can.page.Remove(can, target), can.onexport.tabs && can.onexport.tabs(can) + } + return {view: [[html.TABS, tabs.type, tabs.role, tabs.status]], title: tabs.title||tabs.text, list: [ + can.onimport._icons(can, tabs), can.onimport._nick(can, tabs), {icon: mdb.DELETE, onclick: function(event) { tabs._target._close(), can.onkeymap.prevent(event) }}, + ], onclick: function(event) { + can.onmotion.delay(can, function() { can.onmotion.scrollIntoView(can, tabs._target) }) + if (can.page.ClassList.has(can, tabs._target, html.SELECT)) { return } + can.onmotion.select(can, action, html.DIV_TABS, tabs._target), can.base.isFunc(cb) && cb(event, tabs) + }, oncontextmenu: function(event) { var target = tabs._target, _action = can.page.parseAction(can, tabs) + var menu = tabs._menu||shy(function(event, button) { can.Update(event, [ctx.ACTION, button]) }) + can.user.carte(event, can, kit.Dict( + "Close", function(event) { target._close() }, + "Close Other", function(event) { target.click(), can.page.SelectChild(can, action, html.DIV_TABS, function(target) { target == tabs._target || target._close() }) }, + "Rename Tabs", function(event) { can.user.input(event, can, [mdb.NAME], function(list) { + can.page.SelectOne(can, target, html.SPAN, function(target) { can.page.Modify(can, target, list[0]||tabs.name) }) + }) }, menu.meta + ), ["Close", "Close Other", "Rename Tabs", ""].concat(can.base.getValid(menu.list, can.core.Item(menu.meta)), _action), function(event, button, meta) { + (meta[button]||menu)(can.request(event, tabs), button, meta) + }) + }, _init: function(target) { + action == can._action && can.page.Select(can, can._action, "div.item._space.state", function(space) { can.page.insertBefore(can, target, space) }) + target._item = tabs, tabs._target = target, target._close = function() { close(target) || cbs && cbs(tabs) }, target.click() + can.page.Modify(can, target, {draggable: true, + ondragstart: function(event) { action._drop = function(before) { before.parentNode == action && action.insertBefore(target, before), can.onexport.tabs(can) } }, + ondragover: function(event) { event.preventDefault(), action._drop(event.target) }, + }) + }} + }))._target }, + tabsCache: function(can, value, target, cb) { if (value._tabs) { return value._tabs.click() } + value._tabs = can.onimport.tabs(can, [value], function() { can.page.isSelect(target) || can.onmotion.delay(can, function() { target.click() }) + can.page.SelectOne(can, can._status, html.LEGEND) || can.onmotion.cache(can, function() { return value._hash }, can._status) + if (can.onmotion.cache(can, function() { return value._hash }, can.ui.content, can.ui.profile, can.ui.display)) { return can.onimport.layout(can) } + can.Status(value); if (can.base.isFunc(cb)) { return cb() } var msg = cb + if (msg.Append(ctx.INDEX)) { msg.Table(function(value, index) { + index == 0 && can.onappend.plugin(can, value, function(sub) { can.db.value._content_plugin = sub, can.onimport.layout(can) }, can.ui.content) + index == 1 && can.onappend.plugin(can, value, function(sub) { + can.onmotion.toggle(can, can.ui.display, true) + can.db.value._display_plugin = sub, can.onimport.layout(can) }, can.ui.display) + index == 2 && can.onappend.plugin(can, value, function(sub) { + can.onmotion.toggle(can, can.ui.profile, true) + can.db.value._profile_plugin = sub, can.onimport.layout(can) }, can.ui.profile) + can.onmotion.delay(can, function() { can.onimport.layout(can) }) + can.onmotion.delay(can, function() { can.onimport.layout(can) }, 100) + can.onmotion.delay(can, function() { can.onimport.layout(can) }, 300) + }) } else { can.onappend.table(can, msg), can.onappend.board(can, msg) } + }, function() { delete(value._tabs), can.onmotion.cacheClear(can, value._hash, can.ui.content, can.ui.profile, can.ui.display) }) + }, + tool: function(can, list, cb, target, status) { target = target||can._status, status = status||can._status + var height = can.base.Max(html.PLUG_HEIGHT, can.ConfHeight()-3*html.ACTION_HEIGHT, 240), width = can.base.Max(html.PLUG_WIDTH, can.ConfWidth()-(can.user.isMobile? 0: html.PROJECT_WIDTH)) + can.core.Next(list.reverse(), function(meta, next) { can.base.isString(meta) && (meta = {index: meta}), meta.mode = html.FLOAT + can.onimport.plug(can, meta, function(sub) { + sub.onexport.output = function() { + can.page.style(can, sub._output, html.MAX_HEIGHT, "", html.HEIGHT, "", html.WIDTH, "", html.MAX_WIDTH, "") + sub.onimport.size(sub, height, width, false), can.onmotion.delay(can, function() { sub.onimport.size(sub, height, width, false) }) + }, sub.onimport.size(sub, height, width, false) + can.page.Append(can, sub._legend,[{text: [can.page.unicode.remove, "", mdb.REMOVE], onclick: function(event) { + can.page.Remove(can, sub._target), can.page.Remove(can, sub._legend), can.onexport.tool(can), can.onkeymap.prevent(event) + }}]), sub._legend._target = sub._target, sub._legend._meta = {index: meta.index} + status.appendChild(sub._legend), sub._legend.oncontextmenu = sub._legend.onclick, sub._legend.onclick = function(event) { can.misc.Event(event, can, function(msg) { + if (can.page.SelectOne(can, status, "legend.select", function(target) { + can.onmotion.hidden(can, target._target), can.page.ClassList.del(can, target, html.SELECT); return target }) == sub._legend) { return } + can.onmotion.select(can, status, html.LEGEND, sub._legend), can.onmotion.toggle(can, sub._target, true) + can.onmotion.select(can, target, html.FIELDSET_PLUG, sub._target) + sub.onimport.size(sub, sub.ConfHeight(), sub.ConfWidth(), false) + if (sub._delay_init || meta.msg) { sub._delay_init = false, meta.msg = false, (sub._inputs && sub._inputs.list || sub._inputs && sub._inputs.refresh) && sub.Update() } + }) }, sub._delay_init = true, sub.select = function(show) { + if (show && can.page.ClassList.has(can, sub._legend, html.SELECT)) { return sub } + return sub._legend.click(), sub + }, can.onmotion.hidden(can, sub._target) + sub.hidden = function() { can.onmotion.hidden(can, sub._target), can.page.ClassList.del(can, sub._legend, html.SELECT) } + sub.onaction._close = function() { can.page.Remove(can, sub._target), can.page.Remove(can, sub._legend), can.onexport.tool(can) } + sub.onaction.close = function() { sub.select() }, can.base.isFunc(cb) && cb(sub), can.onexport.tool(can) + next() + }, target) + }) + }, + plug: function(can, meta, cb, target, field) { if (!meta || !meta.index) { return } + meta.type = meta.type||html.PLUG, meta.name = meta.index, can.onappend.plugin(can, meta, function(sub) { sub.sup = can + sub.onaction.close = function() { can.onmotion.hidden(can, target) }, can.base.isFunc(cb) && cb(sub) + }, target, field) + }, + }) + Volcanos(chat.ONLAYOUT, { + _init: function(can, height, width) { can.core.CallFunc([can.onimport, html.LAYOUT], {can: can, height: height, width: width}) }, + zone: function(can, height, width) { can.onlayout._init(can, height, width) }, + result: function(can, height, width) { can.onlayout._init(can, height, width) }, + simple: function(can, height, width) { can.onlayout._init(can, height, width) }, + output: function(can, height, width) { can.onlayout._init(can, height, width) }, + float: function(can, height, width) { can.onlayout._init(can, height, width) }, + full: function(can, height, width) { can.onlayout._init(can, height, width) }, + cmd: function(can, height, width) { can.onlayout._init(can, height, width) }, + }) + Volcanos(chat.ONEXPORT, { + title: function(can, title) { can.sup.onexport.title.apply(can.sup.onexport, [can.sup].concat(can.core.List(arguments).slice(1))) }, + action_value: function(can, key, def) { var value = can.Action(key); return can.base.isIn(value, ice.AUTO, key, undefined)? def: value }, + tabs: function(can) {}, + tool: function(can) { can.misc.sessionStorage(can, [can.ConfIndex(), "tool"], JSON.stringify(can.page.Select(can, can._status, html.LEGEND, function(target) { return target._meta }))) }, + hash: function(can, hash) { hash = typeof hash == code.STRING? hash.split(":").concat(can.core.List(arguments).slice(2)||[]): hash || can.core.Item(can.Option(), function(key, value) { return value||"" }) + return can.sup.onexport.hash(can.sup, hash) + }, + session: function(can, key, value) { return can.sup.onexport.session(can.sup, key, value) }, + storage: function(can, key, value) { return can.sup.onexport.storage(can.sup, key, value) }, + table: function(can) { var msg = can._msg; if (msg.Length() == 0) { return } var res = [msg.append && msg.append.join(mdb.FS)] + msg.Table(function(line, index, array) { res.push(can.core.Item(line, function(key, value) { return value }).join(ice.FS)) }) + return res.join(lex.NL) + }, + board: function(can) { var msg = can._msg; return msg.Result() }, + }) + Volcanos(chat.ONACTION, { + onkeydown: function(event, can) { + if (can.onkeymap.selectCtrlN(event, can, can.ui.tabs||can._action, html.DIV_TABS)) { return } + can.onkeymap._parse(event, can) + }, + }) + Volcanos(chat.ONKEYMAP, { + escape: function(event, can) {}, enter: function(event, can) {}, + ctrln: function(event, can) { can.onkeymap.selectCtrlN(event, can, can._action, html.DIV_TABS) }, + space: function(event, can) { can.ui.filter && (can.ui.filter.focus(), can.onkeymap.prevent(event)) }, + tabx: function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { target._close() }) }, + tabs: function(event, can) {}, + _mode: { + plugin: { + Escape: shy("清理屏幕", function(event, can) { can.onkeymap.escape(event, can) }), + Enter: shy("执行操作", function(event, can) { can.onkeymap.enter(event, can) }), + " ": shy("搜索项目", function(event, can) { can.onkeymap.space(event, can) }), + f: shy("搜索项目", function(event, can) { can.ui.filter && (can.ui.filter.focus(), can.onkeymap.prevent(event)) }), + a: shy("展示项目", function(event, can) { can.ui.project && (can.onmotion.toggle(can, can.ui.project), can.onimport.layout(can)) }), + v: shy("展示预览", function(event, can) { can.ui.profile && (can.onmotion.toggle(can, can.ui.profile), can.onimport.layout(can)) }), + r: shy("展示输出", function(event, can) { can.ui.display && (can.onmotion.toggle(can, can.ui.display), can.onimport.layout(can)) }), + p: shy("添加插件", function(event, can) { can.sup.onaction["添加工具"](event, can.sup) }), + t: shy("添加标签", function(event, can) { can.onkeymap.tabs(event, can) }), + x: shy("添加标签", function(event, can) { can.onkeymap.tabx(event, can) }), + l: shy("打开右边标签", function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { + var next = target.nextSibling; next && can.page.ClassList.has(can, next, html.TABS) && next.click() + }) }), + h: shy("打开左边标签", function(event, can) { can.page.Select(can, can._action, html.DIV_TABS_SELECT, function(target) { + var prev = target.previousSibling; prev && can.page.ClassList.has(can, prev, html.TABS) && prev.click() + }) }), + }, + }, _engine: {}, + }) + Volcanos(chat.ONINPUTS, { + _nameicon: function(event, can, msg, target, name) { + can.page.Appends(can, can._output, msg.Table(function(value) { + return {view: html.ITEM, list: [{img: can.misc.Resource(can, value.icons)}, + {view: html.CONTAINER, list: [{view: [html.TITLE, "", value[name]||value[mdb.NAME]]}, + can.onappend.label(can, value, {version: icon.version, time: icon.compile}), + ]}, + ], onclick: function(event) { can.showIcons(value[name]||value[mdb.NAME], value.icons) }} + })) + }, + dream: function(event, can, msg, target, name) { can.sup.sub.oninputs._nameicon(event, can, msg, target, name) }, + }) + \ No newline at end of file