{% 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 %}