Skip to content
This repository has been archived by the owner on Dec 16, 2023. It is now read-only.

Commit

Permalink
Both focus and blur methods now work.
Browse files Browse the repository at this point in the history
You can also get the activeElement.
  • Loading branch information
assaf committed May 25, 2012
1 parent 3a69400 commit 7a2ce28
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 94 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,11 @@ Tweak to in-line script processing to fix a problem no one reported.
Fire `focus` and `blur` events when filling fields, selecting fields, pressing
button and switching windows.

Both `focus` and `blur` methods now work and you can get the `activeElement`.

513 tests
12.9 sec to complete


## Version 1.1.5 2012-05-24

Expand Down
10 changes: 5 additions & 5 deletions lib/zombie/browser.coffee
Expand Up @@ -521,7 +521,7 @@ class Browser extends EventEmitter
throw new Error("This INPUT field is disabled")
if field.getAttribute("readonly")
throw new Error("This INPUT field is readonly")
@window._focused = field
field.focus()
field.value = value
@fire "change", field, callback
return this
Expand Down Expand Up @@ -613,7 +613,7 @@ class Browser extends EventEmitter
if option && !option.getAttribute("selected")
select = @xpath("./ancestor::select", option).value[0]
option.setAttribute("selected", "selected")
@window._focused = select
select.focus()
@fire "change", select, callback
else if callback
process.nextTick ->
Expand Down Expand Up @@ -645,7 +645,7 @@ class Browser extends EventEmitter
unless select.multiple
throw new Error("Cannot unselect in single select")
option.removeAttribute("selected")
@window._focused = select
select.focus()
@fire "change", select, callback
else if callback
process.nextTick ->
Expand All @@ -670,7 +670,7 @@ class Browser extends EventEmitter
field.files ||= []
field.files.push file
field.value = filename
@window._focused = field
field.focus()
@fire "change", field, callback
return this

Expand Down Expand Up @@ -703,7 +703,7 @@ class Browser extends EventEmitter
throw new Error("No BUTTON '#{selector}'")
if button.getAttribute("disabled")
throw new Error("This button is disabled")
@window._focused = button
button.focus()
return @fire("click", button, callback)

# ### browser.focused => element
Expand Down
29 changes: 27 additions & 2 deletions lib/zombie/forms.coffee
Expand Up @@ -123,13 +123,13 @@ 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 = ->
focus(@ownerDocument, this)

# First event we fire is click event
click = =>
event = @ownerDocument.createEvent("HTMLEvents")
event.initEvent "click", true, true
cancelled = @ownerDocument.parentWindow.browser.dispatchEvent(this, event)
unless cancelled
@ownerDocument.parentWindow._focused = this
return !cancelled

# If that works out, we follow with a change event
Expand Down Expand Up @@ -187,3 +187,28 @@ HTML.Document.prototype._elementBuilders["button"] = (doc, s)->
button = new HTML.HTMLButtonElement(doc, s)
button.type ||= "submit"
return button


# The element in focus.
HTML.HTMLDocument.prototype.__defineGetter__ "activeElement", ->
return document._focused

# Change the current element in focus
focus = (document, element)->
unless element == document._focused
if document._focused
onblur = document.createEvent("HTMLEvents")
onblur.initEvent "blur", false, false
document._focused.dispatchEvent onblur
if element
onfocus = document.createEvent("HTMLEvents")
onfocus.initEvent "focus", false, false
element.dispatchEvent onfocus
document._focused = element

for element in [HTML.HTMLInputElement, HTML.HTMLSelectElement, HTML.HTMLTextAreaElement, HTML.HTMLButtonElement, HTML.HTMLAnchorElement]
element.prototype.focus = ->
focus @ownerDocument, this
element.prototype.blur = ->
focus @ownerDocument, null

26 changes: 4 additions & 22 deletions lib/zombie/windows.coffee
Expand Up @@ -223,35 +223,17 @@ class Windows

# -- Focusing --

# Handle change to in-focus element
focused = null
Object.defineProperty window, "_focused",
get: ->
return focused
set: (element)->
unless element == focused
if focused
onblur = window.document.createEvent("HTMLEvents")
onblur.initEvent "blur", false, false
previous = focused
previous.dispatchEvent onblur
if element
onfocus = window.document.createEvent("HTMLEvents")
onfocus.initEvent "focus", false, false
element.dispatchEvent onfocus
focused = element

# If window goes in/out of focus, notify focused input field
window.addEventListener "focus", (event)->
if window._focused
if window.document.activeElement
onfocus = window.document.createEvent("HTMLEvents")
onfocus.initEvent "focus", false, false
window._focused.dispatchEvent onfocus
window.document.activeElement.dispatchEvent onfocus
window.addEventListener "blur", (event)->
if window._focused
if window.document.activeElement
onblur = window.document.createEvent("HTMLEvents")
onblur.initEvent "blur", false, false
window._focused.dispatchEvent onblur
window.document.activeElement.dispatchEvent onblur

