Display value depending on selected values from 2 Dropdown menus in Javascript? - javascript

This is what I've constructed so far: https://plnkr.co/edit/fnhKUhuTYjUTQgJLnZoT?p=preview
I want to display a value in the input textbox that depends on the user's 2 choices from the 2 dropdown menus. I want that value to come from the values array here:
var values = [1, 2, 0.1, 1, 3, .2, 2, 3,.3];
If the 1st choice is 1 and the 2nd choice is 2, then I want the input textbox to display 0.1. And vice-versa, so if the 1st choice is 2 and the 2nd choice is 1 then I want 0.1 to be the output.
And I want nothing to happen if the user chooses the same value for both menus. So if the user chooses 2 for both menus, then I want there to be no output
How can I program this?
EDIT: I should probably first convert the values array to a hashmap like this:
var values = [(1, 2): 0.1, (1, 3): .2, (2, 3): .3];

I hope you won't mind me using jQuery in my solution since you had it included in your Plunk.
var $selects = $('select');
var $output = $('#pred');
First I will create a map of input pairs to output values.
var values = {
'1,2': 0.1,
'1,3': 0.2,
'2,3': 0.3
};
Next, I will listen for a change event on the select menus. In my change handler, I will map the values of the selects into an array of numbers. Next, by sorting and joining this array, I should end up with a stringed pair of numbers in ascending order and delimited by a comma; a key, just like the keys in my values object.
Finally, I will set the value of $output to the value of values at the resultant key. If values[key] is undefined, I will default to an empty string.
$selects.on('change', function () {
var key = $selects.map(function (index, el) {
return Number($(el).val());
})
.get()
.sort()
.join(',');
$output.val(values[key] || '');
});

Related

Generalize multiple forEach to execute on the entire array of values not just selected columns of the array. Google Script, JavaScript

I have a function that takes an array of RegEx(es) and applies them to the selected columns of an array of values, and returns this entire array of values with the columns transformed by the RegEx(es)
used like:
values = processRegEx(values, [0,4,7], RgX);
I want to generalize this so that if the array - colIdx has no entries, it runs on the entire array of values.
values = processRegEx(values, [], RgX);
I tried:
colIdx.length > 0 ? row[idx]=row[idx].replaceAll(...n) : row=row.replaceAll(...n);
but this does not work as no RegEx gets applied. the original array values is returned
How do to do this?
What I have so far:
// Add more as needed:
// [Regex, Replacement]
const RgX = [
[/\bN\./g, 'North'],
[/\bS\./g, 'South'],
[/\bSt\./g, 'Street']
];
function processRegEx(arr, colIdx, replaceTable) {
arr.forEach(function(row){
colIdx.forEach(function(idx){
replaceTable.forEach(function(n){
row[idx]=row[idx].replaceAll(...n)
});
});
});
return arr;
};

Can SUBSTR() query change the output format of an array such that javascript field listeners can no longer read the array?

