1 var __slice = [].slice;
3 Poltergeist.Node = (function () {
4 var name, _fn, _i, _len, _ref;
5 var xpathStringLiteral;
7 Node.DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'checked',
8 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple',
9 'select', 'tagName', 'find', 'getAttributes', 'isVisible',
10 'position', 'trigger', 'input', 'parentId', 'parentIds', 'mouseEventTest',
11 'scrollIntoView', 'isDOMEqual', 'isDisabled', 'deleteText', 'selectRadioValue',
12 'containsSelection', 'allHTML', 'changed', 'getXPathForElement', 'deselectAllOptions'];
14 function Node(page, id) {
20 * Returns the parent Node of this Node
21 * @return {Poltergeist.Node}
23 Node.prototype.parent = function () {
24 return new Poltergeist.Node(this.page, this.parentId());
27 _ref = Node.DELEGATES;
29 _fn = function (name) {
30 return Node.prototype[name] = function () {
32 if (arguments.length >= 1) {
33 args = __slice.call(arguments, 0)
35 return this.page.nodeCall(this.id, name, args);
39 //Adding all the delegates from the agent Node to this Node
40 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
45 xpathStringLiteral = function (s) {
46 if (s.indexOf('"') === -1)
48 if (s.indexOf("'") === -1)
50 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
54 * Gets an x,y position tailored for mouse event actions
57 Node.prototype.mouseEventPosition = function () {
58 var middle, pos, viewport;
60 viewport = this.page.viewportSize();
61 pos = this.position();
62 middle = function (start, end, size) {
63 return start + ((Math.min(end, size) - start) / 2);
67 x: middle(pos.left, pos.right, viewport.width),
68 y: middle(pos.top, pos.bottom, viewport.height)
73 * Executes a phantomjs native mouse event
77 Node.prototype.mouseEvent = function (name) {
80 this.scrollIntoView();
81 pos = this.mouseEventPosition();
82 test = this.mouseEventTest(pos.x, pos.y);
84 if (test.status === 'success') {
85 if (name === 'rightclick') {
86 this.page.mouseEvent('click', pos.x, pos.y, 'right');
87 this.trigger('contextmenu');
89 this.page.mouseEvent(name, pos.x, pos.y);
93 throw new Poltergeist.MouseEventFailed(name, test.selector, pos);
98 * Executes a mouse based drag from one node to another
102 Node.prototype.dragTo = function (other) {
103 var otherPosition, position;
105 this.scrollIntoView();
106 position = this.mouseEventPosition();
107 otherPosition = other.mouseEventPosition();
108 this.page.mouseEvent('mousedown', position.x, position.y);
109 return this.page.mouseEvent('mouseup', otherPosition.x, otherPosition.y);
113 * Checks if one node is equal to another
117 Node.prototype.isEqual = function (other) {
118 return this.page === other.page && this.isDOMEqual(other.id);
123 * The value to select
127 Node.prototype.select_option = function (value, multiple) {
128 var tagName = this.tagName().toLowerCase();
130 if (tagName === "select") {
131 var escapedOption = xpathStringLiteral(value);
132 // The value of an option is the normalized version of its text when it has no value attribute
133 var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
134 var ids = this.find("xpath", optionQuery);
135 var polterNode = this.page.get(ids[0]);
137 if (multiple || !this.getAttribute('multiple')) {
138 if (!polterNode.getAttribute('selected')) {
139 polterNode.select(value);
140 this.trigger('click');
146 this.deselectAllOptions();
147 polterNode.select(value);
148 this.trigger('click');
151 } else if (tagName === "input" && this.getAttribute("type").toLowerCase() === "radio") {
152 return this.selectRadioValue(value);
155 throw new Poltergeist.BrowserError("The element is not a select or radio input");