diff --git a/.eslintrc b/.eslintrc index c435e6b66..12defcd8a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -17,7 +17,6 @@ }, "parser": "@typescript-eslint/parser", "parserOptions": { - "project": "./tsconfig.json", "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { @@ -26,7 +25,7 @@ }, "plugins": ["@typescript-eslint/eslint-plugin"], "overrides": [{ - "files": ["src/*.js","src/**/*.js", "demo/*.js", "demo/**/*.js", "i18n/**/*.js", "i18n/*.js", "test/**/*.js", "test/*.js"], + "files": ["src/*.js","src/**/*.js", "demo/*.js", "demo/**/*.js", "i18n/**/*.js", "i18n/*.js", "test/**/*.js", "test/*.js", "examples/*.js", "examples/**/*.js"], "extends": "plugin:@fui/es5", "rules": { "no-param-reassign": "off", @@ -34,7 +33,10 @@ "comma-dangle": ["error", "never"] // 多行对象字面量中要求拖尾逗号 } }, { - "files": ["webpack/*.js", "types/*.ts", "typescript/*.ts","typescript/**/*.ts", "./*.js", "lib/**/*.js", "lib/*.js"], + "files": ["webpack/*.js", "./*.js", "lib/**/*.js", "lib/*.js", "./bin/*.js", "./bin/**/*.js"], + "extends": "plugin:@fui/esnext" + }, { + "files": ["types/*.ts", "typescript/*.ts","typescript/**/*.ts"], "extends": "plugin:@fui/typescript" }] } diff --git a/.npmignore b/.npmignore index a6aad7230..a5bc0942a 100644 --- a/.npmignore +++ b/.npmignore @@ -38,3 +38,5 @@ !.eslintrc !dist/2.0/jsy.min.css !dist/2.0/bi.min.css +!bin/* +!bin/**/* diff --git a/bin/cli/cli.js b/bin/cli/cli.js new file mode 100644 index 000000000..732fc1133 --- /dev/null +++ b/bin/cli/cli.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node + +const workerCmd = require('./worker/cli.worker'); + +function getArgs (startIndex = 1) { + const args = {}; + process.argv + .slice(startIndex, process.argv.length) + .forEach(arg => { + // long arg + if (arg.slice(0, 2) === '--') { + const longArg = arg.split('='); + const longArgFlag = longArg[0].slice(2, longArg[0].length); + const longArgValue = longArg.length > 1 ? longArg[1] : true; + args[longArgFlag] = longArgValue; + // flags + } else if (arg[0] === '-') { + const flags = arg.slice(1, arg.length); + args[flags] = true; + } + }); + + return args; +} + +const cmds = new Map([ + ['worker', workerCmd], +]); + +const baseCmd = 'fui-cli'; + +const startIndex = process.argv.findIndex(argv => argv.indexOf(baseCmd) !== -1); + +if (startIndex === -1) { + throw new Error(`Command ${baseCmd} not found in args`); +} + +const cmd = process.argv[startIndex + 1]; + +if (cmds.has(cmd)) { + cmds.get(cmd)?.exec(getArgs(startIndex + 2)); +} else { + throw new Error(`Command ${cmd} not supported`); +} diff --git a/bin/cli/worker/cli.worker.js b/bin/cli/worker/cli.worker.js new file mode 100644 index 000000000..0c086db08 --- /dev/null +++ b/bin/cli/worker/cli.worker.js @@ -0,0 +1,62 @@ +const fs = require('fs'); +const path = require('path'); + +function scanAndCreate(structure, root = process.cwd()) { + Object.keys(structure) + .forEach(name => { + if (typeof structure[name] === 'object') { + fs.mkdirSync(path.resolve(root, name)); + + scanAndCreate(structure[name], path.resolve(root, `./${name}`)); + } else if (structure[name] === '') { + fs.appendFileSync(path.resolve(root, name), ''); + } else if (typeof structure[name] === 'string') { + const content = fs.readFileSync(structure[name]).toString(); + + fs.appendFileSync(path.resolve(root, name), content); + } + }); +} + +module.exports = { + exec: async args => { + if (!args.init) { + throw new Error(`Command init not found in args`); + } + + if (!args.name) { + throw new Error('Command --name=... not found in args'); + } + + const name = args.name; + + const structure = { + [`${name}_worker`]: { + 'main_thread': { + action: {}, + [`${name}_main_thread.ts`]: path.resolve(__dirname, './template/main_thread_template.ts'), + }, + utils: { + 'action_type.ts': '', + }, + 'worker_thread': { + action: {}, + [`${name}_worker_thread.ts`]: path.resolve(__dirname, './template/worker_thread_template.ts'), + }, + }, + }; + + scanAndCreate(structure); + }, +}; + +// 结构 +// -xxx_worker +// -|--main_thread +// -|--|--action +// -|--|--xxx_main_thread.ts +// -|--utils +// -|--|--action_type.ts +// -|--worker_thread +// -|--|--action +// -|--|--worker_main_thread.ts diff --git a/bin/cli/worker/template/action_type.ts b/bin/cli/worker/template/action_type.ts new file mode 100644 index 000000000..e69de29bb diff --git a/bin/cli/worker/template/main_thread_template.ts b/bin/cli/worker/template/main_thread_template.ts new file mode 100644 index 000000000..8df764495 --- /dev/null +++ b/bin/cli/worker/template/main_thread_template.ts @@ -0,0 +1,5 @@ +class CrudMainTreadWorker extends BI.Workers.MainThreadWorker { + protected initActions(): void { + // to init some actions + } +} diff --git a/bin/cli/worker/template/worker_thread_template.ts b/bin/cli/worker/template/worker_thread_template.ts new file mode 100644 index 000000000..fc457c9c7 --- /dev/null +++ b/bin/cli/worker/template/worker_thread_template.ts @@ -0,0 +1,5 @@ +class CrudWorkerTreadWorker extends BI.Workers.MainThreadWorker { + protected initActions(): void { + // to init some actions + } +} diff --git a/demo/js/base/button/demo.button.js b/demo/js/base/button/demo.button.js index 110431afb..d0b14aaff 100644 --- a/demo/js/base/button/demo.button.js +++ b/demo/js/base/button/demo.button.js @@ -4,416 +4,310 @@ Demo.Button = BI.inherit(BI.Widget, { }, render: function () { var items = [{ - el: { - type: "bi.button", - text: "一般按钮", - level: "common", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示成功状态按钮", - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示警告状态的按钮", - level: "warning", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示错误状态的按钮", - level: "error", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示忽略状态的按钮", - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "普通灰化按钮", - disabled: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "忽略状态灰化按钮", - disabled: true, - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "带图标的按钮", - // level: 'ignore', - iconCls: "close-font", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "一般按钮", - block: true, - level: "common", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示成功状态按钮", - block: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示警告状态的按钮", - block: true, - level: "warning", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示忽略状态的按钮", - block: true, - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "普通灰化按钮", - block: true, - disabled: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "忽略状态灰化按钮", - block: true, - disabled: true, - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "带图标的按钮", - block: true, - // level: 'ignore', - iconCls: "close-font", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "一般按钮", - clear: true, - level: "common", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示成功状态按钮", - clear: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示警告状态的按钮", - clear: true, - level: "warning", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "表示忽略状态的按钮", - clear: true, - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "普通灰化按钮", - clear: true, - disabled: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "忽略状态灰化按钮", - clear: true, - disabled: true, - level: "ignore", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "带图标的按钮", - clear: true, - // level: 'ignore', - iconCls: "close-font", - height: 30 - } - }, { - el: { - type: "bi.text_button", - text: "文字按钮", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "幽灵按钮(common)", - ghost: true, - height: 30 - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "幽灵按钮(common)", - ghost: true, - height: 30 - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "幽灵按钮(common)", - ghost: true, - level: "warning", - height: 30 - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "幽灵按钮(common)", - ghost: true, - level: "error", - height: 30 - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "幽灵按钮(common)", - ghost: true, - level: "success", - height: 30 - } - }, { - el: { - type: "bi.button", - text: "幽灵按钮(common)灰化", - disabled: true, - ghost: true, - height: 30 - } - }, { - el: { - type: "bi.button", - text: "弹出bubble", - bubble: function () { - return BI.parseInt(Math.random() * 100) % 10 + "提示" - }, - handler: function () { - BI.Msg.toast("1111"); - }, - height: 30 - } - }, { - el: { - type: "bi.button", - text: "图标在上面的按钮,而且可以自动撑开高度", - iconCls: "close-font", - iconGap: 24, - iconPosition: "top" - } + type: "bi.button", + text: "一般按钮", + level: "common", + height: 30 + }, { + type: "bi.button", + text: "表示成功状态按钮", + level: "success", + height: 30 + }, { + type: "bi.button", + text: "表示警告状态的按钮", + level: "warning", + height: 30 + }, { + type: "bi.button", + text: "表示错误状态的按钮", + level: "error", + height: 30 + }, { + type: "bi.button", + text: "表示忽略状态的按钮", + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "普通灰化按钮", + disabled: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "忽略状态灰化按钮", + disabled: true, + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "带图标的按钮", + // level: 'ignore', + iconCls: "close-font", + height: 30 + }, { + type: "bi.button", + text: "一般按钮", + block: true, + level: "common", + height: 30 + }, { + type: "bi.button", + text: "表示成功状态按钮", + block: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "表示警告状态的按钮", + block: true, + level: "warning", + height: 30 + }, { + type: "bi.button", + text: "表示忽略状态的按钮", + block: true, + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "普通灰化按钮", + block: true, + disabled: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "忽略状态灰化按钮", + block: true, + disabled: true, + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "带图标的按钮", + block: true, + // level: 'ignore', + iconCls: "close-font", + height: 30 + }, { + type: "bi.button", + text: "一般按钮", + clear: true, + level: "common", + height: 30 + }, { + type: "bi.button", + text: "表示成功状态按钮", + clear: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "表示警告状态的按钮", + clear: true, + level: "warning", + height: 30 + }, { + type: "bi.button", + text: "表示忽略状态的按钮", + clear: true, + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "普通灰化按钮", + clear: true, + disabled: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "忽略状态灰化按钮", + clear: true, + disabled: true, + level: "ignore", + height: 30 + }, { + type: "bi.button", + text: "带图标的按钮", + clear: true, + // level: 'ignore', + iconCls: "close-font", + height: 30 + }, { + type: "bi.text_button", + text: "文字按钮", + height: 30 + }, { + type: "bi.button", + text: "幽灵按钮(common)", + ghost: true, + height: 30 + }, { + type: "bi.button", + iconCls: "plus-font", + text: "幽灵按钮(common)", + ghost: true, + height: 30 + }, { + type: "bi.button", + iconCls: "plus-font", + text: "幽灵按钮(common)", + ghost: true, + level: "warning", + height: 30 + }, { + type: "bi.button", + iconCls: "plus-font", + text: "幽灵按钮(common)", + ghost: true, + level: "error", + height: 30 + }, { + type: "bi.button", + iconCls: "plus-font", + text: "幽灵按钮(common)", + ghost: true, + level: "success", + height: 30 + }, { + type: "bi.button", + text: "幽灵按钮(common)灰化", + disabled: true, + ghost: true, + height: 30 + }, { + type: "bi.button", + text: "弹出bubble", + bubble: function () { + return BI.parseInt(Math.random() * 100) % 10 + "提示" + }, + handler: function () { + BI.Msg.toast("1111"); + }, + height: 30 + }, { + type: "bi.button", + text: "图标在上面的按钮,而且可以自动撑开高度", + iconCls: "close-font", + iconGap: 24, + iconPosition: "top" },{ - el: { - type: "bi.button", - text: "自动撑开高度", - iconCls: "close-font", - textHeight: 32, - iconGap: 24, - vgap: 16, - hgap: 100, - iconPosition: "top" - } - }, { - el: { - type: "bi.button", - text: "图标在下面的按钮", - iconCls: "close-font", - iconPosition: "bottom" - } - }, { - el: { - type: "bi.button", - text: "图标在左边的按钮", - iconCls: "close-font", - iconPosition: "left" - } - }, { - el: { - type: "bi.button", - text: "图标在右边的按钮", - iconCls: "close-font", - iconPosition: "right" - } - }, { - el: { - type: "bi.button", - text: "浅色的一般按钮", - iconCls: "plus-font", - light: true - } - }, { - el: { - type: "bi.button", - text: "浅色的成功按钮", - level: "success", - iconCls: "plus-font", - light: true - } - }, { - el: { - type: "bi.button", - text: "浅色的警告按钮", - level: "warning", - iconCls: "plus-font", - light: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "浅色的失败按钮", - level: "error", - cls: "hover-mask", - light: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "common", - plain: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "success", - plain: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "error", - plain: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "warning", - plain: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "ignore", - plain: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "ignore", - plain: true, - disabled: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "error", - plain: true, - disabled: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "朴素的按钮", - level: "common", - plain: true, - disabled: true - } - }, { - el: { - type: "bi.button", - iconCls: "plus-font", - text: "点我,更改图标", - handler() { - this.i = this.i === undefined ? 0 : ++this.i; - const arr = ["text-background-font", "check-mark-ha-font", "close-font", "search-font", "date-change-h-font"]; - if(this.i >= arr.length) { - this.i = 0; - } - this.setIcon(arr[this.i]); - }, - height: 24 - } + type: "bi.button", + text: "自动撑开高度", + iconCls: "close-font", + textHeight: 32, + iconGap: 24, + vgap: 16, + hgap: 100, + iconPosition: "top" + }, { + type: "bi.button", + text: "图标在下面的按钮", + iconCls: "close-font", + iconPosition: "bottom" + }, { + type: "bi.button", + text: "图标在左边的按钮", + iconCls: "close-font", + iconPosition: "left" + }, { + type: "bi.button", + text: "图标在右边的按钮", + iconCls: "close-font", + iconPosition: "right" + }, { + type: "bi.button", + text: "浅色的一般按钮", + iconCls: "plus-font", + light: true + }, { + type: "bi.button", + text: "浅色的成功按钮", + level: "success", + iconCls: "plus-font", + light: true + }, { + type: "bi.button", + text: "浅色的警告按钮", + level: "warning", + iconCls: "plus-font", + light: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "浅色的失败按钮", + level: "error", + cls: "hover-mask", + light: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + level: "common", + plain: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + level: "success", + plain: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + level: "error", + plain: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + level: "warning", + plain: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + level: "ignore", + plain: true + }, { + type: "bi.button", + iconCls: "plus-font", + plain: true, + level: "error", + }, { + type: "bi.button", + iconCls: "plus-font", + text: "朴素的按钮", + plain: true, + disabled: true + }, { + type: "bi.button", + iconCls: "plus-font", + text: "点我,更改图标", + handler() { + this.i = this.i === undefined ? 0 : ++this.i; + const arr = ["text-background-font", "check-mark-ha-font", "close-font", "search-font", "date-change-h-font"]; + if(this.i >= arr.length) { + this.i = 0; + } + this.setIcon(arr[this.i]); + }, + height: 24 }]; - // BI.each(items, function (i, item) { - // item.el.handler = function () { - // BI.Msg.alert("按钮", this.options.text); - // }; - // }); + return { type: "bi.left", scrolly: true, vgap: 100, hgap: 20, - items: items + items: BI.map(items, function (index, value) { + return { + el: value + } + }) }; } }); diff --git a/demo/js/base/tip/demo.title.js b/demo/js/base/tip/demo.title.js index 44a5bdc23..5a983068d 100644 --- a/demo/js/base/tip/demo.title.js +++ b/demo/js/base/tip/demo.title.js @@ -30,10 +30,30 @@ Demo.Title = BI.inherit(BI.Widget, { warningTitle: "自定义title提示效果", text: "自定义title提示效果", textAlign: "center" + }, { + type: "bi.label", + cls: "layout-bg3", + height: 50, + title: () => "函数返回值作为title提示", + text: "title提示支持函数", + textAlign: "center" + }, { + type: "bi.label", + cls: "layout-bg4", + height: 50, + title: function () { + return { + level: "success", + text: "自定义title\n提示效果", + textAlign: "center" + }; + }, + text: "title提示支持对象,作为bi.tooltip的props", + textAlign: "center" }], hgap: 300, vgap: 20 }; } }); -BI.shortcut("demo.title", Demo.Title); \ No newline at end of file +BI.shortcut("demo.title", Demo.Title); diff --git a/demo/js/base/tree/demo.sync_tree.js b/demo/js/base/tree/demo.sync_tree.js index 6b78ac97e..682619b7f 100644 --- a/demo/js/base/tree/demo.sync_tree.js +++ b/demo/js/base/tree/demo.sync_tree.js @@ -4,7 +4,10 @@ Demo.Func = BI.inherit(BI.Widget, { }, mounted: function () { - this.syncTree.stroke({ + this.syncTree1.stroke({ + keyword: "1" + }); + this.syncTree2.stroke({ keyword: "1" }); }, @@ -13,40 +16,92 @@ Demo.Func = BI.inherit(BI.Widget, { var self = this; return { type: "bi.vtape", - items: [{ - type: "bi.label", - height: 50, - text: "可以异步获取数据的树" - }, { - type: "bi.async_tree", - ref: function (_ref) { - self.syncTree = _ref; - }, - paras: { - selectedValues: {"1": {}, "2": {"1": {}}} - }, - itemsCreator: function (op, callback) { - callback({ - items: [{ - id: (op.id || "") + "1", - pId: op.id, - text: 1, - isParent: true + rowSize: [0.5, 0.5], + items: [ + { + type: "bi.vtape", + items: [ + { + type: "bi.label", + height: 50, + text: "可以异步获取数据的树" }, { - id: (op.id || "") + "2", - pId: op.id, - text: 2 + type: "bi.async_tree", + ref: function (_ref) { + self.syncTree1 = _ref; + }, + paras: { + selectedValues: { "1": {}, "2": { "1": {} } } + }, + itemsCreator: function (op, callback) { + callback({ + items: [{ + id: (op.id || "") + "1", + pId: op.id, + text: (op.id || "") + "1", + isParent: true, + iconCls: "close-h-font" + }, { + id: (op.id || "") + "2", + pId: op.id, + text: (op.id || "") + "2", + iconCls: "search-font" + }, { + id: (op.id || "") + "3", + pId: op.id, + text: (op.id || "") + "3", + iconCls: "date-font" + }], + hasNext: BI.isNull(op.id) + }); + } + }, + ] + }, + { + type: "bi.vtape", + items: [ + { + type: "bi.label", + height: 50, + text: "showIcon属性搭配节点iconCls,可以显示图标" }, { - id: (op.id || "") + "3", - pId: op.id, - text: 3 - }], - hasNext: BI.isNull(op.id) - }); + type: "bi.async_tree", + ref: function (_ref) { + self.syncTree2 = _ref; + }, + paras: { + selectedValues: { "1": {}, "2": { "1": {} } } + }, + showIcon: true, + itemsCreator: function (op, callback) { + callback({ + items: [{ + id: (op.id || "") + "1", + pId: op.id, + text: (op.id || "") + "1", + isParent: true, + iconCls: "close-h-font" + }, { + id: (op.id || "") + "2", + pId: op.id, + text: (op.id || "") + "2", + iconCls: "search-font" + }, { + id: (op.id || "") + "3", + pId: op.id, + text: (op.id || "") + "3", + iconCls: "date-font" + }], + hasNext: BI.isNull(op.id) + }); + } + }, + ] } - }] + ] }; } }); -BI.shortcut("demo.sync_tree", Demo.Func); \ No newline at end of file +BI.shortcut("demo.sync_tree", Demo.Func); diff --git a/dist/fix/fix.compact.js b/dist/fix/fix.compact.js index b8e49eb28..df02143b6 100644 --- a/dist/fix/fix.compact.js +++ b/dist/fix/fix.compact.js @@ -38,7 +38,7 @@ cb = cb.handler; } options = options || {}; - return Fix.watch(vm.model, keyOrFn, _.bind(cb, vm), BI.extend(options, { + return Fix.watch(vm.model, keyOrFn, BI._.bind(cb, vm), BI.extend(options, { store: vm.store })); } @@ -177,7 +177,7 @@ delete this.__cacheStore; }; - _.each(["_render", "__afterRender", "_mount", "__afterMount"], function (name) { + BI._.each(["_render", "__afterRender", "_mount", "__afterMount"], function (name) { var old = BI.Widget.prototype[name]; old && (BI.Widget.prototype[name] = function () { this.store && pushTarget(this.store); diff --git a/dist/fix/fix.js b/dist/fix/fix.js index 52a6a7907..9a106ae7a 100644 --- a/dist/fix/fix.js +++ b/dist/fix/fix.js @@ -96,8 +96,8 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons setImmediate(nextTickHandler); }; } else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || - // PhantomJS - MessageChannel.toString() === '[object MessageChannelConstructor]')) { + // PhantomJS + MessageChannel.toString() === '[object MessageChannelConstructor]')) { var channel = new MessageChannel(); var port = channel.port2; channel.port1.onmessage = nextTickHandler; @@ -106,18 +106,18 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons }; } else /* istanbul ignore next */ - if (typeof Promise !== 'undefined' && isNative(Promise)) { - // use microtask in non-DOM environments, e.g. Weex - var p = Promise.resolve(); - timerFunc = function timerFunc() { - p.then(nextTickHandler); - }; - } else { - // fallback to setTimeout - timerFunc = function timerFunc() { - setTimeout(nextTickHandler, 0); - }; - } + if (typeof Promise !== 'undefined' && isNative(Promise)) { + // use microtask in non-DOM environments, e.g. Weex + var p = Promise.resolve(); + timerFunc = function timerFunc() { + p.then(nextTickHandler); + }; + } else { + // fallback to setTimeout + timerFunc = function timerFunc() { + setTimeout(nextTickHandler, 0); + }; + } return function queueNextTick(cb, ctx) { var _resolve = void 0; @@ -428,10 +428,10 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons if (this.active) { var value = this.get(); if (value !== this.value || - // Deep watchers and watchers on Object/Arrays should fire even - // when the value is the same, because the value may - // have mutated. - _.isObject(value) && options && options.refresh || this.deep) { + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + BI._.isObject(value) && options && options.refresh || this.deep) { // set new value var oldValue = this.value; this.value = value; @@ -491,8 +491,8 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function _traverse(val, seen) { var i = void 0, keys = void 0; - var isA = _.isArray(val); - if (!isA && !_.isObject(val)) { + var isA = BI._.isArray(val); + if (!isA && !BI._.isObject(val)) { return; } if (val.__ob__) { @@ -508,7 +508,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons _traverse(val[i], seen); } } else { - keys = _.keys(val); + keys = BI._.keys(val); i = keys.length; while (i--) { _traverse(val[keys[i]], seen); @@ -518,7 +518,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var arrayProto = Array.prototype; var arrayMethods = []; - _.each(['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'], function (method) { + BI._.each(['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'], function (method) { var original = arrayProto[method]; arrayMethods[method] = function mutator() { for (var _len = arguments.length, args = Array(_len), _key2 = 0; _key2 < _len; _key2++) { @@ -554,7 +554,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons }; }); - var arrayKeys = _.keys(arrayMethods); + var arrayKeys = BI._.keys(arrayMethods); var observerState = { shouldConvert: true @@ -583,7 +583,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons this.value = value; this.dep = new Dep(); this.vmCount = 0; - if (_.isArray(value)) { + if (BI._.isArray(value)) { var augment = hasProto ? protoAugment : copyAugment; augment(value, arrayMethods, arrayKeys); this.model = this.observeArray(value); @@ -623,13 +623,13 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } function observe(value, parentObserver, parentKey) { - if (!_.isObject(value)) { + if (!BI._.isObject(value)) { return; } var ob = void 0; if (value.__ob__ instanceof Observer) { ob = value.__ob__; - } else if (observerState.shouldConvert && isExtensible(value) && (_.isArray(value) || isPlainObject(value))) { + } else if (observerState.shouldConvert && isExtensible(value) && (BI._.isArray(value) || isPlainObject(value))) { ob = new Observer(value); } if (ob) { @@ -643,7 +643,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons dep.notify({ observer: observer, key: key, refresh: refresh }); if (observer) { //触发a.*绑定的依赖 - _.each(observer._deps, function (dep) { + BI._.each(observer._deps, function (dep) { dep.notify({ observer: observer, key: key }); }); //触发a.**绑定的依赖 @@ -651,7 +651,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons root = observer, route = key || ""; while (parent) { - _.each(parent._scopeDeps, function (dep) { + BI._.each(parent._scopeDeps, function (dep) { dep.notify({ observer: observer, key: key }); }); if (parent.parentKey != null) { @@ -674,7 +674,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function defineReactive(obj, observer, shallow) { var props = {}; var model = void 0; - _.each(obj, function (val, key) { + BI._.each(obj, function (val, key) { if (key in $$skipArray) { return; } @@ -691,7 +691,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons dep.depend(); if (childOb) { childOb.dep.depend(); - if (_.isArray(value)) { + if (BI._.isArray(value)) { dependArray(value); } } @@ -740,7 +740,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons dep.depend(); if (childOb) { childOb.dep.depend(); - if (_.isArray(value)) { + if (BI._.isArray(value)) { dependArray(value); } } @@ -767,12 +767,12 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons * already exist. */ function set(target, key, val) { - if (_.isArray(target)) { + if (BI._.isArray(target)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val; } - if (_.has(target, key)) { + if (BI._.has(target, key)) { target[key] = val; return val; } @@ -795,12 +795,12 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons * Delete a property and trigger change if necessary. */ function del(target, key) { - if (_.isArray(target)) { + if (BI._.isArray(target)) { target.splice(key, 1); return; } var ob = target.__ob__; - if (!_.has(target, key)) { + if (!BI._.has(target, key)) { return; } if (!ob) { @@ -821,7 +821,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons for (var e, i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); - if (_.isArray(e)) { + if (BI._.isArray(e)) { dependArray(e); } } @@ -838,7 +838,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function runBinaryFunction(binarys) { var expr = ''; for (var i = 0, len = binarys.length; i < len; i++) { - if (_.isBoolean(binarys[i]) || _.has(operators, binarys[i])) { + if (BI._.isBoolean(binarys[i]) || BI._.has(operators, binarys[i])) { expr += binarys[i]; } else { expr += 'false'; @@ -863,7 +863,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons options = options || {}; options.user = true; var exps = void 0; - if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && expOrFn.indexOf("*") < 0) { + if (BI._.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9BI._.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && expOrFn.indexOf("*") < 0) { var watcher = new Watcher(model, expOrFn, cb, options); if (options.immediate) { cb(watcher.value); @@ -900,8 +900,8 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } } }; - _.each(exps, function (exp, i) { - if (_.has(operators, exp)) { + BI._.each(exps, function (exp, i) { + if (BI._.has(operators, exp)) { return; } if (exp.indexOf("*") >= 0) { @@ -929,7 +929,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons _dep.depend(); return NaN; }, function (newValue, oldValue, attrs) { - callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + callback(i, newValue, oldValue, BI._.extend({ index: i }, attrs)); }, options); watchers.push(function unwatchFn() { _w.teardown(); @@ -955,7 +955,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var _regStr = routeToRegExp(exp); var _dep2 = new Dep(); _root._globalDeps || (_root._globalDeps = {}); - if (_.isArray(_root._globalDeps[_regStr])) { + if (BI._.isArray(_root._globalDeps[_regStr])) { _root._globalDeps[_regStr].push(_dep2); } else { _root._globalDeps[_regStr] = [_dep2]; @@ -965,7 +965,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons _dep2.depend(); return NaN; }, function (newValue, oldValue, attrs) { - callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + callback(i, newValue, oldValue, BI._.extend({ index: i }, attrs)); }, options); watchers.push(function unwatchFn() { if (_root._globalDeps) { @@ -1005,7 +1005,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var regStr = routeToRegExp(exp); var dep = new Dep(); root._globalDeps || (root._globalDeps = {}); - if (_.isArray(root._globalDeps[regStr])) { + if (BI._.isArray(root._globalDeps[regStr])) { root._globalDeps[regStr].push(dep); } else { root._globalDeps[regStr] = [dep]; @@ -1015,7 +1015,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons dep.depend(); return NaN; }, function (newValue, oldValue, attrs) { - callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + callback(i, newValue, oldValue, BI._.extend({ index: i }, attrs)); }, options); watchers.push(function unwatchFn() { if (root._globalDeps) { @@ -1029,7 +1029,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons return; } var watcher = new Watcher(model, exp, function (newValue, oldValue, attrs) { - callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + callback(i, newValue, oldValue, BI._.extend({ index: i }, attrs)); }, options); watchers.push(function unwatchFn() { watcher.teardown(); @@ -1045,7 +1045,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } function mixin(xtype, cls) { - mixinInjection[xtype] = _.cloneDeep(cls); + mixinInjection[xtype] = BI._.cloneDeep(cls); } var computedWatcherOptions = { lazy: true }; @@ -1119,7 +1119,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons vm._watchers || (vm._watchers = []); for (var key in watch$$1) { var handler = watch$$1[key]; - if (_.isArray(handler)) { + if (BI._.isArray(handler)) { for (var i = 0; i < handler.length; i++) { vm._watchers.push(createWatcher(vm, key, handler[i])); } @@ -1137,27 +1137,27 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons if (typeof cb === 'string') { cb = vm[cb]; } - return watch(vm.model, keyOrFn, _.bind(cb, vm.$$model ? vm.model : vm), options); + return watch(vm.model, keyOrFn, BI._.bind(cb, vm.$$model ? vm.model : vm), options); } function initMethods(vm, methods) { for (var key in methods) { - vm[key] = methods[key] == null ? noop : _.bind(methods[key], vm.$$model ? vm.model : vm); + vm[key] = methods[key] == null ? noop : BI._.bind(methods[key], vm.$$model ? vm.model : vm); } } function initMixins(vm, mixins) { mixins = (mixins || []).slice(0); - _.each(mixins.reverse(), function (mixinType) { + BI._.each(mixins.reverse(), function (mixinType) { var mixin$$1 = getMixins(mixinType); for (var key in mixin$$1) { if (typeof mixin$$1[key] !== "function") continue; - if (_.has(vm, key)) continue; + if (BI._.has(vm, key)) continue; - vm[key] = _.bind(mixin$$1[key], vm.$$model ? vm.model : vm); + vm[key] = BI._.bind(mixin$$1[key], vm.$$model ? vm.model : vm); } }); } @@ -1282,7 +1282,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function getInjectValues(vm) { var inject = vm.inject || []; var result = {}; - _.each(inject, function (key) { + BI._.each(inject, function (key) { result[key] = getInjectValue(vm, key); }); return result; @@ -1303,7 +1303,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons this.options = model || {}; } this._parent = Model.target; - var state = _.isFunction(this.state) ? this.state() : this.state; + var state = BI._.isFunction(this.state) ? this.state() : this.state; var computed = this.computed; var context = this.context; var inject = this.inject; @@ -1311,7 +1311,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var provide = this.provide; var watch$$1 = this.watch; var actions = this.actions; - var keys = _.keys(this.$$model).concat(_.keys(state)).concat(_.keys(computed)).concat(inject || []).concat(context || []); + var keys = BI._.keys(this.$$model).concat(BI._.keys(state)).concat(BI._.keys(computed)).concat(inject || []).concat(context || []); var mixins = this.mixins; defineProps(this, keys); // deprecated @@ -1320,7 +1320,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons this.$$model && (this.model.__ob__ = this.$$model.__ob__); initMixins(this, mixins); this.init(); - initState(this, _.extend(getInjectValues(this), state)); + initState(this, BI._.extend(getInjectValues(this), state)); initComputed(this, computed); REACTIVE && initWatch(this, watch$$1); initMethods(this, actions); @@ -1341,9 +1341,9 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons for (var _key3 in this._computedWatchers) { this._computedWatchers[_key3].teardown(); } - _.each(this._watchers, function (unwatches) { - unwatches = _.isArray(unwatches) ? unwatches : [unwatches]; - _.each(unwatches, function (unwatch) { + BI._.each(this._watchers, function (unwatches) { + unwatches = BI._.isArray(unwatches) ? unwatches : [unwatches]; + BI._.each(unwatches, function (unwatch) { unwatch(); }); }); @@ -1373,7 +1373,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function toJSON(model) { var result = void 0; - if (_.isArray(model)) { + if (BI._.isArray(model)) { result = []; for (var i = 0, len = model.length; i < len; i++) { result[i] = toJSON(model[i]); @@ -1381,7 +1381,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } else if (model && isPlainObject(model)) { result = {}; for (var _key4 in model) { - if (!_.has($$skipArray, _key4)) { + if (!BI._.has($$skipArray, _key4)) { result[_key4] = toJSON(model[_key4]); } } @@ -1416,4 +1416,4 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons exports.toJSON = toJSON; exports.__esModule = true; -}); +}); \ No newline at end of file diff --git a/dist/fix/fix.proxy.js b/dist/fix/fix.proxy.js index 19eca6178..4a709fb3c 100644 --- a/dist/fix/fix.proxy.js +++ b/dist/fix/fix.proxy.js @@ -2,22 +2,16 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Fix = {})); -}(this, (function (exports) { 'use strict'; +})(this, (function (exports) { 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - _typeof = function (obj) { - return typeof obj; - }; - } else { - _typeof = function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); } function _classCallCheck(instance, Constructor) { @@ -39,6 +33,9 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); return Constructor; } @@ -542,10 +539,10 @@ if (type === "clear" /* CLEAR */ ) { - // collection being cleared - // trigger all effects for target - deps = _toConsumableArray(depsMap.values()); - } else if (key === 'length' && isArray(target)) { + // collection being cleared + // trigger all effects for target + deps = _toConsumableArray(depsMap.values()); + } else if (key === 'length' && isArray(target)) { depsMap.forEach(function (dep, key) { if (key === 'length' || key >= newValue) { deps.push(dep); @@ -728,12 +725,12 @@ if (key === "__v_isReactive" /* IS_REACTIVE */ ) { - return !isReadonly; - } else if (key === "__v_isReadonly" + return !isReadonly; + } else if (key === "__v_isReadonly" /* IS_READONLY */ ) { - return isReadonly; - } else if (key === "__v_raw" + return isReadonly; + } else if (key === "__v_raw" /* RAW */ && receiver === (isReadonly ? shallow ? shallowReadonlyMap : readonlyMap : shallow ? shallowReactiveMap : reactiveMap).get(target)) { return target; @@ -1217,16 +1214,16 @@ if (key === "__v_isReactive" /* IS_REACTIVE */ ) { - return !isReadonly; - } else if (key === "__v_isReadonly" + return !isReadonly; + } else if (key === "__v_isReadonly" /* IS_READONLY */ ) { - return isReadonly; - } else if (key === "__v_raw" + return isReadonly; + } else if (key === "__v_raw" /* RAW */ ) { - return target; - } + return target; + } return Reflect.get(hasOwn(instrumentations, key) && key in target ? instrumentations : target, key, receiver); }; @@ -1335,8 +1332,8 @@ if (targetType === 0 /* INVALID */ ) { - return target; - } + return target; + } var proxy = new Proxy(target, targetType === 2 /* COLLECTION */ @@ -1631,7 +1628,7 @@ return mixinInjection[type]; } function mixin(xtype, cls) { - mixinInjection[xtype] = _.cloneDeep(cls); + mixinInjection[xtype] = BI._.cloneDeep(cls); } var queue = []; @@ -1710,7 +1707,7 @@ } function innerWatch(source, cb, options) { - if (!_.isFunction(cb)) { + if (!BI._.isFunction(cb)) { console.warn("`watch(fn, options?)` signature has been moved to a separate API. " + "Use `watchEffect(fn, options?)` instead. `watch` now only " + "supports `watch(source, cb, options?) signature."); } @@ -1775,21 +1772,21 @@ }; deep = true; - } else if (_.isArray(source)) { + } else if (BI._.isArray(source)) { getter = function getter() { return source.map(function (s) { if (isRef(s)) { return s.value; } else if (isReactive(s)) { return traverse(s); - } else if (_.isFunction(s)) { + } else if (BI._.isFunction(s)) { return s.call(instance); } else { warnInvalidSource(s); } }); }; - } else if (_.isFunction(source)) { + } else if (BI._.isFunction(source)) { if (cb) { // getter with cb getter = function getter() { @@ -1831,7 +1828,7 @@ }; }; - var oldValue = _.isArray(source) ? [] : INITIAL_WATCHER_VALUE; + var oldValue = BI._.isArray(source) ? [] : INITIAL_WATCHER_VALUE; var job = function job() { // 这里去掉的原因是,新增属性没有生效也会触发变化监听 @@ -1903,7 +1900,7 @@ function traverse(value) { var seen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set(); - if (!_.isObject(value) || seen.has(value)) { + if (!BI._.isObject(value) || seen.has(value)) { return value; } @@ -1911,7 +1908,7 @@ if (isRef(value)) { traverse(value.value, seen); - } else if (_.isArray(value)) { + } else if (BI._.isArray(value)) { for (var i = 0; i < value.length; i++) { traverse(value[i], seen); } @@ -1940,7 +1937,7 @@ var expr = ""; for (var i = 0, len = binarys.length; i < len; i++) { - if (_.isBoolean(binarys[i]) || _.has(operators, binarys[i])) { + if (BI._.isBoolean(binarys[i]) || BI._.has(operators, binarys[i])) { expr += binarys[i]; } else { expr += "false"; @@ -1953,7 +1950,7 @@ function watchExp(model, getter) { var result = getter.call(model, model); - if (_.isArray(result)) { + if (BI._.isArray(result)) { return result.concat(); } @@ -1974,14 +1971,14 @@ options.user = true; var exps; - if (_.isFunction(expOrFn)) { + if (BI._.isFunction(expOrFn)) { var watcher = innerWatch(expOrFn, cb, options); return function unwatchFn() { watcher(); }; } - if (!(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && !/\*/.test(expOrFn)) { + if (!(exps = expOrFn.match(/[a-zA-Z0-9BI._.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && !/\*/.test(expOrFn)) { var paths = expOrFn.split("."); var prePaths = paths.slice(0, paths.length - 1); var preGetter = parsePath(prePaths.join(".")); @@ -2030,8 +2027,8 @@ } }; - _.each(exps, function (exp, i) { - if (_.has(operators, exp)) { + BI._.each(exps, function (exp, i) { + if (BI._.has(operators, exp)) { return; } @@ -2079,14 +2076,14 @@ return watchExp(_v2, _getter); }, function (newValue, oldValue) { // a.** 在a变化的时候不会触发change - if (!_.isArray(newValue) && oldValue !== newValue) { + if (!BI._.isArray(newValue) && oldValue !== newValue) { return; } - callback(i, NaN, NaN, _.extend({ + callback(i, NaN, NaN, BI._.extend({ index: i })); - }, _.extend({ + }, BI._.extend({ deep: true }, options))); return; @@ -2145,11 +2142,11 @@ changes = []; if (newValue === true) { - callback(i, NaN, NaN, _.extend({ + callback(i, NaN, NaN, BI._.extend({ index: i })); } - }, _.extend({}, options, { + }, BI._.extend({}, options, { deep: true, onTrigger: function onTrigger(_ref) { var target = _ref.target, @@ -2167,7 +2164,7 @@ watchers.push(innerWatch(function () { return watchExp(model, getter); }, function (newValue, oldValue) { - callback(i, newValue, oldValue, _.extend({ + callback(i, newValue, oldValue, BI._.extend({ index: i })); }, options)); @@ -2188,7 +2185,7 @@ var $$computed = vm.$$computed = {}; for (var key in c) { - $$computed[key] = computed(_.bind(c[key], vm)); + $$computed[key] = computed(BI._.bind(c[key], vm)); } } @@ -2198,7 +2195,7 @@ for (var key in watch) { var handler = watch[key]; - if (_.isArray(handler)) { + if (BI._.isArray(handler)) { for (var i = 0; i < handler.length; i++) { vm._watchers.push(createWatcher(vm, key, handler[i])); } @@ -2218,25 +2215,25 @@ cb = vm[cb]; } - return watch(vm.model, keyOrFn, _.bind(cb, vm), options); + return watch(vm.model, keyOrFn, BI._.bind(cb, vm), options); } function initMethods(vm, methods) { for (var key in methods) { - vm[key] = methods[key] == null ? noop : _.bind(methods[key], vm); + vm[key] = methods[key] == null ? noop : BI._.bind(methods[key], vm); } } function initMixins(vm, mixins) { mixins = (mixins || []).slice(0); - _.each(mixins.reverse(), function (mixinType) { + BI._.each(mixins.reverse(), function (mixinType) { var mixin = getMixins(mixinType); for (var key in mixin) { if (typeof mixin[key] !== "function") continue; - if (_.has(vm, key)) continue; - vm[key] = _.bind(mixin[key], vm); + if (BI._.has(vm, key)) continue; + vm[key] = BI._.bind(mixin[key], vm); } }); } @@ -2329,7 +2326,7 @@ var inject = vm.inject || []; var result = {}; - _.each(inject, function (key) { + BI._.each(inject, function (key) { result[key] = getInjectValue(vm, key); }); @@ -2346,7 +2343,7 @@ value: function _constructor(options, destroyHandler) { this.options = options || {}; this._parent = Model.target; - var state = _.isFunction(this.state) ? this.state() : this.state; + var state = BI._.isFunction(this.state) ? this.state() : this.state; var computed = this.computed; var context = this.context; var inject = this.inject; @@ -2354,14 +2351,14 @@ var watch = this.watch; var actions = this.actions; - _.keys(state).concat(_.keys(computed)).concat(inject || []).concat(context || []); + BI._.keys(state).concat(BI._.keys(computed)).concat(inject || []).concat(context || []); var mixins = this.mixins; defineProps(this); childContext && defineContext(this, childContext); initMixins(this, mixins); this.init(); - initState(this, _.extend(getInjectValues(this), state)); + initState(this, BI._.extend(getInjectValues(this), state)); initComputed(this, computed); REACTIVE && initWatch(this, watch); initMethods(this, actions); @@ -2379,10 +2376,10 @@ }, { key: "destroy", value: function destroy() { - _.each(this._watchers, function (unwatches) { - unwatches = _.isArray(unwatches) ? unwatches : [unwatches]; + BI._.each(this._watchers, function (unwatches) { + unwatches = BI._.isArray(unwatches) ? unwatches : [unwatches]; - _.each(unwatches, function (unwatch) { + BI._.each(unwatches, function (unwatch) { unwatch(); }); }); @@ -2398,7 +2395,7 @@ return Model; }(); function set(target, key, val) { - if (_.isArray(target)) { + if (BI._.isArray(target)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val; @@ -2416,12 +2413,12 @@ return value; } function del(target, key) { - if (_.isArray(target)) { + if (BI._.isArray(target)) { target.splice(key, 1); return; } - if (!_.has(target, key)) { + if (!BI._.has(target, key)) { return; } @@ -2441,7 +2438,7 @@ function toJSON(model) { var result; - if (_.isArray(model)) { + if (BI._.isArray(model)) { result = []; for (var i = 0, len = model.length; i < len; i++) { @@ -2475,4 +2472,4 @@ Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); diff --git a/examples/worker_new.html b/examples/worker_new.html new file mode 100644 index 000000000..53e83c4ee --- /dev/null +++ b/examples/worker_new.html @@ -0,0 +1,15 @@ + + + + + + + Document + + + + +
+ + + \ No newline at end of file diff --git a/examples/worker_new/index.js b/examples/worker_new/index.js new file mode 100644 index 000000000..67646a1ec --- /dev/null +++ b/examples/worker_new/index.js @@ -0,0 +1,105 @@ +document.cookie = "test=demo"; + +// worker获取主线程资源 +var CookieAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() { + this.controller.addActionHandler("Cookie", this.getCookie.bind(this)); + }, + + getCookie: function() { + return document.cookie; + } +}); + +// 调用worker计算 +var FibonacciAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() {}, + + getResult: function(times) { + return this.controller.requestPromise("Fibonacci", { times: times }) + .then(function(v) { + console.log(v); + }); + } +}); + +// 主线程与worker多次交互 +const HeartBeatCheckAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() { + this.controller.addActionHandler("HeartBeatChecked", this.recieveHeartBeatChecked.bind(this)); + }, + + recieveHeartBeatChecked: function (payload) { + console.log("heartbeat: " + payload.time); + }, + + startHeatBeatCheck: function() { + return this.controller.request("HeartBeatCheckStart"); + }, + + stopHeatBeatCheck: function() { + return this.controller.request("HeartBeatCheckStop"); + } +}); + +var WorkerThreadWorker = BI.inherit(BI.Workers.MainThreadWorker, { + initActions: function() { + this.cookieAction = this.createAction(CookieAction); + + this.fibonacciAction = this.createAction(FibonacciAction); + + this.heartBeatCheckAction = this.createAction(HeartBeatCheckAction); + }, + + calculateFibonacci: function(times) { + this.fibonacciAction.getResult(times); + }, + + startHeatBeatCheck: function() { + this.heartBeatCheckAction.startHeatBeatCheck(); + }, + + stopHeatBeatCheck: function() { + this.heartBeatCheckAction.stopHeatBeatCheck(); + } +}); + +var mainThreadWorker = new WorkerThreadWorker({ + workerUrl: "./worker_new/worker.js", + workerName: "demo" +}); + +BI.createWidget({ + type: "bi.vertical", + element: "#wrapper", + vgap: 10, + hgap: 10, + items: [ + { + type: "bi.button", + text: "点击计算斐波那契数列第40项", + width: 200, + handler: function() { + console.log("click"); + + mainThreadWorker.calculateFibonacci(40); + } + }, + { + type: "bi.button", + text: "开始心跳", + width: 200, + handler: function() { + mainThreadWorker.startHeatBeatCheck(); + } + }, + { + type: "bi.button", + text: "停止心跳", + width: 200, + handler: function() { + mainThreadWorker.stopHeatBeatCheck(); + } + } + ] +}); diff --git a/examples/worker_new/worker.js b/examples/worker_new/worker.js new file mode 100644 index 000000000..f30856b21 --- /dev/null +++ b/examples/worker_new/worker.js @@ -0,0 +1,80 @@ +self.importScripts("https://fanruan.design/fineui/fineui_without_jquery_polyfill.js"); + +var CookieAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() {}, + + getCookie: function() { + return this.controller.requestPromise("Cookie"); + } +}); + +function fibonacci(n) { + if (n === 1 || n === 2) { + return 1; + } + + return fibonacci(n - 2) + fibonacci(n - 1); +} + +var FibonacciAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() { + this.controller.addActionHandler("Fibonacci", this.getResult.bind(this)); + }, + + getResult: function(payload) { + return fibonacci(payload.times); + } +}); + +const HeartBeatCheckAction = BI.inherit(BI.Workers.WorkerBaseAction, { + addActionHandler: function() { + this.controller.addActionHandler("HeartBeatCheckStart", this.startHeatBeatCheck.bind(this)); + this.controller.addActionHandler("HeartBeatCheckStop", this.stopHeatBeatCheck.bind(this)); + }, + + startHeatBeatCheck: function() { + var self = this; + + if (!this.timer) { + console.log("heart beat check started"); + + this.timer = setInterval(function() { + // 模拟请求 + setTimeout(function() { + self.controller.request("HeartBeatChecked", { + time: new Date() + }); + }, 50); + }, 5 * 1000); + } else { + console.log("heart beat has already started!"); + } + }, + + stopHeatBeatCheck: function() { + console.log("heart beat check stopped"); + + clearInterval(this.timer); + } +}); + +var WorkerThreadWorker = BI.inherit(BI.Workers.WorkerThreadWorker, { + initActions: function() { + this.cookieAction = this.createAction(CookieAction); + + this.fibonacciAction = this.createAction(FibonacciAction); + + this.heartBeatCheckAction = this.createAction(HeartBeatCheckAction); + }, + + fetchCookie: function() { + return this.cookieAction.getCookie() + .then(function (v) { + console.log(v); + }); + } +}); + +var workerThreadWorker = new WorkerThreadWorker(); + +workerThreadWorker.fetchCookie(); diff --git a/examples/替换loading动画.html b/examples/替换loading动画.html new file mode 100644 index 000000000..9ae3707d4 --- /dev/null +++ b/examples/替换loading动画.html @@ -0,0 +1,104 @@ + + + + + + + + Document + + + + + + +
+ + + + \ No newline at end of file diff --git a/package.json b/package.json index 9cf646a11..8f235e458 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,17 @@ { "name": "fineui", - "version": "2.0.20220617213406", + "version": "2.0.20220720140353", "description": "fineui", - "main": "dist/fineui.min.js", + "main": "dist/fineui_without_conflict.min.js", "types": "dist/lib/index.d.ts", + "bin": { + "fui-cli": "./bin/cli/cli.js" + }, "devDependencies": { "@babel/core": "^7.17.4", "@babel/polyfill": "7.6.0", "@fui/babel-preset-fineui": "^2.0.0", - "@fui/eslint-plugin": "1.0.11", + "@fui/eslint-plugin": "1.0.15", "@types/node": "15.6.1", "autoprefixer": "9.6.1", "babel-loader": "8.0.6", @@ -47,7 +50,7 @@ "source-map-loader": "0.2.4", "style-loader": "0.23.1", "terser-webpack-plugin": "4.2.3", - "typescript": "3.5.2", + "typescript": "3.9.2", "webpack": "4.35.2", "webpack-cli": "3.3.5", "webpack-dev-server": "3.7.2", diff --git a/src/base/1.pane.js b/src/base/1.pane.js index 8df568ead..0a4c93a96 100644 --- a/src/base/1.pane.js +++ b/src/base/1.pane.js @@ -40,30 +40,9 @@ BI.Pane = BI.inherit(BI.Widget, { loading: function () { var self = this, o = this.options; - var isIE = BI.isIE(); - var loadingAnimation = BI.createWidget({ - type: "bi.horizontal", - cls: "bi-loading-widget" + (isIE ? " wave-loading hack" : ""), - height: this._getSize(60), - width: this._getSize(60), - hgap: this._getSize(10), - vgap: 2.5, - items: isIE ? [] : [{ - type: "bi.layout", - cls: "animate-rect rect1", - height: this._getSize(50), - width: this._getSize(5) - }, { - type: "bi.layout", - cls: "animate-rect rect2", - height: this._getSize(50), - width: this._getSize(5) - }, { - type: "bi.layout", - cls: "animate-rect rect3", - height: this._getSize(50), - width: this._getSize(5) - }] + var loadingAnimation = BI.Providers.getProvider("bi.provider.system").getLoading({ + loadingSize: o.loadingSize, + context: this }); // pane在同步方式下由items决定tipText的显示与否 // loading的异步情况下由loaded后对面板的populate的时机决定 diff --git a/src/base/combination/bubble.js b/src/base/combination/bubble.js index 11af9cb7a..f698b4a1a 100644 --- a/src/base/combination/bubble.js +++ b/src/base/combination/bubble.js @@ -44,7 +44,9 @@ var self = this, o = this.options; this._initCombo(); // 延迟绑定事件,这样可以将自己绑定的事情优先执行 - BI.nextTick(this._initPullDownAction.bind(this)); + BI.nextTick(() => { + !this.isDestroyed() && this._initPullDownAction(); + }); this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { if (self.isEnabled() && self.isValid()) { if (type === BI.Events.EXPAND) { @@ -82,7 +84,7 @@ element: this }, BI.LogicFactory.createLogic("vertical", BI.extend(o.logic, { items: [ - {el: this.combo} + { el: this.combo } ] })))); o.isDefaultInit && (this._assertPopupView()); @@ -113,7 +115,7 @@ var enterPopup = false; - function hide (e) { + function hide(e) { if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid() && o.toggle === true) { self._hideView(e); self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.combo); @@ -255,7 +257,7 @@ scrolly: false, element: this.options.container || this, items: [ - {el: this.popupView} + { el: this.popupView } ] }); this._rendered = true; diff --git a/src/base/combination/combo.js b/src/base/combination/combo.js index ddf020a62..27d00fc6a 100644 --- a/src/base/combination/combo.js +++ b/src/base/combination/combo.js @@ -50,9 +50,14 @@ var self = this, o = this.options; this._initCombo(); // 延迟绑定事件,这样可以将自己绑定的事情优先执行 - BI.nextTick(this._initPullDownAction.bind(this)); + BI.nextTick(() => { + !this.isDestroyed() && this._initPullDownAction(); + }); this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { if (self.isEnabled() && self.isValid()) { + if (type === BI.Events.TOGGLE) { + self._toggle(); + } if (type === BI.Events.EXPAND) { self._popupView(); } @@ -88,7 +93,7 @@ element: this }, BI.LogicFactory.createLogic("vertical", BI.extend(o.logic, { items: [ - {el: this.combo} + { el: this.combo } ] })))); o.isDefaultInit && (this._assertPopupView()); @@ -153,7 +158,7 @@ this._assertPopupViewRender(); this.fireEvent(BI.Combo.EVENT_BEFORE_POPUPVIEW); // popupVisible是为了获取其宽高, 放到可视范围之外以防止在IE下闪一下 - this.popupView.css({left: -999999999, top: -99999999}); + this.popupView.css({ left: -999999999, top: -99999999 }); this.popupView.visible(); BI.each(needHideWhenAnotherComboOpen, function (i, combo) { if (i !== self.getName()) { diff --git a/src/base/combination/expander.js b/src/base/combination/expander.js index 83b99566a..407413c40 100644 --- a/src/base/combination/expander.js +++ b/src/base/combination/expander.js @@ -26,7 +26,9 @@ BI.Expander = BI.inherit(BI.Widget, { this._expanded = !!o.el.open; this._initExpander(); // 延迟绑定事件,这样可以将自己绑定的事情优先执行 - BI.nextTick(this._initPullDownAction.bind(this)); + BI.nextTick(() => { + !this.isDestroyed() && this._initPullDownAction(); + }); this.expander.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { if (self.isEnabled() && self.isValid()) { if (type === BI.Events.EXPAND) { @@ -63,7 +65,7 @@ BI.Expander = BI.inherit(BI.Widget, { scrolly: false, element: this, items: [ - {el: this.expander} + { el: this.expander } ] }); o.isDefaultInit && this._assertPopupView(); @@ -167,7 +169,7 @@ BI.Expander = BI.inherit(BI.Widget, { scrolly: false, element: this, items: [ - {el: this.popupView} + { el: this.popupView } ] }); this._rendered = true; diff --git a/src/base/combination/group.button.js b/src/base/combination/group.button.js index a9ba5c23c..ed4f9d680 100644 --- a/src/base/combination/group.button.js +++ b/src/base/combination/group.button.js @@ -197,7 +197,7 @@ BI.ButtonGroup = BI.inherit(BI.Widget, { items = this._packageItems(items, this._packageBtns(this.buttons)); } - this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items))); + this.layouts = BI.createWidget(BI.extend({ element: this }, this._packageLayout(items))); }, setNotSelectedValue: function (v) { @@ -233,6 +233,23 @@ BI.ButtonGroup = BI.inherit(BI.Widget, { }); }, + setValueMap: function (map) { + map = map || {}; + BI.each(this.buttons, function (i, item) { + if (BI.isNotNull(map[item.getValue()])) { + item.setSelected && item.setSelected(true); + } else { + item.setSelected && item.setSelected(false); + } + }); + }, + + setAllSelected: function (v) { + BI.each(this.getAllButtons(), function (i, btn) { + (btn.setSelected || btn.setAllSelected).apply(btn, [v]); + }); + }, + getNotSelectedValue: function () { var v = []; BI.each(this.buttons, function (i, item) { @@ -314,6 +331,16 @@ BI.ButtonGroup = BI.inherit(BI.Widget, { return node; }, + /** + * 滚动到指定的节点 + */ + scrollToValue: function (value, scrollIntoViewOptions) { + var node = this.getNodeByValue(value); + if (node) { + node.element[0].scrollIntoView(scrollIntoViewOptions); + } + }, + empty: function () { BI.ButtonGroup.superclass.empty.apply(this, arguments); this.options.items = []; diff --git a/src/base/combination/group.virtual.js b/src/base/combination/group.virtual.js index e816ab108..d42c7a5b7 100644 --- a/src/base/combination/group.virtual.js +++ b/src/base/combination/group.virtual.js @@ -96,6 +96,20 @@ BI.VirtualGroup = BI.inherit(BI.Widget, { return v; }, + getNodeByValue: function (value) { + return this.buttonMap[value]; + }, + + /** + * 滚动到指定的节点 + */ + scrollToValue: function (value, scrollIntoViewOptions) { + var node = this.getNodeByValue(value); + if (node) { + node.element[0].scrollIntoView(scrollIntoViewOptions); + } + }, + getValue: function () { var v = []; BI.each(this.buttonMap, function (i, item) { @@ -113,7 +127,7 @@ BI.VirtualGroup = BI.inherit(BI.Widget, { this.options.items = items; items = this._packageBtns(items); if (!this.layouts) { - this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items))); + this.layouts = BI.createWidget(BI.extend({ element: this }, this._packageLayout(items))); } else { this.layouts.populate(items, { context: this diff --git a/src/base/combination/switcher.js b/src/base/combination/switcher.js index b464af3d9..1a929f704 100644 --- a/src/base/combination/switcher.js +++ b/src/base/combination/switcher.js @@ -26,7 +26,9 @@ BI.Switcher = BI.inherit(BI.Widget, { var self = this, o = this.options; this._initSwitcher(); // 延迟绑定事件,这样可以将自己绑定的事情优先执行 - BI.nextTick(this._initPullDownAction.bind(this)); + BI.nextTick(() => { + !this.isDestroyed() && this._initPullDownAction(); + }); this.switcher.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { if (self.isEnabled() && self.isValid()) { if (type === BI.Events.EXPAND) { @@ -63,7 +65,7 @@ BI.Switcher = BI.inherit(BI.Widget, { scrolly: false, element: this, items: [ - {el: this.switcher} + { el: this.switcher } ] }); o.isDefaultInit && (this._assertPopupView()); @@ -136,7 +138,7 @@ BI.Switcher = BI.inherit(BI.Widget, { if (!this._created) { this.popupView = BI.createWidget(o.popup, { type: "bi.button_group", - element: o.adapter && BI.Maskers.create(this.getName(), o.adapter, BI.extend({container: this}, o.masker)), + element: o.adapter && BI.Maskers.create(this.getName(), o.adapter, BI.extend({ container: this }, o.masker)), cls: "switcher-popup", layouts: [{ type: "bi.vertical", @@ -157,7 +159,7 @@ BI.Switcher = BI.inherit(BI.Widget, { scrolly: false, element: this, items: [ - {el: this.popupView} + { el: this.popupView } ] }); } diff --git a/src/base/combination/tab.js b/src/base/combination/tab.js index 893513721..90a788a17 100644 --- a/src/base/combination/tab.js +++ b/src/base/combination/tab.js @@ -86,15 +86,18 @@ BI.Tab = BI.inherit(BI.Widget, { created: function () { var self = this, o = this.options; - if (o.showIndex !== false) { - if (BI.isFunction(o.showIndex)) { - var v = this.__watch(o.showIndex, function (context, newValue) { - self.setSelect(newValue); - }); - this.setSelect(v); - } else { - this.setSelect(o.showIndex); - } + + var showIndex; + if (BI.isFunction(o.showIndex)) { + showIndex = this.__watch(o.showIndex, function (context, newValue) { + self.setSelect(newValue); + }); + } else { + showIndex = o.showIndex; + } + + if (showIndex !== false) { + this.setSelect(showIndex); } }, @@ -135,7 +138,7 @@ BI.Tab = BI.inherit(BI.Widget, { getTab: function (v) { this._assertCard(v); -return this.layout.getCardByName(v); + return this.layout.getCardByName(v); }, setValue: function (v) { diff --git a/src/base/list/listview.js b/src/base/list/listview.js index 052abc139..65f777a99 100644 --- a/src/base/list/listview.js +++ b/src/base/list/listview.js @@ -1,5 +1,5 @@ /** - * 表示当前对象 + * 边滚动边加载的列表控件 * * Created by GUY on 2017/5/23. * @class BI.ListView @@ -33,8 +33,8 @@ BI.ListView = BI.inherit(BI.Widget, { items: [BI.extend({ type: "bi.vertical", scrolly: false, - ref: function () { - self.container = this; + ref: function (_ref) { + self.container = _ref; } }, o.el)], element: this @@ -69,8 +69,8 @@ BI.ListView = BI.inherit(BI.Widget, { var self = this, o = this.options; var height = this.element.height(); var minContentHeight = o.scrollTop + height + o.overscanHeight; - var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0, - cnt = this.renderedIndex + 1; + var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0; + var cnt = this.renderedIndex + 1; var lastHeight; var getElementHeight = function () { return self.container.element.height(); @@ -112,6 +112,12 @@ BI.ListView = BI.inherit(BI.Widget, { this.cache = {}; }, + scrollTo: function (scrollTop) { + this.options.scrollTop = scrollTop; + this._calculateBlocksToRender(); + this.element.scrollTop(scrollTop); + }, + populate: function (items) { if (items && this.options.items !== items) { this.restore(); diff --git a/src/base/list/virtualgrouplist.js b/src/base/list/virtualgrouplist.js index 0eae74875..cb8d1b533 100644 --- a/src/base/list/virtualgrouplist.js +++ b/src/base/list/virtualgrouplist.js @@ -62,7 +62,7 @@ BI.VirtualGroupList = BI.inherit(BI.Widget, { }) : o.items; this._populate(); this.ticking = false; - this.element.scroll(function() { + this.element.scroll(function () { o.scrollTop = self.element.scrollTop(); if (!self.ticking) { requestAnimationFrame(function () { @@ -123,7 +123,7 @@ BI.VirtualGroupList = BI.inherit(BI.Widget, { } this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))); this.container.populate(items.map(function (item, i) { - return o.itemFormatter(item, (start < 0 ? 0 : start) * o.blockSize + i) + return o.itemFormatter(item, (start < 0 ? 0 : start) * o.blockSize + i); })); } else { for (var i = (start < 0 ? 0 : start); i <= end; i++) { @@ -134,7 +134,7 @@ BI.VirtualGroupList = BI.inherit(BI.Widget, { } this.container.element.height(o.rowHeight * o.items.length - topHeight); this.container.populate(items.map(function (item, i) { - return o.itemFormatter(item, (start < 0 ? 0 : start) * o.blockSize + i) + return o.itemFormatter(item, (start < 0 ? 0 : start) * o.blockSize + i); })); } }, @@ -162,6 +162,13 @@ BI.VirtualGroupList = BI.inherit(BI.Widget, { this.bottomBlank.setHeight(0); }, + // 暂时只支持固定行高的场景 + scrollTo: function (scrollTop) { + this.options.scrollTop = scrollTop; + this._calculateBlocksToRender(); + this.element.scrollTop(scrollTop); + }, + restore: function () { this.options.scrollTop = 0; this._restore(); diff --git a/src/base/list/virtuallist.js b/src/base/list/virtuallist.js index b7f2700c7..d5881b30b 100644 --- a/src/base/list/virtuallist.js +++ b/src/base/list/virtuallist.js @@ -46,7 +46,6 @@ BI.VirtualList = BI.inherit(BI.Widget, { self.bottomBlank = this; } }], - element: this }; }, @@ -78,7 +77,7 @@ BI.VirtualList = BI.inherit(BI.Widget, { while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) { var items = o.items.slice(index, index + o.blockSize); this.container.addItems(items.map(function (item, i) { - return o.itemFormatter(item, index + i) + return o.itemFormatter(item, index + i); }), this); var addedHeight = getElementHeight() - lastHeight; this.tree.set(cnt, addedHeight); @@ -177,6 +176,12 @@ BI.VirtualList = BI.inherit(BI.Widget, { this.container.attr("items", []); }, + scrollTo: function (scrollTop) { + this.options.scrollTop = scrollTop; + this._calculateBlocksToRender(); + this.element.scrollTop(scrollTop); + }, + restore: function () { this.renderedIndex = -1; this._clearChildren(); diff --git a/src/base/single/0.single.js b/src/base/single/0.single.js index bb926e9a2..47dc6718f 100644 --- a/src/base/single/0.single.js +++ b/src/base/single/0.single.js @@ -9,6 +9,9 @@ * @extends BI.Widget * @abstract */ + +var delayingTooltips; + BI.Single = BI.inherit(BI.Widget, { _defaultConfig: function () { var conf = BI.Single.superclass._defaultConfig.apply(this, arguments); @@ -17,17 +20,29 @@ BI.Single = BI.inherit(BI.Widget, { title: null, warningTitle: null, tipType: null, // success或warning - belowMouse: false // title是否跟随鼠标 + belowMouse: false, // title是否跟随鼠标 + enableHover: false }); }, _showToolTip: function (e, opt) { opt || (opt = {}); - var self = this, o = this.options; - var type = this.getTipType() || (this.isEnabled() ? "success" : "warning"); - var title = type === "success" ? this.getTitle() : (this.getWarningTitle() || this.getTitle()); - if (BI.isKey(title)) { - BI.Tooltips.show(e, this.getName(), title, type, this, opt); + var o = this.options; + var tooltipOpt = {}; + var title = this.getTitle(); + if (BI.isPlainObject(title)) { + tooltipOpt = title; + } else { + tooltipOpt.level = this.getTipType() || "success"; + // 由于以前的用法,存在大量disabled:true搭配warningTitle的情况,所以这里做一个兼容,disabled:true的情况下,依然优先显示warningTitle,避免只设置了warningTitle而没有设置title的情况 + if (BI.isNull(o.tipType) && !this.isEnabled()) { + tooltipOpt.text = (this.getWarningTitle() || title); + } else { + tooltipOpt.text = tooltipOpt.level === "success" ? title : (this.getWarningTitle() || title); + } + } + if (BI.isKey(tooltipOpt.text)) { + BI.Tooltips.show(e, this.getName(), tooltipOpt, this, opt); if (o.action) { BI.Actions.runAction(o.action, "hover", o, this); } @@ -51,7 +66,7 @@ BI.Single = BI.inherit(BI.Widget, { self.setValue(newValue); }) : o.value; BI.Single.superclass._init.apply(this, arguments); - if (BI.isKey(o.title) || BI.isKey(o.warningTitle) + if (o.enableHover || BI.isKey(o.title) || BI.isKey(o.warningTitle) || BI.isFunction(o.title) || BI.isFunction(o.warningTitle)) { this.enableHover({ belowMouse: o.belowMouse, @@ -78,14 +93,16 @@ BI.Single = BI.inherit(BI.Widget, { this.element.on("mouseenter.title" + this.getName(), function (e) { self._e = e; if (self.getTipType() === "warning" || (BI.isKey(self.getWarningTitle()) && !self.isEnabled())) { + delayingTooltips = self.getName(); self.showTimeout = BI.delay(function () { - if (BI.isNotNull(self.showTimeout)) { + if (BI.isNotNull(self.showTimeout) && delayingTooltips === self.getName()) { self._showToolTip(self._e || e, opt); } }, 200); } else if (self.getTipType() === "success" || self.isEnabled()) { + delayingTooltips = self.getName(); self.showTimeout = BI.delay(function () { - if (BI.isNotNull(self.showTimeout)) { + if (BI.isNotNull(self.showTimeout) && delayingTooltips === self.getName()) { self._showToolTip(self._e || e, opt); } }, 500); diff --git a/src/base/single/button/button.basic.js b/src/base/single/button/button.basic.js index aab172495..da7791890 100644 --- a/src/base/single/button/button.basic.js +++ b/src/base/single/button/button.basic.js @@ -49,7 +49,9 @@ BI.BasicButton = BI.inherit(BI.Single, { this.setSelected(true); } // 延迟绑定事件,这样可以将自己绑定的事情优先执行 - BI.nextTick(this.bindEvent.bind(this)); + BI.nextTick(() => { + !this.isDestroyed() && this.bindEvent(); + }); BI.BasicButton.superclass._initRef.apply(this, arguments); }, @@ -211,7 +213,7 @@ BI.BasicButton = BI.inherit(BI.Single, { // enter键等同于点击 o.attributes && o.attributes.zIndex >= 0 && hand.keyup(function (e) { if (e.keyCode === BI.KeyCode.ENTER) { - clk(e); + clk(e); } }); break; @@ -224,7 +226,7 @@ BI.BasicButton = BI.inherit(BI.Single, { "trailing": false }); - function ev (e) { + function ev(e) { if (o.stopEvent) { e.stopEvent(); } @@ -233,7 +235,7 @@ BI.BasicButton = BI.inherit(BI.Single, { } } - function clk (e) { + function clk(e) { ev(e); if (!self.isEnabled() || (self.isOnce() && self.isSelected())) { return; @@ -297,7 +299,7 @@ BI.BasicButton = BI.inherit(BI.Single, { onClick.apply(self, arguments); } - function getBubble () { + function getBubble() { var bubble = self.options.bubble; if (BI.isFunction(bubble)) { return bubble(); diff --git a/src/base/single/button/buttons/button.js b/src/base/single/button/buttons/button.js index cd3cfebd8..420b5f7aa 100644 --- a/src/base/single/button/buttons/button.js +++ b/src/base/single/button/buttons/button.js @@ -30,12 +30,14 @@ adaptiveHeight += (tGap + bGap); } + var clearMinWidth = props.block === true || props.clear === true || props.plain; + return BI.extend(conf, { baseCls: (conf.baseCls || "") + " bi-button" + ((BI.isIE() && BI.isIE9Below()) ? " hack" : ""), attributes: { tabIndex: 1 }, - minWidth: (props.block === true || props.clear === true) ? 0 : 80, + minWidth: clearMinWidth ? 0 : 80, height: isVertical(props.iconPosition) ? adaptiveHeight : 24, shadow: props.clear !== true, isShadowShowingOnSelected: true, @@ -64,7 +66,7 @@ }, render: function () { - var o = this.options; + var o = this.options, self = this; // 由于button默认情况下有个边框,所以要主动算行高 var lineHeight, textHeight = o.textHeight; @@ -110,12 +112,12 @@ tgap: o.iconPosition === "top" ? o.iconGap : 0, bgap: o.iconPosition === "bottom" ? o.iconGap : 0 }; - var items = [this.icon, BI.extend({el: this.text}, gapContainer)]; + var items = [this.icon, BI.extend({ el: this.text }, gapContainer)]; if (isVertical(o.iconPosition)) { layoutType = "bi.vertical"; } if (o.iconPosition === "right" || o.iconPosition === "bottom") { - items = [BI.extend({el: this.text}, gapContainer), this.icon]; + items = [BI.extend({ el: this.text }, gapContainer), this.icon]; } BI.createWidget({ type: "bi.center_adapt", @@ -145,29 +147,20 @@ rgap: o.rgap, element: this, text: o.text, - value: o.value + value: o.value, + title: null, }); } - if (o.block === true) { - this.element.addClass("block"); - } - if (o.clear === true) { - this.element.addClass("clear"); - } - if (o.ghost === true) { - this.element.addClass("ghost"); - } - if (o.plain === true) { - this.element.addClass("plain"); - } - if (o.loading === true) { - this.element.addClass("loading"); - } - if (o.light === true) { - this.element.addClass("light"); - } + var classArr = ["block", "clear", "ghost", "plain", "loading", "light"]; + // 如果 options 对应的属性为 true 则给元素添加 class + BI.each(classArr, function (_, clz) { + if (BI.get(o, clz) === true) { + self.element.addClass(clz); + } + }); + if (o.minWidth > 0) { - this.element.css({"min-width": o.minWidth / BI.pixRatio + BI.pixUnit}); + this.element.css({ "min-width": o.minWidth / BI.pixRatio + BI.pixUnit }); } }, diff --git a/src/base/single/editor/editor.multifile.js b/src/base/single/editor/editor.multifile.js index 7aec220f0..ae0d5e0a9 100644 --- a/src/base/single/editor/editor.multifile.js +++ b/src/base/single/editor/editor.multifile.js @@ -71,6 +71,10 @@ BI.MultifileEditor = BI.inherit(BI.Widget, { this.file.reset(); }, + setUrl: function (v) { + this.file.setUrl(v); + }, + setMaxFileLength: function (v) { this.file.setMaxFileLength(v); }, diff --git a/src/base/single/input/file.js b/src/base/single/input/file.js index b86963f41..ff211e6f1 100644 --- a/src/base/single/input/file.js +++ b/src/base/single/input/file.js @@ -655,6 +655,13 @@ }); }, + setUrl: function(v) { + this.options.url = v; + if (this.wrap) { + this.wrap.url = v; + } + }, + setMaxFileLength: function (v) { this.options.maxLength = v; if (this.wrap) { diff --git a/src/base/single/label/abstract.label.js b/src/base/single/label/abstract.label.js index 76fb27fbd..46e5e7969 100644 --- a/src/base/single/label/abstract.label.js +++ b/src/base/single/label/abstract.label.js @@ -18,10 +18,27 @@ tgap: 0, bgap: 0, highLight: false, - handler: null + handler: null, + enableHover: props.title !== null, }); }, + getTitle: function () { + var title = this.options.title; + var text = this.options.text; + if (BI.isFunction(title)) { + return title(); + } + if (BI.isNotNull(title)) { + return title; + } + + if (BI.isFunction(text)) { + return text(); + } + return text; + }, + _createJson: function () { var o = this.options; return { @@ -374,6 +391,7 @@ setValue: function (v) { BI.AbstractLabel.superclass.setValue.apply(this, arguments); if (!this.isReadOnly()) { + this.options.text = v; this.text.setValue(v); } } diff --git a/src/base/single/tip/tip.toast.js b/src/base/single/tip/tip.toast.js index a9a7aeb7e..0440ee23d 100644 --- a/src/base/single/tip/tip.toast.js +++ b/src/base/single/tip/tip.toast.js @@ -11,7 +11,6 @@ BI.Toast = BI.inherit(BI.Tip, { minWidth: 100, closableMaxWidth: 410, maxWidth: 400, - hgap: 8 }, _defaultConfig: function () { @@ -21,7 +20,10 @@ BI.Toast = BI.inherit(BI.Tip, { level: "success", // success或warning autoClose: true, closable: null, - vgap: 7, + textHeight: 20, + vgap: 10, + innerHgap: 4, + hgap: 8, }); }, @@ -46,7 +48,7 @@ BI.Toast = BI.inherit(BI.Tip, { mouseleave: fn, mousemove: fn }); - var cls = "close-font"; + var cls; switch (o.level) { case "success": cls = "toast-success-font"; @@ -72,19 +74,18 @@ BI.Toast = BI.inherit(BI.Tip, { var items = [{ type: "bi.icon_label", cls: cls + " toast-icon", - width: 36 + height: o.textHeight, }, { el: BI.isPlainObject(o.text) ? o.text : { type: "bi.label", whiteSpace: "normal", text: o.text, - textHeight: 16, + textHeight: o.textHeight, textAlign: "left" }, - rgap: hasCloseIcon() ? 0 : this._const.hgap }]; - var columnSize = [36, "fill"]; + var columnSize = ["", "fill"]; if (hasCloseIcon()) { items.push({ @@ -93,23 +94,20 @@ BI.Toast = BI.inherit(BI.Tip, { handler: function () { self.destroy(); }, - width: 36 + height: o.textHeight, }); - columnSize.push(36); + columnSize.push(""); } - this.text = BI.createWidget({ + return { type: "bi.horizontal", horizontalAlign: BI.HorizontalAlign.Stretch, - element: this, items: items, + hgap: o.hgap, vgap: o.vgap, + innerHgap: o.innerHgap, columnSize: columnSize - }); - }, - - setText: function (text) { - this.text.setText(text); + }; }, beforeDestroy: function () { diff --git a/src/base/single/tip/tip.tooltip.js b/src/base/single/tip/tip.tooltip.js index ca206a849..5499f05ac 100644 --- a/src/base/single/tip/tip.tooltip.js +++ b/src/base/single/tip/tip.tooltip.js @@ -7,8 +7,8 @@ */ BI.Tooltip = BI.inherit(BI.Tip, { _const: { - hgap: 5, - vgap: 3 + hgap: 8, + vgap: 4 }, _defaultConfig: function () { @@ -17,7 +17,8 @@ BI.Tooltip = BI.inherit(BI.Tip, { text: "", level: "success", // success或warning stopEvent: false, - stopPropagation: false + stopPropagation: false, + textAlign: "left", }); }, @@ -44,10 +45,11 @@ BI.Tooltip = BI.inherit(BI.Tip, { type: "bi.vertical", element: this, hgap: this._const.hgap, + innerVgap: this._const.vgap, items: BI.map(texts, function (i, text) { return { type: "bi.label", - textAlign: "left", + textAlign: o.textAlign, whiteSpace: "normal", text: text, textHeight: 18 @@ -58,11 +60,12 @@ BI.Tooltip = BI.inherit(BI.Tip, { this.text = BI.createWidget({ type: "bi.label", element: this, - textAlign: "left", + textAlign: o.textAlign, whiteSpace: "normal", text: o.text, textHeight: 18, - hgap: this._const.hgap + hgap: this._const.hgap, + vgap: this._const.vgap, }); } }, diff --git a/src/case/combo/bubblecombo/combo.bubble.js b/src/case/combo/bubblecombo/combo.bubble.js index 2709295d9..5f0a4c720 100644 --- a/src/case/combo/bubblecombo/combo.bubble.js +++ b/src/case/combo/bubblecombo/combo.bubble.js @@ -52,6 +52,7 @@ BI.BubbleCombo = BI.inherit(BI.Widget, { hideChecker: o.hideChecker, offsetStyle: o.offsetStyle, showArrow: true, + comboClass: o.comboClass, el: o.el, popup: () => BI.extend({ type: "bi.bubble_popup_view", diff --git a/src/case/combo/searchtextvaluecombo/trigger.searchtextvalue.js b/src/case/combo/searchtextvaluecombo/trigger.searchtextvalue.js index 3344d1804..c61093b35 100644 --- a/src/case/combo/searchtextvaluecombo/trigger.searchtextvalue.js +++ b/src/case/combo/searchtextvaluecombo/trigger.searchtextvalue.js @@ -24,7 +24,10 @@ BI.SearchTextValueTrigger = BI.inherit(BI.Trigger, { }, width: o.height, height: o.height, - width: 24, + stopPropagation: true, + handler: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.TOGGLE); + } }; var stateText = this._digest(o.value, o.items) || o.text; diff --git a/src/case/layer/pane.list.js b/src/case/layer/pane.list.js index efeb8c8fb..26be09624 100644 --- a/src/case/layer/pane.list.js +++ b/src/case/layer/pane.list.js @@ -47,11 +47,15 @@ BI.ListPane = BI.inherit(BI.Pane, { } o.itemsCreator(op, function () { calback.apply(self, arguments); - op.times === 1 && BI.nextTick(function () { - self.loaded(); - // callback可能在loading之前执行, check保证显示正确 - self.check(); - }); + o.items = BI.concat(o.items, BI.get(arguments, [0], [])); + if (op.times === 1) { + o.items = BI.get(arguments, [0], []); + BI.nextTick(function () { + self.loaded(); + // callback可能在loading之前执行, check保证显示正确 + self.check(); + }); + } }); }, hasNext: o.hasNext, @@ -113,7 +117,7 @@ BI.ListPane = BI.inherit(BI.Pane, { populate: function (items) { var self = this, o = this.options; if (arguments.length === 0 && (BI.isFunction(this.button_group.attr("itemsCreator")))) {// 接管loader的populate方法 - this.button_group.attr("itemsCreator").apply(this, [{times: 1}, function () { + this.button_group.attr("itemsCreator").apply(this, [{ times: 1 }, function () { if (arguments.length === 0) { throw new Error("参数不能为空"); } @@ -150,6 +154,16 @@ BI.ListPane = BI.inherit(BI.Pane, { this.button_group.setValue.apply(this.button_group, arguments); }, + setAllSelected: function (v) { + if (this.button_group.setAllSelected) { + this.button_group.setAllSelected(v); + } else { + BI.each(this.getAllButtons(), function (i, btn) { + (btn.setSelected || btn.setAllSelected).apply(btn, [v]); + }); + } + }, + getValue: function () { return this.button_group.getValue.apply(this.button_group, arguments); }, @@ -183,4 +197,4 @@ BI.ListPane = BI.inherit(BI.Pane, { } }); BI.ListPane.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.list_pane", BI.ListPane); \ No newline at end of file +BI.shortcut("bi.list_pane", BI.ListPane); diff --git a/src/case/list/list.select.js b/src/case/list/list.select.js index bab4a15af..a1c77107c 100644 --- a/src/case/list/list.select.js +++ b/src/case/list/list.select.js @@ -113,9 +113,13 @@ BI.SelectList = BI.inherit(BI.Widget, { }, setAllSelected: function (v) { - BI.each(this.getAllButtons(), function (i, btn) { - (btn.setSelected || btn.setAllSelected).apply(btn, [v]); - }); + if (this.list.setAllSelected) { + this.list.setAllSelected(v); + } else { + BI.each(this.getAllButtons(), function (i, btn) { + (btn.setSelected || btn.setAllSelected).apply(btn, [v]); + }); + } this.allSelected = !!v; this.toolbar.setSelected(v); this.toolbar.setHalfSelected(false); diff --git a/src/case/ztree/0.treeview.js b/src/case/ztree/0.treeview.js index 2ba474460..41166220d 100644 --- a/src/case/ztree/0.treeview.js +++ b/src/case/ztree/0.treeview.js @@ -95,7 +95,7 @@ BI.TreeView = BI.inherit(BI.Pane, { expandSpeed: "", nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false, - showLine: o.showLine + showLine: o.showLine, }, callback: { beforeExpand: beforeExpand, @@ -360,7 +360,7 @@ BI.TreeView = BI.inherit(BI.Pane, { tagName: "span", whiteSpace: "nowrap", root: true, - keyword: o.paras.keyword + keyword: o.paras.keyword, }, newNode, { type: "bi.text", text: BI.replaceAll(newNode.text, "\n", " ") diff --git a/src/case/ztree/1.asynctree.js b/src/case/ztree/1.asynctree.js index 0bc90c55b..dde174b5b 100644 --- a/src/case/ztree/1.asynctree.js +++ b/src/case/ztree/1.asynctree.js @@ -6,7 +6,10 @@ */ BI.AsyncTree = BI.inherit(BI.TreeView, { _defaultConfig: function () { - return BI.extend(BI.AsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + return BI.extend(BI.AsyncTree.superclass._defaultConfig.apply(this, arguments), { + showIcon: false, + showLine: true, + }); }, _init: function () { BI.AsyncTree.superclass._init.apply(this, arguments); @@ -42,11 +45,14 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, view: { - showIcon: false, + showIcon: o.showIcon, expandSpeed: "", nameIsHTML: true, dblClickExpand: false, - showLine: o.showLine + showLine: o.showLine, + nodeClasses: function (treeId, treeNode) { + return { add: [treeNode.iconCls || ""] }; + } }, callback: { beforeCheck: beforeCheck, @@ -54,7 +60,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { beforeExpand: beforeExpand, onExpand: onExpand, onCollapse: onCollapse, - onClick: onClick + onClick: onClick, } }; diff --git a/src/case/ztree/jquery.ztree.core-3.5.js b/src/case/ztree/jquery.ztree.core-3.5.js index d0f2f4622..875f33e67 100644 --- a/src/case/ztree/jquery.ztree.core-3.5.js +++ b/src/case/ztree/jquery.ztree.core-3.5.js @@ -1,1715 +1,2020 @@ /* - * JQuery zTree core v3.5.18 - * http://zTree.me/ + * JQuery zTree core + * v3.5.48 + * http://treejs.cn/ * * Copyright (c) 2010 Hunter.z * * Licensed same as jquery - MIT License * http://www.opensource.org/licenses/mit-license.php * - * email: hunter.z@263.net - * Date: 2015-06-18 + * Date: 2020-11-21 */ -(function($){ - var settings = {}, roots = {}, caches = {}, - //default consts of core - _consts = { - className: { - BUTTON: "button", - LEVEL: "level", - ICO_LOADING: "ico_loading", - SWITCH: "switch" - }, - event: { - NODECREATED: "ztree_nodeCreated", - CLICK: "ztree_click", - EXPAND: "ztree_expand", - COLLAPSE: "ztree_collapse", - ASYNC_SUCCESS: "ztree_async_success", - ASYNC_ERROR: "ztree_async_error", - REMOVE: "ztree_remove", - SELECTED: "ztree_selected", - UNSELECTED: "ztree_unselected" - }, - id: { - A: "_a", - ICON: "_ico", - SPAN: "_span", - SWITCH: "_switch", - UL: "_ul" - }, - line: { - ROOT: "root", - ROOTS: "roots", - CENTER: "center", - BOTTOM: "bottom", - NOLINE: "noline", - LINE: "line" - }, - folder: { - OPEN: "open", - CLOSE: "close", - DOCU: "docu" - }, - node: { - CURSELECTED: "curSelectedNode" - } - }, - //default setting of core - _setting = { - treeId: "", - treeObj: null, - view: { - addDiyDom: null, - autoCancelSelected: true, - dblClickExpand: true, - expandSpeed: "fast", - fontCss: {}, - nameIsHTML: false, - selectedMulti: true, - showIcon: true, - showLine: true, - showTitle: true, - txtSelectedEnable: false - }, - data: { - key: { - children: "children", - name: "name", - title: "", - url: "url" - }, - simpleData: { - enable: false, - idKey: "id", - pIdKey: "pId", - rootPId: null - }, - keep: { - parent: false, - leaf: false - } - }, - async: { - enable: false, - contentType: "application/x-www-form-urlencoded", - type: "post", - dataType: "text", - url: "", - autoParam: [], - otherParam: [], - dataFilter: null - }, - callback: { - beforeAsync:null, - beforeClick:null, - beforeDblClick:null, - beforeRightClick:null, - beforeMouseDown:null, - beforeMouseUp:null, - beforeExpand:null, - beforeCollapse:null, - beforeRemove:null, - onAsyncError:null, - onAsyncSuccess:null, - onNodeCreated:null, - onClick:null, - onDblClick:null, - onRightClick:null, - onMouseDown:null, - onMouseUp:null, - onExpand:null, - onCollapse:null, - onRemove:null - } - }, - //default root of core - //zTree use root to save full data - _initRoot = function (setting) { - var r = data.getRoot(setting); - if (!r) { - r = {}; - data.setRoot(setting, r); - } - r[setting.data.key.children] = []; - r.expandTriggerFlag = false; - r.curSelectedList = []; - r.noSelection = true; - r.createdNodes = []; - r.zId = 0; - r._ver = (new Date()).getTime(); - }, - //default cache of core - _initCache = function(setting) { - var c = data.getCache(setting); - if (!c) { - c = {}; - data.setCache(setting, c); - } - c.nodes = []; - c.doms = []; - }, - //default bindEvent of core - _bindEvent = function(setting) { - var o = setting.treeObj, - c = consts.event; - o.bind(c.NODECREATED, function (event, treeId, node) { - tools.apply(setting.callback.onNodeCreated, [event, treeId, node]); - }); +(function ($) { + var settings = {}, roots = {}, caches = {}, + //default consts of core + _consts = { + className: { + BUTTON: "button", + ICON: "icon", + LEVEL: "level", + ICO_LOADING: "ico_loading", + SWITCH: "switch", + NAME: 'node_name' + }, + event: { + NODECREATED: "ztree_nodeCreated", + CLICK: "ztree_click", + EXPAND: "ztree_expand", + COLLAPSE: "ztree_collapse", + ASYNC_SUCCESS: "ztree_async_success", + ASYNC_ERROR: "ztree_async_error", + REMOVE: "ztree_remove", + SELECTED: "ztree_selected", + UNSELECTED: "ztree_unselected" + }, + id: { + A: "_a", + ICON: "_ico", + SPAN: "_span", + SWITCH: "_switch", + UL: "_ul" + }, + line: { + ROOT: "root", + ROOTS: "roots", + CENTER: "center", + BOTTOM: "bottom", + NOLINE: "noline", + LINE: "line" + }, + folder: { + OPEN: "open", + CLOSE: "close", + DOCU: "docu" + }, + node: { + CURSELECTED: "curSelectedNode" + } + }, + //default setting of core + _setting = { + treeId: "", + treeObj: null, + view: { + addDiyDom: null, + autoCancelSelected: true, + dblClickExpand: true, + expandSpeed: "fast", + fontCss: {}, + nodeClasses: {}, + nameIsHTML: false, + selectedMulti: true, + showIcon: true, + showLine: true, + showTitle: true, + txtSelectedEnable: false + }, + data: { + key: { + isParent: "isParent", + children: "children", + name: "name", + title: "", + url: "url", + icon: "icon" + }, + render: { + name: null, + title: null, + }, + simpleData: { + enable: false, + idKey: "id", + pIdKey: "pId", + rootPId: null + }, + keep: { + parent: false, + leaf: false + } + }, + async: { + enable: false, + contentType: "application/x-www-form-urlencoded", + type: "post", + dataType: "text", + headers: {}, + xhrFields: {}, + url: "", + autoParam: [], + otherParam: [], + dataFilter: null + }, + callback: { + beforeAsync: null, + beforeClick: null, + beforeDblClick: null, + beforeRightClick: null, + beforeMouseDown: null, + beforeMouseUp: null, + beforeExpand: null, + beforeCollapse: null, + beforeRemove: null, - o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) { - tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]); - }); + onAsyncError: null, + onAsyncSuccess: null, + onNodeCreated: null, + onClick: null, + onDblClick: null, + onRightClick: null, + onMouseDown: null, + onMouseUp: null, + onExpand: null, + onCollapse: null, + onRemove: null + } + }, + //default root of core + //zTree use root to save full data + _initRoot = function (setting) { + var r = data.getRoot(setting); + if (!r) { + r = {}; + data.setRoot(setting, r); + } + data.nodeChildren(setting, r, []); + r.expandTriggerFlag = false; + r.curSelectedList = []; + r.noSelection = true; + r.createdNodes = []; + r.zId = 0; + r._ver = (new Date()).getTime(); + }, + //default cache of core + _initCache = function (setting) { + var c = data.getCache(setting); + if (!c) { + c = {}; + data.setCache(setting, c); + } + c.nodes = []; + c.doms = []; + }, + //default bindEvent of core + _bindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.bind(c.NODECREATED, function (event, treeId, node) { + tools.apply(setting.callback.onNodeCreated, [event, treeId, node]); + }); - o.bind(c.EXPAND, function (event, treeId, node) { - tools.apply(setting.callback.onExpand, [event, treeId, node]); - }); + o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) { + tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]); + }); - o.bind(c.COLLAPSE, function (event, treeId, node) { - tools.apply(setting.callback.onCollapse, [event, treeId, node]); - }); + o.bind(c.EXPAND, function (event, treeId, node) { + tools.apply(setting.callback.onExpand, [event, treeId, node]); + }); - o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) { - tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]); - }); + o.bind(c.COLLAPSE, function (event, treeId, node) { + tools.apply(setting.callback.onCollapse, [event, treeId, node]); + }); - o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) { - tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]); - }); + o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) { + tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]); + }); - o.bind(c.REMOVE, function (event, treeId, treeNode) { - tools.apply(setting.callback.onRemove, [event, treeId, treeNode]); - }); + o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) { + tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]); + }); - o.bind(c.SELECTED, function (event, srcEvent, treeId, node) { - tools.apply(setting.callback.onSelected, [srcEvent, treeId, node]); - }); - o.bind(c.UNSELECTED, function (event, srcEvent, treeId, node) { - tools.apply(setting.callback.onUnSelected, [srcEvent, treeId, node]); - }); - }, - _unbindEvent = function(setting) { - var o = setting.treeObj, - c = consts.event; - o.unbind(c.NODECREATED) - .unbind(c.CLICK) - .unbind(c.EXPAND) - .unbind(c.COLLAPSE) - .unbind(c.ASYNC_SUCCESS) - .unbind(c.ASYNC_ERROR) - .unbind(c.REMOVE) - .unbind(c.SELECTED) - .unbind(c.UNSELECTED); - }, - //default event proxy of core - _eventProxy = function(event) { - var target = event.target, - setting = data.getSetting(event.data.treeId), - tId = "", node = null, - nodeEventType = "", treeEventType = "", - nodeEventCallback = null, treeEventCallback = null, - tmp = null; + o.bind(c.REMOVE, function (event, treeId, treeNode) { + tools.apply(setting.callback.onRemove, [event, treeId, treeNode]); + }); - if (tools.eqs(event.type, "mousedown")) { - treeEventType = "mousedown"; - } else if (tools.eqs(event.type, "mouseup")) { - treeEventType = "mouseup"; - } else if (tools.eqs(event.type, "contextmenu")) { - treeEventType = "contextmenu"; - } else if (tools.eqs(event.type, "click")) { - if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode"+ consts.id.SWITCH) !== null) { - tId = tools.getNodeMainDom(target).id; - nodeEventType = "switchNode"; - } else { - tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]); - if (tmp) { - tId = tools.getNodeMainDom(tmp).id; - nodeEventType = "clickNode"; - } - } - } else if (tools.eqs(event.type, "dblclick")) { - treeEventType = "dblclick"; - tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]); - if (tmp) { - tId = tools.getNodeMainDom(tmp).id; - nodeEventType = "switchNode"; - } - } - if (treeEventType.length > 0 && tId.length == 0) { - tmp = tools.getMDom(setting, target, [{tagName:"a", attrName:"treeNode"+consts.id.A}]); - if (tmp) {tId = tools.getNodeMainDom(tmp).id;} - } - // event to node - if (tId.length>0) { - node = data.getNodeCache(setting, tId); - switch (nodeEventType) { - case "switchNode" : - if (!node.isParent) { - nodeEventType = ""; - } else if (tools.eqs(event.type, "click") - || (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) { - nodeEventCallback = handler.onSwitchNode; - } else { - nodeEventType = ""; - } - break; - case "clickNode" : - nodeEventCallback = handler.onClickNode; - break; - } - } - // event to zTree - switch (treeEventType) { - case "mousedown" : - treeEventCallback = handler.onZTreeMousedown; - break; - case "mouseup" : - treeEventCallback = handler.onZTreeMouseup; - break; - case "dblclick" : - treeEventCallback = handler.onZTreeDblclick; - break; - case "contextmenu" : - treeEventCallback = handler.onZTreeContextmenu; - break; - } - var proxyResult = { - stop: false, - node: node, - nodeEventType: nodeEventType, - nodeEventCallback: nodeEventCallback, - treeEventType: treeEventType, - treeEventCallback: treeEventCallback - }; - return proxyResult - }, - //default init node of core - _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { - if (!n) return; - var r = data.getRoot(setting), - childKey = setting.data.key.children; - n.level = level; - n.tId = setting.treeId + "_" + (++r.zId); - n.parentTId = parentNode ? parentNode.tId : null; - n.open = (typeof n.open == "string") ? tools.eqs(n.open, "true") : !!n.open; - if (n[childKey] && n[childKey].length > 0) { - n.isParent = true; - n.zAsync = true; - } else { - n.isParent = (typeof n.isParent == "string") ? tools.eqs(n.isParent, "true") : !!n.isParent; - n.open = (n.isParent && !setting.async.enable) ? n.open : false; - n.zAsync = !n.isParent; - } - n.isFirstNode = isFirstNode; - n.isLastNode = isLastNode; - n.getParentNode = function() {return data.getNodeCache(setting, n.parentTId);}; - n.getPreNode = function() {return data.getPreNode(setting, n);}; - n.getNextNode = function() {return data.getNextNode(setting, n);}; - n.isAjaxing = false; - data.fixPIdKeyValue(setting, n); - }, - _init = { - bind: [_bindEvent], - unbind: [_unbindEvent], - caches: [_initCache], - nodes: [_initNode], - proxys: [_eventProxy], - roots: [_initRoot], - beforeA: [], - afterA: [], - innerBeforeA: [], - innerAfterA: [], - zTreeTools: [] - }, - //method of operate data - data = { - addNodeCache: function(setting, node) { - data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node; - }, - getNodeCacheId: function(tId) { - return tId.substring(tId.lastIndexOf("_")+1); - }, - addAfterA: function(afterA) { - _init.afterA.push(afterA); - }, - addBeforeA: function(beforeA) { - _init.beforeA.push(beforeA); - }, - addInnerAfterA: function(innerAfterA) { - _init.innerAfterA.push(innerAfterA); - }, - addInnerBeforeA: function(innerBeforeA) { - _init.innerBeforeA.push(innerBeforeA); - }, - addInitBind: function(bindEvent) { - _init.bind.push(bindEvent); - }, - addInitUnBind: function(unbindEvent) { - _init.unbind.push(unbindEvent); - }, - addInitCache: function(initCache) { - _init.caches.push(initCache); - }, - addInitNode: function(initNode) { - _init.nodes.push(initNode); - }, - addInitProxy: function(initProxy, isFirst) { - if (!!isFirst) { - _init.proxys.splice(0,0,initProxy); - } else { - _init.proxys.push(initProxy); - } - }, - addInitRoot: function(initRoot) { - _init.roots.push(initRoot); - }, - addNodesData: function(setting, parentNode, nodes) { - var childKey = setting.data.key.children; - if (!parentNode[childKey]) parentNode[childKey] = []; - if (parentNode[childKey].length > 0) { - parentNode[childKey][parentNode[childKey].length - 1].isLastNode = false; - view.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]); - } - parentNode.isParent = true; - parentNode[childKey] = parentNode[childKey].concat(nodes); - }, - addSelectedNode: function(setting, node) { - var root = data.getRoot(setting); - if (!data.isSelectedNode(setting, node)) { - root.curSelectedList.push(node); - } - }, - addCreatedNode: function(setting, node) { - if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { - var root = data.getRoot(setting); - root.createdNodes.push(node); - } - }, - addZTreeTools: function(zTreeTools) { - _init.zTreeTools.push(zTreeTools); - }, - exSetting: function(s) { - $.extend(true, _setting, s); - }, - fixPIdKeyValue: function(setting, node) { - if (setting.data.simpleData.enable) { - node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId; - } - }, - getAfterA: function(setting, node, array) { - for (var i=0, j=_init.afterA.length; i-1) { - result.push(nodes[i]); - } - result = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value)); - } - return result; - }, - getNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) { - if (!nodes) return (isSingle ? null : []); - var childKey = setting.data.key.children, - result = isSingle ? null : []; - for (var i = 0, l = nodes.length; i < l; i++) { - if (tools.apply(filter, [nodes[i], invokeParam], false)) { - if (isSingle) {return nodes[i];} - result.push(nodes[i]); - } - var tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam); - if (isSingle && !!tmpResult) {return tmpResult;} - result = isSingle ? tmpResult : result.concat(tmpResult); - } - return result; - }, - getPreNode: function(setting, node) { - if (!node) return null; - var childKey = setting.data.key.children, - p = node.parentTId ? node.getParentNode() : data.getRoot(setting); - for (var i=0, l=p[childKey].length; i 0))); - }, - clone: function (obj){ - if (obj === null) return null; - var o = tools.isArray(obj) ? [] : {}; - for(var i in obj){ - o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? arguments.callee(obj[i]) : obj[i]); - } - return o; - }, - eqs: function(str1, str2) { - return str1.toLowerCase() === str2.toLowerCase(); - }, - isArray: function(arr) { - return Object.prototype.toString.apply(arr) === "[object Array]"; - }, - $: function(node, exp, setting) { - if (!!exp && typeof exp != "string") { - setting = exp; - exp = ""; - } - if (typeof node == "string") { - return $(node, setting ? setting.treeObj.get(0).ownerDocument : null); - } else { - return $("#" + node.tId + exp, setting ? setting.treeObj : null); - } - }, - getMDom: function (setting, curDom, targetExpr) { - if (!curDom) return null; - while (curDom && curDom.id !== setting.treeId) { - for (var i=0, l=targetExpr.length; curDom.tagName && i 0 ); - }, - uCanDo: function(setting, e) { - return true; - } - }, - //method of operate ztree dom - view = { - addNodes: function(setting, parentNode, newNodes, isSilent) { - if (setting.data.keep.leaf && parentNode && !parentNode.isParent) { - return; - } - if (!tools.isArray(newNodes)) { - newNodes = [newNodes]; - } - if (setting.data.simpleData.enable) { - newNodes = data.transformTozTreeFormat(setting, newNodes); - } - if (parentNode) { - var target_switchObj = $$(parentNode, consts.id.SWITCH, setting), - target_icoObj = $$(parentNode, consts.id.ICON, setting), - target_ulObj = $$(parentNode, consts.id.UL, setting); + if (tools.eqs(event.type, "mousedown")) { + treeEventType = "mousedown"; + } else if (tools.eqs(event.type, "mouseup")) { + treeEventType = "mouseup"; + } else if (tools.eqs(event.type, "contextmenu")) { + treeEventType = "contextmenu"; + } else if (tools.eqs(event.type, "click")) { + if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.SWITCH) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "switchNode"; + } else { + tmp = tools.getMDom(setting, target, [{ tagName: "a", attrName: "treeNode" + consts.id.A }]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "clickNode"; + } + } + } else if (tools.eqs(event.type, "dblclick")) { + treeEventType = "dblclick"; + tmp = tools.getMDom(setting, target, [{ tagName: "a", attrName: "treeNode" + consts.id.A }]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "switchNode"; + } + } + if (treeEventType.length > 0 && tId.length == 0) { + tmp = tools.getMDom(setting, target, [{ tagName: "a", attrName: "treeNode" + consts.id.A }]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + } + } + // event to node + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "switchNode" : + var isParent = data.nodeIsParent(setting, node); + if (!isParent) { + nodeEventType = ""; + } else if (tools.eqs(event.type, "click") + || (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) { + nodeEventCallback = handler.onSwitchNode; + } else { + nodeEventType = ""; + } + break; + case "clickNode" : + nodeEventCallback = handler.onClickNode; + break; + } + } + // event to zTree + switch (treeEventType) { + case "mousedown" : + treeEventCallback = handler.onZTreeMousedown; + break; + case "mouseup" : + treeEventCallback = handler.onZTreeMouseup; + break; + case "dblclick" : + treeEventCallback = handler.onZTreeDblclick; + break; + case "contextmenu" : + treeEventCallback = handler.onZTreeContextmenu; + break; + } + var proxyResult = { + stop: false, + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult; + }, + //default init node of core + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + var r = data.getRoot(setting), + children = data.nodeChildren(setting, n); + n.level = level; + n.tId = setting.treeId + "_" + (++r.zId); + n.parentTId = parentNode ? parentNode.tId : null; + n.open = (typeof n.open == "string") ? tools.eqs(n.open, "true") : !!n.open; + var isParent = data.nodeIsParent(setting, n); + if (tools.isArray(children)) { + data.nodeIsParent(setting, n, true); + n.zAsync = true; + } else { + isParent = data.nodeIsParent(setting, n, isParent); + n.open = (isParent && !setting.async.enable) ? n.open : false; + n.zAsync = !isParent; + } + n.isFirstNode = isFirstNode; + n.isLastNode = isLastNode; + n.getParentNode = function () { + return data.getNodeCache(setting, n.parentTId); + }; + n.getPreNode = function () { + return data.getPreNode(setting, n); + }; + n.getNextNode = function () { + return data.getNextNode(setting, n); + }; + n.getIndex = function () { + return data.getNodeIndex(setting, n); + }; + n.getPath = function () { + return data.getNodePath(setting, n); + }; + n.isAjaxing = false; + data.fixPIdKeyValue(setting, n); + }, + _init = { + bind: [_bindEvent], + unbind: [_unbindEvent], + caches: [_initCache], + nodes: [_initNode], + proxys: [_eventProxy], + roots: [_initRoot], + beforeA: [], + afterA: [], + innerBeforeA: [], + innerAfterA: [], + zTreeTools: [] + }, + //method of operate data + data = { + addNodeCache: function (setting, node) { + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node; + }, + getNodeCacheId: function (tId) { + return tId.substring(tId.lastIndexOf("_") + 1); + }, + addAfterA: function (afterA) { + _init.afterA.push(afterA); + }, + addBeforeA: function (beforeA) { + _init.beforeA.push(beforeA); + }, + addInnerAfterA: function (innerAfterA) { + _init.innerAfterA.push(innerAfterA); + }, + addInnerBeforeA: function (innerBeforeA) { + _init.innerBeforeA.push(innerBeforeA); + }, + addInitBind: function (bindEvent) { + _init.bind.push(bindEvent); + }, + addInitUnBind: function (unbindEvent) { + _init.unbind.push(unbindEvent); + }, + addInitCache: function (initCache) { + _init.caches.push(initCache); + }, + addInitNode: function (initNode) { + _init.nodes.push(initNode); + }, + addInitProxy: function (initProxy, isFirst) { + if (!!isFirst) { + _init.proxys.splice(0, 0, initProxy); + } else { + _init.proxys.push(initProxy); + } + }, + addInitRoot: function (initRoot) { + _init.roots.push(initRoot); + }, + addNodesData: function (setting, parentNode, index, nodes) { + var children = data.nodeChildren(setting, parentNode), params; + if (!children) { + children = data.nodeChildren(setting, parentNode, []); + index = -1; + } else if (index >= children.length) { + index = -1; + } - if (!parentNode.open) { - view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE); - view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE); - parentNode.open = false; - target_ulObj.css({ - "display": "none" - }); - } + if (children.length > 0 && index === 0) { + children[0].isFirstNode = false; + view.setNodeLineIcos(setting, children[0]); + } else if (children.length > 0 && index < 0) { + children[children.length - 1].isLastNode = false; + view.setNodeLineIcos(setting, children[children.length - 1]); + } + data.nodeIsParent(setting, parentNode, true); - data.addNodesData(setting, parentNode, newNodes); - view.createNodes(setting, parentNode.level + 1, newNodes, parentNode); - if (!isSilent) { - view.expandCollapseParentNode(setting, parentNode, true); - } - } else { - data.addNodesData(setting, data.getRoot(setting), newNodes); - view.createNodes(setting, 0, newNodes, null); - } - }, - appendNodes: function(setting, level, nodes, parentNode, initFlag, openFlag) { - if (!nodes) return []; - var html = [], - childKey = setting.data.key.children; - for (var i = 0, l = nodes.length; i < l; i++) { - var node = nodes[i]; - if (initFlag) { - var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting), - tmpPChild = tmpPNode[childKey], - isFirstNode = ((tmpPChild.length == nodes.length) && (i == 0)), - isLastNode = (i == (nodes.length - 1)); - data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag); - data.addNodeCache(setting, node); - } + if (index < 0) { + data.nodeChildren(setting, parentNode, children.concat(nodes)); + } else { + params = [index, 0].concat(nodes); + children.splice.apply(children, params); + } + }, + addSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + if (!data.isSelectedNode(setting, node)) { + root.curSelectedList.push(node); + } + }, + addCreatedNode: function (setting, node) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + root.createdNodes.push(node); + } + }, + addZTreeTools: function (zTreeTools) { + _init.zTreeTools.push(zTreeTools); + }, + exSetting: function (s) { + $.extend(true, _setting, s); + }, + fixPIdKeyValue: function (setting, node) { + if (setting.data.simpleData.enable) { + node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId; + } + }, + getAfterA: function (setting, node, array) { + for (var i = 0, j = _init.afterA.length; i < j; i++) { + _init.afterA[i].apply(this, arguments); + } + }, + getBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.beforeA.length; i < j; i++) { + _init.beforeA[i].apply(this, arguments); + } + }, + getInnerAfterA: function (setting, node, array) { + for (var i = 0, j = _init.innerAfterA.length; i < j; i++) { + _init.innerAfterA[i].apply(this, arguments); + } + }, + getInnerBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.innerBeforeA.length; i < j; i++) { + _init.innerBeforeA[i].apply(this, arguments); + } + }, + getCache: function (setting) { + return caches[setting.treeId]; + }, + getNodeIndex: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return i; + } + } + return -1; + }, + getNextNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return (i == l ? null : children[i + 1]); + } + } + return null; + }, + getNodeByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return null; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + return nodes[i]; + } + var children = data.nodeChildren(setting, node); + var tmp = data.getNodeByParam(setting, children, key, value); + if (tmp) return tmp; + } + return null; + }, + getNodeCache: function (setting, tId) { + if (!tId) return null; + var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)]; + return n ? n : null; + }, + getNodePath: function (setting, node) { + if (!node) return null; - var childHtml = []; - if (node[childKey] && node[childKey].length > 0) { - //make child html first, because checkType - childHtml = view.appendNodes(setting, level + 1, node[childKey], node, initFlag, openFlag && node.open); - } - if (openFlag) { + var path; + if (node.parentTId) { + path = node.getParentNode().getPath(); + } else { + path = []; + } - view.makeDOMNodeMainBefore(html, setting, node); - view.makeDOMNodeLine(html, setting, node); - data.getBeforeA(setting, node, html); - view.makeDOMNodeNameBefore(html, setting, node); - data.getInnerBeforeA(setting, node, html); - view.makeDOMNodeIcon(html, setting, node); - data.getInnerAfterA(setting, node, html); - view.makeDOMNodeNameAfter(html, setting, node); - data.getAfterA(setting, node, html); - if (node.isParent && node.open) { - view.makeUlHtml(setting, node, html, childHtml.join('')); - } - view.makeDOMNodeMainAfter(html, setting, node); - data.addCreatedNode(setting, node); - } - } - return html; - }, - appendParentULDom: function(setting, node) { - var html = [], - nObj = $$(node, setting); - if (!nObj.get(0) && !!node.parentTId) { - view.appendParentULDom(setting, node.getParentNode()); - nObj = $$(node, setting); - } - var ulObj = $$(node, consts.id.UL, setting); - if (ulObj.get(0)) { - ulObj.remove(); - } - var childKey = setting.data.key.children, - childHtml = view.appendNodes(setting, node.level+1, node[childKey], node, false, true); - view.makeUlHtml(setting, node, html, childHtml.join('')); - nObj.append(html.join('')); - }, - asyncNode: function(setting, node, isSilent, callback) { - var i, l; - if (node && !node.isParent) { - tools.apply(callback); - return false; - } else if (node && node.isAjaxing) { - return false; - } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) { - tools.apply(callback); - return false; - } - if (node) { - node.isAjaxing = true; - var icoObj = $$(node, consts.id.ICON, setting); - icoObj.attr({"style":"", "class":consts.className.BUTTON + " " + consts.className.ICO_LOADING}); - } + if (path) { + path.push(node); + } - var tmpParam = {}; - for (i = 0, l = setting.async.autoParam.length; node && i < l; i++) { - var pKey = setting.async.autoParam[i].split("="), spKey = pKey; - if (pKey.length>1) { - spKey = pKey[1]; - pKey = pKey[0]; - } - tmpParam[spKey] = node[pKey]; - } - if (tools.isArray(setting.async.otherParam)) { - for (i = 0, l = setting.async.otherParam.length; i < l; i += 2) { - tmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1]; - } - } else { - for (var p in setting.async.otherParam) { - tmpParam[p] = setting.async.otherParam[p]; - } - } + return path; + }, + getNodes: function (setting) { + return data.nodeChildren(setting, data.getRoot(setting)); + }, + getNodesByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParam(setting, children, key, value)); + } + return result; + }, + getNodesByParamFuzzy: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + value = value.toLowerCase(); + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (typeof node[key] == "string" && nodes[i][key].toLowerCase().indexOf(value) > -1) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParamFuzzy(setting, children, key, value)); + } + return result; + }, + getNodesByFilter: function (setting, nodes, filter, isSingle, invokeParam) { + if (!nodes) return (isSingle ? null : []); + var result = isSingle ? null : []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (tools.apply(filter, [node, invokeParam], false)) { + if (isSingle) { + return node; + } + result.push(node); + } + var children = data.nodeChildren(setting, node); + var tmpResult = data.getNodesByFilter(setting, children, filter, isSingle, invokeParam); + if (isSingle && !!tmpResult) { + return tmpResult; + } + result = isSingle ? tmpResult : result.concat(tmpResult); + } + return result; + }, + getPreNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] === node) { + return (i == 0 ? null : children[i - 1]); + } + } + return null; + }, + getRoot: function (setting) { + return setting ? roots[setting.treeId] : null; + }, + getRoots: function () { + return roots; + }, + getSetting: function (treeId) { + return settings[treeId]; + }, + getSettings: function () { + return settings; + }, + getZTreeTools: function (treeId) { + var r = this.getRoot(this.getSetting(treeId)); + return r ? r.treeTools : null; + }, + initCache: function (setting) { + for (var i = 0, j = _init.caches.length; i < j; i++) { + _init.caches[i].apply(this, arguments); + } + }, + initNode: function (setting, level, node, parentNode, preNode, nextNode) { + for (var i = 0, j = _init.nodes.length; i < j; i++) { + _init.nodes[i].apply(this, arguments); + } + }, + initRoot: function (setting) { + for (var i = 0, j = _init.roots.length; i < j; i++) { + _init.roots[i].apply(this, arguments); + } + }, + isSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i]) return true; + } + return false; + }, + nodeChildren: function (setting, node, newChildren) { + if (!node) { + return null; + } + var key = setting.data.key.children; + if (typeof newChildren !== 'undefined') { + node[key] = newChildren; + } + return node[key]; + }, + nodeIsParent: function (setting, node, newIsParent) { + if (!node) { + return false; + } + var key = setting.data.key.isParent; + if (typeof newIsParent !== 'undefined') { + if (typeof newIsParent === "string") { + newIsParent = tools.eqs(newIsParent, "true"); + } + newIsParent = !!newIsParent; + node[key] = newIsParent; + } else if (typeof node[key] == "string") { + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }, + nodeName: function (setting, node, newName) { + var key = setting.data.key.name; + if (typeof newName !== 'undefined') { + node[key] = newName; + } + var rawName = "" + node[key]; + if (typeof setting.data.render.name === 'function') { + return setting.data.render.name.call(this, rawName, node); + } + return rawName; + }, + nodeTitle: function (setting, node) { + var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title; + var rawTitle = "" + node[t]; + if (typeof setting.data.render.title === 'function') { + return setting.data.render.title.call(this, rawTitle, node); + } + return rawTitle; + }, + removeNodeCache: function (setting, node) { + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + } + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null; + }, + removeSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) { + root.curSelectedList.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, node]); + i--; + j--; + } + } + }, + setCache: function (setting, cache) { + caches[setting.treeId] = cache; + }, + setRoot: function (setting, root) { + roots[setting.treeId] = root; + }, + setZTreeTools: function (setting, zTreeTools) { + for (var i = 0, j = _init.zTreeTools.length; i < j; i++) { + _init.zTreeTools[i].apply(this, arguments); + } + }, + transformToArrayFormat: function (setting, nodes) { + if (!nodes) return []; + var r = []; + if (tools.isArray(nodes)) { + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + _do(node); + } + } else { + _do(nodes); + } + return r; - var _tmpV = data.getRoot(setting)._ver; - $.ajax({ - contentType: setting.async.contentType, - cache: false, - type: setting.async.type, - url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url), - data: tmpParam, - dataType: setting.async.dataType, - success: function(msg) { - if (_tmpV != data.getRoot(setting)._ver) { - return; - } - var newNodes = []; - try { - if (!msg || msg.length == 0) { - newNodes = []; - } else if (typeof msg == "string") { - newNodes = eval("(" + msg + ")"); - } else { - newNodes = msg; - } - } catch(err) { - newNodes = msg; - } + function _do(_node) { + r.push(_node); + var children = data.nodeChildren(setting, _node); + if (children) { + r = r.concat(data.transformToArrayFormat(setting, children)); + } + } + }, + transformTozTreeFormat: function (setting, sNodes) { + var i, l, + key = setting.data.simpleData.idKey, + parentKey = setting.data.simpleData.pIdKey; + if (!key || key == "" || !sNodes) return []; - if (node) { - node.isAjaxing = null; - node.zAsync = true; - } - view.setNodeLineIcos(setting, node); - if (newNodes && newNodes !== "") { - newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes); - view.addNodes(setting, node, !!newNodes ? tools.clone(newNodes) : [], !!isSilent); - } else { - view.addNodes(setting, node, [], !!isSilent); - } - setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]); - tools.apply(callback); - }, - error: function(XMLHttpRequest, textStatus, errorThrown) { - if (_tmpV != data.getRoot(setting)._ver) { - return; - } - if (node) node.isAjaxing = null; - view.setNodeLineIcos(setting, node); - setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]); - } - }); - return true; - }, - cancelPreSelectedNode: function (setting, node, excludeNode) { - var list = data.getRoot(setting).curSelectedList, - i, n; - for (i=list.length-1; i>=0; i--) { - n = list[i]; - if (node === n || (!node && (!excludeNode || excludeNode !== n))) { - $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED); - if (node) { - data.removeSelectedNode(setting, node); - setting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]); - break; - } else { - list.splice(i, 1); - setting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]); - } - } - } - }, - createNodeCallback: function(setting) { - if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { - var root = data.getRoot(setting); - while (root.createdNodes.length>0) { - var node = root.createdNodes.shift(); - tools.apply(setting.view.addDiyDom, [setting.treeId, node]); - if (!!setting.callback.onNodeCreated) { - setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]); - } - } - } - }, - createNodes: function(setting, level, nodes, parentNode) { - if (!nodes || nodes.length == 0) return; - var root = data.getRoot(setting), - childKey = setting.data.key.children, - openFlag = !parentNode || parentNode.open || !!$$(parentNode[childKey][0], setting).get(0); - root.createdNodes = []; - var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, true, openFlag); - if (!parentNode) { - setting.treeObj.append(zTreeHtml.join('')); - } else { - var ulObj = $$(parentNode, consts.id.UL, setting); - if (ulObj.get(0)) { - ulObj.append(zTreeHtml.join('')); - } - } - view.createNodeCallback(setting); - }, - destroy: function(setting) { - if (!setting) return; - data.initCache(setting); - data.initRoot(setting); - event.unbindTree(setting); - event.unbindEvent(setting); - setting.treeObj.empty(); - delete settings[setting.treeId]; - }, - expandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) { - var root = data.getRoot(setting), - childKey = setting.data.key.children; - if (!node) { - tools.apply(callback, []); - return; - } - if (root.expandTriggerFlag) { - var _callback = callback; - callback = function(){ - if (_callback) _callback(); - if (node.open) { - setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]); - } else { - setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]); - } - }; - root.expandTriggerFlag = false; - } - if (!node.open && node.isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (node[childKey] && node[childKey].length>0 && !$$(node[childKey][0], setting).get(0)))) { - view.appendParentULDom(setting, node); - view.createNodeCallback(setting); - } - if (node.open == expandFlag) { - tools.apply(callback, []); - return; - } - var ulObj = $$(node, consts.id.UL, setting), - switchObj = $$(node, consts.id.SWITCH, setting), - icoObj = $$(node, consts.id.ICON, setting); + if (tools.isArray(sNodes)) { + var r = []; + var tmpMap = {}; + for (i = 0, l = sNodes.length; i < l; i++) { + tmpMap[sNodes[i][key]] = sNodes[i]; + } + for (i = 0, l = sNodes.length; i < l; i++) { + var p = tmpMap[sNodes[i][parentKey]]; + if (p && sNodes[i][key] != sNodes[i][parentKey]) { + var children = data.nodeChildren(setting, p); + if (!children) { + children = data.nodeChildren(setting, p, []); + } + children.push(sNodes[i]); + } else { + r.push(sNodes[i]); + } + } + return r; + } else { + return [sNodes]; + } + } + }, + //method of event proxy + event = { + bindEvent: function (setting) { + for (var i = 0, j = _init.bind.length; i < j; i++) { + _init.bind[i].apply(this, arguments); + } + }, + unbindEvent: function (setting) { + for (var i = 0, j = _init.unbind.length; i < j; i++) { + _init.unbind[i].apply(this, arguments); + } + }, + bindTree: function (setting) { + var eventParam = { + treeId: setting.treeId + }, + o = setting.treeObj; + if (!setting.view.txtSelectedEnable) { + // for can't select text + o.bind('selectstart', handler.onSelectStart).css({ + "-moz-user-select": "-moz-none" + }); + } + o.bind('click', eventParam, event.proxy); + o.bind('dblclick', eventParam, event.proxy); + o.bind('mouseover', eventParam, event.proxy); + o.bind('mouseout', eventParam, event.proxy); + o.bind('mousedown', eventParam, event.proxy); + o.bind('mouseup', eventParam, event.proxy); + o.bind('contextmenu', eventParam, event.proxy); + }, + unbindTree: function (setting) { + var o = setting.treeObj; + o.unbind('selectstart', handler.onSelectStart) + .unbind('click', event.proxy) + .unbind('dblclick', event.proxy) + .unbind('mouseover', event.proxy) + .unbind('mouseout', event.proxy) + .unbind('mousedown', event.proxy) + .unbind('mouseup', event.proxy) + .unbind('contextmenu', event.proxy); + }, + doProxy: function (e) { + var results = []; + for (var i = 0, j = _init.proxys.length; i < j; i++) { + var proxyResult = _init.proxys[i].apply(this, arguments); + results.push(proxyResult); + if (proxyResult.stop) { + break; + } + } + return results; + }, + proxy: function (e) { + var setting = data.getSetting(e.data.treeId); + if (!tools.uCanDo(setting, e)) return true; + var results = event.doProxy(e), + r = true, x = false; + for (var i = 0, l = results.length; i < l; i++) { + var proxyResult = results[i]; + if (proxyResult.nodeEventCallback) { + x = true; + r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + if (proxyResult.treeEventCallback) { + x = true; + r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + } + return r; + } + }, + //method of event handler + handler = { + onSwitchNode: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (node.open) { + if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } else { + if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } + return true; + }, + onClickNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + clickFlag = ((setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1; + if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true; + if (clickFlag === 0) { + view.cancelPreSelectedNode(setting, node); + } else { + view.selectNode(setting, node, clickFlag === 2); + } + setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]); + return true; + }, + onZTreeMousedown: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]); + } + return true; + }, + onZTreeMouseup: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]); + } + return true; + }, + onZTreeDblclick: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]); + } + return true; + }, + onZTreeContextmenu: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]); + } + return (typeof setting.callback.onRightClick) != "function"; + }, + onSelectStart: function (e) { + var n = e.originalEvent.srcElement.nodeName.toLowerCase(); + return (n === "input" || n === "textarea"); + } + }, + //method of tools for zTree + tools = { + apply: function (fun, param, defaultValue) { + if ((typeof fun) == "function") { + return fun.apply(zt, param ? param : []); + } + return defaultValue; + }, + canAsync: function (setting, node) { + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + return (setting.async.enable && node && isParent && !(node.zAsync || (children && children.length > 0))); + }, + clone: function (obj) { + if (obj === null) return null; + var o = tools.isArray(obj) ? [] : {}; + for (var i in obj) { + o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? tools.clone(obj[i]) : obj[i]); + } + return o; + }, + eqs: function (str1, str2) { + return str1.toLowerCase() === str2.toLowerCase(); + }, + isArray: function (arr) { + return Object.prototype.toString.apply(arr) === "[object Array]"; + }, + isElement: function (o) { + return ( + typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string" + ); + }, + $: function (node, exp, setting) { + if (!!exp && typeof exp != "string") { + setting = exp; + exp = ""; + } + if (typeof node == "string") { + return $(node, setting ? setting.treeObj.get(0).ownerDocument : null); + } else { + return $("#" + node.tId + exp, setting ? setting.treeObj : null); + } + }, + getMDom: function (setting, curDom, targetExpr) { + if (!curDom) return null; + while (curDom && curDom.id !== setting.treeId) { + for (var i = 0, l = targetExpr.length; curDom.tagName && i < l; i++) { + if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) { + return curDom; + } + } + curDom = curDom.parentNode; + } + return null; + }, + getNodeMainDom: function (target) { + return ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0)); + }, + isChildOrSelf: function (dom, parentId) { + return ($(dom).closest("#" + parentId).length > 0); + }, + uCanDo: function (setting, e) { + return true; + } + }, + //method of operate ztree dom + view = { + addNodes: function (setting, parentNode, index, newNodes, isSilent) { + var isParent = data.nodeIsParent(setting, parentNode); + if (setting.data.keep.leaf && parentNode && !isParent) { + return; + } + if (!tools.isArray(newNodes)) { + newNodes = [newNodes]; + } + if (setting.data.simpleData.enable) { + newNodes = data.transformTozTreeFormat(setting, newNodes); + } + if (parentNode) { + var target_switchObj = $$(parentNode, consts.id.SWITCH, setting), + target_icoObj = $$(parentNode, consts.id.ICON, setting), + target_ulObj = $$(parentNode, consts.id.UL, setting); - if (node.isParent) { - node.open = !node.open; - if (node.iconOpen && node.iconClose) { - icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); - } + if (!parentNode.open) { + view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE); + view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE); + parentNode.open = false; + target_ulObj.css({ + "display": "none" + }); + } - if (node.open) { - view.replaceSwitchClass(node, switchObj, consts.folder.OPEN); - view.replaceIcoClass(node, icoObj, consts.folder.OPEN); - if (animateFlag == false || setting.view.expandSpeed == "") { - ulObj.show(); - tools.apply(callback, []); - } else { - if (node[childKey] && node[childKey].length > 0) { - ulObj.slideDown(setting.view.expandSpeed, callback); - } else { - ulObj.show(); - tools.apply(callback, []); - } - } - } else { - view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE); - view.replaceIcoClass(node, icoObj, consts.folder.CLOSE); - if (animateFlag == false || setting.view.expandSpeed == "" || !(node[childKey] && node[childKey].length > 0)) { - ulObj.hide(); - tools.apply(callback, []); - } else { - ulObj.slideUp(setting.view.expandSpeed, callback); - } - } - } else { - tools.apply(callback, []); - } - }, - expandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) { - if (!node) return; - if (!node.parentTId) { - view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); - return; - } else { - view.expandCollapseNode(setting, node, expandFlag, animateFlag); - } - if (node.parentTId) { - view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback); - } - }, - expandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) { - var root = data.getRoot(setting), - childKey = setting.data.key.children, - treeNodes = (node) ? node[childKey]: root[childKey], - selfAnimateSign = (node) ? false : animateFlag, - expandTriggerFlag = data.getRoot(setting).expandTriggerFlag; - data.getRoot(setting).expandTriggerFlag = false; - if (treeNodes) { - for (var i = 0, l = treeNodes.length; i < l; i++) { - if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign); - } - } - data.getRoot(setting).expandTriggerFlag = expandTriggerFlag; - view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback ); - }, - isSelectedNode: function (setting, node) { - if (!node) { - return false; - } - var list = data.getRoot(setting).curSelectedList, - i; - for (i=list.length-1; i>=0; i--) { - if (node === list[i]) { - return true; - } - } - return false; - }, - makeDOMNodeIcon: function(html, setting, node) { - var nameStr = data.getNodeName(setting, node), - name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g,'&').replace(//g,'>'); - html.push("",name,""); - }, - makeDOMNodeLine: function(html, setting, node) { - html.push(""); - }, - makeDOMNodeMainAfter: function(html, setting, node) { - html.push(""); - }, - makeDOMNodeMainBefore: function(html, setting, node) { - html.push("
  • "); - }, - makeDOMNodeNameAfter: function(html, setting, node) { - html.push(""); - }, - makeDOMNodeNameBefore: function(html, setting, node) { - var title = data.getNodeTitle(setting, node), - url = view.makeNodeUrl(setting, node), - fontcss = view.makeNodeFontCss(setting, node), - fontStyle = []; - for (var f in fontcss) { - fontStyle.push(f, ":", fontcss[f], ";"); - } - html.push(" 0) ? "href='" + url + "'" : ""), " target='",view.makeNodeTarget(node),"' style='", fontStyle.join(''), - "'"); - if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {html.push("title='", title.replace(/'/g,"'").replace(//g,'>'),"'");} - html.push(">"); - }, - makeNodeFontCss: function(setting, node) { - var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss); - return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {}; - }, - makeNodeIcoClass: function(setting, node) { - var icoCss = ["ico"]; - if (!node.isAjaxing) { - icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0]; - if (node.isParent) { - icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); - } else { - icoCss.push(consts.folder.DOCU); - } - } - return consts.className.BUTTON + " " + icoCss.join('_'); - }, - makeNodeIcoStyle: function(setting, node) { - var icoStyle = []; - if (!node.isAjaxing) { - var icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node.icon; - if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;"); - if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) { - icoStyle.push("width:0px;height:0px;"); - } - } - return icoStyle.join(''); - }, - makeNodeLineClass: function(setting, node) { - var lineClass = []; - if (setting.view.showLine) { - if (node.level == 0 && node.isFirstNode && node.isLastNode) { - lineClass.push(consts.line.ROOT); - } else if (node.level == 0 && node.isFirstNode) { - lineClass.push(consts.line.ROOTS); - } else if (node.isLastNode) { - lineClass.push(consts.line.BOTTOM); - } else { - lineClass.push(consts.line.CENTER); - } - } else { - lineClass.push(consts.line.NOLINE); - } - if (node.isParent) { - lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); - } else { - lineClass.push(consts.folder.DOCU); - } - return view.makeNodeLineClassEx(node) + lineClass.join('_'); - }, - makeNodeLineClassEx: function(node) { - return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " "; - }, - makeNodeTarget: function(node) { - return (node.target || "_blank"); - }, - makeNodeUrl: function(setting, node) { - var urlKey = setting.data.key.url; - return node[urlKey] ? node[urlKey] : null; - }, - makeUlHtml: function(setting, node, html, content) { - html.push("
      "); - html.push(content); - html.push("
    "); - }, - makeUlLineClass: function(setting, node) { - return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : ""); - }, - removeChildNodes: function(setting, node) { - if (!node) return; - var childKey = setting.data.key.children, - nodes = node[childKey]; - if (!nodes) return; + data.addNodesData(setting, parentNode, index, newNodes); + view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index); + if (!isSilent) { + view.expandCollapseParentNode(setting, parentNode, true); + } + } else { + data.addNodesData(setting, data.getRoot(setting), index, newNodes); + view.createNodes(setting, 0, newNodes, null, index); + } + }, + appendNodes: function (setting, level, nodes, parentNode, index, initFlag, openFlag) { + if (!nodes) return []; + var html = []; - for (var i = 0, l = nodes.length; i < l; i++) { - data.removeNodeCache(setting, nodes[i]); - } - data.removeSelectedNode(setting); - delete node[childKey]; + var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting), + tmpPChild = data.nodeChildren(setting, tmpPNode), + isFirstNode, isLastNode; - if (!setting.data.keep.parent) { - node.isParent = false; - node.open = false; - var tmp_switchObj = $$(node, consts.id.SWITCH, setting), - tmp_icoObj = $$(node, consts.id.ICON, setting); - view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU); - view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU); - $$(node, consts.id.UL, setting).remove(); - } else { - $$(node, consts.id.UL, setting).empty(); - } - }, - setFirstNode: function(setting, parentNode) { - var childKey = setting.data.key.children, childLength = parentNode[childKey].length; - if ( childLength > 0) { - parentNode[childKey][0].isFirstNode = true; - } - }, - setLastNode: function(setting, parentNode) { - var childKey = setting.data.key.children, childLength = parentNode[childKey].length; - if ( childLength > 0) { - parentNode[childKey][childLength - 1].isLastNode = true; - } - }, - removeNode: function(setting, node) { - var root = data.getRoot(setting), - childKey = setting.data.key.children, - parentNode = (node.parentTId) ? node.getParentNode() : root; + if (!tmpPChild || index >= tmpPChild.length - nodes.length) { + index = -1; + } - node.isFirstNode = false; - node.isLastNode = false; - node.getPreNode = function() {return null;}; - node.getNextNode = function() {return null;}; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (initFlag) { + isFirstNode = ((index === 0 || tmpPChild.length == nodes.length) && (i == 0)); + isLastNode = (index < 0 && i == (nodes.length - 1)); + data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag); + data.addNodeCache(setting, node); + } + var isParent = data.nodeIsParent(setting, node); - if (!data.getNodeCache(setting, node.tId)) { - return; - } + var childHtml = []; + var children = data.nodeChildren(setting, node); + if (children && children.length > 0) { + //make child html first, because checkType + childHtml = view.appendNodes(setting, level + 1, children, node, -1, initFlag, openFlag && node.open); + } + if (openFlag) { + view.makeDOMNodeMainBefore(html, setting, node); + view.makeDOMNodeLine(html, setting, node); + data.getBeforeA(setting, node, html); + view.makeDOMNodeNameBefore(html, setting, node); + data.getInnerBeforeA(setting, node, html); + view.makeDOMNodeIcon(html, setting, node); + data.getInnerAfterA(setting, node, html); + view.makeDOMNodeNameAfter(html, setting, node); + data.getAfterA(setting, node, html); + if (isParent && node.open) { + view.makeUlHtml(setting, node, html, childHtml.join('')); + } + view.makeDOMNodeMainAfter(html, setting, node); + data.addCreatedNode(setting, node); + } + } + return html; + }, + appendParentULDom: function (setting, node) { + var html = [], + nObj = $$(node, setting); + if (!nObj.get(0) && !!node.parentTId) { + view.appendParentULDom(setting, node.getParentNode()); + nObj = $$(node, setting); + } + var ulObj = $$(node, consts.id.UL, setting); + if (ulObj.get(0)) { + ulObj.remove(); + } + var children = data.nodeChildren(setting, node), + childHtml = view.appendNodes(setting, node.level + 1, children, node, -1, false, true); + view.makeUlHtml(setting, node, html, childHtml.join('')); + nObj.append(html.join('')); + }, + asyncNode: function (setting, node, isSilent, callback) { + var i, l; + var isParent = data.nodeIsParent(setting, node); + if (node && !isParent) { + tools.apply(callback); + return false; + } else if (node && node.isAjaxing) { + return false; + } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) { + tools.apply(callback); + return false; + } + if (node) { + node.isAjaxing = true; + var icoObj = $$(node, consts.id.ICON, setting); + icoObj.attr({ "style": "", "class": consts.className.BUTTON + " " + consts.className.ICO_LOADING }); + } - $$(node, setting).remove(); - data.removeNodeCache(setting, node); - data.removeSelectedNode(setting, node); + var tmpParam = {}; + var autoParam = tools.apply(setting.async.autoParam, [setting.treeId, node], setting.async.autoParam); + for (i = 0, l = autoParam.length; node && i < l; i++) { + var pKey = autoParam[i].split("="), spKey = pKey; + if (pKey.length > 1) { + spKey = pKey[1]; + pKey = pKey[0]; + } + tmpParam[spKey] = node[pKey]; + } + var otherParam = tools.apply(setting.async.otherParam, [setting.treeId, node], setting.async.otherParam); + if (tools.isArray(otherParam)) { + for (i = 0, l = otherParam.length; i < l; i += 2) { + tmpParam[otherParam[i]] = otherParam[i + 1]; + } + } else { + for (var p in otherParam) { + tmpParam[p] = otherParam[p]; + } + } - for (var i = 0, l = parentNode[childKey].length; i < l; i++) { - if (parentNode[childKey][i].tId == node.tId) { - parentNode[childKey].splice(i, 1); - break; - } - } - view.setFirstNode(setting, parentNode); - view.setLastNode(setting, parentNode); + var _tmpV = data.getRoot(setting)._ver; + $.ajax({ + contentType: setting.async.contentType, + cache: false, + type: setting.async.type, + url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url), + data: setting.async.contentType.indexOf('application/json') > -1 ? JSON.stringify(tmpParam) : tmpParam, + dataType: setting.async.dataType, + headers: setting.async.headers, + xhrFields: setting.async.xhrFields, + success: function (msg) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + var newNodes = []; + try { + if (!msg || msg.length == 0) { + newNodes = []; + } else if (typeof msg == "string") { + newNodes = eval("(" + msg + ")"); + } else { + newNodes = msg; + } + } catch (err) { + newNodes = msg; + } - var tmp_ulObj,tmp_switchObj,tmp_icoObj, - childLength = parentNode[childKey].length; + if (node) { + node.isAjaxing = null; + node.zAsync = true; + } + view.setNodeLineIcos(setting, node); + if (newNodes && newNodes !== "") { + newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes); + view.addNodes(setting, node, -1, !!newNodes ? tools.clone(newNodes) : [], !!isSilent); + } else { + view.addNodes(setting, node, -1, [], !!isSilent); + } + setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]); + tools.apply(callback); + }, + error: function (XMLHttpRequest, textStatus, errorThrown) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + if (node) node.isAjaxing = null; + view.setNodeLineIcos(setting, node); + setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]); + } + }); + return true; + }, + cancelPreSelectedNode: function (setting, node, excludeNode) { + var list = data.getRoot(setting).curSelectedList, + i, n; + for (i = list.length - 1; i >= 0; i--) { + n = list[i]; + if (node === n || (!node && (!excludeNode || excludeNode !== n))) { + $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED); + if (node) { + data.removeSelectedNode(setting, node); + break; + } else { + list.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, n]); + } + } + } + }, + createNodeCallback: function (setting) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + while (root.createdNodes.length > 0) { + var node = root.createdNodes.shift(); + tools.apply(setting.view.addDiyDom, [setting.treeId, node]); + if (!!setting.callback.onNodeCreated) { + setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]); + } + } + } + }, + createNodes: function (setting, level, nodes, parentNode, index) { + if (!nodes || nodes.length == 0) return; + var root = data.getRoot(setting), + openFlag = !parentNode || parentNode.open || !!$$(data.nodeChildren(setting, parentNode)[0], setting).get(0); + root.createdNodes = []; + var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, index, true, openFlag), + parentObj, nextObj; - //repair nodes old parent - if (!setting.data.keep.parent && childLength == 0) { - //old parentNode has no child nodes - parentNode.isParent = false; - parentNode.open = false; - tmp_ulObj = $$(parentNode, consts.id.UL, setting); - tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting); - tmp_icoObj = $$(parentNode, consts.id.ICON, setting); - view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU); - view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU); - tmp_ulObj.css("display", "none"); + if (!parentNode) { + parentObj = setting.treeObj; + //setting.treeObj.append(zTreeHtml.join('')); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + if (ulObj.get(0)) { + parentObj = ulObj; + //ulObj.append(zTreeHtml.join('')); + } + } + if (parentObj) { + if (index >= 0) { + nextObj = parentObj.children()[index]; + } + if (index >= 0 && nextObj) { + $(nextObj).before(zTreeHtml.join('')); + } else { + parentObj.append(zTreeHtml.join('')); + } + } - } else if (setting.view.showLine && childLength > 0) { - //old parentNode has child nodes - var newLast = parentNode[childKey][childLength - 1]; - tmp_ulObj = $$(newLast, consts.id.UL, setting); - tmp_switchObj = $$(newLast, consts.id.SWITCH, setting); - tmp_icoObj = $$(newLast, consts.id.ICON, setting); - if (parentNode == root) { - if (parentNode[childKey].length == 1) { - //node was root, and ztree has only one root after move node - view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT); - } else { - var tmp_first_switchObj = $$(parentNode[childKey][0], consts.id.SWITCH, setting); - view.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS); - view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); - } - } else { - view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); - } - tmp_ulObj.removeClass(consts.line.LINE); - } - }, - replaceIcoClass: function(node, obj, newName) { - if (!obj || node.isAjaxing) return; - var tmpName = obj.attr("class"); - if (tmpName == undefined) return; - var tmpList = tmpName.split("_"); - switch (newName) { - case consts.folder.OPEN: - case consts.folder.CLOSE: - case consts.folder.DOCU: - tmpList[tmpList.length-1] = newName; - break; - } - obj.attr("class", tmpList.join("_")); - }, - replaceSwitchClass: function(node, obj, newName) { - if (!obj) return; - var tmpName = obj.attr("class"); - if (tmpName == undefined) return; - var tmpList = tmpName.split("_"); - switch (newName) { - case consts.line.ROOT: - case consts.line.ROOTS: - case consts.line.CENTER: - case consts.line.BOTTOM: - case consts.line.NOLINE: - tmpList[0] = view.makeNodeLineClassEx(node) + newName; - break; - case consts.folder.OPEN: - case consts.folder.CLOSE: - case consts.folder.DOCU: - tmpList[1] = newName; - break; - } - obj.attr("class", tmpList.join("_")); - if (newName !== consts.folder.DOCU) { - obj.removeAttr("disabled"); - } else { - obj.attr("disabled", "disabled"); - } - }, - selectNode: function(setting, node, addFlag) { - if (!addFlag) { - view.cancelPreSelectedNode(setting, null, node); - } - $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED); - data.addSelectedNode(setting, node); - setting.treeObj.trigger(consts.event.SELECTED, [event, setting.treeId, node]); - }, - setNodeFontCss: function(setting, treeNode) { - var aObj = $$(treeNode, consts.id.A, setting), - fontCss = view.makeNodeFontCss(setting, treeNode); - if (fontCss) { - aObj.css(fontCss); - } - }, - setNodeLineIcos: function(setting, node) { - if (!node) return; - var switchObj = $$(node, consts.id.SWITCH, setting), - ulObj = $$(node, consts.id.UL, setting), - icoObj = $$(node, consts.id.ICON, setting), - ulLine = view.makeUlLineClass(setting, node); - if (ulLine.length==0) { - ulObj.removeClass(consts.line.LINE); - } else { - ulObj.addClass(ulLine); - } - switchObj.attr("class", view.makeNodeLineClass(setting, node)); - if (node.isParent) { - switchObj.removeAttr("disabled"); - } else { - switchObj.attr("disabled", "disabled"); - } - icoObj.removeAttr("style"); - icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); - icoObj.attr("class", view.makeNodeIcoClass(setting, node)); - }, - setNodeName: function(setting, node) { - var title = data.getNodeTitle(setting, node), - nObj = $$(node, consts.id.SPAN, setting); - nObj.empty(); - if (setting.view.nameIsHTML) { - nObj.html(data.getNodeName(setting, node)); - } else { - nObj.text(data.getNodeName(setting, node)); - } - if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) { - var aObj = $$(node, consts.id.A, setting); - aObj.attr("title", !title ? "" : title); - } - }, - setNodeTarget: function(setting, node) { - var aObj = $$(node, consts.id.A, setting); - aObj.attr("target", view.makeNodeTarget(node)); - }, - setNodeUrl: function(setting, node) { - var aObj = $$(node, consts.id.A, setting), - url = view.makeNodeUrl(setting, node); - if (url == null || url.length == 0) { - aObj.removeAttr("href"); - } else { - aObj.attr("href", url); - } - }, - switchNode: function(setting, node) { - if (node.open || !tools.canAsync(setting, node)) { - view.expandCollapseNode(setting, node, !node.open); - } else if (setting.async.enable) { - if (!view.asyncNode(setting, node)) { - view.expandCollapseNode(setting, node, !node.open); - return; - } - } else if (node) { - view.expandCollapseNode(setting, node, !node.open); - } - } - }; - // zTree defind - $.fn.zTree = { - consts : _consts, - _z : { - tools: tools, - view: view, - event: event, - data: data - }, - getZTreeObj: function(treeId) { - var o = data.getZTreeTools(treeId); - return o ? o : null; - }, - destroy: function(treeId) { - if (!!treeId && treeId.length > 0) { - view.destroy(data.getSetting(treeId)); - } else { - for(var s in settings) { - view.destroy(settings[s]); - } - } - }, - init: function(obj, zSetting, zNodes) { - var setting = tools.clone(_setting); - $.extend(true, setting, zSetting); - setting.treeId = obj.attr("id"); - setting.treeObj = obj; - setting.treeObj.empty(); - settings[setting.treeId] = setting; - //For some older browser,(e.g., ie6) - if(typeof document.body.style.maxHeight === "undefined") { - setting.view.expandSpeed = ""; - } - data.initRoot(setting); - var root = data.getRoot(setting), - childKey = setting.data.key.children; - zNodes = zNodes ? tools.clone(tools.isArray(zNodes)? zNodes : [zNodes]) : []; - if (setting.data.simpleData.enable) { - root[childKey] = data.transformTozTreeFormat(setting, zNodes); - } else { - root[childKey] = zNodes; - } + view.createNodeCallback(setting); + }, + destroy: function (setting) { + if (!setting) return; + data.initCache(setting); + data.initRoot(setting); + event.unbindTree(setting); + event.unbindEvent(setting); + setting.treeObj.empty(); + delete settings[setting.treeId]; + }, + expandCollapseNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting); + var tmpCb, _callback; + if (!node) { + tools.apply(callback, []); + return; + } + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + if (root.expandTriggerFlag) { + _callback = callback; + tmpCb = function () { + if (_callback) _callback(); + if (node.open) { + setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]); + } else { + setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]); + } + }; + callback = tmpCb; + root.expandTriggerFlag = false; + } + if (!node.open && isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (children && children.length > 0 && !$$(children[0], setting).get(0)))) { + view.appendParentULDom(setting, node); + view.createNodeCallback(setting); + } + if (node.open == expandFlag) { + tools.apply(callback, []); + return; + } + var ulObj = $$(node, consts.id.UL, setting), + switchObj = $$(node, consts.id.SWITCH, setting), + icoObj = $$(node, consts.id.ICON, setting); - data.initCache(setting); - event.unbindTree(setting); - event.bindTree(setting); - event.unbindEvent(setting); - event.bindEvent(setting); + if (isParent) { + node.open = !node.open; + if (node.iconOpen && node.iconClose) { + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + } - var zTreeTools = { - setting : setting, - addNodes : function(parentNode, newNodes, isSilent) { - if (!newNodes) return null; - if (!parentNode) parentNode = null; - if (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null; - var xNewNodes = tools.clone(tools.isArray(newNodes)? newNodes: [newNodes]); - function addCallback() { - view.addNodes(setting, parentNode, xNewNodes, (isSilent==true)); - } + if (node.open) { + view.replaceSwitchClass(node, switchObj, consts.folder.OPEN); + view.replaceIcoClass(node, icoObj, consts.folder.OPEN); + if (animateFlag == false || setting.view.expandSpeed == "") { + ulObj.show(); + tools.apply(callback, []); + } else { + if (children && children.length > 0) { + ulObj.slideDown(setting.view.expandSpeed, callback); + } else { + ulObj.show(); + tools.apply(callback, []); + } + } + } else { + view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE); + view.replaceIcoClass(node, icoObj, consts.folder.CLOSE); + if (animateFlag == false || setting.view.expandSpeed == "" || !(children && children.length > 0)) { + ulObj.hide(); + tools.apply(callback, []); + } else { + ulObj.slideUp(setting.view.expandSpeed, callback); + } + } + } else { + tools.apply(callback, []); + } + }, + expandCollapseParentNode: function (setting, node, expandFlag, animateFlag, callback) { + if (!node) return; + if (!node.parentTId) { + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + return; + } else { + view.expandCollapseNode(setting, node, expandFlag, animateFlag); + } + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback); + } + }, + expandCollapseSonNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting), + treeNodes = (node) ? data.nodeChildren(setting, node) : data.nodeChildren(setting, root), + selfAnimateSign = (node) ? false : animateFlag, + expandTriggerFlag = data.getRoot(setting).expandTriggerFlag; + data.getRoot(setting).expandTriggerFlag = false; + if (treeNodes) { + for (var i = 0, l = treeNodes.length; i < l; i++) { + if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign); + } + } + data.getRoot(setting).expandTriggerFlag = expandTriggerFlag; + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + }, + isSelectedNode: function (setting, node) { + if (!node) { + return false; + } + var list = data.getRoot(setting).curSelectedList, + i; + for (i = list.length - 1; i >= 0; i--) { + if (node === list[i]) { + return true; + } + } + return false; + }, + makeDOMNodeIcon: function (html, setting, node) { + var nameStr = data.nodeName(setting, node), + name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g, '&').replace(//g, '>'); + html.push("", name, ""); + }, + makeDOMNodeLine: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeMainAfter: function (html, setting, node) { + html.push("
  • "); + }, + makeDOMNodeMainBefore: function (html, setting, node) { + html.push("
  • "); + }, + makeDOMNodeNameAfter: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeNameBefore: function (html, setting, node) { + var title = data.nodeTitle(setting, node), + url = view.makeNodeUrl(setting, node), + fontcss = view.makeNodeFontCss(setting, node), + nodeClasses = view.makeNodeClasses(setting, node), + fontStyle = []; + for (var f in fontcss) { + fontStyle.push(f, ":", fontcss[f], ";"); + } + html.push(" 0) ? " href='" + url + "'" : ""), " target='", view.makeNodeTarget(node), "' style='", fontStyle.join(''), + "'"); + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) { + html.push("title='", title.replace(/'/g, "'").replace(//g, '>'), "'"); + } + html.push(">"); + }, + makeNodeFontCss: function (setting, node) { + var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss); + return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {}; + }, + makeNodeClasses: function (setting, node) { + var classes = tools.apply(setting.view.nodeClasses, [setting.treeId, node], setting.view.nodeClasses); + return (classes && (typeof classes !== "function")) ? classes : { add: [], remove: [] }; + }, + makeNodeIcoClass: function (setting, node) { + var icoCss = ["ico"]; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0]; + if (isParent) { + icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + icoCss.push(consts.folder.DOCU); + } + } + return "x-icon b-font " + consts.className.ICON + " " + icoCss.join('_'); + }, + makeNodeIcoStyle: function (setting, node) { + var icoStyle = []; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + var icon = (isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node[setting.data.key.icon]; + if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;"); + if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) { + icoStyle.push("display:none;"); + } + } + return icoStyle.join(''); + }, + makeNodeLineClass: function (setting, node) { + var lineClass = []; + if (setting.view.showLine) { + if (node.level == 0 && node.isFirstNode && node.isLastNode) { + lineClass.push(consts.line.ROOT); + } else if (node.level == 0 && node.isFirstNode) { + lineClass.push(consts.line.ROOTS); + } else if (node.isLastNode) { + lineClass.push(consts.line.BOTTOM); + } else { + lineClass.push(consts.line.CENTER); + } + } else { + lineClass.push(consts.line.NOLINE); + } + if (data.nodeIsParent(setting, node)) { + lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + lineClass.push(consts.folder.DOCU); + } + return view.makeNodeLineClassEx(node) + lineClass.join('_'); + }, + makeNodeLineClassEx: function (node) { + return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " "; + }, + makeNodeTarget: function (node) { + return (node.target || "_blank"); + }, + makeNodeUrl: function (setting, node) { + var urlKey = setting.data.key.url; + return node[urlKey] ? node[urlKey] : null; + }, + makeUlHtml: function (setting, node, html, content) { + html.push("
      "); + html.push(content); + html.push("
    "); + }, + makeUlLineClass: function (setting, node) { + return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : ""); + }, + removeChildNodes: function (setting, node) { + if (!node) return; + var nodes = data.nodeChildren(setting, node); + if (!nodes) return; - if (tools.canAsync(setting, parentNode)) { - view.asyncNode(setting, parentNode, isSilent, addCallback); - } else { - addCallback(); - } - return xNewNodes; - }, - cancelSelectedNode : function(node) { - view.cancelPreSelectedNode(setting, node); - }, - destroy : function() { - view.destroy(setting); - }, - expandAll : function(expandFlag) { - expandFlag = !!expandFlag; - view.expandCollapseSonNode(setting, null, expandFlag, true); - return expandFlag; - }, - expandNode : function(node, expandFlag, sonSign, focus, callbackFlag) { - if (!node || !node.isParent) return null; - if (expandFlag !== true && expandFlag !== false) { - expandFlag = !node.open; - } - callbackFlag = !!callbackFlag; + for (var i = 0, l = nodes.length; i < l; i++) { + data.removeNodeCache(setting, nodes[i]); + } + data.removeSelectedNode(setting); + delete node[setting.data.key.children]; - if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) { - return null; - } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) { - return null; - } - if (expandFlag && node.parentTId) { - view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false); - } - if (expandFlag === node.open && !sonSign) { - return null; - } + if (!setting.data.keep.parent) { + data.nodeIsParent(setting, node, false); + node.open = false; + var tmp_switchObj = $$(node, consts.id.SWITCH, setting), + tmp_icoObj = $$(node, consts.id.ICON, setting); + view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU); + $$(node, consts.id.UL, setting).remove(); + } else { + $$(node, consts.id.UL, setting).empty(); + } + }, + scrollIntoView: function (setting, dom) { + if (!dom) { + return; + } + // support IE 7 / 8 + if (typeof Element === 'undefined' || typeof HTMLElement === 'undefined') { + var contRect = setting.treeObj.get(0).getBoundingClientRect(), + findMeRect = dom.getBoundingClientRect(); + if (findMeRect.top < contRect.top || findMeRect.bottom > contRect.bottom + || findMeRect.right > contRect.right || findMeRect.left < contRect.left) { + dom.scrollIntoView(); + } + return; + } + // CC-BY jocki84@googlemail.com, https://gist.github.com/jocki84/6ffafd003387179a988e + if (!Element.prototype.scrollIntoViewIfNeeded) { + Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { + "use strict"; - data.getRoot(setting).expandTriggerFlag = callbackFlag; - if (!tools.canAsync(setting, node) && sonSign) { - view.expandCollapseSonNode(setting, node, expandFlag, true, function() { - if (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}} - }); - } else { - node.open = !expandFlag; - view.switchNode(this.setting, node); - if (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}} - } - return expandFlag; - }, - getNodes : function() { - return data.getNodes(setting); - }, - getNodeByParam : function(key, value, parentNode) { - if (!key) return null; - return data.getNodeByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value); - }, - getNodeByTId : function(tId) { - return data.getNodeCache(setting, tId); - }, - getNodesByParam : function(key, value, parentNode) { - if (!key) return null; - return data.getNodesByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value); - }, - getNodesByParamFuzzy : function(key, value, parentNode) { - if (!key) return null; - return data.getNodesByParamFuzzy(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value); - }, - getNodesByFilter: function(filter, isSingle, parentNode, invokeParam) { - isSingle = !!isSingle; - if (!filter || (typeof filter != "function")) return (isSingle ? null : []); - return data.getNodesByFilter(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), filter, isSingle, invokeParam); - }, - getNodeIndex : function(node) { - if (!node) return null; - var childKey = setting.data.key.children, - parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); - for (var i=0, l = parentNode[childKey].length; i < l; i++) { - if (parentNode[childKey][i] == node) return i; - } - return -1; - }, - getSelectedNodes : function() { - var r = [], list = data.getRoot(setting).curSelectedList; - for (var i=0, l=list.length; i 0) { - view.createNodes(setting, 0, root[childKey]); - } else if (setting.async.enable && setting.async.url && setting.async.url !== '') { - view.asyncNode(setting); - } - return zTreeTools; - } - }; + function coverRange(inner, outer) { + if ( + false === centerIfNeeded || + (outer.start < inner.end && inner.start < outer.end) + ) { + return Math.max( + inner.end - outer.length, + Math.min(outer.start, inner.start) + ); + } + return (inner.start + inner.end - outer.length) / 2; + } - var zt = $.fn.zTree, - $$ = tools.$, - consts = zt.consts; -})(BI.jQuery); \ No newline at end of file + function makePoint(x, y) { + return { + "x": x, + "y": y, + "translate": function translate(dX, dY) { + return makePoint(x + dX, y + dY); + } + }; + } + + function absolute(elem, pt) { + while (elem) { + pt = pt.translate(elem.offsetLeft, elem.offsetTop); + elem = elem.offsetParent; + } + return pt; + } + + var target = absolute(this, makePoint(0, 0)), + extent = makePoint(this.offsetWidth, this.offsetHeight), + elem = this.parentNode, + origin; + + while (elem instanceof HTMLElement) { + // Apply desired scroll amount. + origin = absolute(elem, makePoint(elem.clientLeft, elem.clientTop)); + elem.scrollLeft = coverRange( + makeRange(target.x - origin.x, extent.x), + makeRange(elem.scrollLeft, elem.clientWidth) + ); + elem.scrollTop = coverRange( + makeRange(target.y - origin.y, extent.y), + makeRange(elem.scrollTop, elem.clientHeight) + ); + + // Determine actual scroll amount by reading back scroll properties. + target = target.translate(-elem.scrollLeft, -elem.scrollTop); + elem = elem.parentNode; + } + }; + } + dom.scrollIntoViewIfNeeded(); + }, + setFirstNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[0].isFirstNode = true; + } + }, + setLastNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[children.length - 1].isLastNode = true; + } + }, + removeNode: function (setting, node) { + var root = data.getRoot(setting), + parentNode = (node.parentTId) ? node.getParentNode() : root; + + node.isFirstNode = false; + node.isLastNode = false; + node.getPreNode = function () { + return null; + }; + node.getNextNode = function () { + return null; + }; + + if (!data.getNodeCache(setting, node.tId)) { + return; + } + + $$(node, setting).remove(); + data.removeNodeCache(setting, node); + data.removeSelectedNode(setting, node); + + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i].tId == node.tId) { + children.splice(i, 1); + break; + } + } + view.setFirstNode(setting, parentNode); + view.setLastNode(setting, parentNode); + + var tmp_ulObj, tmp_switchObj, tmp_icoObj, + childLength = children.length; + + //repair nodes old parent + if (!setting.data.keep.parent && childLength == 0) { + //old parentNode has no child nodes + data.nodeIsParent(setting, parentNode, false); + parentNode.open = false; + delete parentNode[setting.data.key.children]; + tmp_ulObj = $$(parentNode, consts.id.UL, setting); + tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting); + tmp_icoObj = $$(parentNode, consts.id.ICON, setting); + view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU); + tmp_ulObj.css("display", "none"); + + } else if (setting.view.showLine && childLength > 0) { + //old parentNode has child nodes + var newLast = children[childLength - 1]; + tmp_ulObj = $$(newLast, consts.id.UL, setting); + tmp_switchObj = $$(newLast, consts.id.SWITCH, setting); + tmp_icoObj = $$(newLast, consts.id.ICON, setting); + if (parentNode == root) { + if (children.length == 1) { + //node was root, and ztree has only one root after move node + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT); + } else { + var tmp_first_switchObj = $$(children[0], consts.id.SWITCH, setting); + view.replaceSwitchClass(children[0], tmp_first_switchObj, consts.line.ROOTS); + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + } else { + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + tmp_ulObj.removeClass(consts.line.LINE); + } + }, + replaceIcoClass: function (node, obj, newName) { + if (!obj || node.isAjaxing) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[tmpList.length - 1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + }, + replaceSwitchClass: function (node, obj, newName) { + if (!obj) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.line.ROOT: + case consts.line.ROOTS: + case consts.line.CENTER: + case consts.line.BOTTOM: + case consts.line.NOLINE: + tmpList[0] = view.makeNodeLineClassEx(node) + newName; + break; + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + if (newName !== consts.folder.DOCU) { + obj.removeAttr("disabled"); + } else { + obj.attr("disabled", "disabled"); + } + }, + selectNode: function (setting, node, addFlag) { + if (!addFlag) { + view.cancelPreSelectedNode(setting, null, node); + } + $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED); + data.addSelectedNode(setting, node); + setting.treeObj.trigger(consts.event.SELECTED, [setting.treeId, node]); + }, + setNodeFontCss: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + fontCss = view.makeNodeFontCss(setting, treeNode); + if (fontCss) { + aObj.css(fontCss); + } + }, + setNodeClasses: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + classes = view.makeNodeClasses(setting, treeNode); + if ('add' in classes && classes.add.length) { + aObj.addClass(classes.add.join(' ')); + } + if ('remove' in classes && classes.remove.length) { + aObj.removeClass(classes.remove.join(' ')); + } + }, + setNodeLineIcos: function (setting, node) { + if (!node) return; + var switchObj = $$(node, consts.id.SWITCH, setting), + ulObj = $$(node, consts.id.UL, setting), + icoObj = $$(node, consts.id.ICON, setting), + ulLine = view.makeUlLineClass(setting, node); + if (ulLine.length == 0) { + ulObj.removeClass(consts.line.LINE); + } else { + ulObj.addClass(ulLine); + } + switchObj.attr("class", view.makeNodeLineClass(setting, node)); + if (data.nodeIsParent(setting, node)) { + switchObj.removeAttr("disabled"); + } else { + switchObj.attr("disabled", "disabled"); + } + icoObj.removeAttr("style"); + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + icoObj.attr("class", view.makeNodeIcoClass(setting, node)); + }, + setNodeName: function (setting, node) { + var title = data.nodeTitle(setting, node), + nObj = $$(node, consts.id.SPAN, setting); + nObj.empty(); + if (setting.view.nameIsHTML) { + nObj.html(data.nodeName(setting, node)); + } else { + nObj.text(data.nodeName(setting, node)); + } + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("title", !title ? "" : title); + } + }, + setNodeTarget: function (setting, node) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("target", view.makeNodeTarget(node)); + }, + setNodeUrl: function (setting, node) { + var aObj = $$(node, consts.id.A, setting), + url = view.makeNodeUrl(setting, node); + if (url == null || url.length == 0) { + aObj.removeAttr("href"); + } else { + aObj.attr("href", url); + } + }, + switchNode: function (setting, node) { + if (node.open || !tools.canAsync(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + } else if (setting.async.enable) { + if (!view.asyncNode(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + return; + } + } else if (node) { + view.expandCollapseNode(setting, node, !node.open); + } + } + }; + // zTree defind + $.fn.zTree = { + consts: _consts, + _z: { + tools: tools, + view: view, + event: event, + data: data + }, + getZTreeObj: function (treeId) { + var o = data.getZTreeTools(treeId); + return o ? o : null; + }, + destroy: function (treeId) { + if (!!treeId && treeId.length > 0) { + view.destroy(data.getSetting(treeId)); + } else { + for (var s in settings) { + view.destroy(settings[s]); + } + } + }, + init: function (obj, zSetting, zNodes) { + var setting = tools.clone(_setting); + $.extend(true, setting, zSetting); + setting.treeId = obj.attr("id"); + setting.treeObj = obj; + setting.treeObj.empty(); + settings[setting.treeId] = setting; + //For some older browser,(e.g., ie6) + if (typeof document.body.style.maxHeight === "undefined") { + setting.view.expandSpeed = ""; + } + data.initRoot(setting); + var root = data.getRoot(setting); + zNodes = zNodes ? tools.clone(tools.isArray(zNodes) ? zNodes : [zNodes]) : []; + if (setting.data.simpleData.enable) { + data.nodeChildren(setting, root, data.transformTozTreeFormat(setting, zNodes)); + } else { + data.nodeChildren(setting, root, zNodes); + } + + data.initCache(setting); + event.unbindTree(setting); + event.bindTree(setting); + event.unbindEvent(setting); + event.bindEvent(setting); + + var zTreeTools = { + setting: setting, + addNodes: function (parentNode, index, newNodes, isSilent) { + if (!parentNode) parentNode = null; + var isParent = data.nodeIsParent(setting, parentNode); + if (parentNode && !isParent && setting.data.keep.leaf) return null; + + var i = parseInt(index, 10); + if (isNaN(i)) { + isSilent = !!newNodes; + newNodes = index; + index = -1; + } else { + index = i; + } + if (!newNodes) return null; + + + var xNewNodes = tools.clone(tools.isArray(newNodes) ? newNodes : [newNodes]); + + function addCallback() { + view.addNodes(setting, parentNode, index, xNewNodes, (isSilent == true)); + } + + if (tools.canAsync(setting, parentNode)) { + view.asyncNode(setting, parentNode, isSilent, addCallback); + } else { + addCallback(); + } + return xNewNodes; + }, + cancelSelectedNode: function (node) { + view.cancelPreSelectedNode(setting, node); + }, + destroy: function () { + view.destroy(setting); + }, + expandAll: function (expandFlag) { + expandFlag = !!expandFlag; + view.expandCollapseSonNode(setting, null, expandFlag, true); + return expandFlag; + }, + expandNode: function (node, expandFlag, sonSign, focus, callbackFlag) { + if (!node || !data.nodeIsParent(setting, node)) return null; + if (expandFlag !== true && expandFlag !== false) { + expandFlag = !node.open; + } + callbackFlag = !!callbackFlag; + + if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) { + return null; + } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) { + return null; + } + if (expandFlag && node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false); + } + if (expandFlag === node.open && !sonSign) { + return null; + } + + data.getRoot(setting).expandTriggerFlag = callbackFlag; + if (!tools.canAsync(setting, node) && sonSign) { + view.expandCollapseSonNode(setting, node, expandFlag, true, showNodeFocus); + } else { + node.open = !expandFlag; + view.switchNode(this.setting, node); + showNodeFocus(); + } + return expandFlag; + + function showNodeFocus() { + var a = $$(node, consts.id.A, setting).get(0); + if (a && focus !== false) { + view.scrollIntoView(setting, a); + } + } + }, + getNodes: function () { + return data.getNodes(setting); + }, + getNodeByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodeByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodeByTId: function (tId) { + return data.getNodeCache(setting, tId); + }, + getNodesByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByParamFuzzy: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParamFuzzy(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByFilter: function (filter, isSingle, parentNode, invokeParam) { + isSingle = !!isSingle; + if (!filter || (typeof filter != "function")) return (isSingle ? null : []); + return data.getNodesByFilter(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), filter, isSingle, invokeParam); + }, + getNodeIndex: function (node) { + if (!node) return null; + var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] == node) return i; + } + return -1; + }, + getSelectedNodes: function () { + var r = [], list = data.getRoot(setting).curSelectedList; + for (var i = 0, l = list.length; i < l; i++) { + r.push(list[i]); + } + return r; + }, + isSelectedNode: function (node) { + return data.isSelectedNode(setting, node); + }, + reAsyncChildNodesPromise: function (parentNode, reloadType, isSilent) { + var promise = new Promise(function (resolve, reject) { + try { + zTreeTools.reAsyncChildNodes(parentNode, reloadType, isSilent, function () { + resolve(parentNode); + }); + } catch (e) { + reject(e); + } + }); + return promise; + }, + reAsyncChildNodes: function (parentNode, reloadType, isSilent, callback) { + if (!this.setting.async.enable) return; + var isRoot = !parentNode; + if (isRoot) { + parentNode = data.getRoot(setting); + } + if (reloadType == "refresh") { + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children ? children.length : 0; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + data.removeSelectedNode(setting); + data.nodeChildren(setting, parentNode, []); + if (isRoot) { + this.setting.treeObj.empty(); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + ulObj.empty(); + } + } + view.asyncNode(this.setting, isRoot ? null : parentNode, !!isSilent, callback); + }, + refresh: function () { + this.setting.treeObj.empty(); + var root = data.getRoot(setting), + nodes = data.nodeChildren(setting, root); + data.initRoot(setting); + data.nodeChildren(setting, root, nodes); + data.initCache(setting); + view.createNodes(setting, 0, data.nodeChildren(setting, root), null, -1); + }, + removeChildNodes: function (node) { + if (!node) return null; + var nodes = data.nodeChildren(setting, node); + view.removeChildNodes(setting, node); + return nodes ? nodes : null; + }, + removeNode: function (node, callbackFlag) { + if (!node) return; + callbackFlag = !!callbackFlag; + if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return; + view.removeNode(setting, node); + if (callbackFlag) { + this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]); + } + }, + selectNode: function (node, addFlag, isSilent) { + if (!node) return; + if (tools.uCanDo(setting)) { + addFlag = setting.view.selectedMulti && addFlag; + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), true, false, showNodeFocus); + } else if (!isSilent) { + try { + $$(node, setting).focus().blur(); + } catch (e) { + } + } + view.selectNode(setting, node, addFlag); + } + + function showNodeFocus() { + if (isSilent) { + return; + } + var a = $$(node, setting).get(0); + view.scrollIntoView(setting, a); + } + }, + transformTozTreeNodes: function (simpleNodes) { + return data.transformTozTreeFormat(setting, simpleNodes); + }, + transformToArray: function (nodes) { + return data.transformToArrayFormat(setting, nodes); + }, + updateNode: function (node, checkTypeFlag) { + if (!node) return; + var nObj = $$(node, setting); + if (nObj.get(0) && tools.uCanDo(setting)) { + view.setNodeName(setting, node); + view.setNodeTarget(setting, node); + view.setNodeUrl(setting, node); + view.setNodeLineIcos(setting, node); + view.setNodeFontCss(setting, node); + view.setNodeClasses(setting, node); + } + } + }; + root.treeTools = zTreeTools; + data.setZTreeTools(setting, zTreeTools); + var children = data.nodeChildren(setting, root); + if (children && children.length > 0) { + view.createNodes(setting, 0, children, null, -1); + } else if (setting.async.enable && setting.async.url && setting.async.url !== '') { + view.asyncNode(setting); + } + return zTreeTools; + } + }; + + var zt = $.fn.zTree, + $$ = tools.$, + consts = zt.consts; +})(BI.jQuery); diff --git a/src/component/allvaluechooser/abstract.allvaluechooser.js b/src/component/allvaluechooser/abstract.allvaluechooser.js index 90cd4afd0..c13d8a30f 100644 --- a/src/component/allvaluechooser/abstract.allvaluechooser.js +++ b/src/component/allvaluechooser/abstract.allvaluechooser.js @@ -40,6 +40,18 @@ BI.AbstractAllValueChooser = BI.inherit(BI.Widget, { return text; }, + _getItemsByTimes: function (items, times) { + var res = []; + for (var i = (times - 1) * this._const.perPage; items[i] && i < times * this._const.perPage; i++) { + res.push(items[i]); + } + return res; + }, + + _hasNextByTimes: function (items, times) { + return times * this._const.perPage < items.length; + }, + _itemsCreator: function (options, callback) { var self = this, o = this.options; if (!o.cache || !this.items) { @@ -50,13 +62,14 @@ BI.AbstractAllValueChooser = BI.inherit(BI.Widget, { } else { call(this.items); } - function call (items) { + + function call(items) { var keywords = (options.keywords || []).slice(); if (options.keyword) { keywords.push(options.keyword); } var resultItems = items; - if(BI.isNotEmptyArray(keywords)) { + if (BI.isNotEmptyArray(keywords)) { resultItems = []; BI.each(keywords, function (i, kw) { var search = BI.Func.getSearchResult(items, kw); @@ -77,12 +90,12 @@ BI.AbstractAllValueChooser = BI.inherit(BI.Widget, { return; } if (options.type === BI.MultiSelectCombo.REQ_GET_DATA_LENGTH) { - callback({count: resultItems.length}); + callback({ count: resultItems.length }); return; } callback({ - items: resultItems, - hasNext: false + items: self._getItemsByTimes(resultItems, options.times), + hasNext: self._hasNextByTimes(resultItems, options.times) }); } }, @@ -101,4 +114,4 @@ BI.AbstractAllValueChooser = BI.inherit(BI.Widget, { } return value; }, -}); \ No newline at end of file +}); diff --git a/src/component/allvaluechooser/pane.allvaluechooser.js b/src/component/allvaluechooser/pane.allvaluechooser.js index 93ad36cba..6188f14ee 100644 --- a/src/component/allvaluechooser/pane.allvaluechooser.js +++ b/src/component/allvaluechooser/pane.allvaluechooser.js @@ -50,10 +50,11 @@ BI.AllValueChooserPane = BI.inherit(BI.AbstractAllValueChooser, { getValue: function () { var val = this.list.getValue() || {}; - if (val.type === BI.Selection.All) { - return val.assist; + if (val.type === BI.Selection.Multi) { + return val.value || []; } - return val.value || []; + + return BI.difference(BI.map(this.items, "value"), val.value || []); }, populate: function (items) { diff --git a/src/component/form/form.field.js b/src/component/form/form.field.js index e6c11a924..0b67041b8 100644 --- a/src/component/form/form.field.js +++ b/src/component/form/form.field.js @@ -9,6 +9,7 @@ baseCls: "bi-form-field", label: "", el: {}, + headerCls: "", labelAlign: "right", // 文字默认右对齐 validate: function () { return true; @@ -69,6 +70,7 @@ textAlign: o.labelAlign, text: o.label, width: o.labelWidth, + cls: o.headerCls, rgap: 20 // 表单文字与右侧输入间距均为20px } }, field] : [field] diff --git a/src/component/form/form.js b/src/component/form/form.js index 27734455f..de8caeaea 100644 --- a/src/component/form/form.js +++ b/src/component/form/form.js @@ -18,7 +18,8 @@ label: "", el: {} }], - labelWidth: "" + labelWidth: "", + headerCls: "", // 左侧文字样式 }, render: function () { @@ -44,6 +45,7 @@ height: item.el.height || 28, labelAlign: o.labelAlign, labelWidth: o.labelWidth, + headerCls: o.headerCls, el: item.el, label: item.label, tip: item.tip, diff --git a/src/core/1.lodash.js b/src/core/1.lodash.js index cab97c0d2..8be57fe24 100644 --- a/src/core/1.lodash.js +++ b/src/core/1.lodash.js @@ -10253,7 +10253,7 @@ // loaded by a script tag in the presence of an AMD loader. // See http://requirejs.org/docs/errors.html#mismatch for more details. // Use `_.noConflict` to remove Lodash from the global object. - root._ = lodash; + BI._ = lodash; // Define as an anonymous module so, through path mapping, it can be // referenced as the "underscore" module. @@ -10270,6 +10270,6 @@ } else { // Export to the global object. - root._ = lodash; + BI._ = lodash; } }.call(this)); diff --git a/src/core/2.base.js b/src/core/2.base.js index ba2d9ec77..7071eb3e1 100644 --- a/src/core/2.base.js +++ b/src/core/2.base.js @@ -11,19 +11,19 @@ }; var _apply = function (name) { return function () { - return _[name].apply(_, arguments); + return BI._[name].apply(BI._, arguments); }; }; var _applyFunc = function (name) { return function () { var args = Array.prototype.slice.call(arguments, 0); - args[1] = _.isFunction(args[1]) ? traverse(args[1], args[2]) : args[1]; - return _[name].apply(_, args); + args[1] = BI._.isFunction(args[1]) ? traverse(args[1], args[2]) : args[1]; + return BI._[name].apply(BI._, args); }; }; // Utility - _.extend(BI, { + BI._.extend(BI, { assert: function (v, is) { if (this.isFunction(is)) { if (!is(v)) { @@ -146,10 +146,10 @@ }); // 集合相关方法 - _.each(["where", "findWhere", "invoke", "pluck", "shuffle", "sample", "toArray", "size"], function (name) { + BI._.each(["where", "findWhere", "invoke", "pluck", "shuffle", "sample", "toArray", "size"], function (name) { BI[name] = _apply(name); }); - _.each(["get", "set", "each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min", + BI._.each(["get", "set", "each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min", "sortBy", "groupBy", "indexBy", "countBy", "partition", "clamp"], function (name) { if (name === "any") { BI[name] = _applyFunc("some"); @@ -157,7 +157,7 @@ BI[name] = _applyFunc(name); } }); - _.extend(BI, { + BI._.extend(BI, { // 数数 count: function (from, to, predicate) { var t; @@ -217,10 +217,10 @@ }).join(""); } if (BI.isArray(obj1)) { - return _.concat.apply([], arguments); + return BI._.concat.apply([], arguments); } if (BI.isObject(obj1)) { - return _.extend.apply({}, arguments); + return BI._.extend.apply({}, arguments); } }, @@ -254,7 +254,7 @@ backFindKey: function (obj, predicate, context) { predicate = BI.iteratee(predicate, context); - var keys = _.keys(obj), key; + var keys = BI._.keys(obj), key; for (var i = keys.length - 1; i >= 0; i--) { key = keys[i]; if (predicate(obj[key], key, obj)) { @@ -347,14 +347,14 @@ }); // 数组相关的方法 - _.each(["first", "initial", "last", "rest", "compact", "flatten", "without", "union", "intersection", + BI._.each(["first", "initial", "last", "rest", "compact", "flatten", "without", "union", "intersection", "difference", "zip", "unzip", "object", "indexOf", "lastIndexOf", "sortedIndex", "range", "take", "takeRight", "uniqBy"], function (name) { BI[name] = _apply(name); }); - _.each(["findIndex", "findLastIndex"], function (name) { + BI._.each(["findIndex", "findLastIndex"], function (name) { BI[name] = _applyFunc(name); }); - _.extend(BI, { + BI._.extend(BI, { // 构建一个长度为length的数组 makeArray: function (length, value) { var res = []; @@ -401,27 +401,27 @@ if (array == null) { return []; } - if (!_.isBoolean(isSorted)) { + if (!BI._.isBoolean(isSorted)) { context = iteratee; iteratee = isSorted; isSorted = false; } iteratee && (iteratee = traverse(iteratee, context)); - return _.uniq.call(_, array, isSorted, iteratee, context); + return BI._.uniq.call(BI._, array, isSorted, iteratee, context); } }); // 对象相关方法 - _.each(["keys", "allKeys", "values", "pairs", "invert", "create", "functions", "extend", "extendOwn", + BI._.each(["keys", "allKeys", "values", "pairs", "invert", "create", "functions", "extend", "extendOwn", "defaults", "clone", "property", "propertyOf", "matcher", "isEqual", "isMatch", "isEmpty", "isElement", "isNumber", "isString", "isArray", "isObject", "isPlainObject", "isArguments", "isFunction", "isFinite", "isBoolean", "isDate", "isRegExp", "isError", "isNaN", "isUndefined", "zipObject", "cloneDeep"], function (name) { BI[name] = _apply(name); }); - _.each(["mapObject", "findKey", "pick", "omit", "tap"], function (name) { + BI._.each(["mapObject", "findKey", "pick", "omit", "tap"], function (name) { BI[name] = _applyFunc(name); }); - _.extend(BI, { + BI._.extend(BI, { inherit: function (sp, overrides) { var sb = function () { @@ -432,7 +432,7 @@ F.prototype = spp; sb.prototype = new F(); sb.superclass = spp; - _.extend(sb.prototype, overrides, { + BI._.extend(sb.prototype, overrides, { superclass: sp }); return sb; @@ -455,10 +455,10 @@ return false; } return BI.every(keys, function (i, key) { - return _.has(obj, key); + return BI._.has(obj, key); }); } - return _.has.apply(_, arguments); + return BI._.has.apply(BI._, arguments); }, freeze: function (value) { @@ -524,13 +524,17 @@ isWindow: function (obj) { return obj != null && obj == obj.window; + }, + + isPromise: function(obj) { + return !!obj && (BI.isObject(obj) || BI.isFunction(obj)) && BI.isFunction(obj.then); } }); // deep方法 - _.extend(BI, { - deepClone: _.cloneDeep, - deepExtend: _.merge, + BI._.extend(BI, { + deepClone: BI._.cloneDeep, + deepExtend: BI._.merge, isDeepMatch: function (object, attrs) { var keys = BI.keys(attrs), length = keys.length; @@ -548,8 +552,8 @@ }, contains: function (obj, target, fromIndex) { - if (!_.isArrayLike(obj)) obj = _.values(obj); - return _.indexOf(obj, target, typeof fromIndex === "number" && fromIndex) >= 0; + if (!BI._.isArrayLike(obj)) obj = BI._.values(obj); + return BI._.indexOf(obj, target, typeof fromIndex === "number" && fromIndex) >= 0; }, deepContains: function (obj, copy) { @@ -647,20 +651,20 @@ }); // 通用方法 - _.each(["uniqueId", "result", "chain", "iteratee", "escape", "unescape", "before", "after"], function (name) { + BI._.each(["uniqueId", "result", "chain", "iteratee", "escape", "unescape", "before", "after"], function (name) { BI[name] = function () { - return _[name].apply(_, arguments); + return BI._[name].apply(BI._, arguments); }; }); // 事件相关方法 - _.each(["bind", "once", "partial", "debounce", "throttle", "delay", "defer", "wrap"], function (name) { + BI._.each(["bind", "once", "partial", "debounce", "throttle", "delay", "defer", "wrap"], function (name) { BI[name] = function () { - return _[name].apply(_, arguments); + return BI._[name].apply(BI._, arguments); }; }); - _.extend(BI, { + BI._.extend(BI, { nextTick: (function () { var callbacks = []; var pending = false; @@ -731,10 +735,10 @@ }); // 数字相关方法 - _.each(["random"], function (name) { + BI._.each(["random"], function (name) { BI[name] = _apply(name); }); - _.extend(BI, { + BI._.extend(BI, { parseInt: function (number) { var radix = 10; @@ -837,9 +841,9 @@ }); // 字符串相关方法 - _.extend(BI, { + BI._.extend(BI, { trim: function () { - return _.trim.apply(_, arguments); + return BI._.trim.apply(BI._, arguments); }, toUpperCase: function (string) { @@ -965,7 +969,7 @@ }); // 日期相关方法 - _.extend(BI, { + BI._.extend(BI, { /** * 是否是闰年 * @param year diff --git a/src/core/3.ob.js b/src/core/3.ob.js index 2c21a11fb..9cf8fd3f9 100644 --- a/src/core/3.ob.js +++ b/src/core/3.ob.js @@ -1,5 +1,5 @@ !(function () { - function extend () { + function extend() { var target = arguments[0] || {}, length = arguments.length, i = 1, options, name, src, copy; for (; i < length; i++) { // Only deal with non-null/undefined values @@ -31,7 +31,7 @@ var OB = function (config) { this._constructor(config); }; - _.extend(OB.prototype, { + BI._.extend(OB.prototype, { props: {}, init: null, destroyed: null, @@ -66,12 +66,12 @@ _initListeners: function () { var self = this; if (this.options.listeners != null) { - _.each(this.options.listeners, function (lis, eventName) { - if (_.isFunction(lis)) { + BI._.each(this.options.listeners, function (lis, eventName) { + if (BI._.isFunction(lis)) { self.on(eventName, lis); return; } - (lis.target ? lis.target : self)[lis.once ? "once" : "on"](lis.eventName, _.bind(lis.action, self)); + (lis.target ? lis.target : self)[lis.once ? "once" : "on"](lis.eventName, BI._.bind(lis.action, self)); }); delete this.options.listeners; } @@ -90,17 +90,17 @@ //释放当前对象 _purgeRef: function () { if (this.options.__ref) { - this.options.__ref.call(null); + this.options.__ref.call(null, null); this.options.__ref = null; } if (this.options.ref) { - this.options.ref.call(null); + this.options.ref.call(null, null); this.options.ref = null; } }, _getEvents: function () { - if (!_.isObject(this.events)) { + if (!BI._.isObject(this.events)) { this.events = {}; } return this.events; @@ -115,7 +115,7 @@ var self = this; eventName = eventName.toLowerCase(); var fns = this._getEvents()[eventName]; - if (!_.isArray(fns)) { + if (!BI._.isArray(fns)) { fns = []; this._getEvents()[eventName] = fns; } @@ -151,9 +151,9 @@ delete this._getEvents()[eventName]; } else { var fns = this._getEvents()[eventName]; - if (_.isArray(fns)) { + if (BI._.isArray(fns)) { var newFns = []; - _.each(fns, function (ifn) { + BI._.each(fns, function (ifn) { if (ifn != fn) { newFns.push(ifn); } diff --git a/src/core/4.widget.js b/src/core/4.widget.js index 861fce38f..ef412cafd 100644 --- a/src/core/4.widget.js +++ b/src/core/4.widget.js @@ -17,7 +17,7 @@ var requestAnimationFrame = _global.requestAnimationFrame || _global.webkitRequestAnimationFrame || _global.mozRequestAnimationFrame || _global.oRequestAnimationFrame || _global.msRequestAnimationFrame || _global.setTimeout; - function callLifeHook (self, life) { + function callLifeHook(self, life) { var hooks = [], hook; hook = self[life]; if (hook) { @@ -124,7 +124,7 @@ var initCallbackCalled = false; var renderCallbackCalled = false; - function init () { + function init() { // 加个保险 if (initCallbackCalled === true) { _global.console && console.error("组件: 请检查beforeInit内部的写法,callback只能执行一次"); @@ -132,7 +132,7 @@ } initCallbackCalled = true; - function render () { + function render() { // 加个保险 if (renderCallbackCalled === true) { _global.console && console.error("组件: 请检查beforeRender内部的写法,callback只能执行一次"); @@ -246,8 +246,8 @@ return getter.call(self, self); }, (handler && function (v) { handler.call(self, self, v); - }) || BI.emptyFn, BI.extend({deep: true}, options)); - this._watchers.push(function unwatchFn () { + }) || BI.emptyFn, BI.extend({ deep: true }, options)); + this._watchers.push(function unwatchFn() { watcher.teardown(); }); return watcher.value; @@ -346,6 +346,7 @@ _initState: function () { this._isMounted = false; + this._isDestroyed = false; }, __initWatch: function () { @@ -449,6 +450,10 @@ return this._isMounted; }, + isDestroyed: function () { + return this._isDestroyed; + }, + setWidth: function (w) { this.options.width = w; this._initElementWidth(); @@ -681,11 +686,11 @@ }, isEnabled: function () { - return this.options.disabled === true ? false: !this.options._disabled; + return this.options.disabled === true ? false : !this.options._disabled; }, isValid: function () { - return this.options.invalid === true ? false: !this.options._invalid; + return this.options.invalid === true ? false : !this.options._invalid; }, isVisible: function () { @@ -732,6 +737,9 @@ this._isMounted = false; callLifeHook(this, "destroyed"); this.destroyed = null; + this._isDestroyed = true; + // this._purgeRef(); // 清除ref的时机还是要仔细考虑一下 + }, _unMount: function () { @@ -825,12 +833,12 @@ BI.Widget.context = context = contextStack.pop(); }; - function pushTarget (_current) { + function pushTarget(_current) { if (current) currentStack.push(current); BI.Widget.current = current = _current; } - function popTarget () { + function popTarget() { BI.Widget.current = current = currentStack.pop(); } diff --git a/src/core/5.inject.js b/src/core/5.inject.js index 3cb1d15bf..9e0ae8503 100644 --- a/src/core/5.inject.js +++ b/src/core/5.inject.js @@ -10,27 +10,29 @@ BI.module = BI.module || function (xtype, cls) { if (moduleInjection[xtype] != null) { _global.console && console.error("module: [" + xtype + "] 已经注册过了"); - } - if (BI.isFunction(cls)) { - cls = cls(); - } - for (var k in moduleInjectionMap) { - if (cls[k]) { - for (var key in cls[k]) { - if (!moduleInjectionMap[k]) { - continue; - } - if (!moduleInjectionMap[k][key]) { - moduleInjectionMap[k][key] = []; + } else { + if (BI.isFunction(cls)) { + cls = cls(); + } + for (var k in moduleInjectionMap) { + if (cls[k]) { + for (var key in cls[k]) { + if (!moduleInjectionMap[k]) { + continue; + } + if (!moduleInjectionMap[k][key]) { + moduleInjectionMap[k][key] = []; + } + moduleInjectionMap[k][key].push({ + version: cls[k][key], + moduleId: xtype + }); } - moduleInjectionMap[k][key].push({ - version: cls[k][key], - moduleId: xtype - }); } } + moduleInjection[xtype] = cls; } - moduleInjection[xtype] = cls; + return function () { return BI.Modules.getModule(xtype); }; @@ -40,8 +42,10 @@ BI.constant = BI.constant || function (xtype, cls) { if (constantInjection[xtype] != null) { _global.console && console.error("constant: [" + xtype + "]已经注册过了"); + } else { + constantInjection[xtype] = cls; } - constantInjection[xtype] = cls; + return function () { return BI.Constants.getConstant(xtype); }; @@ -51,8 +55,10 @@ BI.model = BI.model || function (xtype, cls) { if (modelInjection[xtype] != null) { _global.console && console.error("model: [" + xtype + "] 已经注册过了"); + } else { + modelInjection[xtype] = cls; } - modelInjection[xtype] = cls; + return function (config) { return BI.Models.getModel(xtype, config); }; @@ -62,8 +68,10 @@ BI.store = BI.store || function (xtype, cls) { if (storeInjection[xtype] != null) { _global.console && console.error("store: [" + xtype + "] 已经注册过了"); + } else { + storeInjection[xtype] = cls; } - storeInjection[xtype] = cls; + return function (config) { return BI.Stores.getStore(xtype, config); }; @@ -74,7 +82,9 @@ if (serviceInjection[xtype] != null) { _global.console && console.error("service: [" + xtype + "] 已经注册过了"); } + serviceInjection[xtype] = cls; + return function (config) { return BI.Services.getService(xtype, config); }; @@ -84,20 +94,33 @@ BI.provider = BI.provider || function (xtype, cls) { if (providerInjection[xtype] != null) { _global.console && console.error("provider: [" + xtype + "] 已经注册过了"); + } else { + providerInjection[xtype] = cls; } - providerInjection[xtype] = cls; + return function (config) { return BI.Providers.getProvider(xtype, config); }; }; var configFunctions = BI.OB.configFunctions = {}; - var runConfigFunction = function (type) { + var runConfigFunction = function (type, configFn) { if (!type || !configFunctions[type]) { return false; } - var queue = configFunctions[type]; - delete configFunctions[type]; + + var queue = []; + if (configFn) { + queue = configFunctions[type].filter(function (conf) { + return conf.fn === configFn; + }); + configFunctions[type] = configFunctions[type].filter(function (conf) { + return conf.fn !== configFn; + }); + } else { + queue = configFunctions[type]; + delete configFunctions[type]; + } var dependencies = BI.Providers.getProvider("bi.provider.system").getDependencies(); var modules = moduleInjectionMap.components[type] @@ -176,6 +199,10 @@ fn: configFn, opt: opt }); + + if (opt.immediately) { + return runConfigFunction(type, configFn); + } }; BI.getReference = BI.getReference || function (type, fn) { diff --git a/src/core/conflict.js b/src/core/conflict.js new file mode 100644 index 000000000..dba9b8b6f --- /dev/null +++ b/src/core/conflict.js @@ -0,0 +1,7 @@ + +if (!_global.$ && !_global.jQuery) { + _global.jQuery = _global.$ = BI.jQuery; +} +if (!_global._) { + _global._ = BI._; +} diff --git a/src/core/constant/events.js b/src/core/constant/events.js index 2faa2593b..76eb97021 100644 --- a/src/core/constant/events.js +++ b/src/core/constant/events.js @@ -2,7 +2,7 @@ * 事件集合 * @class BI.Events */ -_.extend(BI, { +BI._.extend(BI, { Events: { /** @@ -143,6 +143,12 @@ _.extend(BI, { */ COLLAPSE: "_COLLAPSE", + /** + * @static + * @property 下拉菜单切换展开收起事件 + */ + TOGGLE: "_TOGGLE", + /** * @static * @property 回调事件 @@ -435,4 +441,4 @@ _.extend(BI, { */ AEMAIL: "afteremail" } -}); \ No newline at end of file +}); diff --git a/src/core/constant/var.js b/src/core/constant/var.js index cc767737b..ac5755e45 100644 --- a/src/core/constant/var.js +++ b/src/core/constant/var.js @@ -2,7 +2,7 @@ * 常量 */ -_.extend(BI, { +BI._.extend(BI, { MAX: 0xfffffffffffffff, MIN: -0xfffffffffffffff, EVENT_RESPONSE_TIME: 200, diff --git a/src/core/controller/controller.tooltips.js b/src/core/controller/controller.tooltips.js index 5e4db152b..2e126b424 100644 --- a/src/core/controller/controller.tooltips.js +++ b/src/core/controller/controller.tooltips.js @@ -12,17 +12,25 @@ BI.TooltipsController = BI.inherit(BI.Controller, { this.showingTips = {};// 存储正在显示的tooltip }, - _createTooltip: function (text, level) { + /** + * + * @param opt + * @param opt.text {String} 文本 + * @param opt.level {String} 级别, success或warning + * @param opt.textAlign {String} 文本对齐方式, left, center, right + * @returns {*} + * @private + */ + _createTooltip: function (opt) { return BI.createWidget({ type: "bi.tooltip", - text: text, - level: level, + ...opt, stopEvent: true }); }, // opt: {container: '', belowMouse: false} - show: function (e, name, text, level, context, opt) { + show: function (e, name, tooltipOpt, context, opt) { opt || (opt = {}); var self = this; BI.each(this.showingTips, function (i, tip) { @@ -30,7 +38,7 @@ BI.TooltipsController = BI.inherit(BI.Controller, { }); this.showingTips = {}; if (!this.has(name)) { - this.create(name, text, level, opt.container || "body"); + this.create(name, tooltipOpt, opt.container || "body"); } if (!opt.belowMouse) { var offset = context.element.offset(); @@ -41,7 +49,6 @@ BI.TooltipsController = BI.inherit(BI.Controller, { var top = offset.top + bounds.height + 5; } var tooltip = this.get(name); - tooltip.setText(text); tooltip.element.css({ left: "0px", top: "0px" @@ -84,9 +91,9 @@ BI.TooltipsController = BI.inherit(BI.Controller, { return this; }, - create: function (name, text, level, context) { + create: function (name, tooltipOpt, context) { if (!this.has(name)) { - var tooltip = this._createTooltip(text, level); + var tooltip = this._createTooltip(tooltipOpt); this.add(name, tooltip); BI.createWidget({ type: "bi.absolute", diff --git a/src/core/element/element.js b/src/core/element/element.js new file mode 100644 index 000000000..7bf1c9d4a --- /dev/null +++ b/src/core/element/element.js @@ -0,0 +1,74 @@ +import { registFunction } from './plugins'; + +export function Element(widget, attribs) { + this.l = this.r = this.t = this.b = 0; // 边框 + this.marginLeft = this.marginRight = this.marginTop = this.marginBottom = 0; //间距 + this.position = {}; + this.classMap = {}; + this.classList = []; + this.children = []; + this.attribs = attribs || {}; + this.styles = {}; + // 兼容处理 + this['0'] = this; + this.style = {}; + if (!widget) { + this.nodeName = 'body'; + this.position.x = 0; + this.position.y = 0; + this.attribs.id = 'body'; + } else if (BI.isWidget(widget)) { + this.widget = widget; + this.nodeName = widget.options.tagName; + this.textBaseLine = widget.options.textBaseLine; + } else if (BI.isString(widget)) { + this.nodeName = widget; + } +} + +initElement(Element); +registFunction(Element); + +function initElement(element) { + element.prototype = { + appendChild(child) { + child.parent = this; + if (this.children.push(child) !== 1) { + var sibling = this.children[this.children.length - 2]; + sibling.next = child; + child.prev = sibling; + child.next = null; + } + }, + append(child) { + child.parent = this; + if (this.children.push(child) !== 1) { + var sibling = this.children[this.children.length - 2]; + sibling.next = child; + child.prev = sibling; + child.next = null; + } + }, + getParent() { + return this.parent; + }, + getSiblings() { + var parent = this.getParent(); + return parent ? parent.getChildren() : [this]; + }, + getChildren() { + return this.children; + }, + + getBounds() { + return {}; + }, + + width() { + + }, + height() { + + } + }; +} diff --git a/src/core/element/index.js b/src/core/element/index.js new file mode 100644 index 000000000..bbc4eb926 --- /dev/null +++ b/src/core/element/index.js @@ -0,0 +1,31 @@ +import { Element } from './element'; + +BI.Element = Element; +BI.Element.renderEngine = { + createElement: (widget) => { + // eslint-disable-next-line no-undef + if (BI.isWidget(widget)) { + var o = widget.options; + if (o.element instanceof Element) { + return o.element; + } + if (typeof o.element === 'string' && o.element !== 'body') { + o.root = false; + return new Element(widget); + } + + if (o.root === true) { + return new Element(); + } + } + // eslint-disable-next-line no-undef + if (BI.isString(widget)) { + return new Element(widget); + } + return new Element(widget); + }, + + createFragment() { + return new Element(); + } +} diff --git a/src/core/element/plugins/attr.js b/src/core/element/plugins/attr.js new file mode 100644 index 000000000..3ae918f29 --- /dev/null +++ b/src/core/element/plugins/attr.js @@ -0,0 +1,22 @@ +export const registAttrFun = (Element) => { + Element.registerFunction('attr', function (key, value) { + var self = this; + if (BI.isObject(key)) { + BI.each(key, (k, v) => { + self.attr(k, v); + }); + return this; + } + if (BI.isNull(value)) { + return this.attribs[key]; + } + this.attribs[key] = value; + return this; + }); + Element.registerFunction('hasAttrib', function (key) { + return this.attribs[key] != null; + }); + Element.registerFunction('removeAttr', function (key) { + delete this.attribs[key]; + }); +}; diff --git a/src/core/element/plugins/class.js b/src/core/element/plugins/class.js new file mode 100644 index 000000000..ce46e6864 --- /dev/null +++ b/src/core/element/plugins/class.js @@ -0,0 +1,23 @@ +export const registClassFun = (Element) => { + Element.registerFunction('addClass', function (classList) { + var self = this; + BI.each(classList.split(' '), (i, cls) => { + if (cls && !self.classMap[cls]) { + self.classList.push(cls); + } + cls && (self.classMap[cls] = true); + }); + return this; + }); + + Element.registerFunction('removeClass', function (classList) { + var self = this; + BI.each(classList.split(' '), (i, cls) => { + if (cls && self.classMap[cls]) { + delete self.classMap[cls]; + self.classList.splice(self.classList.indexOf(cls), 1); + } + }); + return this; + }); +}; diff --git a/src/core/element/plugins/css.js b/src/core/element/plugins/css.js new file mode 100644 index 000000000..e1826a155 --- /dev/null +++ b/src/core/element/plugins/css.js @@ -0,0 +1,22 @@ +export const registCssFun = (Element) => { + Element.registerFunction('css', function (key, value) { + var self = this; + if (BI.isObject(key)) { + BI.each(key, (k, v) => { + self.css(k, v); + }); + return this; + } + key = BI.trim(BI.camelize(key)); + return css(this, key, value); + }); +}; + +const css = (elem, key, value) => { + key = BI.trim(BI.camelize(key)); + if (BI.isNull(value)) { + return elem.styles[key]; + } + elem.styles[key] = value; + return elem; +}; diff --git a/src/core/element/plugins/data.js b/src/core/element/plugins/data.js new file mode 100644 index 000000000..e141c96c3 --- /dev/null +++ b/src/core/element/plugins/data.js @@ -0,0 +1,12 @@ +export const registDataFun = (Element) => { + Element.registerFunction('data', function (key, value) { + if (!this._data) { + this._data = {}; + } + if (BI.isNull(value)) { + return this._data[key]; + } + this._data[key] = value; + return this; + }); +}; diff --git a/src/core/element/plugins/empty.js b/src/core/element/plugins/empty.js new file mode 100644 index 000000000..dbe5e0c1d --- /dev/null +++ b/src/core/element/plugins/empty.js @@ -0,0 +1,9 @@ +export const registEmptyFun = (Element) => { + Element.registerFunction('empty', function (text) { + this.children = []; + return this; + }); + Element.registerFunction('destroy', function (text) { + return this; + }); +}; diff --git a/src/core/element/plugins/event.js b/src/core/element/plugins/event.js new file mode 100644 index 000000000..38004ed88 --- /dev/null +++ b/src/core/element/plugins/event.js @@ -0,0 +1,32 @@ +var returnThis = function () { + return this; +}; +export const registEventFun = (Element) => { + [ + 'mousedown', + 'mouseup', + 'mousewheel', + 'keydown', + 'keyup', + 'focus', + 'focusin', + 'focusout', + 'click', + 'on', + 'off', + 'bind', + 'unbind', + 'trigger', + 'hover', + 'scroll', + 'scrollLeft', + 'scrollTop', + 'resize', + 'show', + 'hide', + 'dblclick', + 'blur', + ].forEach((event) => { + Element.registerFunction(event, returnThis); + }); +}; diff --git a/src/core/element/plugins/html.js b/src/core/element/plugins/html.js new file mode 100644 index 000000000..b115f9388 --- /dev/null +++ b/src/core/element/plugins/html.js @@ -0,0 +1,15 @@ +export const registHtmlFun = (Element) => { + Element.registerFunction('html', function (text) { + if (text && text.charAt(0) === '<') { + BI.createWidget({ + type: 'bi.html', + element: this.widget, + html: text, + }); + this.originalHtml = text; + } else { + this.text = BI.htmlDecode(text); + } + return this; + }); +}; diff --git a/src/core/element/plugins/index.js b/src/core/element/plugins/index.js new file mode 100644 index 000000000..c32aab4dc --- /dev/null +++ b/src/core/element/plugins/index.js @@ -0,0 +1,31 @@ +import { registAttrFun } from './attr'; +import { registClassFun } from './class'; +import { registCssFun } from './css'; +import { registDataFun } from './data'; +import { registEmptyFun } from './empty'; +import { registEventFun } from './event'; +import { registHtmlFun } from './html'; +import { registKeywordMarkFun } from './keywordMark'; +import { registRenderToHtmlFun } from './renderToHtml'; +import { registRenderToStringFun } from './renderToString'; +import { registTextFun } from './text'; +import { registValFun } from './val'; + +export const registFunction = (Element) => { + var functionMap = {}; + Element.registerFunction = (key, fn) => { + Element.prototype[key] = functionMap[key] = fn; + }; + registAttrFun(Element); + registClassFun(Element); + registCssFun(Element); + registDataFun(Element); + registEmptyFun(Element); + registEventFun(Element); + registHtmlFun(Element); + registKeywordMarkFun(Element); + registRenderToStringFun(Element); + registRenderToHtmlFun(Element); + registTextFun(Element); + registValFun(Element); +}; diff --git a/src/core/element/plugins/keywordMark.js b/src/core/element/plugins/keywordMark.js new file mode 100644 index 000000000..a7eab83dd --- /dev/null +++ b/src/core/element/plugins/keywordMark.js @@ -0,0 +1,6 @@ +export const registKeywordMarkFun = (Element) => { + Element.registerFunction('__textKeywordMarked__', function (text) { + this[0].textContent = text; + return this; + }); +}; diff --git a/src/core/element/plugins/renderToHtml.js b/src/core/element/plugins/renderToHtml.js new file mode 100644 index 000000000..525afe062 --- /dev/null +++ b/src/core/element/plugins/renderToHtml.js @@ -0,0 +1,65 @@ +var skipArray = []; +var pxStyle = ['font-size', 'width', 'height']; +var _renderToHtml = function (root) { + var str = ''; + if (BI.isNull(root.originalHtml)) { + if (root.tag !== 'body') { + str += `<${root.tag}`; + if (root.classList.length > 0) { + str += ' class="'; + BI.each(root.classList, (i, cls) => { + str += ` ${cls}`; + }); + str += '"'; + } + str += ' style="'; + BI.each(root.originalStyles, (key, stl) => { + if ( + skipArray.contains(key) || + (key == 'height' && root.classList.contains('bi-design-components-data-data-table-cell')) + ) { + return; + } + key = BI.hyphenate(key); + if (key === 'font-family') { + stl = stl.replace(/\"/g, ''); + } + if (pxStyle.contains(key) && BI.isNumeric(stl)) { + stl += 'px'; + } + if (BI.isKey(stl)) { + str += ` ${key}:${stl};`; + } + }); + str += '"'; + BI.each(root.attribs, (key, attr) => { + if (BI.isKey(attr)) { + str += ` ${key}=${attr}`; + } + }); + if (root.textContent) { + str += ` title=${root.textContent}`; + } + str += '>'; + } + // 特殊处理,spread_table的行列元素是不取配置里的高度的,使用stretch拉伸的(leaves取了高度),但是功能代码里给单元格默认高度了,导致拉伸不了 + // 而spread_grid_table的行列元素是取配置里的高度的,拉不拉伸都一样 + BI.each(root.children, (i, child) => { + str += _renderToHtml(child); + }); + } else { + str += root.originalHtml; + } + if (root.tag !== 'body') { + if (root.textContent) { + str += root.textContent; + } + str += ``; + } + return str; +}; +export const registRenderToHtmlFun = (Element) => { + Element.registerFunction('renderToHtml', function () { + return _renderToHtml(this); + }); +}; diff --git a/src/core/element/plugins/renderToString.js b/src/core/element/plugins/renderToString.js new file mode 100644 index 000000000..f0073f258 --- /dev/null +++ b/src/core/element/plugins/renderToString.js @@ -0,0 +1,50 @@ +var skipArray = ['width', 'height']; +var _renderToString = function (root) { + var str = ''; + if (root.nodeName !== 'body') { + str += `<${root.nodeName}`; + if (root.classList.length > 0) { + str += ' class="'; + BI.each(root.classList, (i, cls) => { + str += ` ${cls}`; + }); + str += '"'; + } + str += ' style="'; + BI.each(root.styles, (key, stl) => { + if (skipArray.includes(key)) { + return; + } + key = BI.hyphenate(key); + str += ` ${key}:${stl};`; + }); + str += ` width:${root.width}px;`; + str += ` height:${root.height}px;`; + str += ' position: fixed;'; + str += ` left: ${root.position.x}px;`; + str += ` top: ${root.position.y}px;`; + str += '"'; + BI.each(root.attribs, (key, attr) => { + str += ` ${key}:${attr}`; + }); + str += '>'; + } + BI.each(root.children, (i, child) => { + str += _renderToString(child); + }); + // if (root.htmlContent) { + // str += root.htmlContent; + // } + if (root.nodeName !== 'body') { + if (root.text) { + str += root.text; + } + str += ``; + } + return str; +}; +export const registRenderToStringFun = (Element) => { + Element.registerFunction('renderToString', function () { + return _renderToString(this); + }); +}; diff --git a/src/core/element/plugins/text.js b/src/core/element/plugins/text.js new file mode 100644 index 000000000..555195251 --- /dev/null +++ b/src/core/element/plugins/text.js @@ -0,0 +1,10 @@ +export const registTextFun = (Element) => { + Element.registerFunction('setText', function (text) { + this.text = text; + return this; + }); + Element.registerFunction('setValue', function (text) { + this.text = text; + return this; + }); +}; diff --git a/src/core/element/plugins/val.js b/src/core/element/plugins/val.js new file mode 100644 index 000000000..f4b868918 --- /dev/null +++ b/src/core/element/plugins/val.js @@ -0,0 +1,9 @@ +export const registValFun = (Element) => { + Element.registerFunction('val', function (value) { + if (BI.isNotNull(value)) { + this.text = `${value}`; + return this; + } + return this.text; + }); +}; diff --git a/src/core/func/alias.js b/src/core/func/alias.js index 3738a83ea..e30d88c24 100644 --- a/src/core/func/alias.js +++ b/src/core/func/alias.js @@ -450,7 +450,7 @@ BI.cjkEncodeDO = function (o) { if (BI.isPlainObject(o)) { var result = {}; - _.each(o, function (v, k) { + BI._.each(o, function (v, k) { if (!(typeof v === "string")) { v = BI.jsonEncode(v); } @@ -603,7 +603,7 @@ return new Date(o.__time__); } for (var a in o) { - if (o[a] == o || typeof o[a] === "object" || _.isFunction(o[a])) { + if (o[a] == o || typeof o[a] === "object" || BI._.isFunction(o[a])) { break; } o[a] = arguments.callee(o[a]); diff --git a/src/core/func/array.js b/src/core/func/array.js index 7111530f4..a96292352 100644 --- a/src/core/func/array.js +++ b/src/core/func/array.js @@ -2,7 +2,7 @@ * 对数组对象的扩展 * @class Array */ -_.extend(BI, { +BI._.extend(BI, { pushArray: function (sArray, array) { for (var i = 0; i < array.length; i++) { diff --git a/src/core/func/date.js b/src/core/func/date.js index 2b7554079..74bf3bea7 100644 --- a/src/core/func/date.js +++ b/src/core/func/date.js @@ -6,7 +6,7 @@ BI.Date.HOUR = 60 * BI.Date.MINUTE; BI.Date.DAY = 24 * BI.Date.HOUR; BI.Date.WEEK = 7 * BI.Date.DAY; -_.extend(BI, { +BI._.extend(BI, { /** * 获取时区 * @returns {String} diff --git a/src/core/func/function.js b/src/core/func/function.js index 2d3f9a3e8..83d58c5ec 100644 --- a/src/core/func/function.js +++ b/src/core/func/function.js @@ -3,7 +3,7 @@ * Created by GUY on 2015/6/24. */ BI.Func = BI.Func || {}; -_.extend(BI.Func, { +BI._.extend(BI.Func, { /** * 创建唯一的名字 * @param array @@ -143,7 +143,7 @@ _.extend(BI.Func, { } }); -_.extend(BI, { +BI._.extend(BI, { beforeFunc: function (sFunc, func) { var __self = sFunc; return function () { diff --git a/src/core/func/number.js b/src/core/func/number.js index 17083caa3..59021349f 100644 --- a/src/core/func/number.js +++ b/src/core/func/number.js @@ -1,4 +1,4 @@ -_.extend(BI, { +BI._.extend(BI, { // 给Number类型增加一个add方法,调用起来更加方便。 add: function (num, arg) { return accAdd(arg, num); diff --git a/src/core/func/string.js b/src/core/func/string.js index e4b613f6d..55a89e63f 100644 --- a/src/core/func/string.js +++ b/src/core/func/string.js @@ -2,7 +2,7 @@ * 对字符串对象的扩展 * @class String */ -_.extend(BI, { +BI._.extend(BI, { /** * 判断字符串是否已指定的字符串开始 @@ -65,7 +65,7 @@ _.extend(BI, { } else { src += "&"; } - _.each(paras, function (value, name) { + BI._.each(paras, function (value, name) { if (typeof(name) === "string") { src += name + "=" + value + "&"; } diff --git a/src/core/platform/web/config.js b/src/core/platform/web/config.js index eeda344b0..9c4ba840c 100644 --- a/src/core/platform/web/config.js +++ b/src/core/platform/web/config.js @@ -210,12 +210,12 @@ BI.prepares.push(function () { }); BI.Plugin.configWidget("bi.horizontal_sticky", function (ob) { if (!isSupportSticky) { - return BI.extend({}, ob, {type: "bi.horizontal_fill"}); + return BI.extend({ scrollx: true }, ob, {type: "bi.horizontal_fill"}); } }); BI.Plugin.configWidget("bi.vertical_sticky", function (ob) { if (!isSupportSticky) { - return BI.extend({}, ob, {type: "bi.vertical_fill"}); + return BI.extend({ scrolly: true }, ob, {type: "bi.vertical_fill"}); } }); diff --git a/src/core/platform/web/function.js b/src/core/platform/web/function.js index faa40307b..230fc6ad5 100644 --- a/src/core/platform/web/function.js +++ b/src/core/platform/web/function.js @@ -1,5 +1,5 @@ // 浏览器相关方法 -_.extend(BI, { +BI._.extend(BI, { isIE: function () { if(!_global.navigator) { return false; diff --git a/src/core/platform/web/jquery/_jquery.js b/src/core/platform/web/jquery/_jquery.js index 48adf702e..8c83f4356 100644 --- a/src/core/platform/web/jquery/_jquery.js +++ b/src/core/platform/web/jquery/_jquery.js @@ -11012,10 +11012,6 @@ // Expose jQuery and $ identifiers, even in // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) // and CommonJS for browser emulators (#13566) - if (!window.$ && !window.jQuery) { - window.jQuery = window.$ = jQuery; - } - BI.jQuery = BI.$ = jQuery; return jQuery; diff --git a/src/core/platform/web/load.js b/src/core/platform/web/load.js index a3278cd39..f367b8cf6 100644 --- a/src/core/platform/web/load.js +++ b/src/core/platform/web/load.js @@ -1,4 +1,4 @@ -_.extend(BI, { +BI._.extend(BI, { $import: function () { var _LOADED = {}; // alex:保存加载过的 function loadReady (src, must) { diff --git a/src/core/plugin.js b/src/core/plugin.js index 50109a40c..bbfd5e5ac 100644 --- a/src/core/plugin.js +++ b/src/core/plugin.js @@ -36,8 +36,8 @@ BI.Plugin = BI.Plugin || {}; }, config: function (widgetConfigFn, objectConfigFn) { - _GlobalWidgetConfigFns = _GlobalWidgetConfigFns.concat(_.isArray(widgetConfigFn) ? widgetConfigFn : [widgetConfigFn]); - __GlobalObjectConfigFns = __GlobalObjectConfigFns.concat(_.isArray(objectConfigFn) ? objectConfigFn : [objectConfigFn]); + _GlobalWidgetConfigFns = _GlobalWidgetConfigFns.concat(BI._.isArray(widgetConfigFn) ? widgetConfigFn : [widgetConfigFn]); + __GlobalObjectConfigFns = __GlobalObjectConfigFns.concat(BI._.isArray(objectConfigFn) ? objectConfigFn : [objectConfigFn]); }, configWidget: function (type, fn, opt) { diff --git a/src/core/structure/aes.js b/src/core/structure/aes.js index fcb9c54c5..ec5d6b86a 100644 --- a/src/core/structure/aes.js +++ b/src/core/structure/aes.js @@ -2308,7 +2308,7 @@ }()); - _.extend(BI, { + BI._.extend(BI, { /** * aes加密方法 * aes-128-ecb diff --git a/src/core/structure/base64.js b/src/core/structure/base64.js index 4974133ce..976fbab9e 100644 --- a/src/core/structure/base64.js +++ b/src/core/structure/base64.js @@ -57,7 +57,7 @@ return string; }; - _.extend(BI, { + BI._.extend(BI, { encode: function (input) { var output = ""; diff --git a/src/core/system.js b/src/core/system.js index 652a9c256..545057e49 100644 --- a/src/core/system.js +++ b/src/core/system.js @@ -19,6 +19,40 @@ TOAST_TOP: 10, H_GAP_SIZE: "M", V_GAP_SIZE: "S" + }, + loadingCreator: function(config) { + var loadingSize = (config ? config.loadingSize : "small") || "small"; + + var isIE = BI.isIE(); + + function getSize(v) { + return Math.ceil(v / (loadingSize === "small" ? 2 : 1)); + } + + return { + type: "bi.horizontal", + cls: "bi-loading-widget" + (isIE ? " wave-loading hack" : ""), + height: getSize(60), + width: getSize(60), + hgap: getSize(10), + vgap: 2.5, + items: isIE ? [] : [{ + type: "bi.layout", + cls: "animate-rect rect1", + height: getSize(50), + width: getSize(5) + }, { + type: "bi.layout", + cls: "animate-rect rect2", + height: getSize(50), + width: getSize(5) + }, { + type: "bi.layout", + cls: "animate-rect rect3", + height: getSize(50), + width: getSize(5) + }] + }; } }; @@ -29,12 +63,11 @@ "L": 24 }; - var provider = function () { - + function provider () { this.SYSTEM = system; this.setSize = function (opt) { - BI.deepExtend(system, {size: opt}); + BI.deepExtend(system, { size: opt }); }; this.setResponsiveMode = function (mode) { @@ -60,6 +93,10 @@ BI.extend(system.dependencies, moduleConfig); }; + this.setLoadingCreator = function(creator) { + system.loadingCreator = creator; + }; + this.$get = function () { return BI.inherit(BI.OB, { @@ -88,13 +125,17 @@ getDependencies: function () { return system.dependencies; + }, + + getLoading: function(config) { + return system.loadingCreator(config); } }); }; - }; + } BI.provider("bi.provider.system", provider); -})(); +}()); BI.prepares.push(function () { BI.SIZE_CONSANTS = BI.Providers.getProvider("bi.provider.system").getSize(); diff --git a/src/core/utils/chinesePY.js b/src/core/utils/chinesePY.js index d1b5ab17f..b22cd94cb 100644 --- a/src/core/utils/chinesePY.js +++ b/src/core/utils/chinesePY.js @@ -422,7 +422,7 @@ return arrRslt.join(splitChar || "").toLowerCase(); }; - _.extend(BI, { + BI._.extend(BI, { makeFirstPY: function (str, options) { options = options || {}; if (typeof (str) !== "string") {return "" + str;} diff --git a/src/core/utils/i18n.js b/src/core/utils/i18n.js index 0dbf0a1a9..9cec7cc48 100644 --- a/src/core/utils/i18n.js +++ b/src/core/utils/i18n.js @@ -1,6 +1,6 @@ !(function () { var i18nStore = {}; - _.extend(BI, { + BI._.extend(BI, { changeI18n: function (i18n) { if (i18n) { i18nStore = i18n; diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js index 7a41ee0ae..5b83ff432 100644 --- a/src/core/wrapper/layout.js +++ b/src/core/wrapper/layout.js @@ -224,14 +224,14 @@ BI.Layout = BI.inherit(BI.Widget, { } } } else { - var keys = _.keys(a), key; + var keys = BI._.keys(a), key; length = keys.length; - if (_.keys(b).length !== length) { + if (BI._.keys(b).length !== length) { return false; } while (length--) { key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) { + if (!(BI._.has(b, key) && eq(a[key], b[key], aStack, bStack))) { return false; } } diff --git a/src/less/base/single/button/button.less b/src/less/base/single/button/button.less index 210bc4e89..6eae05320 100644 --- a/src/less/base/single/button/button.less +++ b/src/less/base/single/button/button.less @@ -467,6 +467,9 @@ body .bi-button, #body .bi-button { & .popup-content{ font-size: @font-size-14; } + .bi-button-mask { + pointer-events: none; + } } .bi-theme-dark { diff --git a/src/less/base/tree/ztree.less b/src/less/base/tree/ztree.less index 4d3cfc877..c4a8b6097 100644 --- a/src/less/base/tree/ztree.less +++ b/src/less/base/tree/ztree.less @@ -17,7 +17,7 @@ line-height: 14px; text-align: left; white-space: pre; - outline: 0 + outline: 0; } .ztree li ul { @@ -35,6 +35,7 @@ // 使用1倍图太模糊,这边就使用css自己画了,calc属性支持IE9, IE8反正会走hack, 不影响 .ztree li ul.line { position: relative; + &:before { position: absolute; content: ''; @@ -60,6 +61,7 @@ border-left: 1px dashed @border-color-dark-gray-line; } } + .ztree.solid li ul.line { &:before { border-left: 1px solid @border-color-dark-gray-line-theme-dark; @@ -68,19 +70,21 @@ } .ztree li a { - padding: 1px 3px 0 0; + padding: 0 3px 0 0; margin: 0; cursor: pointer; - height: 23px; + height: 24px; background-color: transparent; text-decoration: none; vertical-align: top; display: inline-block; + .tree-node-text { &:not(.disabled) { &:hover { .background-color(@color-bi-background-highlight, 10%); } + &:active { color: @color-bi-text-highlight; .background-color(@color-bi-background-highlight, 15%); @@ -90,7 +94,7 @@ } .ztree.solid li a { - height: 31px; + height: 32px; } .ztree li a.curSelectedNode { @@ -144,11 +148,24 @@ line-height: 32px; } +.ztree li span.icon { + display: inline-block; + vertical-align: top; + text-align: center; + width: 24px; + height: 24px; + line-height: 24px; +} + +.ztree li span.icon { + width: 32px; + height: 32px; + line-height: 32px; +} + .ztree li span.button { line-height: 0; margin: 0; - width: 16px; - height: 16px; display: inline-block; vertical-align: middle; border: 0 none; @@ -163,18 +180,22 @@ &.bi-checkbox { border: 1px solid @color-bi-border-dark-line; box-sizing: border-box; + &.active { background-color: @color-bi-background-highlight; border-color: @color-bi-border-highlight; } + &.disabled { border: 1px solid @color-bi-border-disabled; background-color: @color-bi-background-disabled; + &.active { border-color: @color-bi-border-disabled; } } } + &.bi-half-button { border: 1px solid @color-bi-border-highlight; box-sizing: border-box; diff --git a/src/less/resource/app.less b/src/less/resource/app.less index 4f61322d1..e09b2bd15 100644 --- a/src/less/resource/app.less +++ b/src/less/resource/app.less @@ -14,7 +14,6 @@ body { top: 0; left: 0; background-repeat: repeat; - .user-select-disable(); color: @color-bi-text-normal; font: normal 12px "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Heiti, "黑体", sans-serif; -webkit-font-smoothing: antialiased; @@ -29,6 +28,7 @@ body { div, textarea { scrollbar-color: fade(@scroll-color, 10%) fade(@scroll-color, 5%); scrollbar-width: thin; + &::-webkit-scrollbar { -webkit-appearance: none; width: 10px; @@ -37,10 +37,10 @@ div, textarea { &::-webkit-scrollbar-track { .border-radius(5px); - .background-color(@scroll-color, 5%); + .background-color(@scroll-color, 0%); &:hover { - .background-color(@scroll-color, 5%); + .background-color(@scroll-color, 0%); } } @@ -48,10 +48,11 @@ div, textarea { border: 2px solid transparent; background-clip: padding-box; .border-radius(10px); - .background-color(@scroll-color, 10%); + .background-color(@scroll-color, 7%); &:hover { - .background-color(@scroll-color, 30%); + .background-color(@scroll-color, 19%); + border: 1px solid transparent; } } @@ -63,23 +64,24 @@ div, textarea { .bi-theme-dark { div, textarea { scrollbar-color: fade(@scroll-color-theme-dark, 10%) fade(@scroll-color-theme-dark, 5%); + &::-webkit-scrollbar { -webkit-appearance: none; } &::-webkit-scrollbar-track { - .background-color(@scroll-color-theme-dark, 5%); + .background-color(@scroll-color-theme-dark, 0%); &:hover { - .background-color(@scroll-color-theme-dark, 5%); + .background-color(@scroll-color-theme-dark, 0%); } } &::-webkit-scrollbar-thumb { - .background-color(@scroll-color-theme-dark, 10%); + .background-color(@scroll-color-theme-dark, 7%); &:hover { - .background-color(@scroll-color-theme-dark, 30%); + .background-color(@scroll-color-theme-dark, 19%); } } } diff --git a/src/less/typographic.less b/src/less/typographic.less index 27aeba270..7c61d36e5 100644 --- a/src/less/typographic.less +++ b/src/less/typographic.less @@ -1,29 +1,30 @@ -.x-overflow-auto(){ +.x-overflow-auto() { overflow-y: hidden; overflow-x: auto; } -.y-overflow-auto(){ +.y-overflow-auto() { overflow-x: hidden; overflow-y: auto; } -.overflow-auto(){ +.overflow-auto() { overflow: auto; overflow-x: auto; overflow-y: auto; } -.overflow-hidden(){ +.overflow-hidden() { overflow: hidden; overflow-x: hidden; overflow-y: hidden; } -.overflow-dot(){ - text-overflow:ellipsis; + +.overflow-dot() { + text-overflow: ellipsis; overflow-x: hidden; overflow-y: hidden; - white-space:nowrap; + white-space: nowrap; } .user-select(@select) { @@ -35,19 +36,10 @@ user-select: @select; } -.user-select-disable(){ - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} -.user-select-enable(){ - -webkit-user-select: text; - -khtml-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - -o-user-select: text; - user-select: text; -} \ No newline at end of file +.user-select-disable() { + .user-select(none); +} + +.user-select-enable() { + .user-select(text); +} diff --git a/src/router/0.router.js b/src/router/0.router.js index 279289fc0..adf48b1bc 100644 --- a/src/router/0.router.js +++ b/src/router/0.router.js @@ -16,7 +16,7 @@ once: function (name, callback, context) { if (!eventsApi(this, "once", name, [callback, context]) || !callback) return this; var self = this; - var once = _.once(function () { + var once = BI._.once(function () { self.off(name, once); callback.apply(this, arguments); }); @@ -37,7 +37,7 @@ return this; } - var names = name ? [name] : _.keys(this._events); + var names = name ? [name] : BI._.keys(this._events); for (var i = 0, length = names.length; i < length; i++) { name = names[i]; @@ -103,7 +103,7 @@ // listening to. listenTo: function (obj, name, callback) { var listeningTo = this._listeningTo || (this._listeningTo = {}); - var id = obj._listenId || (obj._listenId = _.uniqueId("l")); + var id = obj._listenId || (obj._listenId = BI._.uniqueId("l")); listeningTo[id] = obj; if (!callback && typeof name === "object") callback = this; obj.on(name, callback, this); @@ -123,7 +123,7 @@ return this; } if (!callback) return this; - var once = _.once(function () { + var once = BI._.once(function () { this.stopListening(obj, name, once); callback.apply(this, arguments); }); @@ -142,7 +142,7 @@ for (var id in listeningTo) { obj = listeningTo[id]; obj.off(name, callback, this); - if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id]; + if (remove || BI._.isEmpty(obj._events)) delete this._listeningTo[id]; } return this; } @@ -222,7 +222,7 @@ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; // Set up all inheritable **BI.Router** properties and methods. - _.extend(Router.prototype, Events, { + BI._.extend(Router.prototype, Events, { // _init is an empty function by default. Override it with your own // initialization logic. @@ -236,8 +236,8 @@ // }); // route: function (route, name, callback) { - if (!_.isRegExp(route)) route = this._routeToRegExp(route); - if (_.isFunction(name)) { + if (!BI._.isRegExp(route)) route = this._routeToRegExp(route); + if (BI._.isFunction(name)) { callback = name; name = ""; } @@ -271,8 +271,8 @@ // routes can be defined at the bottom of the route map. _bindRoutes: function () { if (!this.routes) return; - this.routes = _.result(this, "routes"); - var route, routes = _.keys(this.routes); + this.routes = BI._.result(this, "routes"); + var route, routes = BI._.keys(this.routes); while ((route = routes.pop()) != null) { this.route(route, this.routes[route]); } @@ -295,7 +295,7 @@ // treated as `null` to normalize cross-browser behavior. _extractParameters: function (route, fragment) { var params = route.exec(fragment).slice(1); - return _.map(params, function (param, i) { + return BI._.map(params, function (param, i) { // Don't decode the search params. if (i === params.length - 1) return param || null; var resultParam = null; @@ -322,7 +322,7 @@ // falls back to polling. var History = function () { this.handlers = []; - this.checkUrl = _.bind(this.checkUrl, this); + this.checkUrl = BI._.bind(this.checkUrl, this); // Ensure that `History` can be used outside of the browser. if (typeof window !== "undefined") { @@ -344,7 +344,7 @@ History.started = false; // Set up all inheritable **BI.History** properties and methods. - _.extend(History.prototype, Events, { + BI._.extend(History.prototype, Events, { // The default interval to poll for hash changes, if necessary, is // twenty times a second. @@ -402,7 +402,7 @@ // Figure out the initial configuration. Do we need an iframe? // Is pushState desired ... is it available? - this.options = _.extend({root: "/"}, this.options, options); + this.options = BI._.extend({root: "/"}, this.options, options); this.root = this.options.root; this._wantsHashChange = this.options.hashChange !== false; this._hasHashChange = "onhashchange" in window; @@ -511,7 +511,7 @@ // remove a route match in routes unRoute: function (route) { - var index = _.findIndex(this.handlers, function (handler) { + var index = BI._.findIndex(this.handlers, function (handler) { return handler.route.test(route); }); if (index > -1) { @@ -545,7 +545,7 @@ // returns `false`. loadUrl: function (fragment) { fragment = this.fragment = this.getFragment(fragment); - return _.some(this.handlers, function (handler) { + return BI._.some(this.handlers, function (handler) { if (handler.route.test(fragment)) { handler.callback(fragment); return true; diff --git a/src/widget/editor/editor.text.js b/src/widget/editor/editor.text.js index 554bf2286..e50e153ae 100644 --- a/src/widget/editor/editor.text.js +++ b/src/widget/editor/editor.text.js @@ -28,15 +28,15 @@ BI.TextEditor = BI.inherit(BI.Widget, { var self = this, o = this.options; var border = o.simple ? 1 : 2; if (BI.isNumber(o.height)) { - this.element.css({height: o.height - border}); + this.element.css({ height: o.height - border }); } if (BI.isNumber(o.width)) { - this.element.css({width: o.width - border}); + this.element.css({ width: o.width - border }); } this.editor = BI.createWidget({ type: "bi.editor", + element: this, simple: o.simple, - height: o.height - border, hgap: o.hgap, vgap: o.vgap, lgap: o.lgap, @@ -116,12 +116,6 @@ BI.TextEditor = BI.inherit(BI.Widget, { this.editor.on(BI.Editor.EVENT_EMPTY, function () { self.fireEvent(BI.TextEditor.EVENT_EMPTY); }); - BI.createWidget({ - type: "bi.vertical", - scrolly: false, - element: this, - items: [this.editor] - }); }, setWaterMark: function (v) { @@ -177,4 +171,4 @@ BI.TextEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; BI.TextEditor.EVENT_REMOVE = "EVENT_REMOVE"; BI.TextEditor.EVENT_EMPTY = "EVENT_EMPTY"; -BI.shortcut("bi.text_editor", BI.TextEditor); \ No newline at end of file +BI.shortcut("bi.text_editor", BI.TextEditor); diff --git a/src/widget/multiselect/loader.js b/src/widget/multiselect/loader.js new file mode 100644 index 000000000..47f34a729 --- /dev/null +++ b/src/widget/multiselect/loader.js @@ -0,0 +1,259 @@ +/** + * 加载控件 + * + * Created by GUY on 2015/8/31. + * @class BI.Loader + * @extends BI.Widget + */ +BI.MultiSelectInnerLoader = BI.inherit(BI.Widget, { + _defaultConfig: function () { + return BI.extend(BI.MultiSelectInnerLoader.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-select-inner-loader", + + direction: "top", + isDefaultInit: true, // 是否默认初始化数据 + logic: { + dynamic: true, + scrolly: true + }, + + // 下面是button_group的属性 + el: { + type: "bi.button_group", + chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, + behaviors: { + redmark: function () { + return true; + } + }, + layouts: [{ + type: "bi.vertical" + }] + }, + + items: [], + itemsCreator: BI.emptyFn, + onLoaded: BI.emptyFn, + + // 下面是分页信息 + count: false, + prev: false, + next: {}, + hasPrev: BI.emptyFn, + hasNext: BI.emptyFn + }); + }, + + _nextLoad: function () { + var self = this, o = this.options; + this.next.setLoading(); + if (this.cachItems && this.cachItems.length > 0) { + this.next.setLoaded(); + this.addItems(this.cachItems.slice(0, 100)); + this.cachItems = this.cachItems.slice(100); + return; + } + o.itemsCreator.apply(this, [{times: ++this.times}, function () { + self.next.setLoaded(); + self.addItems.apply(self, arguments); + }]); + }, + + render: function () { + var self = this, o = this.options; + if (o.itemsCreator === false) { + o.next = false; + } + this.button_group = BI.createWidget(o.el, { + type: "bi.button_group", + chooseType: 0, + items: o.items, + behaviors: {}, + layouts: [{ + type: "bi.vertical" + }], + value: o.value + }); + this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { + if (type === BI.Events.CLICK) { + var node = self.cachGroup.getNodeByValue(value); + if (node) { + node.setSelected(obj.isSelected()); + } + } + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + if (type === BI.Events.CLICK) { + self.fireEvent(BI.Loader.EVENT_CHANGE, obj); + } + }); + + var renderEngine = BI.Widget._renderEngine; + BI.Widget.registerRenderEngine(BI.Element.renderEngine); + this.cachGroup = BI.createWidget(o.el, { + type: "bi.button_group", + root: true, + chooseType: 0, + items: o.items, + behaviors: {}, + layouts: [{ + type: "bi.vertical" + }], + value: o.value + }); + BI.Widget.registerRenderEngine(renderEngine); + + if (o.next !== false) { + this.next = BI.createWidget(BI.extend({ + type: "bi.loading_bar" + }, o.next)); + this.next.on(BI.Controller.EVENT_CHANGE, function (type) { + if (type === BI.Events.CLICK) { + self._nextLoad(); + } + }); + } + + BI.createWidget({ + type: "bi.vertical", + element: this, + items: [this.button_group, this.next] + }); + + o.isDefaultInit && BI.isEmpty(o.items) && BI.nextTick(BI.bind(function () { + o.isDefaultInit && BI.isEmpty(o.items) && this._populate(); + }, this)); + }, + + hasNext: function () { + var o = this.options; + if (BI.isNumber(o.count)) { + return this.count < o.count; + } + if (this.cachItems && this.cachItems.length > 0) { + return true; + } + return !!o.hasNext.apply(this, [{ + times: this.times, + count: this.count + }]); + }, + + addItems: function (items) { + this.count += items.length; + if (BI.isObject(this.next)) { + if (this.hasNext()) { + this.options.items = this.options.items.concat(items); + this.next.setLoaded(); + } else { + this.next.setEnd(); + } + } + var renderEngine = BI.Widget._renderEngine; + BI.Widget.registerRenderEngine(BI.Element.renderEngine); + this.cachGroup.addItems.apply(this.cachGroup, arguments); + BI.Widget.registerRenderEngine(renderEngine); + this.button_group.addItems.apply(this.button_group, arguments); + }, + + _populate: function (items) { + var self = this, o = this.options; + if (arguments.length === 0 && (BI.isFunction(o.itemsCreator))) { + o.itemsCreator.apply(this, [{times: 1}, function (items, keyword) { + if (arguments.length === 0) { + throw new Error("参数不能为空"); + } + self.populate.apply(self, arguments); + o.onLoaded(); + }]); + return false; + } + this.options.items = (items || []).slice(0, 100); + this.times = 1; + this.count = 0; + this.count += items.length; + if (BI.isObject(this.next)) { + if (this.hasNext()) { + this.next.setLoaded(); + } else { + this.next.invisible(); + } + } + return true; + }, + + populate: function (items, keyword) { + if (this._populate.apply(this, arguments)) { + this.cachItems = []; + if (items.length > 100) { + this.cachItems = items.slice(100); + } + var renderEngine = BI.Widget._renderEngine; + BI.Widget.registerRenderEngine(BI.Element.renderEngine); + this.cachGroup.populate.call(this.cachGroup, items, keyword); + BI.Widget.registerRenderEngine(renderEngine); + this.button_group.populate.call(this.button_group, items.slice(0, 100), keyword); + } + }, + + setNotSelectedValue: function () { + this.button_group.setNotSelectedValue.apply(this.button_group, arguments); + this.cachGroup.setNotSelectedValue.apply(this.cachGroup, arguments); + }, + + getNotSelectedValue: function () { + return this.cachGroup.getNotSelectedValue(); + }, + + setAllSelected: function (v) { + this.button_group.setAllSelected(v); + this.cachGroup.setAllSelected(v); + }, + + setValue: function (value) { + var map = BI.makeObject(BI.isArray(value) ? value : [value]); + this.cachGroup.setValueMap.call(this.cachGroup, map); + this.button_group.setValueMap.call(this.button_group, map); + }, + + getValue: function () { + return this.cachGroup.getValue.apply(this.cachGroup, arguments); + }, + + getAllButtons: function () { + return this.button_group.getAllButtons(); + }, + + getAllLeaves: function () { + return this.button_group.getAllLeaves(); + }, + + getSelectedButtons: function () { + return this.button_group.getSelectedButtons(); + }, + + getNotSelectedButtons: function () { + return this.button_group.getNotSelectedButtons(); + }, + + getIndexByValue: function (value) { + return this.button_group.getIndexByValue(value); + }, + + getNodeById: function (id) { + return this.button_group.getNodeById(id); + }, + + getNodeByValue: function (value) { + return this.button_group.getNodeByValue(value); + }, + + empty: function () { + this.button_group.empty(); + this.cachGroup.empty(); + BI.each([this.prev, this.next], function (i, ob) { + ob && ob.setVisible(false); + }); + } +}); +BI.MultiSelectInnerLoader.EVENT_CHANGE = "EVENT_CHANGE"; +BI.shortcut("bi.multi_select_inner_loader", BI.MultiSelectInnerLoader); diff --git a/src/widget/multiselect/multiselect.combo.js b/src/widget/multiselect/multiselect.combo.js index 23d5385b8..2e71071b8 100644 --- a/src/widget/multiselect/multiselect.combo.js +++ b/src/widget/multiselect/multiselect.combo.js @@ -173,7 +173,7 @@ BI.MultiSelectCombo = BI.inherit(BI.Single, { }, value: o.value, hideChecker: function (e) { - return triggerBtn.element.find(e.target).length === 0 && self.numberCounter.element.find(e.target).length === 0; + return self.numberCounter.element.find(e.target).length === 0; }, }); @@ -198,21 +198,6 @@ BI.MultiSelectCombo = BI.inherit(BI.Single, { } }); - var triggerBtn = BI.createWidget({ - type: "bi.trigger_icon_button", - width: o.height, - height: o.height, - cls: "multi-select-trigger-icon-button", - }); - triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { - self.numberCounter.hideView(); - if (self.combo.isViewVisible()) { - self.combo.hideView(); - } else { - self.combo.showView(); - } - }); - this.numberCounter = BI.createWidget({ type: "bi.multi_select_check_selected_switcher", masker: { @@ -263,11 +248,6 @@ BI.MultiSelectCombo = BI.inherit(BI.Single, { right: 0, top: 0, bottom: 0, - }, { - el: triggerBtn, - right: 0, - top: 0, - bottom: 0, }, { el: { type: "bi.vertical_adapt", diff --git a/src/widget/multiselect/multiselect.combo.nobar.js b/src/widget/multiselect/multiselect.combo.nobar.js index ff4cc5d34..a72519750 100644 --- a/src/widget/multiselect/multiselect.combo.nobar.js +++ b/src/widget/multiselect/multiselect.combo.nobar.js @@ -174,8 +174,7 @@ BI.MultiSelectNoBarCombo = BI.inherit(BI.Single, { value: o.value }, hideChecker: function (e) { - return triggerBtn.element.find(e.target).length === 0 && - self.numberCounter.element.find(e.target).length === 0; + return self.numberCounter.element.find(e.target).length === 0; } }); @@ -200,21 +199,6 @@ BI.MultiSelectNoBarCombo = BI.inherit(BI.Single, { } }); - var triggerBtn = BI.createWidget({ - type: "bi.trigger_icon_button", - width: o.height, - height: o.height, - cls: "multi-select-trigger-icon-button" - }); - triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { - self.numberCounter.hideView(); - if (self.combo.isViewVisible()) { - self.combo.hideView(); - } else { - self.combo.showView(); - } - }); - this.numberCounter = BI.createWidget({ type: "bi.multi_select_check_selected_switcher", masker: { @@ -268,11 +252,6 @@ BI.MultiSelectNoBarCombo = BI.inherit(BI.Single, { right: 0, top: 0, bottom: 0 - }, { - el: triggerBtn, - right: 0, - top: 0, - bottom: 0 }, { el: { type: "bi.vertical_adapt", diff --git a/src/widget/multiselect/multiselect.loader.js b/src/widget/multiselect/multiselect.loader.js index f01ac18bc..2f51ae181 100644 --- a/src/widget/multiselect/multiselect.loader.js +++ b/src/widget/multiselect/multiselect.loader.js @@ -17,6 +17,7 @@ BI.MultiSelectLoader = BI.inherit(BI.Widget, { }, valueFormatter: BI.emptyFn, itemsCreator: BI.emptyFn, + itemFormatter: BI.emptyFn, onLoaded: BI.emptyFn, itemHeight: BI.SIZE_CONSANTS.LIST_ITEM_HEIGHT, }); @@ -43,23 +44,7 @@ BI.MultiSelectLoader = BI.inherit(BI.Widget, { el: BI.extend({ onLoaded: opts.onLoaded, el: { - type: "bi.loader", - isDefaultInit: false, - logic: { - dynamic: true, - scrolly: true - }, - el: { - chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, - behaviors: { - redmark: function () { - return true; - } - }, - layouts: [{ - type: "bi.vertical" - }] - } + type: "bi.multi_select_inner_loader", } }, opts.el), itemsCreator: function (op, callback) { @@ -78,7 +63,8 @@ BI.MultiSelectLoader = BI.inherit(BI.Widget, { text: txt, value: v, title: txt, - selected: self.storeValue.type === BI.Selection.Multi + selected: self.storeValue.type === BI.Selection.Multi, + ...opts.itemFormatter(v), }; }); if (BI.isKey(self._startValue) && !BI.contains(self.storeValue.value, self._startValue)) { @@ -87,7 +73,8 @@ BI.MultiSelectLoader = BI.inherit(BI.Widget, { text: txt, value: startValue, title: txt, - selected: true + selected: true, + ...opts.itemFormatter(startValue), }); } firstItems = self._createItems(json); @@ -190,4 +177,4 @@ BI.MultiSelectLoader = BI.inherit(BI.Widget, { }); BI.MultiSelectLoader.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.multi_select_loader", BI.MultiSelectLoader); \ No newline at end of file +BI.shortcut("bi.multi_select_loader", BI.MultiSelectLoader); diff --git a/src/widget/multiselect/multiselect.trigger.js b/src/widget/multiselect/multiselect.trigger.js index 5b39b84dc..4f75b38cb 100644 --- a/src/widget/multiselect/multiselect.trigger.js +++ b/src/widget/multiselect/multiselect.trigger.js @@ -83,7 +83,15 @@ BI.MultiSelectTrigger = BI.inherit(BI.Trigger, { el: this.wrapNumberCounter, width: 0 }, { - el: BI.createWidget(), + el: { + type: "bi.trigger_icon_button", + height: o.height, + stopPropagation: true, + cls: "multi-select-trigger-icon-button", + handler: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.TOGGLE); + } + }, width: 24 }] }); @@ -114,7 +122,7 @@ BI.MultiSelectTrigger = BI.inherit(BI.Trigger, { /** * 重新调整numberCounter的空白占位符 */ - refreshPlaceHolderWidth: function(width) { + refreshPlaceHolderWidth: function (width) { this.wrapper.attr("items")[1].width = width; this.wrapper.resize(); }, @@ -167,4 +175,4 @@ BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW = "EVENT_BEFORE_COUNTER_POP BI.MultiSelectTrigger.EVENT_BLUR = "EVENT_BLUR"; BI.MultiSelectTrigger.EVENT_FOCUS = "EVENT_FOCUS"; -BI.shortcut("bi.multi_select_trigger", BI.MultiSelectTrigger); \ No newline at end of file +BI.shortcut("bi.multi_select_trigger", BI.MultiSelectTrigger); diff --git a/src/widget/multiselect/search/multiselect.search.insert.pane.js b/src/widget/multiselect/search/multiselect.search.insert.pane.js index 5af3ec36e..e72b64661 100644 --- a/src/widget/multiselect/search/multiselect.search.insert.pane.js +++ b/src/widget/multiselect/search/multiselect.search.insert.pane.js @@ -39,6 +39,7 @@ BI.MultiSelectSearchInsertPane = BI.inherit(BI.Widget, { type: "bi.multi_select_search_loader", keywordGetter: o.keywordGetter, valueFormatter: o.valueFormatter, + itemFormatter: o.itemFormatter, itemsCreator: function (op, callback) { o.itemsCreator.apply(self, [op, function (res) { callback(res); @@ -95,4 +96,4 @@ BI.MultiSelectSearchInsertPane = BI.inherit(BI.Widget, { BI.MultiSelectSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.multi_select_search_insert_pane", BI.MultiSelectSearchInsertPane); \ No newline at end of file +BI.shortcut("bi.multi_select_search_insert_pane", BI.MultiSelectSearchInsertPane); diff --git a/src/widget/multiselect/search/multiselect.search.loader.js b/src/widget/multiselect/search/multiselect.search.loader.js index dc2cf5d06..8f17eacfc 100644 --- a/src/widget/multiselect/search/multiselect.search.loader.js +++ b/src/widget/multiselect/search/multiselect.search.loader.js @@ -12,6 +12,7 @@ BI.MultiSelectSearchLoader = BI.inherit(BI.Widget, { itemsCreator: BI.emptyFn, keywordGetter: BI.emptyFn, valueFormatter: BI.emptyFn, + itemFormatter: BI.emptyFn, itemHeight: 24 }); }, @@ -113,7 +114,7 @@ BI.MultiSelectSearchLoader = BI.inherit(BI.Widget, { var newValues = BI.map(values, function (i, v) { return { text: o.valueFormatter(v) || v, - value: v + value: v, }; }); if (BI.isKey(keyword)) { @@ -125,7 +126,8 @@ BI.MultiSelectSearchLoader = BI.inherit(BI.Widget, { text: v.text, title: v.text, value: v.value, - selected: src.type === BI.Selection.All + selected: src.type === BI.Selection.All, + ...o.itemFormatter(v.value), }; }); }, @@ -162,4 +164,4 @@ BI.MultiSelectSearchLoader = BI.inherit(BI.Widget, { }); BI.MultiSelectSearchLoader.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.multi_select_search_loader", BI.MultiSelectSearchLoader); \ No newline at end of file +BI.shortcut("bi.multi_select_search_loader", BI.MultiSelectSearchLoader); diff --git a/src/widget/multiselect/search/multiselect.search.pane.js b/src/widget/multiselect/search/multiselect.search.pane.js index c81b40257..98c733348 100644 --- a/src/widget/multiselect/search/multiselect.search.pane.js +++ b/src/widget/multiselect/search/multiselect.search.pane.js @@ -31,6 +31,7 @@ BI.MultiSelectSearchPane = BI.inherit(BI.Widget, { type: "bi.multi_select_search_loader", keywordGetter: o.keywordGetter, valueFormatter: o.valueFormatter, + itemFormatter: o.itemFormatter, itemsCreator: function (op, callback) { o.itemsCreator.apply(self, [op, function (res) { callback(res); @@ -82,4 +83,4 @@ BI.MultiSelectSearchPane = BI.inherit(BI.Widget, { BI.MultiSelectSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.multi_select_search_pane", BI.MultiSelectSearchPane); \ No newline at end of file +BI.shortcut("bi.multi_select_search_pane", BI.MultiSelectSearchPane); diff --git a/src/widget/multiselectlist/multiselectlist.insert.js b/src/widget/multiselectlist/multiselectlist.insert.js index 082669692..277ee20a9 100644 --- a/src/widget/multiselectlist/multiselectlist.insert.js +++ b/src/widget/multiselectlist/multiselectlist.insert.js @@ -28,6 +28,7 @@ BI.MultiSelectInsertList = BI.inherit(BI.Single, { itemsCreator: o.itemsCreator, itemHeight: o.itemHeight, valueFormatter: o.valueFormatter, + itemFormatter: o.itemFormatter, logic: { dynamic: false }, @@ -45,6 +46,7 @@ BI.MultiSelectInsertList = BI.inherit(BI.Single, { type: "bi.multi_select_search_insert_pane", cls: "bi-border-left bi-border-right bi-border-bottom", valueFormatter: o.valueFormatter, + itemFormatter: o.itemFormatter, keywordGetter: function () { return self.trigger.getKeyword(); }, @@ -240,7 +242,7 @@ BI.MultiSelectInsertList = BI.inherit(BI.Single, { digest(); - function digest () { + function digest() { BI.each(keywords, function (i, val) { self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); }); diff --git a/src/widget/multiselectlist/multiselectlist.js b/src/widget/multiselectlist/multiselectlist.js index c0a3505ff..eccc18581 100644 --- a/src/widget/multiselectlist/multiselectlist.js +++ b/src/widget/multiselectlist/multiselectlist.js @@ -215,7 +215,7 @@ BI.MultiSelectList = BI.inherit(BI.Widget, { digest(values); }); - function digest (items) { + function digest(items) { var selectedMap = self._makeMap(items); BI.each(keywords, function (i, val) { if (BI.isNotNull(selectedMap[val])) { @@ -235,7 +235,7 @@ BI.MultiSelectList = BI.inherit(BI.Widget, { text: o.valueFormatter(v) || v, value: v }; - }), this.trigger.getKey()); + }), this.trigger.getKeyword()); var change = false; var map = this._makeMap(this.storeValue.value); BI.each(BI.concat(result.match, result.find), function (i, obj) { @@ -251,7 +251,7 @@ BI.MultiSelectList = BI.inherit(BI.Widget, { } o.itemsCreator({ type: BI.MultiSelectList.REQ_GET_ALL_DATA, - keywords: [this.trigger.getKey()], + keywords: [this.trigger.getKeyword()], selectedValues: BI.filter(this.storeValue.value, function (_i, v) { return !BI.contains(res.value, v); }), @@ -288,7 +288,7 @@ BI.MultiSelectList = BI.inherit(BI.Widget, { callback(); } - function adjust () { + function adjust() { if (self.storeValue.type === BI.Selection.All && self.storeValue.value.length >= self._count) { self.storeValue = { type: BI.Selection.Multi, @@ -365,4 +365,4 @@ BI.extend(BI.MultiSelectList, { }); BI.MultiSelectList.EVENT_CHANGE = "EVENT_CHANGE"; -BI.shortcut("bi.multi_select_list", BI.MultiSelectList); \ No newline at end of file +BI.shortcut("bi.multi_select_list", BI.MultiSelectList); diff --git a/src/widget/multitree/multi.tree.combo.js b/src/widget/multitree/multi.tree.combo.js index 4e42df154..ec94374d8 100644 --- a/src/widget/multitree/multi.tree.combo.js +++ b/src/widget/multitree/multi.tree.combo.js @@ -22,7 +22,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { var isInit = false; var want2showCounter = false; - this.storeValue = {value: o.value || {}}; + this.storeValue = { value: o.value || {} }; this.trigger = BI.createWidget({ type: "bi.multi_select_trigger", @@ -44,7 +44,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { type: "bi.multi_tree_searcher", itemsCreator: o.itemsCreator }, - value: {value: o.value || {}} + value: { value: o.value || {} } }); this.combo = BI.createWidget({ @@ -105,10 +105,9 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { maxWidth: o.isNeedAdjustWidth ? "auto" : 500, }, isNeedAdjustWidth: o.isNeedAdjustWidth, - value: {value: o.value || {}}, + value: { value: o.value || {} }, hideChecker: function (e) { - return triggerBtn.element.find(e.target).length === 0 && - self.numberCounter.element.find(e.target).length === 0; + return self.numberCounter.element.find(e.target).length === 0; } }); @@ -131,12 +130,12 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { }); this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; this.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); }); this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { - self.storeValue = {value: this.getValue()}; + self.storeValue = { value: this.getValue() }; self.combo.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); BI.nextTick(function () { @@ -151,11 +150,11 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { self.fireEvent(BI.MultiTreeCombo.EVENT_SEARCHING); }); - function showCounter () { + function showCounter() { if (isSearching()) { - self.storeValue = {value: self.trigger.getValue()}; + self.storeValue = { value: self.trigger.getValue() }; } else if (isPopupView()) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; } self.trigger.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); @@ -174,7 +173,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { var checked = this.getSearcher().hasChecked(); var val = { type: BI.Selection.Multi, - value: checked ? {1: 1} : {} + value: checked ? { 1: 1 } : {} }; this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); self.numberCounter.setButtonChecked(val); @@ -186,7 +185,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { return; } if (change === true) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; change = false; } self.combo.setValue(self.storeValue); @@ -201,9 +200,9 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { } else { if (isPopupView()) { self._stopEditing(); - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; if (clear === true) { - self.storeValue = {value: {}}; + self.storeValue = { value: {} }; } self.fireEvent(BI.MultiTreeCombo.EVENT_CONFIRM); } @@ -212,21 +211,6 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { change = false; }); - var triggerBtn = BI.createWidget({ - type: "bi.trigger_icon_button", - width: o.height, - height: o.height, - cls: "multi-select-trigger-icon-button" - }); - triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { - self.numberCounter.hideView(); - if (self.combo.isViewVisible()) { - self.combo.hideView(); - } else { - self.combo.showView(); - } - }); - this.numberCounter = BI.createWidget({ type: "bi.multi_select_check_selected_switcher", el: { @@ -245,7 +229,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { }, itemsCreator: o.itemsCreator, valueFormatter: o.valueFormatter, - value: {value: o.value || {}} + value: { value: o.value || {} } }); this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { if (!self.combo.isViewVisible()) { @@ -289,11 +273,6 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { right: 0, top: 0, bottom: 0 - }, { - el: triggerBtn, - right: 0, - top: 0, - bottom: 0 }, { el: { type: "bi.vertical_adapt", @@ -306,7 +285,7 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { }); }, - _stopEditing: function() { + _stopEditing: function () { this.trigger.stopEditing(); this.numberCounter.hideView(); }, diff --git a/src/widget/multitree/multi.tree.insert.combo.js b/src/widget/multitree/multi.tree.insert.combo.js index 9694b3556..9823b37a7 100644 --- a/src/widget/multitree/multi.tree.insert.combo.js +++ b/src/widget/multitree/multi.tree.insert.combo.js @@ -23,7 +23,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { var isInit = false; var want2showCounter = false; - this.storeValue = {value: o.value || {}}; + this.storeValue = { value: o.value || {} }; this.trigger = BI.createWidget({ type: "bi.multi_select_trigger", @@ -59,7 +59,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { }] } }, - value: {value: o.value || {}} + value: { value: o.value || {} } }); @@ -121,10 +121,9 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { maxWidth: o.isNeedAdjustWidth ? "auto" : 500, }, isNeedAdjustWidth: o.isNeedAdjustWidth, - value: {value: o.value || {}}, + value: { value: o.value || {} }, hideChecker: function (e) { - return triggerBtn.element.find(e.target).length === 0 && - self.numberCounter.element.find(e.target).length === 0; + return self.numberCounter.element.find(e.target).length === 0; } }); @@ -147,12 +146,12 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { }); this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; this.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); }); this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { - self.storeValue = {value: this.getValue()}; + self.storeValue = { value: this.getValue() }; self.combo.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); BI.nextTick(function () { @@ -167,11 +166,11 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { self.fireEvent(BI.MultiTreeInsertCombo.EVENT_SEARCHING); }); - function showCounter () { + function showCounter() { if (isSearching()) { - self.storeValue = {value: self.trigger.getValue()}; + self.storeValue = { value: self.trigger.getValue() }; } else if (isPopupView()) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; } self.trigger.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); @@ -185,7 +184,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { var checked = this.getSearcher().hasChecked(); var val = { type: BI.Selection.Multi, - value: checked ? {1: 1} : {} + value: checked ? { 1: 1 } : {} }; this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); self.numberCounter.setButtonChecked(val); @@ -197,7 +196,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { return; } if (change === true) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; change = false; } self.combo.setValue(self.storeValue); @@ -212,9 +211,9 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { } else { if (isPopupView()) { self._stopEditing(); - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; if (clear === true) { - self.storeValue = {value: {}}; + self.storeValue = { value: {} }; } self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); } @@ -223,21 +222,6 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { change = false; }); - var triggerBtn = BI.createWidget({ - type: "bi.trigger_icon_button", - width: o.height, - height: o.height, - cls: "multi-select-trigger-icon-button" - }); - triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { - self.numberCounter.hideView(); - if (self.combo.isViewVisible()) { - self.combo.hideView(); - } else { - self.combo.showView(); - } - }); - this.numberCounter = BI.createWidget({ type: "bi.multi_select_check_selected_switcher", el: { @@ -300,11 +284,6 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { right: 0, top: 0, bottom: 0 - }, { - el: triggerBtn, - right: 0, - top: 0, - bottom: 0 }, { el: { type: "bi.vertical_adapt", @@ -322,7 +301,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { this.numberCounter.setButtonChecked(this.storeValue); }, - _stopEditing: function() { + _stopEditing: function () { this.trigger.stopEditing(); this.numberCounter.hideView(); }, diff --git a/src/widget/multitree/multi.tree.list.combo.js b/src/widget/multitree/multi.tree.list.combo.js index ff5a2864a..2a378b1ae 100644 --- a/src/widget/multitree/multi.tree.list.combo.js +++ b/src/widget/multitree/multi.tree.list.combo.js @@ -23,7 +23,7 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { var isInit = false; var want2showCounter = false; - this.storeValue = {value: o.value || []}; + this.storeValue = { value: o.value || [] }; this.trigger = BI.createWidget({ type: "bi.multi_select_trigger", @@ -74,7 +74,7 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { itemsCreator: o.itemsCreator } }, - value: {value: o.value || {}} + value: { value: o.value || {} } }); @@ -139,10 +139,9 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { maxWidth: o.isNeedAdjustWidth ? "auto" : 500, }, isNeedAdjustWidth: o.isNeedAdjustWidth, - value: {value: o.value || {}}, + value: { value: o.value || {} }, hideChecker: function (e) { - return triggerBtn.element.find(e.target).length === 0 && - self.numberCounter.element.find(e.target).length === 0; + return self.numberCounter.element.find(e.target).length === 0; } }); @@ -165,12 +164,12 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { }); this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; this.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); }); this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { - self.storeValue = {value: this.getValue()}; + self.storeValue = { value: this.getValue() }; self.combo.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); BI.nextTick(function () { @@ -185,11 +184,11 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { self.fireEvent(BI.MultiTreeListCombo.EVENT_SEARCHING); }); - function showCounter () { + function showCounter() { if (isSearching()) { - self.storeValue = {value: self.trigger.getValue()}; + self.storeValue = { value: self.trigger.getValue() }; } else if (isPopupView()) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; } self.trigger.setValue(self.storeValue); self.numberCounter.setValue(self.storeValue); @@ -203,7 +202,7 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { var checked = this.getSearcher().hasChecked(); var val = { type: BI.Selection.Multi, - value: checked ? {1: 1} : {} + value: checked ? { 1: 1 } : {} }; this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); self.numberCounter.setButtonChecked(val); @@ -215,7 +214,7 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { return; } if (change === true) { - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; change = false; } self.combo.setValue(self.storeValue); @@ -230,9 +229,9 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { } else { if (isPopupView()) { self._stopEditing(); - self.storeValue = {value: self.combo.getValue()}; + self.storeValue = { value: self.combo.getValue() }; if (clear === true) { - self.storeValue = {value: []}; + self.storeValue = { value: [] }; } self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); } @@ -241,21 +240,6 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { change = false; }); - var triggerBtn = BI.createWidget({ - type: "bi.trigger_icon_button", - width: o.height, - height: o.height, - cls: "multi-select-trigger-icon-button" - }); - triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { - self.numberCounter.hideView(); - if (self.combo.isViewVisible()) { - self.combo.hideView(); - } else { - self.combo.showView(); - } - }); - this.numberCounter = BI.createWidget({ type: "bi.multi_select_check_selected_switcher", el: { @@ -318,11 +302,6 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { right: 0, top: 0, bottom: 0 - }, { - el: triggerBtn, - right: 0, - top: 0, - bottom: 0 }, { el: { type: "bi.vertical_adapt", @@ -340,7 +319,7 @@ BI.MultiTreeListCombo = BI.inherit(BI.Single, { this.numberCounter.setButtonChecked(this.storeValue); }, - _stopEditing: function() { + _stopEditing: function () { this.trigger.stopEditing(); this.numberCounter.hideView(); }, diff --git a/test/utils.js b/test/utils.js index 7e363b9bc..8ecf90a72 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,6 +1,6 @@ !(function () { BI.Test = {}; - _.extend(BI.Test, { + BI._.extend(BI.Test, { createWidget: function (widgetJson) { var widget = BI.createWidget(BI.extend(widgetJson, { root: true diff --git a/tsconfig.json b/tsconfig.json index 8a4138e71..5630b275a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,5 +28,7 @@ "types/*.d.ts", "src/*.js", "src/**/*.js", + "examples/*.js", + "examples/**/*.js", ] } \ No newline at end of file diff --git a/types/globals.d.ts b/types/globals.d.ts index f35336db4..0b5805aa0 100644 --- a/types/globals.d.ts +++ b/types/globals.d.ts @@ -11,3 +11,5 @@ declare const Fix: Obj; declare interface String { replaceAll(regx: string, callback: (str: string) => void): string; } + +declare const _global: typeof window; diff --git a/typescript/base/combination/group.button.ts b/typescript/base/combination/group.button.ts index eca1a224b..020ef0275 100644 --- a/typescript/base/combination/group.button.ts +++ b/typescript/base/combination/group.button.ts @@ -40,4 +40,6 @@ export declare class ButtonGroup extends Widget { getNodeByValue(value: any): any; getValue(): T[]; + + scrollToValue(value: any, scrollIntoViewOptions?: boolean | Obj): void; } diff --git a/typescript/base/combination/group.virtual.ts b/typescript/base/combination/group.virtual.ts index c3004e75f..d8e8c1b24 100644 --- a/typescript/base/combination/group.virtual.ts +++ b/typescript/base/combination/group.virtual.ts @@ -3,7 +3,7 @@ import { Widget } from '../../core/widget'; export declare class VirtualGroup extends Widget { static xtype: string; static EVENT_CHANGE: string; - + addItems(items: T[]): void; prependItems(items: T[]): void; @@ -13,4 +13,6 @@ export declare class VirtualGroup extends Widget { getValue(): T[]; populate(items?: any, ...args: any[]): void -} \ No newline at end of file + + scrollToValue(value: any, scrollIntoViewOptions?: boolean | Obj): void; +} diff --git a/typescript/base/list/listview.ts b/typescript/base/list/listview.ts index 459623383..b0007d5a1 100644 --- a/typescript/base/list/listview.ts +++ b/typescript/base/list/listview.ts @@ -1,4 +1,4 @@ -import { Widget } from '../../core/widget'; +import { Widget } from "../../core/widget"; export declare class ListView extends Widget { static xtype: string; @@ -6,4 +6,6 @@ export declare class ListView extends Widget { restore(): void; populate(items: T[]): void; + + scrollTo(scrollTop: number): void; } diff --git a/typescript/base/list/virtualgrouplist.ts b/typescript/base/list/virtualgrouplist.ts new file mode 100644 index 000000000..51b27423d --- /dev/null +++ b/typescript/base/list/virtualgrouplist.ts @@ -0,0 +1,11 @@ +import { Widget } from "../../core/widget"; + +export declare class VirtualGroupList extends Widget { + static xtype: string; + + restore(): void; + + populate(items: T[]): void; + + scrollTo(scrollTop: number): void; +} diff --git a/typescript/base/list/virtuallist.ts b/typescript/base/list/virtuallist.ts new file mode 100644 index 000000000..f23c00487 --- /dev/null +++ b/typescript/base/list/virtuallist.ts @@ -0,0 +1,11 @@ +import { Widget } from "../../core/widget"; + +export declare class VirtualList extends Widget { + static xtype: string; + + restore(): void; + + populate(items: T[]): void; + + scrollTo(scrollTop: number): void; +} diff --git a/typescript/core/base.ts b/typescript/core/base.ts index a30828489..b5a3ce55c 100644 --- a/typescript/core/base.ts +++ b/typescript/core/base.ts @@ -1,7 +1,7 @@ import { _Widget } from "./widget"; export interface _base { - assert: (v: any, is: Function) => Boolean + assert: (v: any, is: Function) => Boolean; warn: (message: any) => Boolean; @@ -15,62 +15,62 @@ export interface _base { packageItems: (items: any[], layouts: any[]) => any[]; - formatEL: (obj: T) => {el: T} | T + formatEL: (obj: T) => { el: T } | T; - stripEL: (obj: {el: T} | T) => T; + stripEL: (obj: { el: T } | T) => T; trans2Element: (widgets: any[]) => any[]; // 集合相关方法 - where: (collection: any[]|object|string, source: object) => any[]; + where: (collection: any[] | object | string, source: object) => any[]; - findWhere: (collection: any[]|object|string, callback?: Function|object|string, thisArg?: any) => object|undefined; + findWhere: (collection: any[] | object | string, callback?: Function | object | string, thisArg?: any) => object | undefined; - invoke: (collection: any[]|object|string, methodName: Function|string, arg?: any) => any[]; + invoke: (collection: any[] | object | string, methodName: Function | string, arg?: any) => any[]; - pluck: (collection: any[]|object|string, property: string) => any[]; + pluck: (collection: any[] | object | string, property: string) => any[]; - shuffle: (collection: any[]|object|string) => any[]; + shuffle: (collection: any[] | object | string) => any[]; - sample: (collection: any[]|object|string, n?: number) => any[]; + sample: (collection: any[] | object | string, n?: number) => any[]; - toArray: (collection: any[]|object|string) => any[]; + toArray: (collection: any[] | object | string) => any[]; size: (collection: any) => number; - each: (collection: T[]|object|string, callback?: ((index: number, value: T) => void)|object|string, thisArg?: any) => any; + each: (collection: T[] | object | string, callback?: ((index: number, value: T) => void) | object | string, thisArg?: any) => any; - map: (collection: T[]|object|string|null|undefined, callback?: ((index: number, value: T) => U)|object|string, thisArg?: any) => U[]; + map: (collection: T[] | object | string | null | undefined, callback?: ((index: number, value: T) => U) | object | string, thisArg?: any) => U[]; - reduce: (collection: T[]|object|string, callback?: ((total: U extends T ? U : T, currentValue: T, currentIndex: number) => U extends T ? U : T)|object|string, initialValue?: U|T) => U extends T ? U : T; + reduce: (collection: T[] | object | string, callback?: ((total: U extends T ? U : T, currentValue: T, currentIndex: number) => U extends T ? U : T) | object | string, initialValue?: U | T) => U extends T ? U : T; - reduceRight: (collection: T[]|object|string, callback?: ((total: U extends T ? U : T, currentValue: T, currentIndex: number) => U extends T ? U : T)|object|string, initialValue?: U|T) => U extends T ? U : T; + reduceRight: (collection: T[] | object | string, callback?: ((total: U extends T ? U : T, currentValue: T, currentIndex: number) => U extends T ? U : T) | object | string, initialValue?: U | T) => U extends T ? U : T; - find: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => T | undefined; + find: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => T | undefined; - filter: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => T[]; + filter: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => T[]; - reject: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => T[]; + reject: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => T[]; - every: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => boolean; + every: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => boolean; - all: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => boolean; + all: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => boolean; - some: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => boolean; + some: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => boolean; - any: (collection: T[]|object|string, callback?: ((index: number, value: T) => boolean)|object|string, thisArg?: any) => boolean; + any: (collection: T[] | object | string, callback?: ((index: number, value: T) => boolean) | object | string, thisArg?: any) => boolean; max: (collection: T[]) => T; min: (collection: T[]) => T; - sortBy: (collection: any[]|object|string, callback?: ((index: number, value: T) => number)|object|string, thisArg?: any) => any[]; + sortBy: (collection: any[] | object | string, callback?: ((index: number, value: T) => number) | object | string, thisArg?: any) => any[]; - groupBy: (collection: any[]|object|string, callback?: ((index: number, value: T) => any)|object|string, thisArg?: any) => object; + groupBy: (collection: any[] | object | string, callback?: ((index: number, value: T) => any) | object | string, thisArg?: any) => object; - indexBy: (collection: any[]|object|string, callback?: ((index: number, value: T) => any)|object|string, thisArg?: any) => object; + indexBy: (collection: any[] | object | string, callback?: ((index: number, value: T) => any) | object | string, thisArg?: any) => object; - countBy: (collection: any[]|object|string, callback?: ((index: number, value: T) => any)|object|string, thisArg?: any) => object; + countBy: (collection: any[] | object | string, callback?: ((index: number, value: T) => any) | object | string, thisArg?: any) => object; count: (from: number, to: number, predicate: Function) => number; @@ -99,7 +99,7 @@ export interface _base { remove: (obj: any, predicate: any, context?: any) => void; - removeAt: (obj: any, index: number|number[]) => void; + removeAt: (obj: any, index: number | number[]) => void; string2Array: (str: string) => string[]; @@ -110,17 +110,17 @@ export interface _base { int2Abc: (num: number) => string; // 数组相关的方法 - first: (array: T[], callback?: Function|object|number|string, thisArg?: any) => T; + first: (array: T[], callback?: Function | object | number | string, thisArg?: any) => T; - initial: (array: T[], callback?: Function|object|number|string, thisArg?: any) => T[]; + initial: (array: T[], callback?: Function | object | number | string, thisArg?: any) => T[]; - last: (array: T[], callback?: Function|object|number|string, thisArg?: any) => T; + last: (array: T[], callback?: Function | object | number | string, thisArg?: any) => T; - rest: (array: T[], callback?: Function|object|number|string, thisArg?: any) => T[]; + rest: (array: T[], callback?: Function | object | number | string, thisArg?: any) => T[]; compact: (array: any[]) => any[]; - flatten: (array: any[], isShallow?: boolean, callback?: Function|object|string, thisArg?: any) => any[]; + flatten: (array: any[], isShallow?: boolean, callback?: Function | object | string, thisArg?: any) => any[]; without: (array: any[], value?: any) => any[]; @@ -140,7 +140,7 @@ export interface _base { lastIndexOf: (array: any[], value: any, fromIndex?: number) => number; - sortedIndex: (array: any[], value: any, callback?: Function|object|string, thisArg?: any) => number; + sortedIndex: (array: any[], value: any, callback?: Function | object | string, thisArg?: any) => number; range: (start: number, end: number, step: number) => number[]; @@ -148,9 +148,9 @@ export interface _base { takeRight: (array: T[], n: number) => T[]; - findIndex: (array: any[], value: any, callback?: Function|object|string, thisArg?: any) => number; + findIndex: (array: any[], value: any, callback?: Function | object | string, thisArg?: any) => number; - findLastIndex: (array: any[], value: any, callback?: Function|object|string, thisArg?: any) => number; + findLastIndex: (array: any[], value: any, callback?: Function | object | string, thisArg?: any) => number; makeArray: (length: number, value?: T) => number[] | T[]; @@ -181,7 +181,7 @@ export interface _base { clone: (object: T) => T; - property: (path: any[]|string) => Function; + property: (path: any[] | string) => Function; propertyOf: (object: object) => Function; @@ -189,7 +189,7 @@ export interface _base { isMatch: (object: object, source: object, customizer?: Function, thisArg?: any) => boolean; - isEmpty: (value: any[]|object|string|null|undefined|number) => boolean; + isEmpty: (value: any[] | object | string | null | undefined | number) => boolean; isElement: (value: any) => boolean; @@ -225,11 +225,11 @@ export interface _base { cloneDeep: (value: T) => T; - findKey: (object: object, predicate?: Function|object|string, thisArg?: any) => any; + findKey: (object: object, predicate?: Function | object | string, thisArg?: any) => any; - pick: (object: object, predicate?: Function|string|string[], thisArg?: any) => object; + pick: (object: object, predicate?: Function | string | string[], thisArg?: any) => object; - omit: (object: object, predicate?: Function|string|string[], thisArg?: any) => object; + omit: (object: object, predicate?: Function | string | string[], thisArg?: any) => object; tap: (value: any, interceptor: Function, thisArg?: any) => any; @@ -237,21 +237,21 @@ export interface _base { init: () => void; - has: (obj: object, keys: string|string[]) => boolean; + has: (obj: object, keys: string | string[]) => boolean; freeze: (value: T) => T; isKey: (key: any) => key is (number | string); - isCapitalEqual: (a: string|null|undefined, b: string|null|undefined) => boolean; + isCapitalEqual: (a: string | null | undefined, b: string | null | undefined) => boolean; - isWidthOrHeight: (w: number|string) => boolean; + isWidthOrHeight: (w: number | string) => boolean; isNotNull: (obj: T) => obj is NonNullable; isNull: (obj: any) => obj is (undefined | null); - isEmptyArray: (arr: T[] | U) => arr is T[] & {length: 0}; + isEmptyArray: (arr: T[] | U) => arr is T[] & { length: 0 }; isNotEmptyArray: (arr: T[] | U) => arr is [T, ...T[]]; @@ -263,7 +263,7 @@ export interface _base { deepClone: (obj: T) => T; - deepExtend: merge['deepExtend']; + deepExtend: merge["deepExtend"]; isDeepMatch: (object: any, attrs: any) => boolean; @@ -307,7 +307,7 @@ export interface _base { wrap: (value: any, wrapper: Function) => Function; - nextTick: (func: Function) => Promise; + nextTick: (func?: Function) => Promise; random: (min?: number, max?: number, floating?: boolean) => number; @@ -317,21 +317,21 @@ export interface _base { parseFloat: (string: string) => number; - isNaturalNumber: (value: string|number) => boolean; + isNaturalNumber: (value: string | number) => boolean; - isPositiveInteger: (value: string|number) => boolean; + isPositiveInteger: (value: string | number) => boolean; - isNegativeInteger: (value: string|number) => boolean; + isNegativeInteger: (value: string | number) => boolean; - isInteger: (value: string|number) => boolean; + isInteger: (value: string | number) => boolean; - isNumeric: (value: string|number) => boolean; + isNumeric: (value: string | number) => boolean; - isFloat: (value: string|number) => boolean; + isFloat: (value: string | number) => boolean; - isOdd: (value: string|number) => boolean; + isOdd: (value: string | number) => boolean; - isEven: (value: string|number) => boolean; + isEven: (value: string | number) => boolean; sum: (array: any[], iteratee?: Function, context?: any) => number; @@ -367,7 +367,7 @@ export interface _base { isLeapYear: (year: number) => boolean; - checkDateVoid: (YY: string | number, MM: string | number, DD: string | number, minDate: string, maxDate: string) => (number|string)[]; + checkDateVoid: (YY: string | number, MM: string | number, DD: string | number, minDate: string, maxDate: string) => (number | string)[]; checkDateLegal: (str: string) => boolean; @@ -376,6 +376,12 @@ export interface _base { getDate: (...args: (number | string)[]) => Date; getTime: (...args: any[]) => number; + + /** + * 判断一个对象是不是promise + * @param obj 对象 + */ + isPromise: (obj: any) => obj is Promise; } type merge = { diff --git a/typescript/core/widget.ts b/typescript/core/widget.ts index 0a1b63246..4c1fc9d2f 100644 --- a/typescript/core/widget.ts +++ b/typescript/core/widget.ts @@ -42,8 +42,8 @@ export interface _Widget extends _OB { element: { width(): number; height(): number; - width(width: number | string): _Widget['element']; - height(height: number | string): _Widget['element']; + width(width: number | string): _Widget["element"]; + height(height: number | string): _Widget["element"]; [key: string]: any; }; @@ -110,7 +110,7 @@ export interface _Widget extends _OB { /** * 更新前 */ - shouldUpdate?(): void; + shouldUpdate?(...args: any[]): void; /** * 更新 @@ -449,8 +449,8 @@ export declare class Widget extends OB { element: { width(): number; height(): number; - width(width: number | string): Widget['element']; - height(height: number | string): Widget['element']; + width(width: number | string): Widget["element"]; + height(height: number | string): Widget["element"]; [key: string]: any; }; @@ -783,6 +783,11 @@ export declare class Widget extends OB { */ _unMount(): void; + /** + * watch响应式数据 + */ + __watch any>(getter: T, handler: Function, options?: Obj): ReturnType + /** * hang元素 */ diff --git a/typescript/core/worker/action/worker.action.ts b/typescript/core/worker/action/worker.action.ts new file mode 100644 index 000000000..8f6920003 --- /dev/null +++ b/typescript/core/worker/action/worker.action.ts @@ -0,0 +1,28 @@ +import type { WorkerBaseController } from "../controller/worker.controller"; + +/** + * 事务的基类 + */ +export class WorkerBaseAction { + /** + * 通信控制器 + */ + protected controller: WorkerBaseController; + + /** + * 线程上的 action 集合, 用于调用其他命名空间下的事务 + */ + protected threadAction: any; + + public constructor(controller: WorkerBaseController, threadAction: any) { + this.controller = controller; + this.threadAction = threadAction; + + this.addActionHandler(); + } + + /** + * 添加事务的处理器 + */ + protected addActionHandler() {} +} diff --git a/typescript/core/worker/controller/worker.controller.ts b/typescript/core/worker/controller/worker.controller.ts new file mode 100644 index 000000000..123bba98a --- /dev/null +++ b/typescript/core/worker/controller/worker.controller.ts @@ -0,0 +1,131 @@ +import type { IWorkerController, IWorkerMessage } from '../worker.core'; +import { WorkerChannel } from '../worker.channel'; + +/** + * 通信控制器 + * + * @class WorkerBaseController + */ +export class WorkerBaseController implements IWorkerController { + /** + * 原生 worker, 在子类中实例化 + */ + protected worker: Worker; + + /** + * 通信 Channel, 在子类中实例化 + */ + protected channel: WorkerChannel; + + /** + * 事务处理器 Map + */ + protected actionHandlerMap: { + [propsName: string]: (payload: any) => any; + }; + + public constructor() { + this.actionHandlerMap = {}; + } + + /** + * 发送事务,不等待结果 + * + * @param actionType 事务类型 + * @param payload 负载 + */ + public request(actionType: string, payload: any): void { + if (this.channel) { + return this.channel.request(actionType, payload); + } + + console.error('No channel.'); + + return; + } + + /** + * 发送 Promise 形式的事务, 在 then 中获取响应 + * + * @param actionType 事务类型 + * @param payload 负载 + * @param [timeout] 响应的超时; Worker 通道是可靠的, 超时后只上报, 不阻止当前请求 + */ + public requestPromise(actionType: string, payload: any = '', timeout?: number): Promise { + // 有 Channel 实例才能进行通信, 此时还没有实例化是浏览器不支持创建 worker + if (this.channel) { + return this.channel.requestPromise(actionType, payload, timeout); + } + + // 兼容上层调用的 .then().catch() + return Promise.reject(new Error('No channel.')); + } + + /** + * 添加事务处理器, 不允许重复添加 + * + * @param actionType 事务类型 + * @param handler 事务处理器 + */ + public addActionHandler(actionType: string, handler: (payload: any) => any): void { + if (this.hasActionHandler(actionType)) { + throw new Error(`Add action \`${actionType}\` handler repeat`); + } + this.actionHandlerMap[actionType] = handler; + } + + /** + * 事务处理器, 提供给通信 Channel 调用 + * + * @param message 会话消息 + * @returns + */ + public actionHandler(message: IWorkerMessage): Promise { + const { actionType, payload } = message; + + if (this.hasActionHandler(actionType)) { + // 执行指定的事务处理器, 并返回 Promise 封装的事务结果 + try { + const actionResult = this.actionHandlerMap[actionType](payload); + + // 对于 Promise 形式的结果, 需要进行 Promise 错误捕获 + if (BI.isPromise(actionResult)) { + return actionResult.catch(error => Promise.reject(error)); + } + + // 对数据结果, 包装为 Promise + return Promise.resolve(actionResult); + } catch (error) { + // 继续抛出给外层 + return Promise.reject(error); + } + } else { + throw new Error(`Not Found Session Handler \`${actionType}\`.`); + } + } + + /** + * 添加 worker onmessage 事件的回调 + * + * @param {(event: any) => void} onmessage 回调函数 + * @returns {() => void} 移除监听函数 + */ + public addOnmessageListener(onmessage: (event: any) => void): () => void { + this.worker.addEventListener('message', onmessage); + + // 返回移除监听函数 + return () => { + this.worker.removeEventListener('message', onmessage); + }; + } + + /** + * 判断是否有指定事务的处理器 + * + * @param actionType 事务类型 + * @returns {boolean} + */ + protected hasActionHandler(actionType: string): boolean { + return !!this.actionHandlerMap[actionType]; + } +} diff --git a/typescript/core/worker/controller/worker.main_thread.controller.ts b/typescript/core/worker/controller/worker.main_thread.controller.ts new file mode 100644 index 000000000..bd7dcfc96 --- /dev/null +++ b/typescript/core/worker/controller/worker.main_thread.controller.ts @@ -0,0 +1,85 @@ +import { WorkerChannel } from "../worker.channel"; +import type { IWorkerOptions } from "../worker.core"; +import { WorkerBaseController } from "./worker.controller"; + +export class WorkerMainThreadController extends WorkerBaseController { + /** + * 浏览器是否实现了 HTML 规范的 Worker Class + */ + public static hasWorkerClass = !!_global.Worker; + + /** + * 是否支持 new Worker, 默认为 Wroker Class 是否实现 + */ + + public canNewWorker: boolean = WorkerMainThreadController.hasWorkerClass; + + /** + * 主线程 new Worker 起始时刻 + */ + public timeBeforeNewWorker: number; + + /** + * 主线程 new Worker 完毕时刻 + */ + public timeAfterNewWorker: number; + + public constructor(options: IWorkerOptions) { + super(); + + if (!this.canNewWorker) { + // 都没有 Worker Class, 没法继续了 + return; + } + + this.newWorker(options); + } + + /** + * 销毁 Worker 线程实例 + */ + public terminate(): void { + this.worker?.terminate(); + } + + protected reportActionHandlerError(actionType: string, error: any): void { + console.error(`Worker aciton ${actionType}:`, error); + + // 主线程的报错, 在 window.onerror 中可以拿到报错堆栈, 直接抛出即可 + throw new Error(error); + } + + /** + * 创建 Worker 线程实例 + */ + private newWorker(options: IWorkerOptions) { + this.timeBeforeNewWorker = Date.now(); + + try { + // 主线程通过 new Worker() 获取 Worker 实例 + this.worker = new Worker(options.workerUrl, { + name: options.workerName, + }); + + /** + * 监控和上报 worker 中的报错 + * window.onerror 中也能监控到 worker.onerror( Worker 运行报错) + */ + this.worker.onerror = (error): void => { + console.error('Worker onerror:', error); + }; + + this.timeAfterNewWorker = Date.now(); + + // 实例化 Channel + this.channel = new WorkerChannel(this.worker, { + actionHandler: this.actionHandler.bind(this), + }); + } catch (error) { + console.error('Init worker fail:', error); + + // 创建 worker 失败, 标识改为不支持 + this.canNewWorker = false; + } + } +} diff --git a/typescript/core/worker/controller/worker.worker_thread.controller.ts b/typescript/core/worker/controller/worker.worker_thread.controller.ts new file mode 100644 index 000000000..2f4bac6cf --- /dev/null +++ b/typescript/core/worker/controller/worker.worker_thread.controller.ts @@ -0,0 +1,21 @@ +import { WorkerChannel } from "../worker.channel"; +import { WorkerBaseController } from "./worker.controller"; + +export class WorkerThreadController extends WorkerBaseController { + public constructor() { + super(); + + // Worker 线程中的全局环境 self 就是 Worker 实例 + this.worker = self as any; + this.channel = new WorkerChannel(this.worker, { + actionHandler: this.actionHandler.bind(this), + }); + } + + protected reportActionHandlerError(actionType: string, error: any): void { + console.error(`Worker aciton ${actionType}:`, error); + + // 正常抛出 + throw new Error(error); + } +} diff --git a/typescript/core/worker/worker.channel.ts b/typescript/core/worker/worker.channel.ts new file mode 100644 index 000000000..a39124a14 --- /dev/null +++ b/typescript/core/worker/worker.channel.ts @@ -0,0 +1,200 @@ +import { IWorkerController, WorkerMessageType, IWorkerMessage } from './worker.core'; + +const COMMUNICATION_TIMEOUT = 30000; + +/** + * 通信通道 + */ +export class WorkerChannel { + /** + * Web Worker 实例 + */ + private worker: Worker; + + /** + * 上层通信控制器 + */ + private controller: IWorkerController; + + /** + * 会话响应器 Map + */ + private sessionHandlerMap: { + [propsName: string]: Function; + }; + + public constructor(worker: Worker, controller: IWorkerController) { + this.worker = worker; + this.controller = controller; + + this.sessionHandlerMap = {}; + + // 绑定 worker onmessage 事件的回调 + this.worker.addEventListener('message', this.onmessage.bind(this)); + } + + /** + * 发送响应 + * + * @param sessionId 会话 Id + * @param payload 负载 + */ + public response(sessionId: string, actionType: string, payload: any): void { + this.postMessage({ + messageType: WorkerMessageType.REPLY, + actionType, + payload, + sessionId, + }); + } + + /** + * 发送请求, 不等待响应 + * + * @param actionType 事务类型 + * @param payload 负载 + */ + public request(actionType: string, payload: any): void { + const sessionId = this.generateSessionId(); + this.postMessage({ + messageType: WorkerMessageType.REQUEST, + actionType, + payload, + sessionId, + }); + + // 不等待结果, 还会收到响应, 添加个空的会话响应器 + this.addSessionHandler(sessionId, () => {}); + } + + /** + * 发送请求, 并等待响应 + * + * @param actionType 事务类型 + * @param payload 负载 + * @param timeout 响应超时 + * @returns {Promise} 等待响应的 Promise + */ + public requestPromise(actionType: string, payload: any, timeout = COMMUNICATION_TIMEOUT): Promise { + const sessionId = this.generateSessionId(); + const message = { + messageType: WorkerMessageType.REQUEST, + actionType, + payload, + sessionId, + }; + + // 请求封装为一个 Promise, 等待会话响应器进行 resolve + const PromiseFunction = (resolve: Function, reject: Function): any => { + // 启动请求超时计时器 + const timeoutHandler = setTimeout(() => { + clearTimeout(timeoutHandler); + + reject(); + }, timeout); + + const sessionHandler: Function = (message: IWorkerMessage) => { + // 会话回调函数, 开始处理响应 + this.deleteSessionHandler(message.sessionId); + clearTimeout(timeoutHandler); + + resolve(message.payload); + }; + + this.addSessionHandler(sessionId, sessionHandler); + + // 开始发送请求 + this.postMessage(message); + }; + + return new Promise(PromiseFunction); + } + + /** + * 收到会话消息的处理函数 + * + * 发现是请求, 调用通信控制器的事务处理器进行处理, 获取事务结果并响应; + * 发现是响应,调用会话响应器 + * @param event worker 通信事件 + */ + private onmessage(event: { data: IWorkerMessage }): void { + const { data: message } = event; + const { messageType, sessionId, actionType } = message; + + // 接收到请求 + if (messageType === WorkerMessageType.REQUEST) { + // 处理请求 + this.controller.actionHandler(message) + .then(actionResult => { + // 响应请求 + this.response(sessionId, actionType, actionResult); + }); + } + + // 接收到响应 + if (messageType === WorkerMessageType.REPLY) { + // 处理响应 + if (this.hasSessionHandler(sessionId)) { + this.sessionHandlerMap[sessionId](message); + } else { + throw new Error(`Session \`${sessionId}\` handler no exist`); + } + } + } + + /** + * 封装的 worker 原生 postMessage 接口 + * 支持 structured clone 和 transfer 2种通信模式 + * + * @param message 会话消息 + */ + private postMessage(message: IWorkerMessage): void { + this.worker.postMessage(message); + } + + /** + * 添加会话响应器 + * + * @param sessionId 会话 Id + * @param handler 会话响应器 + */ + private addSessionHandler(sessionId: string, handler: Function): void { + if (!this.hasSessionHandler(sessionId)) { + this.sessionHandlerMap[sessionId] = handler; + } else { + throw new Error(`SessionId \`${sessionId}\` already exist!`); + } + } + + /** + * 移除会话响应器 + * + * @param sessionId + */ + private deleteSessionHandler(sessionId: string): void { + if (this.hasSessionHandler(sessionId)) { + delete this.sessionHandlerMap[sessionId]; + } + } + + /** + * 生成每次独立会话的 Id + * + * @returns 会话 Id + */ + private generateSessionId(): string { + const sessionId = `w_${BI.UUID()}`; + + return sessionId; + } + + /** + * 判断是否有指定会话的处理器 + * + * @param sessionId 会话 Id + * @returns {boolean} 判断结果 + */ + private hasSessionHandler(sessionId: string): boolean { + return !!this.sessionHandlerMap[sessionId]; + } +} diff --git a/typescript/core/worker/worker.core.ts b/typescript/core/worker/worker.core.ts new file mode 100644 index 000000000..0c6db6186 --- /dev/null +++ b/typescript/core/worker/worker.core.ts @@ -0,0 +1,48 @@ +/** + * 会话消息类型枚举 + */ +export const WorkerMessageType = { + REQUEST: 'REQUEST', + REPLY: 'REPLY', +}; + +/** + * 会话消息 + */ +export interface IWorkerMessage { + messageType: string; + actionType: string; + sessionId: string; + + /** + * 数据交换参数 + */ + payload: any; +} + +/** + * 通信控制器需要实现的 interface + */ +export interface IWorkerController { + + /** + * 事务处理器 + */ + actionHandler: (message: IWorkerMessage) => Promise; +} + +/** + * Worker创建配置 + */ +export interface IWorkerOptions { + + /** + * worker 资源 url + */ + workerUrl: string; + + /** + * worker 实例名称 + */ + workerName: string; +} diff --git a/typescript/core/worker/worker.main_thread.ts b/typescript/core/worker/worker.main_thread.ts new file mode 100644 index 000000000..42e0c18dd --- /dev/null +++ b/typescript/core/worker/worker.main_thread.ts @@ -0,0 +1,49 @@ +import type { WorkerBaseAction } from "./action/worker.action"; +import { WorkerMainThreadController } from "./controller/worker.main_thread.controller"; +import { IWorkerOptions } from "./worker.core"; + +/** + * 主线程Worker + */ +export abstract class MainThreadWorker { + /** + * Worker 名称 + */ + public name: string; + + /** + * 主线程通信控制器 + */ + public controller: WorkerMainThreadController; + + /** + * 是否已经终止掉 Worker + */ + protected isTerminated = false; + + public constructor(options: IWorkerOptions) { + this.name = options.workerName; + this.controller = new WorkerMainThreadController(options); + this.initActions(); + } + + protected abstract initActions(): void; + + /** + * 销毁 worker 实例 + * 子实例需要销毁action + */ + public terminate(): void { + this.controller.terminate(); + // 设置终止标志位 + this.isTerminated = true; + } + + /** + * 实例化action + * @param Action action类 + */ + protected createAction(Action: T): InstanceType { + return (new Action(this.controller, this)) as InstanceType; + } +} diff --git a/typescript/core/worker/worker.worker_thread.ts b/typescript/core/worker/worker.worker_thread.ts new file mode 100644 index 000000000..9907955fb --- /dev/null +++ b/typescript/core/worker/worker.worker_thread.ts @@ -0,0 +1,28 @@ +import type { WorkerBaseAction } from "./action/worker.action"; +import { WorkerThreadController } from "./controller/worker.worker_thread.controller"; + +/** + * worker线程实例 + */ +export abstract class WorkerThreadWorker { + /** + * Worker 线程通信控制器 + */ + protected controller: WorkerThreadController; + + public constructor() { + this.controller = new WorkerThreadController(); + + this.initActions(); + } + + protected abstract initActions(): void; + + /** + * 实例化action + * @param Action action类 + */ + protected createAction(Action: T): InstanceType { + return (new Action(this.controller, this)) as InstanceType; + } +} diff --git a/typescript/core/worker/workers.ts b/typescript/core/worker/workers.ts new file mode 100644 index 000000000..f02447120 --- /dev/null +++ b/typescript/core/worker/workers.ts @@ -0,0 +1,19 @@ +import { WorkerChannel } from "./worker.channel"; +import { WorkerBaseController } from "./controller/worker.controller"; +import { WorkerMessageType } from "./worker.core"; +import { WorkerMainThreadController } from "./controller/worker.main_thread.controller"; +import { WorkerThreadController } from "./controller/worker.worker_thread.controller"; +import { WorkerBaseAction } from "./action/worker.action"; +import { MainThreadWorker } from "./worker.main_thread"; +import { WorkerThreadWorker } from "./worker.worker_thread"; + +export const Workers = { + WorkerChannel, + WorkerBaseController, + WorkerMainThreadController, + WorkerThreadController, + WorkerBaseAction, + MainThreadWorker, + WorkerThreadWorker, + WorkerMessageType, +}; diff --git a/typescript/index.ts b/typescript/index.ts index fa9a08d19..3aaca1ead 100644 --- a/typescript/index.ts +++ b/typescript/index.ts @@ -20,12 +20,12 @@ import { IconChangeButton } from "./case/button/icon/icon.change"; import { MultiSelectItem } from "./case/button/item.multiselect"; import { BubbleCombo } from "./case/combo/bubblecombo/combo.bubble"; import { TextValueCombo } from "./case/combo/combo.textvalue"; -import { SmallTextValueCombo } from './case/combo/combo.textvaluesmall'; +import { SmallTextValueCombo } from "./case/combo/combo.textvaluesmall"; import { SearchTextValueCombo } from "./case/combo/searchtextvaluecombo/combo.searchtextvalue"; import { SignEditor } from "./case/editor/editor.sign"; -import { StateEditor } from './case/editor/editor.state'; +import { StateEditor } from "./case/editor/editor.state"; import { AllValueMultiTextValueCombo } from "./component/allvaluemultitextvaluecombo/allvalue.multitextvalue.combo"; -import { Form } from './component/form/form'; +import { Form } from "./component/form/form"; import { AbstractTreeValueChooser } from "./component/treevaluechooser/abstract.treevaluechooser"; import { AbstractListTreeValueChooser } from "./component/treevaluechooser/abstract.treevaluechooser.list"; import { Action, ActionFactory } from "./core/action/action"; @@ -53,7 +53,10 @@ import { DownListCombo } from "./widget/downlist/combo.downlist"; import { DownListPopup } from "./widget/downlist/popup.downlist"; import { Icon } from "./base/single/icon/icon"; import { LeftVerticalAdaptLayout } from "./core/wrapper/layout/adapt/adapt.leftvertical"; -import { LeftRightVerticalAdaptLayout, RightVerticalAdaptLayout } from "./core/wrapper/layout/adapt/adapt.leftrightvertical"; +import { + LeftRightVerticalAdaptLayout, + RightVerticalAdaptLayout, +} from "./core/wrapper/layout/adapt/adapt.leftrightvertical"; import { IconTextIconItem } from "./base/single/button/listitem/icontexticonitem"; import { HorizontalAutoLayout } from "./core/wrapper/layout/adapt/auto.horizontal"; import { InlineVerticalAdaptLayout } from "./core/wrapper/layout/adapt/inline.vertical"; @@ -82,14 +85,14 @@ import { MultiSelectCombo } from "./widget/multiselect/multiselect.combo"; import { SearchEditor } from "./widget/editor/editor.search"; import { MultiLayerSingleLevelTree } from "./widget/multilayersingletree/multilayersingletree.leveltree"; import { SimpleColorChooser } from "./case/colorchooser/colorchooser.simple"; -import { ColorChooser } from './case/colorchooser/colorchooser'; +import { ColorChooser } from "./case/colorchooser/colorchooser"; import { A } from "./base/a/a"; import { Html } from "./base/single/html/html"; import { Switcher } from "./base/combination/switcher"; -import { Expander } from './base/combination/expander'; +import { Expander } from "./base/combination/expander"; import { Loader } from "./base/combination/loader"; import { ListPane } from "./case/layer/pane.list"; -import { MultiPopupView } from './case/layer/layer.multipopup'; +import { MultiPopupView } from "./case/layer/layer.multipopup"; import { MultiSelectBar } from "./case/toolbar/toolbar.multiselect"; import { SelectList } from "./case/list/list.select"; import { AbstractAllValueChooser } from "./component/allvaluechooser/abstract.allvaluechooser"; @@ -130,7 +133,7 @@ import { TextValueDownListCombo } from "./widget/textvaluedownlistcombo/combo.te import { Switch } from "./case/button/switch"; import { HorizontalLayout } from "./core/wrapper/layout/layout.horizontal"; import { ShelterEditor } from "./case/editor/editor.shelter"; -import { TextTrigger } from './case/trigger/trigger.text'; +import { TextTrigger } from "./case/trigger/trigger.text"; import { SelectTextTrigger } from "./case/trigger/trigger.text.select"; import { DateInterval } from "./widget/timeinterval/dateinterval"; import { DynamicDatePane } from "./widget/datepane/datepane"; @@ -151,43 +154,46 @@ import { Segment } from "./case/segment/segment"; import { LinearSegment } from "./case/linersegment/linear.segment"; import { Img } from "./base/single/img/img"; import { EditorIconCheckCombo } from "./case/combo/editoriconcheckcombo/combo.editiconcheck"; -import { IconTextValueCombo } from './case/combo/icontextvaluecombo/combo.icontextvalue'; -import { ListView } from './base/list/listview'; -import { FloatCenterLayout } from './core/wrapper/layout/middle/middle.float.center'; -import { _msg } from './base/foundation/message'; -import { _web } from './core/platform/web'; -import { DynamicYearMonthPopup } from './widget/yearmonth/popup.yearmonth'; -import { _utils } from './core/utils'; +import { IconTextValueCombo } from "./case/combo/icontextvaluecombo/combo.icontextvalue"; +import { ListView } from "./base/list/listview"; +import { VirtualList } from "./base/list/virtuallist"; +import { VirtualGroupList } from "./base/list/virtualgrouplist"; +import { FloatCenterLayout } from "./core/wrapper/layout/middle/middle.float.center"; +import { _msg } from "./base/foundation/message"; +import { _web } from "./core/platform/web"; +import { DynamicYearMonthPopup } from "./widget/yearmonth/popup.yearmonth"; +import { _utils } from "./core/utils"; import { Controller } from "./core/controller/controller"; import { LayerController } from "./core/controller/controller.layer"; import { DateCalendarPopup } from "./widget/date/calendar/popup.calendar.date"; import { Tree, Node } from "./core/utils/tree"; import { TextNode } from "./base/single/button/node/textnode"; import { TextValueCheckComboPopup } from "./case/combo/textvaluecheckcombo/popup.textvaluecheck"; -import { ImageButton } from './base/single/button/buttons/button.image'; +import { ImageButton } from "./base/single/button/buttons/button.image"; import { History, Router } from "./router/router"; -import { DateTimeCombo } from './widget/datetime/datetime.combo'; +import { DateTimeCombo } from "./widget/datetime/datetime.combo"; import { FloatHorizontalLayout } from "./core/wrapper/layout/adapt/float.horizontal"; import { AdaptiveLayout } from "./core/wrapper/layout/layout.adaptive"; -import { HexColorChooserPopup } from './case/colorchooser/colorchooser.popup.hex'; -import { BlankIconTextItem } from './base/single/button/listitem/blankicontextitem'; +import { HexColorChooserPopup } from "./case/colorchooser/colorchooser.popup.hex"; +import { BlankIconTextItem } from "./base/single/button/listitem/blankicontextitem"; import { Broadcasts, Layers } from "./base/base"; import { BroadcastController } from "./core/controller/controller.broadcast"; import { Pager } from "./base/pager/pager"; -import { TimeInterval } from './widget/timeinterval/timeinterval'; -import { DynamicDateTimePane } from './widget/datetimepane/datetimepane'; -import { SingleSelectInsertList } from './widget/singleselect/singleselectlist.insert'; -import { MultiSelectTree } from './widget/multiselecttree/multiselecttree'; +import { TimeInterval } from "./widget/timeinterval/timeinterval"; +import { DynamicDateTimePane } from "./widget/datetimepane/datetimepane"; +import { SingleSelectInsertList } from "./widget/singleselect/singleselectlist.insert"; +import { MultiSelectTree } from "./widget/multiselecttree/multiselecttree"; import { HtmlLabel } from "./base/single/label/html.label"; -import { TreeValueChooserPane } from './component/treevaluechooser/pane.treevaluechooser'; -import { TdLayout } from './core/wrapper/layout/layout.td'; -import { MultiLayerSelectLevelTree } from './widget/multilayerselecttree/multilayerselecttree.leveltree'; -import { SelectTreeExpander } from './widget/selecttree/selecttree.expander'; +import { TreeValueChooserPane } from "./component/treevaluechooser/pane.treevaluechooser"; +import { TdLayout } from "./core/wrapper/layout/layout.td"; +import { MultiLayerSelectLevelTree } from "./widget/multilayerselecttree/multilayerselecttree.leveltree"; +import { SelectTreeExpander } from "./widget/selecttree/selecttree.expander"; import { DownListGroupItem } from "./widget/downlist/item.downlistgroup"; import { VerticalStickyLayout } from "./core/wrapper/layout/sticky/sticky.vertical"; import { HorizontalStickyLayout } from "./core/wrapper/layout/sticky/sticky.horizontal"; import { TableLayout } from "./core/wrapper/layout/layout.table"; -import './shims-tsx'; +import "./shims-tsx"; +import { Workers } from "./core/worker/workers"; export interface BI extends _func, _i18n, _base, _inject, _var, _web, _utils { @@ -355,6 +361,8 @@ export interface BI extends _func, _i18n, _base, _inject, _var, _web, _utils { EditorIconCheckCombo: typeof EditorIconCheckCombo; IconTextValueCombo: typeof IconTextValueCombo; ListView: typeof ListView; + VirtualList: typeof VirtualList; + VirtualGroupList: typeof VirtualGroupList; FloatCenterLayout: typeof FloatCenterLayout; Msg: _msg; DynamicYearMonthPopup: typeof DynamicYearMonthPopup; @@ -382,10 +390,12 @@ export interface BI extends _func, _i18n, _base, _inject, _var, _web, _utils { VerticalStickyLayout: typeof VerticalStickyLayout; HorizontalStickyLayout: typeof HorizontalStickyLayout; TableLayout: typeof TableLayout; + Workers: typeof Workers; } export default { Decorators: decorator, + Workers, }; export { OB, @@ -547,6 +557,8 @@ export { EditorIconCheckCombo, IconTextValueCombo, ListView, + VirtualList, + VirtualGroupList, FloatCenterLayout, DynamicYearMonthPopup, DateCalendarPopup, diff --git a/webpack/attachments.js b/webpack/attachments.js index eefbe4b42..cf26e9d09 100644 --- a/webpack/attachments.js +++ b/webpack/attachments.js @@ -5,6 +5,7 @@ const fixProxyJs = './dist/fix/fix.proxy.js'; const fixCompact = "./dist/fix/fix.compact.js"; const workerCompact = './dist/fix/worker.compact.js'; const lodashJs = "src/core/1.lodash.js"; +const jqueryJs = "src/core/platform/web/jquery/_jquery.js"; const basicAttachmentMap = { polyfill: sync(["src/core/0.foundation.js", "src/polyfill/**/*.js"]).concat(["@babel/polyfill", "es6-promise/auto"]), @@ -12,6 +13,7 @@ const basicAttachmentMap = { "src/less/core/**/*.less", "src/less/theme/**/*.less", lodashJs, + jqueryJs, "src/core/**/*.js", "src/data/**/*.js", ]), @@ -46,6 +48,15 @@ const basicAttachmentMap = { core_without_normalize: sync( ["src/less/core/**/*.less", "src/less/theme/**/*.less"], ["src/less/core/normalize.less", "src/less/core/normalize2.less"] ), + core_without_conflict: sync([ + "src/less/core/**/*.less", + "src/less/theme/**/*.less", + lodashJs, + "src/core/**/*.js", + "src/data/**/*.js", + ], [ + "src/core/conflict.js", + ]), resource: sync(["src/less/resource/**/*.less"]), font: sync(["public/less/font.less"]), ts: ['./typescript/bundle.ts'], @@ -156,6 +167,19 @@ const fineui = [].concat( basicAttachmentMap.ts, ); +const fineuiWithoutConflict = [].concat( + basicAttachmentMap.polyfill, + basicAttachmentMap.core_without_conflict, + basicAttachmentMap.fix, + basicAttachmentMap.base, + basicAttachmentMap.case, + basicAttachmentMap.widget, + basicAttachmentMap.router, + [fixCompact, workerCompact], + basicAttachmentMap.ui, + basicAttachmentMap.ts, +); + // const fineuiModern = [].concat( // sync(["src/less/modern.less"]), // sync([ @@ -221,6 +245,7 @@ module.exports = { font: basicAttachmentMap.font, bundle: uniq(bundle), fineuiWithoutNormalize: uniq(fineuiWithoutNormalize), + fineuiWithoutConflict: uniq(fineuiWithoutConflict), bundleWithoutNormalize: uniq(bundleWithoutNormalize), fineui: uniq(fineui), fineuiProxy: uniq(fineuiProxy), diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 05cb95648..1af08c2af 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -18,6 +18,7 @@ module.exports = merge.smart(common, { font: attachments.font, "fineui.min": attachments.fineui, "fineui_without_normalize.min": attachments.fineuiWithoutNormalize, + "fineui_without_conflict.min": attachments.fineuiWithoutConflict, "fineui.proxy.min": attachments.fineuiProxy, "core_without_platform": attachments.coreWithoutPlatform, utils: attachments.utils,