Permalink
Browse files

Clicking on checkbox or radio button now changes the value and

propagated the click event.  If `preventDefault`, the value is
changed back.
  • Loading branch information...
1 parent 3eec41f commit 446d57e512ac4cc040b0651e1101d94c5447ebdc @assaf assaf committed Jan 19, 2012
Showing with 86 additions and 20 deletions.
  1. +3 −0 CHANGELOG.md
  2. +11 −14 lib/zombie/browser.coffee
  3. +43 −6 lib/zombie/forms.coffee
  4. +29 −0 spec/forms_spec.coffee
View
@@ -5,6 +5,9 @@ zombie.js-changelog(7) -- Changelog
`Browser.fire` takes no options (that was an undocumented argument), and always fires events that bubble and can be
cancelled.
+Clicking on checkbox or radio button now changes the value and propagated the click event. If `preventDefault`, the
+value is changed back.
+
## Version 0.12.12 2012-01-16
View
@@ -231,10 +231,10 @@ class Browser extends EventEmitter
type = if name in MOUSE_EVENT_NAMES then "MouseEvents" else "HTMLEvents"
event = @window.document.createEvent(type)
event.initEvent name, true, true
-
@dispatchEvent target, event
if callback
- @wait callback
+ @wait (error, browser)->
+ callback error, browser, event
else
return this
@@ -266,6 +266,8 @@ class Browser extends EventEmitter
context.querySelector(selector)
else
return context
+ $$: (selector, context)->
+ return @query(selector, context)
# ### browser.querySelector(selector) => Element
#
@@ -514,9 +516,10 @@ class Browser extends EventEmitter
if field.getAttribute("readonly")
throw new Error("This INPUT field is readonly")
if field.checked ^ value
- @fire "click", field, callback
- else if callback
- callback null, false
+ field.click()
+
+ if callback
+ @wait callback
else
return this
else
@@ -552,16 +555,10 @@ class Browser extends EventEmitter
choose: (selector, callback)->
field = @field(selector) || @field("input[type=radio][value=\"#{escape(selector)}\"]")
if field && field.tagName == "INPUT" && field.type == "radio" && field.form
- if !field.checked
- radios = @querySelectorAll(":radio[name='#{field.getAttribute("name")}']", field.form)
- for radio in radios
- radio.checked = false unless radio.getAttribute("disabled") || radio.getAttribute("readonly")
- field.checked = true
- @fire "click", field
- @fire "change", field, callback
+ field.click()
+ if callback
+ @wait callback
else
- @fire "click", field, callback
- unless callback
return this
else
throw new Error("No radio INPUT matching '#{selector}'")
View
@@ -109,9 +109,7 @@ HTML.HTMLInputElement.prototype._eventDefaults =
if form = input.form
form._dispatchSubmitEvent input
when "checkbox"
- unless input.getAttribute("readonly")
- input.checked = !input.checked
- change()
+ change()
when "radio"
unless input.getAttribute("readonly")
input.checked = true
@@ -121,9 +119,48 @@ HTML.HTMLInputElement.prototype._eventDefaults =
# ignore all other clicks. We need those other clicks to occur, so we're going
# to dispatch them all.
HTML.HTMLInputElement.prototype.click = ->
- event = @ownerDocument.createEvent("HTMLEvents")
- event.initEvent "click", true, true
- @ownerDocument.parentWindow.browser.dispatchEvent this, event
+ # First event we fire is click event
+ click = =>
+ event = @ownerDocument.createEvent("HTMLEvents")
+ event.initEvent "click", true, true
+ @ownerDocument.parentWindow.browser.dispatchEvent this, event
+ return !event._preventDefault
+
+ # If that works out, we follow with a change event
+ change = =>
+ event = @ownerDocument.createEvent("HTMLEvents")
+ event.initEvent "change", true, true
+ @ownerDocument.parentWindow.browser.dispatchEvent this, event
+
+ switch @type
+ when "checkbox"
+ unless @getAttribute("readonly")
+ original = @checked
+ @checked = !@checked
+ if click()
+ change()
+ else
+ @checked = original
+ when "radio"
+ unless @getAttribute("readonly")
+ if !@checked
+ radios = @ownerDocument.querySelectorAll(":radio[name='#{@getAttribute("name")}']", @form)
+ checked = null
+ for radio in radios
+ if radio.checked
+ checked = radio
+ radio.checked = false
+ @checked = true
+ if click()
+ change()
+ else
+ for radio in radios
+ radio.checked = radio == checked
+ else
+ click()
+ else
+ click()
+ return
# Default behavior for form BUTTON: submit form.
HTML.HTMLButtonElement.prototype._eventDefaults =
View
@@ -85,6 +85,9 @@ Vows.describe("Forms").addBatch(
<input type="image" name="image" id="image_submit" value="Image Submit">
<button name="button" value="hit-me">Hit Me</button>
+
+ <input type="checkbox" id="field-prevent-check">
+ <input type="radio" id="field-prevent-radio">
</form>
</body>
</html>
@@ -242,6 +245,19 @@ Vows.describe("Forms").addBatch(
"should callback": (_, browser)->
assert.ok !browser.querySelector("#field-check").checked
+ "prevent default":
+ topic: (browser)->
+ check_box = browser.$$("#field-prevent-check")
+ values = [check_box.checked]
+ check_box.addEventListener "click", (event)=>
+ values.push check_box.checked
+ event.preventDefault()
+ browser.check check_box, =>
+ values.push check_box.checked
+ @callback null, values
+ "should turn checkbox on then off": (values)->
+ assert.deepEqual values, [false, true, false]
+
"radio buttons":
Browser.wants "http://localhost:3003/forms/form"
@@ -279,6 +295,19 @@ Vows.describe("Forms").addBatch(
"should uncheck other radio": (browser)->
assert.ok !browser.querySelector("#field-scary").checked
+ "prevent default":
+ topic: (browser)->
+ radio = browser.$$("#field-prevent-radio")
+ values = [radio.checked]
+ radio.addEventListener "click", (event)=>
+ values.push radio.checked
+ event.preventDefault()
+ browser.choose radio, =>
+ values.push radio.checked
+ @callback null, values
+ "should turn radio on then off": (values)->
+ assert.deepEqual values, [false, true, false]
+
"select option":
Browser.wants "http://localhost:3003/forms/form"

0 comments on commit 446d57e

Please sign in to comment.