I'm having some trouble getting my code to work. This is what I have so far.
function outputNamesAndTotal() {
var name;
var outputTable;
var inputForm;
var nameArray;
var outputDiv;
outputDiv = document.getElementById("outputDiv");
inputForm = document.getElementById("inputForm");
outputTable = document.getElementById("outputTable");
name = inputForm.name.value;
nameArray = [];
nameArray.push(name);
for (var i = 0; i > nameArray.length; i++) {
outputTable.innerHTML += "<tr>" + nameArray[i] + "</tr>";
}
inputForm.name.focus();
inputForm.name.select();
return false;
}
When I add the loop it breaks the code completely, but I can't figure out why.
What I'm trying to do is use an HTML form to get a name from the user. Once the user enters the name, the program adds the name to the array, and outputs each array entry to a row in a table.
It's pretty basic, but it's still giving me all kinds of trouble!
I think you are clearing your array of names every time you call the function. You should bring the line:
nameArray = [];
out and make it global.
I ran a quick test and the following code works in at least FireFox
Edited to use appendChild
<html>
<head>
<script type='text/javascript'>
var names = [];
function addName() {
var nameTxt = document.getElementById('name_txt');
var name = nameTxt.value;
names.push(name);
var outTable = document.getElementById('out_tbl');
var row = document.createElement('tr');
var entry = document.createElement('td');
var txt = document.createTextNode(name);
entry.appendChild(txt);
row.appendChild(entry);
outTable.appendChild(row);
var numDiv = document.getElementById('num_div');
removeAllChildren(numDiv);
var numTxt = document.createTextNode('You have ' + names.length + ' names');
numDiv.appendChild(numTxt);
}
function removeAllChildren(e) {
while (e.hasChildNodes()) {
e.removeChild(e.firstChild);
}
}
</script>
</head>
<body>
<table id='out_tbl'>
</table>
<div id='num_div'>You have 0 names</div>
<input id='name_txt' type='text'/>
<button onclick="addName()">CLICK</button>
</body>
</html>
Edit: Oh yeah and you are the fact that you are looping through the array every time. If you "globalize" the name array, you're gonna print the whole array every time you add a name.
Edit x2: the code you originally posted had nameArray as a local variable inside the function. This effectively clears the array every time you call the function. Then every time you call the function you add the current name to the now empty array, and loop through all 1 (one) elements that the array now holds.
What you want to do is "globalize" the name array, and remove the loop from your function. This will allow you to build up your name array across multiple calls, and works the way that you want it.
Also, innerHTML is not really the best way to add things to the page. I would suggest using appendChild().
-C
for (var i = 0; i > nameArray.length; i++) {
I think you mean i < nameArray.length
Related
I'm trying to make a runnable console command through Chrome that searches for the word "takeID", and then grabs the content immediately after it between = and & from a div class.
What I have so far doesn't work because I'm very bad at JS so any help would be appreciated. Below is what I have so far:
var iframe=document.getElementsByClassName("activity activity-container-html5");
var searchValue = "takeID";
for(var i=0;i<iframe.length;i++){ if(iframe[i].innerHTML.indexOf(searchValue)>-1){}};
var subString = iframe.substring( iframe.lastIndexOf("=")+1, iframe.lastIndexOf("&"));
console.log(searchValue+"="+subString);
An example of the div class it would be searching would look like:
<div class="activity activity-container-html5" config="{example text;takeID=cd251erwera34a&more example text}">
There are two issues with the code. The first issue is the searchValue posts to the console as whatever is in between the takeID, and not the actual result from searching. The second issue is that the code to search between = and & doesn't work at all and I don't know why. What is wrong with the code?
I just want an output that would post to the log or a popup window saying:
takeID=cd251erwera34a
EDIT:
Something else I thought of was how would you be able to just parse the div and then search for what is in between "takeID=" and "&"? I tried this but I was getting the error "Uncaught TypeError: iframe.lastIndexOf is not a function".
var iframe=document.getElementsByClassName("activity activity-container-html5");
var subString = iframe.substring( iframe.lastIndexOf("takeId=") + 1, iframe.lastIndexOf("&") );
console.log(subString);
I looked this up and I see this is because what it is trying to process is not a string but I'm not sure why that is or how to fix it.
I don't know about you but the best would be to use json directly inside the html tag like this:
<div class="activity activity-container-html5" config="{'example':'text', 'takeID':'cd251erwera34a', 'other':''}">
Or use an array and check manually if the one you are checking is the one you want, like this:
function config(element, searchValue) {
if (element.hasAttribute('config')) {
var configData = JSON.parse(element.getAttribute('config'));
var res = "";
for (var i = 0; i < configData.length; i++) {
if (configData[i].includes(searchValue)) {
res = configData[i];
break;
}
}
return res;
}
}
el = document.getElementsByClassName('activity activity-container-html5');
for (var i = 0; i < el.length; i++) {
console.log(config(el[i], "takeID"));
}
<div class="activity activity-container-html5" config='["example=text", "takeID=cd251erwera34a", "othertext=here"]'>
The array-type (second example) is most likely to work better than the simple json one (first one).
I figured out what I needed to do. Below is working code:
var iframe=document.getElementsByClassName("activity activity-container-html5");
var div = "";
for(var i=0;i < iframe.length; i++){
div += (iframe[i].outerHTML);
}
var take = /takeID=([a-z0-9]*)&/;
var capture = div.match(take);
var matchID = capture[1];
console.log(matchID);
window.alert("takeID=" + matchID);
I am a novice here to google app scripts and my JavaScript is also not very strong, but neither of these seem to be the problem here as my code works the first time I run it but then when I try to call it again it fails.
Simply I am trying to have a function that will dynamically find a given text in a given range. While it looks like there might be a built in package that does this I cannot figure out how to implement it. And the documentation is not helpful for someone new.
Option 1: was to implement the following: https://developers.google.com/apps-script/reference/spreadsheet/text-finder#findAll()
Since that has not been sucessful in finding out how to do it I moved to creating the following simple two functions, Option 2:
function findIndexRow(range,fText){
for(var i = 0; i<range.length;i++){
for(var j = 0; j<range.length;j++){
if(range[i][j] == fText){
var fTextRow = i+1;
var fTextCol = j+1;
}
}
}
return fTextRow
}
function findIndexCol(range,fText){
for(var i = 0; i<range.length;i++){
for(var j = 0; j<range.length;j++){
if(range[i][j] == fText){
var fTextRow = i+1;
var fTextCol = j+1;
}
}
}
return fTextCol
}
It takes in a range that I defined like:
var sheet = SpreadsheetApp.openById('the-gsheet-id');
var CurrSheet = sheet.getSheetByName('Sheet1');
var SHTvalues = CurrSheet.getDataRange().getValues();
So the above works when I call it once in my main code but the second time it returns null, help here as to why re calling the same function does not work.
var text1Row = findIndexRow(SHTvalues,"text1");
var text1Col = findIndexCol(SHTvalues,"text1");
Logger.log(text1Row)
Logger.log(text1Col)
var text2Row = findIndexRow(SHTvalues,"text2");
var text2Col = findIndexCol(SHTvalues,"text2");
Logger.log(text2Col)
Logger.log(text2Row)
I can't understand why my logs return the correct values for text1Row and text1Col but when it is called a second time the text2Row and text2Col both return null
I believe your goal as follows.
You want to search a text value from a sheet in the Google Spreadsheet, and want to retrieve the row and column numbers of the found values.
You want to achieve this using TextFinder.
For this, how about this answer?
Sample script:
var findText = "text1";
var sheet = SpreadsheetApp.openById('the-gsheet-id');
var CurrSheet = sheet.getSheetByName('Sheet1');
var SHTvalues = CurrSheet.createTextFinder(findText).findAll();
var result = SHTvalues.map(r => ({row: r.getRow(), col: r.getColumn()}));
console.log(result)
Note:
About my logs return the correct values for text1Row and text1Col but when it is called a second time the text2Row and text2Col both return null in your script, if there are the values of text1 and text2 in Sheet1, text1Row, text1Col, text2Col and text2Row has the values. If only the value of text1 is put in Sheet1, text1Col and text2Col has the values. But text2Col and text2Row has no values (null). Please be careful this.
But in this case, when 2 values of `text1 are put to the cells "A1" and "A2", only "A2" is returned. Also please be careful this.
In this sample script, please enable V8.
References:
createTextFinder() in Class Sheet
Class TextFinder
Here's a script that I used for searching through my spreadsheets when I'm having trouble finding the sheet I want. It does read another sheet to get a list of spreadsheets to search through.
function regexSearch(sObj) {
var ass=SpreadsheetApp.getActive();
var startRow=2;
var msrsh=ass.getSheetByName('MultiSearchResults');
msrsh.clearContents();
msrsh.appendRow(['Path','FileName','FileId','SheetName','CellA1Notation','Value','Pattern']);
msrsh.activate();
var sh=ass.getSheetByName('SelectedSpreadsheets');
var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];
var getArrayIndex={};
hA.forEach(function(e,i){getArrayIndex[e]=i;});
var rg=sh.getRange(startRow,1,sh.getLastRow()-startRow+1,sh.getLastColumn());
var ssA=rg.getValues();
var matches='';
var n=0
for(var k=0;k<ssA.length;k++) {
var fileid=ssA[k][getArrayIndex['FileId']];
var filename=ssA[k][getArrayIndex['FileName']];
var filepath=getFilePathFromId(ssA[k][getArrayIndex['FileId']]);
//Logger.log(fileid);
var ss=SpreadsheetApp.openById(fileid);
Logger.log(sObj.pattern);
var tf=ss.createTextFinder(sObj.pattern).useRegularExpression(true);
var all=tf.findAll();
for(var i=0;i<all.length;i++) {
if(i==0)n++;
matches+=Utilities.formatString('<br /><b>Path:</b> %s <b>Sheet:</b> %s <b>Cell:</b> %s <b>Value:</b> %s<hr width="100%"/>',filepath,all[i].getSheet().getName(),all[i].getA1Notation(),all[i].getValue());
msrsh.appendRow([filepath,filename,fileid,all[i].getSheet().getName(),all[i].getA1Notation(),all[i].getValue(),sObj.pattern]);
}
}
if(matches) {
sObj.matches=matches;
sObj.message=Utilities.formatString('<p>Pattern %s was found in %s spreadsheet out of a total of %s</p>',sObj.pattern,n,ssA.length);
}else{
sObj.message=Utilities.formatString('No Matches found for %s',sObj.pattern);
}
return sObj;
}
I'm looping through a js object with a nested for loop, stated below, it appends the first element correctly, but then throws the following error:
Can't set the property className of an undefined reference or empty reference. (not sure if exact error, translating from Dutch...)
function allVideos() {
var sql = "SELECT videos.VideoName, videos.VideoPath FROM videos";
var resultSet = db.query(sql, {json:true}); //returns: [{"VideoName":"timelapse aethon2","VideoPath":"videos\\Roermond Papier\\160424 Time laps Aethon2.avi"},{"VideoName":"timelapse aethon3","VideoPath":"videos\\Roermond Papier\\160424 Time laps Aethon2.avi"}]
var parsed = JSON.parse(resultSet);
var parsedlength = arrLenght(parsed);
//alert(resultSet);
for(var i = 0; i < parsedlength; i++) {
var obj = parsed[i];
//alert(i);
var videoElement = document.getElementById("allVideos");
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
videoElement.appendChild(document.createElement('div'));
videoElement.children[i].id='allVid' + i;
videoElement.children[i].className='col-md-4 col-xs-12';
//alert(typeof key)
var card = document.getElementById('allVid' + i);
alert(i);
card.appendChild(document.createElement('div'));
card.children[i].className='card card-block';
card.children[i].innerHTML = "<h3 class='card-title'>" + obj['VideoName'] + "</h3><button class='btn btn-primary'>Selecteren</button>"
}
}
}
}
[EDIT] added screenshot of how it looks
Your code has some significant logic issues. You're using nested loops, but appending to an element assuming that the outer loop counter will let you index into that element's children to get the element you just appended. Later, you try to get that same element again using getElementById. Then, you append a new element to your newly-created element, but try to access that new element using children[i] on the one you just created — at that point, the card element will only have a single child, so as of the second outer loop, it will fail.
createElement returns the element to you, so there's no reason at all to try to access it via children[i] (either time) or getElementById.
See comments:
function allVideos() {
var sql = "SELECT videos.VideoName, videos.VideoPath FROM videos";
var resultSet = db.query(sql, {json:true});
var parsed = JSON.parse(resultSet);
var parsedlength = arrLenght(parsed);
for(var i = 0; i < parsedlength; i++) {
var obj = parsed[i];
//alert(i);
var videoElement = document.getElementById("allVideos");
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
// Create the card, give it its id and class
var card = document.createElement('div');
card.id='allVid' + i;
card.className='col-md-4 col-xs-12';
// Create the div to put in the card, give it its class and content
var div = document.createElement('div');
card.appendChild(div);
div.className='card card-block';
div.innerHTML = "<h3 class='card-title'>" + obj['VideoName'] + "</h3><button class='btn btn-primary'>Selecteren</button>"
// Append the card
videoElement.appendChild(card);
}
}
}
}
Side note: arrLenght looks like a typo (it should be th, not ht), but moreover, there's no reason to use a function to get the length of an array; it's available via the array's length property: parsedLength = parsed.length.
Side note 2: You may find these ways of looping through arrays useful.
Your problem is the if within the nested for:
if(obj.hasOwnProperty(key)) { ...
The variable i is increased even if the property is not "owned" (when the if condition returns false), so next time that the condition is true, i is out of bounds.
Okay I have a a couple of functions. I don't think most of them are relevant. What I want to do is create an html list when you click a button, and store the value in an array. However I want to be able to update this list without outputting the entire array again. I have it set up to accept the input and I can get it to loop and print the array but it will print the entire array and I only want one. This seems like a common thing but my Google-fu returned nothing.
So I have a list variable that connects to an input, logs it into an array, and another function to clear it and print out the values.
Code snippet:
var listItemInput= document.getElementByID("listItem");
var listItem= [];
function insertListItem(){
listItem.push(listItemInput.value);
clearAndShow();
}
function clearAndShow(){
listItemInput.value= "";
}
function printList{
for (var i = 0; i < listItem.length; i++){
document.getElementById("list").innerHTML += '<li>' + listItem[i] + '</li>';
}
When the printList funciton is called by pressing the button it prints the entire array over however I would like a button that simply prints the newest item. How could I do that?
For clarification, I need to print out the list to html and store the values in an array, the values will later be referenced in an if else argument to combine and print them with new variables.
EDIT:
I plugged in the var = lastIndex and changed it as well as made two more variables for my list. This seems to make it work. Thank you.
You could keep track of the last index printed.
var listItemInput= document.getElementByID("listItem");
var listItem = [];
var lastIndex = 0; //Keep track of the last index shown.
function insertListItem() {
listItem.push(listItemInput.value);
clearAndShow();
}
function clearAndShow() {
listItemInput.value = "";
}
function printList() {
for (; lastIndex < listItem.length; lastIndex++) {
document.getElementById("list").innerHTML += '<li>' + listItem[lastIndex] + '</li>';
}
}
This approach assumes you won't be removing items from listItem array, which you didn't express is something that would be done.
If you only want one element, why do you need to iterate?
function printList() {
document.getElementById('list').innerHTML = '<li>' + listItem[listItem.length-1] + '</li>';
}
I am new to JavaScript and would like to ask for some help with my simple script.
What I am trying to do is to retrieve and display the values of all list item elements in the unordered list with the help of the (for) loop. I was able to get the script display all list items in the alert window one by one. But the problem is that I need values of all list elements displayed in a table row way. Like this:
Monday
Tuesday
Wednesday
.......
Here is what I have in my script:
<script language="JavaScript">
<!--
function process() {
a = document.getElementsByTagName('li')
for (i = 0; i < a.length; i++) {
alert(a[i].childNodes[0].nodeValue);
}
}
//-->
</script>
And here is HTML code:
<body>
<ul>
<li>Monday</li>
<li>Tuesday</li>
<li>Wednesday</li>
</ul>
<input type="button" value="Submit" onclick="process()" />
</body>
If that's possible at all would anyone please also explain where I am wrong in my script? Why all 3 list item values can't be shown in the alert window at once?
Thanks a lot!
First, create a string variable: var all_at_once = "". Then, add the contents of the nodeValue. Finally, alert this variable:
function process(){
var a = document.getElementsByTagName('li')
var all_at_once = "";
for(i=0;i<a.length;i++){
all_at_once += a[i].childNodes[0].nodeValue + " ";
}
alert(all_at_once);
}
The alert shows repeatedly because that is what a for loop does... it loops! The loop will iterate over the array of elements returned by getElementsByTagName, executing the loop body once for each element in that array.
If you wanted to display one alert, an option would be to build up a string containing the appropriate text, and alert it afterwards:
var yourString = "";
for(i=0;i<a.length;i++){
yourString += a[i].childNodes[0].nodeValue;
}
alert(yourString);
Some other notes on your code... you should almost always declare variables with the var keyword to prevent them leaking into the global scope. You should also always end lines with semi-colons:
function process(){
var a = document.getElementsByTagName('li'),
yourString = "";
for(i=0;i<a.length;i++){
yourString += a[i].childNodes[0].nodeValue;
}
alert(yourString);
}
<script language="JavaScript">
<!--
function process(){
var data = '';
a=document.getElementsByTagName('li')
for(i=0;i<a.length;i++){
data = data + '\n' +(a[i].childNodes[0].nodeValue);
}
alert(data);
}
//-->
</script>
You need to call alert only once if you need 1 popup with all the text.
function process()
{
var a = getElementsByTagName('li'),
text = '';
for( i = 0; i < a.length; i++ )
{
text += a[i].childNodes[0].nodeValue + '\n';
}
alert( text );
}
You can process the days in whatever manner you like by storing them in an array first, and then iterating:
var days = new Array();
var a = document.getElementsByTagName('li')
for(var i = 0; i < a.length; i++) {
days.push(a[i].childNodes[0].nodeValue);
}
for (i=0; i < days.length; i++) {
// process the day
}
See: http://jsfiddle.net/jkeyes/Cfg4k/ for a working example.
These few adjustments to your function should produce the result you want. Good luck!
What changed: 1) Set up an empty string var 2) Instead of alerting each value, just append them to the string var you created earlier 3) Finally, alert the newly created (concatenated) string!
function process() {
a = document.getElementsByTagName('li');
var days = new String("");
for (i = 0; i < a.length; i++) {
days = days+(a[i].childNodes[0].nodeValue)+"\n";
}
alert(days);
}
Now I see there have been tons of answers since opening this thread... but maybe all the different solutions will help you in different ways.