I've been using Python and Selenium to try to automate an export process in Qualtrics. I have the web driver navigate to the login page, input my login credentials, and then navigate to the Data and Analytics page of the relevant survey. However, once I navigate to the Data and Analysis page, I'm having trouble selecting the element for the dropdown icon under the action header, which I need to click in order to export the responses.
I've tried to use this code (omitting the part where I login):
from selenium import webdriver
survey_url= {The Survey Url}
browser= webdriver.Chrome()
browser.get(survey_url)
browser.find_element_by_xpath("//div[#id='itemContext']").click()
However, I keep getting this error: NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div[#id='itemContext']"}
I've tried using both the absolute (/html/body/div[6]) and the relative (//*[#id="itemContext"]) xpath given to me by inspect element, but neither worked.
This is the HTML that I see for the element:
<div id="itemContext" ng-click="removeSelf()" qmenu items="recordActions" on-select="selectRecordAction()(value,rowId, recordIndex)" class="response-context ng-scope ng-isolate-scope" style="left:1315px;top:357px">
<span ng-transclude></span></div>
Here is the HTML for the webpage:
<html ng-app="responses-client">
<head>
<meta charset="utf-8">
<title>Data | Qualtrics Experience Management</title>
<script>
(function (window) {
'use strict';
/*
* This function is used to attempt to get the initial definition before
* angular is loaded. If this fails for some reason the definition will
* still be loaded, but not via this function. See fast-definition-service.
*/
function rejectError(data, status, statusText) {
data = data || {};
window.fastDefinitionState = 'ERROR';
window.fastDefinitionError = {
status: status || 500,
statusText: statusText || 'Internal Server Error',
data: data,
config: {
method: 'GET',
url: url
}
};
}
function handleResponse() {
var status = request.status;
var data;
try {
data = JSON.parse(request.responseText);
} catch (e) {
data = request.responseText;
}
function handleSuccess() {
window.returnedDefinition = { data };
window.fastDefinitionState = 'SUCCESS';
}
if (status >= 200 && status < 400) {
return handleSuccess();
} else {
return rejectError(data, status, request.statusText);
}
}
function attemptRequest() {
request.open('GET', url, true);
request.onload = handleResponse; // Recieved response from server
request.onerror = rejectError; // Connection to server error
request.send();
window.fastDefinitionState = 'PENDING';
}
var surveyIdRegex = /surveys\/(SV_[a-zA-Z0-9]{15})/;
var canonicalId = (surveyIdRegex.exec(window.location.hash) || [])[1];
var fieldsetIdRegex = /fieldsets\/([\w-]+)/;
var fieldsetId = (fieldsetIdRegex.exec(window.location.hash) || [])[1];
var conjointIdRegex = /surveys\/SV_[a-zA-Z0-9]{15}\?conjointProjectId=(.+)/;
var conjointId = (conjointIdRegex.exec(window.location.hash) || [])[1];
var idpProjectRegex = /fieldsets\/[\w-]+\?(?:projectId|idpProjectId)=(IDP_.+|PROJ_.+)/;
var idpProjectId = (idpProjectRegex.exec(window.location.hash) || [])[1];
var resourceIdRegex = /surveys\/SV_[a-zA-Z0-9]{15}\?resourceId=(.+)/;
var resourceId = (resourceIdRegex.exec(window.location.hash) || [])[1];
var projectIdRegex = /surveys\/SV_[a-zA-Z0-9]{15}\?projectId=(.+)/;
var projectId = (projectIdRegex.exec(window.location.hash) || [])[1];
var url;
if (canonicalId) {
url = '/responses/surveys/' + canonicalId;
} else if (fieldsetId) {
url = '/responses/fieldsets/' + fieldsetId;
} else {
return rejectError(new Error('Missing surveyId for fast definition'));
}
if (conjointId) {
url += '?optProjectId=' + conjointId;
} else if (idpProjectId) {
url += '?idpProjectId=' + idpProjectId;
} else if (resourceId) {
url += '?resourceId=' + resourceId;
} else if (projectId) {
url += '?projectId=' + projectId;
}
window.fastDefinitionUrl = url;
var request = new XMLHttpRequest();
return attemptRequest();
})(window);
</script>
<link rel="icon" href="/brand-management/favicon">
<link rel="apple-touch-icon-precomposed" href="/brand-management/apple-touch-icon">
<link href="/responses/static/vendor/vendor.min.a113b2563.css" rel="stylesheet" type="text/css">
<link href="/responses/static/css/responsesclient.min.a49de54f5.css" rel="stylesheet" type="text/css">
</head>
<body ng-click="checkMenu()" ng-controller="MainController" keep-alive style="margin:0px;">
<div class="dp-container">
<div ng-view></div>
<div q-footer user-id="userId" language="userLanguage"></div>
</div>
</body>
<script src="/responses/static/vendor/vendor.min.a4f381856.js"></script>
<script src="/responses/static/js/responsesclient.min.ad8d40058.js"></script>
<script src="/wrapper/static/client.js"></script>
<script type="text/javascript" src="/project-workflow/static/bundle.js"></script>
<script type="text/javascript" src="https://static-assets.qualtrics.com/static/expert-review-ui/prod/response-iq.js"></script>
<script>
window.Qualtrics = {"User":{"brandId":"mindshare";
function hackAFixForProjectFramework() {
var surveyIdRegex = /surveys\/(SV_[a-zA-Z0-9]{15})/;
var fieldsetIdRegex = /fieldsets\/([\w-]+)/;
var canonicalId = (surveyIdRegex.exec(window.location.hash) || [])[1];
var fieldsetId = (fieldsetIdRegex.exec(window.location.hash) || [])[1];
window.Qualtrics.surveyId = canonicalId || fieldsetId;
}
// Hack a fix for updating to jquery 3.5 breaking project framework as they assumed it was ready sooner with jquery 3.5. Couldn't discover why, but it's somewhere in their code base.
hackAFixForProjectFramework();
var user = _.get(window, 'Qualtrics.User', {}),
requiredUserKeys = [
'userId',
'brandId',
'brandName',
'brandType',
'language',
'email',
'userName',
'firstName',
'lastName',
'accountType',
'accountCreationDate'
];
angular.module('responses-client').config([
'rsw.userServiceProvider',
function(userServiceProvider) {
try {
userServiceProvider.setUser(_.pick(user, requiredUserKeys));
} catch (e) {
console.log(e);
}
}
]);
</script>
</html>
I suspect the problem may be that the website is using a lot of javascript to dynamically change the responses. Above the HTML element I showed above, there are a bunch of "<'script type...'>" and src programs that I don't really understand, though I can guess from the names that they are handling the display of responses. Thinking it might be a loading problem, I've also tried making the program wait before searching for the element, but that didn't work either.
Cheers!
I am trying to build a Rust Web App using Rocket that uploads images from the client.
My problem is that I don't know how to encode the data of an uploaded image (the pixels) into a JSON on the client side. This data would be later send via AJAX.
The POST request here complains that image is not a String, but a map. That is understandable but what I really would like to do is to POST the correct data in the Javascript side (image in the xhr.send()), because I believe that is the part that I am missing.
use rocket_contrib::json::{Json, JsonValue};
#[derive(Deserialize)]
pub struct Image {
file_type: String,
image: String,
message: String,
}
#[post("/img_upload", data = "<image>")]
pub fn upload(image: Json<Image>) -> JsonValue {
// here the back end should do some obscure matrix multiplications
json!({
"message": format!("Message {} received", image.0.message),
"received_type": image.0.file_type,
"image": image.0.image,
})
}
The image is uploaded by the client:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input type="file" name="fileb" id="fileb" />
</body>
<script src="./main_moc.js">
</script>
And this is main_moc.js.
var target_brows = document.getElementById("fileb");
target_brows.addEventListener('change', loadDoc);
// POST REQUEST TO SERVER: upload image
function loadDoc(event) {
var input = target_brows;
var file = input.files[0];
console.log(file);
if (validFileType(file)) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/img_upload");
xhr.onload = function(e) {
if(xhr.status === 200) {
console.log("Received stuff");
var data = JSON.parse(xhr.responseText);
console.log(data);
} else {
console.log("Some error:");
console.log(xhr.responseText);
}
}
xhr.send(JSON.stringify({
"file_type": file.type,
"image": file,
"message": "Apples"
}));
}
}
I also tried to write an image from the file into a canvas and the send data using context.getImageData() but that wasn't working either (error on the client side).
I think I have managed to solve the problem. I use the File API to read the input and then I submit it via POST request.
I am still unsure if this is the best way to do it but at least I can handle it on the server side.
function loadDoc(event) {
// cancel default actions
var file = target_brows.files[0];
var fr = new FileReader();
fr.onload = function () {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/img_upload");
xhr.onload = function(e) {
//The response of the upload
xhr.responseText;
if(xhr.status === 200) {
console.log("Received stuff");
var data = JSON.parse(xhr.responseText);
console.log(data);
} else {
console.log("Some error:");
console.log(xhr.responseText);
}
}
xhr.send(JSON.stringify({
"file_type": file.type,
"image": fr.result,
"message": "Apples"
}));
}
fr.readAsDataURL(file);
}
I am trying working off of https://wiki.apache.org/solr/SolJSON tutorial. I have put my url for solr in the code, copied from solr admin query result to make sure the query should return something.
I try typing in "title:Asian" into text box (that field/search term combo returned results in the admin console query) but when the button is hit, textbox just clears and nothing in output spot.
I used the dev tools from [F12] key of browser to check console and see there was no errors given there, such as for syntax, so not due to that.
Perhaps I am understanding how the url for query works or should be here? If I leave out local host part as shown I just get error for not specifying local full path.
Does anyone see anything wrong here, or have any ideas/tips of what more to do to try and solve the issue?
[ If I must do/add anything else to make good/better post here, please do explain so I can fix :) ]
<html>
<head>
<title>Solr Ajax Example</title>
<meta charset="UTF-8">
<script language="Javascript">
// derived from http://www.degraeve.com/reference/simple-ajax-example.php
function xmlhttpPost(strURL)
{
var xmlHttpReq = false;
var self = this;
if (window.XMLHttpRequest) { // Mozilla/Safari
self.xmlHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open('POST', strURL, true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {
updatepage(self.xmlHttpReq.responseText);
}
};
var params = getstandardargs().concat(getquerystring());
var strData = params.join('&');
self.xmlHttpReq.send(strData);
//document.getElementById("raw").innerHTML = strData;
return false;
}
function getstandardargs() {
var params = [
'wt=json'
, 'indent=on'
, 'hl=true'
];
return params;
}
function getquerystring() {
var form = document.forms['f1'];
var query = form.query.value;
qstr = 'q=' + escape(query);
return qstr;
}
// this function does all the work of parsing the solr response and updating the page.
function updatepage(str)
{
document.getElementById("raw").innerHTML = str;
var rsp = eval("("+str+")"); // use eval to parse Solr's JSON response
var html = "<br>numFound=" + rsp.response.numFound;
var first = rsp.response.docs[0];
html += "<br>product name=" + first.name;
var hl = rsp.highlighting[first.id];
if (hl.name != null) { html += "<br>name highlighted: " + hl.name[0]; }
if (hl.features != null) { html += "<br>features highligted: " + hl.features[0]; }
document.getElementById("result").innerHTML = html;
}
</script>
</head>
<body>
<form name="f1" onsubmit='xmlhttpPost("http://localhost:8983/solr/myCore/select?")'>
<p>query: <input name="query" type="text">
<input value="Go" type="submit"></p>
<div id="result"></div>
<p/><pre>Raw JSON String/output: <div id="raw"></div></pre>
</form>
</body>
</html>
I have an HTML page with a button on it. When I click on that button, I need to call a REST Web Service API. I tried searching online everywhere. No clue whatsoever. Can someone give me a lead/Headstart on this? Very much appreciated.
I'm surprised nobody has mentioned the new Fetch API, supported by all browsers except IE11 at the time of writing. It simplifies the XMLHttpRequest syntax you see in many of the other examples.
The API includes a lot more, but start with the fetch() method. It takes two arguments:
A URL or an object representing the request.
Optional init object containing the method, headers, body etc.
Simple GET:
const userAction = async () => {
const response = await fetch('http://example.com/movies.json');
const myJson = await response.json(); //extract JSON from the http response
// do something with myJson
}
Recreating the previous top answer, a POST:
const userAction = async () => {
const response = await fetch('http://example.com/movies.json', {
method: 'POST',
body: myBody, // string or object
headers: {
'Content-Type': 'application/json'
}
});
const myJson = await response.json(); //extract JSON from the http response
// do something with myJson
}
Your Javascript:
function UserAction() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
alert(this.responseText);
}
};
xhttp.open("POST", "Your Rest URL Here", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send("Your JSON Data Here");
}
Your Button action::
<button type="submit" onclick="UserAction()">Search</button>
For more info go through the following link (Updated 2017/01/11)
Here is another Javascript REST API Call with authentication using json:
<script type="text/javascript" language="javascript">
function send()
{
var urlvariable;
urlvariable = "text";
var ItemJSON;
ItemJSON = '[ { "Id": 1, "ProductID": "1", "Quantity": 1, }, { "Id": 1, "ProductID": "2", "Quantity": 2, }]';
URL = "https://testrestapi.com/additems?var=" + urlvariable; //Your URL
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = callbackFunction(xmlhttp);
xmlhttp.open("POST", URL, false);
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.setRequestHeader('Authorization', 'Basic ' + window.btoa('apiusername:apiuserpassword')); //in prod, you should encrypt user name and password and provide encrypted keys here instead
xmlhttp.onreadystatechange = callbackFunction(xmlhttp);
xmlhttp.send(ItemJSON);
alert(xmlhttp.responseText);
document.getElementById("div").innerHTML = xmlhttp.statusText + ":" + xmlhttp.status + "<BR><textarea rows='100' cols='100'>" + xmlhttp.responseText + "</textarea>";
}
function callbackFunction(xmlhttp)
{
//alert(xmlhttp.responseXML);
}
</script>
<html>
<body id='bod'><button type="submit" onclick="javascript:send()">call</button>
<div id='div'>
</div></body>
</html>
$("button").on("click",function(){
//console.log("hii");
$.ajax({
headers:{
"key":"your key",
"Accept":"application/json",//depends on your api
"Content-type":"application/x-www-form-urlencoded"//depends on your api
}, url:"url you need",
success:function(response){
var r=JSON.parse(response);
$("#main").html(r.base);
}
});
});
I think add if (this.readyState == 4 && this.status == 200) to wait is better:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var response = xhttp.responseText;
console.log("ok"+response);
}
};
xhttp.open("GET", "your url", true);
xhttp.send();
If that helps anyone, if you are ok with an external library then I can vouch for Axios, which has a pretty clean API and rich documentation to deal with REST calls, here's an example below:-
const axios = require('axios');
axios.get('/user?ID=12345')
.then(function (response) {
// handle success
console.log(response);
});
Before we try to put anything on the front end of the website, let's open a connection the API. We'll do so using XMLHttpRequest objects, which is a way to open files and make an HTTP request.
We'll create a request variable and assign a new XMLHttpRequest object to it. Then we'll open a new connection with the open() method - in the arguments we'll specify the type of request as GET as well as the URL of the API endpoint. The request completes and we can access the data inside the onload function. When we're done, we'll send the request.
// Create a request variable and assign a new XMLHttpRequest object to it.
var request = new XMLHttpRequest()
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', 'https://ghibliapi.herokuapp.com/films', true)
request.onload = function () {
// Begin accessing JSON data here
}
}
// Send request
request.send()
By far, the easiest for me is Axios. You can download the node module or use the CDN for your simpler projects.
CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Code example for GET/POST:
let postData ={key: "some value"}
axios.get(url).then(response =>{
//Do stuff with the response.
})
axios.post(url, postData).then(response=>{
//Do stuff with the response.
});
Without a doubt, the simplest method uses an invisible FORM element in HTML specifying the desired REST method. Then the arguments can be inserted into input type=hidden value fields using JavaScript and the form can be submitted from the button click event listener or onclick event using one line of JavaScript. Here is an example that assumes the REST API is in file REST.php:
<body>
<h2>REST-test</h2>
<input type=button onclick="document.getElementById('a').submit();"
value="Do It">
<form id=a action="REST.php" method=post>
<input type=hidden name="arg" value="val">
</form>
</body>
Note that this example will replace the page with the output from page REST.php.
I'm not sure how to modify this if you wish the API to be called with no visible effect on the current page. But it's certainly simple.
Usual way is to go with PHP and ajax. But for your requirement, below will work fine.
<body>
https://www.google.com/controller/Add/2/2<br>
https://www.google.com/controller/Sub/5/2<br>
https://www.google.com/controller/Multi/3/2<br><br>
<input type="text" id="url" placeholder="RESTful URL" />
<input type="button" id="sub" value="Answer" />
<p>
<div id="display"></div>
</body>
<script type="text/javascript">
document.getElementById('sub').onclick = function(){
var url = document.getElementById('url').value;
var controller = null;
var method = null;
var parm = [];
//validating URLs
function URLValidation(url){
if (url.indexOf("http://") == 0 || url.indexOf("https://") == 0) {
var x = url.split('/');
controller = x[3];
method = x[4];
parm[0] = x[5];
parm[1] = x[6];
}
}
//Calculations
function Add(a,b){
return Number(a)+ Number(b);
}
function Sub(a,b){
return Number(a)/Number(b);
}
function Multi(a,b){
return Number(a)*Number(b);
}
//JSON Response
function ResponseRequest(status,res){
var res = {status: status, response: res};
document.getElementById('display').innerHTML = JSON.stringify(res);
}
//Process
function ProcessRequest(){
if(method=="Add"){
ResponseRequest("200",Add(parm[0],parm[1]));
}else if(method=="Sub"){
ResponseRequest("200",Sub(parm[0],parm[1]));
}else if(method=="Multi"){
ResponseRequest("200",Multi(parm[0],parm[1]));
}else {
ResponseRequest("404","Not Found");
}
}
URLValidation(url);
ProcessRequest();
};
</script>
<!doctype html>
<html>
<head>
<title>Twitter</title>
<meta charset="utf-8">
<script>
window.onload = function () {
// set up the click handler for the form button
var button = document.getElementById("submit");
button.onclick = getTweets;
}
// when you click "Get Tweets" we call this function
function getTweets() {
// set up a new XHR request
var xhr = new XMLHttpRequest();
// we're calling search.php and passing in a query string
var url = "search.php?query=";
var query = document.getElementById("query").value;
if (!query) {
query = "html5";
}
// we encode the query to handle any special characters properly
url += encodeURIComponent(query);
// this is the function that is called when the XHR request
// to our search.php script is handled, and a response sent back
xhr.onload = function () {
// if everything went okay, then send the response data
// to the displayTweets() function
if (xhr.status == 200) {
displayTweets(xhr.responseText);
} else {
var errorDiv = document.getElementById("error");
errorDiv.innerHTML = "Error getting tweets: " + xhr.status;
}
};
// make the request!
xhr.open("GET", url);
xhr.send(null);
}
function displayTweets(tweets) {
// tweets is a big long string, so we need to parse it
// into JSON first
tweets = JSON.parse(tweets);
var ul = document.querySelector("ul");
// clear existing tweets from list
while (ul.hasChildNodes()) {
ul.removeChild(ul.lastChild);
}
// add new tweets
for (var i = 0; i < tweets.length; i++) {
var li = document.createElement("li");
li.innerHTML = tweets[i].tweet;
ul.appendChild(li);
}
}
</script>
</head>
<body>
<form>
Query:
<input type="text" id="query">
<input type="button" id="submit" value="Get Tweets">
</form>
<div id="error"></div>
<ul></ul>
</body>
</html>
In the above code when I enter some text in the textbox and click on "Get Tweets" button it gives an error as Error getting tweets: 0. The search.php when executed independently without embedding in html and javascript gives accurate and required results.Can you please check the html and js code and suggest any changes in code??
Seems that the issue is CROSS-DOMAIN Ajax issue. When you execute the search.php independently, then there is no X-domain issue. But when you are embedding the code in some html, check if the html is part of the same domain or not. Also, if you are trying to run the html file from file:/// it will not work.