diff --git a/frame.js b/frame.js index efe8e5bf..1163e75e 100644 --- a/frame.js +++ b/frame.js @@ -25,6 +25,7 @@ Volcanos("onaction", { _init: function(can, meta, list, cb, target) { can.onengine && getRiver(can.onengine.river) // 应用入口 + can.user.title(can.user.Search(can, "title")) var pane = can[meta.main.name], msg = can.request({}); pane.onaction._init(pane, msg, msg.option||[], cb, target); }) @@ -33,7 +34,7 @@ Volcanos("onaction", { _init: function(can, meta, list, cb, target) { search: function(event, can, msg, pane, cmds, cb) { var chain = cmds[1] var sub, mod = can, key, fun = can; can.core.List(chain.split("."), function(value, index, array) { fun && (sub = mod, mod = fun, key = value, fun = mod[value]) - }); if (!sub || !mod || !fun) { console.error("not found", chain); return } + }); if (!sub || !mod || !fun) { console.info("not found", chain); return } typeof fun == "function" && fun(sub, msg, cmds.slice(2), cb, sub._target) }, @@ -57,8 +58,8 @@ Volcanos("onaction", { _init: function(can, meta, list, cb, target) { typeof cb == "function" && cb(msg) return true case "Action": - var river = can.onengine.river[cmds[0]]; - var storm = river && river.storm[cmds[1]]; + var river = can.onengine.river[cmds[0]||can.user.Search(can, "river")]; + var storm = river && river.storm[cmds[1]||can.user.Search(can, "storm")]; var action = storm && storm.action[cmds[2]]; if (!storm) { break } if (cmds.length == 2) { can.core.List(storm.action, function(value) { @@ -96,6 +97,7 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { var output = can.page.Select(can, field, "div.output")[0]; var status = can.page.Select(can, field, "div.status")[0]; var feature = can.base.Obj(meta.feature) + can.page.ClassList.add(can, field, feature.style||"") // 添加插件 var sub = Volcanos(meta.name, { _help: meta.name, _target: field, @@ -133,6 +135,10 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { _follow: can._follow+"."+meta.name+"."+item.name, }, Volcanos.meta.libs.concat([item.display||"/plugin/input.js"]), function(input) { input.onimport._init(input, input.Conf(item), item.list||[], function() {}, input._target); + if (can.user.Search(can, "active") == meta.name) { + var p = sub.user.Search(can, item.name) || "" + p && (input._target.value = p) + } input.run = function(event, cmds, cb, silent) { // 控件回调 @@ -153,48 +159,9 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { if (!cmds[i]) { cmds.pop() } else { break } } - sub._history.push(cmds); sub.run(event, cmds, function(msg) { - if (silent) { typeof cb == "function" && cb(msg); return } - - // 添加组件 - var display = (msg.Option("_display")||feature.display||"table.js") - display.indexOf("/") == 0 || (display = "/plugin/"+display) - - sub[display] = Volcanos(display, { _help: display, _target: output, - _option: option, _action: action, _output: output, - _follow: can._follow+"."+meta.name+"."+display, - Option: sub.Option, Action: sub.Action, Status: sub.Status, - }, Volcanos.meta.libs.concat(["/frame.js", display]), function(table) { table.Conf(sub.Conf()) - table.onimport._init(table, msg, msg.append||[], function() {}, output) - - table.run = function(event, cmds, cb, silent) { cmds = cmds || [] - // 组件回调 - cmds[0] == "field"? sub.run(event, cmds.slice(1), cb, silent): input.run(event, cmds, cb, silent) - } - - // 工具栏 - action.innerHTML = "", table.onaction && can.core.List(table.onaction.list, function(item) { - typeof item == "string"? can.onappend.input(can, action, "input", {type: "button", value: item, onclick: function(event) { - table.onaction[item](event, table, msg) - }}): item.length > 0? can.onappend.input(can, action, "input", {type: "select", values: item.slice(1), name: item[0], onchange: function(event) { - table.onaction[item[0]](event, table, msg, item[event.target.selectedIndex+1]) - }}): typeof item == "object" && can.onappend.input(can, action, "input", item) - }) - - // 上下文 - table.ondetail && table.ondetail.list && table.ondetail.list.length > 0 && (table._target.oncontextmenu = function(event) { - can.onappend.carte(sub, table.ondetail||{}, msg["_detail"] || sub.Conf("detail"), function(ev, item, meta) { - (table.ondetail[item]||table.onaction[item])(event, table, msg) - }) - }) - - // 状态条 - status.innerHTML = "", table.onexport && can.core.List(table.onexport.list, function(item) { - can.page.Append(can, status, [{view: "item "+item, title: item, list: [{text: [item+": ", "label"]}, {text: ["", "span"]}]}]) - }) - }) - var table = sub[display]; - }, silent) + var msg = sub.request(event); msg.Option("_action", item.name); + cmds[0] != "action" && sub._history.push(cmds); + run(event, cmds, cb, silent) } // 添加事件 @@ -210,6 +177,49 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { } }) }) + + function run(event, cmds, cb, silent) { sub.run(event, cmds, function(msg) { + if (silent) { typeof cb == "function" && cb(msg); return } + + // 添加组件 + var display = (msg.Option("_display")||feature.display||"table.js") + display.indexOf("/") == 0 || (display = "/plugin/"+display) + + sub[display] = Volcanos(display, { _help: display, _target: output, + _option: option, _action: action, _output: output, + _follow: can._follow+"."+meta.name+"."+display, + Option: sub.Option, Action: sub.Action, Status: sub.Status, + }, Volcanos.meta.libs.concat(["/frame.js", display]), function(table) { table.Conf(sub.Conf()) + table.onimport._init(table, msg, msg.result||[], function() {}, output) + + table.run = function(event, cmds, cb, silent) { cmds = cmds || [] + sub.run(event, cmds, cb, silent) + } + + // 工具栏 + action.innerHTML = "", table.onaction && can.core.List(table.onaction.list, function(item) { + typeof item == "string"? can.onappend.input(can, action, "input", {type: "button", value: item, onclick: function(event) { + table.onaction[item](event, table, msg) + }}): item.length > 0? can.onappend.input(can, action, "input", {type: "select", values: item.slice(1), name: item[0], onchange: function(event) { + table.onaction[item[0]](event, table, msg, item[event.target.selectedIndex+1]) + }}): typeof item == "object" && can.onappend.input(can, action, "input", item) + }) + + // 上下文 + table.ondetail && table.ondetail.list && table.ondetail.list.length > 0 && (table._target.oncontextmenu = function(event) { + can.onappend.carte(sub, table.ondetail||{}, msg["_detail"] || sub.Conf("detail"), function(ev, item, meta) { + (table.ondetail[item]||table.onaction[item])(event, table, msg) + }) + }) + + // 状态条 + status.innerHTML = "", table.onexport && can.core.List(table.onexport.list, function(item) { + can.page.Append(can, status, [{view: "item "+item, title: item, list: [{text: [item+": ", "label"]}, {text: ["", "span"]}]}]) + }) + }) + var table = sub[display]; + }, silent) } + }); cb(sub); }, item: function(can, target, type, item, cb, cbs) { @@ -280,7 +290,7 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { return target; }, table: function(can, target, type, msg) { - var table = can.page.AppendTable(can, can._output, msg, msg.append, function(event, value, key, index, tr, td) { + var table = can.page.AppendTable(can, target, msg, msg.append, function(event, value, key, index, tr, td) { can.page.Select(can, can._option, "input.args", function(input) { if (input.name == key) { var data = input.dataset || {} input.value = value; if (data.action == "auto") { can.run(event, [], function(msg) {}) @@ -320,7 +330,7 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { }) }, board: function(can, target, type, msg) { - msg.result && can.page.AppendBoard(can, can._output, can.page.Display(msg.Result())) + msg.result && can.page.AppendBoard(can, target, can.page.Display(msg.Result())) }, carte: function(can, meta, list, cb) { list = list && list.length > 0? list: meta.list; if (list.length == 0) { return } @@ -394,7 +404,44 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { can.page.Modify(can, can._toast, {style: {display: "none"}}) }]}] }); }) - } + }, + + upload: function(can) { var begin = new Date(); + can._upload = can._upload || can.page.Append(can, can._target, [{view: "upload", list: [{view: "action"}, {view: "output"}]}]) + + function show(event, value, total, loaded) { + var now = new Date(); can.page.Appends(can, can._upload.output, [ + {view: ["progress"], style: {height: "10px", border: "solid 2px red"}, list: [{ + view: ["progress"], style: {height: "10px", width: value + "%", background: "red"}, + }]}, + {text: [value+"%", "div"], style: {"float": "right"}}, + {text: [can.base.Duration(now - begin), "div"], style: {"float": "left"}}, + {text: [can.base.Size(loaded)+"/"+can.base.Size(total), "div"], style: {"text-align": "center"}}, + ]); + } + + var action = can.page.AppendAction(can, can._upload.action, [ + {type: "input", data: {name: "upload", type: "file", onchange: function(event) { + var file = action.upload.files[0] + show(event, 0, file.size, 0) + }}, style: {width: "200px"}}, "上传", "关闭"], function(event, value, cmd) { + if (action.upload.files.length == 0) {return action.upload.focus()} + if (value == "关闭") {can._upload.stick = false; return can.page.Remove(can, can._upload.output.parentNode)} + + var msg = can.request(event); + can.page.Select(can, can._option, "input", function(item) { + item.name && item.value && msg.Option(item.name, item.value) + }) + + // 上传文件 + begin = new Date(); + msg._progress = show + msg.upload = action.upload.files[0]; + can.run(event, ["action", "upload"], function(msg) { + can.onappend.toast(can, "上传成功") + }, true); + }) + }, }, [], function(can) {}) Volcanos("onlayout", { _init: function(can, meta, list, cb, target) { var width = can._width, height = can._height; diff --git a/index.css b/index.css index ce4b6ed4..8f89df5e 100644 --- a/index.css +++ b/index.css @@ -77,6 +77,17 @@ fieldset>div.action { fieldset>div.action>div.item { float:left; } +fieldset>div.action>div.item>input { + color:cyan; + background:black; +} +fieldset>div.action>div.item>input:hover { + background:gray; +} +fieldset>div.action>div.item>select { + color:cyan; + background:black; +} fieldset>div.status>div.item { float:left; padding:4px; @@ -86,27 +97,32 @@ fieldset>div.status>div.item>label { color:gray; } -fieldset div.output { +fieldset>div.output { margin-top:4px; clear:both; overflow:auto; + position:relative; } -fieldset div.output>div.project { +fieldset>div.output>div.project { float:left; + /* position:fixed; */ } -fieldset div.output>div.project>div.item { +fieldset>div.output>div.project>div.item { clear:both; } -fieldset div.output>div.project>div.item:hover { +fieldset>div.output>div.project>div.item:hover { border:solid 1px red; } -fieldset div.output>pre.display { - padding:4px; - max-height:80px; - border:solid 2px red; - margin:0; - overflow:auto; +fieldset>div.output>pre.profile { + float:right; } +fieldset>div.output>div.profile>div.item { + clear:both; +} +fieldset>div.output>div.profile>div.item:hover { + border:solid 1px red; +} + fieldset div.code { color:white; font-size:14px; @@ -172,7 +188,8 @@ div.toast { border:solid 2px red; position:absolute; padding:5px; - color:yellow + color:yellow; + z-index:100; } div.toast div.title { font-size:14px; @@ -185,3 +202,17 @@ div.toast div.duration { font-size:14px; color:gray; } + +div.upload { + background:black; + border:solid 2px red; + position:absolute; + padding:5px; + color:yellow; + z-index:100; + left:20px; + top:20px; +} +div.upload div.item { + float:left; +} diff --git a/lib/core.js b/lib/core.js index dc5904fd..e671382e 100644 --- a/lib/core.js +++ b/lib/core.js @@ -62,7 +62,9 @@ Volcanos("core", {help: "核心模块", }), Split: shy("分词器", function(str) { if (!str || !str.length) {return []} - var arg = []; for (var i = 1; i < arguments.length; i++) { arg.push(arguments[i]) } + var opt = {simple: false}, arg = []; for (var i = 1; i < arguments.length; i++) { + typeof arguments[i] == "object"? opt=arguments[i]: arg.push(arguments[i]) + } function trans(str) { var res = {}; for (var i = 0; i < str.length; i++) { res[str[i]] = true }; return res } // 空白符 @@ -74,36 +76,28 @@ Volcanos("core", {help: "核心模块", // 开始分词 var res = [], list = str; - var left = '\000', space = true, begin = 0; + var left = "", space = true, begin = 0; for (var i = 0; i < list.length; i++) { if (seps[list[i]]) { // 空白符 - if (left == '\000') { + if (left == "") { if (!space) { res.push(list.slice(begin, i)) } - res.push({text: list.slice(i, i+1), type: "space", left: left}) + opt.simple || res.push({text: list.slice(i, i+1), type: "space", left: left}) space = true, begin = i+1 } } else if (subs[list[i]]) { // 引用符 - if (arg.length > 0) { - if (left == '\000') { - left = list[i] - } else if (left == list[i]) { - left = '\000' - } - } else { - if (left == '\000') { - left = list[i], space = false, begin = i+1 - } else if (left == list[i]) { - res.push({text: list.slice(begin, i), type: "string", left: left}) - left = '\000', space = true, begin = i+1 - } + if (left == "") { + left = list[i], space = false, begin = i+1 + } else if (left == list[i]) { + res.push({text: list.slice(begin, i), type: "string", left: left}) + left = "", space = true, begin = i+1 } } else if (sups[list[i]]) { // 分隔符 - if (left == '\000') { + if (left == "") { if (!space) { res.push(list.slice(begin, i)) } diff --git a/page/share.html b/page/share.html index 7c42a158..c565d338 100644 --- a/page/share.html +++ b/page/share.html @@ -4,7 +4,7 @@ volcanos - + diff --git a/page/share.js b/page/share.js index 1c958835..772f1146 100644 --- a/page/share.js +++ b/page/share.js @@ -1,26 +1,13 @@ -var Config = {name: "demo", volcano: "/frame.js", iceberg: "/chat/", intshell: "plug.sh", +Volcanos({name: "demo", volcano: "/frame.js", iceberg: "/chat/", intshell: "plug.sh", libs: ["/lib/base", "/lib/core", "/lib/misc", "/lib/page", "/lib/user"], panes: [ {type: "pane", name: "Action", help: "工作台", pos: "middle", list: ["/pane/Action.js", "/pane/Action.css"]}, - ], main: {name: "Action", engine: "remote", list: []}, - list: ["/plugin/state.js", "/plugin/input.js", "/plugin/table.js", + ], main: {name: "Action", engine: "remote", list: ["/publish/order.js"]}, plugin: [ + "/plugin/state.js", + "/plugin/input.js", + "/plugin/table.js", "/plugin/input/key", "/plugin/input/date", "/plugin/input/upload", "/plugin/input/province", ], -} - -var Preload = Config.libs; Config.panes.forEach(function(pane) { - Preload = Preload.concat(pane.list); -}); Preload = Preload.concat(Config.list) - -Volcanos(Config.name, { _target: document.body, _follow: "demo", - _head: document.head, _body: document.body, - _width: window.innerWidth, _height: window.innerHeight, -}, Preload.concat(Config.volcano), function(can) { // 程序入口 - can.onaction._init(can, can.Conf(Config), [], function(msg) { - console.log(can._root, can._name, "start", can, msg); - }, can._target) }) - - diff --git a/pane/Action.css b/pane/Action.css index 35051458..a7df8780 100644 --- a/pane/Action.css +++ b/pane/Action.css @@ -17,7 +17,7 @@ fieldset.Action fieldset.plugin legend { margin-top:5px; } fieldset.Action fieldset.plugin form.option div.item { - margin:5px; + margin:2px; } fieldset.Action fieldset.plugin div.output { margin:5px; diff --git a/pane/Action.js b/pane/Action.js index c1c0f99d..d0067073 100644 --- a/pane/Action.js +++ b/pane/Action.js @@ -32,6 +32,8 @@ Volcanos("onexport", {help: "导出数据", list: [], {type: "button", name: "查看", action: "auto"}, {type: "button", name: "返回"}, ]); + value.width = can._target.offsetWidth + value.height = can._target.offsetHeight can.onappend._init(can, value, Volcanos.meta.libs.concat(["/plugin/state.js"]), function(sub) { sub.run = function(event, cmds, cb, silent) { var msg = can.request(event, event._msg||{_msg: sup}); // 插件回调 diff --git a/plugin/inner.css b/plugin/inner.css index 4bc00988..434779d4 100644 --- a/plugin/inner.css +++ b/plugin/inner.css @@ -1,62 +1,116 @@ -fieldset.editor>div.output textarea.editor { - font-family:monospace; - background-color:black; - color:white; - border:solid 1px red; - padding:0; - width:0; - height:20px; - margin:0; - position:relative; - float:right; -} -fieldset.editor>div.output div.lineno { - font-family:monospace; +fieldset.editor>div.action>div.file { + border:solid 2px red; + padding:2px; float:left; } -fieldset.editor>div.output div.lineno>div.item { - text-align:right; - border:solid 1px black; - padding:0 4px; - height:20px; - margin:0; +fieldset.editor>div.action>div.file:hover { + background-color:green; + cursor:pointer; } -fieldset.editor>div.output div.lineno>div.item:hover { +fieldset.editor>div.action>div.file.select { background-color:green; } -fieldset.editor>div.output div.lineno>div.item.select { +fieldset.editor>div.output { + min-height:300px; +} +fieldset.editor>div.output>div.project { + width:80px; overflow:auto; + position:fixed; +} +fieldset.editor>div.output>div.profile { + position:absolute; right:0; + width:80px; overflow:auto; +} +fieldset.editor>div.output>div.profile:hover { + position:absolute; right:0; + width:480px; +} + +fieldset.editor>div.output div.preview { + font-family:monospace; + float:left; margin-left:80px; +} +fieldset.editor>div.output div.preview>div.item { + text-align:right; + height:20px; border:solid 1px black; + padding:0 4px; margin:0; +} +fieldset.editor>div.output div.preview>div.item:hover { + background-color:green; +} +fieldset.editor>div.output div.preview>div.item.select { background-color:red; } fieldset.editor>div.output div.content { - font-family:monospace; + font-size:16px; font-family:monospace; border-left:solid 2px red; padding-left:10px; } fieldset.editor>div.output div.content>pre.item { - border:solid 1px black; - padding:0; - height:20px; - margin:0; -} -fieldset.editor>div.output div.content>pre.item span.comment { - background-color:blue; - color:cyan; -} -fieldset.editor>div.output div.content>pre.item span.keyword { - color:yellow; - font-weight:bold; -} -fieldset.editor>div.output div.content>pre.item span.function { - color:cyan; - font-weight:bold; -} -fieldset.editor>div.output div.content>pre.item span.datatype { - color:lightgreen; - font-weight:bold; -} -fieldset.editor>div.output div.content>pre.item span.string { - color:magenta; + height:20px; border:solid 1px black; + padding:0; margin:0; } fieldset.editor>div.output div.content>pre.item:hover { border:solid 1px red; } +fieldset.editor>div.output div.content>pre.item span.comment { + background-color:blue; color:cyan; +} +fieldset.editor>div.output div.content>pre.item span.keyword { + font-weight:bold; + color:yellow; +} +fieldset.editor>div.output div.content>pre.item span.function { + font-weight:bold; + color:cyan; +} +fieldset.editor>div.output div.content>pre.item span.datatype { + font-weight:bold; + color:lightgreen; +} +fieldset.editor>div.output div.content>pre.item span.string { + color:magenta; +} +fieldset.editor>div.output pre.display { + padding:6px; border:solid 1px red; + max-height:80px; overflow:auto; + position:sticky; bottom:0; + display:none; +} +fieldset.editor>div.output pre.display:hover { + background-color:black; + max-height:360px; + z-index:100; +} + +fieldset.editor>div.output textarea.editor.normal { + background-color:#00000000; color:#00000000; + caret-color:#00000000; +} +fieldset.editor>div.output textarea.editor { + font-size:16px; font-family:monospace; + background-color:black; color:white; + caret-color:yellow; + + position:absolute; left:0; + border:solid 1px red; + width:0; height:20px; + padding:0; margin:0; + + background-color:#00000000; color:#00000000; + padding-left:12px; + display:none; +} +fieldset.editor>div.output textarea.command { + background-color:black; color:white; + font-family:monospace; + caret-color:red; + + position:sticky; bottom:0; + width:0; height:20px; + border:solid 1px red; + padding:0; margin:0; + padding-left:10px; + z-index:10; +} + diff --git a/plugin/inner.js b/plugin/inner.js index b48a7571..68554f5f 100644 --- a/plugin/inner.js +++ b/plugin/inner.js @@ -1,71 +1,125 @@ -Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, target) { target.innerHTML = ""; - // can.onappend.table(can, target, "table", msg); +Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, target) { target.innerHTML = "" + var width = can.Conf("width"), height = can.Conf("height") + can.page.Modify(can, target, {style: {"max-height": height-160+"px"}}) - can.history = [] - can.ui = can.page.Append(can, target, [{view: ["editor", "textarea"], onkeydown: function(event) { - can.history.push(event.key); if (can.mode != "insert") { - event.stopPropagation() - event.preventDefault() - } - - can.Status("输入值", can.history.join()) - var cb = can.onkeymap[can.mode][event.key] - if (typeof cb == "function") { return cb(event, can), can.history = [] } - - var map = can.onkeymap[can.mode]._engine - for (var i = can.history.length-1; i > -1; i--) { - var pos = map[can.history[i]] - if (typeof pos == "object") { map = pos; continue } - if (typeof pos == "function") { pos(event, can); can.history = [] } break - } - }, onkeyup: function(event) { - - }, onblur: function(event) { - can.onaction.modifyLine(can, can.current, can.editor.value) - }}, + msg.Option("_action") != "查看" && can.onappend.table(can, target, "table", msg) + can.ui = can.page.Append(can, target, [ {view: ["project", "div"], style: {width: "80px"}}, - {view: "lineno", style: {width: "30px"}}, - {view: "content"}, - {view: "preview"}, {view: ["display", "pre"]}, - ]); - can.onlayout.show_project(can); - can.onlayout.show_project(can); + {view: ["profile", "div"]}, - can.core.List(can.onkeymap.list, function(item) { var engine = {}; - can.core.Item(can.onkeymap[item], function(key, cb) { var map = engine; - for (var i = key.length-1; i > -1; i--) { - map = map[key[i]] = i == 0? cb: (map[key[i]]||{}); + {view: "preview", style: {width: "30px"}}, + {view: "content"}, {type: "code", list: [{view: ["display", "pre"]}]}, + + {view: ["command", "textarea"], onkeydown: function(event) { + can.onkeymap.parse(event, can, "command") + }}, + {view: ["editor", "textarea"], onkeydown: function(event) { + can.onkeymap.parse(event, can, "insert"), can.Timer(10, function() { + can.onaction.modifyLine(can, can.current, can.editor.value) + }) + }, onblur: function(event) { + can.onaction.modifyLine(can, can.current, can.editor.value) + }}, + ]) + + msg.Option("path", can.Option("path")) + msg.Option("name", can.Option("name")) + can.tabview = {}, can.Timer(10, function() { + can.onlayout._init(can) + can.onkeymap._init(can, "normal") + can.onimport.project(can, can.Option("path")) + can.onimport.tabview(can, can.Option("path"), can.Option("name")) + }) + return typeof cb == "function" && cb(msg) + }, + tabview: function(can, path, name) { + can.Option("path", path) + can.Option("name", name) + if (can.tabview[path+name]) { return can.onsyntax._init(can, can.tabview[path+name]) } + + var p = can.onsyntax[can.parse] + !p && can.run({}, ["action", "plug", can.Option("path"), can.Option("name")], function(msg) { + can.onsyntax[can.parse] = p + }, true) + + can.run({}, [path, name], function(msg) { + msg.Option("path", can.Option("path")) + msg.Option("name", can.Option("name")) + + can.page.Append(can, can._action, [{view: ["file", "div", name], onclick: function(event) { + can.onsyntax._init(can, msg) + }}]), can.onsyntax._init(can, can.tabview[path+name] = msg) + }, true) + }, + project: function(can, path) { can.ui.project.innerHTML = "" + can.Option("path", path) + can.run({}, ["action", "project", path], function(res) { + res.Table(function(value) { can.page.Append(can, can.ui.project, [{text: [value.file, "div", "item"], onclick: function(event) { + if (value.file.endsWith("/")) { + can.onimport.project(can, can.Option("path", can.base.Path(can.Option("path"), value.file))) + } else { + can.onimport.tabview(can, can.Option("path"), can.Option("name", value.file)) } - }) - can.onkeymap[item]._engine = engine - }) - console.log(can.onkeymap) - - var ls = can.Option("name").split("."); - can.parse = ls.pop()||"txt"; - can.editor = can.ui.editor, can.max = 0, can.ls = msg.Result().split("\n"); - can.core.List(can.ls, function(item) { can.onaction.appendLine(can, item) }); - can.Timer(100, function() { - can.onaction.project(can); - can.onaction.selectLine(can, 0); - can.onaction.mode(null, can, null, "normal"); - can.Status("文件名", can.Option("name")) - can.Status("解析器", can.parse) - }) - return typeof cb == "function" && cb(msg); + }} ]) }) + }, true) }, }, ["/plugin/inner.css"]) -Volcanos("onsyntax", {help: "语法高亮", list: ["normal", "insert"], - parse: function(can, line) { var p = can.onsyntax[can.parse]; +Volcanos("onsyntax", {help: "语法高亮", list: ["keyword", "prefix", "line"], _init: function(can, msg) { + var file = can.base.Path(msg.Option("path"), msg.Option("name")) + + // option + can.core.List(["path", "name"], function(item) { + can.Option(item, msg.Option(item)) + }) + // action + can.page.Select(can, can._action, "div.file", function(item) { + item.innerText == msg.Option("name")? can.page.ClassList.add(can, item, "select"): can.page.ClassList.del(can, item, "select") + }) + + // caches + can.core.List(["preview", "content", "display"], function(item) { + can.Cache(can.file+item, can.ui[item], can.current) + }); + // caches + can.file = file; var cache = false; can.core.List(["preview", "content", "display"], function(item) { + var p = can.Cache(can.file+item, can.ui[item]); if (p) { p.click(), cache = true } + }); if (cache) { return } + + // remote + can.ui.preview.innerHTML = "" + can.ui.content.innerHTML = "" + can.parse = file.split(".").pop()||"txt" + can.max = 0, can.core.List(can.ls = msg.Result().split("\n"), function(item) { + can.onaction.appendLine(can, item) + }) + + // status + can.Status("当前行", can.onexport.position(can, 0)) + can.Status("文件名", can.file), can.Status("解析器", can.parse) + + // plugin + function init() { + can.onkeymap._remote(event, can, "运行") + typeof p.display == "object" && ( + p.display.height && can.page.Modify(can, can.ui.display, {style: { + "max-height": p.display.height, + }}) + ) + }; var p = can.onsyntax[can.parse]; !p? can.run({}, ["action", "plug", can.Option("path"), can.Option("name")], function(msg) { + can.onsyntax[can.parse] = p = can.base.Obj(msg.Result()), p.display && init() + }, true): p.display && init() + }, + parse: function(can, line) { var p = can.onsyntax[can.parse] function wrap(type, str) { return type? ''+str+'': str } - p && p.keyword && (line = can.core.List(can.core.Split(line), function(item, index, array) { - var text = item.text || item; - var key = p.keyword[text]; + p && p.keyword && (line = can.core.List(can.core.Split(line, " ", p.split.operator), function(item, index, array) { + item = typeof item == "object"? item: {text: item} + p.word && (item = p.word(item, index, array)) + var text = item.text; var key = item.keyword||p.keyword[text] switch (item.type) { - case "string": return wrap("string", item.left+text+item.left); case "space": return text - default: return wrap(key, text); + case "string": return wrap("string", item.left+text+item.left) + default: return wrap(key, text) } }).join("")) @@ -75,47 +129,43 @@ Volcanos("onsyntax", {help: "语法高亮", list: ["normal", "insert"], return p && p.line? p.line(can, line): line }, sh: { + display: true, + split: {}, keyword: { - "require": "keyword", - "export": "keyword", - "source": "keyword", - }, - prefix: { - "#": "comment", - }, - line: function(can, line) { - return line + export: "keyword", + source: "keyword", + require: "keyword", }, + prefix: {"#": "comment"}, + line: function(can, line) { return line }, }, vim: { + split: {}, keyword: { - syntax: "keyword", highlight: "keyword", + syntax: "keyword", }, - prefix: { - "\"": "comment", - }, + prefix: {"\"": "comment"}, }, shy: { - keyword: { - }, - prefix: { - "~": "keyword", - "#": "comment", - }, + profile: true, + display: true, + split: {}, + line: function(can, line) { return line }, }, mod: { + split: {}, keyword: { "module": "keyword", "require": "keyword", "replace": "keyword", "=>": "keyword", }, - prefix: { - "#": "comment", - }, + prefix: {"#": "comment"}, }, go: { + display: true, + split: {}, keyword: { "package": "keyword", "import": "keyword", @@ -158,142 +208,332 @@ Volcanos("onsyntax", {help: "语法高亮", list: ["normal", "insert"], "msg": "function", "kit": "keyword", }, + prefix: {"//": "comment"}, + }, + js: { + display: true, + split: { + space: " ", + operator: "{[(.:,;!|)]}", + }, + keyword: { + "var": "keyword", + "new": "keyword", + "delete": "keyword", + "typeof": "keyword", + "function": "keyword", + + "if": "keyword", + "else": "keyword", + "for": "keyword", + "while": "keyword", + "break": "keyword", + "continue": "keyword", + "switch": "keyword", + "case": "keyword", + "default": "keyword", + "return": "keyword", + + "window": "function", + "console": "function", + "document": "function", + "arguments": "function", + "event": "function", + "Date": "function", + "JSON": "function", + + "0": "string", + "1": "string", + "-1": "string", + "true": "string", + "false": "string", + "undefined": "string", + "null": "string", + + "__proto__": "function", + "setTimeout": "function", + "createElement": "function", + "appendChild": "function", + "removeChild": "function", + "parentNode": "function", + "childNodes": "function", + + "Volcanos": "function", + "request": "function", + "require": "function", + + "cb": "function", + "cbs": "function", + "shy": "function", + "can": "function", + "sub": "function", + "msg": "function", + "res": "function", + "pane": "function", + "plugin": "function", + }, + prefix: {"//": "comment"}, + word: function(value, index, array) { + var libs = { + base: true, + core: true, + misc: true, + page: true, + user: true, + } + return array[index-2]=="can"&&array[index-1]=="."&&(libs[value]||libs[value.text])? {keyword: "function", text: value.text||value}: value + }, + }, + + png: { + line: function(can, line) { return can.page.Format("img", "/share/local/"+line) } + }, + m4v: { + keymap: { + j: function(event, can) { + console.log("down") + }, + k: function(event, can) { + }, + }, + display: true, + line: function(can, line) { var auto = false, loop = true + var total = 0 + function cb(event) { console.log(event) } + return {className: "preview", type: "video", style: {height: can.Conf("height")-160+"px", width: can.Conf("width")-160+"px"}, + data: {src: "/share/local/"+line, controls: "controls", autoplay: auto, loop: loop}, + oncontextmenu: cb, onplay: cb, onpause: cb, onended: cb, + onloadedmetadata: function(event) { total = event.timeStamp }, onloadeddata: cb, ontimeupdate: function(event) { + can.Status("当前行", can.onexport.position(can, event.target.currentTime-1, event.target.duration)) + }, + } + }, }, }) -Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert"], - _command: function(can) { can.onaction.mode(null, can, null, "command") }, - _normal: function(can) { can.onaction.mode(null, can, null, "normal") }, - _insert: function(can) { can.onaction.mode(null, can, null, "insert") }, +Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert"], _init: function(can, mode) { + can.page.Modify(can, can.ui.command, {style: {display: "none", width: can._target.offsetWidth-20+"px"}}) + + can.history = [], can.editor = can.ui.editor + can.core.List(can.onkeymap.list, function(item) { var engine = {} + can.core.Item(can.onkeymap[item], function(key, cb) { var map = engine + for (var i = key.length-1; i > -1; i--) { + map = map[key[i]] = i == 0? cb: (map[key[i]]||{}) + } + }), can.onkeymap[item]._engine = engine + }), can.onkeymap._mode(can, mode||"normal") + }, + _mode: function(can, value) { can.Status("输入法", can.mode = value) + can.ui.editor.className = "editor "+can.mode + can.Action("mode", can.mode) + return value + }, + _command: function(can) { can.onkeymap._mode(can, "command") + can.page.Modify(can, can.ui.command, {value: "", style: {display: "block"}}) + can.ui.command.focus() + }, + _normal: function(can) { can.onkeymap._mode(can, "normal") }, + _insert: function(can) { can.onkeymap._mode(can, "insert") }, + + _remote: function(event, can, key, arg) { can.ui.display.innerHTML = "", can.ui.profile.innerHTML = "" + var p = can.onsyntax[can.parse] + can.display = p && p.profile && can.ui.profile || can.ui.display + var msg = can.request(event); msg.Option("content", can.onexport.content(can)) + can.run(event, arg||["action", key, can.Option("path"), can.Option("name")], function(msg) { + can.page.Modify(can, can.display, {innerHTML: "", style: {display: "block"}}) + can.onappend.table(can, can.display, "table", msg) + can.onappend.board(can, can.display, "board", msg) + }, true) + }, _engine: { - w: function(event, can) { - can.onaction.remote(event, can, null, "保存") + w: function(event, can) { can.onkeymap._remote(event, can, "保存") }, + e: function(event, can, line, ls) { ls = ls[1].split("/") + can.onimport.tabview(can, ls.slice(0, -1).join("/"), ls.slice(-1).join("")) }, + r: function(event, can) { can.onkeymap._remote(event, can, "运行") }, + + commit: function(event, can) { can.onkeymap._remote(event, can, "提交") }, + history: function(event, can) { can.onkeymap._remote(event, can, "历史") }, + }, + + parse: function(event, can, mode) { + event.key.length == 1 && can.history.push(event.key); if (can.mode != mode) { + event.stopPropagation(), event.preventDefault() + }; can.mode != "command" && can.Status("输入值", can.history.join()) + + for (var pre = 0; pre < can.history.length; pre++) { + if ("0" <= can.history[pre] && can.history[pre] <= "9") { continue } break + }; can.count = parseInt(can.history.slice(0, pre).join("")) + + var p = can.onsyntax[can.parse] + var cb = (p&&p.keymap||can.onkeymap[can.mode])[event.key]; if (typeof cb == "function") { + return cb(event, can, can.count), can.history = [] + } + + var map = can.onkeymap[can.mode]._engine; for (var i = can.history.length-1; i > pre-1; i--) { + var cb = map[can.history[i]]; if (typeof cb == "function") { + return cb(event, can, can.count), can.history = [] + }; if (typeof cb == "object") { map = cb; continue }; break + } }, command: { - Enter: function(event, can) { can.onkeymap._normal(can); - var line = can.history.slice(0, -1).join(""); - var cb = can.onkeymap._engine[line]; if (typeof cb == "function") { - return cb(event, can) - } - can.run(event, ["action", line, can.base.Path(can.Option("path"), can.Option("name"))], function(res) { - can.ui.display.innerHTML = res.Result() - }, true); + Escape: function(event, can) { can.onkeymap._normal(can) + can.page.Modify(can, can.ui.command, {style: {display: "none"}}) + can.editor.focus() }, - jk: function(event, can) { can.history = can.history.slice(0, -1); - can.onkeymap.command.Enter(event, can); + Enter: function(event, can) { can.onkeymap._normal(can) + var line = can.ui.command.value + var ls = can.core.Split(line, " ", ",", {simple: true}) + var cb = can.onkeymap._engine[ls[0]] + typeof cb == "function"? cb(event, can, line, ls): can.onkeymap._remote(event, can, line, ls) + + can.onkeymap.command.Escape(event, can) + }, + jk: function(event, can) { can.history = can.history.slice(0, -1) + can.onkeymap.command.Enter(event, can) }, }, normal: { - ":": function(event, can) { - can.onkeymap._command(can) - }, + ":": function(event, can) { can.onkeymap._command(can) }, + h: function(event, can) { can.editor.setSelectionRange(can.editor.selectionStart-1, can.editor.selectionStart-1) }, l: function(event, can) { can.editor.setSelectionRange(can.editor.selectionStart+1, can.editor.selectionStart+1) }, - j: function(event, can) { - can.onaction.selectLine(can, can.current.nextSibling) + j: function(event, can, count) { count = count || 1 + for (var i = 0; i < count; i++) { + var pos = can.current.offsetTop-can._target.scrollTop + can.onaction.selectLine(can, can.current.nextSibling) + if (pos > 22*15) { + can._target.scrollBy(0, 22) + } + } }, - k: function(event, can) { - can.onaction.selectLine(can, can.current.previousSibling) + k: function(event, can, count) { count = count || 1 + for (var i = 0; i < count; i++) { + var pos = can.current.offsetTop-can._target.scrollTop + can.onaction.selectLine(can, can.current.previousSibling) + if (pos < 22*5) { + can._target.scrollBy(0, -22) + } + } + }, + gg: function(event, can, count) { count = count || 1 + can.onaction.selectLine(can, count - 1) + can.current.scrollIntoView() + can._target.scrollBy(0, -22*5) + }, + G: function(event, can, count) { count = count || can.max + can.onaction.selectLine(can, count - 1) + can.current.scrollIntoView() + if (count - can.max < -5) { + can._target.scrollBy(0, -22*5) + } + }, + zt: function(event, can, count) { count = count || 2 + can.current.scrollIntoView() + can._target.scrollBy(0, -22*count) + }, + zz: function(event, can, count) { count = count || 5 + can.current.scrollIntoView() + can._target.scrollBy(0, -22*count) + }, + zb: function(event, can, count) { count = count || 3 + can._target.scrollBy(0, -(can._target.offsetHeight - (can.current.offsetTop - can._target.scrollTop))+22*count) }, - r: function(event, can) { - can.run(event) + i: function(event, can) { can.onkeymap._insert(can) }, - i: function(event, can) { - can.onkeymap._insert(can) + I: function(event, can) { can.onkeymap._insert(can) + can.editor.setSelectionRange(0, 0) }, - O: function(event, can) { - can.onkeymap._insert(can) - can.onaction.insertLine(can, can.current, "", true).click() - }, - o: function(event, can) { - can.onkeymap._insert(can) + o: function(event, can) { can.onkeymap._insert(can) can.onaction.insertLine(can, can.current).click() }, - yy: function(event, can) { - can.last = can.current.innerText + O: function(event, can) { can.onkeymap._insert(can) + can.onaction.insertLine(can, can.current, "", true).click() }, - dd: function(event, can) { - can.last = can.current.innerText - var next = can.current.nextSibling || can.current.previousSibling - can.onaction.deleteLine(can, can.current) - next.click() + + yy: function(event, can) { can.last = can.current.innerText }, - p: function(event, can) { - can.onaction.insertLine(can, can.current, can.last).click() + dd: function(event, can, count) { count = count || 1 + for (var i = 0; i < count; i++) { + can.last = can.current.innerText + var next = can.current.nextSibling || can.current.previousSibling + can.onaction.deleteLine(can, can.current) + next.click() + } + }, + p: function(event, can, count) { count = count || 1 + for (var i = 0; i < count; i++){ + var last = can.onaction.insertLine(can, can.current, can.last) + } + last.click() }, P: function(event, can) { can.onaction.insertLine(can, can.current, can.last, true).click() }, }, insert: { + Escape: function(event, can) { can.onkeymap._normal(can) + can.onaction.modifyLine(can, can.current, can.editor.value) + }, + Enter: function(event, can) { + can.onaction.modifyLine(can, can.current, can.editor.value) + can.onaction.insertLine(can, can.current, "", event.shiftKey).click() + event.stopPropagation(), event.preventDefault() + }, + Backspace: function(event, can) { + can.editor.selectionStart == 0 && can.onaction.mergeLine(can, can.current.previousSibling).click() + }, ArrowDown: function(event, can) { can.onaction.selectLine(can, can.current.nextSibling) }, ArrowUp: function(event, can) { can.onaction.selectLine(can, can.current.previousSibling) }, - Escape: function(event, can) { - can.onaction.modifyLine(can, can.current, can.editor.value) - can.onkeymap._normal(can) - }, - Enter: function(event, can) { - can.onaction.modifyLine(can, can.current, can.editor.value) - can.onaction.insertLine(can, can.current, "", event.shiftKey).click() - event.stopPropagation() - event.preventDefault() - }, - Backspace: function(event, can) { - can.editor.selectionStart == 0 && can.onaction.mergeLine(can, can.current.previousSibling).click() - }, - jk: function(event, can) { + jk: function(event, can) { can.onkeymap._normal(can) can.page.DelText(can.editor, can.editor.selectionStart-1, 1) - can.onaction.modifyLine(can, can.current, can.editor.value) - can.onkeymap._normal(can) - event.stopPropagation() - event.preventDefault() + event.stopPropagation(), event.preventDefault() }, }, }) -Volcanos("onaction", {help: "控件交互", list: ["项目", "保存", "运行", "提交", ["mode", "normal", "insert"]], - modifyLine: function(can, target, value) { - value = can.onsyntax.parse(can, value) - target.innerHTML = value +Volcanos("onaction", {help: "控件交互", list: ["项目", "上传", "保存", "运行", "提交", "历史"], + modifyLine: function(can, target, value) { var p = can.onsyntax.parse(can, value) + typeof p == "object"? can.page.Appends(can, target, [p]): target.innerHTML = p }, - deleteLine: function(can, target) { - can.page.Remove(can, target) - - var ls = can.page.Select(can, can.ui.lineno, "div.item") - can.page.Remove(can, ls[ls.length-1]) - // can.max-- + deleteLine: function(can, target) { can.page.Remove(can, target) + var ls = can.page.Select(can, can.ui.preview, "div.item") + can.page.Remove(can, ls[ls.length-1]), can.max-- }, - selectLine: function(can, target) { if (!target) { return } - can.page.Select(can, can.ui.content, "pre.item", function(item, index) { - if (item != target && index != target) { return } - target = item, can.Status("当前行", can.onexport.position(can, index)), can.page.Select(can, can.ui.lineno, "div.item", function(item, i) { - can.page.ClassList.del(can, item, "select") - index == i && can.page.ClassList.add(can, item, "select") + selectLine: function(can, target) { if (target !== 0 && !target) { return } + can.page.Select(can, can.ui.content, "pre.item", function(item, index) { if (item != target && index != target) { return } + target = item, can.Status("当前行", can.onexport.position(can, index)) + can.page.Select(can, can.ui.preview, "div.item", function(item, i) { + can.page.ClassList[index==i? "add": "del"](can, item, "select") }) - }) + }); if (typeof target != "object") { return }; can.current = target - can.current = target, can.page.Modify(can, can.editor, {value: can.current.innerText, style: { + can.page.Modify(can, can.editor, {className: "editor "+can.mode, value: can.current.innerText, style: { height: target.offsetHeight+"px", width: target.offsetWidth+"px", - top: (target.offsetTop-can._output.offsetTop)+"px", - }}), can.editor.focus(); + top: (target.offsetTop)+"px", display: "block", + }}), can.editor.focus() + + can.page.Modify(can, can.ui.command, {value: can.current.innerText, style: { + height: target.offsetHeight+"px", width: target.offsetWidth+"px", + }}) }, - appendLine: function(can, value) { var index = can.max++; - can.page.Append(can, can.ui.lineno, [{view: ["item", "div", index+1], onclick: function(event) { + appendLine: function(can, value) { var index = can.max++ + can.page.Append(can, can.ui.preview, [{view: ["item", "div", index+1], onclick: function(event) { can.onaction.selectLine(can, index) }}]) - value = can.onsyntax.parse(can, value) - return can.page.Append(can, can.ui.content, [{view: ["item", "pre", value||""], onclick: function(event) { - can.onaction.selectLine(can, event.target) + var p = can.onsyntax.parse(can, value||"") + var line = can.page.Append(can, can.ui.content, [typeof p == "object"? p: {view: ["item", "pre", p], onclick: function(event) { + can.onaction.selectLine(can, line) }}]).last + return line }, insertLine: function(can, target, value, before) { var line = can.onaction.appendLine(can, value) @@ -301,52 +541,17 @@ Volcanos("onaction", {help: "控件交互", list: ["项目", "保存", "运行", return line }, mergeLine: function(can, target) { if (!target) {return} - can.onaction.modifyLine(can, target, target.innerHTML + target.nextSibling.innerHTML); - can.onaction.deleteLine(can, target.nextSibling); + can.onaction.modifyLine(can, target, target.innerHTML + target.nextSibling.innerHTML) + can.onaction.deleteLine(can, target.nextSibling) return target }, - project: function(can) { can.ui.project.innerHTML = "" - can.run({}, ["action", "project", can.Option("path")], function(res) { - res.Table(function(value) { - can.page.Append(can, can.ui.project, [{text: [value.file, "div", "item"], onclick: function(event) { - if (value.file.endsWith("/")) { - can.Option("path", can.base.Path(can.Option("path"), value.file)) - can.onaction.project(can) - } else { - can.Option("name", value.file) - can.run(event) - } - }}]) - }) - }, true) - }, - - - remote: function(event, can, msg, key, cb) { - msg = can.request(event), msg.Option("content", can.onexport.content(can)) - can.run(event, ["action", key, can.base.Path(can.Option("path"), can.Option("name"))], function(res) { - }, true) - }, - mode: function(event, can, msg, value) { - can.Action("mode", can.mode = value) - can.Status("输入法", can.mode) - return value - }, - "项目": function(event, can, msg) { - can.onlayout.show_project(can) - }, - "保存": function(event, can, msg) { - can.onaction.remote(event, can, msg, "保存") - }, - "运行": function(event, can, msg) { - can.run(event, ["action", can.parse, can.base.Path(can.Option("path"), can.Option("name"))], function(res) { - can.ui.display.innerHTML = res.Result() - }, true); - }, - "提交": function(event, can, msg) { - can.onaction.remote(event, can, msg, "提交") - }, + "项目": function(event, can, msg) { can.onlayout.project(can) }, + "上传": function(event, can, msg) { can.onappend.upload(can) }, + "保存": function(event, can, msg) { can.onkeymap._remote(event, can, "保存") }, + "运行": function(event, can, msg) { can.onkeymap._remote(event, can, "运行") }, + "提交": function(event, can, msg) { can.onkeymap._remote(event, can, "提交") }, + "历史": function(event, can, msg) { can.onkeymap._remote(event, can, "历史") }, }) Volcanos("ondetail", {help: "菜单交互", list: ["删除行", "合并行", "插入行", "添加行", "追加行"], "删除行": function(event, can, msg) { @@ -365,19 +570,29 @@ Volcanos("ondetail", {help: "菜单交互", list: ["删除行", "合并行", " can.onaction.appendLine(can) }, }) -Volcanos("onlayout", {help: "页面布局", list: [], - show_project: function(can) { - var hide = can.ui.project.style.display == "none" - can.page.Modify(can, can.ui.project, {style: { - display: hide? "": "none", - }}) - can.page.Modify(can, can.ui.content, {style: { - "margin-left": hide? "110px": "30px", - }}) - can.page.Modify(can, can.ui.display, {style: { - "margin-left": hide? "110px": "30px", - }}) +Volcanos("onlayout", {help: "页面布局", list: [], _init: function(can) { + can.onlayout.project(can) + can.onlayout.project(can) }, + + project: function(can) { var hide = can.ui.project.style.display == "none" + can.page.Modify(can, can.ui.project, {style: {display: hide? "": "none"}}) + + var style = {style: { + "margin-left": hide? "80px": "0px", + }}; can.page.Modify(can, can.ui.preview, style) + + var style = {style: { + "margin-left": hide? "110px": "30px", + }}; can.page.Modify(can, can.ui.content, style) + + can.page.Modify(can, can.ui.display, style) + can.page.Modify(can, can.ui.command, style) + can.page.Modify(can, can.ui.editor, style) + }, +}) +Volcanos("ondaemon", {help: "数据刷新", list: [], _init: function(can) { +}, }) Volcanos("onexport", {help: "导出数据", list: ["输入法", "输入值", "文件名", "解析器", "当前行"], content: function(can) { @@ -385,7 +600,8 @@ Volcanos("onexport", {help: "导出数据", list: ["输入法", "输入值", " return can.current == item? can.editor.value: item.innerText }).join("\n") }, - position: function(can, index) { - return parseInt((index+1)*100/can.max)+"%"+" = "+(index+1)+"/"+can.max + position: function(can, index, total) { total = total || can.max + return parseInt((index+1)*100/total)+"%"+" = "+(parseInt(index)+1)+"/"+parseInt(total) }, }) +