1
0
Fork 0
mirror of https://github.com/teampoltergeist/poltergeist.git synced 2022-11-09 12:05:00 -05:00

Use native keyboard events to fill inputs

This means that WebKit generates the DOM events itself which should
prevent bugs and edge case problems. It also drastically simplifies the
implementation.

Closes #162, #131
This commit is contained in:
Jon Leighton 2012-10-05 00:38:21 +01:00
parent 332f80a696
commit c7ba561411
4 changed files with 30 additions and 180 deletions

View file

@ -110,32 +110,6 @@ class PoltergeistAgent.Node
event.initEvent('change', true, false)
@element.dispatchEvent(event)
input: ->
event = document.createEvent('HTMLEvents')
event.initEvent('input', true, false)
@element.dispatchEvent(event)
keyupdowned: (eventName, keyCode) ->
event = document.createEvent('UIEvents')
event.initEvent(eventName, true, true)
event.keyCode = keyCode
event.which = keyCode
event.charCode = 0
@element.dispatchEvent(event)
keypressed: (altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) ->
event = document.createEvent('UIEvents')
event.initEvent('keypress', true, true)
event.window = @agent.window
event.altKey = altKey
event.ctrlKey = ctrlKey
event.shiftKey = shiftKey
event.metaKey = metaKey
event.keyCode = keyCode
event.charCode = charCode
event.which = keyCode
@element.dispatchEvent(event)
insideBody: ->
@element == @agent.document.body ||
@agent.document.evaluate('ancestor::body', @element, null, XPathResult.BOOLEAN_TYPE, null).booleanValue
@ -161,25 +135,6 @@ class PoltergeistAgent.Node
else
@element.value
set: (value) ->
if (@element.maxLength >= 0)
value = value.substr(0, @element.maxLength)
@element.value = ''
this.trigger('focus')
for char in value
keyCode = this.characterToKeyCode(char)
this.keyupdowned('keydown', keyCode)
@element.value += char
this.keypressed(false, false, false, false, char.charCodeAt(0), char.charCodeAt(0))
this.keyupdowned('keyup', keyCode)
this.changed()
this.input()
this.trigger('blur')
isMultiple: ->
@element.multiple
@ -238,6 +193,13 @@ class PoltergeistAgent.Node
@element.dispatchEvent(event)
focusAndHighlight: ->
@element.focus()
@element.select()
blur: ->
@element.blur()
clickTest: (x, y) ->
el = origEl = document.elementFromPoint(x, y)
@ -257,45 +219,6 @@ class PoltergeistAgent.Node
selector += ".#{className}"
selector
characterToKeyCode: (character) ->
code = character.toUpperCase().charCodeAt(0)
specialKeys =
96: 192 #`
45: 189 #-
61: 187 #=
91: 219 #[
93: 221 #]
92: 220 #\
59: 186 #;
39: 222 #'
44: 188 #,
46: 190 #.
47: 191 #/
127: 46 #delete
126: 192 #~
33: 49 #!
64: 50 #@
35: 51 ##
36: 52 #$
37: 53 #%
94: 54 #^
38: 55 #&
42: 56 #*
40: 57 #(
41: 48 #)
95: 189 #_
43: 187 #+
123: 219 #{
125: 221 #}
124: 220 #|
58: 186 #:
34: 222 #"
60: 188 #<
62: 190 #>
63: 191 #?
specialKeys[code] || code
isDOMEqual: (other_id) ->
@element == @agent.get(other_id).element

View file

