fix attribute syncing for input, select, textarea
optimize events
This commit is contained in:
parent
4a215a2815
commit
d5371533a7
7 changed files with 503 additions and 32 deletions
|
|
@ -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
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue