<input type="text" id="tnum" maxlength="50" placeholder="Enter Your Tracking ID" />
<input class="btn" type="button" value="TRACK" onclick="doTrack()" />
<div id="YQContainer"></div>
So basically, I have a page that can track packages for my customers. I want to be able to send them a link in their email that will automatically track their package from the link. ( they don't have to type in their tracking id and click track when they go to my tracking page )
example.com/track?tnum=3298439857
This is what i'm using to track packages.
https://www.17track.net/en/externalcall/single
The basic idea is as follows:
Wait for page to load
Parse the URL and extract needed query parameter
Set the value of the form element
Call the doTrack() function
// Handy function to parse the URL and get a map of the query parameters
function parseQueryParameters(url) {
var qp = {};
if (!url) {
return qp;
}
var queryString = url.split('?')[1];
if (!queryString) {
return qp;
}
return queryString.split('&')
.reduce(function(m, d) {
var splits = d.split('=');
var key = splits[0];
var value = splits[1];
if (key && value) {
m[key] = value;
}
return m;
}, qp);
}
//Wait for page to load
window.onload = function() {
//Extract tnum query parameter
var qp = parseQueryParameters(window.location.href);
//If no parameter is provided, do nothing
if (!qp.tnum) return;
//Set the value of the form element
document.getElementById("tnum").value = qp.tnum;
// Call doTrack
doTrack();
}
//Temporary doTrack function - remove when integrating ;)
function doTrack() {
console.log(document.getElementById("tnum").value)
}
<input type="text" id="tnum" maxlength="50" placeholder="Enter Your Tracking ID" />
<input class="btn" type="button" value="TRACK" onclick="doTrack()" />
<div id="YQContainer"></div>
<html>
<head>
<script>
function setURL(){
var dt_value = document.getElementById("tnum").value;
//just test here ..what is coming..
alert(dt_value );
var sjdurl = "example.com/track?tnum="+dt_value;
popup = window.open(sjdurl,"popup"," menubar =0,toolbar =0,location=0, height=900, width=1000");
popup.window.moveTo(950,150);
}
</script>
</head>
<body>
<input type="Text" id="tnum" maxlength="25" size="25"/>
<input type='button' onclick='setURL()' value='SUBMIT'>
</body>
</html>
function doTrack(tnum) {
var trackNumber = tnum;
window.open("example.com/track?tnum="+trackNumber);
}
$(".btn").on('click',function(e) {
e.preventDefault();
var tnum = $('#tnum').val();
if (tnum!="") {
doTrack(tnum);
} else {
return false;
}
});
Related
I have followed a tutorial "Create HTML Form that Moves through RecordSet on Google Sheets" done by Code With Curt.
https://www.youtube.com/watch?v=V9ptq7tZV50&t=152s
The project doesn't look that complicated. It is a simple CRUD app that I want to run in a modal dialog in google sheets, I am a newbie, I really tried to understand the code that I was copying from the video and not make any typos. The form shows up OK from the custom menu but it is not populating with the data from the sheet. The only error I can see is in the console which says "Uncaught ReferenceError: loadRecords is not defined" I have double checked the variable and function names but just can't see the error.
Any help would be appreciated.
Code.gs
function getList()
{
var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
var ss= SpreadsheetApp.openByUrl(url);
//var ss = SpreadsheetApp.getActiveSpreadsheet();
var recordSheet = ss.getSheetByName("WebInscriptions");
var getLastRow = recordSheet.getLastRow();
return recordSheet.getRange(2, 1, getLastRow -1, 9).getValues();
}
function startForm()
{
var form = HtmlService.createHtmlOutputFromFile("Modal");
SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}
function addMenu()
{
var ui = SpreadsheetApp.getUi()
ui.createMenu('HR-Recruitment')
.addItem('New Submissions','startForm')
.addItem('Manage Recruits','startForm')
.addToUi();
}
function onOpen(e)
{
addMenu;
}
Modal.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function loadRecords(record)
{
google.script.run.withSuccessHandler
(function(ar)
{
var record = document.getElementById("record").value;
//console.log (ar);
//console.log (record);
var recordCount = 0;
ar.forEach(function(item, index)
{
if(index == record - 1)
{
document.getElementById("inscriptionDate").value = item[0];
document.getElementById("firstName").value = item[1];
document.getElementById("lastName").value = item[2];
document.getElementById("gender").value = item[3];
document.getElementById("email").value = item[4];
document.getElementById("telNumWhatsApp").value = item[5];
document.getElementById("location").value = item[6];
document.getElementById("visaImageUpload").value = item[7];
document.getElementById("commentMessage").value = item[8];
document.getElementById("referrer").value = item[9];
}
recordCount ++;
});
console.log (recordCount);
document.getElementById("maxRecord").value = recordCount;
}).getList();
}
function NextRecord()
{
var record = document.getElementById("record").value;
var maxRecord = document.getElementById("maxRecord").value;
var nextRecord = Number record + 1;
if(nextRecord <= maxRecord)
{
document.getElementById ("record").value = nextRecord;
loadRecords();
}
}
function PreviousRecord()
{
var record = document.getElementById("record").value;
var previousRecord = Number record - 1;
if(previousRecord >= 1)
{
document.getElementById ("record").value = previousRecord;
loadRecords();
}
}
//loadRecords();
</script>
</head>
<body>
Inscription Date: <input type="text" id="inscriptionDate"/><br>
First Name: <input type="text" id="firstName"/><br>
Last Name: <input type="text" id="lastName"/><br>
Gender: <input type="text" id="gender"/><br>
Email: <input type="text" id="email"/><br>
Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/><br>
Location: <input type="text" id="location"/><br>
VISA Image Upload: <input type="text" id="visaImageUpload"/><br>
Comment or Message: <input type="text" id="commentMessage"/><br>
Referrer: <input type="text" id="referrer"/><br>
<input type="button" value = "PREVIOUS" onclick="PreviousRecord"/>
<input type="text" value="1" id="record" size="2px"/>
<input type="hidden" id="maxRecord"/>
<input type="button" value = "NEXT" onclick="NextRecord"/>
<script>loadRecords();</script>
</body>
</html>
Google Sheet image
Regarding the specific error, the parenthesis are missing in two lines:
var nextRecord = Number record + 1;
var previousRecord = Number record - 1;
Correct syntax
var nextRecord = Number(record) + 1;
var previousRecord = Number(record) - 1;
As mentioned in the Yuri's answer, the video that you used looks to have some problems. From my point of view it's obsolete, one hint is that it's using the now called "Classic Editor" instead of the current default editor. It's weird that the comment with the code was removed, next time start with a more recent example and once you have learned how to debug and learned the differences between the "old" Google Apps Script and the new (i.e. old runtime based on Mozilla Rhino, and the new runtime Chrome V8), go to old tutorials / examples.
P.S. It might be possible that if you are using new editor that your project is using the new runtime, if you want to try the code as is in the video, try enabling the Rhino runtime, for details see https://developers.google.com/apps-script/guides/v8-runtime.
Related
How to go about debugging JavaScript in the HtmlService in Google Scripts
Debugging client side code from Google Apps Script
Given that the youtube guy removed his code and doesn't answer on comments it's obviously that there is something terribly wrong with his code.
As far as I can tell the main problem was that you can't return an array from the function getList() into the HTML form. You need to convert it into a string with return JSON.stringify(array) and then (within HTML form) to convert it back into an array with var array = JSON.parse(array).
Basically, if you add the JSON.stringify and JSON.parse and add the brackets as #Rubén said, it should work.
Just in case, here is my a bit rewritten code:
Modal.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function NextRecord() {
var record = document.getElementById("record").value;
var maxRecord = document.getElementById("maxRecord").value;
var nextRecord = +record + 1;
if(nextRecord <= maxRecord) {
document.getElementById ("record").value = nextRecord;
google.script.run.withSuccessHandler(loadRecords).getList();
}
}
function PreviousRecord() {
var record = document.getElementById("record").value;
var previousRecord = +record - 1;
if(previousRecord >= 1) {
document.getElementById ("record").value = previousRecord;
google.script.run.withSuccessHandler(loadRecords).getList();
}
}
function loadRecords(ar) {
ar = JSON.parse(ar); // <--- here we parse the string back into an array
var record = document.getElementById("record").value;
document.getElementById("maxRecord").value = ar.length;
var item = ar[+record-1];
document.getElementById("inscriptionDate").value = item[0];
document.getElementById("firstName").value = item[1];
document.getElementById("lastName").value = item[2];
document.getElementById("gender").value = item[3];
document.getElementById("email").value = item[4];
document.getElementById("telNumWhatsApp").value = item[5];
document.getElementById("location").value = item[6];
document.getElementById("visaImageUpload").value = item[7];
document.getElementById("commentMessage").value = item[8];
document.getElementById("referrer").value = item[9];
}
google.script.run.withSuccessHandler(loadRecords).getList();
</script>
</head>
<body>
Inscription Date: <input type="text" id="inscriptionDate"/><br>
First Name: <input type="text" id="firstName"/><br>
Last Name: <input type="text" id="lastName"/><br>
Gender: <input type="text" id="gender"/><br>
Email: <input type="text" id="email"/><br>
Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/><br>
Location: <input type="text" id="location"/><br>
VISA Image Upload: <input type="text" id="visaImageUpload"/><br>
Comment or Message: <input type="text" id="commentMessage"/><br>
Referrer: <input type="text" id="referrer"/><br>
<input type="button" value = "PREVIOUS" onClick="PreviousRecord()"/> // <-- don't forget the brackets here
<input type="text" value = "1" id = "record" size = "2px"/>
<input type="hidden" value = "" id = "maxRecord"/>
<input type="button" value = "NEXT" onClick="NextRecord()"/> // <-- don't forget the brackets here
</body>
</html>
Code.gs
function getList(){
var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
var ss= SpreadsheetApp.openByUrl(url);
// var ss = SpreadsheetApp.getActiveSpreadsheet();
var recordSheet = ss.getSheetByName("WebInscriptions");
var lastRow = recordSheet.getLastRow();
var list = recordSheet.getRange(2, 1, lastRow-1, 10).getValues();
return JSON.stringify(list); // <--- here we return a string instead of the array
}
function startForm() {
var form = HtmlService.createHtmlOutputFromFile("Modal.html");
SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}
function addMenu() {
var ui = SpreadsheetApp.getUi()
ui.createMenu('HR-Recruitment')
.addItem('New Submissions','startForm')
.addItem('Manage Recruits','startForm')
.addToUi();
}
function onOpen(e) { addMenu() }
hey i am trying to make a phonebook where everytime i add someones name and phonenumber it displays it into the front page and then i can remove or edit...
now i have tried to add a remove function so it removes only the one row or name i choose after many tries i noticed in the application(in the inspect where the developers tools) there is only one key and it seems like i am storing all the arrays (values) into it , now what if i want to remove one value only from the key i am not sure if its possible
maybe i have to make it so i have multiple keys with each key with its own value i am not sure
this is my js code
"use strict";
function showOverlay(showButton, showContainer) { // this whole funciton opens up the overlay
const addButton = document.querySelector("." + showButton);
addButton.addEventListener("click", function addSomthing() {
document.querySelector("." + showContainer).style.display = 'block';
});
} //end of function
showOverlay("addBtn", "formContainer");
function cancelOverlay(cancelButton, showContainer) { //this dynamic funciton helps with closing overlays after we are done with the event
const removeOverlay = document.querySelector("." + cancelButton);
removeOverlay.addEventListener("click", function removeSomthing() {
document.querySelector("." + showContainer).style.display = 'none';
});
} //end of function
cancelOverlay("cancelOverlay", "formContainer");
//
let phoneArray = [];
window.onload = init;
const submitButton = document.getElementById("submitButton");
submitButton.addEventListener("click", function addPerson() {
const person = {
name: document.getElementById("name").value,
phoneNumber: document.getElementById("phone").value
};
if (person.name != "" && person.phoneNumber != "") {
phoneArray = JSON.parse(localStorage.getItem("person")) || [];
phoneArray.push(person);
localStorage.setItem("person", JSON.stringify(phoneArray));
phoneArray = localStorage.getItem("person");
phoneArray = JSON.parse(phoneArray);
window.location.reload(true);
} //end if
} //end addPerson)
);
function createLayout(person) {
const divv = document.getElementById("outPutContainer");
let row = document.createElement("ul");
row.innerHTML = `
<li>${person.name} </li>
<li>${person.phoneNumber} </li>
<button class="insideRemoveBtn"> - </button>
`;
divv.appendChild(row);
} //end of function
function getPersonArray() {
return JSON.parse(localStorage.getItem("person"));
} //end of function
function init() {
const personArray = getPersonArray();
for (let i = 0; i < personArray.length; i++) {
const person = personArray[i];
createLayout(person);
const insideRemoveBtn = document.querySelector(".insideRemoveBtn");
insideRemoveBtn.addEventListener("click", function removeSingleItem() {
localStorage.removeItem('person');
location.reload(true);
});
}
} //end of function
const removeAllBtn = document.getElementById("removeAllBtn");
removeAllBtn.addEventListener("click", function removeAll() {
localStorage.clear();
location.reload(true);
});
and this is my html code if needed
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PhoneBook</title>
<link rel="stylesheet" href="Css/Whole.css">
<script defer src="JavaScript/PU.js"></script>
</head>
<body>
<h1>PhoneBook</h1>
<div class="childContainer">
<div class="buttonsContainer">
<div>
<input type="search" placeholder="search" class="searchBar"></div>
<div class="buttonsRightSide"> <button value="submit" id="addBtn" class="addBtn">+</button>
<button value="submit" id="removeAllBtn" class="removeAllBtn">-</button>
<button value="submit" id="saveBtn" class="saveBtn">*</button></div>
</div>
<div class="formContainer">
<form class="addForm" id="addForm">
<h2>Create Contact</h2>
<label for="name">First name*:</label>
<input id="name" type="text" pattern="[A-Z][a-zA-Z]{3,7}" required><br>
<label for="phoneNumber">Phone number*:</label>
<input id="phone" type="number" pattern="[0][5][0-8][ -]?\d{7}" required><br>
<label for="Adress">Address:</label>
<input type="text" id="Address"><br>
<label for="Email">Email:</label>
<input type="email" id="Email"><br>
<label for="Description">Description:</label>
<textarea type="text" id="Description"></textarea><br>
<div class="sendCancelButtons">
<button type="submit" class="submitButton" id="submitButton">Send</button>
<button value="submit" class="cancelOverlay">Cancel</button></div>
</form>
</div>
<div id="outPutContainer" class="outPutContainer">
</div>
</div>
</body>
</html>
any hints and suggestions are welcome and thanks in advance <3
From what I understood from your question, you are storing all your phonebook data inside person key. For deleting any specific "person" from the localStorage you can parse the array once again and then remove that "person" from array and save it back to localStorage. I'm assuming you want to remove person by it's phone number.
function removeByPhoneNumber(phoneNumber){
const prevArray = JSON.parse(localStorage.getItem("person")) || [];
const newArray = prevArray.filter(_person => _person.phoneNumber !== phoneNumber)
localStorage.setItem("person", JSON.stringify(newArray))
}
I am writing a "Gamebook Engine" which offers the possibility of setting a user name. The Name is taken from an input with the id="setUserNameInput" and saved by the function setUserName(). It is displayed / loaded into an element containing the class="displayUserName" and loaded by the function displayUserName(). It works fine with only one class one the page, but as soon as I add more I have to define which one to target as it won't target them all automatically. I have tried to use document.getElementById, document.getElementsByName as well as document.querySelectorAll and document.querySelector, none of which work. (I use Bulma as my CSS Framework, by the way)
Here is the code I have so far (though it will show an error as it cannot access the localStorage inside the snippet):
This page http://scampsblog.com/docs/example-de.html contains an (working, haha) example. Since it is a documentation (page lies on my testing sever, thus the domain) you might want to take a look at http://scampsblog.com/docs/character-enginedotjs-de.html which explains / shows the individual elements (the documentation is in German but I can provide a translation if you need one).
The part of the JS I am struggling with is right in the first line but if you suggest some overall improvements, I will be happy to take them.
var userNameOutput = document.getElementsByClassName('displayUserName')[0];
function setUserName() {
var usernameinput = document.getElementById('setUserNameInput').value;
localStorage.setItem('userName', usernameinput);
if (!localStorage.getItem('userName')) {
setUserName();
} else {
var storedUserName = localStorage.getItem('userName');
userNameOutput.innerHTML = storedUserName;
}
}
function displayUserName() {
if (!localStorage.getItem('userName')) {
setUserName();
} else {
var storedUserName = localStorage.getItem('userName');
userNameOutput.innerHTML = storedUserName;
}
}
window.onload = function displayUserName() {
if (!localStorage.getItem('userName')) {
setUserName();
} else {
var storedUserName = localStorage.getItem('userName');
userNameOutput.innerHTML = storedUserName;
}
}
<input type="text" class="input" placeholder="Your name goes here" id="setUserNameInput">
<input type="button" class="button" value="Set your username" onclick="setUserName()" />
<input type="button" class="button" value="Display on click" onclick="displayUserName()" />
<br> So you shall be called <span class="displayUserName"></span>! But dont worry, <span class="displayUserName"></span>, it will be all fine.
Instead of getting the first item in the collection (using [0]) you could iterate through it (using for...of) and set the innerHTML of each element having the class displayUserName.
e.g.
var userNameOutputs = document.querySelectorAll('.displayUserName');
for (let ele of userNameOutputs) {
ele.innerHTML = userName;
}
Full code, with some optimizations to structure:
function setUserName() {
var usernameinput = document.getElementById('setUserNameInput').value;
localStorage.setItem('userName', usernameinput);
displayUserName(true); // pass true to avoid recursion
}
function displayUserName(skipSet) {
var userName = localStorage.getItem('userName');
if (!userName && !skipSet) {
setUserName();
} else {
var userNameOutputs = document.querySelectorAll('.displayUserName');
for (let ele of userNameOutputs) {
ele.innerHTML = userName;
}
}
}
window.onload = displayUserName;
<input type="text" class="input" placeholder="Your name goes here" id="setUserNameInput">
<input type="button" class="button" value="Set your username" onclick="setUserName()" />
<input type="button" class="button" value="Display on click" onclick="displayUserName()" />
<br> So you shall be called <span class="displayUserName"></span>! But dont worry, <span class="displayUserName"></span>, it will be all fine.
Working fiddle: https://jsfiddle.net/hosney/3pxfybrc/1/
var userNameOutput = document.getElementsByClassName('displayUserName')[0];
the [0] selects the first element of the array of elements of the class name.
I'm willing to use two textfields to pass on values via url.
Here are my textfields:
<h3 class="title1">Email</h3>
<input type="text" id="myTextField1" />
<br/><br/>
<h3 class="title2">Secret</h3>
<input type="text" id="myTextField2" />
<br/><br/>
There's a link below them:
<a id="myLink" href="index2.php"></a>
Then there's a function I use, which should create something like:
index2.php?email=value1&secret=value2
However what I am getting is:
index2.php?email=value1, secret=value1&email=value2, secret=value2
This is the function I use:
document.querySelector('#myBtn').addEventListener('click', function change() {
function isInvalid(input) {
return input.value.length == 0;
}
var inputs = [...document.querySelectorAll('[id^="myTextField"]')];
var anchor = document.getElementById('myLink');
var querystring = inputs.map((input) => {
// Remove all leading non-digits to get the number //ex bladiebla1 = 1
var number = input.id.replace( /^\D+/g, '');
var titles = [...document.querySelectorAll('.title'+ number)];
titles.forEach((title) => title.innerHTML = input.value);
return `email=${input.value}`+` secret=${input.value}`;
});
anchor.href = `index2.php?${querystring.join('&')}`;
document.getElementById('result').innerHTML = querystring;
});
I realize that it is wrong and I get why this doesn't return what I want however I do not know how to fix this..
Could anybody tweek my code and point me in the right direction?
You're overcomplicating things here a bit.
You have the inputs in the inputs variable. If they had a name attribute in the html you can simply map over them and get the values out.
You don't really need the bit where you parse the number from the ID.
document.querySelector('#myBtn').addEventListener('click', function change() {
function isInvalid(input) {
return input.value.length == 0;
}
var inputs = [...document.querySelectorAll('[id^="myTextField"]')];
var anchor = document.getElementById('myLink');
var querystring = inputs.map((input) => {
return `${input.name}=${input.value}`;
});
anchor.href = `index2.php?${querystring.join('&')}`;
document.getElementById('result').innerHTML = querystring.join('&');
});
<h3 class="title1">Email</h3>
<input type="text" name="email" id="myTextField1" />
<br/><br/>
<h3 class="title2">Secret</h3>
<input type="text" name="secret" id="myTextField2" />
<br/><br/>
<button id=myBtn>Run the function</button>
<a id=myLink>Target Link</a>
<h3>Results:</h3>
<div id=result></div>
You iterate through each input and set email and secret for each of two inputs. Just add check for id. Something like return number === 1 ? email=${input.value} : &secret=${input.value};
I want to return the object from code.gs to html file on google app script. But I couldnt return the values. I want to display the values on the html interface. I couldnt return value at "alert(retsearch[0].yourname);"
Please help, Thank you!!
Code.gs
function getData() {
var ss=SpreadsheetApp.openById('1PWJyASHmjJ_W8-72u8bbrGbN-Nv6kdkCvjdmYuNNlEY');
var sheet=ss.getSheetByName('invoice1');
return sheet;
}
function processSearch(searchform){
var sheet = getData();
var data = ObjApp.rangeToObjects(sheet.getDataRange().getValues());
var searchfname=searchform.surname;
var searchcname=searchform.scustomername;
var searchpayementdate=searchform.spayementdate;
var results = [];
for(var i=0 ; i < data.length ; i++) {
if(searchfname == data[i].yourname || searchcname == data[i].customername || searchpayementdate == data[i].paymentday ) {
var events ={yourname:data[i].yourname, customername:data[i].customername,paymentday:data[i].paymentday };
results.push(events);
}
}
Logger.log(results);
return results;
}
Html file
<form id="fsrecord">
<input type="text" name="surname" id="surname" placeholder="by your name"/> <br/>
<input type="text" name="scustomername" id="scustomername" placeholder="by customer name"/> <br/>
<input type="date" name="spayementdate" id="spayementdate" placeholder="by payment date"> <br>
<input type="submit" value="search" />
</form>
<script>
$( document ).ready(function() {
$("#fsrecord").submit(function() {
google.script.run.withSuccessHandler(function(retsearch){
alert(retsearch[0].yourname);
}).processSearch(this);
});
});
</script>
You can convert the stringify the data at the server side and parse the JSON at the client side.
code.js
function processSearch(searchform){
...
...
return JSON.stringify(results);
}
index.html
$(document).ready(function () {
$("#fsrecord").submit(function () {
google.script.run.withSuccessHandler(function (retsearch) {
var response = JSON.parse(retsearch);
alert(response[0].yourname);
}).processSearch(this);
});
});