From 2bd1fe41fcbcf3134cb043031ed32655cd493373 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 10 Aug 2017 02:14:34 +0400 Subject: [PATCH] fix forms not updating and add tests --- plugins/c9.ide.dialog.common/error_test.js | 8 -- plugins/c9.ide.dialog/dialog.js | 5 +- plugins/c9.ide.dialog/dialog_test.js | 76 ++++++++++ .../c9.ide.preferences/preferences_test.js | 36 +++-- plugins/c9.ide.ui/forms.js | 132 ++++++++---------- plugins/c9.ide.ui/lib_apf.js | 13 +- 6 files changed, 166 insertions(+), 104 deletions(-) create mode 100644 plugins/c9.ide.dialog/dialog_test.js diff --git a/plugins/c9.ide.dialog.common/error_test.js b/plugins/c9.ide.dialog.common/error_test.js index c6093a99..a6bc20a9 100644 --- a/plugins/c9.ide.dialog.common/error_test.js +++ b/plugins/c9.ide.dialog.common/error_test.js @@ -18,14 +18,6 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) staticPrefix: "plugins/c9.ide.layout.classic" }, - // Mock plugins - { - consumes: [], - provides: [ - "util", "settings", "c9", "dialog.alert", "commands", "dialog.question" - ], - setup: expect.html.mocked - }, { consumes: ["dialog.error"], provides: [], diff --git a/plugins/c9.ide.dialog/dialog.js b/plugins/c9.ide.dialog/dialog.js index 6efe46fb..8035a9b9 100644 --- a/plugins/c9.ide.dialog/dialog.js +++ b/plugins/c9.ide.dialog/dialog.js @@ -242,14 +242,11 @@ define(function(require, module, exports) { dropdown.setAttribute("value", item.value); break; default: - // supported attributes - var validAttributes = /^(value|visible|zindex|disabled|caption|tooltip|command|class|icon|src|submenu)$/; Object.keys(item).forEach(function(key) { // Check for onclick explictly if (key === "onclick") return el.onclick = item.onclick; - // Check for attributes we know exist and will directly set - if (validAttributes.test(key)) + if (key != "id") return el.setAttribute(key, item[key]); }); break; diff --git a/plugins/c9.ide.dialog/dialog_test.js b/plugins/c9.ide.dialog/dialog_test.js new file mode 100644 index 00000000..9bb411dc --- /dev/null +++ b/plugins/c9.ide.dialog/dialog_test.js @@ -0,0 +1,76 @@ +/*global describe, it, after */ + +"use client"; + +require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) { + var expect = chai.expect; + + expect.setupArchitectTest([ + "plugins/c9.ide.ui/lib_apf", + { + packagePath: "plugins/c9.ide.ui/ui", + staticPrefix: "plugins/c9.ide.ui" + }, + + "plugins/c9.core/ext", + { + packagePath: "plugins/c9.ide.dialog/dialog", + staticPrefix: "plugins/c9.ide.layout.classic" + }, + + { + consumes: ["Dialog"], + provides: [], + setup: main + } + ], architect); + + function main(options, imports, register) { + var Dialog = imports.Dialog; + var d; + + describe('layout', function() { + it('should update items', function(done) { + d = new Dialog('', [], { + elements: [{ + type: "checkbox", + id: "foobar", + caption: "foo bar", + checked: false + }] + }); + d.show(); + setTimeout(function() { + expect.html(d.aml.$html).visible; + expect.html(d.aml.$html.querySelector(".cbcontainer:not(.checked)")).visible; + expect.html(d.aml.$html).text("foo bar"); + expect(d.aml.$html.querySelector(".cbcontainer.cbcontainerChecked")).to.not.ok; + d.update([{ id: "foobar", caption: "updated", checked: true }]); + setTimeout(function() { + expect.html(d.aml.$html.querySelector(".cbcontainer.cbcontainerChecked")).to.ok; + d.hide(); + setTimeout(function() { + expect.html(d.aml.$html).not.visible; + done(); + }); + }); + }); + }); + }); + + if (!onload.remain) { + describe("unload()", function() { + it('should destroy all ui elements when it is unloaded', function() { + d.unload(); + }); + }); + + after(function(done) { + document.body.style.marginBottom = ""; + done(); + }); + } + + onload && onload(); + } +}); \ No newline at end of file diff --git a/plugins/c9.ide.preferences/preferences_test.js b/plugins/c9.ide.preferences/preferences_test.js index 70bbeaa4..b3246f04 100644 --- a/plugins/c9.ide.preferences/preferences_test.js +++ b/plugins/c9.ide.preferences/preferences_test.js @@ -168,26 +168,34 @@ require([ tabs.openEditor("preferences", function(err, tab) { expect(tabs.getTabs()).length(1); + var checkbox = Array.apply( + null, tab.editor.aml.$ext.querySelectorAll(".hsplitbox>.label") + ).filter(function(e) { + return /ui animation/i.test(e.textContent); + })[0].nextSibling.host; + + expect(checkbox.getValue()).to.equal(true); + expect(checkbox.$ext.className).to.match(/checked/i) + expect(settings.get("user/general/@animateui")).to.equal(true); + settings.set("user/general/@animateui", false); + expect(settings.get("user/general/@animateui")).to.equal(false); + expect(checkbox.getValue()).to.equal(false); + expect(checkbox.$ext.className).to.not.match(/checked/i) done(); }); }); }); - describe("unload()", function() { - it('should unload the preferences', function(done) { - general.unload(); - prefs.unload(); - tabs.getTabs()[0].editor.unload(); - tabs.getTabs()[0].unload(); - tabs.unload(); - done(); - }); - }); - if (!onload.remain) { - after(function(done) { - document.body.style.marginBottom = ""; - done(); + describe("unload()", function() { + it('should unload the preferences', function(done) { + general.unload(); + prefs.unload(); + tabs.getTabs()[0].editor.unload(); + tabs.getTabs()[0].unload(); + tabs.unload(); + done(); + }); }); } }); diff --git a/plugins/c9.ide.ui/forms.js b/plugins/c9.ide.ui/forms.js index 2e656092..943491c4 100644 --- a/plugins/c9.ide.ui/forms.js +++ b/plugins/c9.ide.ui/forms.js @@ -161,45 +161,56 @@ define(function(require, exports, module) { options.path = options.setting; if (debug) - name = "\\[" + (position || "") + "\\] " + name; + name = "[" + (position || "") + "] " + name; + var ignoreChange = false; + function onAfterChange(e) { + if (ignoreChange) + return; + if (options.path) + settings.set(options.path, e.value); + + if (options.onchange) + options.onchange({ value: e.value, type: e.currentTarget.tagName }); + } + function addSettingListener(path, item, plugin) { + if (path && item) { + var update = function() { + ignoreChange = true; + item.setValue(settings.get(path)); + ignoreChange = false; + }; + settings.on(path, update, plugin); + settings.on("read", update, plugin); + } + } + + var main, secondary; switch (options.type) { case "checkbox": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.checkbox({ + main = new ui.checkbox({ value: options.path ? settings.get(options.path) : (options.defaultValue || ""), values: options.values, skin: "cboffline", - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - - if (options.onchange) - options.onchange({ value: e.value }); - } + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; case "dropdown": - var dd; childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - dd = new ui.dropdown({ + main = new ui.dropdown({ items: options.items, width: options.width || widths.dropdown, skin: "black_dropdown", margin: "-1 0 0 0", zindex: 100, - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - - if (options.onchange) - options.onchange({ value: e.value || e.args[2] }); - }, + onafterchange: onAfterChange, value: options.path ? settings.get(options.path) : (options.defaultValue || ""), @@ -207,15 +218,11 @@ define(function(require, exports, module) { "empty-message": options["empty-message"] }) ]; - - settings.on(options.path, function() { - dd.setValue(settings.get(options.path)); - }, plugin); break; case "spinner": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.spinner({ + main = new ui.spinner({ width: options.width || widths.spinner, value: options.path ? settings.get(options.path) @@ -223,32 +230,24 @@ define(function(require, exports, module) { min: options.min || 0, max: options.max || 10, realtime: typeof options.realtime !== "undefined" ? options.realtime : 1, - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - if (options.onchange) - options.onchange({ value: e.value }); - }, + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; case "checked-spinner": childNodes = [ - new ui.checkbox({ + secondary = new ui.checkbox({ value: options.checkboxPath ? settings.get(options.checkboxPath) : (options.defaultCheckboxValue || ""), width: width, maxwidth: maxwidth, label: name + ":", skin: "checkbox_black", - onafterchange: function(e) { - if (options.checkboxPath) - settings.set(options.checkboxPath, e.value); - if (options.onchange) - options.onchange({ value: e.value, type: "checkbox" }); - }, + onafterchange: onAfterChange, + settingPath: options.checkboxPath, }), - new ui.spinner({ + main = new ui.spinner({ width: options.width || widths["checked-spinner"], value: options.path ? settings.get(options.path) @@ -256,37 +255,29 @@ define(function(require, exports, module) { min: options.min || 0, max: options.max || 10, realtime: typeof options.realtime !== "undefined" ? options.realtime : 1, - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - if (options.onchange) - options.onchange({ value: e.value, type: "spinner" }); - }, + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; case "checkbox-single": childNodes = [ - new ui.checkbox({ + main = new ui.checkbox({ value: options.path ? settings.get(options.path) : (options.defaultValue || ""), width: options.width || widths["checked-single"], label: name, skin: "checkbox_black", - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - if (options.onchange) - options.onchange({ value: e.value }); - } + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; case "textbox": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.textbox({ + main = new ui.textbox({ skin: skins.textbox || "searchbox", margin: "-3 0 0 0", "initial-message": options.message || "", @@ -295,19 +286,15 @@ define(function(require, exports, module) { ? settings.get(options.path) : (options.defaultValue || ""), realtime: typeof options.realtime !== "undefined" ? options.realtime : 1, - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - if (options.onchange) - options.onchange({ value: e.value }); - }, + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; case "password": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.password({ + main = new ui.password({ skin: skins.password || "forminput", width: options.width || widths.password, value: options.path @@ -320,18 +307,14 @@ define(function(require, exports, module) { case "colorbox": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.colorbox({ + main = new ui.colorbox({ width: options.width || widths.colorbox, value: options.path ? settings.get(options.path) : (options.defaultValue || ""), realtime: typeof options.realtime !== "undefined" ? options.realtime : 1, - onafterchange: function(e) { - if (options.path) - settings.set(options.path, e.value); - if (options.onchange) - options.onchange({ value: e.value }); - }, + onafterchange: onAfterChange, + settingPath: options.path, }) ]; break; @@ -386,7 +369,7 @@ define(function(require, exports, module) { case "textarea": childNodes = [ new ui.label({ width: width, maxwidth: maxwidth, caption: name + ":" }), - new ui.textarea({ + main = new ui.textarea({ width: options.width || widths.textarea, height: options.height || 200, value: options.path @@ -405,7 +388,7 @@ define(function(require, exports, module) { type: options.type, childNodes: [ new ui.label({ height: 40, caption: name + ":" }), - new ui.textarea({ + main = new ui.textarea({ width: options.width || widths.textarea, height: options.height || 200, style: options.fixedFont @@ -414,7 +397,9 @@ define(function(require, exports, module) { value: options.path ? settings.get(options.path) : (options.defaultValue || ""), - realtime: typeof options.realtime !== "undefined" ? options.realtime : 1 + realtime: typeof options.realtime !== "undefined" ? options.realtime : 1, + onafterchange: onAfterChange, + settingPath: options.path, }) ] }); @@ -423,8 +408,7 @@ define(function(require, exports, module) { node = options.node; break; default: - throw new Error("Unknown form element type: " - + options.type); + throw new Error("Unknown form element type: " + options.type); } if (!node) { @@ -446,6 +430,9 @@ define(function(require, exports, module) { foreign.addElement(node); + addSettingListener(options.path, main, foreign || plugin); + addSettingListener(options.checkboxPath, secondary, foreign || plugin); + return node; } @@ -463,14 +450,11 @@ define(function(require, exports, module) { dropdown.setAttribute("value", item.value); break; default: - // supported attributes - var validAttributes = /^(value|visible|zindex|disabled|caption|tooltip|command|class|icon|src|submenu)$/; Object.keys(item).forEach(function(key) { // Check for onclick explictly if (key === "onclick") return el.onclick = item.onclick; - // Check for attributes we know exist and will directly set - if (validAttributes.test(key)) + if (key != "id") return el.setAttribute(key, item[key]); }); break; diff --git a/plugins/c9.ide.ui/lib_apf.js b/plugins/c9.ide.ui/lib_apf.js index 896593e7..94ed7062 100644 --- a/plugins/c9.ide.ui/lib_apf.js +++ b/plugins/c9.ide.ui/lib_apf.js @@ -13049,10 +13049,7 @@ apf.checkbox = function(struct, tagName) { this.checked = apf.isTrue(value); } - if (this.checked) - apf.setStyleClass(this.$ext, this.$baseCSSname + "Checked"); - else - apf.setStyleClass(this.$ext, "", [this.$baseCSSname + "Checked"]); + this.updateClass(); }; /** @@ -13191,7 +13188,15 @@ apf.checkbox = function(struct, tagName) { this.$notfromext = this.$input && this.$input != this.$ext; this.$setupEvents(); + this.updateClass(); }; + + this.updateClass = function() { + if (this.checked) + apf.setStyleClass(this.$ext, this.$baseCSSname + "Checked"); + else + apf.setStyleClass(this.$ext, "", [this.$baseCSSname + "Checked"]); + } this.$childProperty = "label";