From 5b1e97872831ab828d4331dbb9e447c7c749e53d Mon Sep 17 00:00:00 2001 From: Bill Keese Date: Thu, 27 Aug 2015 11:04:47 +0900 Subject: [PATCH] FormWidget: add afterFormResetCallback() method. The default FormWidget and FormValueWidget afterFormResetCallback() methods reset the widget according to the value (or checked property) of this.valueNode. Strangely, there's no code in FormWidget and FormValueWidget to do that on initialization. That should be added in the future. Also, the original code in deliteful got the form reference from this.valueNode.form, but that assumes that the widget is rendered before attachedCallback(), which won't always be true (see #404). So instead, I'm just tracing up the DOM tree for the nearest
ancestor. Fixes #423, refs ibm-js/deliteful#584. --- FormValueWidget.js | 9 ++- FormWidget.js | 29 +++++++++ tests/functional/FormValueWidget.html | 85 +++++++++++++++++++++++++++ tests/functional/FormValueWidget.js | 40 +++++++++++++ tests/functional/all.js | 1 + 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 tests/functional/FormValueWidget.html create mode 100644 tests/functional/FormValueWidget.js diff --git a/FormValueWidget.js b/FormValueWidget.js index eaecd79cf4..85f3b21543 100644 --- a/FormValueWidget.js +++ b/FormValueWidget.js @@ -132,6 +132,13 @@ define([ * @function * @protected */ - handleOnInput: genHandler("input", "_previousOnInputValue", "_onInputHandle") + handleOnInput: genHandler("input", "_previousOnInputValue", "_onInputHandle"), + + afterFormResetCallback: function () { + console.log(this.id, "FormValueWidget#afterFormResetCallback"); + if (this.value !== this.valueNode.value) { + this.value = this.valueNode.value; + } + } }); }); diff --git a/FormWidget.js b/FormWidget.js index 478f70e958..ed531ebfb3 100644 --- a/FormWidget.js +++ b/FormWidget.js @@ -239,6 +239,35 @@ define([ HTMLElement.prototype.removeAttribute.call(this, attr.name); } } + }, + + attachedCallback: function () { + // If the widget is in a form, reset the initial value of the widget when the form is reset. + for (var form = this.parentNode; form; form = form.parentNode) { + if (/^form$/i.test(form.tagName)) { + this.on("reset", function () { + this.defer(function () { + this.afterFormResetCallback(); + }); + }.bind(this), form); + break; + } + } + }, + + /** + * Callback after `` containing this widget is reset. + * By the time this callback executes, `this.valueNode.value` will have already been reset according to + * the form's original value. + * + * @protected + */ + afterFormResetCallback: function () { + if (this.checked !== this.valueNode.checked) { + this.checked = this.valueNode.checked; + } } }); }); + + diff --git a/tests/functional/FormValueWidget.html b/tests/functional/FormValueWidget.html new file mode 100644 index 0000000000..8e6db6997f --- /dev/null +++ b/tests/functional/FormValueWidget.html @@ -0,0 +1,85 @@ + + + + + + + FormValueWidget + + + + + + + + +

FormValueWidget functional test

+ + + Spinner widget based on FormValueWidget: + + +
+ + + +
+ Clicking the reset button should put the spinner's value back to 5 +
+ + \ No newline at end of file diff --git a/tests/functional/FormValueWidget.js b/tests/functional/FormValueWidget.js new file mode 100644 index 0000000000..debf61edf4 --- /dev/null +++ b/tests/functional/FormValueWidget.js @@ -0,0 +1,40 @@ +define([ + "require", + "intern", + "intern!object", + "intern/chai!assert", + "intern/dojo/node!leadfoot/keys", + "intern/dojo/node!leadfoot/helpers/pollUntil" +], function (require, intern, registerSuite, assert, keys, pollUntil) { + + registerSuite({ + name: "FormValueWidget functional tests", + + setup: function () { + return this.remote + .get(require.toUrl("./FormValueWidget.html")) + .then(pollUntil("return ready || null;", [], + intern.config.WAIT_TIMEOUT, intern.config.POLL_INTERVAL)); + }, + + reset: function () { + this.timeout = intern.config.TEST_TIMEOUT; + var environmentType = this.remote.environmentType; + if (environmentType.browserName === "internet explorer") { + return this.skip("click() doesn't generate mousedown/mouseup, so popup won't open"); + } + return this.remote.findByCssSelector("my-spinner .increment") + .click() + .end() + .execute("return spinner1.value").then(function (value) { + assert.equal(value, 6, "incremented value"); // use equal() to ignore string vs. number diff + }) + .findByCssSelector("#resetB") + .click() + .end() + .execute("return spinner1.value").then(function (value) { + assert.equal(value, 5, "reset value"); // use equal() to ignore string vs. number diff + }); + } + }); +}); diff --git a/tests/functional/all.js b/tests/functional/all.js index 4babcd704d..9c324f09c5 100644 --- a/tests/functional/all.js +++ b/tests/functional/all.js @@ -3,6 +3,7 @@ define([ "./activationTracker", "./Widget", "./DialogUnderlay", + "./FormValueWidget", "./HasDropDown", "./TabIndex", "./KeyNav",