!(function() { /** * 顶部组件,提供输入框添加todo项目 * 布局: bi.horizontal_auto 实现水平居中. bi.left_right_vertical_adapt 实现标题是输入框的靠左靠右垂直居中 */ var ToDoListHeader = BI.inherit(BI.Widget, { props: { // 指定组件的className baseCls: "my-todolist-header" }, render: function() { var self = this, o = this.options; return { type: "bi.horizontal_auto", // 水平居中布局 items: [ { el: { type: "bi.left_right_vertical_adapt", // 左右垂直居中布局 width: 600, height: o.height, items: { left: [ { el: { type: "bi.label", cls: "my-todolist-title", text: "FineUI ToDoList", height: o.height } } ], right: [ { el: { type: "bi.editor", ref: function(_ref) { self.editor = _ref; }, allowBlank: true, cls: "my-todolist-header-editor", watermark: "添加ToDo", width: 300, height: 24, listeners: [ { // 监听bi.editor 组件的"EVENT_ENTER"事件(即敲回车),触发事件ToDoListHeader.EVENT_ADD事件并将输入框值置空 eventName: "EVENT_ENTER", action: function() { // 注意:在这里this指向的是bi.editor的实例.通过bi.editor的getValue()方法获取输入框输入值. self.fireEvent(ToDoListHeader.EVENT_ADD, this.getValue()); self.editor.setValue(""); } } ] } } ] } } } ] }; } }); ToDoListHeader.EVENT_ADD = "EVENT_ADD"; BI.shortcut("my.todolist.header", ToDoListHeader); })();!(function() { /** * todo项列表 * */ var List = BI.inherit(BI.Widget, { props: { // 指定组件的className baseCls: "my-todolist-list", text: "正在进行" }, render: function() { var self = this, o = this.options; return { type: "bi.vertical", items: [ { el: { type: "bi.vertical_adapt", height: 40, items: [ { type: "bi.label", cls: "my-todolist-list-text", textAlign: "left", text: o.text, width: 580 }, { type: "bi.center_adapt", cls: "my-todolist-list-count-container", width: 20, height: 20, items: [ { el: { type: "bi.label", ref: function(_ref) { self.count = _ref; }, text: "0" } } ] } ] } }, { // 用bi.vertical布局作为列表项的容器. type: "bi.vertical", vgap: 10, ref: function(_ref) { self.list = _ref; }, items: this._createItems(o.items) } ] }; }, _createItems: function(items) { var self = this; return BI.map(items, function(index, item) { return BI.extend(item, { type: "bi.multi_select_item", // 节点采用复选节点展示 selected: item.done, // 已完成的todo项置为选中状态 disabled: item.done, // 已完成的todo项置为灰化状态 listeners: [ { // 为每个todo项添加"EVENT_CHANGE"事件监听,触发组件自身"EVENT_CHANGE"事件 eventName: "EVENT_CHANGE", action: function(v) { self.fireEvent("EVENT_CHANGE", v); } } ] }); }); }, _setCount: function(count) { this.count.setText(count); }, populate: function(items) { this.list.populate(this._createItems(items)); this._setCount(items.length); } }); BI.shortcut("my.todolist.list", List); })();!(function() { /** * todolist 组件 */ var ToDoList = BI.inherit(BI.Widget, { props: { baseCls: "fine-to-do-list" }, // 生命周期函数,在组件创建前 beforeCreate: function() { // 初始化存储数据 this.list = localStorage.getItem("fine-todolist") ? JSON.parse(localStorage.getItem("fine-todolist")) : []; }, render: function() { var self = this, o = this.options; return { type: "bi.vtape", // vtape布局,顶部高度固定,下部分列表占满高度 items: [ { el: { type: "my.todolist.header", // 顶部组件 listeners: [ { // 监听组件的EVENT_ADD事件,新建todo项 eventName: "EVENT_ADD", action: function(v) { self.addToDo(v); } } ], height: 40 }, height: 40 }, { type: "bi.horizontal_auto", // 水平居中布局 cls: "my-todolist-background", // 添加className items: [ { el: { type: "my.todolist.list", // need todo项列表 ref: function(_ref) { self.todolist = _ref; }, items: this._getNeedTodoList(), text: "正在进行", listeners: [ { // 监听EVENT_CHANGE事件,完成某一项todo eventName: "EVENT_CHANGE", action: function(v) { self.finishTodo(v); } } ], width: 600 } }, { el: { type: "my.todolist.list", // 已经完成的todo项列表 text: "已经完成", items: this._getAlreadyDoneList(), ref: function(_ref) { self.donelist = _ref; }, width: 600 } } ] } ] }; }, _updateLocalStorage: function() { localStorage.setItem("fine-todolist", JSON.stringify(this.list)); }, _getNeedTodoList: function() { return BI.filter(this.list, function(index, item) { return !item.done; }); }, _getAlreadyDoneList: function() { return BI.filter(this.list, function(index, item) { return item.done; }); }, /** * 添加todo项 * @param text todo项的内容 */ addToDo: function(text) { this.list.push({ value: BI.UUID(), text: text, done: false }); this.todolist.populate(this._getNeedTodoList()); this._updateLocalStorage(); }, /** * 完成某一项todo * @param v todo项的value */ finishTodo: function(v) { BI.some(this.list, function(index, item) { if (item.value === v) { item.done = true; } }); this.todolist.populate(this._getNeedTodoList()); this.donelist.populate(this._getAlreadyDoneList()); this._updateLocalStorage(); } }); BI.shortcut("my.todolist", ToDoList); })(); !(function () { /** * 多层级单选树增加无效值时状态,使用BI.config覆盖原组件,只能调用一次 * 新增defaultText参数,表示空默认值,不传默认值为请选择,注意不能替代text,只是为了跟text区分开,text现在包含空默认值和暂不可用值两种情况。 * value存在且不存在于items中,为无效值,文本框标红 * value不存在,text不为defaultText时,为暂不可用值,文本框不变,去除水印 */ BI.config("bi.multilayer_single_tree_combo", function (config) { var ERROR_CLASS = "combo-error"; var WATERMARK_CLASS = "bi-water-mark"; var DEFAULT_TEXT = "请选择"; /** * 判断是否是有效值 * @param {Object} config * @param {String} value setValue传入的值 * @returns {Boolean} */ function isValueValid (options, value) { if (!BI.isObject(options)) { return true; } value = value || options.value; // null/undefined/空字符串作为空值 if (BI.isNull(value) || (value === "")) { return true; } var items = options.items || []; var itemIds = []; // 获取id列表 BI.each(items, function (i, item) { item && item.value && itemIds.push(item.value); }); return BI.contains(itemIds, value); } /** * 增加/去除标红className * @param {Object} widget * @param {String} value setValue传入的值 */ function changeInvalidClassName (widget, value) { if (!BI.isObject(widget)) { return; } var combo = widget.combo; var trigger = widget.textTrigger && widget.textTrigger.trigger && widget.textTrigger.trigger.trigger && widget.textTrigger.trigger.trigger.text && widget.textTrigger.trigger.trigger.text.element; var options = widget.options; var defaultText = options.defaultText || DEFAULT_TEXT; if (isValueValid(options, value)) { combo && combo.element.removeClass(ERROR_CLASS); } else { combo && combo.element.addClass(ERROR_CLASS); } if (options.text !== defaultText) { trigger.removeClass(WATERMARK_CLASS); } } config.listeners = config.listeners || []; // 新增mount生命周期回调 config.listeners.push({ eventName: BI.Events.MOUNT, action: function () { // 覆盖原setValue方法,调用原setValue前,修改样式 var _setValue = this.setValue; this.setValue = function (value) { _setValue.call(this, value); changeInvalidClassName(this, value && value[0]); }; // 立即触发一次样式变更,不需要传value changeInvalidClassName(this); } }); return config; }); var treeItems = [ {id: -1, pId: -2, value: "根目录", text: "根目录"}, {id: 1, pId: -1, value: "第一级目录1", text: "第一级目录1"}, {id: 11, pId: 1, value: "第二级文件1", text: "第二级文件1"}, {id: 12, pId: 1, value: "第二级目录2", text: "第二级目录2"}, {id: 121, pId: 12, value: "第三级目录1", text: "第三级目录1"}, {id: 122, pId: 12, value: "第三级文件1", text: "第三级文件1"}, {id: 1211, pId: 121, value: "第四级目录1", text: "第四级目录1"}, {id: 12111, pId: 1211, value: "第五级文件1", text: "第五级文件111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"}, {id: 2, pId: -1, value: "第一级目录2", text: "第一级目录2"}, {id: 21, pId: 2, value: "第二级目录3", text: "第二级目录3"}, {id: 22, pId: 2, value: "第二级文件2", text: "第二级文件2"}, {id: 211, pId: 21, value: "第三级目录2", text: "第三级目录2"}, {id: 212, pId: 21, value: "第三级文件2", text: "第三级文件2"}, {id: 2111, pId: 211, value: "第四级文件1", text: "第四级文件1"} ]; var TestTreeModel = BI.inherit(Fix.Model, { state: function () { return { items: BI.deepClone(treeItems), value: "第三级文件1" }; }, childContext: ["items"] }); BI.model("dec.amiba.test.tree.model", TestTreeModel); var TestTree = BI.inherit(BI.Widget, { _store: function () { return BI.Models.getModel("dec.amiba.test.tree.model"); }, props: { baseCls: "fine-test-tree" }, watch: { items: function (items) { console.log("items", items); this.treeRef.populate(items); }, value: function (v) { console.log("value", v); } }, render: function () { var self = this, o = this.options; return { type: "bi.vertical", height: 150, lgap: 20, tgap: 20, mounted: function () { // 测试增加树节点 var m = self.model; var newItems = [ {id: 3, pId: -1, value: "第三级目录1", text: "第三级目录1"}, {id: 31, pId: 3, value: "第三级文件1", text: "第三级文件1"} ]; m.items = m.items.concat(newItems); // 测试修改value; setTimeout(function () { console.log("setValue"); self.treeRef.setValue("不存在的值"); }, 3000); }, items: [ { type: "bi.label", textAlign: "left", text: "叶子节点单选" }, { type: "bi.multilayer_single_tree_combo", text: "无效值", defaultText: "无效值", allowEdit: false, items: self.model.items, ref: function (ref) { self.treeRef = ref; }, width: 250, value: self.model.value, listeners: [{ eventName: "EVENT_CHANGE", action: function () { self.model.value = self.treeRef.getValue()[0]; } }] } ] }; } }); BI.shortcut("dec.amiba.test.tree", TestTree); })();!(function () { // 将todolist组件挂载到#wrapper上. // BI.createWidget({ // type: "my.todolist", // element: "#wrapper" // }); // 挂载下拉树测试组件 BI.createWidget({ type: "dec.amiba.test.tree", element: "#wrapper" }); })();