diff --git a/frame.js b/frame.js index fc8f58c8..61be66c9 100644 --- a/frame.js +++ b/frame.js @@ -439,7 +439,9 @@ Volcanos(chat.ONAPPEND, { input: function(can, item, value, target, style) { if (["_space"].indexOf(item.view) > -1) { return can.page.Append(can, target, [item]) } if ([html.BR, html.HR].indexOf(item.type) > -1) { return can.page.Append(can, target, [item]) } + var selectonly = false; if (item.type == html.SELECT) { if (!item.list || item.list.length == 0) { selectonly = true, item.type = html.TEXT } } var _icon = [], _item = can.base.Copy({className: "", type: "", name: ""}, item), input = can.page.input(can, _item, value) + if (selectonly) { input._selectonly = true } if (item.type == html.SELECT) { can.core.List(input.list, function(item) { item.inner = can.user.trans(can, item.inner, item._trans, html.INPUT) }) item.icon = item.icon||icon[item.name] @@ -614,8 +616,12 @@ Volcanos(chat.ONAPPEND, { if (msg.append[msg.append.length-1] == ctx.ACTION && (!msg[ctx.ACTION] || msg[ctx.ACTION].length == 0)) { msg.append.pop() } var option = can.core.Item(can.Option()) var table = can.page.AppendTable(can, msg, target||can.ui.content||can._output, msg.append, cb||function(value, key, index, data, list) { var _value = value - if (msg.append.length == 2 && msg.append[0] == mdb.KEY && msg.append[1] == mdb.VALUE) { - if (key == mdb.VALUE) { key = data.key } data = {}, can.core.List(list, function(item) { data[item.key] = item.value }) + if (msg.IsDetail()) { + if (key == mdb.VALUE) { key = data.key } data = {}, can.core.List(list, function(item) { + data[item.key] = item.value + }) + if (can.user.isMobile && key == "key" && !data[value]) { return } + if (can.user.isMobile && key != "key" && !data[key]) { return } } function request(event) { delete(data.action); return can.request(event, data, can.Option()) } function run(event, cmd, arg) { can.misc.Event(event, can, function(msg) { can.run(request(event), [ctx.ACTION, cmd].concat(arg)) }) } @@ -654,7 +660,6 @@ Volcanos(chat.ONAPPEND, { } } if (key == mdb.STATUS && value) { _value = can.user.trans(can, value, "", key) } - if (key == ctx.ACTION && !value && msg.IsDetail()) { return } return {className: option.indexOf(key) > -1? ice.MSG_OPTION: key == ctx.ACTION? ctx.ACTION: "", text: [ msg.IsDetail() && key == mdb.KEY? can.user.trans(can, _value, null, html.INPUT): can.user.trans(can, _value, null, "value."+key), html.TD, ], onclick: function(event) { if (onclick()) { return } var target = event.target @@ -665,6 +670,7 @@ Volcanos(chat.ONAPPEND, { can.sup.onimport.change(event, can.sup, key, value, null, data) || can.sup.onexport.record(can.sup, value, key, data, event) } }, ondblclick: function(event) { if (can.base.isIn(key, mdb.KEY, mdb.HASH, mdb.ID)) { return } + if (can.user.isMobile) { return } var item = can.core.List(can.Conf([ctx.FEATURE, mdb.INSERT]), function(item) { if (item.name == key) { return item } })[0]||{name: key, value: value} item.run = function(event, cmds, cb) { can.run(request(event), cmds, cb, true) } item._enter = function(event, value) { if (event.ctrlKey) { run(event, mdb.MODIFY, [key, value.trimRight()]) } } @@ -1251,30 +1257,25 @@ Volcanos(chat.ONMOTION, { }, slideAction: function(can, target) { var action = can.page.Select(can, target.parentNode, html.DIV_ACTION)[0] - var beginY, beginX, beginLeft, max = can.base.Max(action.offsetWidth, 120, 60) - target.addEventListener("touchstart", function(event) { max = can.base.Max(action.offsetWidth, 120, 60) + var beginY, beginX, beginLeft, max = can.base.Max(action.offsetWidth, 200, 60) + target.addEventListener("touchstart", function(event) { max = can.base.Max(action.offsetWidth, 200, 60) beginY = event.touches[0].clientY, beginX = event.touches[0].clientX, beginLeft = parseFloat(target.style.left)||0 }) target.addEventListener("touchmove", function(event) { if (Math.abs(event.touches[0].clientY - beginY) > Math.abs(event.touches[0].clientX - beginX)) { return } - var left = event.touches[0].clientX - beginX + beginLeft - target._left = left + var left = event.touches[0].clientX - beginX + beginLeft; target._left = left if (left < 0 && left > -max) { can.page.style(can, event.currentTarget, {left: left}) } can.onmotion.select(can, target.parentNode.parentNode, html.DIV_ITEM, target.parentNode) can.onkeymap.prevent(event) }) - target.addEventListener("touchend", function(event) { - var left = target._left + target.addEventListener("touchend", function(event) { var left = target._left if (left < -max/2) { can.page.style(can, event.currentTarget, {left: -max}) } else { can.page.style(can, event.currentTarget, {left: 0}) } can.page.Select(can, target.parentNode.parentNode, html.DIV_ITEM+">div.output", function(_target) { - if (_target != target) { - can.page.style(can, _target, {left: 0}) - _target._left = 0 - } + if (_target != target) { can.page.style(can, _target, {left: 0}), _target._left = 0 } }) }) }, diff --git a/index.css b/index.css index b00e1989..ffe55371 100644 --- a/index.css +++ b/index.css @@ -157,6 +157,7 @@ body.mobile table.content.checkbox th:first-child { padding:var(--table-padding) body.mobile table.content.checkbox td:first-child { padding:var(--table-padding) var(--input-padding); } body.mobile table.content.action th:last-child { padding:var(--table-padding) var(--input-padding); } body.mobile table.content.action td:last-child { padding:var(--table-padding) var(--input-padding); } +body.mobile table.content.detail thead { display:none; } table.content input { border:none; background-color:var(--th-bg-color); padding:var(--input-padding); } table.content input:not(:last-child) { margin-right:var(--input-margin); } body:not(.mobile) fieldset.Action:not(.tabview):not(.horizon):not(.grid) fieldset.plugin:not(.float):not(.full):not(.cmd)>div.output>table.content td i { display:none; } @@ -185,18 +186,23 @@ div.output.card>div.item>div.title>div.title>span.exists { color:var(--notice-bg div.output.card>div.item>div.title>img { height:var(--header-height); width:var(--header-height); margin:0; float:left; } div.output.card>div.item>div.title>img.jpg { padding:var(--input-padding); } div.item.card { position:relative; display:flex; align-items:center; padding:0; } -div.item.card img { height:40px; } +div.output>div.item.card { border:solid 5px var(--plugin-bg-color); } +div.item.card img { height:40px; width:40px; margin:5px; } div.item.card div.info { width:100%; } div.item.card div.title { font-size:16px; } div.item.card div.title span { margin-right:5px; } div.item.card div.title span.type { border:var(--box-notice); color:var(--notice-bg-color); font-size:12px; padding:0 5px; margin-left:5px; } div.item.card div.title span.role { border:var(--box-notice); color:var(--notice-bg-color); font-size:12px; padding:0 5px; margin-left:5px; } +div.item.card div.title span.status { border:var(--box-notice); color:var(--notice-bg-color); font-size:12px; padding:0 5px; margin-left:5px; } div.item.card div.status { font-size:12px; color:gray; } div.item.card div.status span { margin-right:5px; } div.item.card div.action { height:40px; } div.item.card div.action { position:absolute; right:0; } -div.item.card div.output { padding:10px 0; width:100%; display:flex; transition:left .2s; } -div.item.card div.output { background-color:var(--output-bg-color); } +div.item.card div.action input[type=button] { border:none; margin-left:5px; } +div.item.card div.action input[type=button]:last-child { margin-right:5px; } +div.item.card div.output { padding:10px 0; display:flex; transition:left .2s; } +body.mobile div.item.card div.output { width:100%; } +body.mobile div.item.card div.output { background-color:var(--output-bg-color); } div.item.card.select div.title { font-weight:bold; } div.item.card.select div.output { transition:left .5s; } div.item img[src*=".ico"] { padding:3px; } @@ -345,6 +351,7 @@ fieldset.input.date>div.output td span.lunar.fest { color:red; } fieldset.input.date>div.output td { cursor:pointer; } fieldset.input.date>div.status { text-align:center; border-top:unset; } fieldset.input.date>div.status>div.today { padding:var(--input-padding); } +body.mobile fieldset.input.date { left:25px !important; } fieldset.input.float { border-radius:0; padding:0; } fieldset.input.float table.content th { padding:var(--input-padding); } fieldset.input.float table.content td { padding:var(--input-padding); } @@ -388,10 +395,11 @@ body>div.input { padding:var(--plugin-padding); } body>div.input>legend { background-color:var(--input-bg-color); float:right; padding:0; } body>div.input tr { margin:var(--button-margin); } body>div.input td { padding:var(--table-padding); } +body>div.input td span.must { color:red; padding:0 5px; } body>div.input td:nth-child(2) { padding:var(--table-padding) 0; } body.mobile>div.input tr { display:flex; flex-direction:column; margin:var(--button-margin); } body.mobile>div.input td { padding:0 var(--button-padding); margin:var(--button-margin); } -body.mobile>div.input td:nth-child(1) { color:var(--disable-fg-color); font-size:var(--status-font-size); padding-left:var(--button-padding); margin-bottom:0; } +body.mobile>div.input td:nth-child(1) { color:gray; font-size:var(--status-font-size); padding-left:var(--button-padding); margin-bottom:0; } body.mobile>div.input td:nth-child(2) { display:none; } body>div.input tr.img td:last-child>span { display:none; } body>div.input tr.img td:last-child>div.item { width:var(--river-width); flex-wrap:wrap; } @@ -444,6 +452,10 @@ body>div.upload div.output div.progress { background-color:var(--progress-bg-col body>div.upload div.status div.cost { float:left; } body>div.upload div.status div.show { float:right; } body>div.upload div.status div.size { text-align:center; } +body.mobile>div.input { margin:10px; width:calc(100% - 20px); left:0 !important; } +body.mobile>div.input table { width:100%; } +body.mobile>div.input td { padding:0; } +body.mobile>div.input table input { width:100% !important; } /* display */ fieldset:not(.Action) { position:relative; } fieldset>form.option:not(.hide), fieldset>div.action:not(.hide):not(.flex) { display:contents; } .hide, .hidden { display:none; } @@ -512,7 +524,7 @@ table.content td.select { background-color:var(--td-hover-bg-color); color:var(- table.content td i:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } table.content td.action { background-color:var(--th-bg-color); color:var(--th-fg-color); } table.content.checkbox td:first-child { background-color:var(--th-bg-color); } -table.content:hover td.option:not(:hover) { background-color:var(--tr-hover-bg-color); color:var(--hover-fg-color); } +body:not(.mobile) table.content:hover td.option:not(:hover) { background-color:var(--tr-hover-bg-color); color:var(--hover-fg-color); } hr, td.hr { border-bottom:var(--box-border); margin:var(--input-margin); } h1:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } h2:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } @@ -525,8 +537,8 @@ span.item:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-c span.icon:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } body:not(.mobile):not(.pad) div.item:not(.text):hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } div.item.select:not(.button) { background-color:var(--hover-bg-color); color:var(--hover-fg-color); } -div.item.button.danger input:hover[type=button] { background-color:var(--danger-bg-color); color:var(--danger-fg-color); } -div.item.button.notice input:hover[type=button] { background-color:var(--notice-bg-color); color:var(--notice-fg-color); } +body:not(.mobile) div.item.button.danger input:hover[type=button] { background-color:var(--danger-bg-color); color:var(--danger-fg-color); } +body:not(.mobile) div.item.button.notice input:hover[type=button] { background-color:var(--notice-bg-color); color:var(--notice-fg-color); } div.item.button.danger input { border:var(--box-danger); } div.item.button.notice input { border:var(--box-notice); } div.action div.tabs.select { background-color:var(--output-bg-color); border-top:var(--item-notice); } @@ -717,6 +729,7 @@ div.item.text._icon input { padding-left:24px; } div.item.select._icon i:first-child { color:var(--disable-fg-color); position:absolute; left:0; padding:var(--input-padding); } div.item.select._icon:hover i:first-child { color:unset; } div.item.text>input { width:var(--input-width); height:var(--action-height); } +fieldset.story>form.option>div.item.text>input { max-width:100px; } div.item.text.id>input { width:80px; } div.item.text.url>input { width:var(--river-width); } div.item.text.port>input { width:80px; } diff --git a/lib/page.js b/lib/page.js index 232d206b..c22d0fb6 100644 --- a/lib/page.js +++ b/lib/page.js @@ -437,26 +437,6 @@ Volcanos("page", { case html.BUTTON: item.value = item.value||item.name||mdb.LIST; break } return input }, - itemcard: function(can, value, list, cb) { - return {view: [[html.ITEM_CARD]], list: [ - {view: html.ACTION, _init: function(target) { if (!value.action) { return } - target.innerHTML = value.action - can.page.Select(can, target, html.INPUT_BUTTON, function(target) { - var style = can.Conf("_style."+target.name)||can.page.buttonStyle(can, target.name); style && can.onappend.style(can, style, target) - target.onclick = function(event) { can.Update(can.request(event, value), [ctx.ACTION, target.name]) } - }) - }}, - {view: html.OUTPUT, list: [ - {img: can.misc.ResourceIcons(can, value.icons)}, - {view: html.INFO, list: list}, - ], _init: function(target) { if (!value.action) { return } - can.onmotion.slideAction(can, target) - }, onclick: function(event) { - can.onmotion.select(can, event.currentTarget.parentNode.parentNode, html.DIV_ITEM, event.currentTarget.parentNode) - cb && cb(event) - }}, - ]} - }, 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"]} } diff --git a/lib/user.js b/lib/user.js index 4806f205..cc7974cc 100644 --- a/lib/user.js +++ b/lib/user.js @@ -74,6 +74,7 @@ Volcanos("user", { title: function(text) { if (window.webview) { return title(text) } return text && (document.title = text), document.title }, language: function(can) { return (can.misc.SearchOrConf(can, aaa.LANGUAGE)||can.user.info.language||"") }, isEnglish: function(can) { return can.base.isIn(can.core.Split(can.user.language(can).toLowerCase()||"en", "_-.")[0], "en", "en-us") }, + transValue: function(can, value, key) { return can.user.trans(can, value[key], null, "value."+key) }, trans: function(can, text, list, zone) { if (can.base.isNumber(text)) { return text+"" } if (can.user.isEnglish(can)) { return text } if (can.base.isObject(text)) { return can.core.Item(text, function(k, v) { can.core.Value(can._trans, can.core.Keys(zone, k), v) }) } if (can.base.isFunc(text)) { text = text.name||"" } if (list && can.base.isString(list)) { return list } @@ -229,7 +230,10 @@ Volcanos("user", { item.placeholder = can.user.trans(can, item.placeholder||item.name, null, html.INPUT) item.title = can.user.trans(can, item.title||item.placeholder||item.name, null, html.INPUT) return {view: [[item.name, item.type, item.action], html.TR], list: [ - {type: html.TD, list: [{text: [can.user.trans(can, item.name||"", item._trans, html.INPUT), html.LABEL]}]}, {type: html.TD, list: [{text: item.need == "must"? "*": "", style: {color: cli.RED}}]}, + {type: html.TD, list: [ + {text: [can.user.trans(can, item.name||"", item._trans, html.INPUT), html.LABEL]}, + item.need == "must" && {text: ["*", "", "must"]}, + ]}, {type: html.TD, list: []}, {type: html.TD, _init: function(target) { can.onappend.input(can, item, msg.Option(item.name), target) }}, ]} })}]}, html.ACTION, diff --git a/plugin/input/date.js b/plugin/input/date.js index 6a4a0636..5d33f02f 100644 --- a/plugin/input/date.js +++ b/plugin/input/date.js @@ -16,7 +16,6 @@ Volcanos(chat.ONFIGURE, {date: { var ui = can.page.Append(can, can._action, ["time", "date"]) can.onappend._action(can, [cli.CLOSE, [HOUR].concat(can.core.List(24)), [MINUTE].concat(can.core.List(0, 60, 5)), [SECOND].concat(can.core.List(0, 60, 5)), TODAY], ui.time, meta) can.onappend._action(can, [mdb.PREV, [YEAR].concat(can.core.List(now.getFullYear() - 10, now.getFullYear() + 10)), [MONTH].concat(can.core.List(1, 13)), mdb.NEXT], ui.date, meta) - can._table = can.page.Appends(can, can._output, [{view: [chat.CONTENT, html.TABLE], list: [{type: html.TBODY}]}]).tbody target.value == "" && (now.setMinutes(now.getMinutes()>30? 30: 0), now.setSeconds(0)) function show(now) { can.Action(YEAR, now.getFullYear()), can.Action(MONTH, now.getMonth()+1) @@ -26,6 +25,8 @@ Volcanos(chat.ONFIGURE, {date: { return now } show(now), can._show = function(d) { d? _cb(show(now = new Date(now.getTime()+d*24*3600*1000))): _cb(show(now)) } })}, + onfocus: function(event, can, meta, target, cbs, mod) { if (target._selectonly) { target.blur() } }, + onblur: function(event, can, sub, cb, target) { if (target._selectonly) { return } }, onkeydown: function(event, can, meta, cb, target, sub, last) { if (sub && sub.hidden()) { return last(event) } switch (event.key) { case "n": can.page.SelectInput(can, sub._action, mdb.NEXT, function(target) { target.click(), sub._show() }); break case "p": can.page.SelectInput(can, sub._action, mdb.PREV, function(target) { target.click(), sub._show() }); break diff --git a/plugin/input/key.js b/plugin/input/key.js index cc203c02..ca93e8a7 100644 --- a/plugin/input/key.js +++ b/plugin/input/key.js @@ -48,22 +48,23 @@ Volcanos(chat.ONFIGURE, {key: { } can.core.CallFunc([can.oninputs, "_show"], {event: event, can: can, msg: msg, target: target, name: name}) var display = msg.Option(ice.MSG_DISPLAY)? can.base.ParseURL(msg.Option(ice.MSG_DISPLAY)): {name: name} + if (display.title && !msg[display.title]) { display.title = msg.append[1] } display.style && can.core.CallFunc([can.sup.sub, "oninputs", display.style], {event: event, can: can, msg: msg, target: target, name: display.name||name, title: display.title}) can.layout(msg) }, onfocus: function(event, can, meta, target, cbs, mod) { can.onengine.signal(can, "onevent", can.request(event)); meta._force && mod.onclick(event, can, meta, target, cbs) + if (target._selectonly) { can.onmotion.delay(can, function() { target.blur() }) } }, onclick: function(event, can, meta, target, cbs) { can.onengine.signal(can, "onevent", can.request(event)); - (target.value == "" || meta._force) && cbs(function(sub, cb) { if (sub.Status(mdb.TOTAL) > 0) { return } + (target.value == "" || meta._force || target._selectonly) && cbs(function(sub, cb) { if (sub.Status(mdb.TOTAL) > 0) { return } sub.sup = can._fields? can.sup: can meta.msg && meta.msg.Length() > 0? sub._show(sub, meta.msg, cb, target, meta.name): sub._load(event, sub, cb, target, meta.name, target.value) }) }, onblur: function(event, can, sub, cb, target) { if (target._hold) { return } - return - debugger + if (target._selectonly) { return } can.onengine.signal(can, "onevent", can.request(event, {query: can.page.getquery(can, target)+","+target.value})) sub && can.onmotion.delay(can, sub.close, 300) }, diff --git a/plugin/table.js b/plugin/table.js index 1203971b..df70b0ba 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -14,6 +14,26 @@ Volcanos(chat.ONIMPORT, { can.onappend.table(can, msg, null, target), can.onappend.board(can, msg, target), can.onmotion.story.auto(can, target) } cb && cb(msg) }, + itemcard: function(can, value, list, cb) { + return {view: [[html.ITEM_CARD, value._uid? "uid-"+value._uid: ""].concat(value._style||[])], list: [ + {view: html.ACTION, _init: function(target) { if (!value.action) { return } target.innerHTML = value.action + can.page.Select(can, target, html.INPUT_BUTTON, function(target) { + var style = can.Conf("_style."+target.name)||can.page.buttonStyle(can, target.name); style && can.onappend.style(can, style, target) + target.onclick = function(event) { can.onkeymap.prevent(event) + can.Update(can.request(event, value), [ctx.ACTION, target.name]) + } + }) + }}, + {view: html.OUTPUT, list: [ + {img: can.misc.ResourceIcons(can, value.icons)}, {view: html.INFO, list: list}, + ], _init: function(target) { if (!value.action) { return } + can.onmotion.slideAction(can, target) + }}, + ], onclick: function(event) { + can.onmotion.select(can, event.currentTarget.parentNode, html.DIV_ITEM, event.currentTarget) + cb && cb(event) + }} + }, card: function(can, msg, target, filter) { target = target||can.ui.content||can._output can.page.Append(can, target, msg.Table(function(value) { if (filter && filter(value)) { return } var img = can.misc.Resource(can, value.icon = value.icons||value.icon||value.image)