I recently asked a question about how to add items to a Google Form from a Google Spreadsheet. And it works great. Instead of using FormApp.create(), though, I'll have to use .openByUrl() because the ID has to stay the same. The problem is that if I run my script again, it'll open the existing form (great) and then append more items to the existing form.
This behaviour makes perfect sense but is not quite what I want. So I thought I'd just remove all existing items before I add new ones from my spreadsheet. I consulted the Google dev site for Form Services and feel like I should have all the pieces. I can't quite put them together, though.
I am now doing this following:
var form = FormApp.openByUrl('https://docs.google.com/forms/d/.../edit');
var items = form.getItems();
for (var i in items) {
form.deleteItem(i);
}
However, that'll give me an out of range error. Can someone point me in the right direction?
The problem is with how you're iterating over the array.
Try this:
var form = FormApp.openByUrl('https://docs.google.com/forms/d/.../edit');
var items = form.getItems();
for (var i=0; i<items.length; i++) {
form.deleteItem(i);
}
function clearForm(){
var items = form.getItems();
while(items.length > 0){
form.deleteItem(items.pop());
}
}
This worked for me when I ran into the same issue:
for (var i=0; i<items.length; i++) {
if (items[i] != null){
form.deleteItem(i);
}
}
Start by deleting the last item and repeat it until all items are deleted. This could be done by a reverse for loop:
function deleteAllItems(){
var form = FormApp.openById(/*put here your form id*/);
var items = form.getItems();
var end = items.length - 1;
for(var i = end ; i >= 0; i--){
form.deleteItem(i);
}
}
Another alternative is avoid of a variable index by using 0, so the first item will be deleted, no matter if a regular or a reverse loop is used. Note: This was already mentioned in a comment to another answer.
I also ran into the same problem. This one worked for me:
function deleteItems(){
var form = FormApp.openById('ID');
var items = form.getItems();
items.forEach(function(e){form.deleteItem(e)})
}
var form = FormApp.openByUrl('https://docs.google.com/forms/.../edit');
var items = form.getItems();
while(items.length > 0)
{
form.deleteItem(items.pop());
}
This works for me.
When you are checking the length of a variable=form.getItems() in a loop, its going to through some error because the length of that is not changing and the loops end up being infinite and throughing error.
So, heres my solution to the problem:
for(;form.getItems().length>0;)
{
form.deleteItem(0);
}
I ran into the same problem. However, I have fixed it by iterating in the reverse order.
var form=FormApp.openByUrl('form url here');
var Items=form.getItems();
var len=Items.length;
for (var i=Items.length-1;i>2;i--){ //Delete every item except first three items
form.deleteItem(i)
}
There are many options for looping over all form items and removing each, the most succinct being:
With Chrome V8 runtime
form.getItems().forEach(form.deleteItem)
Without Chrome V8 runtime
for each (var item in form.getItems()) {
form.deleteItem(item);
}
Related
I'm doing an assignment that requires us to add objects to a fake cart array from a fake database array, then go to a cart page that displays everything in the "cart." Now, that's all well and good, but for some reason I can't get more than one object to show up in the fakeCart array.
I'm fairly certain the issue is in this function, because everything displays properly otherwise in every way.
So, it turns out I posted code that I was tinkering with. I've since updated it to the almost-working one.
function addToCart(e) {
'use strict';
var fakeCart = [];
for (var i = 0; i < fakeDatabase.length; i++) {
if (fakeDatabase[i].id == e.currentTarget.id) {
fakeCart.push(fakeDatabase[i]);
}
}
sessionStorage.fakeCart = JSON.stringify(fakeCart);
}
Essentially, I can get the code to make a single object go from one array (database) to the other (cart), but whenever I try to add one back in it just replaces the last one.
The code overwrites any existing value of sessionStorage.fakeCart, so there will never be more than one element in the serialized array. You can fix that by reading the value from sessionStorage instead of creating a new list each time.
function addToCart(e, productNum) {
'use strict';
// change this
var fakeCart = JSON.parse(sessionStorage.fakeCart) || [];
for (var i = 0; i < fakeDatabase.length; i++) {
if (fakeDatabase[i].id == e.currentTarget.id) {
// and this
fakeCart.push(fakeDatabase[i]);
}
}
sessionStorage.fakeCart = JSON.stringify(fakeCart);
}
I think :
Instead of
fakeCart[i].push(fakeDatabase[i]);
you require this
fakeCart.splice(i, 0, fakeDatabase[i]);
a fairly simple question today.
I have an object that looks like this:
var buttonLogos = {
adcraft: [".","..","1.png","2.png","3.png"],
ferries: [".","..","1.png","2.png"]
}
and I'm looking for a quick way to remove the entries at the beginning with the dots, I would usually just filter out anything with a dot, but I can't because the strings I want contain a .png
it might be a solution to filter out the first two entries, because they will always be "." and ".." but alas I'm not sure how to even do that.
(jQuery is encouraged)
I would love some help! Thanks.
for(i in buttonLogos){
buttonLogos[i] = buttonLogos[i].filter(function(i){
return !i.match(/^\.{1,2}$/);
});
}
You can use js regex as follows,
buttonLogos.adcraft = $(buttonLogos.adcraft).filter(function(i,val){return val.match(/[^\.]/);});
Filters as mentioned in other answers or a combination of indexOf and splice would also work.
var adcraft = [".","..","1.png","2.png","3.png"];
var elems_to_rm = [];
for (var i = 0; i < adcraft.length; i++) {
if (adcraft[i].indexOf('.') === 0) {
elems_to_rm.push(adcraft[i]);
}
}
for (var i = 0; i < elems_to_rm.length; i++) {
var index = adcraft.indexOf(elems_to_rm[i]);
adcraft.splice(index, 1);
}
Try manually. Any number of items can be deleted from the array by specifying just two
arguments: the position of the first item to delete and the number of items to delete. For
example, splice(0, 2) deletes the first two items.
I'm trying hard to learn javascrip+jquery on my own, and also trying to learn it right. Thus trying to enforce the DRY rule.
I find myself stuck with a problem where I have an array,
var animals = [4];
a function,
var legs = function(amount){
this.amount = amount;
this.body = Math.floor(Math.random()*amount)+1;
}
and an evil for loop. I also have 5 div's called printAnimal1, printAnimal2 and so on.. In which I wish to print out each value in the array into.
for(i = 0; i < animals.length; i++){
animals[i] = new legs(6);
$(".printAnimal"+i).append("animals[i]");
}
I feel as if I'm close to the right thing, but I cant seem to figure it out. I also tried something like this:
for(i = 0; i < animals.length; i++){
animals[i] = new legs(6);
$this = $(".printAnimal");
$(this+i).append("animals[i]");
}
But one of the problems seem to be the "+i" and I cant make heads or tails out of it.
I also know that I can simply do:
$(".printAnimal1").append("animals[i]");
$(".printAnimal2").append("animals[i]");
$(".printAnimal3").append("animals[i]");
...
But that would break the DRY rule. Is it all wrong trying to do this with a for loop, or can it be done? Or is there simply a better way to do it! Could anyone clarify?
Your first attempt should be fine, as long as you take "animals[i]" out of quotes in your append() call ($(".printAnimal"+i).append(animals[i]))
Also, I assume you declared var i; outside your for loop? If not, you'll want to declare it in your for loop (for(var i=0....)
EDIT: problems with your fiddle
you never call startGame()
you didn't include jQuery
you can't (as far as I know) append anything that isn't html-- in your case, you're trying to append a js object. What do you want the end result to look like?
http://jsfiddle.net/SjHgh/1/ is a working fiddle showing that append() works as you think it should.
edit: forgot to update the fiddle. Correct link now.
EDIT: reread your response to the other answer about what you want. http://jsfiddle.net/SjHgh/3/ is a working fiddle with what you want. More notes:
You didn't declare new when you called DICE
you have to reference the field you want, (hence dices[i].roll), not just the object
Just a few comments:
This is declaring an array with only one item and that item is the number 4
var animals = [4];
In case you still need that array, you should be doing something like:
var animals = []; // A shiny new and empty array
and then add items to it inside a for loop like this:
animals.push(new legs(6)); //This will add a new legs object to the end of the array
Also, what is the content that you are expecting to appear after adding it to the div?
If you want the number of legs, you should append that to the element (and not the legs object directly).
for(i = 0; i < animals.length; i++){
animals.push(new legs(6));
$(".printAnimal"+i).append(animals[i].body);
}
Adding another answer as per your comment
var i, dicesThrown = [];
function throwDice(){
return Math.ceil(Math.random() * 6);
}
//Throw 5 dices
for (i=0 ; i<5 ; i++){
dicesThrown.push( throwDice() );
}
//Show the results
for (i=0 ; i<5 ; i++){
$("body").append("<div>Dice " + (i+1) + ": " + dicesThrown[i] +"</div>");
}
I'm using the Datatables jQuery plugin. The table is pulling the data from an AJAX source (a SQL Server query, processed by ASP.NET into a JSON object). I want to create a live view of the table so that changes appear in real time. But rather than reloading the entire table every few seconds with fnReloadAjax() (which, from experience, has proven to be quite burdensome on the browser) I'm only updating the records that are new or modified, using fnAddData() and fnUpdate().
After getting a JSON object of just the new or modified records, here's my code to process the object.
var newData = updatedDataJSON.aaData;
if (newData[0] != null) {
for (i = 0; i < newData.length; i++) { //Loop through each object
if (newData[i].bNewCase === true) { //Process new cases
oTable.fnAddData(newData[i]);
} else { //Process modified cases
var tableArray = oTable.fnGetData();
var index;
var found = false;
var serial = newData[i].serial;
var dataObject = newData[i];
//First gotta find the index in the main table for
// the record that has been modified. This is done
// by matching the serial number of the newData
// object to the original aData set:
for (ii = 0; ii < tableArray.length; ii++) {
var value = tableArray[ii]['serial'];
value = value.replace(/<\/?[^>]+(>|$)/g, "");
if (value === serial) {
index = ii;
found = true;
}
}
if (found) {
oTable.fnUpdate(dataObject, index);
console.log('Updated ' + newData[i].serial);
}
}
}
}
My problem is that even though the newData.length property of the first for loop could be greater than 1, the for loop exits early (after one iteration). I added the console.log statement at the end and it started passing errors saying that newData[i].serial was undefined. This makes me think that the entire newData array was destroyed or something...
I'm really hoping that I've just made a stupid mistake (though I've checked and checked and checked some more but can't find one). Maybe there's something that I'm overlooking. If anyone has any advice, it would be greatly appreciated.
Credit goes to #elclarnrs for the solution, posted above in the comments. The solution was declaring the values of i and ii in the scope of the function. That got everything working smoothly. Good to know for future reference.
I have been working on creating a custom script to help manage a secret questions form for a login page. I am trying to make all the seperate select lists dynamic, in that if a user selects a question in one, it will no longer be an option in the rest, and so on. Anyways, the problem I am having is when I try to set the variables in the other lists to null. I am currently working with only 3 lists, so I look at one list, and find/delete matches in the other 2 lists. Here is my loop for deleting any matches.
for(i=0; i<array1.length; i++) {
if(array2[i].value == txtbox1.value) {
document.questions.questions2.options[i] = null
}
if(array3[i].value == txtbox1.value) {
document.questions.questions3.options[i] = null
}
}
This works fine if both the matches are located at the same value/position in the array. But if one match is at array1[1] and the other match is at array3[7] for example, then only the first match gets deleted and not the second. Is there something I am missing? Any help is appreciated. Thanks!
I don't see too many choices here, considering that the position in each array can vary.
Do it in separate loops, unless of course you repeat values in both arrays and share the same position
EDTI I figured out a simple solution, it may work, create a function. How about a function wich recives an array as parameter.
Something like this:
function finder(var array[], var valueToFound, var question) {
for (i=0; i<array.lenght; i++) {
if (array[i].value == valueToFound) {
switch (question) {
case 1: document.questions.questions1.options[i] = null;
break;
}
return;
}
}
}
I think i make my point, perhaps it can take you in the right direction
My bet is that the code isn't getting to array3[7] because either it doesn't exist or that array2 is too short and you're getting a JavaScript exception that's stopping the code from doing the check. Is it possible that array2 and array3 are shorter than array1?
It is more code, but I would do it like this:
var selectedvalue == txtbox1.value;
for(i=0; i<array2.length; i++) { // iterate over the length of array2, not array1
if(array2[i].value == selectedvalue) {
document.questions.questions2.options[i] = null;
break; // found it, move on
}
}
for(i=0; i<array3.length; i++) {
if(array3[i].value == selectedvalue) {
document.questions.questions3.options[i] = null;
break; // you're done
}
}