fix attribute syncing for input, select, textarea

optimize events
This commit is contained in:
Leo Horie 2016-05-10 01:55:48 -04:00
parent 4a215a2815
commit d5371533a7
7 changed files with 503 additions and 32 deletions

View file

@ -163,6 +163,10 @@ module.exports = function() {
}
},
dispatchEvent: function(e) {
if (this.nodeName === "INPUT" && this.attributes["type"] != null && this.attributes["type"].nodeValue === "checkbox" && e.type === "click") {
this.checked = !this.checked
}
e.target = this
if (events[e.type] != null) {
for (var i = 0; i < events[e.type].length; i++) {
@ -172,6 +176,7 @@ module.exports = function() {
if (typeof this["on" + e.type] === "function" && !isModernEvent(e.type)) this["on" + e.type](e)
},
}
if (element.nodeName === "A") {
var href
Object.defineProperty(element, "href", {
@ -180,6 +185,7 @@ module.exports = function() {
enumerable: true,
})
}
if (element.nodeName === "INPUT") {
var checked
Object.defineProperty(element, "checked", {
@ -187,6 +193,98 @@ module.exports = function() {
set: function(value) {checked = Boolean(value)},
enumerable: true,
})
element.value = ""
}
if (element.nodeName === "TEXTAREA") {
var value
Object.defineProperty(element, "value", {
get: function() {
return value != null ? value :
this.firstChild ? this.firstChild.nodeValue : ""
},
set: function(v) {value = v},
enumerable: true,
})
}
function getOptions(element) {
var options = []
for (var i = 0; i < element.childNodes.length; i++) {
if (element.childNodes[i].nodeName === "OPTION") options.push(element.childNodes[i])
else if (element.childNodes[i].nodeName === "OPTGROUP") options = options.concat(getOptions(element.childNodes[i]))
}
return options
}
function getOptionValue(element) {
return element.attributes["value"] != null ?
element.attributes["value"].nodeValue :
element.firstChild != null ? element.firstChild.nodeValue : ""
}
if (element.nodeName === "SELECT") {
var selectedValue, selectedIndex = 0
Object.defineProperty(element, "selectedIndex", {
get: function() {return getOptions(this).length > 0 ? selectedIndex : -1},
set: function(value) {
var options = getOptions(this)
if (value >= 0 && value < options.length) {
selectedValue = getOptionValue(options[selectedIndex])
selectedIndex = value
}
else {
selectedValue = ""
selectedIndex = -1
}
},
enumerable: true,
})
Object.defineProperty(element, "value", {
get: function() {
if (this.selectedIndex > -1) return getOptionValue(getOptions(this)[this.selectedIndex])
return ""
},
set: function(value) {
var options = getOptions(this)
var stringValue = String(value)
for (var i = 0; i < options.length; i++) {
if (getOptionValue(options[i]) === stringValue) {
selectedValue = stringValue
selectedIndex = i
return
}
}
selectedValue = stringValue
selectedIndex = -1
},
enumerable: true,
})
}
if (element.nodeName === "OPTION") {
Object.defineProperty(element, "value", {
get: function() {return getOptionValue(this)},
set: function(value) {
this.setAttribute("value", value)
},
enumerable: true,
})
Object.defineProperty(element, "selected", {
get: function() {
var options = getOptions(this.parentNode)
var index = options.indexOf(this)
if (index > -1) return index === this.parentNode.selectedIndex
return false
},
set: function(value) {
if (value) {
var options = getOptions(this.parentNode)
var index = options.indexOf(this)
if (index > -1) this.parentNode.selectedIndex = index
}
else this.parentNode.selectedIndex = 0
},
enumerable: true,
})
}
return element
},

View file

@ -553,7 +553,7 @@ o.spec("domMock", function() {
})
})
o.spec("attributes", function() {
o.spec("link href", function() {
o.spec("a[href]", function() {
o("is empty string if no attribute", function() {
var a = $document.createElement("a")
@ -575,7 +575,7 @@ o.spec("domMock", function() {
o(a.attributes["href"].nodeValue).equals("")
})
})
o.spec("input checked", function() {
o.spec("input[checked]", function() {
o("only exists in input elements", function() {
var input = $document.createElement("input")
var a = $document.createElement("a")
@ -616,6 +616,195 @@ o.spec("domMock", function() {
o(input.checked).equals(true)
})
o("toggles on click", function() {
var input = $document.createElement("input")
input.setAttribute("type", "checkbox")
input.checked = false
var e = $document.createEvent("MouseEvents")
e.initEvent("click", true, true)
input.dispatchEvent(e)
o(input.checked).equals(true)
})
})
o.spec("input[value]", function() {
o("only exists in input elements", function() {
var input = $document.createElement("input")
var a = $document.createElement("a")
o("value" in input).equals(true)
o("value" in a).equals(false)
})
})
o.spec("textarea[value]", function() {
o("reads from child if no value", function() {
var input = $document.createElement("textarea")
input.appendChild($document.createTextNode("aaa"))
o(input.value).equals("aaa")
})
o("ignores child if value set", function() {
var input = $document.createElement("textarea")
input.value = "aaa"
input.setAttribute("value", "bbb")
o(input.value).equals("aaa")
})
})
o.spec("select[value] and select[selectedIndex]", function() {
o("only exist in select elements", function() {
var select = $document.createElement("select")
var a = $document.createElement("a")
o("value" in select).equals(true)
o("value" in a).equals(false)
o("selectedIndex" in select).equals(true)
o("selectedIndex" in a).equals(false)
})
o("value defaults to value at first index", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
o(select.value).equals("a")
o(select.selectedIndex).equals(0)
})
o("value falls back to child nodeValue if no attribute", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.appendChild($document.createTextNode("a"))
select.appendChild(option1)
o(select.value).equals("a")
o(select.selectedIndex).equals(0)
})
o("value defaults to invalid if no options", function() {
var select = $document.createElement("select")
o(select.value).equals("")
o(select.selectedIndex).equals(-1)
})
o("setting valid value works", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
select.value = "b"
o(select.value).equals("b")
o(select.selectedIndex).equals(1)
})
o("setting valid selectedIndex works", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
select.selectedIndex = 1
o(select.value).equals("b")
o(select.selectedIndex).equals(1)
})
o("setting option[selected] works", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
select.childNodes[1].selected = true
o(select.value).equals("b")
o(select.selectedIndex).equals(1)
})
o("setting invalid value yields a selectedIndex of -1 and value of empty string", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
select.value = "c"
o(select.value).equals("")
o(select.selectedIndex).equals(-1)
})
o("setting invalid selectedIndex yields a selectedIndex of -1 and value of empty string", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "b")
select.appendChild(option2)
select.selectedIndex = -2
o(select.value).equals("")
o(select.selectedIndex).equals(-1)
})
o("setting invalid value yields a selectedIndex of -1 and value of empty string even when there's an option whose value is empty string", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "")
select.appendChild(option2)
select.value = "c"
o(select.value).equals("")
o(select.selectedIndex).equals(-1)
})
o("setting invalid selectedIndex yields a selectedIndex of -1 and value of empty string even when there's an option whose value is empty string", function() {
var select = $document.createElement("select")
var option1 = $document.createElement("option")
option1.setAttribute("value", "a")
select.appendChild(option1)
var option2 = $document.createElement("option")
option2.setAttribute("value", "")
select.appendChild(option2)
select.selectedIndex = -2
o(select.value).equals("")
o(select.selectedIndex).equals(-1)
})
})
})
})