I'm trying to develop an 'autocomplete' feature on element which will get data from the remote database (using simple HTTP GET requests which will return JSON).
In the workflow form, in share-conifg-custom.xml i provided control template:
<control template="/com/test/mytest.ftl"/>
And this is mytest.ftl:
<input type="text" name="search" id="search" placeholder="Type Something" list="searchresults" autocomplete="off">
<datalist id="searchresults"></datalist>
<script type="text/javascript">
myHttp = new XMLHttpRequest();
url='https://jsonplaceholder.typicode.com/posts';
myHttp.open("GET", url);
myHttp.send();
myHttp.onreadystatechange = (e) => {
var arr = JSON.parse(myHttp.responseText);
for (var i =0; i < arr.length; i++) {
var option = document.createElement("OPTION");
option.setAttribute("value", arr[i]["title"]);
document.getElementById("searchresults").appendChild(option);
}
}
</script>
The problem is that it does not send any requests.
What am I missing here?
As far as I understand, Freemarker template should convert it to HTML code and <script> tag should be executed on my browser.
Related
I want a link "Run this in " just below each PRE-CODE block.
The link should popup a new tab with any online compiler/interpreter and the code of the block.
I don't know if there is a solution already done. Like highlight.js but do this. So I tried my own approach unsuccessfully. I want to keep the HTML simple and clean.
Picked jdoodle as starting point, but the idea is to have options.
The HTML form, works! Either by redirecting or by changing the target to a new tab.
Now I want this working without the HTML FORM (to keep the HTML simple and clean) and do this in a javascript function call.
With XMLHttpRequest to perform the POST call, I get errors on CORS policy.
Access to XMLHttpRequest at 'https://www.jdoodle.com/api/redirect-to-post/execute-lua-online/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
I believe that this doesn't happens with HTML-FORM because it redirects and origin gets to be the same.
So I tried unsuccessfully to either use XMLHttpRequest to redirect or popup into jdoodle but I cant get to transfer the POST data containing the code.
My non-working-javascript-example
<pre><code class="language-lua">
print("hello jdoodle")
</code></pre>
Run this on jDoodle.
<form id="inputform" method="post" action=
"https://www.jdoodle.com/api/redirect-to-post/execute-lua-online/" target="_blank">
<textarea name="initScript"
rows="4" cols="20">
print("Either redirecting or in a tab, it works!")
</textarea>
<br/><br/>
<input type="submit" value="Test">
</form>
<script>
function runthis(caller) {
prev_el = caller.previousElementSibling;
code_el = prev_el.getElementsByTagName("CODE")[0];
code_str = code_el.innerText;
alert(code_str);
var handle=window.open("https://www.jdoodle.com/api/redirect-to-post/execute-lua-online/");
const http = new XMLHttpRequest();
http.open('POST', 'https://www.jdoodle.com/api/redirect-to-post/execute-lua-online/', true);
http.onload = function () {
console.log(this.responseText);
};
FD = new FormData();
FD.append('initScript', code_str);
FD.append('submit', 'Test');
alert(JSON.stringify(FD)); // it shows empty ¿why?
http.send(FD);
}
</script>
Answering my own question, but I would always appreciate better alternatives.
As the HTML Form was working, the first step is to reproduce this in javascript, and this is not done with XMLHttpRequest.
function runthis_on_external_site(pre_elem, url, textareaname="initScript" ) {
code_el = pre_elem.getElementsByTagName("CODE")[0];
code_str = code_el.innerText;
var form_elem = document.createElement("FORM");
form_elem.method = "POST";
form_elem.action = url;
form_elem.target = "_blank";
var element1 = document.createElement("TEXTAREA");
element1.name=textareaname;
element1.innerHTML = code_str;
form_elem.appendChild(element1);
document.body.appendChild(form_elem);
form_elem.submit();
form_elem.remove();
}
Then a link must be added below each <PRE><CODE> block after the page is loaded.
function insert_A_tag_after_( pre_elem, inner, url, textareaname) {
A = document.createElement("A");
A.className = 'ref';
A.href = '#';
A.innerHTML = inner;
A.onclick = function() {
runthis_on_external_site( pre_elem, url, textareaname);
};
pre_elem.parentNode.insertBefore(A, pre_elem.nextSibling);
}
//========================================================
window.addEventListener('DOMContentLoaded', function() {
console.log('Adding external Compilers/Interpreters');
document.querySelectorAll( 'code' ).forEach((e) => {
if( e.classList.contains( 'language-lua' ) ){
url = "https://www.jdoodle.com/api/redirect-to-post/execute-lua-online/";
insert_A_tag_after_( e.parentNode, "jDoodle", url, "initScript" );
url = "https://www.lua.org/cgi-bin/demo";
insert_A_tag_after_( e.parentNode, "lua.org", url, "input" );
}
})
});
NOTE: that, I have only found jDoodle and lua.org/cgi-bin/demo so far to be able to get the code from a POST variable. Others online compilers would be appreciated.
NOTE2: I picked the class name as 'language-lua' for compatibility with highlight.js
NOTE3: As far as I could research, I couldn't found any other popular alternative solution for this. Most solutions are to embed a compiler/editor from only one site.
I have a Google Form to collect information from my workers working in remote locations
Emp No *
Punch *
Customer details / mode or travel
The data goes into a Google spreadsheet with the below structure
Timestamp Emp No Punch Remark Name GeoCode GeoAddress Email
I am able to capture the GPS co-ordinates of the user by the below script. I made a web app (anyone even anonymous can run) and asked the user to click the link.
What I am not able to do :
I want to save the email ID (or emp no) of the user filling the form. But the email ID is not getting captured into the form. If I fill the form, the email ID is captured. For other users it is not captured. I don't want all the users to authenticate the script (to run the script as the logged in user). It must be captured by some other way. Is it possible?
If the GPS is not captured (it is empty), I want to display a different message in the HTML page. How to do it?
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("Index");
}
//
function getLoc(value) {
var destId = FormApp.getActiveForm().getDestinationId() ;
var ss = SpreadsheetApp.openById(destId) ;
var respSheet = ss.getSheetByName("Location");
var numResponses = respSheet.getLastRow();
var currentemail = Session.getActiveUser().getEmail();
var c=value[0]; var d=value[1];
var e=c + "," + d ;
//respSheet.getRange(numResponses,6).setValue(e);
//respSheet.getRange(numResponses,8).setValue(currentemail);
var response = Maps.newGeocoder().reverseGeocode(value[0], value[1]);
var f= response.results[0].formatted_address;
//respSheet.getRange(numResponses,7).setValue(f);
respSheet.getRange(numResponses,6,1,3 ).setValues([[ e, f, currentemail ]]);
}
//
index.html
<!DOCTYPE html>
<html>
<script>
(function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
})()
function showPosition(position){
var a= position.coords.latitude;
var b= position.coords.longitude;
var c=[a,b]
getPos(c)
function getPos(value){
google.script.run.getLoc(value);
}
}
</script>
<body>
<p>Please ensure your GPS is on to record your location. You can generate the report from website to check. Pl. close this window (version 3)</p>
</body>
</html>
From the question
I want to save the email ID (or emp no) of the user filling the form. But the email ID is not getting captured into the form. If I fill the form, the email ID is captured. For other users it is not captured. I don't want all the users to authenticate the script (to run the script as the logged in user). It must be captured by some other way. Is it possible?
On a web application created using Google Apps Script to automatically get the user email ID you could set your web application to be executed as the user running the application instead being executed as you but if don't want to use this feature then you have to set your own authentication process.
From the question
If the GPS is not captured (it is empty), I want to display a different message in the HTML page. How to do it?
Use a JavaScript conditional expression
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
alert('Can\'t get the position');
}
})()
function showPosition(position){
var a= position.coords.latitude;
var b= position.coords.longitude;
var c=[a,b];
getPos(c);
function getPos(value){
google.script.run.getLoc(value);
}
}
The above code uses alert but you could use the DOM.
Resources
Web Apps | Google Apps Script
Document Object Model (DOM)
I was able to make a complete solution without any google form (just HTML) and managed to display an alert message also. The "Login" is still not possible.
Code.gs
It runs the form and saves the answers in the required columns into google sheet.
It runs faster than google form and "Submit" has to be clicked only once.
As the saving happens by "append row", the jumbling of data (between rows) which was happening in my earlier method is avoided.
/* #Include JavaScript and CSS Files */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
/* #Process Form */
function processForm(formObject) {
var url = "https://docs.google.com/spreadsheets/d/...../edit#gid=52499297";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Location");
var response = Maps.newGeocoder().reverseGeocode(formObject.lat, formObject.long);
var address= response.results[0].formatted_address;
ws.appendRow(
[
new Date(),
formObject.empno,
formObject.punch,
formObject.rem,
"",
formObject.lat+","+formObject.long,
address
]
);
}
Index.html
This has the questions.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<?!= include('JavaScript'); ?>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-6">
<form id="myForm" onsubmit="handleFormSubmit(this);">
<p class="h4 mb-4 text-left">Record Attendance and Location</p>
<div class="form-group">
<label for="empno">Emp No - Click to see list</label>
<input type="number" class="form-control" id="empno" name="empno" min="1" max="9999999" required>
</div>
<div class="form-group">
<label for="punch">Punch (Select one)</label>
<select class="form-control" id="punch" name="punch" required>
<option selected disabled hidden style='display: none' value=''></option>
<option value="In">In</option>
<option value="Out">Out</option>
<option value="Started">Started</option>
<option value="Reached">Reached</option>
</select>
</div>
<div class="form-group">
<label for="rem">Remark</label>
<input type="text" class="form-control" id="rem" name="rem">
</div>
<div class="form-group">
<input type="hidden" class="form-control" id="lat" name="lat">
<input type="hidden" class="form-control" id="long" name="long">
</div>
<button type="submit" class="btn btn-primary btn-block">Submit</button>
</form>
<div id="output"></div>
</div>
</div>
</div>
</body>
</html>
JavaScript.html
This processes the answers
<script>
function showPosition() {
navigator.geolocation.getCurrentPosition(showMap);
}
function showMap(position) {
// Get location data
var lat = position.coords.latitude;
var geo1 = document.getElementById("lat");
geo1.value = lat;
var long = position.coords.longitude;
var geo2 = document.getElementById("long");
geo2.value = long;
}
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
window.addEventListener('load', showPosition);
function handleFormSubmit(formObject) {
google.script.run.processForm(formObject);
document.getElementById("myForm").reset();
alert('Data saved successfully');
}
</script>
I am trying to get information from a form without using a submit button. First I need to build a query string and then I need to make an ajax request to a URL that contains a program that will take the information from the forms to calculate the mileage from one city to the other. here is my http file:
<!DOCTYPE html>
<html>
<head>
<title>Mileage Calculator</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<h1>Mileage Calculator</h1>
<form>
Start City<input type="text" id="startCity" name="startCity"></input><br><br>
Start State<input type="text" id="startState" name="startState"></input><br><br>
End City<input type="text" id="endCity" name="endCity"></input><br><br>
End State<input type="text" id="endState" name="endState"></input><br><br>
<input type="button" onclick="buildQuery()" value="Submit"></input>
</form>
<p id="justTry">Let's see if we can change this guy</p>
<script src="assign12.js"></script>
</body>
</html>
I am using an onclick event to call a javascript function that collects all the form info and arranges it into a query string. Here is that function "buildQuery()" :
function buildQuery() {
startcity = document.getElementById("startCity").value;
startstate = document.getElementById("startState").value;
endcity = document.getElementById("endCity").value;
endstate = document.getElementById("endState").value;
var params = {
startcity,
startstate,
endcity,
endstate
};
var esc = encodeURIComponent;
var query = Object.keys(params)
.map(k => esc(k) + '=' + esc(params[k]))
.join('&');
loadSite(query);
}
the buildQuery() function then calls the loadQuery(query) function which makes an ajax request. This is were I am having trouble. the query string must be appended to the URL so it can take the form info and calculate the mileage, but I'm not sure how to get that to happen. here is what I have so far:
function loadSite(query) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
appendQuery(this.responseText);
//document.getElementById("justTry").innerHTML = url;
}
};
var url = "/cgi-bin/ercanbracks/mileage/mileageAjaxJSON" + query;
xhttp.open("POST", "/cgi-bin/ercanbracks/mileage/mileageAjaxJSON", true)
xhttp.send();
}
what is the best way to accomplish this task?
thanks, Megan
First thing first, you should not manually select all the inputs with ids. Instead I would recommend selecting the inputs using querySelectorAll as below
function getFormPayload(formId){
const payload = {};
for(const input of document.querySelectorAll(`form#${formId} *[name]`)){
payload[input.getAttribute('name')] = input.value;
}
return payload;
}
With the function above you can then iterate through the value and create the query as you initially did.
p/s: Note that some elements like select doesn't have value attribute so you would need to wrap the value assign in an if statement. Good luck!
I am trying to display Json Response in input checkbox tag on button click. But i am unable to do it.
Can anyone guide me how to do it.
Below is the code -
<!DOCTYPE html>
<html>
<body>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
<label><input type="checkbox" name="test_name" value=""></label>
<button type="button" onclick="loadDoc()">Change Content</button>
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementsByName('test_name').innerHTML = JSON.stringify(this.responseText,undefined, 2).replace(/\\n/g, "").replace(/\\r/g, "")
.replace(/\\/g, "")
.replace(/^"/, "")
.replace(/"$/, "");
var jsonobj = JSON.parse(document.getElementsByName('test_name').innerHTML);
for ( var i=0;i<jsonobj.length; i++)
{
console.log(jsonobj[i].Newsletter_Name);
var label = document.getElementsByName('test_name');
console.log(label);
label.value= jsonobj[i].Newsletter_Name;
};
}
};
xhttp.open("GET", "https://members.s7.exacttarget.com/Pages/Page.aspx?QS=38dfbe491fab00ea764e20685ddf905a854eb2c63c649afb00651f16b30a4189&brand_code=PE", true);
xhttp.send();
}
</script>
</body>
</html>
Json Return - There will be a lot of data. But i am displaying few.
[{
"Test_Name": "FOOD",
"Brand": "Test"
},
{
"Test_Name": "HOME",
"Brand": "Test"
}]
Sticking with jQuery only (read more here) - to tick the checkboxes from the values in your JSON, you can do something like this:
$.ajax({
url: "https://testendpoint/",
dataType: "json",
success: function (response) {
if (response) {
// Tick checkboxes from JSON
for (var i=0; i<json.length; i++) {
$('#' + json[i].Newsletter_Name).prop('checked', true);
}
}
}
});
That is assuming your checkboxes look something like this:
<div>
<input id="FOOD" type="checkbox" value="FOOD">
<label for="Food">Food</label>
<input id="HOME" type="checkbox" value="HOME">
<label for="Home">Home</label>
</div>
I can't access the URL you are using, so I'll give an example using Librivox.org API:
A couple of points:
1: You don't need to populate a DOM innerText first - the returned value is available already.
2: Unless you have a good reason (performance usually) you should use JQuery as others have said because it hides x-browser issues when using native XMLHTTPRequest.
3: I think you are trying to render a checkbox per item returned. This is what I will show.
The proxy used is simply a C# handler to pass the request to the remote server, so I don't run into cross-domain request issues. The response is exactly as returned directly from the following call:
https://librivox.org/api/feed/authors?format=json
JQuery will automatically convert the returned JSON string into a Javascript object - which you can see with the console.log() statement.
The code makes a request to the remote server (Librivox) and returns a list of data (authors) as a JSON string. Because I passed the type 'json' as the expected return type, JQuery will automatically convert the data into a usable Javascript object.
The rest of the code just builds up a collection of checkboxes, and appends to a specified DOM element.
It would be straightforward to attach click handlers to each checkbox to further process the data.
<!DOCTYPE html>
<html>
<body>
<script src="js/libs/jquery/jquery.js" type="text/javascript"></script>
<label><input type="checkbox" name="test_name" value=""></label>
<div id="test"><!-- Appending checkboxes here -->
</div>
<button type="button" id="loaddoc">Change Content</button>
<script>
var proxyUrl = "/proxy/proxy.aspx";
$(function(){
$.ajax(proxyUrl + "?endpoint=api/feed/authors",{
dataType:"json"
}).complete(function(data){
//log data:
console.log(data);//big list of authors
var dv = document.createElement("div");
//build checkboxes...
for(var a=0;a<data.responseJSON.authors.length;a++){
var lbl = document.createElement("label");
lbl.appendChild(document.createTextNode(data.responseJSON.authors[a].last_name));
var chk = document.createElement("input");
chk.setAttribute("type","checkbox");
chk.setAttribute("name",data.responseJSON.authors[a].last_name);
chk.setAttribute("value",data.responseJSON.authors[a].id);
lbl.appendChild(chk);
dv.appendChild(lbl);
}
//append to element:
$("#test")[0].appendChild(dv);
});
});
</script>
</body>
</html>
I am trying to post some json data to REST web service implemented with Jersey framework. I am not using JAXB or jquery but only javascript.
I verified that formed json is correct but in spite of setting content type "application/json", on server it is received as "application/x-www-form-urlencoded".
Here is my code:
<html>
<head>
<script type="text/javascript">
function DisplayFormValues()
{
var str = {};
var elem = document.getElementById('frmMain').elements;
//alert(elem.length);
for(var i = 0; i < elem.length-1; i++)
{
str[elem[i].name] = elem[i].value;
}
document.getElementById('lblValues').innerHTML = str;
var json = JSON.stringify(str);
// construct an HTTP request
var xhr = new XMLHttpRequest();
xhr.open(document.getElementById('frmMain').method,
document.getElementById('frmMain').action);
xhr.setRequestHeader("Content-type", "application/json");
xhr.setRequestHeader("Content-Length",json.length);
xhr.setRequestHeader('Accept', 'application/json');
//alert(json);
// send the collected data as JSON
xhr.send(json);
xhr.onloadend = function() {
// done
}
}
</script>
</head>
<body>
<form id="frmMain" name="frmMain" action="/JerseyTest/rest/postUser"
method="post">
<input name="firstName" value="harry" /> <input name="lastName"
value="tester" /> <input name="toEmail" value="testtest#test.com" />
<br /> <input type="submit" value="Test"
onclick="DisplayFormValues();" />
</form>
<hr />
<div id="lblValues"></div>
</body>
</html>
On the server side:
package com.example.jersey.test;
import javax.ws.rs.*;
#Path("/postUser")
public class JsonTest {
#POST
#Consumes("application/json")
#Produces(MediaType.TEXT_PLAIN)
public String pingPong(String json) {
return "Answer is "+ json;
}
}
I am new to web development and not sure on what I am missing in above code.
I am answering my own question for those who may visit this later. The code above is correct and works well except the fact that the url is been hit twice. First time, for submit button's default action and then as per our script by XMLHttpRequest.
This I came to know after I checked the headers in Httpfox which showed error as NS_BINDING_ABORTED.
After changing the input type to button from submit, all is working fine.