diff --git a/render/render.js b/render/render.js index 0b8cad97..844d766a 100644 --- a/render/render.js +++ b/render/render.js @@ -483,7 +483,7 @@ module.exports = function($window) { if (key === "value") { var normalized = "" + value // eslint-disable-line no-implicit-coercion //setting input[value] to same value by typing on focused element moves cursor to end in Chrome - if (vnode.tag === "input" && vnode.dom.value === normalized && vnode.dom === $doc.activeElement) return + if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === normalized && vnode.dom === $doc.activeElement) return //setting select[value] to same value while having select open blinks select dropdown in Chrome if (vnode.tag === "select") { if (value === null) { diff --git a/render/tests/test-attributes.js b/render/tests/test-attributes.js index 64a3fdfd..fcc7f150 100644 --- a/render/tests/test-attributes.js +++ b/render/tests/test-attributes.js @@ -288,6 +288,43 @@ o.spec("attributes", function() { // o(b.dom.value).equals("") }) + o("isn't set when equivalent to the previous value and focused", function() { + var $window = domMock({spy: o.spy}) + var root = $window.document.body + var render = vdom($window).render + + var a = {tag: "textarea"} + var b = {tag: "textarea", attrs: {value: "1"}} + var c = {tag: "textarea", attrs: {value: "1"}} + var d = {tag: "textarea", attrs: {value: 1}} + var e = {tag: "textarea", attrs: {value: 2}} + + render(root, [a]) + var spies = $window.__getSpies(a.dom) + a.dom.focus() + + o(spies.valueSetter.callCount).equals(0) + + render(root, [b]) + + o(b.dom.value).equals("1") + o(spies.valueSetter.callCount).equals(1) + + render(root, [c]) + + o(c.dom.value).equals("1") + o(spies.valueSetter.callCount).equals(1) + + render(root, [d]) + + o(d.dom.value).equals("1") + o(spies.valueSetter.callCount).equals(1) + + render(root, [e]) + + o(d.dom.value).equals("2") + o(spies.valueSetter.callCount).equals(2) + }) }) o.spec("link href", function() { o("when link href is true, attribute is present", function() { diff --git a/test-utils/domMock.js b/test-utils/domMock.js index ad0c669d..060ba4f7 100644 --- a/test-utils/domMock.js +++ b/test-utils/domMock.js @@ -345,18 +345,22 @@ module.exports = function(options) { if (element.nodeName === "TEXTAREA") { var wasNeverSet = true var value = "" + var valueSetter = spy(function(v) { + wasNeverSet = false + /*eslint-disable no-implicit-coercion*/ + value = v === null ? "" : "" + v + /*eslint-enable no-implicit-coercion*/ + }) Object.defineProperty(element, "value", { get: function() { return wasNeverSet && this.firstChild ? this.firstChild.nodeValue : value }, - set: function(v) { - wasNeverSet = false - /*eslint-disable no-implicit-coercion*/ - value = v === null ? "" : "" + v - /*eslint-enable no-implicit-coercion*/ - }, + set: valueSetter, enumerable: true, }) + registerSpies(element, { + valueSetter: valueSetter + }) } /* eslint-disable radix */ diff --git a/test-utils/tests/test-domMock.js b/test-utils/tests/test-domMock.js index e56b3c04..a5829458 100644 --- a/test-utils/tests/test-domMock.js +++ b/test-utils/tests/test-domMock.js @@ -1237,5 +1237,21 @@ o.spec("domMock", function() { o(spies.valueSetter.this).equals(option) o(spies.valueSetter.args[0]).equals("aaa") }) + o("textarea elements have spies on value setters", function() { + var textarea = $window.document.createElement("textarea") + + var spies = $window.__getSpies(textarea) + + o(typeof spies).equals("object") + o(spies).notEquals(null) + o(typeof spies.valueSetter).equals("function") + o(spies.valueSetter.callCount).equals(0) + + textarea.value = "aaa" + + o(spies.valueSetter.callCount).equals(1) + o(spies.valueSetter.this).equals(textarea) + o(spies.valueSetter.args[0]).equals("aaa") + }) }) })