# -- JavaScript evaluation

Expand Down
137 changes: 72 additions & 65 deletions test/forms_test.coffee
Expand Up @@ -218,29 +218,28 @@ describe "Forms", ->
assert.throws ->
@browser.fill @browser.querySelector("#readonly_input_field"), "yeahh"

@browser.fill @browser.querySelector("#field-email3"), "headchomper@example.com", done

it "should fire the callback", ->
assert.equal @browser.querySelector("#field-email3").value, "headchomper@example.com"

describe "any field", ->
before ->
@field1 = @browser.querySelector("#field-email2")
@field2 = @browser.querySelector("#field-email3")

it "should fire focus event on selected field", (done)->
@browser.fill @field1, "something"
@field2.addEventListener "focus", ->
done()
done = null
@browser.fill @field2, "else"
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-email2")
field2 = browser.querySelector("#field-email3")
browser.fill field1, "something"
field2.addEventListener "focus", ->
done()
browser.fill field2, "else"

it "should fire blur event on previous field", (done)->
@browser.fill @field1, "something"
@field1.addEventListener "blur", ->
done()
done = null
@browser.fill @field2, "else"
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-email2")
field2 = browser.querySelector("#field-email3")
browser.fill field1, "something"
field1.addEventListener "blur", ->
done()
browser.fill field2, "else"


describe "check box", ->
Expand Down Expand Up @@ -337,25 +336,29 @@ describe "Forms", ->
assert.deepEqual @values, [false, true, false]

describe "any checkbox", ->
before ->
@field1 = @browser.querySelector("#field-check")
@field2 = @browser.querySelector("#field-uncheck")

it "should fire focus event on selected field", (done)->
@browser.uncheck @field1
@browser.check @field1
@field2.addEventListener "focus", ->
done()
done = null
@browser.check @field2
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-check")
field2 = browser.querySelector("#field-uncheck")
browser.uncheck field1
browser.check field1
field2.addEventListener "focus", ->
done()
browser.check field2

it "should fire blur event on previous field", (done)->
@browser.uncheck @field1
@browser.check @field1
@field1.addEventListener "blur", ->
done()
done = null
@browser.check @field2
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-check")
field2 = browser.querySelector("#field-uncheck")
browser.uncheck field1
browser.check field1
field1.addEventListener "blur", ->
done()
browser.check field2


describe "radio buttons", ->
Expand Down Expand Up @@ -506,22 +509,28 @@ describe "Forms", ->

describe "any selection", ->
before ->
@field1 = @browser.querySelector("#field-email2")
@field2 = @browser.querySelector("#field-kills")

it "should fire focus event on selected field", (done)->
@browser.fill @field1, "something"
@field2.addEventListener "focus", ->
done()
done = null
@browser.select @field2, "Five"
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-email2")
field2 = browser.querySelector("#field-kills")
browser.fill field1, "something"
field2.addEventListener "focus", ->
done()
browser.select field2, "Five"

it "should fire blur event on previous field", (done)->
@browser.fill @field1, "something"
@field1.addEventListener "blur", ->
done()
done = null
@browser.select @field2, "Five"
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field1 = browser.querySelector("#field-email2")
field2 = browser.querySelector("#field-kills")
browser.fill field1, "something"
field1.addEventListener "blur", ->
done()
browser.select field2, "Five"


describe "multiple select option", ->
Expand Down Expand Up @@ -752,27 +761,25 @@ describe "Forms", ->
assert.equal @browser.text("#image_clicked"), "undefined"

describe "pressButton", ->
before (done)->
@browser = new Browser()
@browser.visit("http://localhost:3003/forms/form")
.then =>
@field1 = @browser.querySelector("#field-email2")
return
.then(done, done)

it "should fire focus event on button", (done)->
@browser.fill @field1, "something"
@browser.button("Hit Me").addEventListener "focus", ->
done()
done = null
@browser.pressButton("Hit Me")
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then ->
field = browser.querySelector("#field-email2")
browser.fill field, "something"
browser.button("Hit Me").addEventListener "focus", ->
done()
browser.pressButton("Hit Me")

it "should fire blur event on previous field", (done)->
@browser.fill @field1, "something"
@field1.addEventListener "blur", ->
done()
done = null
@browser.pressButton("Hit Me")
browser = new Browser()
browser.visit("http://localhost:3003/forms/form")
.then =>
field = browser.querySelector("#field-email2")
browser.fill field, "something"
field.addEventListener "blur", ->
done()
browser.pressButton("Hit Me")


describe "by clicking image button", ->
Expand Down

0 comments on commit 7a2ce28

Please sign in to comment.