@ -167,38 +167,6 @@ PoltergeistAgent.Node = (function() {
return this.element.dispatchEvent(event);
};
Node.prototype.input = function() {
var event;
event = document.createEvent('HTMLEvents');
event.initEvent('input', true, false);
return this.element.dispatchEvent(event);
};
Node.prototype.keyupdowned = function(eventName, keyCode) {
var event;
event = document.createEvent('UIEvents');
event.initEvent(eventName, true, true);
event.keyCode = keyCode;
event.which = keyCode;
event.charCode = 0;
return this.element.dispatchEvent(event);
};
Node.prototype.keypressed = function(altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {
var event;
event = document.createEvent('UIEvents');
event.initEvent('keypress', true, true);
event.window = this.agent.window;
event.altKey = altKey;
event.ctrlKey = ctrlKey;
event.shiftKey = shiftKey;
event.metaKey = metaKey;
event.keyCode = keyCode;
event.charCode = charCode;
event.which = keyCode;
return this.element.dispatchEvent(event);
};
Node.prototype.insideBody = function() {
return this.element === this.agent.document.body || this.agent.document.evaluate('ancestor::body', this.element, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;
};
@ -240,26 +208,6 @@ PoltergeistAgent.Node = (function() {
}
};
Node.prototype.set = function(value) {
var char, keyCode, _i, _len;
if (this.element.maxLength >= 0) {
value = value.substr(0, this.element.maxLength);
}
this.element.value = '';
this.trigger('focus');
for (_i = 0, _len = value.length; _i < _len; _i++) {
char = value[_i];
keyCode = this.characterToKeyCode(char);
this.keyupdowned('keydown', keyCode);
this.element.value += char;
this.keypressed(false, false, false, false, char.charCodeAt(0), char.charCodeAt(0));
this.keyupdowned('keyup', keyCode);
}
this.changed();
this.input();
return this.trigger('blur');
};
Node.prototype.isMultiple = function() {
return this.element.multiple;
};
@ -329,6 +277,15 @@ PoltergeistAgent.Node = (function() {
return this.element.dispatchEvent(event);
};
Node.prototype.focusAndHighlight = function() {
this.element.focus();
return this.element.select();
};
Node.prototype.blur = function() {
return this.element.blur();
};
Node.prototype.clickTest = function(x, y) {
var el, origEl;
el = origEl = document.elementFromPoint(x, y);
@ -362,47 +319,6 @@ PoltergeistAgent.Node = (function() {
return selector;
};
Node.prototype.characterToKeyCode = function(character) {
var code, specialKeys;
code = character.toUpperCase().charCodeAt(0);
specialKeys = {
96: 192,
45: 189,
61: 187,
91: 219,
93: 221,
92: 220,
59: 186,
39: 222,
44: 188,
46: 190,
47: 191,
127: 46,
126: 192,
33: 49,
64: 50,
35: 51,
36: 52,
37: 53,
94: 54,
38: 55,
42: 56,
40: 57,
41: 48,
95: 189,
43: 187,
123: 219,
125: 221,
124: 220,
58: 186,
34: 222,
60: 188,
62: 190,
63: 191
};
return specialKeys[code] || code;
};
Node.prototype.isDOMEqual = function(other_id) {
return this.element === this.agent.get(other_id).element;
};

View file

@ -4,7 +4,7 @@ Poltergeist.Node = (function() {
var name, _fn, _i, _len, _ref,
_this = this;
Node.DELEGATES = ['text', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'isVisible', 'position', 'trigger', 'parentId', 'clickTest', 'scrollIntoView', 'isDOMEqual'];
Node.DELEGATES = ['text', 'getAttribute', 'value', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'isVisible', 'position', 'trigger', 'parentId', 'clickTest', 'scrollIntoView', 'isDOMEqual', 'focusAndHighlight', 'blur'];
function Node(page, id) {
this.page = page;
@ -67,6 +67,12 @@ Poltergeist.Node = (function() {
return this.page === other.page && this.isDOMEqual(other.id);
};
Node.prototype.set = function(value) {
this.focusAndHighlight();
this.page.sendEvent('keypress', value.toString());
return this.blur();
};
return Node;
}).call(this);

View file

@ -1,10 +1,10 @@
# Proxy object for forwarding method calls to the node object inside the page.
class Poltergeist.Node
@DELEGATES = ['text', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete',
@DELEGATES = ['text', 'getAttribute', 'value', 'setAttribute', 'isObsolete',
'removeAttribute', 'isMultiple', 'select', 'tagName', 'find',
'isVisible', 'position', 'trigger', 'parentId', 'clickTest',
'scrollIntoView', 'isDOMEqual']
'scrollIntoView', 'isDOMEqual', 'focusAndHighlight', 'blur']
constructor: (@page, @id) ->
@ -51,3 +51,8 @@ class Poltergeist.Node
isEqual: (other) ->
@page == other.page && this.isDOMEqual(other.id)
set: (value) ->
this.focusAndHighlight()
@page.sendEvent('keypress', value.toString())
this.blur()