extract javascript variable from a function - javascript

this is my first post. Hope I've observed all the rules properly.
I'm a JS beginner and I've been watching tutorials on thenewboston.com and w3schools and some others on Youtube but can't find the answer to my question.
I have a form that uses JS to dynamically add input rows and that works fine. However the last part I just can't get to work. It is the bit that is supposed to collate all the data entered by the user.
This is what I have so far:
//get all the row data
function getData(TechRiskTable){
try {
var table = document.getElementById(TechRiskTable);
var rowCount = table.rows.length;
var jsonArray = new Array();
for(var index=0; index < rowCount; index++) {
var mapObj = {};
var row = table.rows[index];
var name1 = row.cells[0].childNodes[0];
var name2 = row.cells[1].childNodes[0];
var name3 = row.cells[2].childNodes[0];
var name4 = row.cells[3].childNodes[0];
var name5 = row.cells[4].childNodes[0];
mapObj['name1'] = name1.value;
mapObj['name2'] = name2.value;
mapObj['name3'] = name3.value;
mapObj['name4'] = name4.value;
mapObj['name5'] = name5.value;
// document.write("Value in jsonArray " + name1.value + "<br />");
}
}catch(e) {
alert(e);
}
}
Ok, so I'm running this on a classic ASP page and the "onclick" does this:
response.write input type=submit onclick='getData(TechRiskTable);' value='Send to Reviewer'><input type=reset value='Start Again'>
My question is this: How can I extract the values the user entered into the added rows in the table "TechRiskTable" so I can insert them into a database. I don't need help with getting it into the dbase, I can do that myself. I'm just having trouble extracting the actual values. That "document.write" bit does actually display the correct values on the page when I have it uncommented, but that is still within the function. I can't find a way to access the entered data from OUTSIDE the function. I've tried using request.querystring but that doesn't return any data either.
I assume that I need to get them out of jsonArray() but I can't find anywhere I can get this to work.
Any clarification required please let me know. I didn't include all the code as this post would then be too long but if you need more just ask.
Cheers

