diff --git a/frame.js b/frame.js index a954ec87..18526121 100644 --- a/frame.js +++ b/frame.js @@ -94,12 +94,25 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { var option = can.page.Select(can, field, "form.option")[0]; var action = can.page.Select(can, field, "div.action")[0]; var output = can.page.Select(can, field, "div.output")[0]; + var status = can.page.Select(can, field, "div.status")[0]; var feature = can.base.Obj(meta.feature) // 添加插件 var sub = Volcanos(meta.name, { _help: meta.name, _target: field, - _option: option, _action: action, _output: output, _history: [], - _follow: can._follow+"."+meta.name, + _option: option, _action: action, _output: output, + _follow: can._follow+"."+meta.name, _history: [], + Option: function(key, value) { + sub.page.Select(sub, option, "input[name="+key+"]", function(item) { + value == undefined? (value = item.value): (item.value = value) + }) + return value + }, + Status: function(key, value) { + sub.page.Select(sub, status, "div."+key, function(item) { + item.innerHTML = key+": "+value + }) + return value + }, }, [Volcanos.meta.volcano].concat(list), function(sub) { meta.feature = can.base.Obj(meta.feature, {}) meta.detail = meta.feature["detail"] || {} @@ -141,18 +154,38 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { var display = (msg.Option("_display")||feature.display||"table.js") display.indexOf("/") == 0 || (display = "/plugin/"+display) - sub[display] = Volcanos(display, { _target: output, + sub[display] = Volcanos(display, { _help: display, _target: output, _option: option, _action: action, _output: output, _follow: can._follow+"."+meta.name+"."+display, + Option: sub.Option, Status: sub.Status, }, Volcanos.meta.libs.concat(["/frame.js", display]), function(table) { table.Conf(sub.Conf()) table.onimport._init(table, msg, msg.append||[], function() {}, output) table.run = function(event, cmds, cb, silent) { // 组件回调 - cmds[0] == "field"? sub.run(event, cmds.slice(1), cb, silent): - input.run(event, cmds, cb, silent) + cmds[0] == "field"? sub.run(event, cmds.slice(1), cb, silent): input.run(event, cmds, cb, silent) } + + // 工具栏 + action.innerHTML = "", table.onaction && can.core.List(table.onaction.list, function(item) { + can.onappend.input(can, action, "input", {type: "button", value: item, onclick: function(event) { + table.onaction[item](event, table, msg) + }}) + }) + + // 上下文 + table.ondetail && table.ondetail.list && table.ondetail.list.length > 0 && (table._target.oncontextmenu = function(event) { + can.onappend.carte(sub, table.ondetail||{}, msg["_detail"] || sub.Conf("detail"), function(ev, item, meta) { + (table.ondetail[item]||table.onaction[item])(event, table, msg) + }) + }) + + // 状态条 + status.innerHTML = "", table.onexport && can.core.List(table.onexport.list, function(item) { + can.page.Append(can, status, [{view: "item "+item, inner: item, title: item}]) + }) }) + var table = sub[display]; }, silent) } @@ -282,7 +315,7 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { msg.result && can.page.AppendBoard(can, can._output, can.page.Display(msg.Result())) }, - carte: function(can, meta, list, cb) { + carte: function(can, meta, list, cb) { list = list && list.length > 0? list: meta.list; if (list.length == 0) { return } can._carte = can._carte || can.page.Append(can, can._target, [{view: "carte", onmouseleave: function(event) { can.page.Modify(can, can._carte, {style: {display: "none"}}) }}]).last diff --git a/index.css b/index.css index 85d44f69..dbb6741c 100644 --- a/index.css +++ b/index.css @@ -71,6 +71,16 @@ fieldset>form.option>div.item.textarea { clear:both; } +fieldset>div.action { + clear:both; +} +fieldset>div.action>div.item { + float:left; +} +fieldset>div.status>div.item { + float:left; +} + fieldset div.output { margin-top:4px; clear:both; diff --git a/plugin/inner.css b/plugin/inner.css new file mode 100644 index 00000000..8573e490 --- /dev/null +++ b/plugin/inner.css @@ -0,0 +1,43 @@ +fieldset.editor>div.output textarea.editor { + font-family:monospace; + background-color:black; + color:white; + border:solid 1px red; + padding:0; + width:0; + height:20px; + margin:0; + position:relative; + float:right; +} +fieldset.editor>div.output div.lineno { + font-family:monospace; + float:left; +} +fieldset.editor>div.output div.lineno>div.item { + text-align:right; + border:solid 1px black; + padding:0 4px; + height:20px; + margin:0; +} +fieldset.editor>div.output div.lineno>div.item:hover { + background-color:green; +} +fieldset.editor>div.output div.lineno>div.item.select { + background-color:red; +} +fieldset.editor>div.output div.content { + font-family:monospace; + border-left:solid 2px red; + padding-left:10px; +} +fieldset.editor>div.output div.content>pre.item { + border:solid 1px black; + padding:0; + height:20px; + margin:0; +} +fieldset.editor>div.output div.content>pre.item:hover { + background-color:green; +} diff --git a/plugin/inner.js b/plugin/inner.js new file mode 100644 index 00000000..ab86991f --- /dev/null +++ b/plugin/inner.js @@ -0,0 +1,112 @@ +Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, target) { target.innerHTML = ""; + can.onappend.table(can, target, "table", msg); + + can.ui = can.page.Append(can, target, [{view: ["editor", "textarea"], onkeydown: function(event) { + (can.onkeymap[can.mode][event.key]||function() {})(event, can) + }, onkeyup: function(event) { + + }, onblur: function(event) { + can.onaction.modifyLine(can, can.current, can.editor.value) + }}, {view: "lineno", style: {width: "30px"}}, {view: "content", style: {"margin-left": "30px"}}, ]); + + can.max = 0, can.ls = msg.Result().split("\n"); + can.editor = can.ui.editor, can.mode = "modify"; + can.core.List(can.ls, function(item) { can.onaction.appendLine(can, item) }); + return typeof cb == "function" && cb(msg); + }, +}, ["/plugin/inner.css"]) +Volcanos("onkeymap", {help: "键盘交互", list: ["modify", "normal"], + modify: { + ArrowDown: function(event, can) { + can.onaction.selectLine(can, can.current.nextSibling) + }, + ArrowUp: function(event, can) { + can.onaction.selectLine(can, can.current.previousSibling) + }, + Enter: function(event, can) { + can.onaction.modifyLine(can, can.current, can.editor.value) + can.onaction.insertLine(can, can.current, event.shiftKey).click() + event.stopPropagation() + event.preventDefault() + }, + Backspace: function(event, can) { + can.editor.selectionStart == 0 && can.onaction.mergeLine(can, can.current.previousSibling).click() + }, + }, +}) +Volcanos("onaction", {help: "控件交互", list: ["保存", "提交"], + modifyLine: function(can, target, value) { + target.innerHTML = value + }, + deleteLine: function(can, target) { + can.page.Remove(can, target) + }, + selectLine: function(can, target) { + can.page.Select(can, can.ui.content, "pre.item", function(item, index) { + if (item != target && index != target) { return } + can.Status("当前行", index+1) && can.page.Select(can, can.ui.lineno, "div.item", function(item, i) { + can.page.ClassList.del(can, item, "select") + index == i && can.page.ClassList.add(can, item, "select") + }) + }) + + can.current = target, can.page.Modify(can, can.editor, {value: can.current.innerText, style: { + height: target.offsetHeight+"px", width: target.offsetWidth+"px", + top: (target.offsetTop-can._output.offsetTop)+"px", + }}), can.editor.focus(); + }, + appendLine: function(can, value) { var index = can.max++; + can.page.Append(can, can.ui.lineno, [{view: ["item", "div", can.Status("总行数", index+1)], onclick: function(event) { + can.onaction.selectLine(can, index) + }}]) + return can.page.Append(can, can.ui.content, [{view: ["item", "pre", value||""], onclick: function(event) { + can.onaction.selectLine(can, event.target) + }}]).last + }, + insertLine: function(can, target, before) { + var line = can.onaction.appendLine(can) + can.ui.content.insertBefore(line, before && target || target.nextSibling) + return line + }, + mergeLine: function(can, target) { + can.ondetail.modifyLine(can, target, target.innerHTML + target.nextSibling.innerHTML); + can.ondetail.deleteLine(can, target.nextSibling); + return target + }, + + remote: function(event, can, msg, key) { + msg = can.request(event), msg.Option("content", can.onexport.content(can)) + can.run(event, ["action", key, can.Option("path")], function(res) { + }, true) + }, + "保存": function(event, can, msg) { + can.onaction.remote(event, can, msg, "保存") + }, + "提交": function(event, can, msg) { + can.onaction.remote(event, can, msg, "提交") + }, +}) +Volcanos("ondetail", {help: "菜单交互", list: ["删除行", "合并行", "插入行", "添加行", "追加行"], + "删除行": function(event, can, msg) { + can.onaction.delteLine(can, can.current) + }, + "合并行": function(event, can, msg) { + can.onaction.mergeLine(can, can.current) + }, + "插入行": function(event, can, msg) { + can.onaction.insertLine(can, can.current, true) + }, + "添加行": function(event, can, msg) { + can.onaction.insertLine(can, can.current, false) + }, + "追加行": function(event, can, msg) { + can.onaction.appendLine(can) + }, +}) +Volcanos("onexport", {help: "导出数据", list: ["当前行", "总行数"], + content: function(can) { + return can.page.Select(can, can._output, "div.content>pre.item", function(item) { + return can.current == item? can.editor.value: item.innerText + }).join("\n") + }, +}) diff --git a/plugin/local/wiki/word.js b/plugin/local/wiki/word.js index cd5c10c7..ee0c8148 100644 --- a/plugin/local/wiki/word.js +++ b/plugin/local/wiki/word.js @@ -18,7 +18,7 @@ Volcanos("onimport", {help: "导入数据", list: [], can.page.Select(can, can._output, "fieldset.story", function(item) {var data = item.dataset var meta = JSON.parse(data.meta||"{}") - can.onappend._init(can, meta, Config.libs.concat(["plugin/state.js"]), function(sub) { + can.onappend._init(can, meta, Volcanos.meta.libs.concat(["plugin/state.js"]), function(sub) { sub.run = function(event, cmds, cb, silent) { can.run(event, ["field", "action", "story", data.type, data.name, data.text].concat(cmds), cb, silent) } diff --git a/plugin/table.js b/plugin/table.js index 292dc4a6..d198cdf5 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -11,5 +11,3 @@ Volcanos("onaction", {help: "控件交互", list: [], }, }) - -