Good afternoon.
I am trying to use the selected value in the options box in a for loop.
The theory being that if the user selects 3, for example, Javascript will populate 3 boxes with a fruit from the array.
Can anyone point me in the right direction? I have enclosed Codepen link too.
function changeText(){
var e = document.getElementById('selectbox');
var strUser = e.options[e.selectedIndex].value;
for (var i=0; i<=strUser; i++) {
document.getElementById('boldStuff').innerHTML = randomFruit + strUser;
}
}
http://codepen.io/jameswinfield/pen/aNWRKm
The ID element should be unique to the entire dom. You are using it multiple times for boldStuff. If you would like to be able to grab them like that you should use a class.
Here is a version that should do what you want: http://codepen.io/anon/pen/KzmGLP?editors=0010
Keep in mind that sets the value to every box, even the hidden ones. You will have to get a new random fruit per box or they will all have the same fruit.
I changed all id="boldStuff" to class="boldStuff",
grabbed all boldStuffs
var boldStuffs = document.getElementsByClassName('boldStuff');
and looped over every boldStuff
for (var i = 0; i < boldStuffs.length; i += 1) {
//And set the value of each boldStuff to a new random fruit.
boldStuffs[i].innerHTML = getRandomItem(fruitsArray);
}
The following line also only runs once so no matter how many boxes there are they will all have the same fruit (because randomFruit is never changed)
var randomFruit = fruitsArray[Math.floor(Math.random() * fruitsArray.length)];
You can use a function to grab a random fruit instead, something like this:
function getRandomItem(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
Then use getRandomItem(fruitsArray); to get a random fruit.
Related
I'm new with Google scripts and now I have to make a form with a list of choices. These choices should be picked up from the Google sheet.
So the first question is how to chose only unique values from some range of my spreadsheet?
The second is how to pass this list so that they will be the items in the list?
The code I've tried is:
function getMembranesList() {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/......");
var itemList = ss.getSheetByName('Answers').getRange("Q1:Q").getValues();
var form = FormApp.getActiveForm();
var item = form.addListItem()
item.setTitle('test question');
item.createChoice(itemList);
}
Looking at the methods available to populate the ListItem, you have to choose one and set your data up so it matches the expected input. For my example, I chose the setChoiceValues method, which looks for an array. So I have to manipulate the items into an array.
One thing the getRange.getValues() method does NOT get you is how many non-blank items are returned in the list. I used this quick way to get a count of those items, so I have a maximum bound for my loops. Then, I formed the itemArray and added only the non-blank items to it.
After that, it's just a matter of creating the ListItem and adding the values:
function getMembranesList() {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/...");
var itemList = ss.getSheetByName('Answers').getRange("Q1:Q").getValues();
var itemCount = itemList.filter(String).length;
var itemArray = [];
for (var i = 0; i < itemCount; i++) {
itemArray[i] = itemList[i];
}
var form = FormApp.getActiveForm();
var item = form.addListItem();
item.setTitle('test question');
item.setChoiceValues(itemArray);
}
So, i have this code, it works:
var curp = document.getElementById("id_sc_field_curp_id_1");
var getcurp = curp.options[curp.selectedIndex].text;
var rfc = getcurp.substr(0, 10);
document.getElementById("id_sc_field_virtual_rfc_1").value = rfc;
It copy the text inside the field (td - CURP) "id_sc_field_curp_id_1", and trim it to put the result in another field (RFC) "id_sc_field_virtual_rfc_1"
Example img
JSFIDDLE: https://jsfiddle.net/90yzgcqe/1/
I want to adapt the code to work with the other rows, witch have an incremental id...
id_sc_field_curp_id_1,id_sc_field_curp_id_2,id_sc_field_curp_id_3, d_sc_field_virtual_rfc_1, d_sc_field_virtual_rfc_2, d_sc_field_virtual_rfc_3...etc
Im making this function, but... i dont know how to make it work...
function rfc() {
for (var i = 0; i <= 19; i++) {
var curp = document.getElementById("id_sc_field_curp_id_" + i);
var getcurp = curp.options[curp.selectedIndex].text;
var rfc = getcurp.substr(0, 10);
document.getElementById("id_sc_field_virtual_rfc_" + i).value = rfc;
}
}
What is wrong?
Some jQuery gets us there fairly easily, first get the matching dropdowns and then interact with them.
$(function() {
//get the list of dropdowns that start with all but the numeral
var lst = $("[id^='id_sc_field_curp_id_']");
$.each(lst, function(idx, elem) {
//lets store the dropdown for use in the loop
let $field = $(elem);
//for example lets print the selected text
console.log($field.find("option:selected").text());
});
});
There are a couple of options from there, you can use the dropdown to create the rfc's id, or use the jQuery function closest() to get it. Once you have the associated rfc's input it should be trivial to get set the value.
EDITED:1
More specific javascript, and a link to a modified jsFiddle
$(function() {
//get the list of dropdowns that start with all but the numeral
var lst = $("[id^='id_sc_field_curp_id_']");
$.each(lst, function(idx, elem) {
//lets store the dropdown for use in the loop
let $field = $(elem);
//for example lets alert the selected text
alert($field.find("option:selected").text().substr(0,10));
$field.closest("[id^='idVertRow']")
.find("[id^='id_sc_field_virtual_rfc_']")
.val($field.find("option:selected").text().substr(0,10));
});
});
Here is my fiddle : DEMO
Under the "Rules" Tab, on click of "+" a group of form-fields are cloned i.e, Join operator, Attributes, Operator & Threshold.
The attribute drop down is populated using a json (called expressionDetails) created using the relationship between contracts and thresholds variables.
Based on the choice of attributes, the thresholds field will be populated.
I could achieve this for the non-cloned Attribute and Threshold. However, due to class/ id duplication I am not able to pick up the cloned attribute's value as all the clones attributes hold the same class and their values are getting concatenated (in var z1).
//Appending option to "cloned" thresold field based on choice of attribute
$('.attributeExpr').on('change', function(e) {
$('.thresholdExpr').empty();
var z1 = $(".attributeExpr option:selected").text();
console.log(z1);
var a1 = expressionDetails[z1];
console.log(a1);
for (var i1 = 0; i1 < a1.length; i1++) {
var b1 = a1[i1].name;
// alert(b1);
var opt1 = $("<option>").text(b1);
// console.log(opt1);
$('.thresholdExpr').append(opt1);
}
});
Is there a different approach for this? Also, it should work for every cloned group thereafter as I will be using all of these values to create the "Expression" field.
Any help would be much appreciated. Thank you.
Replace the line 3 in above code with this. it will only return selected value.
var z1 = $("option:selected",$(this)).text();
Have you tried something like:
var z1 = $(this).find('option:selected').text();
Instead
var z1 = $(".attributeExpr option:selected").text();
Try this, I have tested it in your fiddle DEMO and it is working.
$('.attributeExpr').on('change', function(e) {
var index = $(this).index('.attributeExpr');
$('.thresholdExpr:eq( '+index+' )').empty();
var z1 = $(this).find("option:selected").text();
console.log(z1);
var a1 = expressionDetails[z1];
console.log(a1);
for (var i1 = 0; i1 < a1.length; i1++) {
var b1 = a1[i1].name;
// alert(b1);
var opt1 = $("<option>").text(b1);
// console.log(opt1);
$('.thresholdExpr:eq( '+index+' )').append(opt1);
}
});
I have added index so it can target the current element.
First thing you should do to make it work properly specially such complex implementation is to make the expressionsBuilder formgroup option fields to be dynamic, means it is being populated by JavaScript and not hard-coded in your HTML.
Then, you will assign the change event listener for each individual fields you created, this way you can control every form-group's behavior.
example click here
by populating it programatically you have total control of the fields behavior. You can then get each and every value of fields by iterating expressions variable like this:
for (var i = 0; i < expressions.length; i++)
{
var id = expressions[i];
var theAttribute = $("#" + id).find("[name='attribute']").val();
var theOperator = $("#" + id).find("[name='operator']").val();
var theThreshold = $("#" + id).find("[name='threshold']").val();
}
Hope that helps
===
ALSO heads up, it appears you are creating such complex application. I am suggesting you should make use for JavaScript frameworks to ease up maintainability of your code. This approach will become very hard to maintain in the long run
So, I have this function that, after an update, deletes elements from a table. The function, lets call it foo(), takes in one parameter.
foo(obj);
This object obj, has a subfield within called messages of type Array. So, it would appear something like this:
obj.messages = [...];
Additionally, inside of obj.messages, each element contains an object that has another subfield called id. So, this looks something like:
obj.messages = [{to:"You",from:"Me",id:"QWERTY12345.v1"}, ...];
Now, in addition to the parameter, I have a live table that is also being referenced by the function foo. It uses a dataTable element that I called oTable. I then grab the rows of oTable and copy them into an Array called theCurrentTable.
var theCurrentTable = oTable.$('tr').slice(0);
Now, where it gets tricky, is when I look into the Array theCurrentTable, I returned values appear like this.
theCurrentTable = ["tr#messagesTable-item-QWERTY12345_v1", ...];
The loop below shows how I tried to show the problem. While it works (seemingly), the function itself can have over 1000 messages, and this is an extremely costly function. All it is doing is checking to see if the current displayed table has the elements given in the parameter, and if not a particular element, delete it. How can I better write this function?
var theCurrentTable = oTable.$('tr').slice(0);
var theReceivedMessages = obj.messages.slice(0);
for(var idx = 0; idx < theCurrentTable.length; idx++){ // through display
var displayID = theCurrentTable[idx].id.replace('messagesTable-item-','').replace('_','.');
var deletionPending = true;
for(var x = 0; x < theReceivedMessages.length; x++){
var messageID = theReceivedMessages[x].id;
if(diplayID == messageID){
console.log(displayID+' is safe...');
deletionPending = false;
}
}
if(deletionPending){
oTable.fnDeleteRow(idx);
}
}
I think I understand your problem. Your <tr> elements have an id that should match an item id within your messages.
First you should extract the message id values you need from the obj parameter
var ids = obj.messages.map(function (m) { return '#messagesTable-item-' + m.id; });
This will give you all the rows ids you need to keep and then join the array together to use jQuery to select the rows you don't want and remove them.
$('tr').not(ids.join(',')).remove();
Note: The Array.prototype.map() function is only supported from IE9 so you may need to use jQuery.map().
You could create a Set of the message ID values you have, so you can later detect if a given ID is in this Set in constant time.
Here is how that would look:
var theCurrentTable = oTable.$('tr').slice(0);
var theReceivedMessages = obj.messages.slice(0);
// Pre-processing: create a set of message id values:
var ids = new Set(theReceivedMessages.map( msg => msg.id ));
theCurrentTable.forEach(function (row, idx) { // through display
var displayID = row.id.replace('messagesTable-item-','').replace('_','.');
// Now you can skip the inner loop and just test whether the Set has the ID:
if(!ids.has(displayId)) {
oTable.fnDeleteRow(idx);
}
});
So now the time complexity is not any more O(n.m) -- where n is number of messages, and m the number of table rows -- but O(n+m), which for large values of n and m can make quite a difference.
Notes:
If theCurrentTable is not a true Array, then you might need to use a for loop like you did, or else use Array.from(theCurrentTable, function ...)
Secondly, the implementation of oTable.fnDeleteRow might be that you need to delete the last rows first, so that idx still points to the original row number. In that case you should reverse the loop, starting from the end.
I have a simple question. I have a select list like this:
var myarray = ["one", "two", "three"];
var container = document.createElement("select");
for (var i = 0; i < myarray.length; i++) {
var element = document.createElement("option");
var textlabel = document.createTextNode(myarray[i]);
if (element.nodeValue == "two") {
element.selected = true;
}
element.appendChild(textlabel);
container.appendChild(element);
}
document.body.appendChild(container);
I have two questions about it:
1) I am pretty sure that the element that should be selected right now is "two"... isn't it?
2) Since the option elements are being created dinamically inside a loop (there are no three different option variables for me to play with, but just one that gets renewed as the loop goes forward), how do I reference the selected one for future uses?
For example, imagine that later on I get user input, and according to that input I want that this list has as a selected item, "three".
Thank you for any help! Here is the fiddle if you want to use it...
1) I am pretty sure that the element that should be selected right now
is "two"... isn't it?
No, it's not: you check element.nodeValue, while in fact you should've been checking textLabel's one - or just the content itself:
if (myarray[i] === 'two') {
element.selected = true;
}
2) Since the option elements are being created dinamically inside a
loop (there are no three different option variables for me to play
with, but just one that gets renewed as the loop goes forward), how do
I reference the selected one for future uses?
See, <select> elements has two useful properties: options (which contains all the options in it, and is updated dynamically) and selectedIndex. You can combine them to get the selected option:
container.addEventListener('change', function() {
console.log(this.options[this.selectedIndex]);
}, false);
But if what you want is to know the value of selected element, that's even easier - with container.value.
For example, imagine that later on I get user input, and according to
that input I want that this list has as a selected item, "three".
That's piece of cake if you know the position of the option that corresponds to this: just use selectedIndex property again:
container.selectedIndex = 3;
Just change the following in the for loop to fix the selection problem:
if (myarray[i] == "two")
Try to use console.log (on chrome or firefox with firebug) to debug your script :
Try this :
var myarray = ["one", "two", "three"];
var container = document.createElement("select");
container.id = "mySelect" ;
for (var i = 0; i < myarray.length; i++) {
var element = document.createElement("option");
var textlabel = document.createTextNode(myarray[i]);
element.appendChild(textlabel);
if (element.value == "two") {
element.selected = true;
}
container.appendChild(element);
}
document.body.appendChild(container);
in order to refer to your selected element you should give your select element an id and access to it like below:
el = document.getElementById('mySelect');
el.selectedIndex ; // give you the selected index
el.options[el.selectedIndex]; // give you the value