Goal:
In a sidebar, display two <select> options for a form. The second <select> is dependent on the choice of the first. The second <select> will call the appropriate array from Google Apps Script.
Problem:
I cannot get the array to populate using eventlistener, by attempting google.run, or by referring to another function.
Example:
Below I have three <select> fields. The first is the primary. The second is a traditional array that is dependent on the first. The third <select> is where I cannot get the pulled arrays from the Apps Script server-side code. Keep in mind, I'm trying to pull different arrays based off of the 1st <select>.
//Google Apps Script
function Array1() {
var rng = SpreadsheetApp.getActiveSpreadsheet().getRangeByName('perTwo').getValues();
Logger.log(rng);
return rng;
}
function getValuesForRngActive(students_active) {
var rngValues = SpreadsheetApp.getActiveSpreadsheet().getRangeByName('students_active').getValues();
return rngValues.sort();
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Entry Selection</h2>
<hr> Period:
<select id="slct1" onchange="populate('slct1','slct2'); populate2('slct3')">
<option value=""></option>
<option value="1">Per 1</option>
<option value="2">Per 2</option>
<option value="3">Per 3</option>
</select>
<hr> Student:
<select id="slct2" onchange="myFunction()"></select>
<hr> New Dependent:
<select id="slct3"></select>
<p>When you select a new car, a function is triggered which outputs the value of the selected car.</p>
<p id="demo"></p>
</body>
<script>
function populate(s1, s2) {
var s1 = document.getElementById(s1);
var s2 = document.getElementById(s2);
s2.innerHTML = "";
if(s1.value == "1") {
var optionArray = ["i10", "i20", "Verna"];
}
else if (s1.value == "2") {
var optionArray = ["Last2, First2", "Student, Ima", ""];
}
else if (s1.value == "3") {
var optionArray = ["i10", "i20", "Verna"];
}
for (var i = 0; i < optionArray.length; i++) {
var newOption = document.createElement('option');
newOption.value = optionArray[i];
newOption.innerHTML = optionArray[i];
s2.appendChild(newOption);
}
}
function myFunction() {
var x = document.getElementById("slct2").value;
document.getElementById("demo").innerHTML = "You selected: " + x;
}
function populate2(s3) {
var s1 = document.getElementById('slct1');
var s3 = document.getElementById(s3);
s3.innerHTML = "";
if(s1.value == "1") {
var optionArray = google.script.run.Array1();
}
else if (s1.value == "2") {
var optionArray = ["Last2, First2", "Student, Ima", ""];
}
else if (s1.value == "3") {
var optionArray = google.script.run.withSuccessHandler(onSuccess).getValuesForRngActive('students_active');
}
for (var i = 0; i < optionArray.length; i++) {
var newOption = document.createElement('option');
newOption.value = optionArray[i];
newOption.innerHTML = optionArray[i];
s3.appendChild(newOption);
}
}
</script>
<script>
// Using the "load" event to execute the function "populate"
window.addEventListener('load', populate2);
</script>
</html>
Any help would be greatly appreciated!
that App Script function should take the name of the range as parameter:
function getValuesForRange(rangeName) {
var rngValues = SpreadsheetApp
.getActiveSpreadsheet()
.getRangeByName(rangeName)
.getValues();
return rngValues.sort();
}
so that the range-name students_active can be passed into the App Script function
... and it's success handler callback probably should be populateSelectA().
google.script.run
.withSuccessHandler(populateSelectA)
.getValuesForRange('students_active');
there are a few more issues with the above code ...
while this at least would enable you to populate one <select> with <option>s.
the misconception somehow is, that these callback functions only accept a single parameter, while your populate() accepts two ...App Script should return {} or []; with JS function declarations alike function populateSelectA(data) {} & function populateSelectB(data) {}. jQuery can also be used for the client-side scripting there.
Related
I'm setting 2 select in html, the second one depends of the first one, so I use a script "onchange", so when the first value of the select change, the second one change too, I don't know how to get the variable of my FOR to get the index of the thymeleaf model in my script
SCRIPT-
So my problem here it's inside the if when I tried to get the value of documentos[i].proyecto.id, but I can get documentos[0, 1 or any number].proyecto.id
/*<![CDATA[*/
function load(){
var e = document.getElementById("proyecto-id");
var value = e.options[e.selectedIndex].value;
var sub = document.getElementById("documento-id");
var length = sub.options.length;
for (z = 0; z < length; z++) {
sub.options[z] = null;
}
for(i=0;i<[[${#lists.size(documentos)}]];i++){
if([[${documentos[ i ].proyecto.id}]] == value){
var opt = document.createElement('option');
opt.value = [[${documentos[ i ].id}]]
opt.text = [[${documentos[ i ].nombre}]];
sub.add(opt);
}
}
}
/*]]>*/
HTML select
<select id="proyecto-id" class="custom-select" th:onchange="load()">
<option th:each="p : ${proyectos}"
th:text="${p.nombre}"
th:value="${p.id}">
</option>
</select>
<select id="documento-id" class="custom-select">
</select>
I want to create a dynamic drop down list with javascript.
Right now it works like this:
- if I choose first option, then second, then third.
I want to change this code to:
- when I choose first option, it shows second and third option in the same time(second and third option depends of first)
I want to do something like:
Choose name:
John Doe(first option)
Choose proffesion:
Dentist(second option)
Choose gender:
male(third option)
Is it possible?
Thanks for reply.
<!doctype html>
<html>
<head>
<script>
var modelsArray = new Array(
["Chevy","","Camaro","Corvette","Impala"],
["Dodge","","Avenger","Challenger","Charger"],
["Ford","","Mustang","Shelby"]
);
var colorsArray = new Array(
["Camaro","","White","Black","Red"],
["Corvette","","White","Purple","Blue","Fawn"],
["Impala","","White","Black","Red","Chrome Yellow"],
["Avenger","","White","Acid Green","Alice Blue"],
["Challenger","","White","Violet","Blue-Green"],
["Charger","","White","Dark Pastel Red"],
["Mustang","","White","Debian red","Impala","Flame"],
["Shelby","","White","Deep Spring Bud"]
);
function populate1(s1,s2,s3){
var optionArray = [];
var s1 = document.getElementById(s1);
var s2 = document.getElementById(s2);
s2.innerHTML = "";
var s3 = document.getElementById(s3);
s3.innerHTML = "";
for(var i = 0; i < modelsArray.length; i++){
if(s1.value == modelsArray[i][0]){
for(var x = 1; x < modelsArray[i].length; x++){
optionArray.push(modelsArray[i][x]);
}
}
}
optionArray.sort();
for(var option in optionArray){
var newOption = document.createElement("option");
newOption.value = optionArray[option];
newOption.innerHTML = optionArray[option];
s2.options.add(newOption);
}
}
function populate2(s1,s2){
var optionArray = [];
var s1 = document.getElementById(s1);
var s2 = document.getElementById(s2);
s2.innerHTML = "";
for(var i = 0; i < colorsArray.length; i++){
if(s1.value == colorsArray[i][0]){
for(var x = 1; x < colorsArray[i].length; x++){
optionArray.push(colorsArray[i][x]);
}
}
}
optionArray.sort();
for(var option in optionArray){
var newOption = document.createElement("option");
newOption.value = optionArray[option];
newOption.innerHTML = optionArray[option];
s2.options.add(newOption);
}
}
</script>
</head>
<body>
<h2>Choose Your Car</h2>
<hr />
Choose Car Make:
<select id="slct1" name="slct1" onchange="populate1(this.id,'slct2','slct3')">
<option value=""></option>
<option value="Chevy">Chevy</option>
<option value="Dodge">Dodge</option>
<option value="Ford">Ford</option>
</select>
<hr />
Choose Car Model:
<select id="slct2" name="slct2" onchange="populate2(this.id,'slct3')"></select>
<hr />
Choose Car Color:
<select id="slct3" name="slct3"></select>
<hr />
</body>
</html>
I've created a jsfiddle here which implements a rudimentary example.
You can create DOM event listeners to respond to the change event of the select elements. When these events are triggered, pass the value of the selected option to a function which can extract the models/colours from the data.
Ideally you will setup your server side code to return the data in a format such as:
{
"makes": {
"ford": {
"models": {
"focus": {
"colours": [
"blue",
"black"
]
},
"probe": {
"colours": [
"green",
"grey"
]
}
}
}
}
Using this data format you can easily drill down the object tree e.g.
carData.makes.ford.models.focus.colours
Once you have the data you can then use jQuery to append options to your select e.g.
for (var model in models) {
$('select').append('<option value="'
+ model + '">' + model +
'</option>');
}
*EDIT: If you want to use the combination of the first two selects then you can do something like this:
var mapCombinations = {canada: {toronto: {mapName: "canada"}}};
var mapName = mapCombinations[selectValue1][selectValue2].mapName);
showMap(mapName);
function showMap(mapName) {
// Call server to get map
$.ajax({
type: "GET",
url: "http://yoururl.com/api/map/" + mapName,
success: function(data){
// display map
}
});
}
EDIT2: You can use the same principle if you want the third select to contain an action. I've replaced the colours array with actions. This third select will change depending on the first 2 select values.
Updated jsfiddle which doesn't use jquery.
You can then set up an event listener to process that action.
I need to repeat third value all the time.
I try to give you an example.
First value = Country
Second value = City
Third value = option
And I want to do something like:
If First value = Canada then Second value = Toronto
If First value = Canada then Third value = Show canada map
Second Value and third value don't depend of themselve, only of first value.
I am trying to load the first available option to the third drop-down.
The code is as below.
var categories = [];
categories["startList"] = ["C.","C#.","D.","Eb.","E.","F.","F#.","G.","Ab.","A.","Bb.","B."]; // Level 1
categories["C."] = ["C","C7","Cm","Cm7","Cmaj7","Csus4","Caug","Cdim"];
categories["C"] = ["032010","335553","133211","543210",""];
var nLists = 3; // number of lists in the set
function fillSelect(currCat,currList){
var step = Number(currList.name.replace(/\D/g,""));
for (i=step; i<nLists+1; i++) {
document.forms[0]['List'+i].length = 1;
document.forms[0]['List'+i].selectedIndex = 0;
}
var nCat = categories[currCat];
for (each in nCat) {
var nOption = document.createElement('option');
var nData = document.createTextNode(nCat[each]);
nOption.setAttribute('value',nCat[each]);
nOption.appendChild(nData);
currList.appendChild(nOption);
}
}
function init() { fillSelect('startList',document.forms[0]['List1']);
fillSelect('startList',document.forms[0]['List4']);
fillSelect('startList',document.forms[0]['List7']);
}
navigator.appName == "Microsoft Internet Explorer"
? attachEvent('onload', init, false)
: addEventListener('load', init, false);
function getValues() {
var str = '';
for(i = 1; i < 6; i++) {
document.createElement('select')
str += document.getElementById('List' + i).value+'\n';
document.getElementById('creation').innerHTML=""; }
}
<select name='List4' id="List4" onchange="fillSelect(this.value,this.form['ch2'])"><option selected></option></select>
<select name='ch2' id="ch2" onchange="fillSelect(this.value,this.form['tb2'])"><option selected></option></select>
<select name='tb2' id="tb2"><option selected></option></select>
<input id="f2" type="text" size="1" value=1 class=copystuff>
<button onclick="do2()">Do2</button><br>
Now the problem is that when I try to select the second drop down menu "ch2", I want the first value to be loaded automatically in the third dropdown "tb2" according to the selection that I make in the second menu. For eg, if I select C. in the first menu, C in the second menu, I want 032010 to be already selected in the next menu. Is there any simple way to do this?
I have changed your code up a good bit. But I think it's a bit more readable, and may be easier to extend to more forms, categories, and selects.
First here is the working JSFiddle: http://jsfiddle.net/z1sw2bfq/
Second, here is the Fiddle code. Please see the comments for additional context.
<script>
//create a blank object to hold the select lists
var lists = { };
//create an object to hold the categories text arrays
var categories = {
"startList": ["C.","C#.","D.","Eb.","E.","F.","F#.","G.","Ab.","A.","Bb.","B."], // Level 1
"C.": ["C","C7","Cm","Cm7","Cmaj7","Csus4","Caug","Cdim"],
"C": ["032010","335553","133211","543210",""]
};
function init() {
//load the SELECT element from the form into lists
//Get all of the selects in forms[0]...
var selects = document.forms[0].getElementsByTagName("select");
for (var i in selects) {
//...and load those into lists.
lists[selects[i].id] = selects[i];
//Ex: creates a property like "lists.List4" also referenced by "list['List4']")
// which equals the select element with id List4
}
//enter the list name and the select id
fillSelect('startList', 'List4');
}
function fillSelect(currCatName, currListName){
//get the category
var cat = categories[currCatName];
//verify the category is valid
if (cat) {
//get the select
var select = lists[currListName];
//verify the select is valid
if (select) {
//clear the select
for (var i = select.options.length-1; i>=0; i--)
select.remove(i);
//check the data-first attribute
var datafirst = select.getAttribute("data-first");
if (datafirst == "blank") {
var opt = document.createElement('option');
opt.value = "";
opt.text = "";
select.add(opt);
}
//load the select
for (var j in cat) {
var opt = document.createElement('option');
opt.value = cat[j];
opt.text = cat[j];
select.add(opt);
}
}
}
}
//best to use feature detection instead of browser detection
if (window.attachEvent)
window.attachEvent('onload', init, false);
else
window.addEventListener('load', init, false);
</script>
<form action="#" method="get">
<!--
I added a "data-first" attribute to the selects. This will be used to determine if the
first option in the select is a blank or the first item in the list.
-->
<select name='List4' id="List4" onchange="fillSelect(this.value,'ch2')" data-first="blank"></select>
<select name='ch2' id="ch2" onchange="fillSelect(this.value,'tb2')" data-first="blank"></select>
<select name='tb2' id="tb2" data-first="first"></select>
</form>
I have created a space invaders game using the following tutorial: http://www.html5rocks.com/en/tutorials/canvas/notearsgame/
I now need to populate a select list of states using json within the javascript. I have tried the following set up; I have created a div where the select box can be displayed.
<body>
<h1>Game</h1>
<div id="displaycontent"></div>
<script type='text/javascript'>
I now have the callback functions to populate the list.
function getStates()
{
var url = "states_json.php";
req = new XMLHttpRequest();
req.open("GET", url, true);
//req.setRequestHeader("Accept","application/json; charset=utf-8");
req.onreadystatechange = getStatesCallBack;
req.send(null);
}
function getStatesCallBack()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
var response = req.responseText.parseJSON();
var displaycontent = document.getElementById("displaycontent");
while (displaycontent.hasChildNodes())
{
displaycontent.removeChild(displaycontent.lastChild);
}
var stateSelect = document.createElement("select");
stateSelect.setAttribute("id", "stateslist");
//artistSelect.setAttribute("onChange", "getArtistInfo()");
displaycontent.appendChild(stateSelect);
var state = response.statesarray;
for (i = 0; i <state.length; i++)
{
var state_id = state[i].state_id;
var state_name = state[i].state_name;
if (stateSelect != null && stateSelect.options != null)
{
stateSelect.options[stateSelect.options.length] =
new Option(state_name, state_id, false, true);
}
}
stateSelect.options[0].selected = true;
displaycontent.appendChild(stateSelect);
var stateDetailDiv = document.createElement("div");
stateDetailDiv.setAttribute("id", "statedetails");
displaycontent.appendChild(stateDetailDiv);
//getArtistInfo();
}
}
}
The game code from the tutorial follows the above code. The game works fine however there is no select list populated at all. I have checked the json file output and it is displaying the correct information so that is not the issue. I have tried debugging in firebug but it doesn't show any errors.
The HTML for your select list should look like this eventually:
<select name="stateslist">
<option value="value1">Label For value 1</option>
<option value="value2">Label For value 2</option>
<option value="value3">Label For value 3</option>
</select>
So you should try changing the contents of your for (i = 0; i <state.length; i++) loop and do something like that for each iteration:
var option = document.createElement("option");
option.setAttribute('value', state_id);
option.textContent = state_name;
stateSelect.appendChild(option);
I've created a dynamic dropdown list with jQuery and JavaScript. I'm hoping someone can take a look and let me know if this is an appropriate way to handle this type of task. I'm specifically curious to know if this code is scalable, and will it perform well? Next, would it be suggested to use a switch statement instead of several if statements in the JavaScript I have below? If so, why? I'd like to store this to be reused anytime I implement a solution like this, but as I'm new to JavaScript I don't completely trust my work yet.
JSFIDDLE: http://jsfiddle.net/6vrpF/
HTML:
<select id='parent'>
<option value='test'>test</option>
<option value='sure'>sure</option>
<option value='cool'>cool</option>
<option value='best'>best</option>
</select>
<select id='child'>
</select>
JavaScript:
function newDropdown()
{
var html = ""
for(i=0; i<arguments.length; i++)
{
html += "<option value='"+arguments[i]+"'>"+arguments[i]+"</option>"
}
$("#child").append(html)
}
$("#parent").on("change",function(){
$('#child').text("")
var selection = $("#parent").val()
if(selection == 'test') {newDropdown('a','b','c')}
if(selection == 'sure') {newDropdown('d','e','f')}
if(selection == 'cool') {newDropdown('g','h','i')}
if(selection == 'best') {newDropdown('j','k','l')}
});
updated the fiddle
http://jsfiddle.net/6vrpF/4/
var parentChild = {
"test" :['a','b','c'],
"sure" :['d','e','f'],
"cool" :['g','h','i'],
"best" :['j','k','l']
};
function newDropdown()
{
var html = ""
for(i=0; i<arguments.length; i++)
{
html += "<option value='"+arguments[i]+"'>"+arguments[i]+"</option>"
}
$("#child").append(html)
}
$("#parent").on("change",function(){
$('#child').text("")
var selection = $("#parent").val();
newDropdown( parentChild[selection].join(",") );
});
You need to get your data in the JSON format as mentioned/defined above
Edit: this is the updated fiddle which will give options one by one
http://jsfiddle.net/6vrpF/6/
var parentChild = {
"test" :['a','b','c'],
"sure" :['d','e','f'],
"cool" :['g','h','i'],
"best" :['j','k','l']
};
function newDropdown()
{
var array = arguments[0];
var html = ""
for(i=0; i<array.length; i++)
{
html += "<option value='"+array[i]+"'>"+array[i]+"</option>"
}
$("#child").append(html)
}
$("#parent").on("change",function(){
$('#child').text("")
var selection = $("#parent").val();
newDropdown( parentChild[selection] );
});