Basically, I'm using JavaScript to dynamically generate a form that allows from multiple entries within a single submission. Here's the code I'm using for that:
function addEvent()
{
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value - 1) + 2;
numi.value = num;
var divIdName = 'my' + num + 'Div';
var newdiv = document.createElement('div');
newdiv.setAttribute('id', divIdName);
newdiv.innerHTML = '<table id="style" style="background-color: #ffffff;"><tr><td colspan="2">Entry ' + num + '<hr \/><\/td><\/tr><tr><td><label>Item 1: <\/td><td><input name="item1_' + num + '" value="" type="text" id="item1" \/><\/label><\/td><\/tr><tr><td><label>Item 2: <\/td><td><input name="item2_' + num + '" type="text" id="item2" \/><\/label><\/td><\/tr><tr><td><label>Item 3: <\/td><td><input type="text" name="item3_' + num + '" id="item3" \/><\/label><\/td><\/tr><tr><td><label>Item 4: <\/td><td><select name="item4_' + num + '" id="item4"><option value="---">---<\/option><option value="opt_1">1<\/option><option value="opt_2">2<\/option><option value="opt_3">3<\/option><option value="opt_4">4<\/option><\/select><\/label><\/td><\/tr><\/table>';
ni.appendChild(newdiv);
}
This works just fine, generating the entries fields I need. Using console in-browser, I've even verified all the names are correct. The issue is that I need to then take the selections and generate output. I've tried several methods, but everything resulted in null values.
function generateVideo()
{
var entries = document.getElementById('theValue').value;
var item1 = {};
var item2 = {};
var item3 = {};
var item4 = {};
for(i = 1; i <= entries; i++)
{
item1[i - 1] = document.getElementById('item1_' + i);
item2[i - 1] = document.getElementById('item2_' + i);
item3[i - 1] = document.getElementById('item3_' + i);
item4[i - 1] = document.getElementById('item4_' + i);
}
var code = 'Copy code and paste it into Notepad<br \/>"Save as" filename.html<br \/><textarea name="" cols="45" rows="34">header template\n';
for(i = 0; i < entries; i++)
{
if(i != (entries - 1))
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"],\n';
}
else
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"]\n';
}
}
code = code + 'footer template<\/textarea>';
var result = document.getElementById("result");
result.innerHTML = code;
}
The output is as follows:
Copy code and paste it into Notepad<br />"Save as" CourseName_Unit_Chapter.html<br /><textarea name="" cols="45" rows="34">header template
["null", "null", "null", "null"]
footer template</textarea>
Now, certain fields can be null, that's fine (I'll do form validation after I get it working), but I'm getting null for every field regardless of what is entered.
I, originally, had the .value on the getElementByIds, but that only results in the script not running when the entries variable is greater than 0 (default), which is why I tried removing them.
function generateVideo()
{
var entries = document.getElementById('theValue').value;
var item1 = {};
var item2 = {};
var item3 = {};
var item4 = {};
for(i = 1; i <= entries; i++)
{
item1[i - 1] = document.getElementById('item1_' + i).value;
item2[i - 1] = document.getElementById('item2_' + i).value;
item3[i - 1] = document.getElementById('item3_' + i).value;
item4[i - 1] = document.getElementById('item4_' + i).value;
}
var code = 'Copy code and paste it into Notepad<br \/>"Save as" filename.html<br \/><textarea name="" cols="45" rows="34">header template\n';
for(i = 0; i < entries; i++)
{
if(i != (entries - 1))
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"],\n';
}
else
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"]\n';
}
}
code = code + 'footer template<\/textarea>';
var result = document.getElementById("result");
result.innerHTML = code;
}
I've also tried variations of multidimensional arrays, instead of four arrays, but got the same results.
The output, as indicated by the removal of the .value on the getElementByIds, is good. Basically, there is something wrong with my attempts to populate the arrays using the dynamically generated forms.
I suspect that the issue with the declaration of the element ID, but I'm not sure how else to declare it. This style of scripting is not my norm. ^^'
Anyone have any ideas on how to fix the for loop to generate the array?
replace all occurences of
itemN[i]
with
itemN[i].value
if that doesnt work add
console.log( itemN[i] )
and see what it outputs
Related
Let's say I have some sentences in Google Docs. Just one sentences as an example:
"My house is on fire"
I actually changed the background color so that every verb is red and every noun blue.
Now I want to make a list with all the verbs and another one with the nouns. Unfortunately getBackgroundColor() only seems to work with paragraphs and not with single words.
My idea was, to do something like this (I didn't yet have the time to think about how to do the loop, but that's not the point here anyway):
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var paragraphs = body.getParagraphs();
var colorVar = paragraphs[0].getText().match(/\w+/).getBackgroundColor(); // The regEx matches the first word. Next I want to get the background color.
Logger.log(colorVar);
}
The error message I get goes something like this:
"The function getBackgroundColor in the text object couldn't be found"
Thx for any help, or hints or comments!
You want to retrieve the text from a paragraph.
You want to retrieve each word and the background color of each word from the retrieved the text.
In this case, the color is the background color which is not getForegroundColor().
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
At first, the reason of your error is that getBackgroundColor() is the method of Class Text. In your script, getBackgroundColor() is used for the string value. By this, the error occurs.
In this answer, for achieving your goal, each character of the text retrieved from the paragraph is scanned, and each word and the background color of each word can be retrieved.
Sample script:
function myFunction() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var paragraphs = body.getParagraphs();
var textObj = paragraphs[0].editAsText();
var text = textObj.getText();
var res = [];
var temp = "";
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (c != " ") {
temp += c;
} else {
if (temp != "") res.push({text: temp, color: textObj.getBackgroundColor(i - 1)});
temp = "";
}
}
Logger.log(res) // result
}
When you run the script, the text of 1st paragraph is parsed. And you can see the result with res as an object.
In this sample script, the 1st paragraph is used as a test case. So if you want to retrieve the value from other paragraph, please modify the script.
References:
getBackgroundColor()
getBackgroundColor(offset)
editAsText()
If I misunderstood your question and this was not the direction you want, I apologize.
Here's a script your welcome to take a look at. It highlights text that a user selects...even individual letters. I did it several years ago just to learn more about how documents work.
function highLightCurrentSelection() {
var conclusionStyle = {};
conclusionStyle[DocumentApp.Attribute.BACKGROUND_COLOR]='#ffffff';
conclusionStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';
conclusionStyle[DocumentApp.Attribute.FONT_FAMILY]='Calibri';
conclusionStyle[DocumentApp.Attribute.FONT_SIZE]=20;
conclusionStyle[DocumentApp.Attribute.BOLD]=false;
conclusionStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.LEFT;
conclusionStyle[DocumentApp.Attribute.VERTICAL_ALIGNMENT]=DocumentApp.VerticalAlignment.BOTTOM;
conclusionStyle[DocumentApp.Attribute.LINE_SPACING]=1.5;
conclusionStyle[DocumentApp.Attribute.HEIGHT]=2;
conclusionStyle[DocumentApp.Attribute.LEFT_TO_RIGHT]=true;
var br = '<br />';
var selection = DocumentApp.getActiveDocument().getSelection();
var s='';
if(selection) {
s+=br + '<strong>Elements in Current Selection</strong>';
var selectedElements = selection.getRangeElements();
for(var i=0;i<selectedElements.length;i++) {
var selElem = selectedElements[i];
var el = selElem.getElement();
var isPartial = selElem.isPartial();
if(isPartial) {
var selStart = selElem.getStartOffset();
var selEnd = selElem.getEndOffsetInclusive();
s+=br + 'isPartial:true selStart=' + selStart + ' selEnd=' + selEnd ;
var bgcolor = (el.asText().getBackgroundColor(selStart)=='#ffff00')?'#ffffff':'#ffff00';
el.asText().setBackgroundColor(selStart, selEnd, bgcolor)
}else {
var selStart = selElem.getStartOffset();
var selEnd = selElem.getEndOffsetInclusive();
s+=br + 'isPartial:false selStart=' + selStart + ' selEnd=' + selEnd ;
var bgcolor = (el.asText().getBackgroundColor()=='#ffff00')?'#ffffff':'#ffff00';
el.asText().setBackgroundColor(bgcolor);
}
var elType=el.getType();
s+=br + 'selectedElement[' + i + '].getType()= ' + elType;
if(elType==DocumentApp.ElementType.TEXT) {
var txt = selElem.getElement().asText().getText().slice(selStart,selEnd+1);
var elattrs = el.getAttributes();
if(elattrs)
{
s+=br + 'Type:<strong>TEXT</strong>';
s+=br + 'Text:<span style="color:#ff0000">' + txt + '</span>';
s+=br + 'Length: ' + txt.length;
s+=br + '<div id="sel' + Number(i) + '" style="display:none;">';
for(var key in elattrs)
{
s+= br + '<strong>' + key + '</strong>' + ' = ' + elattrs[key];
s+=br + '<input type="text" value="' + elattrs[key] + '" id="elattr' + key + Number(i) + '" />';
s+=br + '<input id="elattrbtn' + Number(i) + '" type="button" value="Save Changes" onClick="setSelectedElementAttribute(\'' + key + '\',' + i + ');" />'
}
s+='</div>Show/Hide';
}
}
if(elType==DocumentApp.ElementType.PARAGRAPH) {
var txt = selElem.getElement().asParagraph().getText();
var elattrs = el.getAttributes();
if(elattrs)
{
s+=br + '<strong>PARAGRAPH Attributes</strong>';
s+=br + 'Text:<span style="color:#ff0000">' + txt + '</span> Text Length= ' + txt.length;
for(var key in elattrs)
{
s+= br + key + ' = ' + elattrs[key];
}
}
}
s+='<hr width="100%"/>';
}
//var finalP=DocumentApp.getActiveDocument().getBody().appendParagraph('Total Number of Elements: ' + Number(selectedElements.length));
//finalP.setAttributes(conclusionStyle);
}else {
s+= br + 'No Elements found in current selection';
}
s+='<input type="button" value="Toggle HighLight" onclick="google.script.run.highLightCurrentSelection();"/>';
//s+='<input type="button" value="Exit" onClick="google.script.host.close();" />';
DocumentApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile('htmlToBody').append(s).setWidth(800).setHeight(450).setTitle('Selected Elements'));
}
I am using XAMPP Apache to do XMLHTTP Javascript (AJAX) request from a json file but I am only looping through two(2) entries instead of the entire array four or five (5). I believe there is a problem with my looping code in both my "next" and "previous" functions. Hitting the next button allow me to go ahead and hitting the previous button allows me to go back but only through two(2
function next(xhttp) {
var i = 0,
len;
//var xhttp;
//xhttp = new XMLHttpRequest();
var users = JSON.parse(xhttp.responseText);
len = users.length;
if (i < len - 1) {
i++;
}
var usersText = '';
usersText +=
'<div class="next">' +
'ID: ' + users[i].id + '<br>' +
'Name: ' + users[i].name + '<br>' +
'Email: ' + users[i].email;
document.getElementById("usersNav").innerHTML = usersText;
}
function previous(xhttp) {
var i = 0,
len;
//var xhttp;
//xhttp = new XMLHttpRequest();
var users = JSON.parse(xhttp.responseText);
len = users.length
if (i > 0) {
i--;
}
var usersText2 = '';
usersText2 +=
'<div class="prev">' +
'ID: ' + users[i].id[navigation image][1] + '<br>' +
'Name: ' + users[i].name + '<br>' +
'Email: ' + users[i].email;
document.getElementById("usersNav").innerHTML = usersText2;
}
<button type="button" onclick="loadDoc('users.json',previous)"><<</button>
<button type="button" onclick="loadDoc('users.json',next)">>></button>
I am only getting two entries to toggle through....if I click next and previous. I should be getting all the entries which is about 4-5.
I was trying to make something where you can type a string, and the js only shows the objects containing this string. For example, I type Address1 and it searches the address value of each one then shows it (here: it would be Name1). Here is my code https://jsfiddle.net/76e40vqg/11/
HTML
<input>
<div id="output"></div>
JS
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
var restoName = [], restoAddress = [], restoRate = [], restoImage= [];
for(i = 0; i < data.length; i++){
restoName.push(data[i].name);
restoAddress.push(data[i].address);
restoRate.push(data[i].rate);
restoImage.push(data[i].image);
}
for(i = 0; i < restoName.length; i++){
document.getElementById('output').innerHTML += "Image : <a href='" + restoImage[i] + "'><div class='thumb' style='background-image:" + 'url("' + restoImage[i] + '");' + "'></div></a><br>" + "Name : " + restoName[i] + "<br>" + "Address : " + restoAddress[i] + "<br>" + "Rate : " + restoRate[i] + "<br>" + i + "<br><hr>";
}
I really tried many things but nothing is working, this is why I am asking here...
Don't store the details as separate arrays. Instead, use a structure similar to the data object returned.
for(i = 0; i < data.length; i++){
if (data[i].address.indexOf(searchedAddress) !== -1) { // Get searchedAddress from user
document.getElementById("output").innerHTML += data[i].name;
}
}
Edits on your JSFiddle: https://jsfiddle.net/76e40vqg/17/
Cheers!
Here is a working solution :
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
document.getElementById('search').onkeyup = search;
var output = document.getElementById('output');
function search(event) {
var value = event.target.value;
output.innerHTML = '';
data.forEach(function(item) {
var found = false;
Object.keys(item).forEach(function(val) {
if(item[val].indexOf(value) > -1) found = true;
});
if(found) {
// ouput your data
var div = document.createElement('div');
div.innerHTML = item.name
output.appendChild(div);
}
});
return true;
}
<input type="search" id="search" />
<div id="output"></div>
I have an array object that needs another array object added to it. So i have details of the object that need the rows in a table to be added to that object as an array. I have tried a few suggestions on stackoverflow , but none seems to be working, and i am not sure this has something to do with the fact that the table is created by js.
// Adding Cosignment number
$('#parcel-overview').append(
// Add main tables which will display the added packages
'<table border="1">' +
'<thead><tr><th>Packages</th><th>Weight</th> <th>Vol Weight</th><th>Charge Weight</th> <th>Price</th></tr></thead><tbody id="parcels-added-overview"></tbody> ' +
'</table>'
);
for (var i = 0; i < packageNum; i++) {
var ii = (i + 1).toString();
// Working out volemetric weight
wei = $('#added-parcels #weighting-' + ii + ' input').val();
len = $('#added-parcels #lengthing-' + ii + ' input').val();
wid = $('#added-parcels #widthing-' + ii + ' input').val();
hei = $('#added-parcels #heighting-' + ii + ' input').val();
//Calculating Volumetric weight
tot = ((len * wid * hei) / 5000).toFixed(1);
pri = (tot * 23).toFixed(2);
chr = (tot * 12).toFixed(2);
$('#parcels-added-overview').append(
'<tr>' +
'<td class="par-id">' + (i + 1).toString() + '</td>' +
'<td class="par-weight">' + wei.toString() + ' kg\'s</td>' +
'<td class="par-vol-weight">' + tot.toString() + ' kg\'s</td>' +
'<td class="par-charge-weight">R ' + chr.toString() + '</td>' +
'<td class="par-price">R ' + pri.toString() + ' </td>' +
'</tr>'
);
}
I then want to add the values of that table that have been added dynamically to an object array that is then added to the primary object array.
var parcelObj = new Object();
$.each($('#parcels-added-overview tr'),function (index) {
parcelObj.parcelId = $(this).children('.par-id').text();
parcelObj.totalWeight = $(this).children('.par-weight').text();
parcelObj.volWeight = $(this).children('.par-vol-weight').text();
parcelObj.chargeWeight = $(this).children('.par-charge-weight').text();
parcelObj.overallPrice = $(this).children('.par-price').text();
parcelsArr.push(parcelObj);
});
consignmentObj.parcels = parcelsArr;
consignmentsArr.push(consignmentObj);
I might be a n00b , but this code (although i think its fairly verbose ) should work.
Does the $(this).children not identify directly on each() row that it is iterating over?
When i add console.log(consignmentsArr); i get the array within the object as it should be but the values for the parcel object are just repeating the last row of the table.
1: Object
deliName: ""
deliStreet: ""
docType: "Document"
insurance: "None"
parcels: Array[2]
0: Object
chargeValue:"R34.43"
overallPrice:"R43.54"
parcelId:"2"
totalWeight:"65 kg's"
volWeight:"63 kg's"
1: Object
chargeValue:"R34.43"
overallPrice:"R43.54"
parcelId:"2"
totalWeight:"65 kg's"
volWeight:"63 kg's"
Why can I not get the first row values to be added to parcels[0]?
Thanks
Try to declare parcelObj object inside the function.
$.each($('#parcels-added-overview tr'),function (index) {
var parcelObj = new Object();
parcelObj.parcelId = $(this).children('.par-id').text();
parcelObj.totalWeight = $(this).children('.par-weight').text();
parcelObj.volWeight = $(this).children('.par-vol-weight').text();
parcelObj.chargeWeight = $(this).children('.par-charge-weight').text();
parcelObj.overallPrice = $(this).children('.par-price').text();
parcelsArr.push(parcelObj);
});
consignmentObj.parcels = parcelsArr;
consignmentsArr.push(consignmentObj);
Is this the optimal way to load form data into a string and then to localStorage ?
I came up with this on my own, and I am not good in programming. It works, for what I need, but I am not sure if it's a bulletproof code?
<script>
var sg = document.getElementById("selectedGateway");
var sd = document.getElementById("selectedDestination");
var dm = document.getElementById("departureMonth");
var dd = document.getElementById("departureDay");
var dy = document.getElementById("departureYear");
var rm = document.getElementById("returnMonth");
var rd = document.getElementById("returnDay");
var ry = document.getElementById("returnYear");
var ad = document.getElementById("adults");
var ch = document.getElementById("option2");
$("#searchRequestForm").submit(function() {
var string = 'From: ' + sg.value + ' \nTo: ' + sd.value + ' \nDeparture: ' + dm.value + '/' + dd.value + '/' + dy.value + ' \nReturn: ' + rm.value + '/' + rd.value + '/' + ry.value + ' \nNumber of adults: ' + ad.value + ' \nNumber of children: ' + ch.value;
localStorage.setItem("string", string);
});
</script>
I would use something like the following so that I could deal with an object and its properties rather than a big string. Note that other than the jQuery selectors, this is pure JavaScript.
Demo: http://jsfiddle.net/grTWc/1/
var data = {
sg: $("#selectedGateway").val(),
sd: $("#selectedDestination").val()
// items here
};
localStorage.setItem("mykey", JSON.stringify(data));
To retrieve the data:
var data = JSON.parse(localStorage["mykey"]);
alert(data.sg);
See Also:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify
http://api.jquery.com/jQuery.parseJSON/
I prefer a table driven approach so there is no repeated code (DRY):
var ids = [
"selectedGateway", "From: ",
"selectedDestination", "\nTo :",
"departureMonth", "\nDeparture: ",
"departureDay", "/",
"departureYear", "/",
"returnMonth", " \nReturn: ",
"returnDay", "/",
"returnYear", "/",
"adults", " \nNumber of adults: ",
"option2", " \nNumber of children: "];
var submitStr = "";
for (var i = 0; i < ids.length; i+=2) {
submitStr += ids[i+1] + document.getElementById(ids[i]).value;
}
localStorage.setItem("string", submitStr);
You could define a function such as the one below to directly get the values by id so then it would be simpler when you build your string.
function form(id) {
return document.getElementById(id).value;
}