this is really hurting my brain so I hope somebody can help.
I have some data from a spreadsheet that has 2 axis'
AGE 50 51 52
£7 £1,497 £1,479 £1,458
£8 £1,746 £1,725 £1,701
£9 £1,996 £1,972 £1,944
the user will input there age into a input box on the page, and click next, i save this into a variable
var age = 50;
the user is then present with another input box and can input a value from 0 - 100
i then save this into another variable
var ammount = 10;
with the two values i need to search the array for the corosponding values to return the answer.
the data i have is currently in a spread sheet, i need to take this data from the spreadsheet put this into an array in java script.
with the two values i need to find the relevant answer.
Try somethink like:
var row1 = {
"50" : "£1,497",
"51" : "£1,479"
// etc
}
var dictionary = {
"£7": row1
// etc
}
Next, call dictionary["£7"]["50"]
Related
I have some JS that stores the name and value of selected checkboxes on one page and then, on a button click, adds this data to a table on page 2.
This works, but now I am looking to do the same for a textbox containing a number. Specifically, I'm looking to take the value entered by the user and add this to a cell in the table. What would be the best way to approach this? Add to the existing function or create a separate on button click function specifically for the textbox value?
I have added a screenshot of the HTML table on page 2 along with where I would like the textbox value to go (highlighted with a red rectangle).
Here's what I have so far:
HTML for textbox (page 1):
<div class="selecttier">
<h1>5. Number of Clicks</h1>
<input id="numberofclickstextbox" name="numberofclicks" type="text" value="0" data-total="0" oninput="calculatetier()" />
</div>
JS on page 1:
$('#sales_order_form_button').click(function() {
let table_info = [];
$('input[type=checkbox]').each(
function(index, value) {
if($(this).is(':checked')) {
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
}
);
}
});
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
});
JS on page 2:
// Helper function
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.href);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
// actual code
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
for(let i = 0; i < data_from_page_1.length; i++){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text(data_from_page_1[i].name);
let recordValue = $("<td></td>").text(data_from_page_1[i].value);
row.append(recordName, recordValue);
$('#output_table').append(row);
}
// code to sum CPC column
var sum1 = 0;
$("#output_table tr > td:nth-child(2)").each(
(_,el) => sum1 += Number($(el).text()) || 0
);
$("#sum1").text(sum1);
//datetime stamp
var dt = new Date();
document.getElementById("datetime").innerHTML = dt.toLocaleString();
Output HTML table (page 2):
<table id="output_table">
<tr>
<th>Name</th>
<th>Value</th>
<th>Number of Clicks</th>
</tr>
<tfoot>
<tr>
<th id="total" colspan="1">Total CPC:</th>
<td id="sum1"></td>
</tr>
</tfoot>
</table>
As stated in the #Manu Varghese comment, the way to go would be using sessionStorage or localStorage.
First, let's differentiate both. According to the Stack Overflow question "HTML5 Local storage vs Session Storage", we have the following answer:
localStorage and sessionStorage both extend Storage. There is no difference between them except for the intended "non-persistence" of sessionStorage.
That is, the data stored in localStorage persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.
For sessionStorage, changes are only available per tab. Changes made are saved and available for the current page in that tab until it is closed. Once it is closed, the stored data is deleted.
Considering they are used the same way and you must to choose between what better fits your case, I will proceed using sessionStorage.
For that, in the first page you must use:
sessionStorage.setItem("key", "value")
You may set the item right when you perceives a change, like in the input 'blur' event.
and when you land in the second page (right when jQuery calls its start event), you will retrieve your data using:
sessionStorage.getItem("key")
Take in mind that localStorage/sessionStorage can support a limited amount of data. Even if that limit is way bigger than URL, most browsers will store only 2.5MB to 10MB per origin, according to the browser implementation (you may test by yourself in the link recommended in MDN (Mozilla Development Network), http://dev-test.nemikor.com/web-storage/support-test/).
Also, you may want to avoid storing sensitive data in the storages, due to some some discussions about security, which seems not to be a complaint here.
Implementation in the given case
Your code can be modified in three steps:
Change the way you save the data to use the storage
Creates a JSON of an object containing the array, instead the make the JSON using the array itself. Then you can add more fields.
Load the JSON object and its fields (the array and the number).
Step 1 - Changing to sessionStorage
Just now you have your Javascript on page 1 creating an array of data and stringifying that data to a JSON string.
If you want to use the storage rather than the URL for all the data, just change these lines of code from:
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
to the code that will save the data into a (local/session)Storage:
let jsonStr=JSON.stringify(table_info); // converts to JSON string
sessionStorage.setItem("oldData", jsonStr); // save to storage
window.location = "page2.html"; // navigate to other page
Notice that the storage can receive any string, but only strings, then we can remove the btoa function, but we must keep the stringify.
Step 2 -- Adding more data to save
Now you have one JSON that is an array of items. But what do you want is to include one more field, parallel to this array. Of course, you can't include it in the array, as it is a different thing. So, what we must to do is to create a JSON object which has a number field AND the array field itself.
Your function to create the array is all ok, then we will use the same "table_data" as the array and include it to a new JSON object:
let table_data = []; // the array you have
$('input[type=checkbox]').each(
... rest of code ...
); // the function that creates the array (I abbreviated it here)
// Creates an object with an array and a number
let jsonObj = {
table_data: table_data,
number_of_clicks: theNumberYouHave/* your variable with the number here */
};
// This is the bit above with CHANGES into variable names
// Instead of "table_data", now we save "jsonObj"
let jsonStr=JSON.stringify(jsonObj); // converts the "jsonObj" to a JSON string
sessionStorage.setItem("oldData", jsonStr);
window.location = "page2.html";
Remember to change "theNumberYouHave" to whatever your variable with the number is called. The you will append the number as a field of the JSON object.
In other words, this simply will create an structure like that:
{
number_of_clicks: 5216,
table_data: [
{ name: "...", value: "..."},
{ name: "...", value: "..."},
{ name: "...", value: "..."},
...
]
}
See? Your table_data is still there, but with a new sibling (number_of_clicks) inside an object.
Step 3 -- Loading data from page 1
For now, you have these two lines of code in page 2 to read data from page 1:
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
What do you need there, is to simply replace the getUrlParameter function to read from the storage, and remove the atob function to reflect the changes we made in page 1, this way:
let jsonObj = sessionStorage.getItem("oldData"); // reads the string
let data_from_page_1 = JSON.parse(jsonObj); // parse the JSON string
let table_data = data_from_page_1.table_data; // grab the table data
let number_of_clicks = data_from_page_1.number_of_clicks; // grab the number
Now you are free to use the variable "table_data" like you did, and to use the "number_of_clicks" in the way you want to use it. It is the number passed from page 1, then you may set it to your table cell.
You have it with the unique ID "sum1", the you may just:
$("#sum1").text(number_of_clicks);
And you are done!
I highly recommend localStorage and sessionStorage to be used, as per this and this
Page 1 code full source
$('#next_page_button').click(function(){
let table_info = [];
// Do for checkboxes
$('.campaignstrategy input[type=checkbox]').each(
function(index, value){
if($(this).is(':checked')){
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
type: 'checkbox'
}
);
}
});
$('.campaignstrategy input[type=text]').each(
function(index, value){
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
type: 'text'
}
);
});
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
});
Page 2 Code full source
// Helper function
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.href);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
// actual code
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
// clear table
$('#output_table').html("");
// generator checboxes
for(let i=0;i<data_from_page_1.length;i++){
if(data_from_page_1[i].type == "checkbox"){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text(data_from_page_1[i].name);
let recordValue = $("<td></td>").text(data_from_page_1[i].value);
let recordCount = $("<td></td>").text("");
row.append(recordName, recordValue, recordCount); // not used but needed
$('#output_table').append(row);
}
}
// generate textboxes
for(let i=0;i<data_from_page_1.length;i++){
if(data_from_page_1[i].type == "text"){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text("");
let recordValue = $("<td></td>").text("");
let recordCount = $("<td></td>").text(data_from_page_1[i].value);
row.append(recordName, recordValue, recordCount);
$('#output_table').append(row);
}
}
ANSWER:
What would be the best way to approach this?
window.localStorage - stores data with no expiration date
window.sessionStorage - stores data for one session
I am very new to JavaScript so please bear with me.
So i want to create multiple voucher codes and for each voucher code there is a specific redeemable amount attached to it. And if a user should buy a voucher and after getting the voucher code, inputs it in a textfield, how do i get JavaScript to validate the users voucher code and confirm the amount redeemed and print that out? Just like redeeming Amazon Giftcards!
I want all these done in a simple HTML file i have created.
Since am just starting out JS i can't seem to achieve this yet on my own.
for example i have several voucher codes in strings:
var voucher1 = AC60";
var voucher2= 'DC60';
var voucher3= 'RC60';
var voucher4= 'XC60';
var voucher5= 'YC60';
var voucher6= 'WC60';
var voucher7= 'ZC60';
How do i attach monetary value for each and validate a users input to confirm which has been redeemed and print out the value just like redeeming amazon giftcards?
What you're looking for is an Object or a Map. These data structures allow you to attach a monetary value to the voucher code in the form of a key-value pair (where the voucher code is the key and the monetary value is the value).
A simple example could work like this:
// This is a simple object literal of keys and values
const vouchers = {
AC60: 100,
DC60: 20,
RC60: 35,
XC60: 45,
YC60: 80,
WC60: 10,
ZC60: 200
};
// This function will update the ouput <div> with the voucher amount
// or indicate an unknown voucher was input
function getVoucherValue(event) {
const key = input.value; // Stores the value of the input
const value = vouchers[key]; // Looks up the key in the object
// If the key is valid, update the output <div> with the monetary value
// Else the key is undefined, update the output <div> with an error message
if (vouchers[key]) {
output.textContent = vouchers[key];
} else {
output.textContent = "Invalid voucher"
}
}
// Whenever the button is clicked, run the getVoucherValue() function
button.addEventListener("click", getVoucherValue);
<input id="input">
<button id="button">Get Voucher Value</button>
<div id="output"></div>
First a little note, as really you should not rely on javascript validation, if there is actual value attached to it, it would be far to easy to redeem whatever whenever.
Beyond that, yes, possible, so you would really want to start by creating a more "Complex" structure. Like an array, containing objects:
var myArray = [
{ code: "uniqueVoucher1", value: "10.00" },
{ code: "uniqueVoucher2", value: "20.00" },
]
Then you can use this array to "loop through" the data, for creating html... perhaps like this...
for (var i=0;i<myArray.length;i++){
document.write("<div>Code: " + myArray[i].code + ", Value: " + myArray[i].value + "</div>")
}
just a small example
I have to retrieve data from an API.
Certain data has to be retrieved in a certain order.
To be exact, data needs to be retrieved in this order:
7,40,8,9,10,45,11,39,5,12,13,15,6,18,0,46,22,23,3,41,1,24,42,25,26,4,27,2
So when loop is doing 0, then it needs to retrieve data number 7, when loop is doing 1, then data number 40 and if loop is doing 2 then data number 8 etc.
listWithDataFromAPI I do this:
metricsSheet.appendRow([listWithDataFromAPI.symbols]);
And get this response:
[Ljava.lang.Object;#1e1aaea2
When I insert a specific number I do this:
metricsSheet.appendRow([listWithDataFromAPI.symbols].symbols[8]]);
And get such response: {name=DataPeter, longVolume=6640.87, longPositions=23678}
Thus if loop is 0 then extract 7, loop is 2 extract 40 etc. as I mentioned.
This is what I'm trying in concept:
var listNumberValue = ["5","30","7"];
var symbols = listWithDataFromAPI.symbols;
for (var i in listNumberValue) {
var symbol = symbols[listNumberValue];
metricsSheet.appendRow([symbol.name]);
}
Hope this makes sense.
Not sure how to do this..?
The big problem for us is that we don't know what listWithDataFromAPI is and you have not explained it. But I think you're trying to say that you want to iterate over something that you can get from it so I took a stab at what I think you're trying to do.
The first function will take your 0 through 46 indexes and reorder as 7,40,8,9,10,45,11,39,5,12,13,15,6,18,0,46,22,23,3,41,1,24,42,25,26,4,27,2
As shown in this table.
function getIdxObj() {
var idxA=[7,40,8,9,10,45,11,39,5,12,13,15,6,18,0,46,22,23,3,41,1,24,42,25,26,4,27,2];
var idxObj={};
for(var i=0;i<idxA.length;i++) {
idxObj[i]=idxA[i];
}
return idxObj;
}
The second function loops over symbols which apparently come from listWithDataFromAPI.symbols which has not been explained and so we know nothing about it.
function theUnknownFunction() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('metrics');//not sure about this either
var idxObj=getIdxObj();
var symbols = listWithDataFromAPI.symbols; //I dont have a clue as to what listWithDataFromAPI is
for (var i=0;i<symbols.length;i++) {
var symbol = symbols[idxObj[i]];
sh.appendRow([symbol.name]);
}
}
I've got objects 'ing' with a field named 'id' and another one called 'fObj' with a field named 'contain'.
By using ng-repeat i'd like to show only these 'ing' objects where ing.id is a part of fObj.contain
e.g.
ing=[{id: 1,field: value},{id:2, field: othervalue},{id:3, field: cat}];
fObj={field1: value1, field: value2, contain: ':1:3:'};
By having this contain value I'd like to show only ing's with id=1 and id=3
Yeah, I know there are two types of data (number and string) but even if i changed numbers to strings it still didn't work
I just dont't know how to make it works. It's probably some kind of custom filter, but I've tried couples and nothing happend.
I would be glad if you suggest me a solution.
Thanks
In your controller,
var ids = fObj.contain.split(':');
// the array for your ng-repeat
var displayIng = [];
// loop the objects, see if the id exists in the list of id's
// retrieved from the split
for(i = 0; i < ing.length; i++) {
if(ids.indexOf(ing.id.toString()) displayIng.push(ing[i]);
}
I would split the numbers out of fObj.contain; and use them as hashmap object keys for simple filtering of the array
var ing=[{id: 1},{id:2},{id:3}];
var fObj={contain: ':1:3:'};
var IDs = fObj.contain.split(':').reduce(function(a,c){
a[c]=true;
return a;
},{});
// produces {1:true,3:true}
var filtered = ing.filter(function(item){
return IDs[item.id];
});
console.log(filtered)
We're building a site with ExpressionEngine. We are running a SQL query to gather up all member IDs for a specific member group. After that, we are using EE tags to get data from a custom member field for each member ID.
The ID and field data need to stay paired, as we will be populating a drop-down so that the ID is the value and the field data is the text, so we are currently putting them into a JS array as key/value pairs. The call is as follows:
var array= [
{exp:query sql="SELECT * FROM exp_members WHERE group_id = 5"}
{exp:member:custom_profile_data
member_id="{member_id}"}
{if company != ''}
{{member_id}:"{company}"},
{/if}
{/exp:member:custom_profile_data}
{/exp:query}
};
This gives us the output:
var array = [
{1:"name01"},
{2:"name02"},
{3:"name01"},
{4:"name03"}
];
Now, our problem. We need to remove objects based on duplicate field data (values) only, so the above array would look like this:
var array = [
{1:"name01"},
{2:"name02"},
{4:"name03"}
];
None of these IDs (keys) will ever be the same, but the field data (values) can be. So we want to keep the first KV pair that comes through with a unique value, but remove any subsequent dupes of that value - despite the fact that they will not be true "duplicate values" due to a different ID (key).
Keeping in mind that the KV pairs are all dynamic, is there any possible way to do this via JS so we can create a new array for the cleaned data to pass to the drop-down?
You could handle the duplications by modifying your MySQL query. (In my example, my custom field ID was 1.)
var myArray = [];
{exp:query sql="SELECT MIN(m.member_id) AS co_member_id, d.m_field_id_1 AS company FROM exp_members m INNER JOIN exp_member_data d ON m.member_id = d.member_id WHERE d.m_field_id_1 != '' AND m.group_id > 0 GROUP BY d.m_field_id_1;"}
myArray.push({{co_member_id}: "{company}"});
{/exp:query}
This query would use the first (in the ordinal sense) member_id found; you could also change the MIN to MAX and get the last.
This will give you a clean output in your source, without the need for any additional JS processing. I'd also recommend changing the names of the variables you're outputting as to not conflict in EE's parsing.
I would do it like...
function removeDups(arry){
var tmp = {}, retainIdx=[], newArry=[];
arry.forEach(function(obj, idx){
var val = obj[Object.keys(obj)[0]];
if(val && !tmp[val]){
retainIdx.push(idx);
tmp[val] = true;
}
});
retainIdx.forEach(function(i){
newArry.push(arry[i]);
});
return newArry;
};