diff --git a/frame.js b/frame.js index fdfe2044..ed6e214d 100644 --- a/frame.js +++ b/frame.js @@ -601,7 +601,7 @@ Volcanos(chat.ONLAYOUT, {help: "页面布局", _init: function(can, target) { ta Volcanos(chat.ONMOTION, {help: "动态特效", _init: function(can, target) { window.addEventListener(html.ORIENTATIONCHANGE, function(event) { can.onengine.signal(can, html.ORIENTATIONCHANGE) }) window.onresize = function(event) { - window.setsize(window.innerWidth, window.innerHeight) + window.setsize && window.setsize(window.innerWidth, window.innerHeight) can.onengine.signal(can, chat.ONRESIZE) } can.onmotion.float.auto(can, target) diff --git a/lib/user.js b/lib/user.js index 654fb5e6..97292967 100644 --- a/lib/user.js +++ b/lib/user.js @@ -280,7 +280,7 @@ Volcanos("user", {help: "用户操作", info: {}, agent: { item._init = function(target) { item._enter = function(event) { action.submit(event, can, "submit") } - item.run = function(event, cmds, cb) { + item.run = item.run||function(event, cmds, cb) { var _msg = can.request(event, {_handle: ice.TRUE, action: msg.Option(html.ACTION)}, msg, can.Option()) can.page.Select(can, ui.table, html.OPTION_ARGS, function(item) { item.name && item.value && _msg.Option(item.name, item.value) diff --git a/page/index.css b/page/index.css index 4a6f8962..3a7876ac 100644 --- a/page/index.css +++ b/page/index.css @@ -67,6 +67,7 @@ fieldset.plug>form.option input[type=button][name=close]{ display:block; } fieldset.plugin>div.status { border-top:1px solid darkcyan; height:30px; } fieldset.story>div.status { border-top:1px solid darkcyan; } +fieldset.output { padding:0; margin:0; } fieldset.output>form.option { display:none; } fieldset.output>div.action { display:none; } fieldset.output>div.status { display:none; } diff --git a/plugin/local/code/inner.js b/plugin/local/code/inner.js index 12dec87a..34982284 100644 --- a/plugin/local/code/inner.js +++ b/plugin/local/code/inner.js @@ -309,7 +309,7 @@ Volcanos(chat.ONACTION, {help: "控件交互", _trans: {link: "链接", width: " case nfs.LINE: return can.onaction.selectLine(can, parseInt(ls[1])), can.current.scroll(can.current.scroll()-4) default: can.core.List(can.sup.paths, function(path) { if (list[0].indexOf(path) == 0) { can.onimport.tabview(can, path, list[0].slice(path.length)) } }) } - })._target, html.LEFT, can.ui.project.offsetWidth+can.ui.content.offsetWidth/4-34, html.TOP, can.ui.content.offsetHeight/4) + })._target, html.LEFT, can.ui.project.offsetWidth+can.ui.content.offsetWidth/4-34, html.TOP, can.ui.content.offsetHeight/4, html.RIGHT, "") }, show: function(event, can) { if (can.base.Ext(can.Option(nfs.FILE)) == nfs.JS) { delete(Volcanos.meta.cache[can.base.Path("/require/", can.Option(nfs.PATH), can.Option(nfs.FILE))]) } diff --git a/plugin/local/code/vimer.js b/plugin/local/code/vimer.js index e0bf6567..653f3e30 100644 --- a/plugin/local/code/vimer.js +++ b/plugin/local/code/vimer.js @@ -223,8 +223,10 @@ Volcanos(chat.ONKEYMAP, {help: "键盘交互", var rest = can.onkeymap.deleteText(target, target.selectionEnd), text = can.ui.current.value var left = text.substr(0, text.indexOf(text.trimLeft()))||(text.trimRight() == ""? text: "") text && can.core.List(["{}", "[]", "()"], function(item) { if (can.base.endWith(text, item[0])) { - !can.base.beginWith(rest, item[1]) && (!rest && can.onaction.insertLine(can, left+item[1], can.current.next()), left += ice.TB) - } }); if (can.base.endWith(text, "`") && can.base.count(text, "`")%2==1) { !rest && can.onaction.insertLine(can, left+"`", can.current.next()) } + if (can.base.beginWith(rest, item[1])) { return true } + (!rest && can.onaction.insertLine(can, left+item[1], can.current.next()), left += ice.TB) + } }).length == 0 && rest && ["}", "]", ")"].indexOf(rest[0]) > -1 && (left = left.slice(0, -1)) + if (can.base.endWith(text, "`") && can.base.count(text, "`")%2==1) { !rest && can.onaction.insertLine(can, left+"`", can.current.next()) } var line = can.onaction.insertLine(can, left+rest.trimLeft(), can.current.next()) can.current.text(text.trimRight()||text), can.onaction.selectLine(can, line) can.onkeymap.cursorMove(target, 0, left.length) diff --git a/plugin/local/team/plan.js b/plugin/local/team/plan.js index 7552ebf9..87e3b2d3 100644 --- a/plugin/local/team/plan.js +++ b/plugin/local/team/plan.js @@ -24,9 +24,9 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.onmotion.clear( can.onaction.modifyTask(event, can, task, "begin_time", time+task.begin_time.slice(time.length), task.begin_time) } }, draggable: time != undefined, title: can.onexport.title(can, task), _init: function(target) { var item = can.onimport.item(can, {nick: task.name+ice.DF+task.text}, function() { can.onmotion.delay(can, function() { - can.onmotion.select(can, can.ui.content, html.TD, target.parentNode), can.onimport._profile(can, task) + can.onmotion.select(can, can.ui.content, html.TD, target.parentNode), can.onimport._profile(can, task), can.Status(mdb.COUNT, msg.Length()) }) }, null, can.ui.project); task._target = target, target.onclick = function(event) { item.click() } - can.sup.task = can.sup.task||task, can.sup.task.zone == task.zone && can.sup.task.id == task.id && (can.sup.task._target = target) + can.sup.task && can.sup.task.zone == task.zone && can.sup.task.id == task.id && (can.sup.task._target = target) var ls = can.core.Split(decodeURIComponent(location.hash.slice(1)))||[]; if (ls[0] == task.zone && ls[1] == task.id) { can.sup.task = task } }, } @@ -143,7 +143,9 @@ Volcanos(chat.ONACTION, {list: [mdb.PREV, mdb.NEXT, mdb.INSERT, mdb.EXPORT, mdb. can.runAction(event, mdb.INSERT, [mdb.ZONE, args[1], "begin_time", time].concat(args)) }) }, - modifyTask: function(event, can, task, key, value) { can.runAction(can.request(event, task, can.Option()), mdb.MODIFY, [key, value], function() { can.Update() }) }, + modifyTask: function(event, can, task, key, value) { + can.runAction(can.request(event, task, can.Option()), mdb.MODIFY, [key, value], function() { can.Update() }) + }, _filter: function(event, can, key, value) { var count = 0 if (value == "all") { diff --git a/plugin/local/wiki/data.js b/plugin/local/wiki/data.js index 947bb4a7..f94b8a36 100644 --- a/plugin/local/wiki/data.js +++ b/plugin/local/wiki/data.js @@ -1,8 +1,6 @@ -Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb) { - can.base.isFunc(cb) && cb(msg) - - can.ui = can.onlayout.display(can) - can.table = can.onappend.table(can, msg, function(value, key, index, line) { +Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, target) { can.onmotion.clear(can) + if (can.Option(mdb.TYPE)) { return can.onfigure[can.Option(mdb.TYPE)](can, msg, can.Option("fields")) } + can.ui = can.onlayout.display(can), can.table = can.onappend.table(can, msg, function(value, key, index, line) { return {text: [value, html.TD], oncontextmenu: function(event) { can.user.carte(event, can, can.ondetail, can.ondetail.list, function(ev, cmd, meta) { var cb = meta[cmd]; cb && cb(event, can, cmd, value, key, index, line) @@ -12,10 +10,7 @@ Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb) { }, ondblclick: function(event) { can.page.editable(can, event.target, true) }} - }, can.ui.content) - - can.onappend._status(can, msg.append) - can.onaction._compute(event, can) + }, can.ui.content), can.base.isFunc(cb) && cb(msg), can.onappend._status(can, msg.append), can.onaction._compute(event, can) }, }, [""]) Volcanos(chat.ONFIGURE, {help: "组件菜单", @@ -34,6 +29,18 @@ Volcanos(chat.ONFIGURE, {help: "组件菜单", res[ncol] = res[ncol] / nrow } }, + "折线图": function(can, msg, fields) { + return can.onappend.plugin(can, {type: "output", index: "can.plugin", display: "/plugin/story/trend.js", width: can.ConfWidth(), height: can.ConfHeight()}, function(sub) { + sub.list = can.core.List(can.core.Split(fields), function(field) { return msg.Table(function(item) { return item[field] }) }) + sub.Conf(ice.VIEW, "折线图") + }) + }, + "比例图": function(can, msg, fields) { + return can.onappend.plugin(can, {type: "output", index: "can.plugin", display: "/plugin/story/pie.js", width: can.ConfWidth(), height: can.ConfHeight()}, function(sub) { + sub.list = can.core.List(can.core.Split(fields), function(field) { return msg.Table(function(item) { return item[field] }) }) + sub.__msg = msg, sub.Conf(mdb.FIELD, fields) + }) + }, }) Volcanos(chat.ONACTION, {help: "组件菜单", list: [ice.SAVE, [ice.MODE, "全选", "块选", "反选", "多选", "拖动", "编辑"], [ice.EXEC, "求和", "最大", "最小", "平均"]], _compute: function(event, can) { @@ -50,6 +57,168 @@ Volcanos(chat.ONACTION, {help: "组件菜单", list: [ice.SAVE, [ice.MODE, "全 save: function(event, can, button) { can.runAction(event, button, [can.Option(nfs.PATH), can.onexport.file(can)]) }, exec: function(event, can, button) { can.onaction._compute(event, can) }, + push: function(event, can, button) { + can.user.input(event, can, can.page.Select(can, can._output, ["table.content", "tr>th"], function(th, index) { return {name: th.innerText, run: function(event, cmds, cb) { + var msg = can.request(event); can.page.Select(can, can._output, ["table.content", "tr"], function(tr, order) { order != 0 && msg.Push(mdb.VALUE, tr.children[index].innerText) }), cb(msg) + }} }), function(list) { can.run(can.request(event, {_handle: true}), [button, can.Option(nfs.PATH)].concat(list), function() { can.Update() }) }) + }, + draw: function(event, can, button) { + can.user.input(event, can, [["type", "折线图", "比例图"], {name: "fields", run: function(event, cmds, cb) { + var msg = can.request(event); can.page.Select(can, can._output, ["table.content", "tr>th"], function(th) { msg.Push(mdb.VALUE, th.innerText) }), cb(msg) + }}], function(list) { can.onfigure[list[0]](can, can._msg, list[1]) }) + }, + + _foreach: function(can, button, cb) { + button && can.Action(ice.MODE, button) + can.page.Select(can, can.ui.content, html.TR, function(item) { + cb(item) + }) + }, + + "全选": function(event, can, button) { + can.onaction._foreach(can, button, function(item) { + can.page.editable(can, item, false) + can.page.draggable(can, item, false) + item.onmouseenter = null, item.onclick = null + can.page.ClassList.del(can, item, html.SELECT) + can.page.ClassList.del(can, item, "over") + }) + can.onaction._compute(event, can) + }, + "块选": function(event, can, button) { + can.onaction._foreach(can, button, function(item) { + item.onmouseenter = function() { + can.page.ClassList.add(can, item, html.SELECT) + can.onaction._compute(event, can) + } + }) + }, + "反选": function(event, can, button) { + can.onaction._foreach(can, button, function(item) { + item.onmouseenter = function() { + can.page.ClassList.del(can, item, html.SELECT) + can.onaction._compute(event, can) + } + }) + }, + "多选": function(event, can, button) { + can.onaction._foreach(can, button, function(item) { + item.onmouseenter = function() {} + item.onclick = function() { + can.page.ClassList.neg(can, item, html.SELECT) + can.onaction._compute(event, can) + } + }) + }, + "拖动": function(event, can, button) { + can.onaction["全选"](event, can, button) + can.onaction._foreach(can, "", function(item) { + can.page.draggable(can, item, true) + item.ondragstart = function(event) { can.drag = item } + item.ondragover = function(event) { event.preventDefault(), can.page.ClassList.add(can, item, "over")} + item.ondragleave = function(event) { can.page.ClassList.del(can, item, "over") } + item.ondrop = function(event) { event.preventDefault() + can.page.Select(can, can.ui.content, html.TABLE, function(table) { + table.insertBefore(can.drag, item) + }) + } + }) + }, + "编辑": function(event, can, button) { + can.onaction._foreach(can, button, function(item) { + can.page.editable(can, item, true) + }) + }, +}) +Volcanos(chat.ONDETAIL, {help: "组件详情", list: ["复制", "删除"], + "复制": function(event, can, button, value, key, index, line) { + var end = can.page.Append(can, can.table, [{type: html.TR, list: can.core.List(can._msg.append, function(key) { + return {text: [line[key], html.TD]} + })}]).tr; can.table.insertBefore(end, event.target.parentNode) + }, + "删除": function(event, can, button) { + can.page.Remove(can, event.target.parentNode) + }, +}) +Volcanos(chat.ONEXPORT, {help: "导出数据", + file: function(can) { + return can.page.Select(can, can.ui.content, html.TR, function(tr) { + return can.page.Select(can, tr, can.page.Keys(html.TH, html.TD), function(td) {return td.innerHTML}).join(ice.FS) + }).join(ice.NL) + }, +}) + +Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, target) { can.onmotion.clear(can) + if (can.Option(mdb.TYPE)) { return can.onfigure[can.Option(mdb.TYPE)](can, msg, can.Option("fields")) } + can.ui = can.onlayout.display(can), can.table = can.onappend.table(can, msg, function(value, key, index, line) { + return {text: [value, html.TD], oncontextmenu: function(event) { + can.user.carte(event, can, can.ondetail, can.ondetail.list, function(ev, cmd, meta) { + var cb = meta[cmd]; cb && cb(event, can, cmd, value, key, index, line) + }) + }, onclick: function(event) { + key == nfs.PATH && can.run(event, [can.Option(nfs.PATH, value)]) + }, ondblclick: function(event) { + can.page.editable(can, event.target, true) + }} + }, can.ui.content), can.base.isFunc(cb) && cb(msg), can.onappend._status(can, msg.append), can.onaction._compute(event, can) + }, +}, [""]) +Volcanos(chat.ONFIGURE, {help: "组件菜单", + "求和": function(event, can, res, td, index) { + res[index] = parseInt(td.innerText) + (res[index]||0); + }, + "最大": function(event, can, res, td, index) { + (res[index] === undefined || parseInt(td.innerText) > parseInt(res[index])) && (res[index] = parseInt(td.innerText)) + }, + "最小": function(event, can, res, td, index) { + (res[index] === undefined || parseInt(td.innerText) < parseInt(res[index])) && (res[index] = parseInt(td.innerText)) + }, + "平均": function(event, can, res, td, ncol, cols, rows, nrow) { + res[ncol] = parseInt(td.innerText) + (res[ncol]||0); + if (nrow == rows.length - 1) { + res[ncol] = res[ncol] / nrow + } + }, + "折线图": function(can, msg, fields) { + return can.onappend.plugin(can, {type: "output", index: "can.plugin", display: "/plugin/story/trend.js", width: can.ConfWidth(), height: can.ConfHeight()}, function(sub) { + sub.list = can.core.List(can.core.Split(fields), function(field) { return msg.Table(function(item) { return item[field] }) }) + sub.Conf(ice.VIEW, "折线图") + }) + }, + "比例图": function(can, msg, fields) { + return can.onappend.plugin(can, {type: "output", index: "can.plugin", display: "/plugin/story/pie.js", width: can.ConfWidth(), height: can.ConfHeight()}, function(sub) { + sub.list = can.core.List(can.core.Split(fields), function(field) { return msg.Table(function(item) { return item[field] }) }) + sub.__msg = msg, sub.Conf(mdb.FIELD, fields) + }) + }, +}) +Volcanos(chat.ONACTION, {help: "组件菜单", list: [ice.SAVE, [ice.MODE, "全选", "块选", "反选", "多选", "拖动", "编辑"], [ice.EXEC, "求和", "最大", "最小", "平均"]], + _compute: function(event, can) { + var mul = html.TR + (can.Action(ice.MODE) == "全选"? "": ".select") + var method = can.onfigure[can.Action(ice.EXEC)], res = {} + + can.page.Select(can, can.ui.content, mul, function(tr, nrow, rows) { + (mul != html.TR || nrow > 0) && can.page.Select(can, tr, html.TD, function(td, ncol, cols) { + method && method(event, can, res, td, ncol, cols, rows, nrow) + }) + }) + can.core.Item(res, function(key, value) { can.Status(can._msg.append[key], value||"") }) + }, + + save: function(event, can, button) { can.runAction(event, button, [can.Option(nfs.PATH), can.onexport.file(can)]) }, + exec: function(event, can, button) { can.onaction._compute(event, can) }, + draw: function(event, can, button) { + can.user.input(event, can, [{name: "type", values: ["折线图", "比例图"]}, "fields"], function(list) { can.onfigure[list[0]](can, can._msg, list[1]) }) + }, + push: function(event, can, button) { + can.user.input(event, can, can.page.Select(can, can._output, ["table.content", "tr>th"], function(th, index) { return {name: th.innerText, run: function(event, cmds, cb) { + var msg = can.request(event); can.page.Select(can, can._output, ["table.content", "tr"], function(tr, order) { + order != 0 && msg.Push("value", tr.children[index].innerText) + }), cb(msg) + }} }), function(list) { + can.run(can.request(event, {_handle: true}), [button, can.Option(nfs.PATH)].concat(list), function() { can.Update() }) + }) + }, _foreach: function(can, button, cb) { button && can.Action(ice.MODE, button) diff --git a/plugin/story/pie.js b/plugin/story/pie.js index d8f19bd5..8c4f8643 100644 --- a/plugin/story/pie.js +++ b/plugin/story/pie.js @@ -2,7 +2,7 @@ Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, tar var color = [cli.RED, cli.YELLOW, cli.GREEN, cli.CYAN, cli.BLUE, cli.PURPLE] var color = ["#3300FF", "#2196F3", "#4CAF50", "#CDDC39", "#FFEB3B", "#9C27B0", "#795548", "#607D8B", "#CC33FF"] var height = msg.Option(html.HEIGHT)||can.ConfHeight() - + msg = can.sup.__msg||msg can.page.ClassList.add(can, can._fields, "draw"), can.onmotion.hidden(can, can._action) can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() { can.onimport._show(can, msg) var margin = height/8, r = height/2-margin; can.svg.Val(html.WIDTH, 2*(r+margin)), can.svg.Val(html.HEIGHT, 2*(r+margin)) diff --git a/plugin/story/trend.js b/plugin/story/trend.js index 0672e13d..345d1b2e 100644 --- a/plugin/story/trend.js +++ b/plugin/story/trend.js @@ -2,7 +2,9 @@ Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, tar can.onmotion.clear(can), can.page.ClassList.add(can, can._fields, "draw") can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() { can.data = msg.Table(), can.onimport._sum(can) - can.base.isFunc(cb) && cb(msg), can.onimport.layout(can), can.base.isFunc(cb) && cb(msg) + can.base.isFunc(cb) && cb(msg), can.Conf(ice.VIEW) && can.Action(ice.VIEW, can.Conf(ice.VIEW)) + can.list = can.sup.list||can.list + can.onimport.layout(can), can.base.isFunc(cb) && cb(msg) can.data = msg.Table(), can.onimport._sum(can) }) }, @@ -43,13 +45,30 @@ Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, tar layout: function(can) { can.onaction[can.Action(ice.VIEW)]({}, can) }, + transform: function(can, target) { + target.Value("transform", "translate(0, "+parseInt(can.ConfHeight())+") scale(1, -1)") + }, }, [""]) Volcanos(chat.ONACTION, {help: "组件菜单", list: [ - [ice.VIEW, "趋势图", "柱状图", "数据源"], + [ice.VIEW, "趋势图", "柱状图", "折线图", "数据源"], [html.HEIGHT, ice.AUTO, 100, 200, 400, 600, 800, ice.AUTO], ["space", 10, 20, 50, 100], [html.SPEED, 10, 20, 50, 100], ], + "折线图": function(event, can) { var args = can.onimport._layout(can) + var black = can.onimport.group(can, cli.BLACK, kit.Dict(html.STROKE, cli.BLACK, html.FILL, cli.BLACK)) + var white = can.onimport.group(can, cli.WHITE, kit.Dict(html.STROKE, cli.WHITE, html.FILL, cli.WHITE)) + can.onimport.transform(can, black), can.onimport.transform(can, white) + can.core.List(can.list, function(list) { + var max = list[0], min = list[0], step = (can.ConfWidth()-2*args.space)/(list.length-1) + for (var i = 1; i < list.length; i += 1) { if (list[i] > max) { max = list[i] } if (list[i] < min) { min = list[i] } } + function scale(y) { return (y - min)/(max - min)*(args.height-2*args.space)+args.space } + function order(i) { return i*step+args.space } + for (var i = 1; i < list.length; i += 1) { + can.onimport.draw({}, can, {shape: svg.LINE, point: [{x: order(i-1), y: scale(list[i-1])}, {x: order(i), y: scale(list[i])}]}, white) + } + }) + }, "趋势图": function(event, can) { var args = can.onimport._layout(can) function scale(y) { return (y - can.min)/(can.max - can.min)*(args.height-2*args.space) } function order(index, x, y) { return {x: args.space+args.step*index+x, y: args.height-args.space-scale(y)} } diff --git a/proto.js b/proto.js index 3a3bf354..8d7e6610 100644 --- a/proto.js +++ b/proto.js @@ -341,6 +341,7 @@ var Volcanos = shy("火山架", {iceberg: "/chat/", volcano: "/frame.js", pack: for (var i = 0; i < cache.length; i++) { var sub = cache[i], name = sub._name if (typeof each == lang.FUNCTION && each(can, name, sub)) { continue } !can[name] && (can[name] = {}); for (var k in sub) { + if (name == "onimport" && k == "_init") { can[name]["_last_init"] = sub[k] } can[name].hasOwnProperty(k) || !sub.hasOwnProperty(k) || (can[name][k] = sub[k]) } }