function getData(TechRiskTable){
try {
var table = document.getElementById(TechRiskTable);
var rowCount = table.rows.length;
var jsonArray = new Array();
for(var index=0; index < rowCount; index++) {
var mapObj = {};
var row = table.rows[index];
var name1 = row.cells[0].childNodes[0];
var name2 = row.cells[1].childNodes[0];
var name3 = row.cells[2].childNodes[0];
var name4 = row.cells[3].childNodes[0];
var name5 = row.cells[4].childNodes[0];
mapObj['name1'] = name1.value;
mapObj['name2'] = name2.value;
mapObj['name3'] = name3.value;
mapObj['name4'] = name4.value;
mapObj['name5'] = name5.value;
// document.write("Value in jsonArray " + name1.value + "<br />");
return mapObj;
}
}catch(e) {
alert(e);
}
return null;
I am assuming you are calling this method from somewhere else,
var mapObj = getData(TechRiskTable);
if(mapObj!=null)
{
alert("name1 is "+mapObj.name1+" and name2 is "+mapObj.name2);
}

Related

Trying to store a table and have it load after refresh?

I am taking information from a form, and storing it as an object into an array.
then I am stringifying that, and storing it into local storage.
grabbing it from local storage,
and attempting to have the row show up.
its a "to do list" web app.
I want it to save the tasks, so that they are there when i come back/refresh the page. but everytime I refresh the page, it just disappears. It looks like the information is still stored in the local storage after I refresh, though. so that isn't the issue. However, if I refresh, AND THEN add a new task, it wipes the storage so that only the new tasks in that session are added.
how can I get this to wear I can add a task, and then, save everything, and have everything STAY even after I refresh?
I tried calling the buildTable function at the top of my file, thinking it might build the table so its there for me when I load the page, but it isn't working.
Thanks!
var table = document.getElementById("tableBody");
var toDoArray = [];
buildTable();
function buildTable(){
var retrievedTaskObject = localStorage.getItem("task");
var parsedObject = JSON.parse(retrievedTaskObject);
var addTheTaskName = parsedObject.taskName;
var addTheTaskDate = parsedObject.taskDate;
for(i=0; i < toDoArray.length; i++){
addTaskToTable(parsedObject[i]);
}
}
function addTaskToTable(obj){
var row = table.insertRow(0);
var cellName = row.insertCell(0);
var cellDate = row.insertCell(1);
var cellId = row.insertCell(2);
var cellCheck = row.insertCell(3);
cellName.innerHTML= obj.name;
cellDate.innerHTML= obj.date;
var checkStuff = "<input type='checkbox'>";
cellCheck.innerHTML = checkStuff;
}
function submitForm(name,date) {
var addTaskName = document.getElementById("taskName").value;
var addTaskDate = document.getElementById("dateTask").value;
var taskSomething = getTaskObj(addTaskName,addTaskDate);
toDoArray.push(taskSomething);
addTaskToTable(taskSomething);
var storedArray = JSON.stringify(toDoArray);
localStorage.setItem("task",storedArray);
};
function getTaskObj(taskName,taskData){
var taskObject = {
name: taskName,
date: taskData,
};
return taskObject;
}
here i've fix your fillde to work >> https://jsfiddle.net/ptzkLqc4/1/
function buildTable() {
var retrievedTaskObject = localStorage.getItem("task");
var parsedObject = JSON.parse(retrievedTaskObject);
for (i = 0; i < parsedObject.length; i++) {
toDoArray.push(getTaskObj(parsedObject[i].name, parsedObject[i].date));
addTaskToTable(parsedObject[i]);
}
}
basicly, since you overwriting your localStorage by toDoArray values, you need to fill toDoArray with localStorage value on load.

How do I insert data from my JS function into table after clicking submit?

I'm trying to create a table showing results of different variables in my javascript function. I'd like the table to appear after clicking the submit button (which I've managed to do with the onclick function). However my problem is actually getting the data into the table. I am unsure how to reference the variables to specific cells in the table. I realise that this explanation might be a bit difficult to understand so I've got an example below:
I want to reference and do calculations with this information:
function myFunction() {
var age = document.getElementById("age").value;
var favoritenumber = document.getElementById("favoritenumber").value;
var birthdayyear = document.getElementById("birthdayyear").checked;
var a1 = +(age - 10);
var fn = +(favoritenumber * 2);
var by;
if (document.getElementById("birthdayyear").checked) {
by = +14;
} else {
by = 0;
}
var total = +(a1 + fn + by);
document.getElementById("submit").innerhtml = total;
}
And show the 'total' in a separate paragraph (say, a h1 tag) onclick of the submit button:
This is the TOTAL
And the rest of the information to be inserted below into a bordered table with the following headings:
A1 FN BY
But for example, if 'birthdayyear' is not checked, this column does not show.
How do I reference the data in myFunction to insert it into the table?
My calculations are more complicated than this but they work, it's just the referencing I need help with!
Thanks in advance for your help!
Check out the suite of functions associated with insertRow() here at w3schools. I think I understood your question correctly, but let me know if I didn't. Try something like this:
function myFunction() {
var age = document.getElementById("age").value;
var favoritenumber = document.getElementById("favoritenumber").value;
var birthdayyear = document.getElementById("birthdayyear").checked;
var a1 = +(age - 10);
var fn = +(favoritenumber * 2);
var by;
if (document.getElementById("birthdayyear").checked) {
by = +14;
} else {
by = 0;
}
var total = +(a1 + fn + by);
var table = document.getElementById("tableid");
var row = table.insertRow(0);
var cella1 = row.insertCell(0);
var cellfn = row.insertCell(1);
var cellby = row.insertCell(2);
cella1.innerHTML = a1;
cellfn.innerHTML = fn;
cellby.innerHTML = by;
document.getElementById("submit").innerhtml = total;
}

JavaScript multiple checkboxes - delimited list - store and parse

I was wondering if anybody can help
I'm new and don't know any  Javascript.
I need help for my caspio app.
The code below works I just need to get the second part
I got the first part of storing the values of checked checkboxes in a database field as a comma de-limited list.
Now I need to read the comma de-limited list from the database and update the checkboxes accordingly.
<SCRIPT LANGUAGE="JavaScript">
function concatenate()
{
var Resultfieldname = "CheckboxChoices";
var firstVirtual = 1;
var lastVirtual = 3;
var ResultString = "";
var virtualFieldName = "";
for (i=firstVirtual ;i<=lastVirtual; i++)
{
virtualFieldName = "cbParamVirtual"+i;
if (document.getElementById(virtualFieldName).checked) ResultString = ResultString + "," + document.getElementById(virtualFieldName).value;
}
Resultfieldname = "EditRecord"+Resultfieldname;
if (ResultString.length>0) ResultString = ResultString.substr(1);
document.getElementById(Resultfieldname ).value = ResultString;
}
document.getElementById("caspioform").onsubmit=concatenate;
</SCRIPT>

Use RegEx to replace tags in document with column data from spreadsheet

I've been searching for the answer to this question but have so far been unable to piece together the answer. Please explain any answer you have in really simple terms as I'm fairly new to GAS and RegEx. I've got most of the syntax down but the execution of it in GAS is giving me a hard time.
Basically, I want to write a script that, when the spreadsheet is edited, checks which rows have yet to be merged. Then, on those rows, creates a copy of a template Google Doc and names the document based on the spreadsheet data. From there (this is the hard part), I need it to replace merge tags in the template with the data from the spreadsheet.
The tags in the templates I'll be using look like this: <<mergeTag>>
My idea was to match the whole tag, and replace it with data from the spreadsheet that exists in the column with the same name as what's inside the "<<>>". Ex: <<FooBar>> would be replaced with the data from the column named FooBar. It would obviously be from the current row that needs the merging.
After that, all that's left is to send an email (a few more row-specific personalization) with that document attached (sometimes as a PDF) with the body of the message coming from an HTML file elsewhere in the project.
This is the whole thing I have so far (notice the placeholders here and there that I can personalize for each spreadsheet I use this for):
function onEdit() {
//SPREADSHEET GLOBAL VARIABLES
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get only the merge sheet
var sheet = ss.getSheetByName("Merge Data");
//get all values for later reference
var range = sheet.getActiveRange();
var values = range.getValues();
var lastRow = range.getLastRow();
var lastColumn = range.getLastColumn();
//get merge checker ranges
var urlColumn = range.getLastColumn();
var checkColumn = (urlColumn - 1);
var checkRow = range.getLastRow();
var checkRange = sheet.getRange(2, checkColumn, checkRow);
var check = checkRange.getBackgrounds();
//get template determination range (unique to each project)
var tempConditionRange = sheet.getRange(row, column);
var tempConditionCheck = tempConditionRange.getValues();
//set color variables for status cell
var red = "#FF0000";
var yellow = "#FFCC00";
var green = "#33CC33";
//////////////////////////////////////////////////////////
//DOC GLOBAL VARIABLES
var docTemplate1 = DriveApp.getFileById(id);
var docTemplate2 = DriveApp.getFileById(id);
var docTemplate3 = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
//////////////////////////////////////////////////////////
//EMAIL GLOBAL VARIABLES
var emailTag = ss.getRangeByName("Merge Data!EmailTag");
var personalizers = "";
var subject = "" + personalizers;
var emailBody = HtmlService.createHtmlOutputFromFile("Email Template");
//////////////////////////////////////////////////////////
// MERGE CODE
for (i = 0; i < check.length; i++) {
//for rows with data, check if they have already been merged
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, lastRow, (lastColumn - 2))
statusCell.setBackground(red);
//for rows with data, but not yet merged, perform the merge code
//////////////////////////////////////////////////////////
//DOC CREATION
//Determine which template to use
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate1;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate2;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate3;
}
//Create a copy of the template
//Rename the document using data from specific columns, at specific rows
//Move the doc to the correct folder
var docName = "";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docToSend = DriveApp.getFileById(docId);
var docBody = DocumentApp.openById(docId).getBody();
Here's where I need the help
//Locate the Merge Tags
//Match Merge Tags to the column headers of the same name
//Replace the Merge Tags with the data from the matched column, from the correct row
function tagReplace() {
var tagMatch = "/(<{2}(\w+)>{2})/g";
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
The rest is just finishing up the process
//////////////////////////////////////////////////////////
//EMAIL CREATION
//Create an email using an HTML template
//Use Merge Tags to personalize email
//Attach the doc we created to the email
//Send email to recipients based on data in the sheet
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Person McPerson",
attachments: [docToSend], //[docToSend.getAs(MIME.PDF)],
html: emailBody,
});
//////////////////////////////////////////////////////////
//CHECK ROW UPDATE
statusCell.setBackground(green);
}
}
}
My sheets all have a frozen first row that acts as the header row. All my columns will be consistently named the exact same thing as the tags (minus the <<>>).
How do I match the tags to the data?
EDIT
```````````````````
The solution did not work as described when I inserted it into my code as follows:
function formMerge() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Merge Data");
var urlColumn = sheet.getMaxColumns();
var checkColumn = urlColumn - 1;
var lastRow = ss.getSheetByName("Form Responses").getLastRow();
var values = sheet.getDataRange().getValues();
var headers = values[0];
var urlRange = sheet.getRange(2, urlColumn, lastRow);
var checkRange = sheet.getRange(2, checkColumn, lastRow);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
var docTemplate = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
// MERGE CODE
for (i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (urlColumn - 2)).getValues();
var clientNameRange = sheet.getRange((i+2), 3);
var clientName = clientNameRange.getValue();
var dateRange = sheet.getRange((i+2), 2);
var datePreFormat = dateRange.getValue();
var timeZone = CalendarApp.getTimeZone();
var date = Utilities.formatDate(new Date(datePreFormat), timeZone, "MM/dd/yyyy");
statusCell.setBackground(red);
//EMAIL VARIABLES
var personalizers = clientName;
var subject = "Post Intake Report for " + personalizers;
var emailBody = "Please see the attached Google Doc for the Post Intake Report for " + clientName + ". The intake was performed on " + date + ".";
var emailTagRange = sheet.getRange((i+2), 24);
var emailTagValue = emailTagRange.getValue();
var emailTag = emailTagValue.split(", ");
//DOC CREATION
var docToUse = docTemplate;
var docName = "Post Intake Report - " + clientName + " [" + date + "]";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docBody = DocumentApp.openById(docId).getBody().editAsText();
for (var j=0; j<headers.length; j++) {
var re = new RegExp("(<<"+headers[j]+">>)","g");
docBody.replaceText(re, dataRow[j]);
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
//EMAIL CREATION
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Christopher Anderson",
attachments: [docCopy],
html: emailBody
});
statusCell.setBackground(green);
}
}
}
Build the RegExp for each tag on the fly, using the header values from your spreadsheet.
Use Body.replaceText() to perform the replacements.
var values = sheet.getDataRange().getValues();
var headers = values[0];
...
// Loop over all columns. Use header names to search for tags.
for (var col=0; col<headers.length; col++) {
// Build RegExp using column header
var re = new RegExp("(<{2}"+headers[col]+">{2})","g");
// Replace tags with data from this column in dataRow
body.replaceText(re, dataRow[col]);
}
This snippet will operate on a single row; the first couple of declarations should appear outside of your row loop. The column looping is then done after you've created and opened the new document, and obtained the body object.
It loops over all the columns in the spreadsheet, using the header names to find the tags you've defined, and replaces them with the corresponding cell contents for the current row.

Script is working, but only with a "hack"

Background:
I am part of a large family and to save everyone some money at Christmas, we do a Secret Santa of sorts for gift giving. I am writing this script so that this all can be managed via a spreadsheet since our process can be somewhat messy. The rules are:
Each "Santa" is given two names that they must buy gifts for.
Those 2 names can not be the same.
Couples can not give gifts to each other or their children. Children
can not give gifts to their siblings or their parents.
Here is a table with some example data:
The Problem
I believe my issue is occurring because of the following code:
//Remove disallowedNames from currentAvailableNames
for (j=0; j<disallowed.length; j++){
var disallowedName = disallowed[j];
currentAvailableNames.splice(currentAvailableNames.indexOf(disallowed[j]), 1);
}
For some reason, the disallowed name(s) are also being removed from the availableNames array and I have no idea why. The only way I have been able to "fix" it, is by adding in the following code after the recipient has been picked:
//Add Disallowed Names back to Available Names Array
for (k=0; k<disallowed.length; k++){
var disallowedName = disallowed[k];
if (disallowedName.length >0) {
availableNames.push(disallowedName);
}
}
Original Code
function giftAssignments() {
//Get Settings
var ss = SpreadsheetApp.getActiveSpreadsheet();
var settings = ss.getSheetByName("Settings");
var resultsSheet = ss.getSheetByName("Results");
var numOfAssignments = settings.getRange("B2").getValue();
var minPrice = settings.getRange("B3").getValue();
var maxPrice = settings.getRange("B4").getValue();
var firstName = settings.getRange("B5").getValue();
var santasLastRow = settings.getLastRow();
var santasLastCol = settings.getLastColumn();
var santasTotal = santasLastRow - firstName + 1;
var santasAsRange = settings.getRange(firstName,1,(santasLastRow - firstName + 1), santasLastCol).getValues();
//Create Santas Array (santas)
var santas = []
for (var i=0; i<santasAsRange.length; i++) {
var name = santasAsRange[i][0];
var email = santasAsRange[i][1];
var disallowedAsString = santasAsRange[i][2];
disallowedAsString = disallowedAsString.replace(", ",",");
var disallowed = disallowedAsString.split(",");
disallowed.push(name);
var santa = [];
santa[0] = name;
santa[1] = email;
santa[2] = disallowed;
santas.push(santa);
}
//Create Array of Names (availableNames)
var availableNames = [];
for (i=0; i<santas.length; i++) {
var aName = santas[i][0];
availableNames.push(aName);
}
//Assign Recipients
var results = assignRecip(santas, availableNames);
Logger.log("RESULTS = " + results);
}
function assignRecip(santas, names) {
var availableNames = names;
for (i=0; i<santas.length; i++) {
var currentAvailableNames = availableNames;
var name = santas[i][0];
var disallowed = santas[i][2];
Logger.log("Santa = " + name);
Logger.log("availableNames = " + availableNames);
//Remove disallowedNames from currentAvailableNames
for (j=0; j<disallowed.length; j++){
var disallowedName = disallowed[j];
currentAvailableNames.splice(currentAvailableNames.indexOf(disallowed[j]), 1);
}
Logger.log("currentAvailableNames = " + currentAvailableNames);
//Pick Random Ricipient from currentAvailableNames
var recipient = currentAvailableNames[Math.floor(Math.random() * currentAvailableNames.length)];
Logger.log("Recipient = " + recipient);
//Add Recipient to Santa Array
santas[i].push(recipient);
//Add Disallowed Names back to Available Names Array
for (k=0; k<disallowed.length; k++){
var disallowedName = disallowed[k];
if (disallowedName.length >0) {
availableNames.push(disallowedName);
}
}
//Add Recipient to Disallowed Names Array
santas[i][2].push(recipient);
//Remove Recipient from Available Names Array
availableNames.splice(availableNames.indexOf(recipient),1);
Logger.log("availableNames = " + availableNames);
Logger.log(" ");
}
return santas;
}
They're references to the same Array. This code doesn't copy the Array itself. It copies the reference to the Array.
var currentAvailableNames = availableNames;
You can fix it using .slice().
var currentAvailableNames = availableNames.slice();
Now you have two separate Arrays, so direct modifications to currentAvailableNames will not affect availableNames.
Note that this is a shallow clone. If it was an Array of Objects or Arrays, then modifications to the nested Object would still be visible from both Arrays.

Categories