diff --git a/lib/page.js b/lib/page.js index 30000e66..2534fe79 100644 --- a/lib/page.js +++ b/lib/page.js @@ -21,7 +21,7 @@ Volcanos("page", {help: "网页模块", }, }, - Select: shy("选择节点", function(can, obj, key, cb, interval, cbs) { + Select: shy("选择节点", function(can, obj, key, cb, interval, cbs) {if (key == ".") {return []} var item = obj && obj.querySelectorAll(key); return can.core.List(item, cb, interval, cbs); }), @@ -204,19 +204,27 @@ Volcanos("page", {help: "网页模块", ]}]).first; return field.Meta = item, field; }), + AppendBoard: shy("添加控件", function(can, target, inner) { + return can.page.Append(can, target, [{view: ["code", "div", inner]}]).code; + }), AppendTable: shy("添加表格", function(can, target, msg, list, cb, cbs) { if (!msg.append || msg.append.length == 0) {return} var table = can.page.Append(can, target, "table"); var tr = can.page.Append(can, table, "tr", {dataset: {index: -1}}); - can.core.List(list, function(key, index) {can.page.Append(can, tr, "th", key).onclick = function(event) { - var dataset = event.target.dataset; - dataset["sort_asc"] = (dataset["sort_asc"] == "1") ? 0: 1; - can.page.RangeTable(can, table, index, dataset["sort_asc"] == "1"); - }}); + can.core.List(list, function(key, index) { + if (key.indexOf("_") == 0) {return} + can.page.Append(can, tr, "th", key).onclick = function(event) { + var dataset = event.target.dataset; + dataset["sort_asc"] = (dataset["sort_asc"] == "1") ? 0: 1; + can.page.RangeTable(can, table, index, dataset["sort_asc"] == "1"); + } + }); can.page.Append(can, table, can.core.List(msg.Table(), function(line, index) { - return {type: "tr", dataset: {index: index}, list: can.core.List(list, function(key) {var cbcb, cbcbs; + return {type: "tr", dataset: {index: index}, list: can.core.List(list, function(key) { + if (key.indexOf("_") == 0) {return} + var cbcb, cbcbs; typeof cb == "function" && (cbcb = function(event) {cb(event, line[key], key, index, event.target.parentNode, event.target)}); typeof cbs == "function" && (cbcbs = function(event) { cbs(event, line[key], key, index, event.target.parentNode, event.target); @@ -278,9 +286,6 @@ Volcanos("page", {help: "网页模块", }) }, - AppendBoard: shy("添加控件", function(can, target, inner) { - return can.page.Append(can, target, [{view: ["code", "div", inner]}]).code; - }), AppendFigure: shy("添加控件", function(event, can, cmd, name) {if (can.figure) {return} return can.figure = can.page.Append(can, document.body, [{view: ["input "+cmd+" "+name, "fieldset"], style: { position: "absolute", left: event.clientX+"px", top: event.clientY+10+"px", @@ -289,9 +294,11 @@ Volcanos("page", {help: "网页模块", can.page.Remove(can, can.figure.first); delete(can.figure); }}]) }), + AppendStruct: shy("添加控件", function(event, can, cmd, name) { + }), AppendAction: shy("添加控件", function(can, action, list, cb) { return can.page.Append(can, action, can.core.List(list, function(line) { - return line.type == "br"? line: {view: "item", list: [typeof line == "string"? {button: [line, cb]}: line.length > 0? {select: [line, cb]}: + return ["br", "hr"].indexOf(line.type) > -1? line: {view: "item", list: [typeof line == "string"? {button: [line, cb]}: line.length > 0? {select: [line, cb]}: line.input && typeof line.input != "string" ? {input: [line.input[0], function(event) { typeof line.input[1] == "function" && line.input[1](event, can) }, function(event) { @@ -414,24 +421,60 @@ Volcanos("page", {help: "网页模块", return true }, - Prepos: function(event, item, p) { - p = p || item.getBoundingClientRect(); + Anchor: function(event, target, pos, point) { + switch (pos) { + case 1: + case 2: + case 3: + point.y = target.Val("y") + break + case 4: + case 5: + case 6: + point.y = target.Val("y") + target.Val("height") / 2 + break + case 7: + case 8: + case 9: + point.y = target.Val("y") + target.Val("height") + break + } - var pos = 1; - var y = (event.clientY - p.y) / p.height - if (y < 0.2) { - pos += 0; - } else if (y > 0.8) { - pos += 6; - } else { + switch (pos) { + case 1: + case 4: + case 7: + point.x = target.Val("x") + break + case 2: + case 5: + case 8: + point.x = target.Val("x") + target.Val("width") / 2 + break + case 3: + case 6: + case 9: + point.x = target.Val("x") + target.Val("width") + break + } + return point + }, + Prepos: function(event, item, p, q) { + var max = 20 + p = p || item.getBoundingClientRect(); + q = q || {x: event.clientX, y: event.clientY} + + var pos = 5; + var y = (q.y - p.y) / p.height + if (y < 0.2 && q.y - p.y < max) { + pos -= 3; + } else if (y > 0.8 && q.y - p.y - p.height > -max) { pos += 3; } - var x = (event.clientX - p.x) / p.width - if (x < 0.2) { - pos += 0; - } else if (x > 0.8) { - pos += 2; - } else { + var x = (q.x - p.x) / p.width + if (x < 0.2 && q.x - p.x < max) { + pos -= 1; + } else if (x > 0.8 && q.x - p.x - p.width > -max) { pos += 1; } diff --git a/lib/user.js b/lib/user.js index 22310db3..92b7f98d 100644 --- a/lib/user.js +++ b/lib/user.js @@ -1,7 +1,7 @@ Volcanos("user", {help: "用户模块", alert: function(text) {alert(JSON.stringify(text))}, confirm: function(text) {return confirm(JSON.stringify(text))}, - prompt: function(text, cb, def) {(text = prompt(text, def||"")) != undefined && typeof cb == "function" && cb(text); return text}, + prompt: function(text, cb, def, silent) {(text = silent? def: prompt(text, def||"")) != undefined && typeof cb == "function" && cb(text); return text}, reload: function(force) {(force || confirm("重新加载页面?")) && location.reload()}, title: function(text) {document.title = text}, diff --git a/plugin/input/date.js b/plugin/input/date.js index 5516f166..f3618719 100644 --- a/plugin/input/date.js +++ b/plugin/input/date.js @@ -14,7 +14,8 @@ Volcanos("onfigure", {help: "控件详情", list: [], can.now = target.value? new Date(target.value): new Date(); var control = can.page.AppendAction(can, figure.action, ["今天", "随机", ["hour"].concat(can.core.List(24)), ["minute"].concat(can.core.List(0, 60, 5)), ["second"].concat(can.core.List(0, 60, 5)), {view: ["", "br"]}, - {type: "br"}, "上一月", ["year"].concat(can.core.List(can.now.getFullYear() - 20, can.now.getFullYear() + 20)), + {type: "hr", style: {margin: 0}}, {type: "br"}, + "上一月", ["year"].concat(can.core.List(can.now.getFullYear() - 20, can.now.getFullYear() + 20)), ["month"].concat(can.core.List(1, 13)), "下一月", {view: ["", "br"]}, ], function(event, value, cmd) {can.stick = true; // 设置时间 diff --git a/plugin/team/plan.css b/plugin/team/plan.css index e4b8ac0f..d933eba3 100644 --- a/plugin/team/plan.css +++ b/plugin/team/plan.css @@ -1,3 +1,7 @@ +fieldset.item.plan div.output td.over { + border:solid 2px red; +} + fieldset.item.plan div.output div.task.finish { color:red; } diff --git a/plugin/wiki/draw.js b/plugin/wiki/draw.js index 53a16fb1..6740a21d 100644 --- a/plugin/wiki/draw.js +++ b/plugin/wiki/draw.js @@ -28,6 +28,7 @@ Volcanos("onimport", {help: "导入数据", list: [], can.point = [], can.keys = [] can.current = null, can.temp = null can.group = null, can.svg = null + can.last = null // 加载绘图 var code = can.page.AppendBoard(can, output, msg.Result()||can.Export(event, null, "file")) @@ -44,7 +45,7 @@ Volcanos("onimport", {help: "导入数据", list: [], can.page.Select(can, svg, "*", function(item, index) { // 元素 can.onaction.init(event, can, msg, index, item); - item.tagName == "g" && list.push(item.Value("class")); + item.tagName == "g" && item.Value("class") != "" && list.push(item.Value("class")); }) }) @@ -60,7 +61,7 @@ Volcanos("onimport", {help: "导入数据", list: [], can.point = can.point.slice(0, -1) }, keydown: function(event, can, value) { - if (["Shift", "Control", "Meta", "Alt"].indexOf(value) > -1 ) {return} + if (["Control", "Shift", "Meta", "Alt"].indexOf(value) > -1 ) {return} can.keys.push((event.ctrlKey? "C-": "") + (event.shiftKey? value.toUpperCase(): value)) var list = { @@ -220,7 +221,7 @@ Volcanos("onfigure", {help: "图形绘制", list: [], size: {x: "x", y: "y"}, copy: ["inner"], }, // hi - draw: function(event, can, point, style) {if (point.length < 1) {return} + draw: function(event, can, point, style) {if (point.length < 1 || event.type == "mousemove") {return} var p0 = point[0]; var data = { "x": p0.x, "y": p0.y, @@ -238,17 +239,19 @@ Volcanos("onfigure", {help: "图形绘制", list: [], copy: ["x1", "y1", "x2", "y2"], x: function(event, can, value, cmd, target) { if (value != undefined) { - var offset = value - target.Val("xx", value) + var offset = value - target.Val("xx") target.Val("x1", target.Val("x1") + offset) - target.Val("x2", target.Val("x2") + offset) + // target.Val("x2", target.Val("x2") + offset) + target.Val("xx", value) } return target.Val("xx") }, y: function(event, can, value, cmd, target) { if (value != undefined) { - var offset = value - target.Val("yy", value) + var offset = value - target.Val("yy") target.Val("y1", target.Val("y1") + offset) - target.Val("y2", target.Val("y2") + offset) + // target.Val("y2", target.Val("y2") + offset) + target.Val("yy", value) } return target.Val("yy") }, @@ -259,6 +262,15 @@ Volcanos("onfigure", {help: "图形绘制", list: [], return value != undefined && target.Val("y2", target.Val("y1") + parseInt(value)), target.Val("y2") - target.Val("y1") }, }, // + grid: function(event, can, point) {var target = event.target + if (event.target == can.svg) {return} + var pos = can.page.Prepos(event, target) + var p = point[point.length-1] + p.target = target + p.anchor = pos + target.Val && can.page.Anchor(event, target, pos, p) + return point + }, draw: function(event, can, point) {if (point.length < 2) {return} var p0 = point[0], p1 = point[1]; var data = { @@ -411,6 +423,32 @@ Volcanos("onfigure", {help: "图形绘制", list: [], }, }, + think: { + data: { + rx: 4, ry: 4, + size: {x: "x", y: "y"}, + copy: ["width", "height", "rx", "ry"], + }, // + draw: function(event, can, point) {if (point.length < 2) {return} + can._temp && can.page.Remove(can, can._temp) && delete(can._temp); + can._temp = can.onaction.push(event, can, {}, "g", can.group||can.svg) + var rect = can.onaction.push(event, can, can.onfigure.rect.draw(event, can, point), "rect", can._temp) + if (event.type == "click" && point.length == 2) { + can.ondetail["标签"](event, can, {}, "", rect); + delete(can._temp) + } + return + }, + text: function(event, can, data, target) { + data.x = target.Val("x")+target.Val("width")/2 + data.y = target.Val("y")+target.Val("height")/2 + return data + }, + show: function(event, can, value, target) { + return ": (" + value.Val("x") + "," + value.Val("y") + ")" + + " + (" + value.Val("width") + "," + value.Val("height") + ")" + }, + }, polyline: { data: {}, // draw: function(event, can, point) {if (point.length < 2) {return} @@ -452,8 +490,9 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", ["stroke-width", 1, 2, 3, 4, 5], {text: "c"}, ["stroke", "red", "yellow", "green", "purple", "blue", "cyan", "white", "black"], {text: "f"}, ["fill", "red", "yellow", "green", "purple", "blue", "cyan", "white", "black", "#0000"], - {text: "a"}, ["mode", "run", "draw", "move", "resize", "select", "delete"], - {text: "s"}, ["shape", "rect", "circle", "ellipse", "text", "line", "path", "polyline", "polygon"], + {text: "a"}, ["go", "auto", "manual"], + {text: "a"}, ["mode", "draw", "move", "resize", "select", "delete"], + {text: "s"}, ["shape", "think", "rect", "circle", "ellipse", "text", "line", "path", "polyline", "polygon"], ["grid", 1, 2, 3, 4, 5, 10, 20], ], "保存": function(event, can, msg, cmd, target) { @@ -488,9 +527,6 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", }) }, - _get: function(can, item) { - return can.onfigure[item.getAttribute("name")||item.tagName]; - }, group: function(event, can, value, cmd, target) { if (cmd == "svg") { can.group = can.svg @@ -514,6 +550,12 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", init: function(event, can, msg, cmd, item) { item.Value = function(key, value) { + if (typeof key == "object") { + can.core.Item(key, function(key, value) { + item.Value(key, value) + }) + return + } var figure = can.onaction._get(can, item); key && (key = figure && figure.data && figure.data.size && figure.data.size[key] || key) if (figure && figure.data && typeof figure.data[key] == "function") { @@ -541,11 +583,24 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", push: function(event, can, msg, cmd, target) { var rect = document.createElementNS("http://www.w3.org/2000/svg", cmd); target.appendChild(can.onaction.init(event, can, msg, cmd, rect)); + can.core.Item(msg, function(key, value) { if (key == "inner") {return rect.innerHTML = value} rect.Value(key, value) }); - return rect; + + if (can.point.length == 0) { + var pid = "p"+ can.svg.Val("count", can.svg.Val("count")+1) + rect.Value("class", (rect.Value("class") + " " + rect.Value("pid", pid)).trim()); + } + return can.last = rect; + }, + _get: function(can, item, name) { + return can.onfigure[name||item.getAttribute("name")||item.tagName]; + }, + _ship: function(can, value, target) { + var ship = JSON.parse(target.Value("ship")||"[]").concat([value]) + target.Value("ship", JSON.stringify(ship)) }, _run: function(event, can, target) { var figure = can.onaction._get(can, event.target); @@ -563,19 +618,22 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", return }, _draw: function(event, can, point) { - can.Status(event, null, "width"); - can.Status(event, null, "begin"); - can.Status(event, point[0], "begin") - - var shape = can.page.Select(can, can.action, "select.shape", function(item) {return item.value})[0] + var shape = can.Action("shape"); var figure = can.onfigure[shape]; + figure && figure.grid && figure.grid(event, can, point); var data = figure && figure.draw(event, can, point); - return data && can.onaction.push(event, can, data, figure.data.name||shape, can.group||can.svg) + var obj = data && can.onaction.push(event, can, data, figure.data.name||shape, can.group||can.svg); + + event.type == "click" && obj && can.core.List(point, function(item, index) {if (!item.target) {return} + can.onaction._ship(can, {pid: obj.Value("pid"), which: index, anchor: item.anchor}, item.target) + }) + return obj }, _move: function(event, can, point) { if (point.length == 1) {if (event.type != "click") {return} can.onaction._select(event, can, point) - can.point = point, can.current = {target: can.group} + // can.point = point, can.current = {target: can.group} + can.point = point, can.current = {target: event.target} } else if (point.length == 2) { if (event.type == "click") { return can.point = [], delete(can.current) @@ -586,6 +644,20 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", var figure = can.onaction._get(can, target); if (point.length == 1) { target.style.cursor = "move" + can.current.pos = 5, can.current.begin = can.core.List([target], function(item) { + if (item.tagName == "g") {return} + return target.style.cursor = "move", { + target: item, + x: item.Val("x"), + y: item.Val("y"), + width: item.Val("width"), + height: item.Val("height"), + ship: can.core.List(JSON.parse(item.Value("ship")||"[]"), function(ship) { + return ship.pid && (ship.target = can.page.Select(can, can.svg, "."+ship.pid)[0]) && ship + }) + } + }) + /* can.current.pos = 5, can.current.begin = can.page.Select(can, target, "*", function(item) { if (item.tagName == "g") {return} return target.style.cursor = "move", { @@ -594,13 +666,34 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", y: item.Val("y"), width: item.Val("width"), height: item.Val("height"), + ship: can.core.List(JSON.parse(item.Value("ship")||"[]"), function(ship) { + ship.target = can.page.Select(can, can.svg, "."+ship.pid)[0]; + return ship + }) } }) + */ return } can.core.List(can.current.begin, function(item) { + var figure = can.onaction._get(can, item.target) + can.page.Resizes(event, item.target, item, point[0], point[1], can.current.pos) + can.page.Select(can, can.svg, "."+item.target.Value("text"), function(text) { + text.Value(figure.text(event, can, {}, item.target)) + }) + can.core.List(item.ship, function(ship) { + var p = can.page.Anchor(event, item.target, ship.anchor, {}) + if (ship.which == 0) { + ship.target.Val("x1", p.x) + ship.target.Val("y1", p.y) + } + if (ship.which == 1) { + ship.target.Val("x2", p.x) + ship.target.Val("y2", p.y) + } + }) }) }, _resize: function(event, can, point) { @@ -673,12 +766,11 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", oncontextmenu: function(event, can) {var target = event.target var figure = can.onaction._get(can, target); - can.user.carte(event, shy("", can.ondetail, figure.data.detail || can.ondetail.list, function(event, key, meta) {var cb = meta[key]; typeof cb == "function" && cb(event, can, figure, key, target); }), can), event.stopPropagation(), event.preventDefault() }, - onclick: function(event, can) {if (!can.svg) {return} + onclick: function(event, can) { var p = can.svg.getBoundingClientRect(); var point = {x: event.clientX-p.x, y: event.clientY-p.y}; point.x = point.x - point.x % parseInt(can.Action("grid")); @@ -687,47 +779,80 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空", "删除", can.temp && can.page.Remove(can, can.temp) && delete(can.temp); can.temp = can.onaction["_"+can.Action("mode")](event, can, can.point); - can.point.length == 0 && (can.temp = null) + can.point.length == 0 && delete(can.temp); }, onmouseover: function(event, can) { can.Status(event, event.target, "which") }, onmousemove: function(event, can) { - if (["move", "resize"].indexOf(can.Action("mode"))) { - can.current || can.page.Prepos(event, event.target) - } - var p = can.svg.getBoundingClientRect() var point = {x: event.clientX-p.x, y: event.clientY-p.y} point.x = point.x - point.x % parseInt(can.Action("grid")); point.y = point.y - point.y % parseInt(can.Action("grid")); can.Status(event, point, "point") - can.temp && can.page.Remove(can, can.temp) && delete(can.temp) - can.temp = can.onaction["_"+can.Action("mode")](event, can, can.point.concat(point)) - can.point.length == 0 && (can.temp = null) + var pos = can.page.Prepos(event, event.target) + + if (can.Action("go") == "auto" && can.point.length == 0) { + if (event.target.tagName == "text") { + + } else if (event.target == can.svg) { + if (pos == 5) { + can.Action("mode", "draw") + can.Action("shape", "think") + } else { + can.Action("mode", "resize") + } + } else { + if (pos == 5) { + can.Action("mode", "move") + } else { + can.Action("mode", "draw") + can.Action("shape", "line") + } + } + } + + // if (["move", "resize"].indexOf(can.Action("mode"))) { + // can.current || + // } + + can.temp && can.page.Remove(can, can.temp) && delete(can.temp); + can.temp = can.onaction["_"+can.Action("mode")](event, can, can.point.concat(point)); + can.point.length == 0 && delete(can.temp); }, }) -Volcanos("onchoice", {help: "组件交互", list: ["保存", "添加", "删除"]}) -Volcanos("ondetail", {help: "组件详情", list: ["标签", "编辑", "复制", "运行", "变色", "删除"], +Volcanos("onchoice", {help: "组件交互", list: ["move", "draw", "保存", "添加", "删除"], + "move": function(event, can, msg, cmd, target) { + can.Action("mode", cmd) + }, + "draw": function(event, can, msg, cmd, target) { + can.Action("mode", cmd) + }, +}) +Volcanos("ondetail", {help: "组件详情", list: ["标签", "编辑", "复制", "变色", "运行", "删除"], "标签": function(event, can, value, cmd, target) { + var def = value.def; can.page.Select(can, can.svg, "."+target.Value("text"), function(item) { + def = item.Value("inner") + }) can.user.prompt("文字", function(text) { if (target.tagName == "text") {return target.innerHTML = text} - var data = {} + if (can.page.Select(can, can.svg, "."+target.Value("text"), function(item) { + item.Value("inner", text) + }).length > 0) { + return + } + var figure = can.onaction._get(can, target); - figure.text(event, can, data, target) - - var p = can.onaction.push(event, can, data, "text", target.Group()) - p.innerHTML = text; - - target.Text && can.page.Remove(can, target.Text) && delete(target.Text) - target.Text = p - }, target.Text && target.Text.innerText || "") + var data = figure.text(event, can, {inner: text}, target) + var obj = can.onaction.push(event, can, data, "text", target.Group()) + target.Value("text", obj.Value("pid")) + }, def, value.silent) }, "编辑": function(event, can, value, cmd, target) { var figure = can.onaction._get(can, target); - can.user.input(event, can, can.core.List(["x", "y", "cmd"].concat(figure.data.copy||[]), function(item) { + can.user.input(event, can, can.core.List(["x", "y"].concat(figure.data.copy||[]), function(item) { return {_input: "text", name: item, value: target.Value(item)} }), function(event, cmd, meta, list) { can.core.Item(meta, function(key, value) { @@ -741,7 +866,13 @@ Volcanos("ondetail", {help: "组件详情", list: ["标签", "编辑", "复制", can.core.List(figure.copy, function(item) {data[item] = target.Value(item)}); data[figure.size.x||"x"] = parseInt(target.Value(figure.size.x||"x"))+20; data[figure.size.y||"y"] = parseInt(target.Value(figure.size.y||"y"))+20; - return data && can.onaction.push(event, can, data, target.tagName, can.group||can.svg) + + var p = data && can.onaction.push(event, can, data, target.tagName, can.group||can.svg) + can.page.Select(can, can.svg, "."+target.Value("text"), function(item) { + can.ondetail["标签"](event, can, {silent: true, def: item.Value("inner")}, "", p); + }) + + return p }, "变色": function(event, can, value, cmd, target) { if (target._timer) { @@ -771,7 +902,7 @@ Volcanos("ondetail", {help: "组件详情", list: ["标签", "编辑", "复制", Volcanos("onstatus", {help: "组件状态", list: ["point", "which", "begin", "width", "keys"], "point": function(event, can, value, cmd, target) {target.innerHTML = value.x+","+value.y}, "which": function(event, can, value, cmd, target) { - var figure = can.onaction._get(can, target); + var figure = can.onaction._get(can, value); target.innerHTML = (value.Group && value.Group().Value("class") || "") + " " + value.tagName + " " + ( figure? figure.show(event, can, value, value): "") }, @@ -782,7 +913,7 @@ Volcanos("onstatus", {help: "组件状态", list: ["point", "which", "begin", "w Volcanos("onexport", {help: "导出数据", list: [], file: function(event, can, svg, cmd, target) { return ['', svg? svg.innerHTML: "", ""]).join("") }, diff --git a/proto.js b/proto.js index 287b75ba..ad8df2ca 100644 --- a/proto.js +++ b/proto.js @@ -276,7 +276,7 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块 key? run(event, key, value, can.onaction[key]||can.onaction[value]): run(event, msg, value, can.onaction[value]); }) // 注册菜单 - can.onchice && (can.target.oncontextmenu = function(event) {can.user.carte(event, shy("", can.onchoice, can.onchoice.list, function(event, key, meta) { + can.onchoice && (can.target.oncontextmenu = function(event) {can.user.carte(event, shy("", can.onchoice, can.onchoice.list, function(event, key, meta) { run(event, msg, key, can.onchoice[key] || can.onaction[key]); }), can), event.stopPropagation(), event.preventDefault()})