--- /dev/null
+{% autoescape 'js' %}
+(function (xpath, value) {
+ function getElement(xpath, within) {
+ var result;
+ if (within === null || within === undefined) {
+ within = document;
+ }
+ result = document.evaluate(xpath, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ if (result.snapshotLength !== 1) {
+ return null;
+ }
+ return result.snapshotItem(0);
+ }
+
+ function isInput(element) {
+ if (element === null || element === undefined) {
+ return false;
+ }
+ return (element.tagName.toLowerCase() == "input");
+ }
+
+ function isTextArea(element) {
+ if (element === null || element === undefined) {
+ return false;
+ }
+ return (element.tagName.toLowerCase() == "textarea");
+ }
+
+ function isSelect(element) {
+ if (element === null || element === undefined) {
+ return false;
+ }
+ return (element.tagName.toLowerCase() == "select");
+ }
+
+ function deselectAllOptions(element) {
+ var i, l = element.options.length;
+ for (i = 0; i < l; i++) {
+ element.options[i].selected = false;
+ }
+ }
+
+ function xpathStringLiteral(s) {
+ if (s.indexOf('"') === -1)
+ return '"' + s + '"';
+ if (s.indexOf("'") === -1)
+ return "'" + s + "'";
+ return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
+ }
+
+ function clickOnElement(element) {
+ // create a mouse click event
+ var event = document.createEvent('MouseEvents');
+ event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+
+ // send click to element
+ element.dispatchEvent(event);
+
+ //After dispatching the event let's wait for 2 seconds at least...
+ return setTimeout(function () {
+ }, 2);
+ }
+
+ function dispatchChange(element) {
+ var tagName =element.tagName.toLowerCase();
+ var elementType = element.getAttribute("type");
+ if (tagName != "option" || (tagName == "input" && elementType == "radio")){
+ return true;
+ }
+ //Force the change when element is option
+ var event;
+ event = document.createEvent('HTMLEvents');
+ event.initEvent('change', true, false);
+ element.dispatchEvent(event);
+ return true;
+ }
+
+ function selectOptionOnElement(element, option, multiple) {
+ var polterAgent = window.__poltergeist;
+ var escapedOption = xpathStringLiteral(option);
+ // The value of an option is the normalized version of its text when it has no value attribute
+ var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
+ var ids = polterAgent.find("xpath", optionQuery, element);
+ var polterNode = polterAgent.get(ids[0]);
+ var optionElement = polterNode.element;
+
+ if (multiple || !element.multiple) {
+ if (!optionElement.selected) {
+ clickOnElement(optionElement);
+ optionElement.selected = true;
+ }
+ return dispatchChange(optionElement);
+ }
+
+ deselectAllOptions(element);
+ clickOnElement(optionElement);
+ optionElement.selected = true;
+ return dispatchChange(optionElement);
+ }
+
+ function selectSetValue(element, value) {
+ var option;
+ if ((Array.isArray && Array.isArray(value)) || (value instanceof Array)) {
+ deselectAllOptions(element);
+ for (option in value) {
+ if (value.hasOwnProperty(option)) {
+ selectOptionOnElement(element, value[option], true);
+ }
+ }
+ return true;
+ }
+
+ selectOptionOnElement(element, value, false);
+ return true;
+ }
+
+ function selectRadioValue(element, value) {
+ if (element.value === value) {
+ clickOnElement(element);
+ element.checked=true;
+ dispatchChange(element);
+ return true;
+ }
+
+ var formElements = element.form.elements;
+ var name = element.getAttribute("name");
+ var radioElement, i;
+
+ if (!name) {
+ return null;
+ }
+
+ for (i = 0; i < formElements.length; i++) {
+ radioElement = formElements[i];
+ if (radioElement.tagName.toLowerCase() == 'input' && radioElement.type.toLowerCase() == 'radio' && radioElement.name === name) {
+ if (value === radioElement.value) {
+ clickOnElement(radioElement);
+ radioElement.checked=true;
+ dispatchChange(radioElement);
+ return true;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ function inputSetValue(element, value, elementXpath) {
+ var allowedTypes = ['submit', 'image', 'button', 'reset'];
+ var elementType = element.type.toLowerCase();
+ var textLikeInputType = ['file', 'text', 'password', 'url', 'email', 'search', 'number', 'tel', 'range', 'date', 'month', 'week', 'time', 'datetime', 'color', 'datetime-local'];
+
+ if (allowedTypes.indexOf(elementType) !== -1) {
+ return null;
+ }
+
+ if (elementType == "checkbox") {
+ var booleanValue = false;
+ if (value == "1" || value == 1) {
+ booleanValue = true;
+ } else if (value == "0" || value == 0) {
+ booleanValue = false;
+ }
+ if ((element.checked && !booleanValue) || (!element.checked && booleanValue)) {
+ clickOnElement(element);
+ dispatchChange(element);
+ }
+ return true;
+ }
+
+ if (elementType == "radio") {
+ return selectRadioValue(element, value);
+ }
+
+ if (textLikeInputType.indexOf(elementType) !== -1) {
+ return textAreaSetValue(elementXpath, value);
+ }
+
+ //No support for the moment for file stuff or other input types
+ return null;
+
+ }
+
+ function textAreaSetValue(elementXpath, value) {
+ var polterAgent = window.__poltergeist;
+ var ids = polterAgent.find("xpath", elementXpath, document);
+ var polterNode = polterAgent.get(ids[0]);
+ polterNode.set(value);
+ return true;
+ }
+
+ var node = getElement(xpath);
+ if (node === null) {
+ return null;
+ }
+
+ if (isSelect(node)) {
+ return selectSetValue(node, value);
+ }
+
+ if (isInput(node)) {
+ return inputSetValue(node, value, xpath);
+ }
+
+ if (isTextArea(node)) {
+ return textAreaSetValue(xpath, value);
+ }
+
+ //for the moment everything else also to textArea stuff
+ return textAreaSetValue(xpath, value);
+
+}('{{xpath}}', JSON.parse('{{ value }}')));
+{% endautoescape %}