1
0
mirror of https://shylinux.com/x/volcanos synced 2025-04-25 08:48:06 +08:00
This commit is contained in:
shaoying 2020-02-13 11:36:53 +08:00
parent 3ca7d99f9c
commit 44ea7eeb88
26 changed files with 1269 additions and 342 deletions

View File

@ -1,46 +1,49 @@
var can = Volcanos("chat", {
Page: shy("构造网页", function(can, name, conf, cb, body) {
var page = Volcanos(name, {_type: "local",
var page = Volcanos(name, {_type: "local", _panes: {}, target: body,
Plugin: can.Plugin, Inputs: can.Inputs, Output: can.Output,
Report: function(event, value, key) {
page.Import && page.Import(event, value, key)
can.core.Item(page.panes, function(index, item) {
item.Import && item.Import(event, value, key)
})
},
Import: function(event, value, key) {var cb = page.onimport[key];
typeof cb == "function" && cb(event, page, value, key, body);
},
Report: function(event, value, key) {
page.Import && page.Import(event, value, key)
can.core.Item(page._panes, function(index, item) {
item.Import && item.Import(event, value, key)
})
},
run: function(event, option, cmds, cb) {can.misc.Run(event, page, option, cmds, cb)},
}, Config.libs.concat(["page/"+name]), function(page) {page.Conf(conf);
page.onimport._init && page.onimport._init(page, conf, body)
can.core.Next(conf.pane, function(item, cb) {page.panes = page.panes || {};
page.panes[item.name] = page[item.pos] = page[item.name] = can.Pane(page, item.name, item, cb,
}, Config.libs.concat(["page/"+name]), function(page) {
page.onimport._init && page.onimport._init(page, page.Conf(conf), body)
can.core.Next(conf.pane, function(item, cb) {
page._panes[item.name] = page[item.pos] = page[item.name] = can.Pane(page, item.name, item, cb,
can.page.Select(can, body, "fieldset."+item.name)[0] ||
can.page.AppendField(can, body, item.name+" "+(item.pos||""), item))
}, function() {typeof cb == "function" && cb(page)})
}, conf)
return page.target = body, page
return page
}),
Pane: shy("构造面板", function(can, name, meta, cb, field) {
var river = "", storm = "";
var pane = Volcanos(name, {_type: "local", target: field,
var pane = Volcanos(name, {_type: "local", _plugins: [], target: field,
option: field.querySelector("form.option"),
action: field.querySelector("div.action"),
output: field.querySelector("div.output"),
Plugin: can.Plugin, Inputs: can.Inputs, Output: can.Output,
_plugins: [],
Export: function(event, value, key) {can.Report(event, value, key)},
Import: function(event, value, key) {var cb = pane.onimport[key];
typeof cb == "function" && cb(event, pane, value, key, pane.output);
can.core.List(pane._plugins, function(item) {item.Import(event, value, key)})
pane.page.Select(pane, pane.action, "input."+key, function(item) {
item.value = value
})
pane.page.Select(pane, pane.action, "input."+key, function(item) {item.value = value})
},
Action: function(key, value) {
return can.page.Select(can, pane.action, "input[name="+key+"],select."+key+",select[name="+key+"]", function(item) {
value != undefined && (item.value = value), value = item.value
}), value
},
Size: function(event, width, height) {var cb = pane.onimport["size"];
@ -95,14 +98,7 @@ var can = Volcanos("chat", {
can.run(event, pane.option.dataset, cmds, cb)
return msg
},
}, Config.libs.concat(["pane/"+name]), function(pane) {
can.Dream(document.head, "pane/"+name+".css")
function deal(event, value) {
typeof pane.onaction[value] == "function" && pane.onaction[value](event, pane, meta, value, pane.output)
}
can.page.Append(can, pane.action, can.core.List(pane.onaction.list, function(line) {
return typeof line == "string"? {button: [line, deal]}: line.length > 0? {select: [line, deal]}: line
}))
}, Config.libs.concat(["pane/"+name]), function(pane) {can.Dream(document.head, "pane/"+name+".css")
pane.onimport._init && pane.onimport._init(pane, pane.Conf(meta), pane.output, pane.action, pane.option, field)
typeof cb == "function" && cb(pane)
}, meta)
@ -120,9 +116,7 @@ var can = Volcanos("chat", {
var feature = JSON.parse(meta.feature||'{}');
var exports = JSON.parse(meta.exports||'""')||feature.exports||[];
var plugin = Volcanos(name, {_type: "local", target: field,
option: field.querySelector("form.option"),
action: field.querySelector("div.action"),
output: field.querySelector("div.output"),
option: option, action: action, output: output,
Inputs: can.Inputs, Output: can.Output,
Import: function(event, value, key) {var cb = plugin.onimport[key];
@ -231,6 +225,7 @@ var can = Volcanos("chat", {
typeof cb == "function" && cb(plugin)
})
}, meta)
field.Check = plugin.Check
return plugin
}),
Inputs: shy("构造控件", function(can, item, type, name, value, cb, option) {
@ -243,14 +238,14 @@ var can = Volcanos("chat", {
},
Append: function(event, value) {can.Append(null, function(input) {can.Select(event, input.target, true)})},
Clone: function(event, value) {can.Clone(event, function(input) {input.Select(event, null, true)})},
run: function(event, cmd, cb, silent) {
run: function(event, cmd, cb, silent) {var msg = can.Event(event);
msg.Option("_action", item.name);
(input[item.cb] || can[item.cb] || can.Check)(event, event.target, cb);
},
}, Config.libs.concat(["plugin/"+type]), function(input) {
var target = input.onimport.init(input, item, name, value, option);
input.target = target, target.Input = input;
typeof cb == "function" && cb(input);
})
return input
@ -263,16 +258,14 @@ var can = Volcanos("chat", {
typeof cb == "function" && cb(event, output, value, key, target);
},
Option: function(key, value) {
can.page.Select(can, can.option, "input[name="+key+"],select[name="+key+"]", function(item) {
return can.page.Select(can, can.option, "input[name="+key+"],select[name="+key+"]", function(item) {
value != undefined && (item.value = value), value = item.value
})
return value
}), value
},
Action: function(key, value) {
can.page.Select(can, can.action, "input[name="+key+"],select."+key+",select[name="+key+"]", function(item) {
return can.page.Select(can, can.action, "input[name="+key+"],select."+key+",select[name="+key+"]", function(item) {
value != undefined && (item.value = value), value = item.value
})
return value
}), value
},
Status: function(event, value, key) {var cb = output.onstatus[key];
typeof cb == "function"? cb(event, output, value, key, can.page.Select(can, status, "div."+key)[0]): false && output.run(event, ["status", key, value], function(msg) {
@ -297,8 +290,11 @@ var can = Volcanos("chat", {
}),
}, Config.libs.concat(Config.list), function(can) {
can[Config.main] = can.Page(can, Config.main, Config, function(chat) {
chat.Login.Export(event||{}, can.user.Search(can, "layout")||Config.layout.def, "layout")
chat.Login.Import(event||{}, "", "login")
can.user.Search(can, "you") && can.user.title(can.user.Search(can, "you"))
chat.Import(event||{}, can.user.Search(can, "layout")||Config.layout.def, "layout")
can.user.title(can.user.Search(can, "you")||Config.title)
can.user.login(function(user) {
chat.River.Import(event||{}, "update", "river")
chat.Header.Import(event||{}, user.name, "username")
})
}, document.body)
})

View File

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/static/volcanos/style.css">
</head>
<body>
<script src="/static/volcanos/lib/wasm.js"></script>
<script src="/static/volcanos/proto.js"></script>
<script src="/static/volcanos/order.js"></script>
<script src="/static/volcanos/frame.js"></script>

View File

@ -1,5 +1,22 @@
Volcanos("core", {help: "核心模块",
List: shy("迭代器", function(obj, cb, interval, cbs) {obj = typeof obj == "string"? [obj]: (obj || [])
List: shy("迭代器", function(obj, cb, interval, cbs) {
if (typeof obj == "number") {
var begin = 0, end = obj, step = 1;
if (typeof interval == "number") {
step = interval
}
if (typeof cb == "number") {
begin = obj, end = cb;
}
var list = []
for (var i = begin; i < end; i += step) {
list.push(i)
}
return list
}
obj = typeof obj == "string"? [obj]: (obj || [])
if (interval > 0) {
function loop(i) {if (i >= obj.length) {return typeof cbs == "function" && cbs(obj)}
typeof cb == "function" && cb(obj[i], i, obj), setTimeout(function() {loop(i+1)}, interval);

View File

@ -36,7 +36,7 @@ Volcanos("misc", {help: "工具模块",
Run: shy("请求后端", {order: 0}, function(event, can, dataset, cmd, cb) {
var msg = can.Event(event)
var option = {"cmds": cmd}
var option = {"cmds": cmd||msg.cmd}
msg.option && msg.option.forEach(function(item) {
msg[item] && (option[item] = msg[item])
})
@ -56,15 +56,13 @@ Volcanos("misc", {help: "工具模块",
// kit.Log(msg.detail.concat([msg]))
// kit.History("run", -1, option)
this.POST(can, msg, can.Conf("context")+dataset.names.toLowerCase(), option, function(msg) {
this.POST(can, msg, can.Conf("iceberg")+(dataset.names||msg.names).toLowerCase(), option, function(msg) {
// kit.Log("run", what, "result", msg.result? msg.result[0]: "", msg)
typeof cb == "function" && cb(msg)
}), delete(event.msg)
}),
WSS: shy("请求后端", {order: 0}, function(can, cb, onerror, onclose, onopen) {var meta = arguments.callee.meta
can._socket = new WebSocket(location.protocol.replace("http", "ws")+"//"+location.host+"/space/?"+can.base.Args({
node: "active", name: can._share||"", user: can._username||"", share: can._share||"",
}))
WSS: shy("请求后端", {order: 0}, function(can, url, args, cb, onopen, onerror, onclose) {var meta = arguments.callee.meta
can._socket = new WebSocket(url+"?"+can.base.Args(args))
var timer = can.Timer(30000, function() {
can._socket.send("{}")
@ -74,7 +72,7 @@ Volcanos("misc", {help: "工具模块",
}, can._socket.onclose = onclose || function() {
timer.stop = true, can.user.toast("wss redial")
can.Log("wss", "close"), delete(can._socket), setTimeout(function() {
can.misc.WSS(can, cb, onerror, onclose, onopen)
can.misc.WSS(can, url, args, cb, onerror, onclose, onopen)
}, 1000)
}, can._socket.onopen = onopen
can._socket.onmessage = function(event) {var order = ++meta.order

View File

@ -195,6 +195,7 @@ Volcanos("page", {help: "网页模块",
{view: ["action"]}, {view: ["output"]}, {view: ["status"]},
// {view: ["border-bottom"]},
]}]).first;
field.Meta = item
return field;
}),
AppendTable: shy("添加表格", function(can, target, msg, list, cb, cbs) {
@ -260,7 +261,7 @@ Volcanos("page", {help: "网页模块",
},
AppendAction: shy("添加控件", function(can, action, list, cb) {
can.page.Append(can, action, can.core.List(list, function(line) {
return can.page.Append(can, action, can.core.List(list, function(line) {
return typeof line == "string"? {button: [line, cb]}: line.length > 0? {select: [line, cb]}: line
}))
}),

View File

@ -7,6 +7,8 @@ Volcanos("user", {help: "用户模块",
toast: function(text) {},
carte: function(event, cb) {},
login: function(cb) {},
share: function(cb) {},
Share: shy("共享链接", function(can, objs, clear) {var obj = objs || {}; var path = location.pathname;
obj.path && (path = obj.path, delete(obj.path))

17
manifest.json Normal file
View File

@ -0,0 +1,17 @@
{
"manifest_version": 2,
"name": "volcanos",
"version": "0.0.1",
"background": {"page": "plugin/chrome/chrome.html"},
"browser_action": {"default_popup": "plugin/chrome/popup.html"},
"content_scripts": [],
"permissions": [
"tabs",
"history",
"cookies",
"bookmarks",
"notifications",
"*://localhost/*",
"*://localhost:9020/*"
]
}

View File

@ -1,4 +1,5 @@
var Config = {context: "/chat/",
var Config = {iceberg: "/chat/", volcano: "/static/volcanos/",
libs: ["lib/base", "lib/core", "lib/misc", "lib/page", "lib/user"],
main: "chat", list: ["page/chat",
"pane/Toast", "pane/Tutor", "pane/Debug",
"pane/Carte", "pane/Favor", "pane/Login",
@ -9,9 +10,7 @@ var Config = {context: "/chat/",
"pane/Footer",
"plugin/state", "plugin/input", "plugin/table", "plugin/inner", "plugin/media",
],
libs: ["lib/base", "lib/core", "lib/misc", "lib/page", "lib/user"],
pane: [
], pane: [
{group: "index", name: "Toast", pos: "dialog", duration: 3000},
{group: "index", name: "Tutor", pos: "dialog"},
{group: "index", name: "Debug", pos: "dialog"},
@ -30,7 +29,7 @@ var Config = {context: "/chat/",
{group: "index", name: "Action", pos: "bottom"},
{group: "index", name: "Footer", pos: "foot", state: ["ntxt", "ncmd"], title: '<a href="mailto:shylinux@163.com">shylinux@163.com</a>'},
], layout: {def: "办公", list: ["工作", "办公", "聊天"], size: {
], title: "volcanos", layout: {def: "办公", list: ["工作", "办公", "聊天"], size: {
"最大": {head: 0, foot: 0, left: 0, right: 0, bottom: -1, center: 0, top: 0},
"工作": {head: 30, foot: 30, left: 0, right: 100, bottom: -1, center: 0, top: 0},
"办公": {head: 30, foot: 30, left: 100, right: 100, bottom: -1, center: 0, top: 0},

View File

@ -21,6 +21,9 @@ Volcanos("onaction", {help: "组件交互", list: [],
can.Action.escape && can.Action.escape(event)
break
case " ":
if (event.target.getAttribute("contenteditable")) {
break
}
if (event.target.tagName == "INPUT" || event.target.tagName == "TEXTAREA") {
break
}

View File

@ -4,76 +4,137 @@ Volcanos("onimport", {help: "导入数据", list: [],
input.value = can.user.Search(can, input.name) || ""
})
},
init: function(event, can, msg, cmd, output) {output.innerHTML = "";
init: function(event, can, msg, cmd, target) {can.output.innerHTML = "";
msg.Table(function(item, index) {if (!item.name) {return}
can._plugins.push(can[item.name] = can.Plugin(can, item.name, item, function(event, cmds, cbs) {
can.run(event, [item.river, item.storm, item.action].concat(cmds), cbs)
}, can.page.AppendField(can, output, "item "+item.group+" "+item.name, item)))
}, can.page.AppendField(can, can.output, "item "+item.group+" "+item.name, item)))
})
},
size: function(event, can, value, cmd, output) {
},
layout: function(event, can, value, cmd, output) {can.layout = value;
layout: function(event, can, value, cmd, target) {can.layout = value;
can.page.Select(can, can.action, "select.layout", function(item) {
item.value = value
})
},
scroll: function(event, can, value, cmd, output) {can.layout = value;
output.parentElement.scrollBy(value.x, value.y)
scroll: function(event, can, value, cmd, target) {can.layout = value;
can.output.parentElement.scrollBy(value.x, value.y)
},
river: function(event, can, value, cmd, output) {
river: function(event, can, value, cmd, target) {
if (value == "update") {return}
can.Conf("temp_river", value)
},
you: function(event, can, value, cmd, output) {
you: function(event, can, value, cmd, target) {
can.user.title(value)
},
storm: function(event, can, value, cmd, output) {
can.Cache(can.Conf("river")+"."+can.Conf("storm"), output, "some");
storm: function(event, can, value, cmd, target) {
can.Cache(can.Conf("river")+"."+can.Conf("storm"), can.output, "some");
can.Conf("river", can.Conf("temp_river"))
can.Conf("storm", value)
if (!can.Cache(can.Conf("river")+"."+can.Conf("storm"), output)) {
if (!can.Cache(can.Conf("river")+"."+can.Conf("storm"), can.output)) {
can.run(event, [can.Conf("river"), can.Conf("storm")], function(msg) {
can.onimport.init(event, can, msg, cmd, output)
can.onimport.init(event, can, msg, cmd, can.output)
})
}
},
favor: function(event, can, msg, cmd, output) {var key = msg.detail[0];
favor: function(event, can, msg, cmd, target) {var key = msg.detail[0];
if (msg._hand) {return}
var cb = can.onaction[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, output); return msg.Echo(can._name, " onaction ", key), msg._hand = true}
var cb = can.onchoice[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, output); return msg.Echo(can._name, " onchoice ", key), msg._hand = true}
var cb = can.onaction[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, can.output); return msg.Echo(can._name, " onaction ", key), msg._hand = true}
var cb = can.onchoice[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, can.output); return msg.Echo(can._name, " onchoice ", key), msg._hand = true}
var sub = can[key]; if (sub && sub.Select) {sub.Select(event, null, true); return msg.Echo(can._name, " select ", sub._name), msg._hand = true}
can._plugin && can._plugin.Import(event, msg, cmd)
},
})
Volcanos("onaction", {help: "组件交互", list: [["layout", "最大", "工作", "办公", "聊天"], "清屏", "刷新", "串行", "并行",
Volcanos("onaction", {help: "组件交互", list: [["layout", "最大", "工作", "办公", "聊天"], "刷新", "清屏", "并行","串行",
["action", "正常", "编辑", "编排", "定位"],
{input: "pod"}, {input: "you"}, {input: "hot"}, {input: "top"},
],
onmousemove: function(event, can, msg, cmd, output) {
onmousemove: function(event, can, msg, cmd, target) {
can.resize && can.resize(event)
},
layout: function(event, can, value, cmd, output) {
action: function(event, can, value, cmd, target) {
switch (value) {
case "正常":
can.page.Select(can, target, "fieldset.item", function(item) {
item.setAttribute("draggable", false)
})
break
case "编排":
can.page.Select(can, target, "fieldset.item", function(item) {
item.setAttribute("draggable", true)
item.ondragstart = function(event) {can.drag = event.target}
item.ondragover = function(event) {event.preventDefault()}
item.ondrop = function(event) {event.preventDefault()
item.parentNode.insertBefore(can.drag, item)
}
})
break
case "定位":
var max = 0;
var current, begin;
can.page.Select(can, target, "fieldset.item", function(item) {
item.style.left = item.offsetLeft + "px"
item.style.top = item.offsetTop + "px"
})
can.page.Select(can, target, "fieldset.item", function(item) {
item.style.position = "absolute"
item.onmousedown = function(event) {
if (can.Action("action") != "定位") {return}
if (current) {
current.style.left = event.clientX - begin.x + begin.left + "px"
current.style.top = event.clientY - begin.y + begin.top + "px"
current = null;
return
}
current = event.target;
current.style["z-index"] = max = max + 1
begin = {x: event.clientX, y: event.clientY, left: item.offsetLeft, top: item.offsetTop}
};
target.onmousemove = item.onmousemove = function(event) {if (!current) {return}
current.style.left = event.clientX - begin.x + begin.left + "px"
current.style.top = event.clientY - begin.y + begin.top + "px"
}
})
break
}
},
layout: function(event, can, value, cmd, target) {
can.Export(event, value, cmd)
},
"清屏": function(event, can, msg, cmd, output) {
can.page.Select(can, output, "fieldset.item>div.output", function(item) {
item.innerHTML = "";
})
},
"刷新": function(event, can, msg, cmd, output) {
can.page.Select(can, output, "fieldset.item>div.output", function(item) {
"刷新": function(event, can, msg, cmd, target) {
can.page.Select(can, can.output, "fieldset.item>div.output", function(item) {
item.innerHTML = "";
})
can.run(event, [can.Conf("river"), can.Conf("storm")], function(msg) {
can.onimport.init(event, can, msg, cmd, output)
can.onimport.init(event, can, msg, cmd, can.output)
})
},
"清屏": function(event, can, msg, cmd, target) {
can.page.Select(can, can.output, "fieldset.item>div.output", function(item) {
item.innerHTML = "";
})
},
"并行": function(event, can, msg, cmd, target) {
can.page.Select(can, target, "fieldset.item", function(field) {
can.page.Select(can, field, "input[type=button]", function(input, index) {
index == 0 && field.Check(event, input, function() {})
})
})
},
"串行": function(event, can, msg, cmd, target) {
can.core.Next(can.page.Select(can, target, "fieldset.item", function(field) {
return field
}), function(field, cb) {
can.page.Select(can, field, "input[type=button]", function(input, index) {
index == 0 && field.Check(event, input, cb)
})
})
},
})
Volcanos("onchoice", {help: "组件菜单", list: [["layout", "工作", "办公", "聊天"]],
Volcanos("onchoice", {help: "组件菜单", list: [["layout", "工作", "办公", "聊天"], "保存"],
"工作": function(event, can, msg, cmd, target) {
can.Export(event, cmd, "layout")
},
@ -83,6 +144,15 @@ Volcanos("onchoice", {help: "组件菜单", list: [["layout", "工作", "办公"
"聊天": function(event, can, msg, cmd, target) {
can.Export(event, cmd, "layout")
},
"保存": function(event, can, msg, cmd, target) {
var list = []
can.page.Select(can, target, "fieldset", function(item) {var meta = item.Meta
list.push(meta.node||"", meta.group, meta.index, meta.index)
})
can.run(event, [can.Conf("river"), can.Conf("storm"), "save"].concat(list), function(msg) {
can.user.toast("保存成功")
})
},
})
Volcanos("ondetail", {help: "组件详情", list: []})
Volcanos("onexport", {help: "导出数据", list: []})

View File

@ -2,11 +2,13 @@ Volcanos("onimport", {help: "导入数据", list: [],
_init: function(can, conf, output, action, option, field) {output.innerHTML = "";
conf.title && can.page.Append(can, output, [{view: "title",
list: [{text: conf.title, className: "title"}], click: function(event) {can.onexport.title(event, can)}}])
can.ui = can.page.Append(can, output, [{view: "state", list: can.core.List(conf.state, function(item) {
return {text: conf[item]||"", className: item, click: function(event) {var cb = can.onexport[item];
typeof cb == "function" && cb(event, can, item, item, output)
}};
})}])
can.timer = can.Timer({interval: 1000, length: -1}, function() {
can.ui.time.innerHTML = can.base.Time().split(" ")[1]
})

View File

@ -1,6 +1,19 @@
Volcanos("onimport", {help: "导入数据", list: [],
_init: function(can, conf, output, action, option, field) {
var ui = can.page.Appends(can, option, [
can.user.login = function(cb) {
can.user.Cookie("sessid")? can.onaction.check(event, can, cb, "check", output):
can.onaction.login(event, can, cb, "login", output)
}
},
})
Volcanos("onaction", {help: "组件交互", list: [],
check: function(event, can, cb, cmd, target) {
can.run(event||{}, ["check"], function(msg) {var user = msg.nickname && msg.nickname[0] || msg.Result()
user? typeof cb == "function" && cb({name: user}): can.onaction.login(event, can, cb, "login", target)
})
},
login: function(event, can, cb, cmd, target) {
var ui = can.page.Appends(can, target, [
{text: ["账号: ", "label"]}, {username: []}, {type: "br"},
{text: ["密码: ", "label"]}, {password: []}, {type: "br"},
{button: ["密码登录", function(event, cmd) {
@ -9,17 +22,14 @@ Volcanos("onimport", {help: "导入数据", list: [],
can.run(event, ["login", ui.username.value, ui.password.value], function(msg) {
if (msg.result && msg.result.length > 0) {
can.Hide(), can.Export(event, "", "login")
} else {
can.user.toast("用户或密码错误")
can.Hide(), can.onaction.check(event, can, cb, "check", target)
return
}
can.user.toast("用户或密码错误")
})
event.stopPropagation()
event.preventDefault()
return true
}]},
{button: ["扫码登录", function(event, cmd) {
can.onimport.username(event, can, "", function(event, msg) {
can.onaction.socket(event, can, "", function(event, msg) {
switch (msg.detail[0]) {
case "space":
if (msg.detail[1] == "share") {can._share = msg.detail[2]
@ -31,19 +41,18 @@ Volcanos("onimport", {help: "导入数据", list: [],
break
case "sessid":
can.user.Cookie(can, "sessid", msg.detail[1])
can.Hide(), can.Export(event, "", "login")
can.Hide(), typeof cb == "function" && cb({name: user})
can.user.toast("")
return true
}
})
event.stopPropagation()
event.preventDefault()
return true
}]},
{type: "br"},
])
can.Show(event, -1, -1)
},
username: function(event, can, value, cmd, output) {can._username = value
socket: function(event, can, value, cmd, output) {can._username = value
// location.protocol.replace("http", "ws")+"//"+location.host+"/space/?"+
return can._socket = can._socket || can.misc.WSS(can, function(event, msg) {
if (msg.Option("_handle")) {return can.user.toast(msg.result.join(""))}
if (typeof cmd == "function" && cmd(event, msg)) {return msg.Reply(msg)}
@ -55,14 +64,7 @@ Volcanos("onimport", {help: "导入数据", list: [],
msg.Reply(msg)
})
},
login: function(event, can, value, cmd, output) {
if (!can.user.Cookie("sessid")) {can.Show(event, 400, 400); return}
can.run(event||{}, ["check"], function(msg) {var user = msg.nickname && msg.nickname[0] || msg.Result()
user? can.Export(event, user, "username"): can.Show(event, -1, -1)
})
},
})
Volcanos("onaction", {help: "组件交互", list: []})
Volcanos("onchoice", {help: "组件菜单", list: []})
Volcanos("ondetail", {help: "组件详情", list: []})
Volcanos("onexport", {help: "导出数据", list: []})

View File

@ -1,21 +1,16 @@
Volcanos("onimport", {help: "导入数据", list: [],
_init: function(can, conf, output, action, option, field) {
},
init: function(event, can, msg, key, output) {output.innerHTML = "";
can.page.AppendItem(can, output, msg.Table(), can.user.Search(can, "river"), function(event, line, item) {
can.Export(event, line.key, "river")
})
},
username: function(event, can, value, key, output) {
river: function(event, can, value, key, output) {if (value == "update") {
can.run(event, [], function(msg) {
can.onimport.init(event, can, msg, key, output)
})
},
river: function(event, can, value, key, output) {
if (value == "update") {
can.run(event, [], function(msg) {
can.onimport.init(event, can, msg, key, output)
})
}
},
}},
favor: function(event, can, msg, cmd, output) {var key = msg.detail[0];
if (msg._hand) {return}
var cb = can.onaction[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, output); return msg.Echo(can._name, " onaction ", key), msg._hand = true}
@ -34,23 +29,18 @@ Volcanos("onaction", {help: "组件交互", list: ["创建", "刷新"],
can.Export(event, "create", "ocean")
},
"刷新": function(event, can, meta, key, output) {
can.run(event, [], function(msg) {
can.onimport.init(event, can, msg, key, output)
})
},
})
Volcanos("onchoice", {help: "组件菜单", list: ["创建", "刷新"],
"创建": function(event, can, msg, key, target) {
can.Export(event, "create", "ocean")
},
"刷新": function(event, can, msg, key, target) {
can.onaction[key](event, can, key, can.output)
can.Import(event, "update", "river")
},
})
Volcanos("onchoice", {help: "组件菜单", list: ["创建", "刷新"]})
Volcanos("ondetail", {help: "组件详情", list: ["共享"],
"共享": function(event, can, line, key, target) {
can.Export(event, "river", "share")
},
})
Volcanos("onexport", {help: "导出数据", list: [],
share: function(event, can, line, key, target) {
can.user.toast(can.user.Share(can, {river: line.key}), "共享链接", 10000)
},
})
Volcanos("onexport", {help: "导出数据", list: []})

13
plugin/chrome/chrome.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<script src="/proto.js"></script>
<script src="config.js"></script>
<script src="chrome.js"></script>
</body>
<html>

142
plugin/chrome/chrome.js Normal file
View File

@ -0,0 +1,142 @@
var can = Volcanos("chrome", {
_send: function(msg, cb) {chrome.extension.sendRequest(msg, cb)},
_open: function(url) {chrome.windows.create({url: url})},
run: function(can, msg, cb) {
can.misc.Run({names: "chrome", msg: msg}, can, {}, null, cb)
},
open: function(msg, cmd, cb) {
chrome.windows.create({url: cmd[0]})
typeof cb == "function" && cb(msg)
},
wins: function(msg, cmd, cb) {
if (cmd.length == 0) {
// 窗口列表
chrome.windows.getAll(function(wins) {
can.core.List(wins, function(win) {win.wid = win.id
msg.Push(win, ["wid", "state", "left", "top", "width", "height"])
})
typeof cb == "function" && cb(msg)
})
return
}
if (cmd.length > 1) {
// 新建标签
chrome.tabs.create({windowId: parseInt(cmd[0]), url: cmd[1], selected: false}, function() {
can.wins(msg, [cmd[0]], cb)
})
return
}
// 标签列表
chrome.tabs.getAllInWindow(parseInt(cmd[0]), function(tabs) {
can.core.List(tabs, function(tab) {tab.tid = tab.id
msg.Push(tab, ["tid", "active", "width", "height", "index", "title", "url"])
})
typeof cb == "function" && cb(msg)
})
},
tabs: function(msg, cmd, cb) {
if (cmd.length == 0) {
chrome.tabs.getAllInWindow(function(tabs) {
can.core.List(tabs, function(tab) {
msg.Push("id", tab.id)
msg.Push("active", tab.active)
msg.Push("index", tab.index)
msg.Push("title", tab.title)
msg.Push("url", tab.url)
})
typeof cb == "function" && cb(msg)
})
return
}
chrome.tabs[cmd[1]](parseInt(cmd[0]), cb)
},
cookie: function(msg, cmd, cb) {
if (cmd[0] == "modify") {var data = {}; data[cmd[1]] = cmd[2]
chrome.bookmarks.update(cmd[4], data, function() {
typeof cb == "function" && cb(msg)
})
return
} else if (cmd[0] == "delete") {
chrome.bookmarks.remove(cmd[2], function() {
typeof cb == "function" && cb(msg)
})
return
} else if (cmd.length > 2) {
chrome.bookmarks.create({parentId: cmd[0], url: cmd[1], title: cmd[2], index: cmd[3]||0}, cb)
}
chrome.cookies.getAll({name: ""}, function(cs) {
typeof cb == "function" && cb(msg)
})
},
history: function(msg, cmd, cb) {
chrome.tabs.getAllInWindow(function(tabs) {
can.core.List(tabs, function(tab) {
msg.Push("id", tab.id)
msg.Push("active", tab.active)
msg.Push("index", tab.index)
msg.Push("title", tab.title)
msg.Push("url", tab.url)
})
typeof cb == "function" && cb(msg)
})
},
bookmark: function(msg, cmd, cb) {
if (cmd[0] == "modify") {var data = {}; data[cmd[1]] = cmd[2]
chrome.bookmarks.update(cmd[4], data, function() {
typeof cb == "function" && cb(msg)
})
return
} else if (cmd[0] == "delete") {
chrome.bookmarks.remove(cmd[2], function() {
typeof cb == "function" && cb(msg)
})
return
} else if (cmd.length > 2) {
chrome.bookmarks.create({parentId: cmd[0], url: cmd[1], title: cmd[2], index: cmd[3]||0}, cb)
}
chrome.bookmarks.getSubTree(cmd[0]||"0", function(labs) {
for (var i = 0; i < labs.length; i++) {labs[i].pid = labs[i].parentId
msg.Push("time", can.base.Time(labs[i].dateAdded))
msg.Push(labs[i], ["pid", "id", "index", "title", "url"])
labs = labs.concat(labs[i].children||[])
}
typeof cb == "function" && cb(msg)
})
},
}, Config.libs.concat(Config.list), function(can) {can.Conf(Config)
can.user.toast = function(message, title) {chrome.notifications.create(null, {
message: message, title: title||Config.title, iconUrl: "/favicon.ico", type: "basic",
})},
can.socket = can.socket || can.misc.WSS(can, "ws://localhost:9020/space/", {node: "chrome", name: chrome.runtime.id}, function(event, msg) {
if (msg.Option("_handle")) {return can.user.toast(msg.result.join(""))}
can.user.toast(msg.detail.join(" "))
switch (msg.detail[0]) {
case "space": can._share = msg.detail[2]; break
case "pwd": msg.Echo("hello world"); break
default: (can[msg.detail[0]]||can.chrome[msg.detail[0]])(msg, msg.detail.slice(1), function(msg) {
msg.Reply(msg)
}); return
}
msg.Reply(msg)
}, function() {can.user.toast("wss connect", "iceberg")})
chrome.history.onVisited.addListener(function(item) {
can.run(can, {names: "crx", cmd: ["history", item.id, item.url, item.title]}, function(msg) {
can.user.toast(item.url, item.title)
})
})
chrome.extension.onRequest.addListener(function(msg, sender, cb) {
can.run(can, msg, cb)
})
})

41
plugin/chrome/config.js Normal file
View File

@ -0,0 +1,41 @@
var Config = {iceberg: "http://localhost:9020/chat/", volcano: "/",
libs: ["lib/base", "lib/core", "lib/misc", "lib/page", "lib/user"],
main: "chat", list: ["page/chat",
"pane/Toast", "pane/Tutor", "pane/Debug",
"pane/Carte", "pane/Favor", "pane/Login",
"pane/Header",
"pane/Ocean", "pane/River", "pane/Storm", "pane/Steam",
"pane/Target", "pane/Source", "pane/Action",
"pane/Footer",
"plugin/state", "plugin/input", "plugin/table", "plugin/inner", "plugin/media",
], pane: [
{group: "index", name: "Toast", pos: "dialog", duration: 3000},
{group: "index", name: "Tutor", pos: "dialog"},
{group: "index", name: "Debug", pos: "dialog"},
{group: "index", name: "Carte", pos: "dialog"},
{group: "index", name: "Favor", pos: "dialog"},
{group: "index", name: "Login", pos: "dialog"},
{group: "index", name: "Header", pos: "head", state: ["time", "user", "link"], title: "github.com/shylinux/context"},
{group: "index", name: "Ocean", pos: "dialog", def_name: "meet"},
{group: "index", name: "River", pos: "left"},
{group: "index", name: "Storm", pos: "right"},
{group: "index", name: "Steam", pos: "dialog", def_name: "miss"},
{group: "index", name: "Target", pos: "top"},
{group: "index", name: "Source", pos: "center"},
{group: "index", name: "Action", pos: "bottom"},
{group: "index", name: "Footer", pos: "foot", state: ["ntxt", "ncmd"], title: '<a href="mailto:shylinux@163.com">shylinux@163.com</a>'},
], title: "范晓旭", layout: {def: "办公", list: ["工作", "办公", "聊天"], size: {
"最大": {head: 0, foot: 0, left: 0, right: 0, bottom: -1, center: 0, top: 0},
"工作": {head: 30, foot: 30, left: 0, right: 100, bottom: -1, center: 0, top: 0},
"办公": {head: 30, foot: 30, left: 100, right: 100, bottom: -1, center: 0, top: 0},
"聊天": {head: 30, foot: 30, left: 100, right: 100, bottom: 300, center: 40, top: -2},
"全屏": {head: 0, foot: 0, left: 0, right: 0, bottom: -1, center: 0, top: 0},
}, border: 4,
},
}

13
plugin/chrome/popup.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body style="min-height:400px">
<script src="/proto.js"></script>
<script src="config.js"></script>
<script src="/frame.js"></script>
<!-- <script src="popup.js"></script> -->
</body>
<html>

19
plugin/chrome/popup.js Normal file
View File

@ -0,0 +1,19 @@
var can = Volcanos("popup", {
demo: function() {
can.chrome.notice("hi", "hello")
},
}, Config.libs.concat(Config.list), function(can) {can.Conf(Config)
can.page.Append(can, document.body, [{button: ["baidu", function() {
can.chrome.open("https://www.baidu.com")
}]}])
can.page.Append(can, document.body, [{button: ["volcanos", function() {
can.chrome.open("http://localhost:9020")
}]}])
can.page.Append(can, document.body, [{button: ["send", function() {
can.chrome.send({names: "crx", cmds: ["hi"]}, function(msg) {
can.chrome.notice("hi", "hello")
console.log(msg)
})
}]}])
})

View File

@ -1,4 +1,6 @@
Volcanos("onimport", {help: "导入数据", list: [],
_begin: function(can) {},
_start: function(can) {},
init: shy("添加控件", function(can, item, name, value, option) {
var input = {type: "input", name: name, data: item};
item.type = item.type || item._type || item._input;
@ -41,8 +43,112 @@ Volcanos("onimport", {help: "导入数据", list: [],
return target.value + (target.value == "" || target.value.endsWith("/")? "": "/") + value
},
})
Volcanos("onfigure", {help: "控件详情", list: [],
date: {click: function(event, can, value, cmd, target) {if (can.date) {return}
target.style.width = "120px"
function set(now) {
target.value = can.base.Time(now);
if (can.item.action == "auto") {
can.run({});
}
}
can.stick = false
can.now = target.value? new Date(target.value): new Date();
can.date = can.page.Append(can, document.body, [{view: ["date input", "fieldset"], style: {
position: "absolute", left: event.clientX+"px", top: event.clientY+10+"px",
}, onmouseleave: function(event) {
if (can.stick) {can.stick = false; return}
can.page.Remove(can, can.date); delete(can.date);
}}]).last
var action = can.page.Append(can, can.date, [{view: ["action"]}]).last
var control = can.page.AppendAction(can, 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"]},
"上一月", ["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;
switch (cmd) {
case "year": can.now.setFullYear(parseInt(value)); show(can.now); return;
case "month": can.now.setMonth(parseInt(value)-1); show(can.now); return;
case "hour": can.now.setHours(parseInt(value)); show(can.now); set(can.now); return;
case "minute": can.now.setMinutes(parseInt(value)); show(can.now); set(can.now); return;
case "second": can.now.setSeconds(parseInt(value)); show(can.now); set(can.now); return;
}
switch (value) {
case "今天": can.now = new Date(); show(can.now); set(can.now); break;
case "随机": can.now.setDate((Math.random() * 100 - 50) + can.now.getDate()); show(can.now); set(can.now); break;
case "关闭":can.page.Remove(can, can.date); delete(can.date);
case "前一年": can.now.setFullYear(can.now.getFullYear()-1); show(can.now); break;
case "后一年": can.now.setFullYear(can.now.getFullYear()+1); show(can.now); break;
case "上一月": can.now.setMonth(can.now.getMonth()-1); show(can.now); break;
case "下一月": can.now.setMonth(can.now.getMonth()+1); show(can.now); break;
}
})
var table = can.page.Append(can, can.date, [{type: "table"}]).table
function click(event) {
var day = new Date(parseInt(event.target.dataset.date))
can.now = day;
set(can.now);
}
function show(now) {
control.month.value = now.getMonth()+1;
control.year.value = now.getFullYear();
control.hour.value = now.getHours();
control.minute.value = parseInt(now.getMinutes()/5)*5;
control.second.value = parseInt(now.getSeconds()/5)*5;
var meta = ["日", "一", "二", "三", "四", "五", "六"]
can.page.Appends(can, table, [{type: "tr", list: can.core.List(meta, function(day) {return {text: [day, "th"]}})}])
var one = new Date(now); one.setDate(1);
var end = new Date(now); end.setMonth(now.getMonth()+1); end.setDate(1);
var head = new Date(one); head.setDate(one.getDate()-one.getDay());
var tail = new Date(end); tail.setDate(end.getDate()+7-end.getDay());
var tr;
function add(day, type) {
if (day.getDay() == 0) {tr = can.page.Append(can, table, [{type: "tr"}]).tr}
can.page.Append(can, tr, [{className: can.base.Time(day).split(" ")[0] == can.base.Time(now).split(" ")[0]? "now": type,
text: [day.getDate(), "td"], dataset: {date: day.getTime()}, click: click,
}])
}
for (var day = new Date(head); day < one; day.setDate(day.getDate()+1)) {add(day, "last")}
for (var day = new Date(one); day < end; day.setDate(day.getDate()+1)) {add(day, "main")}
for (var day = new Date(end); end.getDay() != 0 && day < tail; day.setDate(day.getDate()+1)) {add(day, "next")}
}
show(can.now);
set(can.now);
}},
province: {click: function(event, can, value, cmd, target) {if (can.figure) {return}
can.figure = can.page.Append(can, document.body, [{view: ["date input", "fieldset"], style: {
position: "absolute", left: "20px", top: event.clientY+10+"px",
}, onmouseleave: function(event) {
can.page.Remove(can, can.figure); delete(can.figure);
}}]).last
can.page.Append(can, can.figure, [{include: ["/plugin/github.com/shylinux/echarts/echarts.js", function(event) {
can.page.Append(can, can.figure, [{include: ["/plugin/github.com/shylinux/echarts/china.js", function(event) {
var china_chart = echarts.init(can.page.Append(can, can.figure, [{type: "div", style: {width: "600px", height: "400px"}}]).last);
var option = {geo: {map: 'china'}};
china_chart.setOption(option);
china_chart.on('click', function (params) {
target.value = params.name;
});
}]}]);
}]}]);
},
},
})
Volcanos("onaction", {help: "控件交互", list: [],
onclick: function(event, can) {can.Select(event); can.item.type == "button" && can.run(event)},
onclick: function(event, can) {can.Select(event);
var figure = can.onfigure[can.item.figure]
figure? figure.click(event, can, can.item, can.item.name, event.target): can.item.type == "button" && can.run(event)
},
onkeydown: function(event, can) {
can.page.oninput(event, can, function(event) {
switch (event.key) {

View File

@ -27,7 +27,8 @@ Volcanos("onimport", {help: "导入数据", list: [],
var sub = can.Event(event);
msg.append.forEach(function(key) {sub.Option(key, msg[key][index].trim())})
typeof cb == "function"? cb(event, can, msg, index, key, cmd, target):
can.run(event, [id, typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
// can.run(event, [id, typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.run(event, ["action", typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.onimport.init(can, msg, cb, output, option)
}, true)
}))
@ -82,7 +83,8 @@ Volcanos("ondetail", {help: "组件详情", list: ["选择", "编辑", "删除",
if (event.key == " ") {return event.stopPropagation()}
if (event.key != "Enter") {return}
if (key == "value" && msg.key) {key = msg.key[index]}
can.run(event, [msg.Ids(index), "modify", key, event.target.value, text], function(msg) {
// can.run(event, [msg.Ids(index), "modify", key, event.target.value, text], function(msg) {
can.run(event, ["action", "modify", key, event.target.value, text, msg.Ids(index)], function(msg) {
td.innerHTML = event.target.value;
can.user.toast("修改成功")
}, true)

149
plugin/team/plan.js Normal file
View File

@ -0,0 +1,149 @@
Volcanos("onimport", {help: "导入数据", list: [],
init: function(can, msg, cb, output, action, option) {output.innerHTML = "";
if (!msg.append || msg.append.length == 0) {
var code = can.page.Append(can, output, [{view: ["code", "div", msg.Result()]}]).code;
return typeof cb == "function" && cb(msg), code;
}
var table = can.page.AppendTable(can, output, msg, msg.append);
table.onclick = function(event) {switch (event.target.tagName) {
case "TD":
can.onimport.which(event, table, msg.append, function(index, key) {
can.ondetail["复制"](event, can, msg, event.target.innerHTML, index, key, event.target);
can.Export(event, event.target.innerHTML.trim(), key, index)
})
break
case "TH":
break
case "TR":
case "TABLE":
}}
table.oncontextmenu = function(event) {var target = event.target;
switch (event.target.tagName) {
case "TD":
can.onimport.which(event, table, msg.append, function(index, key) {
can.user.carte(event, shy("", can.ondetail, can.feature.detail || can.ondetail.list, function(event, cmd, meta) {var cb = meta[cmd];
var id = msg.Ids(index);
var sub = can.Event(event);
msg.append.forEach(function(key) {sub.Option(key, msg[key][index].trim())})
typeof cb == "function"? cb(event, can, msg, index, key, cmd, target):
// can.run(event, [id, typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.run(event, ["action", typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.onimport.init(can, msg, cb, output, option)
}, true)
}))
})
event.stopPropagation()
event.preventDefault()
break
case "TH":
case "TR":
case "TABLE":
}
}
can.page.Select(can, table, "div.miss", function(item) {
item.setAttribute("draggable", true)
item.ondragstart = function(event) {can.drag = event.target}
item.ondragover = function(event) {event.preventDefault()}
item.ondrop = function(event) {event.preventDefault()
can.preview.insertBefore(can.drag, item)
}
})
can.page.Select(can, table, "tr", function(tr) {tr.list = [];
can.page.Select(can, tr, "td", function(item, index) {tr.list.push(item);
// item.setAttribute("draggable", true)
// item.ondragstart = function(event) {can.drag = event.target}
item.ondragover = function(event) {event.preventDefault(), can.page.Select(can, table, "td.over", function(item) {
can.page.ClassList.del(can, item, "over")
}), can.page.ClassList.add(can, item, "over")}
item.ondrop = function(event) {event.preventDefault()
item.append(can.drag)
var data = can.drag.dataset;
var begin_time = new Date(data.begin_time);
begin_time.setHours(parseInt(tr.list[0].innerText));
begin_time.setMinutes(0);
begin_time.setSeconds(0);
if (can.Option("scale") == "week") {
begin_time.setDate(begin_time.getDate() - (begin_time.getDay() - index + 1))
}
can.run(event, ["action", "modify", "begin_time", can.base.Time(begin_time), data.begin_time, data.id, data.name], function(msg) {
can.user.toast("修改成功")
}, true);
}
})
})
return typeof cb == "function" && cb(msg), table;
},
which: function(event, table, list, cb) {if (event.target == table) {return cb(-1, "")}
can.page.Select(can, table, "tr", function(tr, index) {if (event.target == tr) {return cb(index-1, "")}
can.page.Select(can, tr, "th,td", function(td, order) {
if (event.target == td) {return cb(index-1, list[order])}
})
})
},
favor: function(event, can, msg, cmd, output) {var key = msg.detail[0];
var cb = can.onaction[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, output); return msg.Echo(can._name, " onaction ", key), msg._hand = true}
var cb = can.onchoice[key]; if (typeof cb == "function") {cb(event, can, msg, cmd, output); return msg.Echo(can._name, " onchoice ", key), msg._hand = true}
},
})
Volcanos("onaction", {help: "组件交互", list: [],
})
Volcanos("onchoice", {help: "组件菜单", list: ["返回", "清空", "复制", "下载"],
"返回": function(event, can, msg, cmd, target) {
can.run(event, ["", "Last"])
},
"清空": function(event, can, msg, cmd, target) {
can.target.innerHTML = "";
},
"复制": function(event, can, msg, cmd, target) {
var list = can.onexport.Format(can, msg, "data");
can.user.toast(can.page.CopyText(can, list[2]), "复制成功")
},
"下载": function(event, can, msg, cmd, target) {msg = msg || can.msg;
var list = can.onexport.Format(can, msg, msg._plugin_name||"data");
can.page.Download(can, list[0]+list[1], list[2]);
},
})
Volcanos("ondetail", {help: "组件详情", list: ["选择", "编辑", "删除", "复制", "下载"],
"选择": "select",
"删除": "delete",
"编辑": function(event, can, msg, index, key, cmd, td) {
var text = td.innerHTML;
var input = can.page.Appends(can, td, [{type: "input", value: text, style: {width: td.clientWidth+"px"}, data: {onkeydown: function(event) {
if (event.key == " ") {return event.stopPropagation()}
if (event.key != "Enter") {return}
if (key == "value" && msg.key) {key = msg.key[index]}
// can.run(event, [msg.Ids(index), "modify", key, event.target.value, text], function(msg) {
can.run(event, ["action", "modify", key, event.target.value, text, msg.Ids(index)], function(msg) {
td.innerHTML = event.target.value;
can.user.toast("修改成功")
}, true)
}}}]).first;
input.focus();
input.setSelectionRange(0, input.value.length);
},
"复制": function(event, can, msg, index, key, cmd, target) {
can.user.toast(can.page.CopyText(can, target.innerHTML), "复制成功")
},
"下载": function(event, can, msg, index, key, cmd, target) {
can.page.Download(can, key, target.innerHTML);
},
})
Volcanos("onexport", {help: "导出数据", list: [],
Format: function(can, msg, name) {
var ext = ".csv", txt = can.page.Select(can, can.target, "tr", function(tr) {
return can.page.Select(can, tr, "td,th", function(td) {return td.innerText}).join(",")
}).join("\n");
!txt && (ext = ".txt", txt = msg.result && msg.result.join("") || "");
return [name, ext, txt]
},
})

View File

@ -12,11 +12,12 @@ Volcanos("onimport", {help: "导入数据", list: [],
var items = item.path.split(".");
switch (items[items.length-1]) {
case "png":
case "JPG":
return {img: "/share/local/web.wiki.feel/"+item.path, width: width, oncontextmenu: menu}
return {className: "preview", img: "/share/local/web.wiki.feel/"+item.path, width: width, oncontextmenu: menu}
case "MOV":
case "m4v":
return {type: "video", width: width, oncontextmenu: menu,
return {className: "preview", type: "video", width: width, oncontextmenu: menu,
onplay: cb, onpause: cb,
onloadedmetadata: cb,
onloadeddata: cb,
@ -31,7 +32,7 @@ Volcanos("onimport", {help: "导入数据", list: [],
var table = can.page.AppendTable(can, output, msg, msg.append);
var begin = 0, limit = 3;
var rate = 1, width = 200;
var rate = 1, width = 600;
var control = can.page.Append(can, output, [{view: ["control"], list: [
{select: [["width", 100, 200, 400, 600, 800], function(event, value) {width = parseInt(value), page(begin, limit)}]},
{select: [["rate", 0.1, 0.2, 0.5, 1, 2, 3, 5, 10], function(event, value) {rate = value}]},
@ -63,23 +64,27 @@ Volcanos("onimport", {help: "导入数据", list: [],
page(begin, limit);
function show(index) {var item = list[can.page.Select(can, table, "tr")[index+1].dataset.index];
var video;
var video = {};
var timer = can.user.toast({text: "", list: [{view: "control", list: [
{button: ["close", function(event) {video.pause(), timer.toast.Hide()}]},
{select: [["width", 100, 200, 400, 600, 800], function(event, value) {timer.toast.Show(event, parseInt(value)+20), video.width = value}]},
{select: [["width", 100, 200, 400, 600, 800], function(event, value) {timer.toast.Show(event, parseInt(value)+20),
width = value
timer.toast.preview.setAttribute("width", value)
// video.width = value
}]},
{select: [["rate", 0.1, 0.2, 0.5, 1, 2, 3, 5, 10], function(event, value) {rate = video.playbackRate = value}]},
{button: ["prev", function(event) {show(index-1)}]},
{text: index+"/"+list.length},
{button: ["next", function(event) {show(index+1)}]},
{type: "br"}, {text: item.path},
{type: "br"}, {text: item.label},
]}].concat([view(index, 400, true, function(event) {video = event.target;
]}].concat([view(index, 600, true, function(event) {video = event.target;
switch (event.type) {
case "loadeddata": video.playbackRate = rate; break
case "ended": show(index+1); break
}
})]), width: 400+20, height: 620, duration: -1})
timer.toast.width.value = 400;
})]), width: 600+20, height: 620, duration: -1})
timer.toast.width.value = 600;
timer.toast.rate.value = rate;
}
@ -99,6 +104,29 @@ Volcanos("onimport", {help: "导入数据", list: [],
case "TR":
case "TABLE":
}}
table.oncontextmenu = function(event) {var target = event.target;
switch (event.target.tagName) {
case "TD":
can.onimport.which(event, table, msg.append, function(index, key) {
can.user.carte(event, shy("", can.ondetail, can.feature.detail || can.ondetail.list, function(event, cmd, meta) {var cb = meta[cmd];
var id = msg.Ids(index);
var sub = can.Event(event);
msg.append.forEach(function(key) {sub.Option(key, msg[key][index].trim())})
typeof cb == "function"? cb(event, can, msg, index, key, cmd, target):
// can.run(event, [id, typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.run(event, ["action", typeof cb == "string"? cb: cmd, key, target.innerHTML], function(msg) {
can.onimport.init(can, msg, cb, output, option)
}, true)
}))
})
event.stopPropagation()
event.preventDefault()
break
case "TH":
case "TR":
case "TABLE":
}
}
return typeof cb == "function" && cb(msg), table;
},
which: function(event, table, list, cb) {if (event.target == table) {return cb(-1, "")}
@ -123,17 +151,12 @@ Volcanos("onchoice", {help: "组件交互", list: ["保存", "清空", ["rect",
console.log("choice", cmd)
},
})
Volcanos("ondetail", {help: "组件详情", list: ["标签", "删除"],
Volcanos("ondetail", {help: "组件详情", list: ["标签"],
"标签": function(event, can, msg, index, key, cmd, target) {
can.user.prompt("目标", function(kind) {
can.run(event, ["action", "标签", msg.path, kind], function() {
}, true)
})
var figure = can.onfigure[target.tagName]
figure.copy(event, can, target)
},
"删除": function(event, can, msg, index, key, cmd, target) {
can.page.Remove(can, target)
},
})
Volcanos("onstatus", {help: "组件状态", list: ["begin", "width", "point", "which"],

View File

@ -1,13 +1,19 @@
Volcanos("onimport", {help: "导入数据", list: [],
_begin: function(can) {
},
_start: function(can) {
can.Action("stroke-width", 2)
can.Action("stroke", "yellow")
can.Action("fill", "purple")
can.Action("grid", "20")
},
init: function(can, msg, cb, output, action, option) {output.innerHTML = "";
if (msg.append && msg.append.length > 0) {
if (msg.append && msg.append.length > 0) {action.innerHTML = "";
var table = can.page.AppendTable(can, output, msg, msg.append);
table.onclick = function(event) {switch (event.target.tagName) {
case "TD":
can.onimport.which(event, table, msg.append, function(index, key) {
var name = event.target.innerHTML.trim()
can.Option("name", name)
can.run(event, [name])
can.run(event, [can.Option("name", event.target.innerHTML.trim())])
})
break
case "TH":
@ -19,18 +25,19 @@ Volcanos("onimport", {help: "导入数据", list: [],
}
var code = can.page.Append(can, output, [{view: ["code", "div", msg.Result()||can.Export(event, null, "file")]}]).code;
can.page.Select(can, output, "svg", function(svg) {can.group = can.svg = svg
can.page.Select(can, output, "svg", function(svg) {can.group = can.svg = svg;
can.onaction.init(event, can, msg, "init", svg);
can.onaction.list[1] = ["group", "svg", "add"]
can.onaction.list[2] = ["group", "svg", "add"];
can.page.Select(can, svg, "*", function(item, index) {
can.onaction.init(event, can, msg, index, item);
switch (item.tagName) {
case "g":
can.onaction.list[1].push(item.Value("class"))
can.onaction.list[2].push(item.Value("class"));
break
}
})
}), can.point = [];
return typeof cb == "function" && cb(msg), code;
},
which: function(event, table, list, cb) {if (event.target == table) {return cb(-1, "")}
@ -42,14 +49,47 @@ Volcanos("onimport", {help: "导入数据", list: [],
},
})
Volcanos("onfigure", {help: "图形绘制", list: [],
move: {
draw: function(event, can, point) {
if (point.length == 1) {
if (event.type != "click") {return}
select: {draw: function(event, can, point) {if (point.length == 1) {return}
var p0 = point[0], p1 = point[1];
var data = {
"x": p0.x > p1.x? p1.x: p0.x,
"y": p0.y > p1.y? p1.y: p0.y,
"width": Math.abs(p0.x-p1.x),
"height": Math.abs(p0.y-p1.y),
"fill": "#11000000",
"class": "temp",
}
can.Status(event, data, "width");
event.type == "click" && point.length == 2 && (can.point = [])
return data;
}},
resize: {draw: function(event, can, point) {
if (point.length == 1) {if (event.type != "click") {return}
// 记录图形
can.current = {target: event.target}
} else if (point.length == 2) {
if (event.type == "click") {return can.point = [], delete(can.current)}
if (event.type == "click") {can.point = [], delete(can.current); return}
}
var target = can.current.target
var figure = can.onfigure[target.tagName];
if (point.length == 1) {
// 记录起点
can.core.Item(figure.data.resize, function(key, value) {
can.current[key] = parseInt(target.Value(value))
})
} else {
var resize = figure.data.resize;
target.Value(resize.width, can.current.width + point[1].x - point[0].x)
target.Value(resize.height, can.current.height + point[1].y - point[0].y)
}
}},
move: {draw: function(event, can, point) {
if (point.length == 1) {if (event.type != "click") {return}
// 记录图形
can.current = {target: event.target}
} else if (point.length == 2) {
if (event.type == "click") {return can.point = [], delete(can.current), null}
}
var target = can.current.target
@ -64,31 +104,10 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
target.Value(move.x, can.current.x+point[1].x-point[0].x)
target.Value(move.y, can.current.y+point[1].y-point[0].y)
}
},
},
resize: {
draw: function(event, can, point) {
if (point.length == 1) {
if (event.type != "click") {return}
// 记录图形
can.current = {target: event.target}
} else if (point.length == 2) {
if (event.type == "click") {return can.point = [], delete(can.current)}
}
var target = can.current.target
var figure = can.onfigure[can.current.target.tagName];
var move = figure.data.move || {x: "x", y: "y"}
if (point.length == 1) {
// 记录起点
can.core.List(figure.data.resize, function(item) {
can.current[item] = parseInt(target.Value(item))
})
} else {
// 绽放图形
figure.resize(event, can, point, can.current, target)
}
},
}},
svg: {
data: {resize: {width: "width", height: "height"}},
show: function(event, can, value, target) {},
},
text: {
data: {move: {x: "x", y: "y"}}, // <text x="60" y="10">hi<text>
@ -96,29 +115,22 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
},
rect: {
data: {
resize: ["width", "height", "rx"],
resize: {width: "width", height: "height"},
move: {x: "x", y: "y"}, copy: ["width", "height", "rx", "ry"],
rx: 4, ry: 4,
}, // <rect x="60" y="10" rx="10" ry="10" width="30" height="30"/>
draw: function(event, can, point) {
if (point.length == 1) {return}
draw: function(event, can, point) {if (point.length < 2) {return}
var p0 = point[0], p1 = point[1];
var data = {
"x": p0.x > p1.x? p1.x: p0.x,
"y": p0.y > p1.y? p1.y: p0.y,
"width": Math.abs(p0.x-p1.x),
"height": Math.abs(p0.y-p1.y),
"rx": this.data.rx,
"ry": this.data.ry,
}
can.core.Item(can.onfigure.rect.data, function(key, value) {
data[key] = value
})
can.Status(event, data, "width");
event.type == "click" && point.length == 2 && (can.point = [])
return data;
},
resize: function(event, can, point, current, target) {
target.Value("width", current.width + point[1].x - point[0].x)
target.Value("height", current.height + point[1].y - point[0].y)
return event.type == "click" && point.length == 2 && (can.point = []), data;
},
text: function(event, can, data, target) {
data.x = target.x.baseVal.value+target.width.baseVal.value/2
@ -131,6 +143,30 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
+ " + (" + value.width.baseVal.value + "," + value.height.baseVal.value+ ")"
},
},
line: {
data: {
resize: {width: "x2", height: "y2"},
move: {x: "x1", y: "y1"}, copy: ["x1", "y1", "x2", "y2"],
}, // <line x1="10" x2="50" y1="110" y2="150"/>
draw: function(event, can, point) {if (point.length < 2) {return}
var p0 = point[0], p1 = point[1];
var data = {
"x1": p0.x, "y1": p0.y,
"x2": p1.x, "y2": p1.y,
}
return event.type == "click" && point.length == 2 && (can.point = []), data;
},
text: function(event, can, data, target) {
data.x = (target.x1.baseVal.value + target.x2.baseVal.value) / 2
data.y = (target.y1.baseVal.value + target.y2.baseVal.value) / 2
return data
},
show: function(event, can, value, target) {
return value.tagName
+ ": (" + value.x1.baseVal.value + "," + value.y1.baseVal.value+ ")"
+ " - (" + value.x2.baseVal.value + "," + value.y2.baseVal.value+ ")"
},
},
circle: {
data: {move: {x: "cx", y: "cy"}, copy: ["r"]}, // <circle cx="25" cy="75" r="20"/>
draw: function(event, can, point) {
@ -176,28 +212,6 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
+ " > (" + parseInt(value.rx.baseVal.value) + parseInt(value.ry.baseVal.value) + ")"
},
},
line: {
data: {}, // <line x1="10" x2="50" y1="110" y2="150"/>
draw: function(event, can, point) {
var p0 = point[0], p1 = point[1];
var data = {
"x1": p0.x, "y1": p0.y,
"x2": p1.x, "y2": p1.y,
}
event.type == "click" && point.length == 2 && (can.point = [])
return data;
},
text: function(event, can, data, target) {
data.x = (target.x1.baseVal.value + target.x2.baseVal.value) / 2
data.y = (target.y1.baseVal.value + target.y2.baseVal.value) / 2
return data
},
show: function(event, can, value, target) {
return value.tagName
+ ": (" + value.x1.baseVal.value + "," + value.y1.baseVal.value+ ")"
+ " - (" + value.x2.baseVal.value + "," + value.y2.baseVal.value+ ")"
},
},
path: {
data: {}, // <path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/>
draw: function(event, can, point) {
@ -211,7 +225,6 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
}
}).join(" ")
}
console.log(data)
event.type == "click" && point.length == 4 && (can.point = [])
return data;
},
@ -261,24 +274,27 @@ Volcanos("onfigure", {help: "图形绘制", list: [],
},
},
})
Volcanos("onaction", {help: "组件菜单", list: ["保存",
Volcanos("onaction", {help: "组件菜单", list: ["保存", "清空",
["group", "svg", "add"],
["stroke-width", 1, 2, 3, 4, 5],
["stroke", "red", "yellow", "green", "purple", "blue", "cyan", "white", "black"],
["fill", "red", "yellow", "green", "purple", "blue", "cyan", "white", "black"],
["shape", "move", "resize", "rect", "circle", "ellipse", "path", "line", "polyline", "polygon"],
["fill", "red", "yellow", "green", "purple", "blue", "cyan", "white", "black", "#0000"],
["shape", "move", "select", "resize", "rect", "circle", "ellipse", "path", "line", "polyline", "polygon"],
["grid", 1, 2, 3, 4, 5, 10, 20],
],
"保存": function(event, can, msg, cmd, target) {
can.run(event, ["action", cmd, can.Option("name"), can.Export(event, can.svg, "file")], function() {
can.user.toast("保存成功")
}, true)
},
"清空": function(event, can, msg, cmd, target) {can.svg.innerHTML = ""},
group: function(event, can, value, cmd, target) {
switch (value) {
case "svg": return can.group = can.svg;
case "add":
can.user.prompt("add group", function(name) {
can.svg.append(can.group = document.createElementNS('http://www.w3.org/2000/svg', 'g'))
can.svg.append(can.onaction.init(event, can, value, cmd, can.group = document.createElementNS('http://www.w3.org/2000/svg', 'g')))
can.group.Value("class", name)
can.core.List(["stroke-width", "stroke", "fill"], function(name) {
can.group.Value(name, can.Action(name))
@ -300,11 +316,7 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存",
stroke: function(event, can, value, cmd, target) {can.group.Value(cmd, value)},
fill: function(event, can, value, cmd, target) {can.group.Value(cmd, value)},
shape: function(event, can, value, cmd, target) {can.shape = value},
resize: function(event, can, value, cmd, item) {var target = can.target.firstChild;
if (cmd == "x") {target.style.width = target.offsetHeight + value + "px"}
if (cmd == "y") {target.style.height = target.offsetHeight + value + "px"}
},
grid: function(event, can, value, cmd, target) {can.grid = value},
init: function(event, can, msg, cmd, item) {
item.ondblclick = item.oncontextmenu = function(event) {can.user.carte(event, shy("", can.ondetail, can.ondetail.list, function(event, key, meta) {var cb = meta[key];
@ -312,10 +324,10 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存",
}), can), event.stopPropagation(), event.preventDefault()}
item.onclick = function() {
}
item.Value = function(key, value) {return value && item.setAttribute(key, value), item.getAttribute(key||"class")||""}
item.Value = function(key, value) {return value && item.setAttribute(key, value), item.getAttribute(key||"class")||item[key]&&item[key].baseVal&&item[key].baseVal.value||item[key]&&item[key].baseVal||""}
return item;
},
push: function(event, can, msg, cmd, target) {
push: function(event, can, msg, cmd, target) {cmd = {select: "rect"}[cmd] || cmd
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) {rect.Value(key, value)});
@ -333,11 +345,14 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存",
},
onclick: function(event, can) {if (!can.svg) {return}
var p = can.svg.getBoundingClientRect()
var point = {x: event.clientX-p.x, y: event.clientY-p.y}
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.point = (can.point || []).concat([point])
can.onaction.draw(event, can, can.point)
can.point = (can.point || []).concat([point]);
can.temp && can.page.Remove(can, can.temp) && delete(can.temp);
can.onaction.draw(event, can, can.point);
},
onmouseover: function(event, can) {
can.Status(event, event.target, "which")
@ -345,24 +360,16 @@ Volcanos("onaction", {help: "组件菜单", list: ["保存",
onmousemove: function(event, can) {if (!can.svg || can.point.length == 0) {return}
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.temp && can.page.Remove(can, can.temp) && delete(can.temp)
can.temp = can.onaction.draw(event, can, can.point.concat(point))
can.Status(event, point, "point")
},
onkeydown: function(event, can) {
if (event.key == "Enter") {
can.point = []
return
}
},
})
Volcanos("onchoice", {help: "组件交互", list: ["保存", "清空", ["rect", "rect", "line", "circle"]],
"清空": function(event, can, msg, cmd, target) {
console.log("choice", cmd)
},
})
Volcanos("onchoice", {help: "组件交互", list: ["保存", "清空"]})
Volcanos("ondetail", {help: "组件详情", list: ["编辑", "复制", "删除"],
"编辑": function(event, can, msg, index, key, cmd, target) {
can.user.prompt("文字", function(text) {
@ -387,9 +394,7 @@ Volcanos("ondetail", {help: "组件详情", list: ["编辑", "复制", "删除"]
can.core.List(figure.copy, function(item) {data[item] = target.Value(item)});
return data && can.onaction.push(event, can, data, target.tagName, can.group||can.svg)
},
"删除": function(event, can, msg, index, key, cmd, target) {
can.page.Remove(can, target)
},
"删除": function(event, can, msg, index, key, cmd, target) {can.page.Remove(can, target)},
})
Volcanos("onstatus", {help: "组件状态", list: ["begin", "width", "point", "which"],
"begin": function(event, can, value, cmd, target) {target.innerHTML = value? value.x+","+value.y: ""},

View File

@ -1,4 +1,6 @@
Volcanos("onimport", {help: "导入数据", list: [],
_begin: function(can) {},
_start: function(can) {},
init: function(can, msg, cb, output, action, option) {output.innerHTML = "";
if (msg.append && msg.append.length > 0) {
var table = can.page.AppendTable(can, output, msg, msg.append);
@ -17,12 +19,21 @@ Volcanos("onimport", {help: "导入数据", list: [],
return typeof cb == "function" && cb(msg), table;
}
can.page.Append(can, output, [{view: "preview", inner: msg.Option("preview"), style: {
float: "left", "max-height": "250px", overflow: "auto",
border: "solid 2px red",
}}])
var last = can.page.Append(can, output, [{type: "textarea", cols: 32, rows: 19, inner: msg.Result()}]).last;
return typeof cb == "function" && cb(msg), can.view = last;
can.preview = can.page.Append(can, output, [{view: "preview", inner: msg.Result(),
style: {border: "solid 2px red"},
}]).last
can.page.Select(can, can.preview, ".story", function(item) {
var figure = can.onfigure[item.dataset.type] || can.onfigure[item.localName];
item.onclick = function(event) {can.node = item}
item.oncontextmenu = function(event) {var target = event.target; can.user.carte(event, shy("", can.ondetail, figure.menu||can.ondetail.list, function(event, key, meta) {var cb = meta[key];
typeof cb == "function" && cb(event, can, msg, 0, key, key, target);
}), can), event.stopPropagation(), event.preventDefault()}
figure && figure.init && figure.init({}, can, item.localName, "init", item)
})
return typeof cb == "function" && cb(msg), can.preview;
},
which: function(event, table, list, cb) {if (event.target == table) {return cb(-1, "")}
can.page.Select(can, table, "tr", function(tr, index) {if (event.target == tr) {return cb(index-1, "")}
@ -32,12 +43,235 @@ Volcanos("onimport", {help: "导入数据", list: [],
})
},
})
Volcanos("onaction", {help: "组件菜单", list: ["保存"],
"保存": function(event, can, msg, cmd, target) {
can.run(event, ["action", cmd, can.Option("name"), can.view.value], function() {
Volcanos("onfigure", {help: "图形绘制", list: [],
premenu: {
init: function(event, can, value, cmd, target) {
can.page.Append(can, target, can.page.Select(can, can.preview, "h1.story,h2.story,h3.story", function(item) {var data = item.dataset;
return {text: [item.innerHTML, "li"], onclick: function(event) {
item.scrollIntoView();
}};
}))
},
save: function(event, can, value, cmd, target) {return "premenu"},
},
endmenu: {
init: function(event, can, value, cmd, target) {},
save: function(event, can, value, cmd, target) {return "endmenu"},
},
h1: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "h1", "h1"], dataset: {type: "title", name: "", text: ""}, inner: "h1...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'title "' + value.replace(data.name+" ", "") + '"': ""
},
},
h2: {
push: function(event, can, value, cmd, target) {
return [{view: ["story", "h2", "h2"], dataset: {type: "title", name: "", text: ""}, inner: "h2...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'chapter "' + value.replace(data.name+" ", "") + '"': ""
},
},
h3: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "h3", "h3"], dataset: {type: "title", name: "", text: ""}, inner: "h3...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'section "' + value.replace(data.name+" ", "") + '"': ""
},
},
brief: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "p", "p"], dataset: {type: "brief", name: "", text: ""}, inner: "brief...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'brief "'+data.name+'" `' + value + '`': ""
},
},
refer: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "ul"], dataset: {type: "refer", name: "", text: ""}, list: [{type: "li", inner: "refer...."}]}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'refer "'+data.name+'" `\n' + can.page.Select(can, target, "li", function(item) {
return item.innerHTML.replace(": ", " ")
}).join("\n") + '\n`': ""
},
},
spark: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "p", "p"], dataset: {type: "spark", name: "", text: ""}, inner: "spark...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'spark "'+data.name+'" `' + value + '`': ""
},
},
local: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "div"], dataset: {type: "local", name: "", text: ""}, inner: "local...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'local "'+data.name+'" '+' `' + data.text + '`': ""
},
},
shell: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "code", "code"], dataset: {type: "shell", name: "", text: "", dir: "./"}, inner: "shell...."}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'shell "'+data.name+'" '+'"'+data.dir+'"' +' `' + data.text + '`': ""
},
},
order: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "ul"], dataset: {type: "order", name: "", text: ""}, list: [{type: "li", inner: "order...."}]}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'order "'+data.name+'" `\n' + can.page.Select(can, target, "li", function(item) {
return item.innerHTML
}).join("\n") + '\n`': ""
},
},
table: {
data: {menu: ["追加行", "追加列", "删除行", "删除列"]},
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "table", "table"], dataset: {type: "table", name: "", text: ""}, list: [
{type: "tr", list: [{type: "th"}, {type: "th"}]},
{type: "tr", list: [{type: "td"}, {type: "td"}]},
]}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'table "'+data.name+'" `\n' + can.page.Select(can, target, "tr", function(tr) {
return can.page.Select(can, tr, "th,td", function(td) {
return td.innerHTML
}).join(" ")
}).join("\n") + '\n`': ""
},
},
stack: {
init: function(event, can, value, cmd, target) {var data = target.dataset;
can.page.Select(can, target, "div.stack", function(stack) {var data = stack.dataset||{};
function fold(stack) {
stack.nextSibling && (stack.nextSibling.style.display = "none")
can.page.Select(can, stack, "span.state", function(state) {
if (state.innerText == "o") {return}
can.page.ClassList.add(can, stack, "fold")
can.page.ClassList.del(can, stack, "span")
state.innerText = ">"
})
}
function span(stack) {
stack.nextSibling && (stack.nextSibling.style.display = "")
can.page.Select(can, stack, "span.state", function(state) {
if (state.innerText == "o") {return}
can.page.ClassList.add(can, stack, "span")
can.page.ClassList.del(can, stack, "fold")
state.innerText = "v"
})
}
function mark(stack, color) {
stack.style.background = color;
stack.style.color = color == ""? "": "white";
}
stack.onclick = function(event) {stack.nextSibling && (stack.nextSibling.style.display == "none"? span(stack): fold(stack))}
stack.oncontextmenu = function(event) {var detail = can.feature.detail || can.ondetail.list, target = event.target;
can.user.carte(event, shy("", can.ondetail, ["全部折叠", "全部展开", "标记颜色", "清除颜色", "red", "green", "blue"], function(event, cmd, meta) {var cb = meta[cmd];
switch (cmd) {
case "red":
case "green":
case "blue":
mark(target, cmd)
break
case "标记颜色":
can.user.prompt("请输入颜色:", function(color) {
mark(target, color)
})
break
case "清除颜色":
mark(target, "")
break
case "全部折叠":
fold(stack), can.page.Select(can, stack.nextSibling, "div.stack", fold)
break
case "全部展开":
span(stack), can.page.Select(can, stack.nextSibling, "div.stack", span)
break
}
}))
}
})
},
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["stack", "div"], dataset: {type: "stack", name: "", text: ""}}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'stack "'+data.name+'"' +' `' + data.text + '`': ""
},
},
label: {
init: function(event, can, value, cmd, target) {var data = target.dataset;
target.Value = function(key, value) {return value && target.setAttribute(key, value), target.getAttribute(key||"class")||target[key]&&target[key].baseVal&&target[key].baseVal.value||target[key]&&target[key].baseVal||""}
},
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "svg"], dataset: {type: "story", name: "", text: ""}}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'label "'+data.name+'"' +' `\n' + data.text + '\n`' + " " + [
target.Value("font-size")||16, target.Value("stroke")||"yellow", target.Value("fill")||"blue",
].join(" "): ""
},
},
chain: {
push: function(event, can, value, cmd, target) {var data = target.dataset;
return [{view: ["story", "svg"], dataset: {type: "story", name: "", text: ""}}]
},
save: function(event, can, value, cmd, target) {var data = target.dataset;
return value? 'chain "'+data.name+'"' +' `\n' + data.text + '\n`': ""
},
},
})
Volcanos("onaction", {help: "组件菜单", list: ["保存", ["操作", "只读", "排序", "编辑"],
"插入", ["元素", "h1", "h2", "h3", "brief", "refer", "spark", "shell", "order", "table", "stack"]],
"保存": function(event, can, value, cmd, target) {
var save = can.page.Select(can, target, ".story", function(story) {
var figure = can.onfigure[story.dataset.type] || can.onfigure[story.localName];
return figure && figure.save && figure.save(event, can, story.innerHTML, cmd, story) || story.innerHTML
}).join("\n\n")
can.run(event, ["action", cmd, can.Option("name"), save], function(msg) {
can.user.toast("保存成功")
}, true)
},
"只读": function(event, can, value, cmd, target) {
can.page.Select(can, can.preview, ".story", function(item) {
item.setAttribute("contenteditable", false)
item.setAttribute("draggable", false)
})
},
"排序": function(event, can, value, cmd, target) {
can.page.Select(can, can.preview, ".story", function(item) {
item.setAttribute("draggable", true)
item.ondragstart = function(event) {can.drag = event.target}
item.ondragover = function(event) {event.preventDefault()}
item.ondrop = function(event) {event.preventDefault()
can.preview.insertBefore(can.drag, item)
}
})
},
"编辑": function(event, can, value, cmd, target) {
can.page.Select(can, can.preview, ".story", function(item) {
item.setAttribute("contenteditable", true)
})
},
"插入": function(event, can, value, cmd, target) {var figure = can.onfigure[can.Action("元素")];
can.page.Append(can, can.preview, figure.push(event, can, value, cmd, target)).first.setAttribute("contenteditable", true)
},
})
Volcanos("onchoice", {help: "组件交互", list: ["保存", "清空", ["rect", "rect", "line", "circle"]],
"清空": function(event, can, msg, cmd, target) {
@ -60,20 +294,32 @@ Volcanos("ondetail", {help: "组件详情", list: ["编辑", "删除"],
target.Text = p
}, target.Text && target.Text.innerText || "")
},
"复制": function(event, can, msg, index, key, cmd, target) {
var figure = can.onfigure[target.tagName]
figure.copy(event, can, target)
},
"删除": function(event, can, msg, index, key, cmd, target) {
can.page.Remove(can, target)
},
"删除行": function(event, can, msg, index, key, cmd, target) {
var table = target.parentNode.parentNode
var tr = target.parentNode
table.removeChild(tr)
},
"追加行": function(event, can, msg, index, key, cmd, target) {
var tr = document.createElement("tr")
can.page.Append(can, tr, can.page.Select(can, target.parentNode, "td,th", function() {
return {type: "td", inner: " "}
}))
target.parentNode.parentNode.append(tr)
},
"追加列": function(event, can, msg, index, key, cmd, target) {
var table = target.parentNode.parentNode
var tr = target.parentNode
var index = can.page.Select(can, tr, "th,td", function(item, index) {
return item == target && index || undefined
})[0]
can.page.Select(can, table, "tr", function(tr, index) {
can.page.Append(can, tr, [{type: index == 0? "th": "td", inner: " "}])
})
Volcanos("onstatus", {help: "组件状态", list: ["begin", "width", "point", "which"],
"begin": function(event, can, value, cmd, target) {target.innerHTML = value? value.x+","+value.y: ""},
"width": function(event, can, value, cmd, target) {target.innerHTML = value? value.width+","+value.height: ""},
"point": function(event, can, value, cmd, target) {target.innerHTML = value.x+","+value.y},
"which": function(event, can, value, cmd, target) {var figure = can.onfigure[value.tagName];
target.innerHTML = figure? figure.show(event, can, value, target): value.tagName;
},
})
Volcanos("onexport", {help: "导出数据", list: []})

126
proto.js
View File

@ -14,35 +14,66 @@ function shy(help, meta, list, cb) { // 封装函数
return cb;
}
function Volcanos(name, can, libs, cb, msg) { // 封装模块
// 全局属性
var list = arguments.callee.list || [], meta = arguments.callee.meta || {
create_time: new Date(), path: "/static/volcanos/", index: 1, cache: {},
};
can = can || {};
can._name = name;
// 全局缓存
var list = arguments.callee.list || [], meta = arguments.callee.meta || {index: 1, cache: {}};
arguments.callee.meta = meta, arguments.callee.list = list;
// 定义原型
var id = 1, conf = {}, conf_cb = {}, sync = {}, cache = {};
can[name] || list.push({_name: name, can: can, create_time: new Date()}) && (can.__proto__ = {
_create_time: new Date(), _name: name, _path: "", _help: "插件模块", load: function(name) {
can = can || {}, list.push(can) && (can.__proto__ = {_name: name, _help: "插件模块", _create_time: new Date(), _load: function(name) {
if (meta.cache[name]) {var cache = meta.cache[name];
for (var i = 0; i < cache.length; i++) {var item = cache[i];
if (item.can._name == can._name) {continue}
can[item._name] = item.can;
if (item._name == can._name) {continue}
can[item._name] = item;
}
return can
}
meta.cache[name] = []
for (var i = meta.index; i < list.length; i++) {var item = list[i];
if (item.can._name == can._name || item.can._type == "local") {continue}
can[item._name] = item.can;
if (item._name == can._name || item._type == "local") {continue}
can[item._name] = item;
meta.cache[name].push(item);
}
meta.index = i;
return can
},
require: function(libs, cb) {
if (!libs || libs.length == 0) {
// 加载完成
typeof cb == "function" && setTimeout(function() {cb(can)}, 10);
return
}
if (can[libs[0]]) {
// 已经加载
can.require(libs.slice(1), cb)
return
}
if (meta.cache[libs[0]]) {
// 缓存加载
can._load(libs[0]), can.require(libs.slice(1), cb)
return
}
if (libs[0].endsWith(".wasm")) {var go = new Go();
// 加载汇编
WebAssembly.instantiateStreaming(fetch(libs[0]), go.importObject).then((result) => {
go.argv = [can];
go.run(result.instance);
can.require(libs.slice(1), cb);
}).catch((err) => {
console.error(err);
});
return
}
// 加载脚本
can.Dream(document.body, libs[0].indexOf(".") == -1? libs[0]+".js": libs[0], function() {
can._load(libs[0]), can.require(libs.slice(1), cb);
})
},
ID: shy("生成器", function() {return id++}),
Log: shy("日志器", function() {console.log(arguments)}),
Conf: shy("配置器", function(key, value, cb) {if (key == undefined) {return conf}
@ -78,8 +109,7 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块
msg = event.msg = msg || event.msg || {}, msg.__proto__ = proto || {
_create_time: can.base.Time(), _source: can,
Log: shy("输出日志", function() {console.log(arguments)}),
Ids: function(index, key) {
var id = index;
Ids: function(index, key) {var id = index;
msg && msg.id && (id = msg.id[index]) || msg && msg.name && (id = msg.name[index]);
return id;
},
@ -96,6 +126,25 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块
for (var i = 0; i < arguments.length; i++) {msg.result.push(arguments[i])}
return msg;
}),
Push: function(key, value) {msg.append = msg.append || []
if (typeof key == "object") {
value? can.core.List(value, function(item) {
msg.Push(item, key[item]||"")
}): can.core.Item(key, function(key, value) {
msg.Push(key, value||"")
})
return
}
for (var i = 0; i < msg.append.length; i++) {
if (msg.append[i] == key) {
break
}
}
if (i >= msg.append.length) {msg.append.push(key)}
msg[key] = msg[key] || []
msg[key].push(""+value)
},
Copy: function(res) {
res.result && (msg.result = res.result)
res.append && (msg.append = res.append) && res.append.forEach(function(item) {
@ -128,21 +177,20 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块
return [name, ext, txt]
},
};
msg.event = event
return msg
return msg.event = event, msg
}),
Dream: shy("构造器", function(target, type, line, key) {
if (type.endsWith(".css")) {
var style = document.createElement("link");
style.rel = "stylesheet", style.type = "text/css";
style.href = (type.startsWith("/")? "": (can._path||meta.path))+type
style.href = (type.startsWith("/")? "": Config.volcano)+type;
style.onload = line;
target.appendChild(style);
return style
}
if (type.endsWith(".js")) {
var script = document.createElement("script");
script.src = (type.startsWith("/")? "": (can._path||meta.path))+type,
script.src = (type.startsWith("/")? "": Config.volcano)+type;
script.onload = line;
target.appendChild(script);
return script
@ -181,11 +229,13 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块
}),
Story: shy("存储器", function(type, meta, list) {
}),
}), arguments.callee.meta = meta, arguments.callee.list = list;
});
// 加载模块
function next() {
libs && libs.length > 1? Volcanos(name, can, libs.slice(1), cb): typeof cb == "function" && setTimeout(function() {cb(can); if (can.target) {
can.require(libs, function() {
can.onimport && can.onimport._begin && can.onimport._begin(can)
typeof cb == "function" && cb(can);
if (can.target) {
// 初始化主模块
function run(event, msg, key, cb) {
if (typeof cb == "function") {
// 本地命令
@ -199,41 +249,15 @@ function Volcanos(name, can, libs, cb, msg) { // 封装模块
can.core.Item(can.onaction, function(key, cb) {key.indexOf("on") == 0 && (can.target[key] = function(event) {cb(event, can)})});
// 注册action
can.action && (can.action.innerHTML = ""), can.onaction && can.page.AppendAction(can, can.action, can.onaction.list, function(event, value, key) {
key? run(event, value, key, can.onaction[key]): run(event, msg, value, can.onaction[value]);
key? run(event, value, key, can.onaction[key]||can.onaction[value]): run(event, msg, value, can.onaction[value]);
})
// 注册choice
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()}
}}, 10);
}
if (libs && libs.length > 0) {
if (can[libs[0]]) {
// 重复加载
next()
} else if (meta.cache[libs[0]]) {
// 缓存加载
can.load(libs[0]), next()
} else {
// 加载脚本
if (libs[0].endsWith(".wasm")) {var go = new Go();
WebAssembly.instantiateStreaming(fetch(libs[0]), go.importObject).then((result) => {
go.argv = [can];
go.run(result.instance);
next();
}).catch((err) => {
console.error(err);
});
} else {
can.Dream(document.body, libs[0].indexOf(".") == -1? libs[0]+".js": libs[0], function() {
can.load(libs[0]), next();
can.onimport && can.onimport._start && can.onimport._start(can)
})
}
}
} else {
// 独立模块
next()
}
return can
}

View File

@ -254,6 +254,49 @@ fieldset table td.select {
background-color:red;
}
fieldset div.code {
color:white;
font-size:14px;
font-family:monospace;
background-color:#272822;
white-space:pre;
padding:10px;
overflow:auto;
border:solid 3px green;
max-height:640px;
}
fieldset div.code span.red {
color:red;
}
fieldset div.code span.green {
color:green;
}
fieldset .story {
border:solid 2px #f000;
}
fieldset .story:hover {
border:solid 2px red;
}
fieldset ul.story li:hover {
border:solid 2px red;
cursor:pointer;
}
fieldset code.story {
display:block;
color:white;
font-size:14px;
font-family:monospace;
background-color:#272822;
white-space:pre;
padding:10px;
overflow:auto;
border:solid 3px green;
max-height:640px;
}
fieldset div.stack:hover {
background-color:red;
}
@ -272,20 +315,25 @@ fieldset ul.stack:hover {
border:solid 2px red;
}
fieldset div.code {
color:white;
font-size:14px;
font-family:monospace;
background-color:#272822;
white-space:pre;
padding:10px;
overflow:auto;
border:solid 3px green;
max-height:640px;
fieldset td.over {
border:solid 2px red;
}
fieldset div.code span.red {
sup.more {
color:red;
}
fieldset div.code span.green {
color:green;
fieldset.input {
z-index: 10000;
border:solid 2px yellow;
}
fieldset.input.date table tr:hover {
background-color:yellow;
}
fieldset.input.date table td:hover {
background-color:red;
cursor:pointer;
}
fieldset.input.date table td.now {
background-color:red;
}