Chris@0
|
1 {% autoescape 'js' %}
|
Chris@0
|
2 (function (xpath, value) {
|
Chris@0
|
3 function getElement(xpath, within) {
|
Chris@0
|
4 var result;
|
Chris@0
|
5 if (within === null || within === undefined) {
|
Chris@0
|
6 within = document;
|
Chris@0
|
7 }
|
Chris@0
|
8 result = document.evaluate(xpath, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
Chris@0
|
9 if (result.snapshotLength !== 1) {
|
Chris@0
|
10 return null;
|
Chris@0
|
11 }
|
Chris@0
|
12 return result.snapshotItem(0);
|
Chris@0
|
13 }
|
Chris@0
|
14
|
Chris@0
|
15 function isInput(element) {
|
Chris@0
|
16 if (element === null || element === undefined) {
|
Chris@0
|
17 return false;
|
Chris@0
|
18 }
|
Chris@0
|
19 return (element.tagName.toLowerCase() == "input");
|
Chris@0
|
20 }
|
Chris@0
|
21
|
Chris@0
|
22 function isTextArea(element) {
|
Chris@0
|
23 if (element === null || element === undefined) {
|
Chris@0
|
24 return false;
|
Chris@0
|
25 }
|
Chris@0
|
26 return (element.tagName.toLowerCase() == "textarea");
|
Chris@0
|
27 }
|
Chris@0
|
28
|
Chris@0
|
29 function isSelect(element) {
|
Chris@0
|
30 if (element === null || element === undefined) {
|
Chris@0
|
31 return false;
|
Chris@0
|
32 }
|
Chris@0
|
33 return (element.tagName.toLowerCase() == "select");
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 function deselectAllOptions(element) {
|
Chris@0
|
37 var i, l = element.options.length;
|
Chris@0
|
38 for (i = 0; i < l; i++) {
|
Chris@0
|
39 element.options[i].selected = false;
|
Chris@0
|
40 }
|
Chris@0
|
41 }
|
Chris@0
|
42
|
Chris@0
|
43 function xpathStringLiteral(s) {
|
Chris@0
|
44 if (s.indexOf('"') === -1)
|
Chris@0
|
45 return '"' + s + '"';
|
Chris@0
|
46 if (s.indexOf("'") === -1)
|
Chris@0
|
47 return "'" + s + "'";
|
Chris@0
|
48 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
|
Chris@0
|
49 }
|
Chris@0
|
50
|
Chris@0
|
51 function clickOnElement(element) {
|
Chris@0
|
52 // create a mouse click event
|
Chris@0
|
53 var event = document.createEvent('MouseEvents');
|
Chris@0
|
54 event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
Chris@0
|
55
|
Chris@0
|
56 // send click to element
|
Chris@0
|
57 element.dispatchEvent(event);
|
Chris@0
|
58
|
Chris@0
|
59 //After dispatching the event let's wait for 2 seconds at least...
|
Chris@0
|
60 return setTimeout(function () {
|
Chris@0
|
61 }, 2);
|
Chris@0
|
62 }
|
Chris@0
|
63
|
Chris@0
|
64 function dispatchChange(element) {
|
Chris@0
|
65 var tagName =element.tagName.toLowerCase();
|
Chris@0
|
66 var elementType = element.getAttribute("type");
|
Chris@0
|
67 if (tagName != "option" || (tagName == "input" && elementType == "radio")){
|
Chris@0
|
68 return true;
|
Chris@0
|
69 }
|
Chris@0
|
70 //Force the change when element is option
|
Chris@0
|
71 var event;
|
Chris@0
|
72 event = document.createEvent('HTMLEvents');
|
Chris@0
|
73 event.initEvent('change', true, false);
|
Chris@0
|
74 element.dispatchEvent(event);
|
Chris@0
|
75 return true;
|
Chris@0
|
76 }
|
Chris@0
|
77
|
Chris@0
|
78 function selectOptionOnElement(element, option, multiple) {
|
Chris@0
|
79 var polterAgent = window.__poltergeist;
|
Chris@0
|
80 var escapedOption = xpathStringLiteral(option);
|
Chris@0
|
81 // The value of an option is the normalized version of its text when it has no value attribute
|
Chris@0
|
82 var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
|
Chris@0
|
83 var ids = polterAgent.find("xpath", optionQuery, element);
|
Chris@0
|
84 var polterNode = polterAgent.get(ids[0]);
|
Chris@0
|
85 var optionElement = polterNode.element;
|
Chris@0
|
86
|
Chris@0
|
87 if (multiple || !element.multiple) {
|
Chris@0
|
88 if (!optionElement.selected) {
|
Chris@0
|
89 clickOnElement(optionElement);
|
Chris@0
|
90 optionElement.selected = true;
|
Chris@0
|
91 }
|
Chris@0
|
92 return dispatchChange(optionElement);
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 deselectAllOptions(element);
|
Chris@0
|
96 clickOnElement(optionElement);
|
Chris@0
|
97 optionElement.selected = true;
|
Chris@0
|
98 return dispatchChange(optionElement);
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 function selectSetValue(element, value) {
|
Chris@0
|
102 var option;
|
Chris@0
|
103 if ((Array.isArray && Array.isArray(value)) || (value instanceof Array)) {
|
Chris@0
|
104 deselectAllOptions(element);
|
Chris@0
|
105 for (option in value) {
|
Chris@0
|
106 if (value.hasOwnProperty(option)) {
|
Chris@0
|
107 selectOptionOnElement(element, value[option], true);
|
Chris@0
|
108 }
|
Chris@0
|
109 }
|
Chris@0
|
110 return true;
|
Chris@0
|
111 }
|
Chris@0
|
112
|
Chris@0
|
113 selectOptionOnElement(element, value, false);
|
Chris@0
|
114 return true;
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 function selectRadioValue(element, value) {
|
Chris@0
|
118 if (element.value === value) {
|
Chris@0
|
119 clickOnElement(element);
|
Chris@0
|
120 element.checked=true;
|
Chris@0
|
121 dispatchChange(element);
|
Chris@0
|
122 return true;
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 var formElements = element.form.elements;
|
Chris@0
|
126 var name = element.getAttribute("name");
|
Chris@0
|
127 var radioElement, i;
|
Chris@0
|
128
|
Chris@0
|
129 if (!name) {
|
Chris@0
|
130 return null;
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 for (i = 0; i < formElements.length; i++) {
|
Chris@0
|
134 radioElement = formElements[i];
|
Chris@0
|
135 if (radioElement.tagName.toLowerCase() == 'input' && radioElement.type.toLowerCase() == 'radio' && radioElement.name === name) {
|
Chris@0
|
136 if (value === radioElement.value) {
|
Chris@0
|
137 clickOnElement(radioElement);
|
Chris@0
|
138 radioElement.checked=true;
|
Chris@0
|
139 dispatchChange(radioElement);
|
Chris@0
|
140 return true;
|
Chris@0
|
141 }
|
Chris@0
|
142 }
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 return null;
|
Chris@0
|
146 }
|
Chris@0
|
147
|
Chris@0
|
148 function inputSetValue(element, value, elementXpath) {
|
Chris@0
|
149 var allowedTypes = ['submit', 'image', 'button', 'reset'];
|
Chris@0
|
150 var elementType = element.type.toLowerCase();
|
Chris@0
|
151 var textLikeInputType = ['file', 'text', 'password', 'url', 'email', 'search', 'number', 'tel', 'range', 'date', 'month', 'week', 'time', 'datetime', 'color', 'datetime-local'];
|
Chris@0
|
152
|
Chris@0
|
153 if (allowedTypes.indexOf(elementType) !== -1) {
|
Chris@0
|
154 return null;
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 if (elementType == "checkbox") {
|
Chris@0
|
158 var booleanValue = false;
|
Chris@0
|
159 if (value == "1" || value == 1) {
|
Chris@0
|
160 booleanValue = true;
|
Chris@0
|
161 } else if (value == "0" || value == 0) {
|
Chris@0
|
162 booleanValue = false;
|
Chris@0
|
163 }
|
Chris@0
|
164 if ((element.checked && !booleanValue) || (!element.checked && booleanValue)) {
|
Chris@0
|
165 clickOnElement(element);
|
Chris@0
|
166 dispatchChange(element);
|
Chris@0
|
167 }
|
Chris@0
|
168 return true;
|
Chris@0
|
169 }
|
Chris@0
|
170
|
Chris@0
|
171 if (elementType == "radio") {
|
Chris@0
|
172 return selectRadioValue(element, value);
|
Chris@0
|
173 }
|
Chris@0
|
174
|
Chris@0
|
175 if (textLikeInputType.indexOf(elementType) !== -1) {
|
Chris@0
|
176 return textAreaSetValue(elementXpath, value);
|
Chris@0
|
177 }
|
Chris@0
|
178
|
Chris@0
|
179 //No support for the moment for file stuff or other input types
|
Chris@0
|
180 return null;
|
Chris@0
|
181
|
Chris@0
|
182 }
|
Chris@0
|
183
|
Chris@0
|
184 function textAreaSetValue(elementXpath, value) {
|
Chris@0
|
185 var polterAgent = window.__poltergeist;
|
Chris@0
|
186 var ids = polterAgent.find("xpath", elementXpath, document);
|
Chris@0
|
187 var polterNode = polterAgent.get(ids[0]);
|
Chris@0
|
188 polterNode.set(value);
|
Chris@0
|
189 return true;
|
Chris@0
|
190 }
|
Chris@0
|
191
|
Chris@0
|
192 var node = getElement(xpath);
|
Chris@0
|
193 if (node === null) {
|
Chris@0
|
194 return null;
|
Chris@0
|
195 }
|
Chris@0
|
196
|
Chris@0
|
197 if (isSelect(node)) {
|
Chris@0
|
198 return selectSetValue(node, value);
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@0
|
201 if (isInput(node)) {
|
Chris@0
|
202 return inputSetValue(node, value, xpath);
|
Chris@0
|
203 }
|
Chris@0
|
204
|
Chris@0
|
205 if (isTextArea(node)) {
|
Chris@0
|
206 return textAreaSetValue(xpath, value);
|
Chris@0
|
207 }
|
Chris@0
|
208
|
Chris@0
|
209 //for the moment everything else also to textArea stuff
|
Chris@0
|
210 return textAreaSetValue(xpath, value);
|
Chris@0
|
211
|
Chris@0
|
212 }('{{xpath}}', JSON.parse('{{ value }}')));
|
Chris@0
|
213 {% endautoescape %}
|