2011-02-26 03:32:22 +00:00
|
|
|
Capybara = {
|
|
|
|
nextIndex: 0,
|
|
|
|
nodes: {},
|
2011-07-18 21:16:57 +00:00
|
|
|
lastAttachedFile: "",
|
2011-02-26 03:32:22 +00:00
|
|
|
|
2011-02-26 03:57:55 +00:00
|
|
|
invoke: function () {
|
|
|
|
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
|
|
|
|
},
|
|
|
|
|
2011-02-26 03:32:22 +00:00
|
|
|
find: function (xpath) {
|
2011-02-26 21:46:59 +00:00
|
|
|
return this.findRelativeTo(document, xpath);
|
|
|
|
},
|
|
|
|
|
|
|
|
findWithin: function (index, xpath) {
|
|
|
|
return this.findRelativeTo(this.nodes[index], xpath);
|
|
|
|
},
|
|
|
|
|
|
|
|
findRelativeTo: function (reference, xpath) {
|
|
|
|
var iterator = document.evaluate(xpath, reference, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
|
2011-02-26 03:32:22 +00:00
|
|
|
var node;
|
|
|
|
var results = [];
|
|
|
|
while (node = iterator.iterateNext()) {
|
|
|
|
this.nextIndex++;
|
|
|
|
this.nodes[this.nextIndex] = node;
|
|
|
|
results.push(this.nextIndex);
|
|
|
|
}
|
2011-02-26 03:33:47 +00:00
|
|
|
return results.join(",");
|
2011-02-26 03:32:22 +00:00
|
|
|
},
|
|
|
|
|
2011-09-30 21:13:54 +00:00
|
|
|
isAttached: function(index) {
|
|
|
|
return document.evaluate("ancestor-or-self::html", this.nodes[index], null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue != null;
|
|
|
|
},
|
|
|
|
|
2011-02-26 04:39:29 +00:00
|
|
|
text: function (index) {
|
2011-07-22 19:21:17 +00:00
|
|
|
var node = this.nodes[index];
|
|
|
|
var type = (node.type || node.tagName).toLowerCase();
|
|
|
|
if (type == "textarea") {
|
|
|
|
return node.innerHTML;
|
|
|
|
} else {
|
|
|
|
return node.innerText;
|
|
|
|
}
|
2011-02-26 04:39:29 +00:00
|
|
|
},
|
|
|
|
|
2011-02-26 03:32:22 +00:00
|
|
|
attribute: function (index, name) {
|
2011-05-23 13:01:12 +00:00
|
|
|
switch(name) {
|
2011-07-22 19:21:17 +00:00
|
|
|
case 'checked':
|
2011-03-11 16:25:06 +00:00
|
|
|
return this.nodes[index].checked;
|
2011-05-23 13:01:12 +00:00
|
|
|
break;
|
|
|
|
|
2011-07-22 19:21:17 +00:00
|
|
|
case 'disabled':
|
2011-05-23 13:01:12 +00:00
|
|
|
return this.nodes[index].disabled;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2011-03-11 16:25:06 +00:00
|
|
|
return this.nodes[index].getAttribute(name);
|
|
|
|
}
|
2011-02-26 19:55:40 +00:00
|
|
|
},
|
|
|
|
|
2011-09-24 22:16:36 +00:00
|
|
|
path: function(index) {
|
|
|
|
return "/" + this.getXPathNode(this.nodes[index]).join("/");
|
|
|
|
},
|
|
|
|
|
|
|
|
getXPathNode: function(node, path) {
|
|
|
|
path = path || [];
|
|
|
|
if(node.parentNode) {
|
|
|
|
path = this.getXPathNode(node.parentNode, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(node.previousSibling) {
|
|
|
|
var count = 1;
|
|
|
|
var sibling = node.previousSibling
|
|
|
|
do {
|
|
|
|
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;}
|
|
|
|
sibling = sibling.previousSibling;
|
|
|
|
} while(sibling);
|
|
|
|
if(count == 1) {count = null;}
|
|
|
|
} else if(node.nextSibling) {
|
|
|
|
var sibling = node.nextSibling;
|
|
|
|
do {
|
|
|
|
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {
|
|
|
|
var count = 1;
|
|
|
|
sibling = null;
|
|
|
|
} else {
|
|
|
|
var count = null;
|
|
|
|
sibling = sibling.previousSibling;
|
|
|
|
}
|
|
|
|
} while(sibling);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(node.nodeType == 1) {
|
|
|
|
path.push(node.nodeName.toLowerCase() + (node.id ? "[@id='"+node.id+"']" : count > 0 ? "["+count+"]" : ''));
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
},
|
|
|
|
|
2011-02-26 19:55:40 +00:00
|
|
|
tagName: function(index) {
|
2011-02-26 20:04:34 +00:00
|
|
|
return this.nodes[index].tagName.toLowerCase();
|
2011-02-26 20:18:11 +00:00
|
|
|
},
|
|
|
|
|
2011-09-24 22:16:57 +00:00
|
|
|
submit: function(index) {
|
|
|
|
return this.nodes[index].submit();
|
|
|
|
},
|
|
|
|
|
2011-02-26 20:18:11 +00:00
|
|
|
click: function (index) {
|
|
|
|
var clickEvent = document.createEvent('MouseEvents');
|
|
|
|
clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
|
|
|
this.nodes[index].dispatchEvent(clickEvent);
|
2011-02-26 20:50:45 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
trigger: function (index, eventName) {
|
|
|
|
var eventObject = document.createEvent("HTMLEvents");
|
|
|
|
eventObject.initEvent(eventName, true, true);
|
|
|
|
this.nodes[index].dispatchEvent(eventObject);
|
2011-02-26 21:20:05 +00:00
|
|
|
},
|
|
|
|
|
2011-05-04 08:45:57 +00:00
|
|
|
keypress: function(index, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {
|
|
|
|
var eventObject = document.createEvent("Events");
|
|
|
|
eventObject.initEvent('keypress', true, true);
|
|
|
|
eventObject.window = window;
|
|
|
|
eventObject.altKey = altKey;
|
|
|
|
eventObject.ctrlKey = ctrlKey;
|
|
|
|
eventObject.shiftKey = shiftKey;
|
|
|
|
eventObject.metaKey = metaKey;
|
|
|
|
eventObject.keyCode = keyCode;
|
|
|
|
eventObject.charCode = charCode;
|
|
|
|
this.nodes[index].dispatchEvent(eventObject);
|
|
|
|
},
|
|
|
|
|
2011-02-26 21:20:05 +00:00
|
|
|
visible: function (index) {
|
|
|
|
var element = this.nodes[index];
|
|
|
|
while (element) {
|
2011-03-10 04:50:21 +00:00
|
|
|
if (element.ownerDocument.defaultView.getComputedStyle(element, null).getPropertyValue("display") == 'none')
|
2011-02-26 21:20:05 +00:00
|
|
|
return false;
|
|
|
|
element = element.parentElement;
|
|
|
|
}
|
|
|
|
return true;
|
2011-02-26 20:48:44 +00:00
|
|
|
},
|
|
|
|
|
2011-07-29 15:18:51 +00:00
|
|
|
selected: function (index) {
|
|
|
|
return this.nodes[index].selected;
|
|
|
|
},
|
|
|
|
|
2011-02-26 20:48:44 +00:00
|
|
|
value: function(index) {
|
|
|
|
return this.nodes[index].value;
|
2011-02-26 21:26:22 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
set: function(index, value) {
|
2011-03-11 16:25:06 +00:00
|
|
|
var node = this.nodes[index];
|
|
|
|
var type = (node.type || node.tagName).toLowerCase();
|
2011-07-13 21:03:18 +00:00
|
|
|
if (type == "text" || type == "textarea" || type == "password" || type == "email") {
|
2011-03-11 16:25:06 +00:00
|
|
|
this.trigger(index, "focus");
|
2011-05-04 08:45:57 +00:00
|
|
|
node.value = "";
|
2011-08-25 17:37:14 +00:00
|
|
|
var maxLength = this.attribute(index, "maxlength"),
|
|
|
|
length;
|
|
|
|
if (maxLength && value.length > maxLength) {
|
|
|
|
length = maxLength;
|
|
|
|
} else {
|
|
|
|
length = value.length;
|
|
|
|
}
|
|
|
|
|
2011-07-22 19:21:36 +00:00
|
|
|
for(var strindex = 0; strindex < length; strindex++) {
|
2011-05-04 08:45:57 +00:00
|
|
|
node.value += value[strindex];
|
|
|
|
this.trigger(index, "keydown");
|
|
|
|
this.keypress(index, false, false, false, false, 0, value[strindex]);
|
|
|
|
this.trigger(index, "keyup");
|
|
|
|
}
|
2011-03-11 16:25:06 +00:00
|
|
|
this.trigger(index, "change");
|
|
|
|
this.trigger(index, "blur");
|
|
|
|
} else if(type == "checkbox" || type == "radio") {
|
|
|
|
node.checked = (value == "true");
|
|
|
|
this.trigger(index, "click");
|
2011-05-27 17:32:12 +00:00
|
|
|
this.trigger(index, "change");
|
2011-07-18 21:16:57 +00:00
|
|
|
} else if(type == "file") {
|
|
|
|
this.lastAttachedFile = value;
|
|
|
|
this.trigger(index, "click");
|
2011-03-11 16:25:06 +00:00
|
|
|
} else {
|
|
|
|
node.value = value;
|
|
|
|
}
|
2011-02-26 22:51:47 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
selectOption: function(index) {
|
2011-04-21 03:01:57 +00:00
|
|
|
this.nodes[index].selected = true;
|
2011-02-26 22:51:47 +00:00
|
|
|
this.nodes[index].setAttribute("selected", "selected");
|
2011-04-21 03:01:57 +00:00
|
|
|
this.trigger(index, "change");
|
2011-02-26 22:51:47 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
unselectOption: function(index) {
|
2011-04-21 03:01:57 +00:00
|
|
|
this.nodes[index].selected = false;
|
2011-02-26 22:51:47 +00:00
|
|
|
this.nodes[index].removeAttribute("selected");
|
2011-04-21 03:01:57 +00:00
|
|
|
this.trigger(index, "change");
|
2011-04-23 11:22:16 +00:00
|
|
|
},
|
2011-02-26 22:51:47 +00:00
|
|
|
|
2011-04-23 11:22:16 +00:00
|
|
|
centerPostion: function(element) {
|
|
|
|
this.reflow(element);
|
|
|
|
var rect = element.getBoundingClientRect();
|
|
|
|
var position = {
|
|
|
|
x: rect.width / 2,
|
|
|
|
y: rect.height / 2
|
|
|
|
};
|
|
|
|
do {
|
|
|
|
position.x += element.offsetLeft;
|
|
|
|
position.y += element.offsetTop;
|
|
|
|
} while ((element = element.offsetParent));
|
|
|
|
position.x = Math.floor(position.x), position.y = Math.floor(position.y);
|
|
|
|
|
|
|
|
return position;
|
|
|
|
},
|
|
|
|
|
|
|
|
reflow: function(element, force) {
|
|
|
|
if (force || element.offsetWidth === 0) {
|
|
|
|
var prop, oldStyle = {}, newStyle = {position: "absolute", visibility : "hidden", display: "block" };
|
|
|
|
for (prop in newStyle) {
|
|
|
|
oldStyle[prop] = element.style[prop];
|
|
|
|
element.style[prop] = newStyle[prop];
|
|
|
|
}
|
|
|
|
element.offsetWidth, element.offsetHeight; // force reflow
|
|
|
|
for (prop in oldStyle)
|
|
|
|
element.style[prop] = oldStyle[prop];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
dragTo: function (index, targetIndex) {
|
|
|
|
var element = this.nodes[index], target = this.nodes[targetIndex];
|
|
|
|
var position = this.centerPostion(element);
|
|
|
|
var options = {
|
|
|
|
clientX: position.x,
|
|
|
|
clientY: position.y
|
|
|
|
};
|
|
|
|
var mouseTrigger = function(eventName, options) {
|
|
|
|
var eventObject = document.createEvent("MouseEvents");
|
|
|
|
eventObject.initMouseEvent(eventName, true, true, window, 0, 0, 0, options.clientX || 0, options.clientY || 0, false, false, false, false, 0, null);
|
|
|
|
element.dispatchEvent(eventObject);
|
|
|
|
}
|
|
|
|
mouseTrigger('mousedown', options);
|
|
|
|
options.clientX += 1, options.clientY += 1;
|
|
|
|
mouseTrigger('mousemove', options);
|
|
|
|
|
|
|
|
position = this.centerPostion(target), options = {
|
|
|
|
clientX: position.x,
|
|
|
|
clientY: position.y
|
|
|
|
};
|
|
|
|
mouseTrigger('mousemove', options);
|
|
|
|
mouseTrigger('mouseup', options);
|
|
|
|
}
|
2011-02-26 03:32:22 +00:00
|
|
|
};
|
|
|
|
|