diff --git a/frame.js b/frame.js index 4e7e5ee5..ac646ed0 100644 --- a/frame.js +++ b/frame.js @@ -1,6 +1,8 @@ Volcanos("onengine", {help: "解析引擎", list: [], _init: function(can, meta, list, cb, target) { can.core.Next(meta.panes, function(item, next) { item.type = "pane" can.onappend._init(can, item, item.list, function(pane) { + pane.Status = function(key, value) { pane.run({}, ["search", "Footer.onimport."+key, value]) } + pane.onaction && pane.onappend._action(pane, pane._action, item._action||pane.onaction.list) pane.run = function(event, cmds, cb, silent) { var msg = pane.request(event); cmds = cmds || [] return (can.onengine[cmds[0]]||can.onengine[meta.main.engine])(event, can, msg, pane, cmds, function(msg) { @@ -8,17 +10,12 @@ Volcanos("onengine", {help: "解析引擎", list: [], _init: function(can, meta, }) }, can[item.name] = pane, next() }, target) - }, function() { - can.onlayout._init(can, meta, list, function() { - can.onkeypop._init(can) - }, target) - + }, function() { can.onlayout._init(can, target) can.require(meta.main.list, function(can) { var pane = can[meta.main.name], msg = can.request({}) + pane.onkeypop._init(pane, target), pane.onmotion._init(pane) pane.onengine._daemon(pane, pane.user.title()) - pane.onaction._init(pane, msg, [], function(msg) { - typeof cb == "function" && cb(msg) - }, pane._target) + pane.onaction._init(pane, msg, [], cb, pane._target) }) }) }, @@ -447,8 +444,8 @@ Volcanos("onappend", {help: "渲染引擎", list: [], _init: function(can, meta, }, true) }, }, [], function(can) {}) -Volcanos("onlayout", {help: "页面布局", list: [], _init: function(can, meta, list, cb, target) { - if (can.user.Search(can, "share")) { return typeof cb == "function" && cb() } +Volcanos("onlayout", {help: "页面布局", list: [], _init: function(can, target) { + if (can.user.Search(can, "share")) { return } var width = can._width, height = can._height can.page.Select(can, target, "fieldset.head", function(field) { @@ -484,251 +481,158 @@ Volcanos("onlayout", {help: "页面布局", list: [], _init: function(can, meta, } }) }) }) - typeof cb == "function" && cb() }, }) -Volcanos("onkeypop", {help: "键盘交互", list: [], _init: function(can) { - var list = ['q', 'a', 'z', 'w', 's', 'x', 'e', 'd', 'c', 'r', 'f', 'v', 't', 'g', 'b', 'y', 'h', 'n', 'u', 'j', 'm', 'i', 'k', 'o', 'l', 'p']; - var ui = can.page.Append(can, document.body, [{view: "high", list: can.core.List(list, function(c, i) { - return {view: "char "+c, style: {position: "fixed", "bottom": "0", - left: document.body.clientWidth/list.length*i+"px", - width: document.body.clientWidth/list.length+"px", - height: "10px", background: "red", - }} - })}]) - var iu = can.page.Append(can, document.body, [{view: "nice", style: {position: "fixed", top: 40, width: 0, height: 40}}]) - can.core.Timer({interval: 100}, function() { - can.page.Select(can, ui.high, "div.char", function(item) { - item.offsetHeight > -2 && can.page.Modify(can, item, {style: { - height: item.offsetHeight-item.offsetHeight/200-1+"px", - }}) +Volcanos("onkeypop", {help: "键盘交互", list: [], _init: function(can, target) { + can.core.Item(can.onkeypop._mode, function(item, value) { var engine = {} + can.core.Item(value, function(key, cb) { var map = engine + for (var i = key.length-1; i > -1; i--) { + map = map[key[i]] = i == 0? cb: (map[key[i]]||{}) + } + }), can.onkeypop._engine[item] = engine }) - can.page.Select(can, document.body, "div.nice", function(item) { - item.offsetWidth > -2 && can.page.Modify(can, item, {style: { - width: item.offsetWidth-1, left: (document.body.clientWidth-item.offsetWidth-1)/2, - }}) - }) - }) - var count = 0, add = true - can.core.Timer({interval: 100}, function() { - if (add) { - count++ - if (count > 100) { - add = false - } - } else { - count-- - if (count < 0) { - add = true - } + target.onkeydown = function(event) { if (event.target != target) { return } + can.page.Select(can, target, "fieldset.Action>div.output", function(item) { + target._keys = can.onkeypop._parse(event, can, item, "normal", target._keys||[]) + }) } - - can.page.Select(can, document.body, "fieldset.Action fieldset", function(item) { - can.page.Modify(can, item, {style: { - "box-shadow": "40px 10px 10px "+(count/10+1)+"px #626bd0", - }}) - }) - }) - - - document.body.onkeydown = function(event) { if (event.target != document.body) { return } - if (can.onkeypop.action && can.onkeypop.action.onimport) { - can.onkeypop.action.onimport.keydown(event, can.onkeypop.action, event.key) - return + target.onkeyup = function(event) { } - switch (event.key) { - case " ": - break - case "g": - can.page.Select(can, document.body, "fieldset.Action>div.output", function(item) { - item.scrollBy(0, -10000) - }) - break - case "j": - can.page.Select(can, document.body, "fieldset.Action>div.output", function(item) { - item.scrollBy(0, 30) - }) - break - case "f": - can.page.Select(can, document.body, "fieldset.Action>div.output", function(item) { - item.scrollBy(0, 300) - }) - break - case "e": - can.page.Select(can, document.body, "fieldset.Action>div.output", function(item) { - item.scrollBy(0, -30) - }) - break - case "k": - can.page.Select(can, document.body, "fieldset.Action>div.output", function(item) { - item.scrollBy(0, -30) - }) - break - default: - return - } - event.stopPropagation() - event.preventDefault() - } - document.body.onkeyup = function(event) { - } -}, - oninput: function(event, can, local) {var target = event.target - if (event.ctrlKey) { - if (typeof local == "function" && local(event)) { - event.stopPropagation() - event.preventDefault() - return true - } - - var his = target.History || [] - var pos = target.Current || -1 - switch (event.key) { - case "p": - pos = (pos-1+his.length+1) % (his.length+1) - target.value = pos < his.length? his[pos]: "" - target.Current = pos - break - case "n": - pos = (pos+1) % (his.length+1) - target.value = pos < his.length? his[pos]: "" - target.Current = pos - break - case "a": - case "e": - case "f": - case "b": - break - case "h": - can.page.DelText(target, target.selectionStart-1, target.selectionStart) - break - case "d": - can.page.DelText(target, 0, target.selectionStart) - break - case "k": - can.page.DelText(target, target.selectionStart) - break - case "u": - can.page.DelText(target, 0, target.selectionEnd) - break - case "w": - var start = target.selectionStart-2 - var end = target.selectionEnd-1 - for (var i = start; i >= 0; i--) { - if (target.value[end] == " " && target.value[i] != " ") { - break - } - if (target.value[end] != " " && target.value[i] == " ") { - break - } - } - can.page.DelText(target, i+1, end-i) - break - default: - return false - } - } else { - switch (event.key) { - case " ": - event.stopPropagation() - return true - default: - return false - } - } - - event.stopPropagation() - event.preventDefault() - return true }, - action: null, show: function(event, can) { - var key = event.key, map = { - "~": "q", - "`": "q", - "1": "q", - "2": "w", - "3": "e", - "4": "r", - "5": "t", - "6": "y", - "7": "u", - "8": "i", - "9": "o", - "0": "p", - "-": "o", - "=": "p", - "[": "i", - "]": "o", - "\\": "p", - ";": "k", - "'": "l", - ",": "k", - ".": "l", - "/": "p", - }; key = map[key]||key + _parse: function(event, can, target, mode, list) { + event.key.length == 1 && list.push(event.key) + can.Status && can.Status("keys", list.join("")) - key = key >= 'a' && key <= 'z'? key: 'a' + parseInt(Math.random()*26) - var some = 0.8 - can.page.Select(can, document.body, "div.char."+key, function(item) { - can.page.Modify(can, item, {style: { - background: "rgba("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+some+")", - height: item.offsetHeight+100+"px", - }}) - }) - can.page.Select(can, document.body, "div.nice", function(item) { - can.page.Modify(can, item, {style: { - background: "rgba("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+some+")", - width: item.offsetWidth 1) { + repeat(cb, count); return list + } + + var map = can.onkeypop._engine[mode]; for (var i = list.length-1; i > pre-1; i--) { + var cb = map[list[i]]; switch (typeof cb) { + case "function": repeat(cb, count); return list + case "object": map = cb; continue + case "string": + default: return list + } + } + return list + }, + _mode: { + normal: { + j: function(event, can, target) { target.scrollBy(0, 30) }, + k: function(event, can, target) { target.scrollBy(0, -30) }, + hello: function(event, can, target) { can.base.Log("nice") }, + + " ": function(event, can, target) { + can.page.Select(can, document.body, "fieldset.pane.Header div.search input", function(target) { + target.focus() + }) + }, + enter: function(event, can, target) { can.base.Log("enter") }, + escape: function(event, can, target) { + can.run(event, ["search", "Search.onaction.hide"]) + can.base.Log("enter") + }, + }, + insert: { + escape: function(event, can, target) { + target.blur() + }, + jk: function(event, can, target) { + can.page.DelText(target, target.selectionStart-1, target.selectionStart) + target.blur() + }, + enter: function(event, can, target) { + var his = target._history || [] + his.push(target.value) + + can.base.Log("input", target, his) + target.setSelectionRange(0, -1) + target._current = his.length + target._history = his + }, + }, + insert_ctrl: { + p: function(event, can, target) { + var his = target._history||[] + var pos = target._current||0 + + pos = --pos % (his.length+1) + if (pos < 0) { pos = his.length} + target.value = his[pos]||"" + can.base.Log(pos, his) + + target._current = pos + }, + n: function(event, can, target) { + var his = target._history||[] + var pos = target._current||0 + + pos = ++pos % (his.length+1) + target.value = his[pos]||"" + can.base.Log(pos, his) + + target._current = pos + }, + + u: function(event, can, target) { + can.page.DelText(target, 0, target.selectionEnd) + }, + k: function(event, can, target) { + can.page.DelText(target, target.selectionStart) + }, + h: function(event, can, target) { + can.page.DelText(target, target.selectionStart-1, target.selectionStart) + }, + d: function(event, can, target) { + can.page.DelText(target, 0, target.selectionStart) + }, + w: function(event, can, target) { + var start = target.selectionStart-2 + var end = target.selectionEnd-1 + for (var i = start; i >= 0; i--) { + if (target.value[end] == " " && target.value[i] != " ") { + break + } + if (target.value[end] != " " && target.value[i] == " ") { + break + } + } + can.page.DelText(target, i+1, end-i) + }, + }, + }, _engine: {}, + + input: function(event, can, local) { var target = event.target + target._keys = can.onkeypop._parse(event, can, target, event.ctrlKey? "insert_ctrl": "insert", target._keys||[]) + if (target._keys.length == 0) { event.stopPropagation(), event.preventDefault() } + }, +}) Volcanos("onmotion", {help: "动态交互", list: [], _init: function(can) { + var count = 0, add = true + can.user.isMobile || can.core.Timer({interval: 100}, function() { + add? count++: count-- + count < 0 && (add = true) + count > 100 && (add = false) + + can.page.Select(can, document.body, "fieldset.story", function(item) { + can.page.Modify(can, item, {style: { + "box-shadow": "40px 10px 10px "+(count/10+1)+"px #626bd0", + }}) + }) + }) }, modifys: function(can, target, cb) { var back = target.innerHTML var ui = can.page.Appends(can, target, [{type: "textarea", value: back, style: {height: "80px"}, onkeydown: function(event) { diff --git a/index.js b/index.js index 43bb354b..1b4af85f 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ Volcanos({name: "chat", iceberg: "/chat/", volcano: "/frame.js", {name: "Search", help: "搜索框", pos: "float"}, {name: "River", help: "群聊组", pos: "left"}, {name: "Action", help: "工作台", pos: "middle"}, - {name: "Footer", help: "状态条", pos: "foot", state: ["ncmd"]}, + {name: "Footer", help: "状态条", pos: "foot", state: ["ncmd", "keys"]}, ], main: {name: "Header", engine: "remote", list: ["publish/order.js"]}, plugin: [ "/plugin/state.js", "/plugin/input.js", diff --git a/lib/base.js b/lib/base.js index ae31e5fc..4e624305 100644 --- a/lib/base.js +++ b/lib/base.js @@ -98,5 +98,25 @@ Volcanos("base", {help: "基础模块", } return parseInt(size) }, + + _fileLine: function() { var obj = {}; Error.captureStackTrace(obj, arguments.callee); return obj.stack; }, + FileLine: function(depth) { return this._fileLine().split("\n")[1+depth].trim() }, + Log: function() { + var args = [this.Time(), this.FileLine(2, 3).split("/").slice(3).slice(-length).join("/") ] + for (var i in arguments) { args.push(arguments[i]) } + console.log.apply(console, args) + }, + Logs: function() { + var args = [this.Time()] + for (var i in arguments) { args.push(arguments[i]) } + args.push(this.FileLine(2, 3)) + console.log.apply(console, args) + }, + Error: function() { + var args = [this.Time()] + for (var i in arguments) { args.push(arguments[i]) } + args.push("\n", this._fileLine().split("\n").slice(2).join("\n")) + console.log.apply(console, args) + }, }) diff --git a/lib/core.js b/lib/core.js index a8ab054a..076e5604 100644 --- a/lib/core.js +++ b/lib/core.js @@ -164,5 +164,6 @@ Volcanos("core", {help: "核心模块", } return obj === other }, + }) diff --git a/pane/Footer.js b/pane/Footer.js index 0162bcff..bac4c3e6 100644 --- a/pane/Footer.js +++ b/pane/Footer.js @@ -17,6 +17,12 @@ Volcanos("onimport", {help: "导入数据", list: [], _init: function(can, msg, }) }, + keys: function(can, msg, list, cb, target) { + can.page.Select(can, target, "span.keys", function(item) { + item.innerHTML = list[0]||"" + }) + typeof cb == "function" && cb(msg) + }, ncmd: function(can, msg, list, cb, target) { can.page.Select(can, target, "span.ncmd", function(item) { item.innerHTML = can.Conf("ncmd", parseInt(can.Conf("ncmd")||"0")+1+"")+"" diff --git a/pane/Header.js b/pane/Header.js index 933154eb..1fe0f3f1 100644 --- a/pane/Header.js +++ b/pane/Header.js @@ -17,8 +17,10 @@ Volcanos("onimport", {help: "导入数据", list: [], _init: function(can, msg, }, _search: function(can, msg, target) { can.user.isMobile || (can.search = can.page.Append(can, target, [{view: "search", list: [{type: "input", data: {placeholder: "search"}, onkeydown: function(event) { + can.onkeypop.input(event, can) + switch (event.key) { - case "Enter": can.run(event, ["search", "Search.onimport.input", "*", event.target.value]); break + case "Enter": can.run(event, ["search", "Search.onimport.select", "*", event.target.value]); break } }, }], }]).input) diff --git a/pane/Search.js b/pane/Search.js index 245f84dc..685e99c2 100644 --- a/pane/Search.js +++ b/pane/Search.js @@ -1,32 +1,79 @@ Volcanos("onimport", {help: "导入数据", list: [], _init: function(can, msg, list, cb, target) { typeof cb == "function" && cb(msg) }, + _table: function(can, msg, fields, search) { + can.onappend.table(can, msg, can.ui.content, "table", function(value, key, index, line) { + can.Status("count", index+1) + + return {text: [value, "td"], onclick: function(event) { + if (line.type == "fieldset") { + can.page.Select(can, document.body, "fieldset.pane.Action fieldset.plugin>legend", function(item) { + if (item.innerHTML == line.name) { + var cb = can.page.Select(can, item.parentNode, "input.args")[0] + can.onmotion.hide(can) + cb && cb.focus() + } + }) + } + + can.page.Append(can, can.ui.table, [{td: can.core.List(fields, function(item) { + return line[item] + }), data: {index: index}, onclick: function(event) { + can.page.Remove(can, event.target.parentNode) + can.Status("selected", can.page.Select(can, can.ui.table, "tr").length-1) + }}]) + can.Status("selected", can.page.Select(can, can.ui.table, "tr").length-1) + }} + }) + }, select: function(can, msg, cmd, cb) { can.onmotion.clear(can) var fields = (msg.Option("fields")||"pod,ctx,cmd,type,name,text").split(",") function search(word, cb) { cmd[1] = word - var msg = can.request({}, {fields: fields.join(",")}) - can.run(msg._event, cmd, function(msg) { can.onmotion.clear(can, can.ui.content) - can.onappend.table(can, msg, can.ui.content, "table", function(value, key, index, line) { - can.Status("count", index+1) - - return {text: [value, "td"], onclick: function(event) { - can.page.Append(can, can.ui.table, [{td: can.core.List(fields, function(item) { - return line[item] - }), data: {index: index}, onclick: function(event) { - can.page.Remove(can, event.target.parentNode) - can.Status("selected", can.page.Select(can, can.ui.table, "tr").length-1) - }}]) - can.Status("selected", can.page.Select(can, can.ui.table, "tr").length-1) - }} + if (word == "" && can.list[0] && can.list[0].type == "fieldset") { + can.page.Select(can, document.body, "fieldset.pane.Action fieldset.plugin>legend", function(item) { + if (item.innerHTML == can.list[0].name) { + var cb = can.page.Select(can, item.parentNode, "input.args")[0] + can.onmotion.hide(can) + cb && cb.focus() + } }) + return + } + + var msg = can.request({}, {fields: fields.join(",")}) + can.page.Select(can, document.body, "fieldset.pane.Action fieldset.plugin>legend", function(item) { + if (item.innerHTML.indexOf(word) == -1) { return } + + can.core.List(fields, function(key) { + switch (key) { + case "type": + msg.Push(key, "fieldset") + break + case "name": + msg.Push(key, item.innerHTML) + break + default: + msg.Push(key, "") + } + }) + }) + can.onmotion.clear(can, can.ui.content) + can.run(msg._event, cmd, function(msg) { + can.list = msg.Table() + can.onimport._table(can, msg, fields, search) typeof cb == "function" && cb(msg) }) } can.ui = can.page.Append(can, can._output, [ - {input: ["word", function(event) { + {input: ["word", function(event) { var target = event.target + can.onkeypop.input(event, can, target) + if (event.key == "Escape") { + can.onmotion.hide(can) + } + if (event.key == "Enter") { search(event.target.value, function(msg) { var list = can.page.Select(can, can.ui.content, "tr"); if (list.length == 2) { list[1].firstChild.click(); event.target.setSelectionRange(0, -1) @@ -52,6 +99,8 @@ Volcanos("onaction", {help: "交互操作", list: ["关闭", "清空", "完成"] "关闭": function(event, can) { can.onmotion.hide(can) }, "清空": function(event, can) { can.onmotion.clear(can) }, "完成": function(event, can) { typeof can.cb == "function" && can.cb() }, + + hide: function(can, msg, cmd, cb) { can.onmotion.hide(can) }, }) Volcanos("onexport", {help: "导出数据", list: ["selected", "count"]}) diff --git a/plugin/input.js b/plugin/input.js index c03bebba..741d2bba 100644 --- a/plugin/input.js +++ b/plugin/input.js @@ -78,7 +78,8 @@ Volcanos("onaction", {help: "控件交互", list: [], _init: function(can, meta, // 通用回调 if (can.Conf("type") == "button") { can.run(event, [name].concat(can.sup.Pack())) } }, - onkeydown: function(event, can) { + onkeydown: function(event, can) { var target = event.target + can.onkeypop.input(event, can, target) switch (event.key) { case "Enter": if (can.Conf("type") == "text") { event.target.setSelectionRange(0, -1), can.run(event) } diff --git a/proto.js b/proto.js index 7e177bed..223889ae 100644 --- a/proto.js +++ b/proto.js @@ -17,6 +17,7 @@ var Volcanos = shy("火山架", {libs: [], cache: {}, index: 1}, [], function(na meta.volcano = Config.volcano, meta.libs = Config.libs var Preload = Config.libs; Config.panes.forEach(function(pane) { Preload = Preload.concat(pane.list = pane.list || ["/pane/"+pane.name+".css", "/pane/"+pane.name+".js"]) + Preload = Preload.concat(pane.list = pane.list || ["/pane/"+pane.name+".js"]) }); Preload = Preload.concat(Config.plugin) name = Config.name, can = { _follow: Config.name, @@ -24,7 +25,7 @@ var Volcanos = shy("火山架", {libs: [], cache: {}, index: 1}, [], function(na _target: document.body, _head: document.head, _body: document.body, }, libs = Preload.concat(Config.volcano), cb = function(can) { can.onengine._init(can, can.Conf(Config), [], function(msg) { - console.log(can) + can.base.Log(can) }, can._target) } }