diff --git a/base.js b/base.js new file mode 100644 index 00000000..fa10c6e3 --- /dev/null +++ b/base.js @@ -0,0 +1,23 @@ +Volcanos("base", {help: "基础模块", + isNone: function(c) {return c === undefined || c === null}, + isSpace: function(c) {return c == " " || c == "Enter"}, + + Format: shy("数据格式化", function(obj) {return JSON.stringify(obj)}), + Number: shy("数字格式化", function(d, n) {var result = []; + while (d>0) {result.push(d % 10); d = parseInt(d / 10); n--} + while (n > 0) {result.push("0"); n--} + result.reverse(); + return result.join(""); + }), + Time: shy("时间格式化", function(t, fmt) {var now = t? new Date(t): new Date(); + fmt = fmt || "%y-%m-%d %H:%M:%S"; + fmt = fmt.replace("%y", now.getFullYear()) + fmt = fmt.replace("%m", kit.number(now.getMonth()+1, 2)) + fmt = fmt.replace("%d", kit.number(now.getDate(), 2)) + fmt = fmt.replace("%H", kit.number(now.getHours(), 2)) + fmt = fmt.replace("%M", kit.number(now.getMinutes(), 2)) + fmt = fmt.replace("%S", kit.number(now.getSeconds(), 2)) + return fmt + }), +}) + diff --git a/core.js b/core.js new file mode 100644 index 00000000..0d04fdd8 --- /dev/null +++ b/core.js @@ -0,0 +1,23 @@ +Volcanos("core", {help: "核心模块", + Item: shy("迭代器", function(obj, cb) {var list = []; + for (var k in obj) {var res; + list.push(typeof cb == "function" && (res = cb(k, obj[k])) != undefined && res || k) + } + return list + }), + List: shy("迭代器", function(obj, cb, interval, cbs) {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); + } + obj.length > 0 && setTimeout(function() {loop(0)}, interval/4); + return obj; + } + + var list = [], res; + for (var i = 0; i < obj.length; i++) { + typeof cb == "function"? (res = cb(obj[i], i, obj)) != undefined && list.push(res): list.push(res); + } + return list; + }), +}) diff --git a/frame.js b/frame.js new file mode 100644 index 00000000..0dd316c2 --- /dev/null +++ b/frame.js @@ -0,0 +1,101 @@ +var can = Volcanos("chat", { + Plugin: shy("构造插件", function(can, meta, run, field) { + var option = field.querySelector("form.option"); + var action = field.querySelector("div.action"); + var output = field.querySelector("div.output"); + + var name = meta.name, args = meta.args || []; + var feature = JSON.parse(meta.feature||'{}'); + var plugin = Volcanos(name, {type: "local", + Append: shy("添加控件", function(item, cb) {item = item || {type: "text", name: "", className: "args temp"}; + var name = item.name || item.value || "args"+plugin.page.Select(can, option, "input.args.temp").length; + var count = plugin.page.Select(can, option, ".args").length, value = ""; + args && count < args.length && (value = args[count] || item.value || ""); + plugin[name] = can.Inputs(plugin, item, name, value, cb, option); + }), + Select: shy("选择控件", function(event, target, focus) { + can.plugin = field, can.input = target || option.querySelectorAll("input")[1]; + focus && can.input.focus(); + }), + Option: shy("控件参数", function(key, value) { + value != undefined && option[key] && (option[key].value = value) + return key != undefined? option[key] && option[key].value || "": + plugin.page.Select(can, option, ".args", function(item) {return item.value}) + }), + Check: shy("检查控件", function(event, target, cb) { + plugin.page.Select(can, option, ".args", function(item, index, list) { + item == target && index < list.length-1 && can.plugin == field && list[index+1].focus(); + (target == undefined || item == target) && index == list.length-1 && plugin.Runs(event, cb); + return item; + }).length == 0 && plugin.Runs(event, cb) + }), + Runs: shy("执行命令", function(event, cb) {plugin.Run(event, plugin.Option(), cb)}), + Run: shy("执行命令", function(event, args, cb, silent) {var show = !silent; + show && plugin.Timer(1000, function() {show && plugin.user.toast(kit.Format(args||["running..."]), meta.name, -1)}); + run(event, args, function(msg) {if (silent) {return typeof cb == "function" && cb(msg)} + var display = feature.display || "table"; + plugin[display] = can.Output(plugin, display, msg, cb, output, option) + show = false, plugin.user.toast(); + }) + }), + }, ["core", "page", "user", "state"], function(plugin) { + function next(list, cb) { + list && list.length > 0 && cb(list[0], function() { + list.length > 0 && next(list.slice(1), cb) + }) + } + next(JSON.parse(meta.inputs||"[]"), plugin.Append) + + kit.Item(plugin.onaction, function(key, cb) {field[key] = function(event) { + cb(event, plugin, field) + }}) + }) + return plugin.target = field, field.Plugin = plugin + }), + Inputs: shy("构造控件", function(can, item, name, value, cb, option) { + var input = Volcanos(name, {type: "local", + Select: function(event) {can.Select(event, input.target, true)}, + run: function(event) {(input[item.cb] || can[item.cb] || can.Check)(event)}, + + }, ["core", "page", "user", "input"], function(input) {typeof cb == "function" && cb(); + var target = input.onimport.init(can, item, name, value, option); + input.target = target, target.Input = input; + + kit.Item(input.onaction, function(key, cb) {target[key] = function(event) { + cb(event, input, item.type, option); + }}) + }) + return input + }), + Output: shy("构造组件", function(can, type, msg, cb, target, option) { + type = "table" + var output = Volcanos(type, {type: "local", + run: function(event, can, msg, value, index, key) {(output[item.cb] || can[item.cb] || can.Check)(event)}, + size: function(cb) { + can.onfigure.meta.size(function(width, height) { + cb(width, height) + }) + } + }, ["core", "page", "user", type], function(output) { + output.onimport.init(output, msg, cb, target, option) + + kit.Item(output.onaction, function(key, cb) {target[key] = function(event) { + cb(event, output, type, msg, target) + }}) + + target.oncontextmenu = function(event) { + can.user.carte(event, shy("", output.onchoice, output.onchoice.list, function(event, value, meta) { + typeof meta[value] == "function"? meta[value](event, can, msg, cb, target, option): + typeof output[value] == "function"? output[value](event, can, msg, cb, target, option): + typeof can[value] == "function"? can[value](event, can, msg, cb, target, option): null + return true + })) + event.stopPropagation() + event.preventDefault() + return true + } + }) + return output.target = target, target.Output = output + }), +}, ["base", "core", "misc", "page", "user"], function(can) {}) + diff --git a/input.js b/input.js new file mode 100644 index 00000000..2aacabdf --- /dev/null +++ b/input.js @@ -0,0 +1,40 @@ +Volcanos("onimport", {help: "导入数据", list: [], + init: shy("添加控件", function(can, item, name, value, option) { + var input = {type: "input", name: name, data: item} + switch (item.type) { + case "upfile": item.type = "file"; break + case "select": + item.values = kit.Trans(item.values) + input.type = "select", input.list = item.values.map(function(value) { + return {type: "option", value: value, inner: value} + }) + item.value = value || item.value || item.values[0] + can.page.ClassList.add(can, item, "args") + break + case "textarea": + var half = parseFloat(item.half||"1")||1 + input.type = "textarea", item.style = "height:"+(item.height||"50px")+";width:"+parseInt(((pane.target.clientWidth-35)/half))+"px" + // no break + case "text": + can.page.ClassList.add(can, item, "args") + item.value = value || item.value || "" + item.autocomplete = "off" + break + } + can.page.ClassList.add(can, item, item.view) + can.core.List((item.clist||"").split(" "), function(value) { + can.page.ClassList.add(can, item, value) + }) + return can.Dream(option, "input", input)[input.name] + }), +}) +Volcanos("onaction", {help: "控件交互", list: [], + onclick: function(event, can, type, option) {can.Select(event); type == "button" && can.run(event)}, +}) +Volcanos("onchoice", {help: "控件菜单", list: [], +}) +Volcanos("ondetail", {help: "控件详情", list: [], +}) +Volcanos("onexport", {help: "导出数据", list: [], +}) + diff --git a/misc.js b/misc.js new file mode 100644 index 00000000..75001f88 --- /dev/null +++ b/misc.js @@ -0,0 +1,4 @@ +Volcanos("misc", {help: "工具模块", + +}) + diff --git a/page.js b/page.js new file mode 100644 index 00000000..90eb5d44 --- /dev/null +++ b/page.js @@ -0,0 +1,48 @@ +Volcanos("page", {help: "网页模块", + ClassList: { + has: function(can, obj, key) {var list = obj.className? obj.className.split(" "): []; + for (var i = 1; i < arguments.length; i++) { + if (list.indexOf(arguments[i]) == -1) {return false} + } + return true + }, + add: function(can, obj, key) {var list = obj.className? obj.className.split(" "): [] + return obj.className = list.concat(can.core.List(arguments, function(value, index) { + return index > 0 && list.indexOf(value) == -1? value: undefined + })).join(" ") + }, + del: function(can, obj, key) {var list = can.core.List(arguments, function(value, index) {return index > 0? value: undefined}) + return obj.className = can.core.List(obj.className.split(" "), function(value) { + return list.indexOf(value) == -1? value: undefined + }).join(" ") + }, + }, + Display: function(text) { + if (text.startsWith("http")) {return ""+text+""} + return text + }, + + Select: shy("选择器", function(can, obj, key, cb, interval, cbs) { + var item = obj && obj.querySelectorAll(key); + return can.core.List(item, cb, interval, cbs); + }), + Modify: shy("修改节点", function(can, target, value) { + if (typeof value == "string") {target.innerHTML = value} + return target + }), + Append: shy("添加节点", function(can, target, key, value) { + if (typeof key == "string") {var res = document.createElement(key); + return target.appendChild(res), can.page.Modify(can, res, value); + } + }), + AppendTable: shy("添加表格", function(can, target, msg, list) { + var table = can.page.Append(can, target, "table") + var tr = can.page.Append(can, table, "tr"); + can.core.List(list, function(key) {can.page.Append(can, tr, "th", key)}); + msg.Table(function(line) {var tr = can.page.Append(can, table, "tr"); + can.core.List(list, function(key) {can.page.Append(can, tr, "td", can.page.Display(line[key]))}); + }) + return table + }), +}) + diff --git a/volcanos.js b/proto.js similarity index 50% rename from volcanos.js rename to proto.js index ec9aa794..88628afd 100644 --- a/volcanos.js +++ b/proto.js @@ -15,19 +15,30 @@ function shy(help, meta, list, cb) { } function Volcanos(name, can, libs, cb) {var list = arguments.callee.list || [], meta = arguments.callee.meta || { // 全局属性 - path: "/static/volcanos/", index: 1, + create_time: new Date(), path: "/static/volcanos/", index: 1, cache: {}, }; var id = 1, conf = {}, conf_cb = {}, sync = {}; can[name] || list.push({name: name, can: can, create_time: new Date()}) && (can.__proto__ = { // 通用属性 - create_time: new Date(), name: name, help: "静态模块", load: shy("加载器", function() { + create_time: new Date(), name: name, help: "插件模块", 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; + } + return can + } + + meta.cache[name] = [] for (var i = meta.index; i < list.length; i++) {var item = list[i]; - can[item.name] = item.can, item.can.name != can.name && (item.can.name = can.name + "." + item.name); + if (item.can.name == can.name || item.can.type == "local") {continue} + can[item.name] = item.can; + meta.cache[name].push(item); } meta.index = i; return can - }), + }, ID: shy("生成器", function() {return id++}), Log: shy("日志器", function() {console.log(arguments)}), Conf: shy("配置器", function(key, value, cb) {if (key == undefined) {return conf} @@ -78,17 +89,16 @@ function Volcanos(name, can, libs, cb) {var list = arguments.callee.list || [], msg.event = event return msg }), - Dream: shy("构造器", function(target, type, msg, list) { + Dream: shy("构造器", function(target, type, line, key) { + var text = line, list = [], item = false, style = "" switch (type) { - case "table": - var table = can.node.Append(can, target, type) - var tr = can.node.Append(can, table, "tr"); - can.core.List(list, function(key) {can.node.Append(can, tr, "th", key)}); - msg.Table(function(line) {var tr = can.node.Append(can, table, "tr"); - can.core.List(list, function(key) {can.node.Append(can, tr, "td", can.node.Display(line[key]))}); - }) - return table + case "input": + style = " "+line.type + list.push(line) + break } + var ui = kit.AppendChild(target, item? list: [{view: ["item"+style], data: {id: "item"+can.ID(), draggable: false}, list:list}]) + return ui["item"+style].Meta = text, ui }), Cache: shy("缓存器", function(name, data) { if (data == undefined) { @@ -100,17 +110,21 @@ function Volcanos(name, can, libs, cb) {var list = arguments.callee.list || [], }), arguments.callee.meta = meta, arguments.callee.list = list; if (libs && libs.length > 0) { + function next() { + libs.length > 1? Volcanos(name, can, libs.slice(1), cb): setTimeout(function() {cb(can)}, 10); + } if (can[libs[0]]) { // 重复加载 - libs.length > 1? Volcanos(name, can, libs.slice(1), cb): cb(can); + next() + } else if (meta.cache[libs[0]]) { + // 缓存加载 + can.load(libs[0]), next() } else { // 加载脚本 var script = document.createElement("script"); script.src = (can.path||meta.path)+libs[0]+".js"; script.type = "text/javascript"; - script.onload = function() { - can.load(), libs.length > 1? Volcanos(name, can, libs.slice(1), cb): cb(can); - } + script.onload = function() {can.load(libs[0]), next()} document.body.appendChild(script); } } else { @@ -119,86 +133,3 @@ function Volcanos(name, can, libs, cb) {var list = arguments.callee.list || [], return can } -Volcanos("type", {help: "类型模块", - isNone: function(c) {return c === undefined || c === null}, - isSpace: function(c) {return c == " " || c == "Enter"}, - - Format: shy("数据格式化", function(obj) {return JSON.stringify(obj)}), - Number: shy("数字格式化", function(d, n) {var result = []; - while (d>0) {result.push(d % 10); d = parseInt(d / 10); n--} - while (n > 0) {result.push("0"); n--} - result.reverse(); - return result.join(""); - }), - Time: shy("时间格式化", function(t, fmt) {var now = t? new Date(t): new Date(); - fmt = fmt || "%y-%m-%d %H:%M:%S"; - fmt = fmt.replace("%y", now.getFullYear()) - fmt = fmt.replace("%m", kit.number(now.getMonth()+1, 2)) - fmt = fmt.replace("%d", kit.number(now.getDate(), 2)) - fmt = fmt.replace("%H", kit.number(now.getHours(), 2)) - fmt = fmt.replace("%M", kit.number(now.getMinutes(), 2)) - fmt = fmt.replace("%S", kit.number(now.getSeconds(), 2)) - return fmt - }), -}) -Volcanos("core", {help: "核心模块", - List: shy("迭代器", function(obj, cb, interval, cbs) {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); - } - obj.length > 0 && setTimeout(function() {loop(0)}, interval/4); - return obj; - } - - var list = [], res; - for (var i = 0; i < obj.length; i++) { - typeof cb == "function"? (res = cb(obj[i], i, obj)) != undefined && list.push(res): list.push(res); - } - return list; - }), -}) -Volcanos("misc", {help: "其它模块", - -}) -Volcanos("node", {help: "节点模块", - Display: function(text) { - if (text.startsWith("http")) {return ""+text+""} - return text - }, - Select: shy("选择器", function(obj, key, list, cb, interval, cbs) { - var item = obj && obj.querySelectorAll(key); - return list? list(item, cb, interval, cbs): item; - }), - Modify: shy("修改节点", function(can, target, value) { - if (typeof value == "string") {target.innerHTML = value} - return target - }), - Append: shy("添加节点", function(can, target, key, value) { - if (typeof key == "string") {var res = document.createElement(key); - return target.appendChild(res), can.node.Modify(can, res, value); - } - }), - AppendTable: shy("添加表格", function(can, target, msg, list) { - var table = can.node.Append(can, target, "table") - var tr = can.node.Append(can, table, "tr"); - can.core.List(list, function(key) {can.node.Append(can, tr, "th", key)}); - msg.Table(function(line) {var tr = can.node.Append(can, table, "tr"); - can.core.List(list, function(key) {can.node.Append(can, tr, "td", can.node.Display(line[key]))}); - }) - return table - }), -}) -Volcanos("user", {help: "用户模块", - toast: function(text) {}, - alert: function(text) {alert(JSON.stringify(text))}, - confirm: function(text) {return confirm(JSON.stringify(text))}, - prompt: function(text, cb) {(text = prompt(text)) != undefined && typeof cb == "function" && cb(text); return text}, - reload: function() {confirm("重新加载页面?") && location.reload()}, - - isWeiXin: navigator.userAgent.indexOf("MicroMessenger") > -1, - isMobile: navigator.userAgent.indexOf("Mobile") > -1, - isIPhone: navigator.userAgent.indexOf("iPhone") > -1, - isMacOSX: navigator.userAgent.indexOf("Mac OS X") > -1, - isWindows: navigator.userAgent.indexOf("Windows") > -1, -}) diff --git a/state.js b/state.js new file mode 100644 index 00000000..e226e634 --- /dev/null +++ b/state.js @@ -0,0 +1,11 @@ +Volcanos("onimport", {help: "导入数据", list: [], +}) +Volcanos("onaction", {help: "组件交互", list: [], +}) +Volcanos("onchoice", {help: "组件菜单", list: ["copy", "复制", "下载"], +}) +Volcanos("ondetail", {help: "组件详情", list: ["copy", "复制", "下载"], +}) +Volcanos("onexport", {help: "导出数据", list: ["复制", "下载"], +}) + diff --git a/table.js b/table.js index ca91bdb3..dbfc8a0b 100644 --- a/table.js +++ b/table.js @@ -1,11 +1,11 @@ -Volcanos("onimport", { +Volcanos("onimport", {help: "导入数据", list: [], init: function(can, msg, cb, target, option) {target.innerHTML = "" - var table = can.node.AppendTable(can, target, msg, msg.append) + var table = can.page.AppendTable(can, target, msg, msg.append) table.onclick = function(event) { switch (event.target.tagName) { case "TD": can.onimport.which(event, table, msg.append, function(index, key) { - can.onexport.init(event, can, msg, index, key) + can.onexport["复制"](event, can, msg, td.innerHTML) }) break case "TH": @@ -13,19 +13,23 @@ Volcanos("onimport", { case "TABLE": } } - table.oncontextmenu = function(event) { + 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.oncarte(event, shy("", can.ondetail, can.ondetail.list, function(event, value, meta) { - meta[value](event, can, msg, index, key, value) + can.user.carte(event, shy("", can.ondetail, can.ondetail.list, function(event, value, meta) { + var cb = meta[value]; + typeof cb == "function"? cb(event, can, msg, value, index, key, target): + can.run(event, typeof cb == "string"? cb: value, index, key, target) })) }) case "TH": case "TR": case "TABLE": - can.oncarte(event, shy("", can.onchoice, can.onchoice.list, function(event, value, meta) { - meta[value](event, can, msg, value) + can.user.carte(event, shy("", can.onchoice, can.onchoice.list, function(event, value, meta) { + var cb = meta[value]; + typeof cb == "function"? cb(event, can, msg, value, target): + can.run(event, typeof cb == "string"? cb: value, target) })) } event.stopPropagation() @@ -34,31 +38,53 @@ Volcanos("onimport", { typeof cb == "function" && cb(msg); }, which: function(event, table, list, cb) {if (event.target == table) {return cb(-1, "")} - can.node.Select(table, "tr", can.core.List, function(tr, index) {if (event.target == tr) {return cb(index, "")} - can.node.Select(tr, "th,td", can.core.List, function(td, order) { + can.page.Select(can, table, "tr", can.core.List, function(tr, index) {if (event.target == tr) {return cb(index, "")} + can.page.Select(can, tr, "th,td", can.core.List, function(td, order) { if (event.target == td) {return cb(index, list[order])} }) }) }, }) -Volcanos("onaction", {list: [], - onmouseover: function(event, can, msg, cb, target, option) { - msg.Log(event, can, msg, index, key) +Volcanos("onaction", {help: "组件交互", list: [], +}) +Volcanos("onchoice", {help: "组件菜单", list: ["返回", "清空", "复制", "下载", "表格", "绘图", "媒体"], + void: function(event, can, msg, value) { + can.run(event, [value]) + }, + "清空": function(event, can, msg, value, target) { + target.innerHMTL = "" + }, + "复制": function(event, can, msg, value, target) { + can.onexport["复制"](event, can, msg, msg.result && msg.result.join() || "") + }, + "下载": function(event, can, msg, value, target) { + can.onexport["下载"](event, can, msg, "hi", msg.result && msg.result.join() || "") }, }) -Volcanos("onchoice", {list: ["copy", "复制", "下载"], - copy: function(event, can, msg, value) { +Volcanos("ondetail", {help: "组件详情", list: ["选择", "修改", "删除", "复制", "下载"], + void: function(event, can, msg, value, index, key, target) { + can.run(event, [value, index, key, msg[key][index]]) + }, + "选择": "select", + "修改": "modify", + "删除": "delete", + "修改": function(event, can, msg, value, index, key, target) { + var text = target.innerHTML + target.innerHTML = "hi" + }, + "复制": function(event, can, msg, value, index, key, target) { + can.onexport["复制"](event, can, msg, msg[key][index]) + }, + "下载": function(event, can, msg, value, index, key, target) { + can.onexport["下载"](event, can, msg, "hi", msg[key][index]) + }, +}) +Volcanos("onexport", {help: "导出数据", list: ["复制", "下载"], + "复制": function(event, can, msg, value) { can.Log(event, can, msg, value) }, -}) -Volcanos("ondetail", {list: ["copy", "复制", "下载"], - copy: function(event, can, msg, index, key, value) { - can.Log(event, can, msg, index, key, value) - }, -}) -Volcanos("onexport", {list: ["复制", "下载"], - init: function(event, can, msg, index, key) { - can.Log(event, can, msg, index, key) + "下载": function(event, can, msg, name, value) { + can.Log(event, can, msg, name, value) }, }) diff --git a/user.js b/user.js new file mode 100644 index 00000000..80274310 --- /dev/null +++ b/user.js @@ -0,0 +1,15 @@ +Volcanos("user", {help: "用户模块", + toast: function(text) {}, + carte: function(event, cb) {}, + alert: function(text) {alert(JSON.stringify(text))}, + confirm: function(text) {return confirm(JSON.stringify(text))}, + prompt: function(text, cb) {(text = prompt(text)) != undefined && typeof cb == "function" && cb(text); return text}, + reload: function() {confirm("重新加载页面?") && location.reload()}, + + isWeiXin: navigator.userAgent.indexOf("MicroMessenger") > -1, + isMobile: navigator.userAgent.indexOf("Mobile") > -1, + isIPhone: navigator.userAgent.indexOf("iPhone") > -1, + isMacOSX: navigator.userAgent.indexOf("Mac OS X") > -1, + isWindows: navigator.userAgent.indexOf("Windows") > -1, +}) +