I keep having issues iterating over some JSON to put in select options
(btw, ignore the actual values for "label", those are garbage atm).
Here is an example that my php is passing into this:
[{"value":"1","label":"04-22-12"},{"value":"4","label":"04\/04\/12"}]
I am currently trying this loop:
*note, dateSelect is defined somewhere else
for (res in JSON.parse(request.responseText)) {
var date = document.createElement("option");
date.value = res.value;
date.text = res.label;
dateSelect.add(date, null);
}
However, it is adding "undefined" into my options...
How do I get it so each value and corresponding label is put in there correctly?
You have an Array, so don't for-in.
In your code, res is the property name (the index of the Array in this case) in the form of a string, so the properties you're looking for aren't going to be defined on the string.
Do it like this...
for (var i = 0, parsed = JSON.parse(request.responseText); i < parsed.length; i++) {
var res = parsed[i];
var date = document.createElement("option");
date.value = res.value;
date.text = res.label;
dateSelect.add(date, null);
}
Related
Seek for help to transform the xml to json. I got an input with this.
"<logRecord>
<logRecord>
<logRecord>
<class name="dto">
<logField fieldName="ID" oldValue=" " newValue="650"/>
<logField fieldName="submissionDt" oldValue="" newValue="03-12-2022"/>
</class>
</logRecord>
</logRecord>
</logRecord>"
and i want change to
[{fieldName : 'ID', oldValue : '' , newValue " '650'}.
{fieldName : 'submissionDt', oldValue : '' , newValue : '03-12-2022'}]
Is it possible? Thanks
I'm almost certain there is probably a better way of doing this, so I fully expect someone to come along and critique my attempt. However, the way I would achieve this (using the functions I know) would be using xpath to extract given values from the XML.
I've commented the code to try explain exactly what I'm doing but in essence, I'm looping over each <class> then looping each <logField> before finally looping over each of the attributes.
//First we'll take our (slightly more complex) XML input string
var xmlString = "<logRecord><logRecord><logRecord><class name=\"dto\"><logField fieldName=\"ID\" oldValue=\"\" newValue=\"650\" /><logField fieldName=\"submissionDt\" oldValue=\"\" newValue=\"03-12-2022\" /></class></logRecord><logRecord><class name=\"dto\"><logField fieldName=\"ID\" oldValue=\"\" newValue=\"123\" /><logField fieldName=\"submissionDt\" oldValue=\"\" newValue=\"19-12-2022\" /></class></logRecord></logRecord></logRecord>";
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString, "text/xml");
//Create a new XPathEvaluator
const evaluator = new XPathEvaluator();
//Evaluate given xpath to target every <class> found inside the XML
const classExpression = evaluator.createExpression('//class');
const classResult = classExpression.evaluate(xmlDoc, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
//Declare a final array
var arr = [];
//Loop each found instance of <class>
for (i=0; i<classResult.snapshotLength; i++) {
//Find all instances of <logField> inside of THIS <class>
const logFieldExpression = evaluator.createExpression('./logField');
const logFieldResult = logFieldExpression.evaluate(classResult.snapshotItem(i), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
//Declare an array to hold each of our <logField>s
var logFieldObj = [];
//Loop each <logField> inside of the <class>
for (j=0; j<logFieldResult.snapshotLength; j++) {
//Find all attributes for THIS <logField>
const attrEvaluator = evaluator.createExpression('./#*');
const attrResult = attrEvaluator.evaluate(logFieldResult.snapshotItem(j), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
//Declare a final object to hold each of the attributes fieldName, oldValue and newValue
var attrObj = {};
//Loop over each attribute
for (k=0; k<attrResult.snapshotLength; k++) {
//Add attribute as attributeName => attributeValue to our object
attrObj[attrResult.snapshotItem(k).localName] = attrResult.snapshotItem(k).textContent;
}
//Add our object to an array
logFieldObj.push(attrObj);
}
//Create the final resulting array
arr.push(logFieldObj);
}
console.log(arr);
I am attemtping to add strings together to create the name of a variable, which I can then check its value. The code may explain this better, to understand what I mean.
I have several variables like below
var scList = ["stream", "dev", "web"];
var stream_sc = ["test0", "test1"];
var dev_sc = ["value","value"];
var web_sc = ["value", "value"];
In another function I am checking if entered text matches one of the values in scList, I then hope to add the string "_sc" to the end of the entered text, and from there be able to display the values inside the variables ending in _sc. The below is what I have so far. (With dataAr[1] being the user entered string I am checking for)
for (var i = 0; i < scList.length; i++) {
if (dataAr[1] == scList[i]) {
window.alert(scList[i]+"_sc"[0]);
}
}
While it is able to match the string to a value in the scList Array properly, the value returned by the window alert is just the user entered string, not showing the "_sc", which makes sense but how could I get this to then relate to the matching variable ending in "_sc"?
To Clarify
My hope is that if a user entered "stream" or if dataAr[1] == "stream" that the returned value would be "test0" from stream_sc[0]
Thank you for any help!
You have an extraneous [0] after "_sc" which would grab the underscore and append it to the variable name. What you want is probably scList[i] + "_sc"
You should store them in a json object, so you can reference the sc names to retrieve the values, like so:
const varMap = {
"stream_sc": [ ],
"dev_sc": [ ],
"web_sc": [ ]
};
// access the map using the entered value
varMap[scList[i] + "_sc"][j]
// where j would be the desired item index in the _sc array
I'm currently on a phone, so I hope the formatting comes out ok.
EDIT: fixed some syntax that was needed that the asker pointed out.
I assume you dataAR is an array as you make a reference to a key in the conditional dataAr[1]. You could use .includes() in that case to see if your array includes the value of scList[i]... I used a select to show how this could be achieved in a for loop and conditional. If the conditional is true, then rather that using the array scList[i] value use the value that is true... Then concatenate the _sc onto the value and define that as a new variable...
var sel = document.getElementById('sel');
var dataAr = ['gaming']; // array with a value that is not true present already
var scList = ["stream", "dev", "web"];
var stream_sc = ["test0", "test1"];
var dev_sc = ["value", "value"];
var web_sc = ["value", "value"];
function getVal(scList, sel) {
for (var i = 0; i < scList.length; i++) {
if (scList.includes(sel.value)) {
val = sel.value + '_sc';
return val;
}
}
}
let val;
sel.addEventListener("change", function(e) {
dataAr.push(sel.value);
alert(getVal(scList, sel));
// val myVar = getVal(scList, sel); <-- Do something with this var now
});
<select name="sel" id="sel">
<option>--select an option below--</option>
<option value="stream">Twitch</option>
<option value="dev">Visual Studio Code</option>
<option value="web">Mozilla</option>
</select>
I've been having a hard time with cross browser compatibility and scrapping the dom.
I've added data analytics tracking to ecommerce transactions in order to grab the product and transaction amount for each purchase.
Initially I was using document.querySelectorAll('#someId')[0].textContent to get the product name and that was working fine for every browser except internet explorer.
It took some time to figure out that it was the .textContent part that was causing ie problems.
Yesterday I changed .textContent to .innerText. From looking inside analytics it seems that the issue has been resolved for ie but now Firefox is failing.
I was hoping to find a solution without writing an if statement to check for the functionality of .textContent or .innerText.
Is there a cross browser solution .getTheText?
If not what would be the best way around this? Is there a simple solution? (I ask given my knowledge and experience with scripting, which is limited)
** added following comments **
If this is my code block:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
prd.brand = brand[i].innerText;
prd.name = name[i].innerText;
prd.price = price[i].innerText;
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
Then if I understand the syntax from the comments and the question linked to in the comment, is this what I should do:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
prd.brand = brand[i].textContent || brand[i].innerText;
prd.name = name[i].textContent || name[i].innerText;
prd.price = price[i].textContent || price[i].innerText;
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
So using or with a double bar || assigns the first non null value?
Re: your edit, not quite. The way to access methods or properties on an object (eg a DOM element) is to use dot notation if you have the name itself, or square brackets in case of variables/expressions (also works with strings, as in obj["propName"], which is equivalent to obj.propName). You can also just test the property against one element and use that from there on:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
var txtProp = ("innerText" in brand[i]) ? "innerText" : "textContent"; //added string quotes as per comments
prd.brand = brand[i][txtProp];
prd.name = name[i][txtProp];
prd.price = price[i][txtProp];
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
Regarding the line:
var txtProp = (innerText in brand[i]) ? innerText : textContent;
The in keyword checks an object to access the property (syntax: var property in object). As for the question notation (I made an error earlier, using ||, the correct thing to use was a :),
var myVar = (prop in object) ? object[prop] : false;
As an expression, it basically evaluates the stuff before the ?, and if it's true, returns the expression before the :, else the one after. So the above is the same as / a shorthand for:
if(prop in object){
var myVar = object[prop];
}
else{
var myVar = false;
}
Since you are checking between two properties only and wanting to assign one or the other, the shortest way would indeed be:
var txtProp = brand[i].innerText || brand[i].textContent;
It would basically test the first property, and if it were false or undefined, it would use the second one. The only reason I (pedantically) avoid using this is because the first test of a || b would fail even if a existed but just had a value of 0, or an empty string (""), or was set to null.
I have multiple checkboxes in a view and each one has some data attributes, example:
Once the button is clicked I'm iterating through all the checkboxes which are selected and what I want to do is get the data-price and value fields for each selected checkbox and create JSON array.
This is what I have so far:
var boxes2 = $("#modifiersDiv :checkbox:checked");
var selectedModifiers = [];
var modifierProperties = [];
for (var i = 0; i < boxes2.length; i++) {
for (var k = 0; k < boxes2[i].attributes.length; k++) {
var attrib = boxes2[i].attributes[k];
if (attrib.specified == true) {
if (attrib.name == 'value') {
modifierProperties[i] = attrib.value;
selectedModifiers[k] = modifierProperties[i];
}
if (attrib.name == 'data-price') {
modifierProperties[i] = attrib.value;
selectedModifiers[k] = modifierProperties[i];
}
}
}
}
var jsonValueCol = JSON.stringify(selectedModifiers);
I'm not able to get the values for each checkbox and I'm able to get the values only for the first one and plus not in correct format, this is what I'm getting as JSON:
[null,"67739",null,"1"]
How can I get the correct data?
You can use $.each to parse a jquery array, something like:
var jsonValueObj = [];
$("#modifiersDiv :checkbox:checked").each(function(){
jsonValueObj.push({'value':$(this).val(),'data-price':$(this).attr('data-price')});
});
jsonValueCol = JSON.stringify(jsonValueObj);
Please note it's generally better to use val() than attr('value'). More information on this in threads like: What's the difference between jQuery .val() and .attr('value')?
As for your code, you only had one answer at most because you were overwriting the result every time you entered your loop(s). Otherwise it was okay (except the formatting but we're not sure what format you exactly want). Could please you provide an example of the result you would like to have?
if you want to get an object with all checked values, skip the JSON (which is just an array of objects) and make your own....
var checked =[];
var getValues = function(){
$('.modifiers').each(function(post){
if($(this).prop('checked')){
checked.push({'data-price':$(this).attr('data-price'),'value':$(this).attr('value')});
}
});
}
getValues();
sure i'm missing something obvious here.. but mind is elsewhere
This should give an array with values (integers) and prices (floats):
var selected = [];
$("#modifiersDiv :checkbox:checked").each(function()
{
var val = parseInt($(this).val(), 10);
var price = parseFloat($(this).data("price"));
selected.push(val);
selected.push(price);
});
Edit: Updated answer after Laziale's comment. The $(this) was indeed not targeting the checked checkbox. Now it should target the checkbox.
i'm new to javascript and jquery and was wondering if someone could let me in on why this isn't working correctly.
i have a drop-down box that a user selects a value from, then "Processes." When processed the value of the drop-down as well as a textbox is stored in an array. I want the user to be able to then basically store the same drop-down selection and textbox data in the array again but now in a new value pair.
First store would be
TestArray[0][0] = "Textbox Value"
If "Processed" again, it would be
TestArray[1][0] = "Textbox Value"
that way I can parse through later and figure how many times the user "Processed" the drop-down selection;
var oneClickReport = $("#reportName").val();
if(oneClickReport == "Sample Report One"){
var arrayOneCount = reportOneArray.length;
var totalHouseholds = 0;
$("#reportChecks span:visible").each(function(){
if($(this).find(':checkbox').prop('checked')){
var HHName = $(this).text();
reportOneArray.push(HHName);
arrayTest[arrayOneCount][totalHouseholds] = HHName;
}
totalHouseholds += 1;
});
for(i = 0; i < arrayOneCount; i+=1){
alert(arrayTest[0][i]);
}
}
But when trying to "Process" for the second time, I receive the error of;
SCRIPT5007: Unable to set property '0' of undefined or null reference
on line;
arrayTest[arrayOneCount][totalHouseholds] = HHName;
You need to initialize your array. I'm not sure what exactly you want to do but you need an array like this
var arrayTest = []
And you will need to initialize subsequent value like
arrayTest[1] = []
Then you can access your array
arrayTest[1][0] = []
I made an example for you
var oneClickReport = $("#reportName").val();
var arrayTest = [] # You may need to put this elsewhere
if(oneClickReport == "Sample Report One"){
var arrayOneCount = reportOneArray.length;
var totalHouseholds = 0;
$("#reportChecks span:visible").each(function(){
if($(this).find(':checkbox').prop('checked')){
var HHName = $(this).text();
reportOneArray.push(HHName);
if(!arrayTest[arrayOneCount]){ arrayTest[arrayOneCount] = []; }
arrayTest[arrayOneCount][totalHouseholds] = HHName;
}
totalHouseholds += 1;
});
for(i = 0; i < arrayOneCount; i+=1){
alert(arrayTest[0][i]);
}
}
your problem with var arrayOneCount = reportOneArray.length; and you're not changing this value