Really struggling to make a concise question without it being two phrases.
All my code worked until I started uses SUBSTR() in my mySQL query.
I have a list of folder numbers (F123456, F233999, etc).
I had a nice function that detected user input into a field, and the field would change color if their entered value was in the array.
After a while I realized the "F" wasn't needed, so I used SUBSTR (value, 2, 6) to drop the "F" in the query result and just return the remaining 6 digits. The query works both in the PMA window and if I print_r or var_dump the results.
But it seems like the array isn't being read fully, down in the javascript code.
This is the query where 'value' is the name of the column where the #'s reside. It sits across from 'cust_folder' which is in the variable column.
$getFileNumbers = $conn->query(" SELECT SUBSTR(value, 2, 6)
FROM smfqg_themes
WHERE variable = 'cust_folder' ");
while($rows = $getFileNumbers->fetch_object()) {
$fileNumberArray[] = $rows;
}
This is the javascript:
<input type="text" size="10" id="idk" name="file_number" onblur="checkNumber()" onkeyup="checkNumber()" >
<script type="text/javascript">
const idk = document.getElementById('idk');
idk.addEventListener('input', checkNumber);
idk.addEventListener('focus', checkNumber);
idk.addEventListener('blur', checkNumber);
function checkNumber() {
const theArray = <?php echo json_encode($fileNumberArray); ?>;
if (theArray.includes(idk.value)) {
idk.style.background = "green"
} else if (theArray.find(item => item.value === idk.value) !== undefined) {
idk.style.background = "green";
}else {
idk.style.background = "red";
}
}
</script>
Is there a format step I'm missing--by using SUBSTR--that is needed to get the cont "theArray" looked at properly?
I have printed and dumped the array, both using an alias and without, and the results produce all the 6-digit values.
I have tried using SUBSTR with both (value, 2, 6) and (value, -6,6) but there are no changes.
When your query was SELECT value ....
the column name in the resultset was called value
When you changed it to SELECT SUBSTR(value, 2, 6)
the column name in the resultset was called SUBSTR(value, 2, 6)
So give that column an alias like this
SELECT SUBSTR(value, 2, 6) as value
Now the column will again have the correct name and there will be a property of value instead of a propery of SUBSTR(value, 2, 6)
Then javascript code that addresses idk.value will work again.

How to filter array for only exact match in Google Apps Script/Javascript

I'm trying to use Google Apps Script to filter only exact matches. I've seen similar questions, but I can't seem to apply them to my situation.
On one sheet, I have a table of information which has the item name in column A, its' ingredient in column B, and its' quantity in column C. Column A contains items named Test and Test 2. When I filter for Test 2, I get results of both Test and Test 2. Here is the code I'm using:
var costSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Cost');
var ingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Recipe Ingredient');
// Create list of items to filter from the full list
var rows = costSheet.getLastRow();
var itemList = costSheet.getRange(2, 1, rows - 1).getValues();
// Convert itemList to array to be used in filter
itemList = itemList.join();
// Get full non-filtered data
var fullList = ingSheet.getRange('A2:C514').getValues();
// Apply filter criteria
function checkMatch(item) {
return itemList.indexOf(item[0]) != -1;
}
filterList = fullList.filter(checkMatch);
// Clear target location, then place filtered data
costSheet.getRange('C2:E514').clearContent();
costSheet.getRange(2, 3, filterList.length, 3).setValues(filterList);
I don't have any trouble getting accurate results for multiple items from all three columns, and the only issue I have is when I try to filter an item that begins with the name of another item in the full list (e.g. filtering for Test 2 returns both Test and Test 2, when I want it to just return Test 2).
I am new to working with Google Apps Script/Javascript, hence the 'amateur' coding.
Explanation:
You are very close!
The issue is related to this line:
itemList = itemList.join();
Assuming that itemList = [["Test 2"],["Test 3"]] as a result of the getValues() method.
If you apply join you are converting the above array into the following string:
Test 1,Test 2
Therefore itemList.indexOf("Test") will return 0 which means your filter function will evaluate to true, but you don't want that since Test is not part of your array. You are mistakenly using the indexOf method of strings instead of the indexOf method of arrays.
Having said that, your goal is to use the the indexOf method of arrays. In order to do so, itemList needs to be an array and not a string.
To convert a 2D array [["Test 2"],["Test 3"]] into a 1D array [Test 1, Test 2] you can use flat.
Solution:
Change:
itemList = itemList.join();
To:
itemList = itemList.flat();
Improved Solution:
Going for the extra mile, you can shorten your code and make it more JavaScript modern like that:
function shorterFunction(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const costSheet = ss.getSheetByName('Cost');
const ingSheet = ss.getSheetByName('Recipe Ingredient');
const itemList = costSheet.getRange(2, 1, costSheet.getLastRow() - 1).getValues().flat();
const fullList = ingSheet.getRange('A2:C514').getValues();
const filterList = fullList.filter(r=>itemList.includes(r[0]))
costSheet.getRange('C2:E514').clearContent();
costSheet.getRange(2, 3, filterList.length, 3).setValues(filterList);
}
In this solution, I used an arrow function and includes.

JQuery Access Arrays - Logical mistake possible

so i'm sitting here for hours and now i have to get the Eyes of the Internet to help me out...
So i'm trying to create a Shift Plan. I created a Table (each cell a jQuery Dropdown button with the possible Shifts). on every selection i write the selected Shifts into an array.
The following code snippet is how i do that. I need this in the on click because it will show the total shift time in n extra field.
Later i want save the arrays to a Database an because of that i need to access the calFirstRow array for each employee.
var calFirstRow = [,];
$(document).ready(function(){
$('.dropdown-menu a').on('click', function(){
// Do the following stuff for every Employee
$.each( jqEmployees, function(index, value){
var name = value['NAME'];
// create array from first row
$( ".first-row-"+ name +" td button" ).each(function( index ) {
calFirstRow[name, index] = $( this ).text();
});
});//End each Employee
});//End Dropdown click
Here i try to Access the array
});//End ready
the problem is, no matter what i do, in every calFirstRow[name] i get the array from the last Employee.
If i print the Array i get something like [User1: Array, User2: Array] but in each, User1 and 2 is the data of User2 saved...
Im new to jQuery and i maybe miss somethin really fundamental....
It looks like you're trying to treat calFirstRow as a two dimensional array, but the way you're accessing it doesn't make any sense. If you pop open your browser's development console and type [,], you'll see this:
> [,]
< [undefined × 1]
It's got only a single dimension, and JavaScript treats the comma as coming after an element, which you haven't provided, so you have an array containing a single undefined.
The next problem happens when you access calFirstRow[name, index]. Arrays can only be accessed by a single integer index, and JavaScript doesn't know what to do with name, so it ignores it and just uses index:
> a = ['a', 'b', 'c']
> a[1, 2]
< 'c' // The element at index 2
> a[2, 0]
< 'a' // The element at index 0
The result is that your loops aren't creating a two dimensional array that matches your table, they're just overwriting calFirstRow again and again, which is why your last user's data ends up in it. It looks like it's in every row, but really when you access calFirstRow['User1', 0] or calFirstRow['User2', 0], you're just accessing calFirstRow[0] twice.
Since you're trying to index by the employee's name, and then their column in the table, I think you want to start with an object. calFirstRow doesn't seem like the name for what you really want, so let's call it shiftData:
var shiftData = {}
The keys in the object will be your employees' names, and the values will be their array of shifts. For example:
> shiftData['Kristjan'] = [1,2,3]
< [1, 2, 3]
> shiftData['Joel'] = [4,5,6]
< [4, 5, 6]
> shiftData
< Object {Kristjan: Array[3], Joel: Array[3]}
Joel: Array[3]
0: 4
1: 5
2: 6
length: 3
Kristjan: Array[3]
0: 1
1: 2
2: 3
length: 3
In your click handler, you can map over each employee's row in the table and set their named entry to the result.
$.each( jqEmployees, function(employeeIndex, value){
var name = value['NAME'];
shiftData[name] = $( ".first-row-"+ name +" td button" ).map(function( columnIndex ) {
return $( this ).text();
});
});
This will result in a shiftData object like I showed in the console above. Each iteration of map returns the text of the td button in the user's row and column. Those values are aggregated into an array and assigned to shiftData[name].

Adding items to a javascript array

I'm attempting to assign items to an array on a users action, so for example, user clicks "Add", this will add the selected id into the relevant section of the array.
The array won't be created at first so I set up an empty array:
var Options={};
On the users click, I then want to assign a key to match the option selected from a drop down so I can use this as a reference later on.
E.g. When the user clicks plus on a record, the option selected from a drop-down is 2. The id of the record they selected is say 5.
I'd like to structure my array like the following:-
[key e.g drop down option]
=> 'records' => array [record_id]
Each time the user clicks plus next to a record, the id is appended to the correct array based on the drop down selected option.
[option 1] => 'publication_date' = 12/09/2010, 'records' => [1, 2, 4]
[option 2] => 'publication_date' = 15/09/2010, 'records => [1, 3, 5]
etc, each option from the select box has a publication date and a series of records the user can assign to it.
You can do something like this:
function AddItem(key, value) {
if(Options[key]) Options[key].push(value);
else Options[key] = [value];
}
For example doing this:
​AddItem(2, 5);
AddItem(2, 6);
Would result in Options being:
{ 2: [5, 6] }
You can give it a try/play with it here.
An object in javascript is good to store a one key dataset not various keys.
ie:
var records = {'12/09/2010':[1, 2, 4], '15/09/2010':[1, 3, 5]}
To get the records for the 15/09: records['15/09/2010']
Add a new record for a date: records['15/09/2010'].push(6)
If the date change, you need to do something like:
records['17/09/2010'] = records['15/09/2010']; delete records['15/09/2010']
The user is not able to change both at the same time(date and add) and you should do both update actions separately.
Now if you plan to have more keys, you should use an array of objects:
var records = [
{publication_date:'12/09/2010', records:[1, 2, 4], ..., otherProp='...'},
...
];
And for each change, loop on the array, find the relevant item and change it.

Categories