From 04b3991922d71281741746f1cba80d2b60f3e7d0 Mon Sep 17 00:00:00 2001 From: shy Date: Fri, 2 Feb 2024 00:06:01 +0800 Subject: [PATCH] add island.group --- const.js | 4 ++-- frame.js | 24 +++++++++++++++++++----- index.css | 11 ++++++----- lib/misc.js | 4 +--- lib/user.js | 5 ++--- panel/action.js | 4 ++-- panel/footer.js | 1 - panel/river.js | 6 ++++-- plugin/local/team/plan.css | 1 + plugin/local/wiki/word.js | 8 ++++++-- plugin/state.js | 4 +++- plugin/story/form.js | 5 +---- plugin/table.js | 11 ----------- 13 files changed, 47 insertions(+), 41 deletions(-) diff --git a/const.js b/const.js index 231b63a0..66fbf07a 100644 --- a/const.js +++ b/const.js @@ -124,7 +124,7 @@ var web = { } var aaa = { USER: "user", AUTH: "auth", SESS: "sess", ROLE: "role", - EMAIL: "email", OFFER: "offer", + EMAIL: "email", OFFER: "offer", APPLY: "apply", LOGIN: "login", LOGOUT: "logout", BACKGROUND: "background", AVATAR: "avatar", MOBILE: "mobile", SECRET: "secret", @@ -370,7 +370,7 @@ var icon = { CHEVRON_DOWN: "bi bi-chevron-down", SEARCH: "bi bi-search", TERMINAL: "bi bi-terminal", SUN: "bi bi-sun", MOON: "bi bi-moon-stars", - admin: "bi bi-window-sidebar", dream: "bi bi-grid-3x3-gap", space: "bi bi-grid-3x3-gap", + admin: "bi bi-window-sidebar", dream: "bi bi-grid-3x3-gap", space: "bi bi-grid-3x3-gap", desktop: "bi bi-window-desktop", configs: "bi bi-gear", conf: "bi bi-gear", logs: "bi bi-calendar4-week", sso: "bi bi-shield-check", login: "bi bi-person-check", start: "bi bi-play-circle", stop: "bi bi-stop-circle", diff --git a/frame.js b/frame.js index 6b3c9abb..4fa263b6 100644 --- a/frame.js +++ b/frame.js @@ -125,7 +125,9 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { Option: function(key, value) { value && (value = can.user.trans(sub, value, null, html.INPUT)); return can.page.SelectArgs(can, option, key, value)[0] }, Update: function(event, cmds, cb, silent) { event = event||{} event.metaKey && sub.request(event, {metaKey: ice.TRUE}) - sub.request(event, can.core.Value(sub, "sub.db._checkbox"))._caller() + sub.request(event)._caller() + var msg = sub.request(event), list = can.core.Value(sub, "sub.db._checkbox") + can.core.Item(list, function(key, value) { msg.Option(key, value) }) if (event.isTrusted && cmds && cmds.length > 0 && cmds[0] == ctx.ACTION) { can.onengine.signal(can, "onrecord", can.request({}, {cmds: [sub.ConfSpace(), sub.ConfIndex()].concat(cmds||[])})) } @@ -264,7 +266,7 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { }) }, _output: function(can, msg, display, cb, output, status, action) { display = display||chat.PLUGIN_TABLE_JS, output = output||can._output - if (msg.IsErr()) { return can.user.toast(can, msg.Result()) } + if (msg.IsErr()) { return can.user.toastFailure(can, msg.Result()) } can.misc.Search(can, log.DEBUG) == ice.TRUE && can.base.beginWith(display, "/require/src/") && delete(Volcanos.meta.cache[display]) Volcanos(display, {_root: can._root, _follow: can.core.Keys(can._follow, display), _fields: can._target, _target: output, _path: display||chat.PLUGIN_TABLE_JS, _legend: can._legend, _option: can._option, _action: action||can._action, _output: output, _status: status||can._status, @@ -495,7 +497,7 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { can.core.List(list, function(target) { can.onappend.style(can, "icons", target); var _icon = can.Conf("_icons."+target.name)||icon[target.name] if (target.name == mdb.DELETE) { _icon = icon.trash } can.page.insertBefore(can, [{icon: _icon, title: can.user.trans(can, target.name), onclick: target.onclick||function(event) { - can.Update(request(event), [ctx.ACTION, target.name]), can.onkeymap.prevent(event) + can.Update(request(event)._event, [ctx.ACTION, target.name]), can.onkeymap.prevent(event) }}], target.nextSibling, target.parentNode) }) can.page.SelectOne(can, target, html.SPAN, function(span) { can.core.List(span.style, function(key) { target.style[key] = span.style[key] }) }) @@ -522,7 +524,13 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { }) } else if (text.indexOf(" 0) { can.page.Select(can, code, html.SVG, function(target) { can.page.style(can, target, html.MIN_HEIGHT, can.ConfHeight(), html.MIN_WIDTH, can.ConfWidth()) }) } else { can.page.Select(can, code, html.INPUT_BUTTON, function(target) { - target.onclick = function(event) { can.misc.Event(event, can, function(msg) { can.run(can.request(event, can.Option()), [ctx.ACTION, target.name]) }) } + target.onclick = function(event) { + if (can.page.ClassList.has(can, target, "disable")) { return } can.page.ClassList.add(can, target, "disable") + can.misc.Event(event, can, function(msg) { can.Update(can.request(event, can.Option()), [ctx.ACTION, target.name], function(msg) { + can.page.ClassList.del(can, target, "disable") + var sup = can._fields? can.sup: can; if (sup.onimport._process(sup, msg)) { return } + }) }) + } }) } return code.scrollBy && code.scrollBy(0, 10000), code }, tools: function(can, msg, cb, target) { can.onimport.tool(can, can.base.Obj(msg.Option(ice.MSG_TOOLKIT))||[], cb, target) }, @@ -959,7 +967,13 @@ Volcanos(chat.ONMOTION, {_init: function(can, target) { }, orderShow: function(can, target, key) { if (can.user.isMobile) { return } var list = can.page.SelectChild(can, target, key||html.DIV_ITEM, function(target) { can.page.style(can, target, html.VISIBILITY, html.HIDDEN); return target }) - can.core.Next(list, function(target, next) { can.page.style(can, target, html.VISIBILITY, ""), can.onmotion.delay(can, next, list.length > 3? 80: 0) }) + can.core.Next(list, function(target, next, index) { + if (index < 30) { + can.page.style(can, target, html.VISIBILITY, ""), can.onmotion.delay(can, next, list.length > 3? 80: 0) + } else { + can.core.List(list, function(target) { can.page.style(can, target, html.VISIBILITY, "") }) + } + }) }, slideGrow: function(can, target) { if (can.page.tagis(target, html.DIV) && can.page.ClassList.has(can, target, html.INPUT)) { return } diff --git a/index.css b/index.css index 123233f4..1fd4c810 100644 --- a/index.css +++ b/index.css @@ -40,7 +40,8 @@ body { --code-bg-color:black; --code-fg-color:silver; --code-border-color:var(--notice-bg-color); --body-font-family:sans-serif; --code-font-family:monospace; --svg-font-family:var(--code-font-family); --legend-font-family:var(--input-font-family); --status-font-family:var(--body-font-family); - --input-font-family:cursive; --table-font-family:var(--body-font-family); + /* --input-font-family:cursive; --table-font-family:var(--body-font-family); */ + --input-font-family:cursive; --table-font-family:var(--code-font-family); --body-font-size:16px; --legend-font-size:20px; --icon-font-size:20px; --code-font-size:14px; --code-line-height:24px; --code-tabs-height:48px; @@ -158,7 +159,7 @@ fieldset>div.action div.item.select.cmds { border-bottom:var(--notice-bg-color) fieldset>div.output { width:100%; } fieldset>div.status { width:100%; } fieldset.input>legend { display:none; } fieldset.input.key div.action { display:none; } -fieldset.input.key div.output table.content { width:100%; } +fieldset.input.key div.output table.content { width:100%; font-family:var(--code-font-family); } fieldset.input.key>div.output>div.item:not(.hide) { display:flex; align-items:center; } fieldset.input.key>div.output>div.item img { height:var(--header-height); width:var(--header-height); } fieldset.input.key div.status { background-color:var(--plugin-bg-color); } @@ -181,12 +182,13 @@ fieldset.input.float { padding:0; border-radius:0 !important; z-index:100; } fieldset.input.float table.content td { padding:var(--input-padding); } fieldset.input.float table.content th { padding:var(--input-padding); } /* float */ +input.disable { color:var(--disable-fg-color) !important; border:unset !important; } body div.float { padding:var(--plugin-padding); box-shadow:var(--box-shadow); } body>div.toast div.title { color:var(--notice-bg-color); font-style:italic; white-space:pre; max-width:280px; overflow:auto; float:left; cursor:copy; } body>div.toast div.delete { color:var(--notice-bg-color); float:right; cursor:pointer; } body>div.toast div.delete:hover { background-color:var(--hover-bg-color); } body>div.toast div.duration { color:var(--disable-fg-color); float:right; } -body>div.toast div.content { color:var(--notice-bg-color); text-align:center; min-height:48px; margin-bottom:5px; } +body>div.toast div.content { color:var(--notice-bg-color); white-space:normal; text-align:center; min-height:48px; margin-bottom:5px; display:block; } body>div.toast div.progress { border:var(--box-notice); margin-left:0px; height:20px; clear:both; } body>div.toast div.progress div.current { background-color:var(--progress-bg-color); height:18px; } body>div.toast div.action:not(.hide) { width:100%; display:block; display:flex; flex-direction:row-reverse; gap:10px; } @@ -266,6 +268,7 @@ div.story[data-type=spark] { padding:var(--input-padding) var(--table-padding); fieldset>div.action>div.tabs { font-style:italic; padding:var(--input-padding) var(--button-padding); margin-left:var(--input-margin); box-shadow:var(--box-shadow); height:var(--action-height); } fieldset>div.action>div.cmds { font-style:italic; padding:var(--input-padding) var(--button-padding); margin-left:var(--input-margin); box-shadow:var(--box-shadow); height:var(--action-height); } fieldset>div.output>div.code { font-size:var(--code-font-size); } +fieldset.plug>div.status { height:31px; } fieldset>div.status { font-family:var(--status-font-family); font-size:var(--status-font-size); font-style:italic; line-height:20px; max-height:var(--action-height); } fieldset>div.status>div.item { padding:var(--input-padding); height:31px; } fieldset>div.status>div.item>label { font-size:var(--status-font-size); cursor:pointer; } @@ -291,8 +294,6 @@ body.windows form.option>div.item.icon.delete { line-height:31px; display:flex; body.windows form.option>div.item.icon.menu { font-size:22px; line-height:32px; } body.windows form.option>div.item.icon.refresh { font-size:24px; line-height:28px; } body.windows form.option>div.item.icon.goback { font-size:24px; line-height:28px; } -body.mobile form.option>div.item.icon.prev { margin-top:4px; height:28px; } -body.mobile form.option>div.item.icon.next { margin-top:4px; height:28px; } div.item.text { position:relative; } div.item.text>input { width:var(--input-width); height:var(--action-height); } div.item.text.id>input { width:var(--button-width); } diff --git a/lib/misc.js b/lib/misc.js index 444f2d1f..c6a3e8db 100644 --- a/lib/misc.js +++ b/lib/misc.js @@ -78,9 +78,7 @@ Volcanos("misc", { Defer: function(cb) { msg._defer = msg._defer||[] if (arguments.length == 0) { msg._defer = can.core.List(msg._defer.reverse(), function(cb) { can.base.isFunc(cb) && cb() }) } else { msg._defer.push(cb) } }, - IsErr: function() { - return msg.result && msg.result[0] == "warn: " - }, + IsErr: function() { return msg.result && msg.result[0] == "warn: " }, _caller: function(skip) { msg.Option("log.caller") || msg.Option("log.caller", can.misc.fileLine((skip||2)+3).link); return msg }, isDebug: function() { return msg.Option(log.DEBUG) == ice.TRUE }, }); return msg }, diff --git a/lib/user.js b/lib/user.js index 12fe49e7..b3fd4e90 100644 --- a/lib/user.js +++ b/lib/user.js @@ -48,8 +48,7 @@ Volcanos("user", { if (location.search.indexOf("debug=true") > 0 && url.indexOf("debug=true") == -1) { var ls = url.split("#"); ls[0] += (ls[0].indexOf("?") > 0? "&": "?") + "debug=true", url = ls.join("#") } - if (window.open(url)) { return } - this.isMobile? location.href = url: null + window.open(url) || (location.href = url) }, close: function(url) { return window.close() }, theme: function(can, name) { can.base.isString(name) && (name = [name]) || name || [] @@ -83,7 +82,7 @@ Volcanos("user", { }, toastProcess: function(can, content, title, progress) { return can.user.toast(can, {content: "🕑 "+(content||ice.PROCESS), title: title, duration: -1, progress: progress, caller: 2}) }, toastSuccess: function(can, content, title) { return can.user.toast(can, {content: "✅ "+(content||ice.SUCCESS), title: title, caller: 2}) }, - toastFailure: function(can, content, title) { return can.user.toast(can, {content: "❌ "+(content||ice.FAILURE), title: title, duration: 10000, caller: 2}) }, + toastFailure: function(can, content, title) { return can.user.toast(can, {content: "❌ "+(content||ice.FAILURE), title: title, duration: 30000, caller: 2}) }, toast: function(can, content, title, duration, progress, caller) { content = {"success": "✅ success", "failure": "❌ failure", "process": "🕑 process"}[content]||content var meta = can.base.isObject(content)? content: {content: content, duration: duration, progress: progress, caller: caller} diff --git a/panel/action.js b/panel/action.js index dcc158d4..bc16e69c 100644 --- a/panel/action.js +++ b/panel/action.js @@ -32,8 +32,8 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) { var river = can.Conf(chat.R }, }) Volcanos(chat.ONACTION, {_init: function(can, target) { can.db.list = can.misc.SearchHash(can) - can.Conf(html.MARGIN_Y, 2*html.PLUGIN_PADDING+2*html.PLUGIN_MARGIN+html.ACTION_HEIGHT) - can.Conf(html.MARGIN_X, 2*html.PLUGIN_PADDING+2*html.PLUGIN_MARGIN) + can.db.list.length == 0 && can.misc.Search(can, chat.RIVER) && can.misc.Search(can, chat.STORM) && (can.db.list = [can.misc.Search(can, chat.RIVER), can.misc.Search(can, chat.STORM)]) + can.Conf(html.MARGIN_X, 2*html.PLUGIN_PADDING+2*html.PLUGIN_MARGIN), can.Conf(html.MARGIN_Y, 2*html.PLUGIN_PADDING+2*html.PLUGIN_MARGIN+html.ACTION_HEIGHT) can.core.List(["ontouchstart", "ontouchmove", "ontouchend"], function(item) { can.onengine.listen(can, item, function(event, msg) { can.onaction[item](event, can), can.onengine.signal(can, chat.ONACTION_TOUCH, msg) }, target) }) diff --git a/panel/footer.js b/panel/footer.js index 1c389edc..862f9fdd 100644 --- a/panel/footer.js +++ b/panel/footer.js @@ -70,7 +70,6 @@ Volcanos(chat.ONACTION, {_init: function(can) {}, }) }) }, }) Volcanos(chat.ONEXPORT, {list: [NTIP, NLOG, NCMD, NKEY, html.WIDTH, html.HEIGHT, nfs.VERSION], - // height: function(can) { return can._target.offsetHeight }, height: function(can) { can.onexport._float(can, html.HEIGHT, "can.view") }, width: function(can) { can.onexport._float(can, html.WIDTH, "can.data") }, ntip: function(can) { can.onexport._float(can, NTIP, "can.toast") }, diff --git a/panel/river.js b/panel/river.js index 26659d5d..57780a26 100644 --- a/panel/river.js +++ b/panel/river.js @@ -6,7 +6,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) { can.onimport._main(can, msg }, _main: function(can, msg) { can.ui = {river_list: {}, storm_list: {}, sublist: {}} var ls = can.misc.SearchHash(can); msg.Table(function(item) { item.main && (can._main_river = item.hash) }) - can._main_river = ls[0]||can.misc.SearchOrConf(can, chat.RIVER)||msg.Option(ice.MSG_RIVER)||can._main_river||(can.user.info.nodetype == web.WORKER? "product": "project") + can._main_river = ls[0]||can.misc.SearchOrConf(can, chat.RIVER)||msg.Option(ice.MSG_RIVER)||can._main_river||(can.user.info.nodetype == web.WORKER || can.misc.Search(can, ice.MSG_DEBUG) != ice.TRUE? "product": "project") can._main_storm = ls[1]||can.misc.SearchOrConf(can, chat.STORM)||msg.Option(ice.MSG_STORM) }, _river: function(can, meta, cb) { return {view: html.ITEM, title: meta.name, list: [{icon: meta.icon}, {text: meta.name}, {icon: icon.CHEVRON_DOWN}], _init: function(target) { can.ui.river_list[meta.hash] = target, cb(target) }, @@ -61,7 +61,9 @@ Volcanos(chat.ONACTION, {list: [mdb.CREATE, web.SHARE, web.REFRESH], _init: func can.run({}, [river, chat.STORM], function(msg) { var next = can.ui.river_list[river].nextSibling if (msg.Length() == 0) { return can.user.isLocalFile? can.user.toastFailure(can, "miss data"): can.onengine.signal(can, chat.ONACTION_NOSTORM, can.request({}, {river: river})) } can.db.storm_list[river] = msg.Table() - var _main_storm; msg.Table(function(item) { item.main && (_main_storm = item.hash) }), _main_storm = can._main_storm || _main_storm || (can.user.info.nodetype == web.WORKER? "desktop": "studio") + var _main_storm; msg.Table(function(item) { item.main && (_main_storm = item.hash) }), _main_storm = can._main_storm || _main_storm || ( + can.user.info.nodetype == web.WORKER? web.DESKTOP: can.misc.Search(can, ice.MSG_DEBUG) != ice.TRUE? web.DREAM: "studio" + ) var select = 0; list = can.page.Append(can, can._output, [{view: html.LIST, list: msg.Table(function(item, index) { river == can._main_river && (item.hash == _main_storm) && (select = index) return can.onimport._storm(can, item, river) diff --git a/plugin/local/team/plan.css b/plugin/local/team/plan.css index 7223c473..ac31bf63 100644 --- a/plugin/local/team/plan.css +++ b/plugin/local/team/plan.css @@ -16,3 +16,4 @@ fieldset.plan>div.output>div.layout>div.layout>div.content>table.content td div. fieldset.plan>div.output>div.layout>div.layout>div.content>table.content tr:first-child { height:30px; position:sticky; top:2px; } fieldset.plan>div.output>div.layout>div.layout>div.content>table.content th:first-child { width:40px; position:sticky; left:2px; } fieldset.plan>div.output>div.layout>div.layout>div.profile>table.content tr:first-child { height:30px; position:sticky; top:2px; } +fieldset.plan.story>form.option>div.item.scale { display:none; } diff --git a/plugin/local/wiki/word.js b/plugin/local/wiki/word.js index 17b4e7b6..35fe8908 100644 --- a/plugin/local/wiki/word.js +++ b/plugin/local/wiki/word.js @@ -43,12 +43,16 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.Conf(html.PADDI return tabs }); select && select.click() }, - field: function(can, meta, target) { var item = can.base.Obj(meta.meta), width = item.width + field: function(can, meta, target) { var item = can.base.Obj(meta.meta) // if (can.Option(nfs.PATH).indexOf(nfs.DF) > 0) { var ls = can.core.Split(can.Option(nfs.PATH), nfs.DF); item.space = ls[0] } + var padding = 2*can.Conf(html.PADDING); if (can.user.isMobile && !can.isCmdMode()) { padding *= 2 } + if (!item.width || parseInt(item.width) > can.ConfWidth()) { item.width = can.ConfWidth()-padding } + var width = item.width can.onappend.plugin(can, item, function(sub) { can._plugins = (can._plugins||[]).concat([sub]) - sub.onimport.size(sub, can.base.Max(html.STORY_HEIGHT, can.ConfHeight()), sub.Conf("_width", width)||(can.ConfWidth()-2*can.Conf(html.PADDING)), true) + sub.onimport.size(sub, can.base.Max(html.STORY_HEIGHT, can.ConfHeight()), sub.Conf("_width", width), true) var size = sub.onimport.size; sub.onimport.size = function(can, height, width, auto, mode) { size(can, height, width, auto, mode), can.page.style(can, sub._output, html.MAX_HEIGHT, "", "overflow-y", "hidden") } can.core.Value(item, "auto.cmd") && can.onmotion.delay(function() { sub.runAction(sub.request({}, can.core.Value(item, "opts")), can.core.Value(item, "auto.cmd")) }) + can.page.style(can, sub._target, html.WIDTH, width) }, can._output, target) }, table: function(can, meta, target) { diff --git a/plugin/state.js b/plugin/state.js index 12b8054f..ac785716 100644 --- a/plugin/state.js +++ b/plugin/state.js @@ -1,5 +1,7 @@ Volcanos(chat.ONIMPORT, { - _process: function(can, msg) { if (can.onimport[msg.OptionProcess()]) { return can.core.CallFunc([can.onimport, msg.OptionProcess()], {can: can, sub: can.sub, msg: msg, arg: msg.Option("_arg")}), true } }, + _process: function(can, msg) { + if (msg.IsErr()) { can.user.toastFailure(can, msg.Result()); } + if (can.onimport[msg.OptionProcess()]) { return can.core.CallFunc([can.onimport, msg.OptionProcess()], {can: can, sub: can.sub, msg: msg, arg: msg.Option("_arg")}), true } }, _location: function(can, msg, arg) { can.user.jumps(arg) }, _replace: function(can, msg, arg) { location.replace(arg) }, _history: function(can, msg) { history.length == 1? can.user.close(): history.back() }, diff --git a/plugin/story/form.js b/plugin/story/form.js index c649d27c..6e1b490c 100644 --- a/plugin/story/form.js +++ b/plugin/story/form.js @@ -3,10 +3,7 @@ Volcanos(chat.ONIMPORT, { if (can.isCmdMode()) { can.onappend.style(can, html.OUTPUT) } can.page.Append(can, can._output, msg.Table(function(item) { return {view: [[html.ITEM, item.type]], list: [item.type != html.BUTTON && {text: [can.user.trans(can, item.name, item._trans, html.INPUT), "", mdb.NAME]}, item.need == "must" && {text: ["*", "", "need"]}], _init: function(target) { - item.type == html.BUTTON && (item.onclick = function(event) { var args = [] - can.core.Item(can.page.SelectArgs(can, can._output)[0], function(key, value) { args.push(key, value) }) - can.Update(can.request(event, {_handle: ice.TRUE}), [ctx.ACTION, item.name].concat(args)) - }), can.onappend.input(can, item, "", target) + can.onappend.input(can, item, "", target) }, onclick: function(event) { can.page.Select(can, event.currentTarget, html.INPUT, function(target) { target.focus() }) }} })), can.onappend.board(can, msg) }, diff --git a/plugin/table.js b/plugin/table.js index 9be02f4b..97d8df26 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -8,17 +8,6 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.onappend.table(can, msg, null, target), can.onappend.board(can, msg, target), can.onmotion.story.auto(can, target) } }, - __project: function(can, msg) { var select, current = can.sup.db._zone||can.db.hash[0]||ice.DEV - msg.Table(function(value) { - var _target = can.onimport.item(can, value, function(event) { can.isCmdMode()? can.misc.SearchHash(can, value.name): can.sup.db._zone = value.name - if (can.onmotion.cache(can, function() { return value.name }, can.ui.content, can._status)) { return can.onimport.layout(can) } - can.run(can.request(event, {_toast: ice.PROCESS}), [value.name], function(msg) { - can.onimport.__content(can, msg), can.onappend._status(can, msg), can.onimport.layout(can) - }) - }, function() {}, can.ui.project); select = (value.name == current? _target: select)||_target - }), select && select.click(), can.onmotion.orderShow(can, can.ui.project) - can.onappend.style(can, "output card", can.ui.content), can.onmotion.delay(can, function() { can.onimport.layout(can) }) - }, __content: function(can, msg) { can.onimport.card(can, msg) }, card: function(can, msg, target) { target = target||can.ui.content||can._output var list = msg.Table(function(value) { value.icon = value.icon||value.image var img = can.misc.Resource(can, value.icon, value.type == web.MASTER? "": value.name)